gwenhywfar  4.6.0beta
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  GWEN_URL *url;
282  GWEN_DB_NODE *dbVars;
283  const char *s;
284  const char *p;
285 
286  url=GWEN_Url_new();
287  dbVars=GWEN_DB_Group_new("vars");
288  GWEN_Url_SetVars(url, dbVars);
289  GWEN_DB_Group_free(dbVars);
290  dbVars=0;
291 
292  s=str;
293 
294  /* get path */
295  if (*s=='/') {
296  p=s;
297  while(*p && *p!='?')
298  p++;
299  if (p!=s) {
300  char *buf;
301 
302  /* got path */
303  buf=(char*)malloc(p-s+1);
304  assert(buf);
305  memmove(buf, s, p-s+1);
306  buf[p-s]=0;
307  GWEN_Url_SetPath(url, buf);
308  free(buf);
309  s=p;
310  }
311  }
312  else {
313  GWEN_Url_SetPath(url, "/");
314  if (*s)
315  s++;
316  }
317 
318  /* read vars */
319  while(*s && *s=='?') {
320  GWEN_BUFFER *bName;
321  GWEN_BUFFER *bValue;
322 
323  bName=GWEN_Buffer_new(0, 256, 0, 1);
324  bValue=GWEN_Buffer_new(0, 256, 0, 1);
325  s++;
326  p=s;
327  while(*p && *p!='?' && *p!='=')
328  p++;
329  if (p!=s)
330  GWEN_Buffer_AppendBytes(bName, s, (p-s));
331  s=p;
332  if (*p=='=') {
333  s++;
334  p=s;
335  while(*p && *p!='?')
336  p++;
337  if (p!=s)
338  GWEN_Buffer_AppendBytes(bValue, s, (p-s));
339  s=p;
340  }
341  /* store variable/value pair */
342  if (GWEN_Buffer_GetUsedBytes(bName))
345  GWEN_Buffer_GetStart(bName),
346  GWEN_Buffer_GetStart(bValue));
347  GWEN_Buffer_free(bValue);
348  GWEN_Buffer_free(bName);
349  }
350 
351  url->url=strdup(str);
352 
353  return url;
354 }
355 
356 
357 
359  GWEN_DB_NODE *dbV;
360 
361  assert(url);
362 
363  if (url->path) {
364  GWEN_Buffer_AppendString(buf, url->path);
365  }
366  if (url->vars) {
367  dbV=GWEN_DB_GetFirstVar(url->vars);
368  while(dbV) {
369  const char *s;
370 
371  s=GWEN_DB_VariableName(dbV);
372  if (s) {
373  GWEN_DB_NODE *dbVal;
374 
375  GWEN_Buffer_AppendString(buf, "?");
376  GWEN_Buffer_AppendString(buf, s);
377  dbVal=GWEN_DB_GetFirstValue(dbV);
378  if (dbVal) {
380  if (s) {
381  GWEN_Buffer_AppendString(buf, "=");
382  GWEN_Buffer_AppendString(buf, s);
383  }
384  }
385  }
386  dbV=GWEN_DB_GetNextVar(dbV);
387  }
388  }
389 
390  return 0;
391 }
392 
393 
394