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
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
00056 while (*path && isspace((int)*path))
00057 path++;
00058
00059
00060 startAtRoot=0;
00061 while (*path && (*path=='/' || *path=='\\')) {
00062 if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00063 startAtRoot=1;
00064 path++;
00065 }
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
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
00084 if (*path) {
00085
00086 path++;
00087 while (*path && (*path=='/' || *path=='\\'))
00088 path++;
00089
00090
00091 if (!*path) {
00092
00093 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00094
00095
00096
00097
00098 DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00099 return 0;
00100 }
00101
00102 flags|=GWEN_PATH_FLAGS_LAST;
00103 }
00104 }
00105 else {
00106
00107 flags|=GWEN_PATH_FLAGS_LAST;
00108 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00109
00110
00111 flags|=GWEN_PATH_FLAGS_VARIABLE;
00112 }
00113 }
00114
00115
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
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 }
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
00207 while (*path && isspace((int)*path))
00208 path++;
00209
00210
00211 startAtRoot=0;
00212 while (*path && (*path=='/' || *path=='\\')) {
00213 if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
00214 startAtRoot=1;
00215 path++;
00216 }
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
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
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
00265 if (*path) {
00266
00267 path++;
00268 while (*path && (*path=='/' || *path=='\\'))
00269 path++;
00270
00271
00272 if (!*path) {
00273
00274 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00275
00276
00277
00278
00279 DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
00280 return 0;
00281 }
00282
00283 flags|=GWEN_PATH_FLAGS_LAST;
00284 }
00285 }
00286 else {
00287
00288 flags|=GWEN_PATH_FLAGS_LAST;
00289 if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
00290
00291
00292 flags|=GWEN_PATH_FLAGS_VARIABLE;
00293 }
00294 }
00295
00296
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
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 }
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