1 //===-- UriParser.cpp -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Utility/UriParser.h"
11 
12 // C Includes
13 
14 // C++ Includes
15 #include <cstring>
16 
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Host/StringConvert.h"
20 
21 using namespace lldb_private;
22 
23 //----------------------------------------------------------------------
24 // UriParser::Parse
25 //----------------------------------------------------------------------
26 bool UriParser::Parse(const std::string &uri, std::string &scheme,
27                       std::string &hostname, int &port, std::string &path) {
28   std::string tmp_scheme, tmp_hostname, tmp_port, tmp_path;
29 
30   static const char *kSchemeSep = "://";
31   auto pos = uri.find(kSchemeSep);
32   if (pos == std::string::npos)
33     return false;
34 
35   // Extract path.
36   tmp_scheme = uri.substr(0, pos);
37   auto host_pos = pos + strlen(kSchemeSep);
38   auto path_pos = uri.find('/', host_pos);
39   if (path_pos != std::string::npos)
40     tmp_path = uri.substr(path_pos);
41   else
42     tmp_path = "/";
43 
44   auto host_port = uri.substr(
45       host_pos,
46       ((path_pos != std::string::npos) ? path_pos : uri.size()) - host_pos);
47 
48   // Extract hostname
49   if (host_port[0] == '[') {
50     // hostname is enclosed with square brackets.
51     pos = host_port.find(']');
52     if (pos == std::string::npos)
53       return false;
54 
55     tmp_hostname = host_port.substr(1, pos - 1);
56     host_port.erase(0, pos + 1);
57   } else {
58     pos = host_port.find(':');
59     tmp_hostname = host_port.substr(
60         0, (pos != std::string::npos) ? pos : host_port.size());
61     host_port.erase(0, (pos != std::string::npos) ? pos : host_port.size());
62   }
63 
64   // Extract port
65   tmp_port = host_port;
66   if (!tmp_port.empty()) {
67     if (tmp_port[0] != ':')
68       return false;
69     tmp_port = tmp_port.substr(1);
70     bool success = false;
71     auto port_tmp =
72         StringConvert::ToUInt32(tmp_port.c_str(), UINT32_MAX, 10, &success);
73     if (!success || port_tmp > 65535) {
74       // there are invalid characters in port_buf
75       return false;
76     }
77     port = port_tmp;
78   } else
79     port = -1;
80 
81   scheme = tmp_scheme;
82   hostname = tmp_hostname;
83   path = tmp_path;
84   return true;
85 }
86