gwenhywfar  4.99.15beta
path.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Tue Sep 09 2003
3  copyright : (C) 2003 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 #include "path.h"
32 #include "gwenhywfar/debug.h"
33 #include "gwenhywfar/misc.h"
34 #include "gwenhywfar/text.h"
35 #include <ctype.h>
36 
37 
38 
39 void *GWEN_Path_Handle(const char *path,
40  void *data,
41  uint32_t flags,
42  GWEN_PATHHANDLERPTR elementFunction)
43 {
44  GWEN_BUFFER *buf1;
45  unsigned int origflags;
46  int startAtRoot;
47 
48  origflags=flags;
49 
50  buf1=GWEN_Buffer_new(0, 128, 0, 1);
51 
52  /* skip leading blanks */
53  while (*path && isspace((int)*path))
54  path++;
55 
56  /* skip leading slashes */
57  startAtRoot=0;
58  while (*path && (*path=='/' || *path=='\\')) {
59  if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
60  startAtRoot=1;
61  path++;
62  } /* while */
63 
64  while (*path) {
65  GWEN_Buffer_Reset(buf1);
66 
67  flags=origflags &
70 
71  /* copy element into buffer */
72  if (startAtRoot) {
73  GWEN_Buffer_AppendByte(buf1, '/');
74  flags|=GWEN_PATH_FLAGS_ROOT;
75  }
76  while (*path && !(*path=='/' || *path=='\\'))
77  GWEN_Buffer_AppendByte(buf1, *(path++));
78 
79  /* check for group or entry */
80  if (*path) {
81  /* skip slashes */
82  path++;
83  while (*path && (*path=='/' || *path=='\\'))
84  path++;
85 
86  /* check if delimiter is followed by #0 */
87  if (!*path) {
88  /* it is so do some more tests */
89  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
90  /* a trailing slash indicates that the current entry is
91  * supposed to be a group. If the flags indicate that an entry
92  * is to be found then this would be an error, because the path
93  * ends in a group instead of an entry */
94  DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
95  return 0;
96  }
97  /* other wise simply mark this element as the last one */
98  flags|=GWEN_PATH_FLAGS_LAST;
99  }
100  } /* if *path */
101  else {
102  /* path ends here with #0 */
103  flags|=GWEN_PATH_FLAGS_LAST;
104  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
105  /* path ends with #0, caller wants a variable so this
106  * last element is one */
108  }
109  }
110 
111  /* escape or unescape if wanted */
112  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
113  ((flags & GWEN_PATH_FLAGS_LAST) &&
114  (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
115  if (flags & GWEN_PATH_FLAGS_ESCAPE) {
116  GWEN_BUFFER *buf2;
117  const char *p;
118  int rv;
119 
120  buf2=GWEN_Buffer_new(0, 64, 0, 1);
121  GWEN_Buffer_SetStep(buf2, 128);
122  p=GWEN_Buffer_GetStart(buf1);
123  if (startAtRoot) {
124  p++;
125  GWEN_Buffer_AppendByte(buf2, '/');
126  }
129  else
130  rv=GWEN_Text_EscapeToBuffer(p, buf2);
131  if (rv) {
132  DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
133  GWEN_Buffer_free(buf2);
134  GWEN_Buffer_free(buf1);
135  return 0;
136  }
137  GWEN_Buffer_free(buf1);
138  buf1=buf2;
139  }
140  else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
141  GWEN_BUFFER *buf2;
142  const char *p;
143  int rv;
144 
145  buf2=GWEN_Buffer_new(0, 64, 0, 1);
146  GWEN_Buffer_SetStep(buf2, 128);
147  p=GWEN_Buffer_GetStart(buf1);
148  if (startAtRoot) {
149  p++;
150  GWEN_Buffer_AppendByte(buf2, '/');
151  }
154  else
155  rv=GWEN_Text_UnescapeToBuffer(p, buf2);
156  if (rv) {
157  DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
158  GWEN_Buffer_free(buf2);
159  GWEN_Buffer_free(buf1);
160  return 0;
161  }
162  GWEN_Buffer_free(buf1);
163  buf1=buf2;
164  }
165  }
166 
167  /* call function */
168  if (elementFunction) {
169  data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, flags);
170  if (!data) {
171  DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
172  GWEN_Buffer_GetStart(buf1));
173  GWEN_Buffer_free(buf1);
174  return 0;
175  }
176  }
177  DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
178  GWEN_Buffer_GetStart(buf1));
179  if (startAtRoot)
180  startAtRoot=0;
181  } /* while (*path) */
182 
183  GWEN_Buffer_free(buf1);
184  return data;
185 }
186 
187 
188 
189 void *GWEN_Path_HandleWithIdx(const char *path,
190  void *data,
191  uint32_t flags,
192  GWEN_PATHIDXHANDLERPTR elementFunction)
193 {
194  GWEN_BUFFER *buf1;
195  unsigned int origflags;
196  int startAtRoot;
197 
198  origflags=flags;
199 
200  buf1=GWEN_Buffer_new(0, 128, 0, 1);
201 
202  /* skip leading blanks */
203  while (*path && isspace((int)*path))
204  path++;
205 
206  /* skip leading slashes */
207  startAtRoot=0;
208  while (*path && (*path=='/' || *path=='\\')) {
209  if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
210  startAtRoot=1;
211  path++;
212  } /* while */
213 
214  while (*path) {
215  char *p;
216  int idx;
217 
218  idx=0;
219  GWEN_Buffer_Reset(buf1);
220 
221  flags=origflags &
224 
225  /* copy element into buffer */
226  if (startAtRoot) {
227  GWEN_Buffer_AppendByte(buf1, '/');
228  flags|=GWEN_PATH_FLAGS_ROOT;
229  }
230  while (*path && !(*path=='/' || *path=='\\'))
231  GWEN_Buffer_AppendByte(buf1, *(path++));
232 
233  /* now buffer contains the element, check for index */
234  if (!(flags & GWEN_PATH_FLAGS_NO_IDX)) {
235  p=strchr(GWEN_Buffer_GetStart(buf1), '[');
236  if (p) {
237  char *p2;
238  int x;
239 
240  *p=0;
241  p++;
242  p2=strchr(p, ']');
243  if (!p2) {
244  DBG_ERROR(GWEN_LOGDOMAIN, "Closing bracket missing");
245  GWEN_Buffer_free(buf1);
246  return 0;
247  }
248  *p2=0;
249  if (sscanf(p, "%d", &x)!=1) {
250  DBG_ERROR(GWEN_LOGDOMAIN, "Bad or missing index in element (%s)",
251  p);
252  GWEN_Buffer_free(buf1);
253  return 0;
254  }
255  idx=x;
256  }
257  }
258 
259  /* check for group or entry */
260  if (*path) {
261  /* skip slashes */
262  path++;
263  while (*path && (*path=='/' || *path=='\\'))
264  path++;
265 
266  /* check if delimiter is followed by #0 */
267  if (!*path) {
268  /* it is so do some more tests */
269  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
270  /* a trailing slash indicates that the current entry is
271  * supposed to be a group. If the flags indicate that an entry
272  * is to be found then this would be an error, because the path
273  * ends in a group instead of an entry */
274  DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
275  return 0;
276  }
277  /* other wise simply mark this element as the last one */
278  flags|=GWEN_PATH_FLAGS_LAST;
279  }
280  } /* if *path */
281  else {
282  /* path ends here with #0 */
283  flags|=GWEN_PATH_FLAGS_LAST;
284  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
285  /* path ends with #0, caller wants a variable so this
286  * last element is one */
288  }
289  }
290 
291  /* escape or unescape if wanted */
292  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
293  ((flags & GWEN_PATH_FLAGS_LAST) &&
294  (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
295  if (flags & GWEN_PATH_FLAGS_ESCAPE) {
296  GWEN_BUFFER *buf2;
297  const char *p;
298  int rv;
299 
300  buf2=GWEN_Buffer_new(0, 64, 0, 1);
301  GWEN_Buffer_SetStep(buf2, 128);
302  p=GWEN_Buffer_GetStart(buf1);
303  if (startAtRoot) {
304  p++;
305  GWEN_Buffer_AppendByte(buf2, '/');
306  }
309  else
310  rv=GWEN_Text_EscapeToBuffer(p, buf2);
311  if (rv) {
312  DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
313  GWEN_Buffer_free(buf2);
314  GWEN_Buffer_free(buf1);
315  return 0;
316  }
317  GWEN_Buffer_free(buf1);
318  buf1=buf2;
319  }
320  else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
321  GWEN_BUFFER *buf2;
322  const char *p;
323  int rv;
324 
325  buf2=GWEN_Buffer_new(0, 64, 0, 1);
326  GWEN_Buffer_SetStep(buf2, 128);
327  p=GWEN_Buffer_GetStart(buf1);
328  if (startAtRoot) {
329  p++;
330  GWEN_Buffer_AppendByte(buf2, '/');
331  }
334  else
335  rv=GWEN_Text_UnescapeToBuffer(p, buf2);
336  if (rv) {
337  DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
338  GWEN_Buffer_free(buf2);
339  GWEN_Buffer_free(buf1);
340  return 0;
341  }
342  GWEN_Buffer_free(buf1);
343  buf1=buf2;
344  }
345  }
346 
347  /* call function */
348  if (elementFunction) {
349  data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, idx, flags);
350  if (!data) {
351  DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
352  GWEN_Buffer_GetStart(buf1));
353  GWEN_Buffer_free(buf1);
354  return 0;
355  }
356  }
357  DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
358  GWEN_Buffer_GetStart(buf1));
359  if (startAtRoot)
360  startAtRoot=0;
361  } /* while (*path) */
362 
363  GWEN_Buffer_free(buf1);
364  return data;
365 }
366 
367 
368 
369 
370 void *GWEN_Path_AppendPathElement(const char *entry,
371  void *data,
372  unsigned int flags)
373 {
374  GWEN_BUFFER *ebuf;
375 
376  ebuf=(GWEN_BUFFER *)data;
377 
378  GWEN_Buffer_AppendString(ebuf, entry);
379  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
380  !(flags & GWEN_PATH_FLAGS_VARIABLE))
381  GWEN_Buffer_AppendByte(ebuf, '/');
382  GWEN_Buffer_AllocRoom(ebuf, 1);
383  GWEN_Buffer_GetPosPointer(ebuf)[0]=0;
384  return data;
385 }
386 
387 
388 
389 int GWEN_Path_Convert(const char *path,
390  GWEN_BUFFER *buffer,
391  uint32_t flags)
392 {
393  void *p;
394 
395  p=GWEN_Path_Handle(path,
396  buffer,
397  flags,
399  if (!p) {
400  return -1;
401  }
402  return 0;
403 }
404 
405 
406 
407 
408 
409 
410 
void * GWEN_Path_Handle(const char *path, void *data, uint32_t flags, GWEN_PATHHANDLERPTR elementFunction)
Definition: path.c:39
#define GWEN_PATH_FLAGS_ESCAPE
Definition: path.h:121
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:290
#define GWEN_PATH_FLAGS_CONVERT_LAST
Definition: path.h:133
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition: buffer.c:786
#define GWEN_PATH_FLAGS_TOLERANT_ESCAPE
Definition: path.h:127
void * GWEN_Path_AppendPathElement(const char *entry, void *data, unsigned int flags)
Definition: path.c:370
int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1444
#define GWEN_PATH_FLAGS_INTERNAL
Definition: path.h:159
void *(* GWEN_PATHIDXHANDLERPTR)(const char *entry, void *data, int idx, uint32_t flags)
Definition: path.h:184
int GWEN_Path_Convert(const char *path, GWEN_BUFFER *buffer, uint32_t flags)
Definition: path.c:389
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
int GWEN_Text_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1488
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:618
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:719
#define GWEN_PATH_FLAGS_LAST
Definition: path.h:166
#define GWEN_PATH_FLAGS_ROOT
Definition: path.h:174
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:208
#define GWEN_PATH_FLAGS_UNESCAPE
Definition: path.h:124
#define GWEN_PATH_FLAGS_VARIABLE
Definition: path.h:111
int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1349
void *(* GWEN_PATHHANDLERPTR)(const char *entry, void *data, uint32_t flags)
Definition: path.h:180
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:399
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:85
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
int GWEN_Text_UnescapeToBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1384
#define GWEN_PATH_FLAGS_CHECKROOT
Definition: path.h:142
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define GWEN_PATH_FLAGS_NO_IDX
Definition: path.h:148
void * GWEN_Path_HandleWithIdx(const char *path, void *data, uint32_t flags, GWEN_PATHIDXHANDLERPTR elementFunction)
Definition: path.c:189
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1062