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