| 157 | } |
| 158 | |
| 159 | bool https_client::handle_buffer(std::string &buffer) |
| 160 | { |
| 161 | bool state_changed = false; |
| 162 | do { |
| 163 | state_changed = false; |
| 164 | switch (state) { |
| 165 | case HTTPS_HEADERS: |
| 166 | if (buffer.find("\r\n\r\n") != std::string::npos) { |
| 167 | |
| 168 | /* Add 10 seconds to retrieve body */ |
| 169 | timeout += 10; |
| 170 | |
| 171 | /* Got all headers, proceed to new state */ |
| 172 | |
| 173 | std::string unparsed = buffer; |
| 174 | |
| 175 | /* Get headers string */ |
| 176 | std::string headers = buffer.substr(0, buffer.find("\r\n\r\n")); |
| 177 | |
| 178 | /* Modify buffer, remove headers section */ |
| 179 | buffer.erase(0, buffer.find("\r\n\r\n") + 4); |
| 180 | |
| 181 | /* Process headers into map */ |
| 182 | std::vector<std::string> h = utility::tokenize(headers); |
| 183 | if (h.size()) { |
| 184 | std::string status_line = h[0]; |
| 185 | h.erase(h.begin()); |
| 186 | /* HTTP/1.1 200 OK */ |
| 187 | std::vector<std::string> req_status = utility::tokenize(status_line, " "); |
| 188 | if (req_status.size() >= 2 && (req_status[0] == "HTTP/1.1" || req_status[0] == "HTTP/1.0") && atoi(req_status[1].c_str())) { |
| 189 | for(auto &hd : h) { |
| 190 | std::string::size_type sep = hd.find(": "); |
| 191 | if (sep != std::string::npos) { |
| 192 | std::string key = hd.substr(0, sep); |
| 193 | std::string value = hd.substr(sep + 2, hd.length()); |
| 194 | std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c){ |
| 195 | return std::tolower(c); |
| 196 | }); |
| 197 | response_headers.emplace(key, value); |
| 198 | } |
| 199 | } |
| 200 | auto it_cl = response_headers.find("content-length"); |
| 201 | if ( it_cl != response_headers.end()) { |
| 202 | content_length = std::stoull(it_cl->second); |
| 203 | } else { |
| 204 | content_length = ULLONG_MAX; |
| 205 | } |
| 206 | chunked = false; |
| 207 | auto it_txenc = response_headers.find("transfer-encoding"); |
| 208 | if (it_txenc != response_headers.end()) { |
| 209 | if (it_txenc->second.find("chunked") != std::string::npos) { |
| 210 | chunked = true; |
| 211 | chunk_size = 0; |
| 212 | chunk_receive = 0; |
| 213 | state = HTTPS_CHUNK_LEN; |
| 214 | state_changed = true; |
| 215 | } |
| 216 | } |