00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00053 while (*path && isspace((int)*path))
00054 path++;
00055
00056
00057 startAtRoot=0;
00058 while (*path && (*path=='/' || *path=='\\')) {
00059 if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00060 startAtRoot=1;
00061 path++;
00062 }
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
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
00081 if (*path) {
00082
00083 path++;
00084 while (*path && (*path=='/' || *path=='\\'))
00085 path++;
00086
00087
00088 if (!*path) {
00089
00090 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00091
00092
00093
00094
00095 DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00096 return 0;
00097 }
00098
00099 flags|=GWEN_PATH_FLAGS_LAST;
00100 }
00101 }
00102 else {
00103
00104 flags|=GWEN_PATH_FLAGS_LAST;
00105 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00106
00107
00108 flags|=GWEN_PATH_FLAGS_VARIABLE;
00109 }
00110 }
00111
00112
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
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 }
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
00204 while (*path && isspace((int)*path))
00205 path++;
00206
00207
00208 startAtRoot=0;
00209 while (*path && (*path=='/' || *path=='\\')) {
00210 if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00211 startAtRoot=1;
00212 path++;
00213 }
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
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
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
00262 if (*path) {
00263
00264 path++;
00265 while (*path && (*path=='/' || *path=='\\'))
00266 path++;
00267
00268
00269 if (!*path) {
00270
00271 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00272
00273
00274
00275
00276 DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00277 return 0;
00278 }
00279
00280 flags|=GWEN_PATH_FLAGS_LAST;
00281 }
00282 }
00283 else {
00284
00285 flags|=GWEN_PATH_FLAGS_LAST;
00286 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00287
00288
00289 flags|=GWEN_PATH_FLAGS_VARIABLE;
00290 }
00291 }
00292
00293
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
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 }
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