CPPMyth
Library to interoperate with MythTV server
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 #include "cppdef.h"
24 
25 #include <ctype.h> // for toupper
26 #include <cstring> // for strchr
27 #include <cstdlib> // for atoi
28 
29 using namespace NSROOT;
30 
31 URIParser::URIParser(const std::string& location)
32 {
33  size_t len = location.length();
34  m_buffer = new char[len + 1];
35  strncpy(m_buffer, location.c_str(), len);
36  m_buffer[len] = '\0';
37  URIScan(m_buffer, &m_parts);
38 }
39 
40 URIParser::~URIParser()
41 {
42  SAFE_DELETE_ARRAY(m_buffer);
43 }
44 
45 void URIParser::URIScan(char *uri, URI_t *parts)
46 {
47  char *p;
48  char *after_scheme = uri;
49  memset(parts, '\0', sizeof(URI_t));
50 
51  /* look for fragment identifier */
52  if ((p = strchr(uri, '#')) != NULL)
53  {
54  *p = '\0';
55  parts->fragment = ++p;
56  }
57  if ((p = strchr(uri, ' ')) != NULL)
58  *p = '\0';
59 
60  for (p = after_scheme; *p; p++)
61  {
62  if (*p == '/' || *p == '#' || *p == '?')
63  break;
64  if (*p == ':')
65  {
66  /* terminate scheme */
67  *p = '\0';
68  /* scheme has been specified */
69  if (toupper(after_scheme[0]) == 'U'
70  && toupper(after_scheme[1]) == 'R'
71  && toupper(after_scheme[2]) == 'L')
72  {
73  /* ignore IETF's URL: pre-prefix */
74  parts->scheme = NULL;
75  }
76  else
77  {
78  parts->scheme = after_scheme;
79  }
80  after_scheme = p + 1;
81  break;
82  }
83  }
84 
85  p = after_scheme;
86  if (*p == '/')
87  {
88  if (p[1] == '/')
89  {
90  /* host has been specified */
91  parts->host = p + 2;
92  /* terminate scheme */
93  *p = '\0';
94  /* look for end of host:port if any */
95  if ((p = strchr(parts->host, '/')) != NULL)
96  {
97  /* terminate host:port */
98  *p = '\0';
99  /* root has been found */
100  parts->absolute = p + 1;
101  }
102  /* look for user:pass from host */
103  if ((p = strchr(parts->host, '@')) != NULL)
104  {
105  /* terminate user:pass */
106  *p = '\0';
107  parts->user = parts->host;
108  parts->host = p + 1;
109  /* look for pass from user */
110  if ((p = strchr(parts->user, ':')) != NULL)
111  {
112  /* terminate user */
113  *p = '\0';
114  parts->pass = p + 1;
115  }
116  }
117  /* look for port from [host] */
118  if ((p = strchr(parts->host, ']')) != NULL)
119  {
120  /* terminate host */
121  *p = '\0';
122  ++(parts->host);
123  if (p[1] == ':')
124  parts->port = (unsigned) atoi(p + 2);
125  }
126  else
127  {
128  /* look for port from host */
129  if ((p = strchr(parts->host, ':')) != NULL)
130  if (p)
131  {
132  /* terminate host */
133  *p = '\0';
134  parts->port = (unsigned) atoi(p + 1);
135  }
136  }
137  }
138  else
139  {
140  /* root found but no host */
141  parts->absolute = p + 1;
142  }
143  }
144  else
145  {
146  /* NULL for "" */
147  parts->relative = (*after_scheme) ? after_scheme : NULL;
148  }
149 }