path.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Tue Sep 09 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #define DISABLE_DEBUGLOG
00033 
00034 #include "path.h"
00035 #include "gwenhywfar/debug.h"
00036 #include "gwenhywfar/misc.h"
00037 #include "gwenhywfar/text.h"
00038 #include <ctype.h>
00039 
00040 
00041 
00042 void *GWEN_Path_Handle(const char *path,
00043                        void *data,
00044                        uint32_t flags,
00045                        GWEN_PATHHANDLERPTR elementFunction) {
00046   GWEN_BUFFER *buf1;
00047   int i;
00048   unsigned int origflags;
00049   int startAtRoot;
00050 
00051   origflags=flags;
00052 
00053   buf1=GWEN_Buffer_new(0, 128, 0, 1);
00054 
00055   /* skip leading blanks */
00056   while (*path && isspace((int)*path))
00057     path++;
00058 
00059   /* skip leading slashes */
00060   startAtRoot=0;
00061   while (*path && (*path=='/' || *path=='\\')) {
00062     if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00063       startAtRoot=1;
00064     path++;
00065   } /* while */
00066 
00067   while (*path) {
00068     GWEN_Buffer_Reset(buf1);
00069 
00070     flags=origflags &
00071       ~GWEN_PATH_FLAGS_INTERNAL &
00072       ~GWEN_PATH_FLAGS_VARIABLE;
00073 
00074     /* copy element into buffer */
00075     i=0;
00076     if (startAtRoot) {
00077       GWEN_Buffer_AppendByte(buf1, '/');
00078       flags|=GWEN_PATH_FLAGS_ROOT;
00079     }
00080     while (*path && !(*path=='/' || *path=='\\'))
00081       GWEN_Buffer_AppendByte(buf1, *(path++));
00082 
00083     /* check for group or entry */
00084     if (*path) {
00085       /* skip slashes */
00086       path++;
00087       while (*path && (*path=='/' || *path=='\\'))
00088         path++;
00089 
00090       /* check if delimiter is followed by #0 */
00091       if (!*path) {
00092         /* it is so do some more tests */
00093         if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00094           /* a trailing slash indicates that the current entry is
00095            * supposed to be a group. If the flags indicate that an entry
00096            * is to be found then this would be an error, because the path
00097            * ends in a group instead of an entry */
00098           DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00099           return 0;
00100         }
00101         /* other wise simply mark this element as the last one */
00102         flags|=GWEN_PATH_FLAGS_LAST;
00103       }
00104     } /* if *path */
00105     else {
00106       /* path ends here with #0 */
00107       flags|=GWEN_PATH_FLAGS_LAST;
00108       if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00109         /* path ends with #0, caller wants a variable so this
00110          * last element is one */
00111         flags|=GWEN_PATH_FLAGS_VARIABLE;
00112       }
00113     }
00114 
00115     /* escape or unescape if wanted */
00116     if (!(flags & GWEN_PATH_FLAGS_LAST) ||
00117         ((flags & GWEN_PATH_FLAGS_LAST) &&
00118          (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
00119       if (flags & GWEN_PATH_FLAGS_ESCAPE) {
00120         GWEN_BUFFER *buf2;
00121         const char *p;
00122         int rv;
00123 
00124         buf2=GWEN_Buffer_new(0, 64, 0, 1);
00125         GWEN_Buffer_SetStep(buf2, 128);
00126         p=GWEN_Buffer_GetStart(buf1);
00127         if (startAtRoot) {
00128           p++;
00129           GWEN_Buffer_AppendByte(buf2, '/');
00130         }
00131         if (flags & GWEN_PATH_FLAGS_TOLERANT_ESCAPE)
00132           rv=GWEN_Text_EscapeToBufferTolerant(p, buf2);
00133         else
00134           rv=GWEN_Text_EscapeToBuffer(p, buf2);
00135         if (rv) {
00136           DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
00137           GWEN_Buffer_free(buf2);
00138           GWEN_Buffer_free(buf1);
00139           return 0;
00140         }
00141         GWEN_Buffer_free(buf1);
00142         buf1=buf2;
00143       }
00144       else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
00145         GWEN_BUFFER *buf2;
00146         const char *p;
00147         int rv;
00148 
00149         buf2=GWEN_Buffer_new(0, 64, 0, 1);
00150         GWEN_Buffer_SetStep(buf2, 128);
00151         p=GWEN_Buffer_GetStart(buf1);
00152         if (startAtRoot) {
00153           p++;
00154           GWEN_Buffer_AppendByte(buf2, '/');
00155         }
00156         if (flags & GWEN_PATH_FLAGS_TOLERANT_ESCAPE)
00157           rv=GWEN_Text_UnescapeToBufferTolerant(p, buf2);
00158         else
00159           rv=GWEN_Text_UnescapeToBuffer(p, buf2);
00160         if (rv) {
00161           DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
00162           GWEN_Buffer_free(buf2);
00163           GWEN_Buffer_free(buf1);
00164           return 0;
00165         }
00166         GWEN_Buffer_free(buf1);
00167         buf1=buf2;
00168       }
00169     }
00170 
00171     /* call function */
00172     if (elementFunction) {
00173       data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, flags);
00174       if (!data) {
00175         DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
00176                   GWEN_Buffer_GetStart(buf1));
00177         GWEN_Buffer_free(buf1);
00178         return 0;
00179       }
00180     }
00181     DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
00182               GWEN_Buffer_GetStart(buf1));
00183     if (startAtRoot)
00184       startAtRoot=0;
00185   } /* while (*path) */
00186 
00187   GWEN_Buffer_free(buf1);
00188   return data;
00189 }
00190 
00191 
00192 
00193 void *GWEN_Path_HandleWithIdx(const char *path,
00194                               void *data,
00195                               uint32_t flags,
00196                               GWEN_PATHIDXHANDLERPTR elementFunction) {
00197   GWEN_BUFFER *buf1;
00198   int i;
00199   unsigned int origflags;
00200   int startAtRoot;
00201 
00202   origflags=flags;
00203 
00204   buf1=GWEN_Buffer_new(0, 128, 0, 1);
00205 
00206   /* skip leading blanks */
00207   while (*path && isspace((int)*path))
00208     path++;
00209 
00210   /* skip leading slashes */
00211   startAtRoot=0;
00212   while (*path && (*path=='/' || *path=='\\')) {
00213     if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00214       startAtRoot=1;
00215     path++;
00216   } /* while */
00217 
00218   while (*path) {
00219     char *p;
00220     int idx;
00221 
00222     idx=0;
00223     GWEN_Buffer_Reset(buf1);
00224 
00225     flags=origflags &
00226       ~GWEN_PATH_FLAGS_INTERNAL &
00227       ~GWEN_PATH_FLAGS_VARIABLE;
00228 
00229     /* copy element into buffer */
00230     i=0;
00231     if (startAtRoot) {
00232       GWEN_Buffer_AppendByte(buf1, '/');
00233       flags|=GWEN_PATH_FLAGS_ROOT;
00234     }
00235     while (*path && !(*path=='/' || *path=='\\'))
00236       GWEN_Buffer_AppendByte(buf1, *(path++));
00237 
00238     /* now buffer contains the element, check for index */
00239     if (!(flags & GWEN_PATH_FLAGS_NO_IDX)) {
00240       p=strchr(GWEN_Buffer_GetStart(buf1), '[');
00241       if (p) {
00242         char *p2;
00243         int x;
00244 
00245         *p=0;
00246         p++;
00247         p2=strchr(p, ']');
00248         if (!p2) {
00249           DBG_ERROR(GWEN_LOGDOMAIN, "Closing bracket missing");
00250           GWEN_Buffer_free(buf1);
00251           return 0;
00252         }
00253         *p2=0;
00254         if (sscanf(p, "%d", &x)!=1) {
00255           DBG_ERROR(GWEN_LOGDOMAIN, "Bad or missing index in element (%s)",
00256                     p);
00257           GWEN_Buffer_free(buf1);
00258           return 0;
00259         }
00260         idx=x;
00261       }
00262     }
00263 
00264     /* check for group or entry */
00265     if (*path) {
00266       /* skip slashes */
00267       path++;
00268       while (*path && (*path=='/' || *path=='\\'))
00269         path++;
00270 
00271       /* check if delimiter is followed by #0 */
00272       if (!*path) {
00273         /* it is so do some more tests */
00274         if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00275           /* a trailing slash indicates that the current entry is
00276            * supposed to be a group. If the flags indicate that an entry
00277            * is to be found then this would be an error, because the path
00278            * ends in a group instead of an entry */
00279           DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00280           return 0;
00281         }
00282         /* other wise simply mark this element as the last one */
00283         flags|=GWEN_PATH_FLAGS_LAST;
00284       }
00285     } /* if *path */
00286     else {
00287       /* path ends here with #0 */
00288       flags|=GWEN_PATH_FLAGS_LAST;
00289       if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00290         /* path ends with #0, caller wants a variable so this
00291          * last element is one */
00292         flags|=GWEN_PATH_FLAGS_VARIABLE;
00293       }
00294     }
00295 
00296     /* escape or unescape if wanted */
00297     if (!(flags & GWEN_PATH_FLAGS_LAST) ||
00298         ((flags & GWEN_PATH_FLAGS_LAST) &&
00299          (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
00300       if (flags & GWEN_PATH_FLAGS_ESCAPE) {
00301         GWEN_BUFFER *buf2;
00302         const char *p;
00303         int rv;
00304 
00305         buf2=GWEN_Buffer_new(0, 64, 0, 1);
00306         GWEN_Buffer_SetStep(buf2, 128);
00307         p=GWEN_Buffer_GetStart(buf1);
00308         if (startAtRoot) {
00309           p++;
00310           GWEN_Buffer_AppendByte(buf2, '/');
00311         }
00312         if (flags & GWEN_PATH_FLAGS_TOLERANT_ESCAPE)
00313           rv=GWEN_Text_EscapeToBufferTolerant(p, buf2);
00314         else
00315           rv=GWEN_Text_EscapeToBuffer(p, buf2);
00316         if (rv) {
00317           DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
00318           GWEN_Buffer_free(buf2);
00319           GWEN_Buffer_free(buf1);
00320           return 0;
00321         }
00322         GWEN_Buffer_free(buf1);
00323         buf1=buf2;
00324       }
00325       else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
00326         GWEN_BUFFER *buf2;
00327         const char *p;
00328         int rv;
00329 
00330         buf2=GWEN_Buffer_new(0, 64, 0, 1);
00331         GWEN_Buffer_SetStep(buf2, 128);
00332         p=GWEN_Buffer_GetStart(buf1);
00333         if (startAtRoot) {
00334           p++;
00335           GWEN_Buffer_AppendByte(buf2, '/');
00336         }
00337         if (flags & GWEN_PATH_FLAGS_TOLERANT_ESCAPE)
00338           rv=GWEN_Text_UnescapeToBufferTolerant(p, buf2);
00339         else
00340           rv=GWEN_Text_UnescapeToBuffer(p, buf2);
00341         if (rv) {
00342           DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
00343           GWEN_Buffer_free(buf2);
00344           GWEN_Buffer_free(buf1);
00345           return 0;
00346         }
00347         GWEN_Buffer_free(buf1);
00348         buf1=buf2;
00349       }
00350     }
00351 
00352     /* call function */
00353     if (elementFunction) {
00354       data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, idx, flags);
00355       if (!data) {
00356         DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
00357                   GWEN_Buffer_GetStart(buf1));
00358         GWEN_Buffer_free(buf1);
00359         return 0;
00360       }
00361     }
00362     DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
00363               GWEN_Buffer_GetStart(buf1));
00364     if (startAtRoot)
00365       startAtRoot=0;
00366   } /* while (*path) */
00367 
00368   GWEN_Buffer_free(buf1);
00369   return data;
00370 }
00371 
00372 
00373 
00374 
00375 void *GWEN_Path_AppendPathElement(const char *entry,
00376                                   void *data,
00377                                   unsigned int flags){
00378   GWEN_BUFFER *ebuf;
00379 
00380   ebuf=(GWEN_BUFFER*)data;
00381 
00382   GWEN_Buffer_AppendString(ebuf, entry);
00383   if (!(flags & GWEN_PATH_FLAGS_LAST) ||
00384       !(flags & GWEN_PATH_FLAGS_VARIABLE))
00385     GWEN_Buffer_AppendByte(ebuf, '/');
00386   GWEN_Buffer_AllocRoom(ebuf, 1);
00387   GWEN_Buffer_GetPosPointer(ebuf)[0]=0;
00388   return data;
00389 }
00390 
00391 
00392 
00393 int GWEN_Path_Convert(const char *path,
00394                       GWEN_BUFFER *buffer,
00395                       uint32_t flags) {
00396   void *p;
00397 
00398   p=GWEN_Path_Handle(path,
00399                      buffer,
00400                      flags,
00401                      GWEN_Path_AppendPathElement);
00402   if (!p) {
00403     return -1;
00404   }
00405   return 0;
00406 }
00407 
00408 
00409 
00410 
00411 
00412 
00413 

Generated by  doxygen 1.6.2