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