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