GNUnet  0.11.x
uri.c
Go to the documentation of this file.
1 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include "gnunet_uri_lib.h"
26 
27 
34 static inline int
35 natoi (const char *str,
36  size_t len)
37 {
38  int i, r = 0;
39  for (i = 0; i < len; i++) {
40  r *= 10;
41  r += str[i] - '0';
42  }
43 
44  return r;
45 }
46 
47 
55 static inline int
56 is_relative (const char *url)
57 {
58  return (*url == '/') ? 1 : 0;
59 }
60 
61 
69 static inline char *
70 parse_scheme (char *str)
71 {
72  char *s;
73 
74  /* If not found or first in string, return error */
75  s = strchr (str, ':');
76  if (s == NULL || s == str) {
77  return NULL;
78  }
79 
80  /* If not followed by two slashes, return error */
81  if (s[1] == '\0' || s[1] != '/' || s[2] == '\0' || s[2] != '/') {
82  return NULL;
83  }
84 
85  *s = '\0'; // Replace ':' with NULL
86 
87  return s + 3;
88 }
89 
90 
101 static inline char *
103  char find)
104 {
105  str = strchr(str, find);
106  if (NULL == str) {
107  return NULL;
108  }
109 
110  *str = '\0';
111  return str + 1;
112 }
113 
114 
115 /* Yes, the following functions could be implemented as preprocessor macros
116  instead of inline functions, but I think that this approach will be more
117  clean in this case. */
118 static inline char *
119 find_fragment (char *str)
120 {
121  return find_and_terminate (str, '#');
122 }
123 
124 
125 static inline char *
126 find_query (char *str)
127 {
128  return find_and_terminate (str, '?');
129 }
130 
131 
132 static inline char *
133 find_path (char *str)
134 {
135  return find_and_terminate (str, '/');
136 }
137 
138 
158 int
160  char *u)
161 {
162  if (NULL == url || NULL == u) {
163  return -1;
164  }
165 
166  memset(url, 0, sizeof (struct GNUNET_Uri));
167 
168  /* (Fragment) */
169  url->fragment = find_fragment (u);
170 
171  /* (Query) */
172  url->query = find_query (u);
173 
174  /* Relative URL? Parse scheme and hostname */
175  if (!is_relative (u)) {
176  /* Scheme */
177  url->scheme = u;
178  u = parse_scheme (u);
179  if (u == NULL) {
180  return -1;
181  }
182 
183  /* Host */
184  if ('\0' == *u) {
185  return -1;
186  }
187  url->host = u;
188 
189  /* (Path) */
190  url->path = find_path (u);
191 
192  /* (Credentials) */
193  u = strchr (url->host, '@');
194  if (NULL != u) {
195  /* Missing credentials? */
196  if (u == url->host) {
197  return -1;
198  }
199 
200  url->username = url->host;
201  url->host = u + 1;
202  *u = '\0';
203 
204  u = strchr (url->username, ':');
205  if (NULL == u) {
206  return -1;
207  }
208 
209  url->password = u + 1;
210  *u = '\0';
211  }
212 
213  /* Missing hostname? */
214  if ('\0' == *url->host) {
215  return -1;
216  }
217 
218  /* (Port) */
219  u = strchr (url->host, ':');
220  if (NULL != u && (NULL == url->path || u < url->path)) {
221  *(u++) = '\0';
222  if ('\0' == *u) {
223  return -1;
224  }
225 
226  if (url->path) {
227  url->port = natoi (u, url->path - u - 1);
228  } else {
229  url->port = atoi (u);
230  }
231  }
232 
233  /* Missing hostname? */
234  if ('\0' == *url->host) {
235  return -1;
236  }
237  } else {
238  /* (Path) */
239  url->path = find_path (u);
240  }
241 
242  return 0;
243 }
244 
245 
259 int
261  char **parts,
262  int max_parts)
263 {
264  int i = 0;
265 
266  if (NULL == path || '\0' == *path) {
267  return -1;
268  }
269 
270  do {
271  /* Forward to after slashes */
272  while (*path == '/') path++;
273 
274  if ('\0' == *path) {
275  break;
276  }
277 
278  parts[i++] = path;
279 
280  path = strchr (path, '/');
281  if (NULL == path) {
282  break;
283  }
284 
285  *(path++) = '\0';
286  } while (i < max_parts);
287 
288  return i;
289 }
290 
291 
311 int
313  char delimiter,
314  struct GNUNET_UriParam *params,
315  int max_params)
316 {
317  int i = 0;
318 
319  if (NULL == query || '\0' == *query) {
320  return -1;
321  }
322 
323  params[i++].key = query;
324  while (i < max_params && NULL != (query = strchr (query, delimiter))) {
325  *query = '\0';
326  params[i].key = ++query;
327  params[i].val = NULL;
328 
329  /* Go back and split previous param */
330  if (i > 0) {
331  if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
332  *(params[i - 1].val)++ = '\0';
333  }
334  }
335  i++;
336  }
337 
338  /* Go back and split last param */
339  if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
340  *(params[i - 1].val)++ = '\0';
341  }
342 
343  return i;
344 }
static char * find_and_terminate(char *str, char find)
Find a character in a string, replace it with &#39;\0&#39; and return the next character in the string...
Definition: uri.c:102
char * query
char * scheme
int GNUNET_uri_parse(struct GNUNET_Uri *url, char *u)
Parse a URL to a struct.
Definition: uri.c:159
char * fragment
static char * find_fragment(char *str)
Definition: uri.c:119
char * password
char * username
static char * find_query(char *str)
Definition: uri.c:126
static int natoi(const char *str, size_t len)
Copyright (C) 2016,2017 Jack Engqvist Johansson.
Definition: uri.c:35
static char * parse_scheme(char *str)
Parse the scheme of a URL by inserting a null terminator after the scheme.
Definition: uri.c:70
int GNUNET_uri_split_path(char *path, char **parts, int max_parts)
Split a path into several strings.
Definition: uri.c:260
struct GNUNET_HashCode key
The key used in the DHT.
Copyright (C) 2016 Jack Engqvist Johansson.
int GNUNET_uri_parse_query(char *query, char delimiter, struct GNUNET_UriParam *params, int max_params)
Parse a query string into a key/value struct.
Definition: uri.c:312
static int is_relative(const char *url)
Check if a URL is relative (no scheme and hostname).
Definition: uri.c:56
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * find_path(char *str)
Definition: uri.c:133