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 
GWEN_Url_fromString(const char * str)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))
212       GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
213                            GWEN_DB_FLAGS_DEFAULT,
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 
GWEN_Url_toString(const GWEN_URL * url,GWEN_BUFFER * buf)227 int GWEN_Url_toString(const GWEN_URL *url, GWEN_BUFFER *buf)
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) {
266             s=GWEN_DB_GetCharValueFromNode(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 
GWEN_Url_toUiShortString(const GWEN_URL * url,GWEN_BUFFER * buf)282 void GWEN_Url_toUiShortString(const GWEN_URL *url, GWEN_BUFFER *buf)
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 
GWEN_Url_fromCommandString(const char * str)308 GWEN_URL *GWEN_Url_fromCommandString(const char *str)
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))
372       GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
373                            GWEN_DB_FLAGS_DEFAULT,
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 
GWEN_Url_toCommandString(const GWEN_URL * url,GWEN_BUFFER * buf)387 int GWEN_Url_toCommandString(const GWEN_URL *url, GWEN_BUFFER *buf)
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) {
409           s=GWEN_DB_GetCharValueFromNode(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 
425