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