gwenhywfar  5.10.1
urlfns.c
Go to the documentation of this file.
1 /***************************************************************************
2  $RCSfile$
3  -------------------
4  cvs : $Id$
5  begin : Fri May 07 2004
6  copyright : (C) 2004 by Martin Preuss
7  email : martin@libchipcard.de
8 
9  ***************************************************************************
10  * Please see toplevel file COPYING for license details *
11  ***************************************************************************/
12 
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16 
17 
18 #include "url_p.h"
19 #include "urlfns.h"
20 #include <gwenhywfar/debug.h>
21 #include <ctype.h> // for isalpha()
22 
23 
24 GWEN_URL *GWEN_Url_fromString(const char *str)
25 {
26  GWEN_URL *url;
27  GWEN_DB_NODE *dbVars;
28  const char *s;
29  const char *p;
30  int starts_with_drive_letter = 0;
31 
32  url=GWEN_Url_new();
33  dbVars=GWEN_DB_Group_new("vars");
34  GWEN_Url_SetVars(url, dbVars);
35  GWEN_DB_Group_free(dbVars);
36  dbVars=0;
37 
38  s=str;
39 
40  /* Check for a drive letter, which occurs on windows, but this will
41  always be one single alpha character followed by a colon followed
42  by a directory separator. */
43  if (s && isalpha(s[0]) && s[1] == ':'
44  && (s[2] == '/' || s[2] == '\\')) {
45  starts_with_drive_letter = 1;
46  }
47 
48  /* read protocol (if any) */
49  p = starts_with_drive_letter ? s : strchr(s, ':');
50  if (p) {
51  if (p[1]=='/' && p[2]=='/') {
52  char *buf;
53 
54  /* got protocol settings */
55  buf=(char *)malloc(p-s+1);
56  assert(buf);
57  memmove(buf, s, p-s+1);
58  buf[p-s]=0;
59  GWEN_Url_SetProtocol(url, buf);
60  free(buf);
61  s=p+3;
62  }
63  }
64 
65  if (!*s) {
66  DBG_ERROR(GWEN_LOGDOMAIN, "No server or path given in url \"%s\"", str);
67  GWEN_Url_free(url);
68  return 0;
69  }
70 
71  /* read user/password */
72  p=strchr(s, '@');
73  if (p) {
74  char *upw;
75  char *pw;
76  char *pat;
77 
78  upw=(char *)malloc(p-s+1);
79  assert(upw);
80  memmove(upw, s, p-s);
81  upw[p-s]=0;
82  pw=strchr(upw, ':');
83  if (pw) {
84  /* there is also a password */
85  *pw=0;
86  pw++;
87  }
88  pat=strchr(upw, '%');
89  if (pat)
90  *pat='@';
91  GWEN_Url_SetUserName(url, upw);
92  if (pw)
93  GWEN_Url_SetPassword(url, pw);
94  free(upw);
95  s=p+1;
96  }
97 
98  /* Do we now have a drive letter? (After the protocol?) */
99  if (!starts_with_drive_letter
100  && s && isalpha(s[0]) && s[1] == ':'
101  && (s[2] == '/' || s[2] == '\\')) {
102  starts_with_drive_letter = 1;
103  }
104 
105  /* read server */
106  if (!*s) {
107  DBG_ERROR(GWEN_LOGDOMAIN, "No server given in url \"%s\"", str);
108  GWEN_Url_free(url);
109  return 0;
110  }
111  p=s;
112  while (!starts_with_drive_letter && *p && *p!=':' && *p!='/' && *p!='?')
113  p++;
114  if (p!=s) {
115  char *buf;
116 
117  /* got server */
118  buf=(char *)malloc(p-s+1);
119  assert(buf);
120  memmove(buf, s, p-s+1);
121  buf[p-s]=0;
122  GWEN_Url_SetServer(url, buf);
123  DBG_DEBUG(GWEN_LOGDOMAIN, "Server: [%s]", buf);
124  free(buf);
125  s=p;
126  }
127 
128  /* get port */
129  if (*s==':') {
130  p=++s;
131  while (*p && *p!='?' && *p!='/')
132  p++;
133  if (p!=s) {
134  char *buf;
135  int port;
136 
137  /* got port */
138  buf=(char *)malloc(p-s+1);
139  assert(buf);
140  memmove(buf, s, p-s+1);
141  buf[p-s]=0;
142  if (sscanf(buf, "%d", &port)!=1) {
143  DBG_ERROR(GWEN_LOGDOMAIN, "Bad port (%s) in url \"%s\"", buf, str);
144  free(buf);
145  GWEN_Url_free(url);
146  return 0;
147  }
148  url->port=port;
149  free(buf);
150  s=p;
151  }
152  }
153  else {
154  if (url->protocol) {
155  if (strcasecmp(url->protocol, "http")==0)
156  url->port=80;
157  else if (strcasecmp(url->protocol, "https")==0)
158  url->port=443;
159  }
160  }
161 
162  /* get path */
163  if (starts_with_drive_letter || *s=='/') {
164  p=s;
165  while (*p && *p!='?')
166  p++;
167  if (p!=s) {
168  char *buf;
169 
170  /* got path */
171  buf=(char *)malloc(p-s+1);
172  assert(buf);
173  memmove(buf, s, p-s+1);
174  buf[p-s]=0;
175  GWEN_Url_SetPath(url, buf);
176  DBG_DEBUG(GWEN_LOGDOMAIN, "Path: [%s]", buf);
177  free(buf);
178  s=p;
179  }
180  }
181  else {
182  GWEN_Url_SetPath(url, "/");
183  if (*s)
184  s++;
185  }
186 
187  /* read vars */
188  while (*s && *s=='?') {
189  GWEN_BUFFER *bName;
190  GWEN_BUFFER *bValue;
191 
192  bName=GWEN_Buffer_new(0, 256, 0, 1);
193  bValue=GWEN_Buffer_new(0, 256, 0, 1);
194  s++;
195  p=s;
196  while (*p && *p!='?' && *p!='=')
197  p++;
198  if (p!=s)
199  GWEN_Buffer_AppendBytes(bName, s, (p-s));
200  s=p;
201  if (*p=='=') {
202  s++;
203  p=s;
204  while (*p && *p!='?')
205  p++;
206  if (p!=s)
207  GWEN_Buffer_AppendBytes(bValue, s, (p-s));
208  s=p;
209  }
210  /* store variable/value pair */
211  if (GWEN_Buffer_GetUsedBytes(bName))
214  GWEN_Buffer_GetStart(bName),
215  GWEN_Buffer_GetStart(bValue));
216  GWEN_Buffer_free(bValue);
217  GWEN_Buffer_free(bName);
218  }
219 
220  url->url=strdup(str);
221  url->_modified=0;
222  return url;
223 }
224 
225 
226 
228 {
229  assert(url);
230  if (!url->_modified && !(url->url==0 || url->url[0]==0)) {
231  GWEN_Buffer_AppendString(buf, url->url);
232  }
233  else {
234  GWEN_DB_NODE *dbV;
235 
236  if (url->protocol) {
237  GWEN_Buffer_AppendString(buf, url->protocol);
238  GWEN_Buffer_AppendString(buf, "://");
239  }
240  if (url->server) {
241  GWEN_Buffer_AppendString(buf, url->server);
242  }
243  if (url->port) {
244  char numbuf[32];
245 
246  snprintf(numbuf, sizeof(numbuf), "%d", url->port);
247  GWEN_Buffer_AppendString(buf, ":");
248  GWEN_Buffer_AppendString(buf, numbuf);
249  }
250  if (url->path) {
251  GWEN_Buffer_AppendString(buf, url->path);
252  }
253  if (url->vars) {
254  dbV=GWEN_DB_GetFirstVar(url->vars);
255  while (dbV) {
256  const char *s;
257 
258  s=GWEN_DB_VariableName(dbV);
259  if (s) {
260  GWEN_DB_NODE *dbVal;
261 
262  GWEN_Buffer_AppendString(buf, "?");
263  GWEN_Buffer_AppendString(buf, s);
264  dbVal=GWEN_DB_GetFirstValue(dbV);
265  if (dbVal) {
267  if (s) {
268  GWEN_Buffer_AppendString(buf, "=");
269  GWEN_Buffer_AppendString(buf, s);
270  }
271  }
272  }
273  dbV=GWEN_DB_GetNextVar(dbV);
274  } /* while */
275  }
276  }
277  return 0;
278 }
279 
280 
281 
283 {
284 
285  assert(url);
286 
287  if (url->protocol) {
288  GWEN_Buffer_AppendString(buf, url->protocol);
289  GWEN_Buffer_AppendString(buf, "://");
290  }
291  if (url->server) {
292  GWEN_Buffer_AppendString(buf, url->server);
293  }
294  if (url->port) {
295  char numbuf[32];
296 
297  snprintf(numbuf, sizeof(numbuf), "%d", url->port);
298  GWEN_Buffer_AppendString(buf, ":");
299  GWEN_Buffer_AppendString(buf, numbuf);
300  }
301  if (url->path) {
302  GWEN_Buffer_AppendString(buf, url->path);
303  }
304 }
305 
306 
307 
309 {
310  GWEN_URL *url;
311  GWEN_DB_NODE *dbVars;
312  const char *s;
313  const char *p;
314 
315  url=GWEN_Url_new();
316  dbVars=GWEN_DB_Group_new("vars");
317  GWEN_Url_SetVars(url, dbVars);
318  GWEN_DB_Group_free(dbVars);
319  dbVars=0;
320 
321  s=str;
322 
323  /* get path */
324  if (*s=='/') {
325  p=s;
326  while (*p && *p!='?')
327  p++;
328  if (p!=s) {
329  char *buf;
330 
331  /* got path */
332  buf=(char *)malloc(p-s+1);
333  assert(buf);
334  memmove(buf, s, p-s+1);
335  buf[p-s]=0;
336  GWEN_Url_SetPath(url, buf);
337  free(buf);
338  s=p;
339  }
340  }
341  else {
342  GWEN_Url_SetPath(url, "/");
343  if (*s)
344  s++;
345  }
346 
347  /* read vars */
348  while (*s && *s=='?') {
349  GWEN_BUFFER *bName;
350  GWEN_BUFFER *bValue;
351 
352  bName=GWEN_Buffer_new(0, 256, 0, 1);
353  bValue=GWEN_Buffer_new(0, 256, 0, 1);
354  s++;
355  p=s;
356  while (*p && *p!='?' && *p!='=')
357  p++;
358  if (p!=s)
359  GWEN_Buffer_AppendBytes(bName, s, (p-s));
360  s=p;
361  if (*p=='=') {
362  s++;
363  p=s;
364  while (*p && *p!='?')
365  p++;
366  if (p!=s)
367  GWEN_Buffer_AppendBytes(bValue, s, (p-s));
368  s=p;
369  }
370  /* store variable/value pair */
371  if (GWEN_Buffer_GetUsedBytes(bName))
374  GWEN_Buffer_GetStart(bName),
375  GWEN_Buffer_GetStart(bValue));
376  GWEN_Buffer_free(bValue);
377  GWEN_Buffer_free(bName);
378  }
379 
380  url->url=strdup(str);
381 
382  return url;
383 }
384 
385 
386 
388 {
389  GWEN_DB_NODE *dbV;
390 
391  assert(url);
392 
393  if (url->path) {
394  GWEN_Buffer_AppendString(buf, url->path);
395  }
396  if (url->vars) {
397  dbV=GWEN_DB_GetFirstVar(url->vars);
398  while (dbV) {
399  const char *s;
400 
401  s=GWEN_DB_VariableName(dbV);
402  if (s) {
403  GWEN_DB_NODE *dbVal;
404 
405  GWEN_Buffer_AppendString(buf, "?");
406  GWEN_Buffer_AppendString(buf, s);
407  dbVal=GWEN_DB_GetFirstValue(dbV);
408  if (dbVal) {
410  if (s) {
411  GWEN_Buffer_AppendString(buf, "=");
412  GWEN_Buffer_AppendString(buf, s);
413  }
414  }
415  }
416  dbV=GWEN_DB_GetNextVar(dbV);
417  }
418  }
419 
420  return 0;
421 }
422 
423 
424 
void GWEN_Url_free(GWEN_URL *st)
Definition: url.c:40
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:421
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
void GWEN_Url_SetProtocol(GWEN_URL *st, const char *d)
Definition: url.c:171
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_Url_SetServer(GWEN_URL *st, const char *d)
Definition: url.c:193
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
GWEN_URL * GWEN_Url_fromCommandString(const char *str)
Definition: urlfns.c:308
int GWEN_Url_toCommandString(const GWEN_URL *url, GWEN_BUFFER *buf)
Definition: urlfns.c:387
int GWEN_Url_toString(const GWEN_URL *url, GWEN_BUFFER *buf)
Definition: urlfns.c:227
GWEN_DB_NODE * GWEN_DB_GetFirstVar(GWEN_DB_NODE *n)
Definition: db.c:479
struct GWEN_URL GWEN_URL
Definition: url.h:77
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
void GWEN_Url_SetUserName(GWEN_URL *st, const char *d)
Definition: url.c:254
void GWEN_Url_SetPassword(GWEN_URL *st, const char *d)
Definition: url.c:276
const char * GWEN_DB_VariableName(GWEN_DB_NODE *n)
Definition: db.c:1928
GWEN_URL * GWEN_Url_new(void)
Definition: url.c:28
void GWEN_Url_toUiShortString(const GWEN_URL *url, GWEN_BUFFER *buf)
Definition: urlfns.c:282
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWEN_URL * GWEN_Url_fromString(const char *str)
Definition: urlfns.c:24
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:997
void GWEN_Url_SetPath(GWEN_URL *st, const char *d)
Definition: url.c:232
GWEN_DB_NODE * GWEN_DB_GetFirstValue(GWEN_DB_NODE *n)
Definition: db.c:518
GWEN_DB_NODE * GWEN_DB_GetNextVar(GWEN_DB_NODE *n)
Definition: db.c:500
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
GWEN_DB_NODE * GWEN_Url_GetVars(const GWEN_URL *st)
Definition: url.c:291
void GWEN_Url_SetVars(GWEN_URL *st, GWEN_DB_NODE *d)
Definition: url.c:298
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:173
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
const char * GWEN_DB_GetCharValueFromNode(const GWEN_DB_NODE *n)
Definition: db.c:578