28 #ifndef WEBSOCKETPP_URI_HPP
29 #define WEBSOCKETPP_URI_HPP
31 #include <websocketpp/error.hpp>
33 #include <websocketpp/common/memory.hpp>
34 #include <websocketpp/common/stdint.hpp>
62 if ((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z')) {
64 }
else if (c >=
'0' && c <=
'9') {
66 }
else if (c ==
'-' || c ==
'.' || c ==
'_' || c ==
'~') {
166 if ((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z')) {
168 }
else if (c >=
'0' && c <=
'9') {
170 }
else if (c ==
'+' || c ==
'-' || c ==
'.') {
185 return c >=
'0' && c <=
'9';
195 inline bool digit(std::string::const_iterator it) {
212 return hexdigit(*it) && hexdigit(*(it + 1));
223 inline bool dec_octet(std::string::const_iterator start, std::string::const_iterator end) {
224 if (end-start == 1) {
226 }
else if (end-start == 2) {
227 return ((*start >=
'1' && *start <=
'9') && digit(start+1));
228 }
else if (end-start == 3) {
230 return digit(start+1) && digit(start+2);
231 }
else if (*start ==
'2') {
232 if (*(start+1) >=
'0' && *(start+1) <=
'4') {
233 return digit(start+2);
234 }
else if (*(start+1) ==
'5') {
235 return *(start+2) >=
'0' && *(start+2) <=
'5';
250 inline bool ipv4_literal(std::string::const_iterator start, std::string::const_iterator end) {
251 std::string::const_iterator cursor = start;
253 for (std::string::const_iterator it = start; it != end; ++it) {
255 if (dec_octet(cursor,it)) {
268 return (counter == 3 && dec_octet(cursor,end));
279 inline bool hex4(std::string::const_iterator start, std::string::const_iterator end) {
280 if (end-start == 0 || end-start >4) {
283 for (std::string::const_iterator it = start; it != end; ++it) {
284 if (!hexdigit(*it)) {
299 inline bool ipv6_literal(std::string::const_iterator start, std::string::const_iterator end) {
301 if (end-start > 45 && end-start >= 2) {
307 std::string::const_iterator cursor = start;
308 std::string::const_iterator it = start;
317 }
else if (it-cursor == 0) {
321 }
else if (hex4(cursor,it)) {
334 }
else if (hex4(cursor,end)) {
336 }
else if (ipv4_literal(cursor, end)) {
342 if ((abbr == 0 && count != 8) || (abbr == 1 && count > 7) || abbr > 1) {
373 inline bool reg_name(std::string::const_iterator start, std::string::const_iterator end) {
374 std::string::const_iterator it = start;
378 if (it+2 < end && uri_helper::pct_encoded(it+1)) {
384 }
else if (!uri_helper::reg_name(*it)) {
399 explicit uri(std::string
const & uri_string) : m_valid(
false), m_ipv6_literal(
false) {
400 std::string::const_iterator it;
401 std::string::const_iterator temp;
405 it = uri_string.begin();
406 size_t uri_len = uri_string.length();
409 if (uri_len >= 7 && std::equal(it,it+6,
"wss://")) {
413 }
else if (uri_len >= 6 && std::equal(it,it+5,
"ws://")) {
417 }
else if (uri_len >= 8 && std::equal(it,it+7,
"http://")) {
421 }
else if (uri_len >= 9 && std::equal(it,it+8,
"https://")) {
442 while (temp != uri_string.end()) {
449 if (temp == uri_string.end()) {
453 if (!uri_helper::ipv6_literal(it,temp)) {
456 m_ipv6_literal =
true;
458 m_host.append(it,temp);
461 if (it == uri_string.end()) {
463 }
else if (*it ==
'/' || *it ==
'?' || *it ==
'#') {
469 }
else if (*it ==
':') {
482 if (it == uri_string.end()) {
485 }
else if (*it ==
'%') {
487 if (it+2 < uri_string.end() && uri_helper::pct_encoded(it+1)) {
488 m_host.append(it,it+2);
491 }
else if (!uri_helper::reg_name(*it)) {
500 }
else if (*it ==
'/' || *it ==
'#' || *it ==
'?') {
524 if (it == uri_string.end()) {
531 }
else if (uri_helper::digit(it)) {
549 m_port = get_port_from_string(port, ec);
556 m_resource.append(it,uri_string.end());
558 if (m_resource.empty()) {
568 uri(
bool secure, std::string
const & host, uint16_t port,
569 std::string
const & resource)
570 : m_scheme(secure ?
"wss" :
"ws")
572 , m_resource(resource.empty() ?
"/" : resource)
576 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
577 m_valid = m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end());
580 uri(
bool secure, std::string
const & host, std::string
const & resource)
581 : m_scheme(secure ?
"wss" :
"ws")
583 , m_resource(resource.empty() ?
"/" : resource)
584 , m_port(secure ? uri_default_secure_port : uri_default_port)
587 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
588 m_valid = m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end());
591 uri(
bool secure, std::string
const & host, std::string
const & port,
592 std::string
const & resource)
593 : m_scheme(secure ?
"wss" :
"ws")
595 , m_resource(resource.empty() ?
"/" : resource)
599 m_port = get_port_from_string(port,ec);
600 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
602 m_valid = !ec && (m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end()));
605 uri(std::string
const & scheme, std::string
const & host, uint16_t port,
606 std::string
const & resource)
609 , m_resource(resource.empty() ?
"/" : resource)
611 , m_secure(scheme ==
"wss" || scheme ==
"https")
613 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
614 m_valid = m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end());
617 uri(std::string scheme, std::string
const & host, std::string
const & resource)
620 , m_resource(resource.empty() ?
"/" : resource)
621 , m_port((scheme ==
"wss" || scheme ==
"https") ? uri_default_secure_port : uri_default_port)
622 , m_secure(scheme ==
"wss" || scheme ==
"https")
624 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
625 m_valid = m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end());
628 uri(std::string
const & scheme, std::string
const & host,
629 std::string
const & port, std::string
const & resource)
632 , m_resource(resource.empty() ?
"/" : resource)
633 , m_secure(scheme ==
"wss" || scheme ==
"https")
636 m_port = get_port_from_string(port,ec);
637 m_ipv6_literal = uri_helper::ipv6_literal(host.begin(), host.end());
639 m_valid = !ec && (m_ipv6_literal || uri_helper::reg_name(host.begin(), host.end()));
642 bool get_valid()
const {
652 return m_ipv6_literal;
655 bool get_secure()
const {
659 std::string
const & get_scheme()
const {
663 std::string
const & get_host()
const {
667 std::string get_host_port()
const {
668 if (m_port == (m_secure ? uri_default_secure_port : uri_default_port)) {
673 if (m_ipv6_literal) {
674 p <<
"[" << m_host <<
"]:" << m_port;
676 p << m_host <<
":" << m_port;
683 std::string get_authority()
const {
685 if (m_ipv6_literal) {
686 p <<
"[" << m_host <<
"]:" << m_port;
688 p << m_host <<
":" << m_port;
693 uint16_t get_port()
const {
697 std::string get_port_str()
const {
703 std::string
const & get_resource()
const {
707 std::string str()
const {
710 s << m_scheme <<
"://";
711 if (m_ipv6_literal) {
712 s <<
"[" << m_host <<
"]";
717 if (m_port != (m_secure ? uri_default_secure_port : uri_default_port)) {
733 std::size_t found = m_resource.find(
'?');
734 if (found != std::string::npos) {
735 return m_resource.substr(found + 1);
759 uint16_t get_port_from_string(std::string
const & port, lib::error_code &
762 ec = lib::error_code();
765 return (m_secure ? uri_default_secure_port : uri_default_port);
768 unsigned int t_port =
static_cast<
unsigned int>(atoi(port.c_str()));
770 if (t_port > 65535) {
771 ec = error::make_error_code(error::invalid_port);
775 ec = error::make_error_code(error::invalid_port);
778 return static_cast<uint16_t>(t_port);
781 std::string m_scheme;
783 std::string m_resource;