gwenhywfar  4.3.3
urlfns.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id$
00005     begin       : Fri May 07 2004
00006     copyright   : (C) 2004 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *          Please see toplevel file COPYING for license details           *
00011  ***************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "url_p.h"
00019 #include "urlfns.h"
00020 #include <gwenhywfar/debug.h>
00021 #include <ctype.h> // for isalpha()
00022 
00023 
00024 GWEN_URL *GWEN_Url_fromString(const char *str) {
00025   GWEN_URL *url;
00026   GWEN_DB_NODE *dbVars;
00027   const char *s;
00028   const char *p;
00029   int starts_with_drive_letter = 0;
00030 
00031   url=GWEN_Url_new();
00032   dbVars=GWEN_DB_Group_new("vars");
00033   GWEN_Url_SetVars(url, dbVars);
00034   GWEN_DB_Group_free(dbVars);
00035   dbVars=0;
00036 
00037   s=str;
00038 
00039   /* Check for a drive letter, which occurs on windows, but this will
00040      always be one single alpha character followed by a colon followed
00041      by a directory separator. */
00042   if (s && isalpha(s[0]) && s[1] == ':'
00043       && (s[2] == '/' || s[2] == '\\')) {
00044     starts_with_drive_letter = 1;
00045   }
00046 
00047   /* read protocol (if any) */
00048   p = starts_with_drive_letter ? s : strchr(s, ':');
00049   if (p) {
00050     if (p[1]=='/' && p[2]=='/') {
00051       char *buf;
00052 
00053       /* got protocol settings */
00054       buf=(char*)malloc(p-s+1);
00055       assert(buf);
00056       memmove(buf, s, p-s+1);
00057       buf[p-s]=0;
00058       GWEN_Url_SetProtocol(url, buf);
00059       free(buf);
00060       s=p+3;
00061     }
00062   }
00063 
00064   if (!*s) {
00065     DBG_ERROR(GWEN_LOGDOMAIN, "No server or path given in url \"%s\"", str);
00066     GWEN_Url_free(url);
00067     return 0;
00068   }
00069 
00070   /* read user/password */
00071   p=strchr(s, '@');
00072   if (p) {
00073     char *upw;
00074     char *pw;
00075     char *pat;
00076 
00077     upw=(char*)malloc(p-s+1);
00078     assert(upw);
00079     memmove(upw, s, p-s);
00080     upw[p-s]=0;
00081     pw=strchr(upw, ':');
00082     if (pw) {
00083       /* there is also a password */
00084       *pw=0;
00085       pw++;
00086     }
00087     pat=strchr(upw, '%');
00088     if (pat)
00089       *pat='@';
00090     GWEN_Url_SetUserName(url, upw);
00091     if (pw)
00092       GWEN_Url_SetPassword(url, pw);
00093     free(upw);
00094     s=p+1;
00095   }
00096 
00097   /* Do we now have a drive letter? (After the protocol?) */
00098   if (!starts_with_drive_letter
00099       && s && isalpha(s[0]) && s[1] == ':'
00100       && (s[2] == '/' || s[2] == '\\')) {
00101     starts_with_drive_letter = 1;
00102   }
00103 
00104   /* read server */
00105   if (!*s) {
00106     DBG_ERROR(GWEN_LOGDOMAIN, "No server given in url \"%s\"", str);
00107     GWEN_Url_free(url);
00108     return 0;
00109   }
00110   p=s;
00111   while(!starts_with_drive_letter && *p && *p!=':' && *p!='/' && *p!='?')
00112     p++;
00113   if (p!=s) {
00114     char *buf;
00115 
00116     /* got server */
00117     buf=(char*)malloc(p-s+1);
00118     assert(buf);
00119     memmove(buf, s, p-s+1);
00120     buf[p-s]=0;
00121     GWEN_Url_SetServer(url, buf);
00122     DBG_DEBUG(GWEN_LOGDOMAIN, "Server: [%s]", buf);
00123     free(buf);
00124     s=p;
00125   }
00126 
00127   /* get port */
00128   if (*s==':') {
00129     p=++s;
00130     while(*p && *p!='?' && *p!='/')
00131       p++;
00132     if (p!=s) {
00133       char *buf;
00134       int port;
00135 
00136       /* got port */
00137       buf=(char*)malloc(p-s+1);
00138       assert(buf);
00139       memmove(buf, s, p-s+1);
00140       buf[p-s]=0;
00141       if (sscanf(buf, "%d", &port)!=1) {
00142         DBG_ERROR(GWEN_LOGDOMAIN, "Bad port (%s) in url \"%s\"", buf, str);
00143         free(buf);
00144         GWEN_Url_free(url);
00145         return 0;
00146       }
00147       url->port=port;
00148       free(buf);
00149       s=p;
00150     }
00151   }
00152   else {
00153     if (url->protocol) {
00154       if (strcasecmp(url->protocol, "http")==0)
00155         url->port=80;
00156       else if (strcasecmp(url->protocol, "https")==0)
00157         url->port=443;
00158     }
00159   }
00160 
00161   /* get path */
00162   if (starts_with_drive_letter || *s=='/') {
00163     p=s;
00164     while(*p && *p!='?')
00165       p++;
00166     if (p!=s) {
00167       char *buf;
00168 
00169       /* got path */
00170       buf=(char*)malloc(p-s+1);
00171       assert(buf);
00172       memmove(buf, s, p-s+1);
00173       buf[p-s]=0;
00174       GWEN_Url_SetPath(url, buf);
00175       DBG_DEBUG(GWEN_LOGDOMAIN, "Path: [%s]", buf);
00176       free(buf);
00177       s=p;
00178     }
00179   }
00180   else {
00181     GWEN_Url_SetPath(url, "/");
00182     if (*s)
00183       s++;
00184   }
00185 
00186   /* read vars */
00187   while(*s && *s=='?') {
00188     GWEN_BUFFER *bName;
00189     GWEN_BUFFER *bValue;
00190 
00191     bName=GWEN_Buffer_new(0, 256, 0, 1);
00192     bValue=GWEN_Buffer_new(0, 256, 0, 1);
00193     s++;
00194     p=s;
00195     while(*p && *p!='?' && *p!='=')
00196       p++;
00197     if (p!=s)
00198       GWEN_Buffer_AppendBytes(bName, s, (p-s));
00199     s=p;
00200     if (*p=='=') {
00201       s++;
00202       p=s;
00203       while(*p && *p!='?')
00204         p++;
00205       if (p!=s)
00206         GWEN_Buffer_AppendBytes(bValue, s, (p-s));
00207       s=p;
00208     }
00209     /* store variable/value pair */
00210     if (GWEN_Buffer_GetUsedBytes(bName))
00211       GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
00212                            GWEN_DB_FLAGS_DEFAULT,
00213                            GWEN_Buffer_GetStart(bName),
00214                            GWEN_Buffer_GetStart(bValue));
00215     GWEN_Buffer_free(bValue);
00216     GWEN_Buffer_free(bName);
00217   }
00218 
00219   url->url=strdup(str);
00220   url->_modified=0;
00221   return url;
00222 }
00223 
00224 
00225 
00226 int GWEN_Url_toString(const GWEN_URL *url, GWEN_BUFFER *buf) {
00227   assert(url);
00228   if (!url->_modified && !(url->url==0 || url->url[0]==0)) {
00229     GWEN_Buffer_AppendString(buf, url->url);
00230   }
00231   else {
00232     GWEN_DB_NODE *dbV;
00233 
00234     if (url->protocol) {
00235       GWEN_Buffer_AppendString(buf, url->protocol);
00236       GWEN_Buffer_AppendString(buf, "://");
00237     }
00238     if (url->server) {
00239       GWEN_Buffer_AppendString(buf, url->server);
00240     }
00241     if (url->port) {
00242       char numbuf[32];
00243 
00244       snprintf(numbuf, sizeof(numbuf), "%d", url->port);
00245       GWEN_Buffer_AppendString(buf, ":");
00246       GWEN_Buffer_AppendString(buf, numbuf);
00247     }
00248     if (url->path) {
00249       GWEN_Buffer_AppendString(buf, url->path);
00250     }
00251     if (url->vars) {
00252       dbV=GWEN_DB_GetFirstVar(url->vars);
00253       while(dbV) {
00254         const char *s;
00255   
00256         s=GWEN_DB_VariableName(dbV);
00257         if (s) {
00258           GWEN_DB_NODE *dbVal;
00259   
00260           GWEN_Buffer_AppendString(buf, "?");
00261           GWEN_Buffer_AppendString(buf, s);
00262           dbVal=GWEN_DB_GetFirstValue(dbV);
00263           if (dbVal) {
00264             s=GWEN_DB_GetCharValueFromNode(dbVal);
00265             if (s) {
00266               GWEN_Buffer_AppendString(buf, "=");
00267               GWEN_Buffer_AppendString(buf, s);
00268             }
00269           }
00270         }
00271         dbV=GWEN_DB_GetNextVar(dbV);
00272       } /* while */
00273     }
00274   }
00275   return 0;
00276 }
00277 
00278 
00279 
00280 GWEN_URL *GWEN_Url_fromCommandString(const char *str) {
00281   GWEN_URL *url;
00282   GWEN_DB_NODE *dbVars;
00283   const char *s;
00284   const char *p;
00285 
00286   url=GWEN_Url_new();
00287   dbVars=GWEN_DB_Group_new("vars");
00288   GWEN_Url_SetVars(url, dbVars);
00289   GWEN_DB_Group_free(dbVars);
00290   dbVars=0;
00291 
00292   s=str;
00293 
00294   /* get path */
00295   if (*s=='/') {
00296     p=s;
00297     while(*p && *p!='?')
00298       p++;
00299     if (p!=s) {
00300       char *buf;
00301 
00302       /* got path */
00303       buf=(char*)malloc(p-s+1);
00304       assert(buf);
00305       memmove(buf, s, p-s+1);
00306       buf[p-s]=0;
00307       GWEN_Url_SetPath(url, buf);
00308       free(buf);
00309       s=p;
00310     }
00311   }
00312   else {
00313     GWEN_Url_SetPath(url, "/");
00314     if (*s)
00315       s++;
00316   }
00317 
00318   /* read vars */
00319   while(*s && *s=='?') {
00320     GWEN_BUFFER *bName;
00321     GWEN_BUFFER *bValue;
00322 
00323     bName=GWEN_Buffer_new(0, 256, 0, 1);
00324     bValue=GWEN_Buffer_new(0, 256, 0, 1);
00325     s++;
00326     p=s;
00327     while(*p && *p!='?' && *p!='=')
00328       p++;
00329     if (p!=s)
00330       GWEN_Buffer_AppendBytes(bName, s, (p-s));
00331     s=p;
00332     if (*p=='=') {
00333       s++;
00334       p=s;
00335       while(*p && *p!='?')
00336         p++;
00337       if (p!=s)
00338         GWEN_Buffer_AppendBytes(bValue, s, (p-s));
00339       s=p;
00340     }
00341     /* store variable/value pair */
00342     if (GWEN_Buffer_GetUsedBytes(bName))
00343       GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
00344                            GWEN_DB_FLAGS_DEFAULT,
00345                            GWEN_Buffer_GetStart(bName),
00346                            GWEN_Buffer_GetStart(bValue));
00347     GWEN_Buffer_free(bValue);
00348     GWEN_Buffer_free(bName);
00349   }
00350 
00351   url->url=strdup(str);
00352 
00353   return url;
00354 }
00355 
00356 
00357 
00358 int GWEN_Url_toCommandString(const GWEN_URL *url, GWEN_BUFFER *buf) {
00359   GWEN_DB_NODE *dbV;
00360 
00361   assert(url);
00362 
00363   if (url->path) {
00364     GWEN_Buffer_AppendString(buf, url->path);
00365   }
00366   if (url->vars) {
00367     dbV=GWEN_DB_GetFirstVar(url->vars);
00368     while(dbV) {
00369       const char *s;
00370   
00371       s=GWEN_DB_VariableName(dbV);
00372       if (s) {
00373         GWEN_DB_NODE *dbVal;
00374   
00375         GWEN_Buffer_AppendString(buf, "?");
00376         GWEN_Buffer_AppendString(buf, s);
00377         dbVal=GWEN_DB_GetFirstValue(dbV);
00378         if (dbVal) {
00379           s=GWEN_DB_GetCharValueFromNode(dbVal);
00380           if (s) {
00381             GWEN_Buffer_AppendString(buf, "=");
00382             GWEN_Buffer_AppendString(buf, s);
00383           }
00384         }
00385       }
00386       dbV=GWEN_DB_GetNextVar(dbV);
00387     }
00388   }
00389 
00390   return 0;
00391 }
00392 
00393 
00394