274{
275 if (m_recv_all_headers) {
276 m_recv_all_headers = false;
277 m_recv_status_line = false;
278 }
279
280 if (!m_recv_status_line) {
281 m_recv_status_line = true;
282
283 std::stringstream ss(header_line);
284 std::string item;
285 if (!std::getline(ss, item, ' ')) return false;
286 m_resp_protocol = item;
287 if (!std::getline(ss, item, ' ')) return false;
288 try {
289 m_status_code = std::stol(item);
290 } catch (...) {
291 return false;
292 }
293 if (m_status_code < 100 || m_status_code >= 600) {
294 return false;
295 }
296 if (!std::getline(ss, item, '\n')) return false;
297 auto cr_loc = item.find('\r');
298 if (cr_loc != std::string::npos) {
299 m_resp_message = item.substr(0, cr_loc);
300 } else {
301 m_resp_message = item;
302 }
303 return true;
304 }
305
306 if (header_line.empty() || header_line == "\n" || header_line == "\r\n") {
307 m_recv_all_headers = true;
308 return true;
309 }
310
311 auto found = header_line.find(":");
312 if (found == std::string::npos) {
313 return false;
314 }
315
316 std::string header_name = header_line.substr(0, found);
318 return false;
319 }
320
321 found += 1;
322 while (found < header_line.size()) {
323 if (header_line[found] != ' ') {break;}
324 found += 1;
325 }
326 std::string header_value = header_line.substr(found);
327
328
329 header_value.erase(header_value.find_last_not_of(" \r\n\t") + 1);
330
331
332
333 auto iter = m_headers.find(header_name);
334 if (iter == m_headers.end()) {
335 m_headers.insert(iter, {header_name, {header_value}});
336 } else {
337 iter->second.push_back(header_value);
338 }
339
340 if (header_name == "Allow") {
341 std::string_view val(header_value);
342 while (!val.empty()) {
343 auto found = val.find(',');
344 auto method = val.substr(0, found);
345 if (method == "PROPFIND") {
348 }
349 if (found == std::string_view::npos) break;
350 val = val.substr(found + 1);
351 }
354 }
355 } else if (header_name == "Content-Length") {
356 try {
357 m_content_length = std::stoll(header_value);
358 } catch (...) {
359 return false;
360 }
361 }
362 else if (header_name == "Content-Type") {
363 std::string_view val(header_value);
364 auto found = val.find(";");
365 auto first_type = val.substr(0, found);
366 m_multipart_byteranges = first_type == "multipart/byteranges";
367 if (m_multipart_byteranges) {
368 auto remainder = val.substr(found + 1);
369 found = remainder.find("boundary=");
370 if (found != std::string_view::npos) {
372 }
373 }
374 }
375 else if (header_name == "Content-Range") {
376 auto found = header_value.find(" ");
377 if (found == std::string::npos) {
378 return false;
379 }
380 std::string range_unit = header_value.substr(0, found);
381 if (range_unit != "bytes") {
382 return false;
383 }
384 auto range_resp = header_value.substr(found + 1);
385 found = range_resp.find("/");
386 if (found == std::string::npos) {
387 return false;
388 }
389 auto incl_range = range_resp.substr(0, found);
390 found = incl_range.find("-");
391 if (found == std::string::npos) {
392 return false;
393 }
394 auto first_pos = incl_range.substr(0, found);
395 try {
396 m_response_offset = std::stoll(first_pos);
397 } catch (...) {
398 return false;
399 }
400 auto last_pos = incl_range.substr(found + 1);
401 size_t last_byte;
402 try {
403 last_byte = std::stoll(last_pos);
404 } catch (...) {
405 return false;
406 }
407 m_content_length = last_byte - m_response_offset + 1;
408 }
409 else if (header_name == "Location") {
410 m_location = header_value;
411 } else if (header_name == "Digest") {
413 }
414 else if (header_name == "Etag")
415 {
416
417
418 m_etag = header_value;
419 m_etag.erase(remove(m_etag.begin(), m_etag.end(), '\"'), m_etag.end());
420 }
421 else if (header_name == "Cache-Control")
422 {
423 m_cache_control = header_value;
424 }
425
426 return true;
427}