Monero
Loading...
Searching...
No Matches
http_protocol_handler.inl
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28#include <boost/regex.hpp>
29#include <boost/lexical_cast.hpp>
31#include "reg_exp_definer.h"
32#include "string_tools.h"
33#include "file_io_utils.h"
34#include "net_parse_helpers.h"
35#include "time_helper.h"
36
37#undef MONERO_DEFAULT_LOG_CATEGORY
38#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
39
40#define HTTP_MAX_URI_LEN 9000
41#define HTTP_MAX_HEADER_LEN 100000
42#define HTTP_MAX_STARTING_NEWLINES 8
43
44namespace epee
45{
46namespace net_utils
47{
48 namespace http
49 {
50
52 {
53 std::list<std::pair<std::string, std::string> > m_etc_header_fields;
55 std::string m_content_type;
56 std::string m_body;
57 };
58
59 inline
60 bool match_boundary(const std::string& content_type, std::string& boundary)
61 {
62 STATIC_REGEXP_EXPR_1(rexp_match_boundary, "boundary=(.*?)(($)|([;\\s,]))", boost::regex::icase | boost::regex::normal);
63 // 1
64 boost::smatch result;
65 if(boost::regex_search(content_type, result, rexp_match_boundary, boost::match_default) && result[0].matched)
66 {
67 boundary = result[1];
68 return true;
69 }
70
71 return false;
72 }
73
74 inline
75 bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry)
76 {
77 STATIC_REGEXP_EXPR_1(rexp_mach_field,
78 "\n?((Content-Disposition)|(Content-Type)"
79 // 12 3
80 "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
81 //4 56 7
82 boost::regex::icase | boost::regex::normal);
83
84 boost::smatch result;
85 std::string::const_iterator it_current_bound = it_begin;
86 std::string::const_iterator it_end_bound = it_end;
87
88 //lookup all fields and fill well-known fields
89 while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
90 {
91 const size_t field_val = 6;
92 const size_t field_etc_name = 4;
93
94 int i = 2; //start position = 2
95 if(result[i++].matched)//"Content-Disposition"
96 entry.m_content_disposition = result[field_val];
97 else if(result[i++].matched)//"Content-Type"
98 entry.m_content_type = result[field_val];
99 else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
100 entry.m_etc_header_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
101 else
102 {
103 LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:"<<std::string(it_current_bound, it_end));
104 }
105
106 it_current_bound = result[(int)result.size()-1].first;
107 }
108 return true;
109 }
110
111 inline
112 bool handle_part_of_multipart(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry)
113 {
114 std::string end_str = "\r\n\r\n";
115 std::string::const_iterator end_header_it = std::search(it_begin, it_end, end_str.begin(), end_str.end());
116 if(end_header_it == it_end)
118 //header not matched
119 return false;
120 }
122 if(!parse_header(it_begin, end_header_it+4, entry))
124 LOG_ERROR("Failed to parse header:" << std::string(it_begin, end_header_it+2));
125 return false;
128 entry.m_body.assign(end_header_it+4, it_end);
130 return true;
131 }
132
133 inline
134 bool parse_multipart_body(const std::string& content_type, const std::string& body, std::list<multipart_entry>& out_values)
135 {
136 //bool res = file_io_utils::load_file_to_string("C:\\public\\multupart_data", body);
137
138 std::string boundary;
139 if(!match_boundary(content_type, boundary))
140 {
141 MERROR("Failed to match boundary in content type: " << content_type);
142 return false;
143 }
144
145 boundary+="\r\n";
146 bool is_stop = false;
147 bool first_step = true;
148
149 std::string::const_iterator it_begin = body.begin();
150 std::string::const_iterator it_end;
151 while(!is_stop)
152 {
153 std::string::size_type pos = body.find(boundary, std::distance(body.begin(), it_begin));
154
155 if(std::string::npos == pos)
156 {
157 is_stop = true;
158 boundary.erase(boundary.size()-2, 2);
159 boundary+= "--";
160 pos = body.find(boundary, std::distance(body.begin(), it_begin));
161 if(std::string::npos == pos)
162 {
163 MERROR("Error: Filed to match closing multipart tag");
164 it_end = body.end();
165 }else
166 {
167 it_end = body.begin() + pos;
168 }
169 }else
170 it_end = body.begin() + pos;
171
172
173 if(first_step && !is_stop)
174 {
175 first_step = false;
176 it_begin = it_end + boundary.size();
177 std::string temp = "\r\n--";
178 boundary = temp + boundary;
179 continue;
180 }
181
182 out_values.push_back(multipart_entry());
183 if(!handle_part_of_multipart(it_begin, it_end, out_values.back()))
184 {
185 MERROR("Failed to handle_part_of_multipart");
186 return false;
187 }
188
189 it_begin = it_end + boundary.size();
190 }
191
192 return true;
193 }
194
195
196
197
198 //--------------------------------------------------------------------------------------------
199 template<class t_connection_context>
216 //--------------------------------------------------------------------------------------------
217 template<class t_connection_context>
219 {
220 try
221 {
222 if (m_initialized)
223 {
225 if (m_config.m_connection_count)
226 --m_config.m_connection_count;
227 auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
228 if (elem != m_config.m_connections.end())
229 {
230 if (elem->second == 1 || elem->second == 0)
231 m_config.m_connections.erase(elem);
232 else
233 --(elem->second);
234 }
235 }
236 }
237 catch (...)
238 {}
239 }
240 //--------------------------------------------------------------------------------------------
241 template<class t_connection_context>
243 {
245 ++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
246 ++m_config.m_connection_count;
247 m_initialized = true;
248 return true;
249 }
250 //--------------------------------------------------------------------------------------------
251 template<class t_connection_context>
263 //--------------------------------------------------------------------------------------------
264 template<class t_connection_context>
266 {
267 std::string buf((const char*)ptr, cb);
268 //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf);
269 //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast<std::string>(ptr), std::string((const char*)ptr, cb));
270
271 bool res = handle_buff_in(buf);
272 if(m_want_close/*m_state == http_state_connection_close || m_state == http_state_error*/)
273 return false;
274 return res;
275 }
276 //--------------------------------------------------------------------------------------------
277 template<class t_connection_context>
279 {
280
281 size_t ndel;
282
283 m_bytes_read += buf.size();
284 if (m_bytes_read > m_config.m_max_content_length)
285 {
286 LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too much data: got " << m_bytes_read);
288 return false;
289 }
290
291 if(m_cache.size())
292 m_cache += buf;
293 else
294 m_cache.swap(buf);
295
296 m_is_stop_handling = false;
297 while(!m_is_stop_handling)
298 {
299 switch(m_state)
300 {
302 //The HTTP protocol does not place any a priori limit on the length of a URI. (c)RFC2616
303 //but we forebly restirct it len to HTTP_MAX_URI_LEN to make it more safely
304 if(!m_cache.size())
305 break;
306
307 //check_and_handle_fake_response();
308 ndel = m_cache.find_first_not_of("\r\n");
309 if (ndel != 0)
310 {
311 //some times it could be that before query line cold be few line breaks
312 //so we have to be calm without panic with assers
313 m_newlines += std::string::npos == ndel ? m_cache.size() : ndel;
315 {
316 LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too many starting newlines");
318 return false;
319 }
320 m_cache.erase(0, ndel);
321 break;
322 }
323
324 if(std::string::npos != m_cache.find('\n', 0))
326 else
327 {
328 m_is_stop_handling = true;
329 if(m_cache.size() > HTTP_MAX_URI_LEN)
330 {
331 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_out: Too long URI line");
333 return false;
334 }
335 }
336 break;
338 {
339 std::string::size_type pos = match_end_of_header(m_cache);
340 if(std::string::npos == pos)
341 {
342 m_is_stop_handling = true;
343 if(m_cache.size() > HTTP_MAX_HEADER_LEN)
344 {
345 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_in: Too long header area");
347 return false;
348 }
349 break;
350 }
352 return false;
353 break;
354 }
358 return false;
359 default:
360 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
361 return false;
362 case http_state_error:
363 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Error state!!!");
364 return false;
365 }
366
367 if(!m_cache.size())
368 m_is_stop_handling = true;
369 }
370
371 return true;
372 }
373 //--------------------------------------------------------------------------------------------
374 inline bool analize_http_method(const boost::smatch& result, http::http_method& method, int& http_ver_major, int& http_ver_minor)
375 {
376 CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed...");
377 if (!boost::conversion::try_lexical_convert<int>(result[11], http_ver_major))
378 return false;
379 if (!boost::conversion::try_lexical_convert<int>(result[12], http_ver_minor))
380 return false;
381
382 if(result[3].matched)
384 else if(result[4].matched)
385 method = http::http_method_get;
386 else if(result[5].matched)
387 method = http::http_method_head;
388 else if(result[6].matched)
389 method = http::http_method_post;
390 else if(result[7].matched)
391 method = http::http_method_put;
392 else
393 method = http::http_method_etc;
394
395 return true;
396 }
397
398 //--------------------------------------------------------------------------------------------
399 template<class t_connection_context>
401 {
402 STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+)\\.(\\d+))\r?\n", boost::regex::icase | boost::regex::normal);
403 // 123 4 5 6 7 8 9 10 11 12
404 //size_t match_len = 0;
405 boost::smatch result;
406 if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched)
407 {
408 if (!analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi))
409 {
411 MERROR("Failed to analyze method");
412 return false;
413 }
414 m_query_info.m_URI = result[10];
415 if (!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content))
416 {
418 MERROR("Failed to parse URI: m_query_info.m_URI");
419 return false;
420 }
421 m_query_info.m_http_method_str = result[2];
422 m_query_info.m_full_request_str = result[0];
423
424 m_cache.erase(m_cache.begin(), result[0].second);
425
427
428 return true;
429 }else
430 {
432 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(): Failed to match first line: " << m_cache);
433 return false;
434 }
435
436 return false;
437 }
438 //--------------------------------------------------------------------------------------------
439 template<class t_connection_context>
441 {
442
443 //Here we returning head size, including terminating sequence (\r\n\r\n or \n\n)
444 std::string::size_type res = buf.find("\r\n\r\n");
445 if(std::string::npos != res)
446 return res+4;
447 res = buf.find("\n\n");
448 if(std::string::npos != res)
449 return res+2;
450 return res;
451 }
452 //--------------------------------------------------------------------------------------------
453 template<class t_connection_context>
455 {
456 LOG_PRINT_L3("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
457
458 m_query_info.m_full_request_buf_size = pos;
459 m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos);
460
461 if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos))
462 {
463 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
465 return false;
466 }
467
468 m_cache.erase(0, pos);
469
470 std::string req_command_str = m_query_info.m_full_request_str;
471 //if we have POST or PUT command, it is very possible tha we will get body
472 //but now, we suppose than we have body only in case of we have "ContentLength"
473 if(m_query_info.m_header_info.m_content_length.size())
474 {
477 if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary))
478 {
479 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<<m_query_info.m_header_info.m_content_length);
481 return false;
482 }
483 if(0 == m_len_summary)
484 { //current query finished, next will be next query
487 else
489 }
491 }else
492 {//current query finished, next will be next query
495 }
496
497 return true;
498 }
499 //-----------------------------------------------------------------------------------
500 template<class t_connection_context>
502 {
504 {
506 return handle_query_measure();
511 default:
512 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type);
514 return false;
515 }
516
517 return true;
518 }
519 //-----------------------------------------------------------------------------------
520 template<class t_connection_context>
522 {
523
524 if(m_len_remain >= m_cache.size())
525 {
526 m_len_remain -= m_cache.size();
527 m_query_info.m_body += m_cache;
528 m_cache.clear();
529 }else
530 {
531 m_query_info.m_body.append(m_cache.begin(), m_cache.begin() + m_len_remain);
532 m_cache.erase(0, m_len_remain);
533 m_len_remain = 0;
534 }
535
536 if(!m_len_remain)
537 {
540 else
542 }
543 return true;
544 }
545 //--------------------------------------------------------------------------------------------
546 template<class t_connection_context>
547 bool simple_http_connection_handler<t_connection_context>::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos)
548 {
549 STATIC_REGEXP_EXPR_1(rexp_mach_field,
550 "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)"
551 // 12 3 4 5 6 7 8 9 10 11
552 "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
553 //11 1213 14
554 boost::regex::icase | boost::regex::normal);
555
556 boost::smatch result;
557 std::string::const_iterator it_current_bound = m_cache_to_process.begin();
558 std::string::const_iterator it_end_bound = m_cache_to_process.begin()+pos;
559
560 body_info.clear();
561
562 //lookup all fields and fill well-known fields
563 while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
564 {
565 const size_t field_val = 14;
566 const size_t field_etc_name = 12;
567
568 int i = 2; //start position = 2
569 if(result[i++].matched)//"Connection"
570 body_info.m_connection = result[field_val];
571 else if(result[i++].matched)//"Referer"
572 body_info.m_referer = result[field_val];
573 else if(result[i++].matched)//"Content-Length"
574 body_info.m_content_length = result[field_val];
575 else if(result[i++].matched)//"Content-Type"
576 body_info.m_content_type = result[field_val];
577 else if(result[i++].matched)//"Transfer-Encoding"
578 body_info.m_transfer_encoding = result[field_val];
579 else if(result[i++].matched)//"Content-Encoding"
580 body_info.m_content_encoding = result[field_val];
581 else if(result[i++].matched)//"Host"
582 body_info.m_host = result[field_val];
583 else if(result[i++].matched)//"Cookie"
584 body_info.m_cookie = result[field_val];
585 else if(result[i++].matched)//"User-Agent"
586 body_info.m_user_agent = result[field_val];
587 else if(result[i++].matched)//"Origin"
588 body_info.m_origin = result[field_val];
589 else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
590 body_info.m_etc_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
591 else
592 {
593 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::parse_cached_header() not matched last entry in:" << m_cache_to_process);
594 }
595
596 it_current_bound = result[(int)result.size()-1]. first;
597 }
598 return true;
599 }
600 //-----------------------------------------------------------------------------------
601 template<class t_connection_context>
603 {
604 STATIC_REGEXP_EXPR_1(rexp_mach_field, "\\d+", boost::regex::normal);
605 std::string res;
606 boost::smatch result;
607 if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched))
608 return false;
609
610 try { len = boost::lexical_cast<size_t>(result[0]); }
611 catch(...) { return false; }
612 return true;
613 }
614 //-----------------------------------------------------------------------------------
615 template<class t_connection_context>
617 {
618 http_response_info response{};
619 //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" );
620 bool res = true;
621
623 {
624 res = handle_request(query_info, response);
625 if (response.m_response_code == 500)
626 {
627 m_want_close = true; // close on all "Internal server error"s
628 }
629 }
630 else
631 {
632 response.m_response_code = 200;
633 response.m_response_comment = "OK";
634 }
635
636 std::string response_data = get_response_header(response);
637 //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body);
638
639 LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data);
640
641 if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options))
642 response_data += response.m_body;
643
644 m_psnd_hndlr->do_send(byte_slice{std::move(response_data)});
645 m_psnd_hndlr->send_done();
646 return res;
647 }
648 //-----------------------------------------------------------------------------------
649 template<class t_connection_context>
651 {
652
653 std::string uri_to_path = query_info.m_uri_content.m_path;
654 if("/" == uri_to_path)
655 uri_to_path = "/index.html";
656
657 //slash_to_back_slash(uri_to_path);
658 m_config.m_lock.lock();
659 std::string destination_file_path = m_config.m_folder + uri_to_path;
660 m_config.m_lock.unlock();
661 if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body))
662 {
663 MWARNING("URI \""<< query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size()-2) << "\" [" << destination_file_path << "] Not Found (404 )");
664 response.m_body = get_not_found_response_body(query_info.m_URI);
665 response.m_response_code = 404;
666 response.m_response_comment = "Not found";
667 response.m_mime_tipe = "text/html";
668 return true;
669 }
670
671 MDEBUG(" -->> " << query_info.m_full_request_str << "\r\n<<--OK");
672 response.m_response_code = 200;
673 response.m_response_comment = "OK";
674 response.m_mime_tipe = get_file_mime_tipe(uri_to_path);
675
676 return true;
677 }
678 //-----------------------------------------------------------------------------------
679 template<class t_connection_context>
681 {
682 std::string buf = "HTTP/1.1 ";
683 buf += boost::lexical_cast<std::string>(response.m_response_code) + " " + response.m_response_comment + "\r\n" +
684 "Server: Epee-based\r\n"
685 "Content-Length: ";
686 buf += boost::lexical_cast<std::string>(response.m_body.size()) + "\r\n";
687
688 if(!response.m_mime_tipe.empty())
689 {
690 buf += "Content-Type: ";
691 buf += response.m_mime_tipe + "\r\n";
692 }
693
694 buf += "Last-Modified: ";
695 time_t tm;
696 time(&tm);
698 buf += "Accept-Ranges: bytes\r\n";
699 //Wed, 01 Dec 2010 03:27:41 GMT"
700
701 string_tools::trim(m_query_info.m_header_info.m_connection);
702 if(m_query_info.m_header_info.m_connection.size())
703 {
704 if(!string_tools::compare_no_case("close", m_query_info.m_header_info.m_connection))
705 {
706 //closing connection after sending
707 buf += "Connection: close\r\n";
709 m_want_close = true;
710 }
711 }
712
713 // Cross-origin resource sharing
714 if(m_query_info.m_header_info.m_origin.size())
715 {
716 if (std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), "*") || std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), m_query_info.m_header_info.m_origin))
717 {
718 buf += "Access-Control-Allow-Origin: ";
719 buf += m_query_info.m_header_info.m_origin;
720 buf += "\r\n";
721 buf += "Access-Control-Expose-Headers: www-authenticate\r\n";
722 if (m_query_info.m_http_method == http::http_method_options)
723 buf += "Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With\r\n";
724 buf += "Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS\r\n";
725 }
726 }
727
728 //add additional fields, if it is
729 for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++)
730 buf += it->first + ": " + it->second + "\r\n";
731
732 buf+="\r\n";
733
734 return buf;
735 }
736 //-----------------------------------------------------------------------------------
737 template<class t_connection_context>
739 {
740 std::string result;
741 std::string ext = string_tools::get_extension(path);
742 if(!string_tools::compare_no_case(ext, "gif"))
743 result = "image/gif";
744 else if(!string_tools::compare_no_case(ext, "jpg"))
745 result = "image/jpeg";
746 else if(!string_tools::compare_no_case(ext, "html"))
747 result = "text/html";
748 else if(!string_tools::compare_no_case(ext, "htm"))
749 result = "text/html";
750 else if(!string_tools::compare_no_case(ext, "js"))
751 result = "application/x-javascript";
752 else if(!string_tools::compare_no_case(ext, "css"))
753 result = "text/css";
754 else if(!string_tools::compare_no_case(ext, "xml"))
755 result = "application/xml";
756 else if(!string_tools::compare_no_case(ext, "svg"))
757 result = "image/svg+xml";
758
759
760 return result;
761 }
762 //-----------------------------------------------------------------------------------
763 template<class t_connection_context>
765 {
766 std::string body =
767 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
768 "<html><head>\r\n"
769 "<title>404 Not Found</title>\r\n"
770 "</head><body>\r\n"
771 "<h1>Not Found</h1>\r\n"
772 "<p>The requested URL \r\n";
773 body += URI;
774 body += "was not found on this server.</p>\r\n"
775 "</body></html>\r\n";
776
777 return body;
778 }
779 //--------------------------------------------------------------------------------------------
780 template<class t_connection_context>
782 {
783 for(std::string::iterator it = str.begin(); it!=str.end(); it++)
784 if('/' == *it)
785 *it = '\\';
786 return true;
787 }
788 }
789}
790}
791
792//--------------------------------------------------------------------------------------------
793//--------------------------------------------------------------------------------------------
794//--------------------------------------------------------------------------------------------
Definition byte_slice.h:69
size_t m_bytes_read
Definition http_protocol_handler.h:148
config_type & m_config
Definition http_protocol_handler.h:145
bool get_len_from_content_lenght(const std::string &str, size_t &len)
Definition http_protocol_handler.inl:602
bool parse_cached_header(http_header_info &body_info, const std::string &m_cache_to_process, size_t pos)
Definition http_protocol_handler.inl:547
@ http_body_transfer_measure
Definition http_protocol_handler.h:110
@ http_body_transfer_undefined
Definition http_protocol_handler.h:114
@ http_body_transfer_connection_close
Definition http_protocol_handler.h:112
@ http_body_transfer_multipart
Definition http_protocol_handler.h:113
@ http_body_transfer_chunked
Definition http_protocol_handler.h:109
i_service_endpoint * m_psnd_hndlr
Definition http_protocol_handler.h:150
bool after_init_connection()
Definition http_protocol_handler.inl:242
virtual ~simple_http_connection_handler()
Definition http_protocol_handler.inl:218
std::string m_cache
Definition http_protocol_handler.h:139
bool handle_retriving_query_body()
Definition http_protocol_handler.inl:501
bool slash_to_back_slash(std::string &str)
Definition http_protocol_handler.inl:781
@ http_state_retriving_body
Definition http_protocol_handler.h:103
@ http_state_connection_close
Definition http_protocol_handler.h:104
@ http_state_error
Definition http_protocol_handler.h:105
@ http_state_retriving_header
Definition http_protocol_handler.h:102
@ http_state_retriving_comand_line
Definition http_protocol_handler.h:101
size_t m_newlines
Definition http_protocol_handler.h:147
http::http_request_info m_query_info
Definition http_protocol_handler.h:143
machine_state m_state
Definition http_protocol_handler.h:140
bool m_initialized
Definition http_protocol_handler.h:152
std::string get_file_mime_tipe(const std::string &path)
Definition http_protocol_handler.inl:738
bool handle_invoke_query_line()
Definition http_protocol_handler.inl:400
bool handle_buff_in(std::string &buf)
Definition http_protocol_handler.inl:278
bool handle_query_measure()
Definition http_protocol_handler.inl:521
body_transfer_type m_body_transfer_type
Definition http_protocol_handler.h:141
bool set_ready_state()
Definition http_protocol_handler.inl:252
bool handle_request_and_send_response(const http::http_request_info &query_info)
Definition http_protocol_handler.inl:616
size_t m_len_remain
Definition http_protocol_handler.h:144
t_connection_context & m_conn_context
Definition http_protocol_handler.h:151
bool analize_cached_request_header_and_invoke_state(size_t pos)
Definition http_protocol_handler.inl:454
std::string get_response_header(const http_response_info &response)
Definition http_protocol_handler.inl:680
std::string::size_type match_end_of_header(const std::string &buf)
Definition http_protocol_handler.inl:440
virtual bool handle_request(const http::http_request_info &query_info, http_response_info &response)
Definition http_protocol_handler.inl:650
bool m_is_stop_handling
Definition http_protocol_handler.h:142
virtual bool handle_recv(const void *ptr, size_t cb)
Definition http_protocol_handler.inl:265
http_server_config config_type
Definition http_protocol_handler.h:76
bool m_want_close
Definition http_protocol_handler.h:146
std::string get_not_found_response_body(const std::string &URI)
Definition http_protocol_handler.inl:764
simple_http_connection_handler(i_service_endpoint *psnd_hndlr, config_type &config, t_connection_context &conn_context)
Definition http_protocol_handler.inl:200
size_t m_len_summary
Definition http_protocol_handler.h:144
#define false
const char * res
Definition hmac_keccak.cpp:42
#define HTTP_MAX_STARTING_NEWLINES
Definition http_protocol_handler.inl:42
#define HTTP_MAX_URI_LEN
Definition http_protocol_handler.inl:40
#define HTTP_MAX_HEADER_LEN
Definition http_protocol_handler.inl:41
Definition cryptonote_config.h:221
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
Definition file_io_utils.cpp:105
std::string get_internet_time_str(const time_t &time_)
Definition time_helper.h:49
http_method
Definition http_base.h:49
@ http_method_head
Definition http_base.h:54
@ http_method_etc
Definition http_base.h:55
@ http_method_put
Definition http_base.h:53
@ http_method_get
Definition http_base.h:51
@ http_method_post
Definition http_base.h:52
@ http_method_options
Definition http_base.h:50
bool match_boundary(const std::string &content_type, std::string &boundary)
Definition http_protocol_handler.inl:60
bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry &entry)
Definition http_protocol_handler.inl:75
bool parse_multipart_body(const std::string &content_type, const std::string &body, std::list< multipart_entry > &out_values)
Definition http_protocol_handler.inl:134
bool analize_http_method(const boost::smatch &result, http::http_method &method, int &http_ver_major, int &http_ver_minor)
Definition http_protocol_handler.inl:374
bool handle_part_of_multipart(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry &entry)
Definition http_protocol_handler.inl:112
bool parse_uri(const std::string uri, http::uri_content &content)
Definition net_parse_helpers.cpp:102
std::string get_extension(const std::string &str)
Definition string_tools.cpp:193
bool compare_no_case(const std::string &str1, const std::string &str2)
Definition string_tools.cpp:136
std::string & trim(std::string &str)
Definition string_tools.h:75
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
#define LOG_ERROR_CC(ct, message)
Definition net_utils_base.h:469
const char *const str
Definition portlistingparse.c:23
#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags)
Definition reg_exp_definer.h:48
tools::wallet2::message_signature_result_t result
Definition signature.cpp:62
const char * buf
Definition slow_memmem.cpp:73
#define OUT
Definition string_tools.h:40
fields_list m_etc_fields
Definition http_base.h:96
std::string m_content_length
Definition http_base.h:88
std::string m_content_encoding
Definition http_base.h:91
std::string m_origin
Definition http_base.h:95
std::string m_referer
Definition http_base.h:87
std::string m_cookie
Definition http_base.h:93
void clear()
Definition http_base.h:98
std::string m_connection
Definition http_base.h:86
std::string m_user_agent
Definition http_base.h:94
std::string m_content_type
Definition http_base.h:89
std::string m_transfer_encoding
Definition http_base.h:90
std::string m_host
Definition http_base.h:92
std::string m_full_request_str
Definition http_base.h:144
uri_content m_uri_content
Definition http_base.h:151
http_method m_http_method
Definition http_base.h:141
std::string m_URI
Definition http_base.h:142
std::string m_response_comment
Definition http_base.h:166
std::string m_mime_tipe
Definition http_base.h:169
int m_response_code
Definition http_base.h:165
std::string m_body
Definition http_base.h:168
fields_list m_additional_fields
Definition http_base.h:167
Definition http_protocol_handler.inl:52
std::string m_body
Definition http_protocol_handler.inl:56
std::list< std::pair< std::string, std::string > > m_etc_header_fields
Definition http_protocol_handler.inl:53
std::string m_content_type
Definition http_protocol_handler.inl:55
std::string m_content_disposition
Definition http_protocol_handler.inl:54
std::string m_path
Definition http_base.h:116
Definition net_utils_base.h:442
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153