CPPMyth
Library to interoperate with MythTV server
Loading...
Searching...
No Matches
uriparser.cpp
1/*
2 * Copyright (C) 2014-2015 Jean-Luc Barriere
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 3, or (at your option)
7 * any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; see the file COPYING. If not, write to
16 * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 */
21
22#include "uriparser.h"
23
24#include <ctype.h> // for toupper
25#include <cstring> // for strchr
26#include <cstdlib> // for atoi
27
28using namespace NSROOT;
29
30URIParser::URIParser(const std::string& location)
31{
32 size_t len = location.length();
33 m_buffer = new char[len + 1];
34 strncpy(m_buffer, location.c_str(), len);
35 m_buffer[len] = '\0';
36 URIScan(m_buffer, &m_parts);
37}
38
39URIParser::~URIParser()
40{
41 if (m_buffer)
42 delete [] m_buffer;
43 m_buffer = nullptr;
44}
45
46void URIParser::URIScan(char *uri, URI_t *parts)
47{
48 char *p;
49 char *after_scheme = uri;
50 memset(parts, '\0', sizeof(URI_t));
51
52 /* space is not allowed, therefore break on space */
53 if ((p = strchr(uri, ' ')) != nullptr)
54 *p = '\0';
55
56 /* first look for scheme */
57 for (p = after_scheme; *p; p++)
58 {
59 if (*p == '/' || *p == '#' || *p == '?')
60 break;
61 if (*p == ':')
62 {
63 /* terminate scheme */
64 *p = '\0';
65 /* scheme has been specified */
66 if (toupper(after_scheme[0]) == 'U'
67 && toupper(after_scheme[1]) == 'R'
68 && toupper(after_scheme[2]) == 'L')
69 {
70 /* ignore IETF's URL: pre-prefix */
71 parts->scheme = nullptr;
72 }
73 else
74 {
75 parts->scheme = after_scheme;
76 }
77 after_scheme = p + 1;
78 break;
79 }
80 }
81
82 /* parse the rest after scheme */
83 p = after_scheme;
84 if (*p == '/')
85 {
86 if (p[1] == '/')
87 {
88 /* host has been specified */
89 parts->host = p + 2;
90 /* terminate scheme */
91 *p = '\0';
92 /* look for end of host:port if any */
93 if ((p = strchr(parts->host, '/')) != nullptr)
94 {
95 /* terminate host:port */
96 *p = '\0';
97 /* root has been found */
98 parts->absolute = p + 1;
99 }
100 /* look for user:pass from host */
101 if ((p = strchr(parts->host, '@')) != nullptr)
102 {
103 /* terminate user:pass */
104 *p = '\0';
105 parts->user = parts->host;
106 parts->host = p + 1;
107 /* look for pass from user */
108 if ((p = strchr(parts->user, ':')) != nullptr)
109 {
110 /* terminate user */
111 *p = '\0';
112 parts->pass = p + 1;
113 }
114 }
115 /* look for port from [host] */
116 if ((p = strchr(parts->host, ']')) != nullptr)
117 {
118 /* terminate host */
119 *p = '\0';
120 ++(parts->host);
121 if (p[1] == ':')
122 parts->port = (unsigned) atoi(p + 2);
123 }
124 else
125 {
126 /* look for port from host */
127 if ((p = strchr(parts->host, ':')) != nullptr)
128 if (p)
129 {
130 /* terminate host */
131 *p = '\0';
132 parts->port = (unsigned) atoi(p + 1);
133 }
134 }
135 }
136 else
137 {
138 /* root found but no host */
139 parts->absolute = p + 1;
140 }
141 }
142 else
143 {
144 /* nullptr for "" */
145 parts->relative = (*after_scheme) ? after_scheme : nullptr;
146 }
147
148 /* parse fragment from path */
149 if (parts->relative)
150 after_scheme = parts->relative;
151 else if (parts->absolute)
152 after_scheme = parts->absolute;
153
154 /* look for fragment identifier */
155 if ((p = strchr(after_scheme, '#')) != nullptr)
156 {
157 *p = '\0';
158 parts->fragment = ++p;
159 after_scheme = p;
160 }
161 /* parse params to follow */
162 if ((p = strchr(after_scheme, '?')) != nullptr)
163 {
164 *p = '\0';
165 parts->params = ++p;
166 }
167}