GNUnet 0.21.1
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
35static inline int
36natoi (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
56static inline int
57is_relative (const char *url)
58{
59 return (*url == '/') ? 1 : 0;
60}
61
62
70static inline char *
71parse_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
102static 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. */
119static inline char *
120find_fragment (char *str)
121{
122 return find_and_terminate (str, '#');
123}
124
125
126static inline char *
127find_query (char *str)
128{
129 return find_and_terminate (str, '?');
130}
131
132
133static inline char *
134find_path (char *str)
135{
136 return find_and_terminate (str, '/');
137}
138
139
159int
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
260int
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
312int
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}
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
struct GNUNET_HashCode key
The key used in the DHT.
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 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 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_path(char *str)
Definition: uri.c:134
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 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