gwenhywfar  4.99.8beta
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  GWEN_BUFFER *buf1;
44  unsigned int origflags;
45  int startAtRoot;
46 
47  origflags=flags;
48 
49  buf1=GWEN_Buffer_new(0, 128, 0, 1);
50 
51  /* skip leading blanks */
52  while (*path && isspace((int)*path))
53  path++;
54 
55  /* skip leading slashes */
56  startAtRoot=0;
57  while (*path && (*path=='/' || *path=='\\')) {
58  if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
59  startAtRoot=1;
60  path++;
61  } /* while */
62 
63  while (*path) {
64  GWEN_Buffer_Reset(buf1);
65 
66  flags=origflags &
69 
70  /* copy element into buffer */
71  if (startAtRoot) {
72  GWEN_Buffer_AppendByte(buf1, '/');
73  flags|=GWEN_PATH_FLAGS_ROOT;
74  }
75  while (*path && !(*path=='/' || *path=='\\'))
76  GWEN_Buffer_AppendByte(buf1, *(path++));
77 
78  /* check for group or entry */
79  if (*path) {
80  /* skip slashes */
81  path++;
82  while (*path && (*path=='/' || *path=='\\'))
83  path++;
84 
85  /* check if delimiter is followed by #0 */
86  if (!*path) {
87  /* it is so do some more tests */
88  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
89  /* a trailing slash indicates that the current entry is
90  * supposed to be a group. If the flags indicate that an entry
91  * is to be found then this would be an error, because the path
92  * ends in a group instead of an entry */
93  DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
94  return 0;
95  }
96  /* other wise simply mark this element as the last one */
97  flags|=GWEN_PATH_FLAGS_LAST;
98  }
99  } /* if *path */
100  else {
101  /* path ends here with #0 */
102  flags|=GWEN_PATH_FLAGS_LAST;
103  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
104  /* path ends with #0, caller wants a variable so this
105  * last element is one */
107  }
108  }
109 
110  /* escape or unescape if wanted */
111  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
112  ((flags & GWEN_PATH_FLAGS_LAST) &&
113  (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
114  if (flags & GWEN_PATH_FLAGS_ESCAPE) {
115  GWEN_BUFFER *buf2;
116  const char *p;
117  int rv;
118 
119  buf2=GWEN_Buffer_new(0, 64, 0, 1);
120  GWEN_Buffer_SetStep(buf2, 128);
121  p=GWEN_Buffer_GetStart(buf1);
122  if (startAtRoot) {
123  p++;
124  GWEN_Buffer_AppendByte(buf2, '/');
125  }
128  else
129  rv=GWEN_Text_EscapeToBuffer(p, buf2);
130  if (rv) {
131  DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
132  GWEN_Buffer_free(buf2);
133  GWEN_Buffer_free(buf1);
134  return 0;
135  }
136  GWEN_Buffer_free(buf1);
137  buf1=buf2;
138  }
139  else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
140  GWEN_BUFFER *buf2;
141  const char *p;
142  int rv;
143 
144  buf2=GWEN_Buffer_new(0, 64, 0, 1);
145  GWEN_Buffer_SetStep(buf2, 128);
146  p=GWEN_Buffer_GetStart(buf1);
147  if (startAtRoot) {
148  p++;
149  GWEN_Buffer_AppendByte(buf2, '/');
150  }
153  else
154  rv=GWEN_Text_UnescapeToBuffer(p, buf2);
155  if (rv) {
156  DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
157  GWEN_Buffer_free(buf2);
158  GWEN_Buffer_free(buf1);
159  return 0;
160  }
161  GWEN_Buffer_free(buf1);
162  buf1=buf2;
163  }
164  }
165 
166  /* call function */
167  if (elementFunction) {
168  data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, flags);
169  if (!data) {
170  DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
171  GWEN_Buffer_GetStart(buf1));
172  GWEN_Buffer_free(buf1);
173  return 0;
174  }
175  }
176  DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
177  GWEN_Buffer_GetStart(buf1));
178  if (startAtRoot)
179  startAtRoot=0;
180  } /* while (*path) */
181 
182  GWEN_Buffer_free(buf1);
183  return data;
184 }
185 
186 
187 
188 void *GWEN_Path_HandleWithIdx(const char *path,
189  void *data,
190  uint32_t flags,
191  GWEN_PATHIDXHANDLERPTR elementFunction) {
192  GWEN_BUFFER *buf1;
193  unsigned int origflags;
194  int startAtRoot;
195 
196  origflags=flags;
197 
198  buf1=GWEN_Buffer_new(0, 128, 0, 1);
199 
200  /* skip leading blanks */
201  while (*path && isspace((int)*path))
202  path++;
203 
204  /* skip leading slashes */
205  startAtRoot=0;
206  while (*path && (*path=='/' || *path=='\\')) {
207  if (origflags & GWEN_PATH_FLAGS_CHECKROOT)
208  startAtRoot=1;
209  path++;
210  } /* while */
211 
212  while (*path) {
213  char *p;
214  int idx;
215 
216  idx=0;
217  GWEN_Buffer_Reset(buf1);
218 
219  flags=origflags &
222 
223  /* copy element into buffer */
224  if (startAtRoot) {
225  GWEN_Buffer_AppendByte(buf1, '/');
226  flags|=GWEN_PATH_FLAGS_ROOT;
227  }
228  while (*path && !(*path=='/' || *path=='\\'))
229  GWEN_Buffer_AppendByte(buf1, *(path++));
230 
231  /* now buffer contains the element, check for index */
232  if (!(flags & GWEN_PATH_FLAGS_NO_IDX)) {
233  p=strchr(GWEN_Buffer_GetStart(buf1), '[');
234  if (p) {
235  char *p2;
236  int x;
237 
238  *p=0;
239  p++;
240  p2=strchr(p, ']');
241  if (!p2) {
242  DBG_ERROR(GWEN_LOGDOMAIN, "Closing bracket missing");
243  GWEN_Buffer_free(buf1);
244  return 0;
245  }
246  *p2=0;
247  if (sscanf(p, "%d", &x)!=1) {
248  DBG_ERROR(GWEN_LOGDOMAIN, "Bad or missing index in element (%s)",
249  p);
250  GWEN_Buffer_free(buf1);
251  return 0;
252  }
253  idx=x;
254  }
255  }
256 
257  /* check for group or entry */
258  if (*path) {
259  /* skip slashes */
260  path++;
261  while (*path && (*path=='/' || *path=='\\'))
262  path++;
263 
264  /* check if delimiter is followed by #0 */
265  if (!*path) {
266  /* it is so do some more tests */
267  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
268  /* a trailing slash indicates that the current entry is
269  * supposed to be a group. If the flags indicate that an entry
270  * is to be found then this would be an error, because the path
271  * ends in a group instead of an entry */
272  DBG_DEBUG(GWEN_LOGDOMAIN, "Path ends with a group while an entry is wanted");
273  return 0;
274  }
275  /* other wise simply mark this element as the last one */
276  flags|=GWEN_PATH_FLAGS_LAST;
277  }
278  } /* if *path */
279  else {
280  /* path ends here with #0 */
281  flags|=GWEN_PATH_FLAGS_LAST;
282  if (origflags & GWEN_PATH_FLAGS_VARIABLE) {
283  /* path ends with #0, caller wants a variable so this
284  * last element is one */
286  }
287  }
288 
289  /* escape or unescape if wanted */
290  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
291  ((flags & GWEN_PATH_FLAGS_LAST) &&
292  (flags & GWEN_PATH_FLAGS_CONVERT_LAST))) {
293  if (flags & GWEN_PATH_FLAGS_ESCAPE) {
294  GWEN_BUFFER *buf2;
295  const char *p;
296  int rv;
297 
298  buf2=GWEN_Buffer_new(0, 64, 0, 1);
299  GWEN_Buffer_SetStep(buf2, 128);
300  p=GWEN_Buffer_GetStart(buf1);
301  if (startAtRoot) {
302  p++;
303  GWEN_Buffer_AppendByte(buf2, '/');
304  }
307  else
308  rv=GWEN_Text_EscapeToBuffer(p, buf2);
309  if (rv) {
310  DBG_ERROR(GWEN_LOGDOMAIN, "Could not escape path element");
311  GWEN_Buffer_free(buf2);
312  GWEN_Buffer_free(buf1);
313  return 0;
314  }
315  GWEN_Buffer_free(buf1);
316  buf1=buf2;
317  }
318  else if (flags & GWEN_PATH_FLAGS_UNESCAPE) {
319  GWEN_BUFFER *buf2;
320  const char *p;
321  int rv;
322 
323  buf2=GWEN_Buffer_new(0, 64, 0, 1);
324  GWEN_Buffer_SetStep(buf2, 128);
325  p=GWEN_Buffer_GetStart(buf1);
326  if (startAtRoot) {
327  p++;
328  GWEN_Buffer_AppendByte(buf2, '/');
329  }
332  else
333  rv=GWEN_Text_UnescapeToBuffer(p, buf2);
334  if (rv) {
335  DBG_ERROR(GWEN_LOGDOMAIN, "Could not unescape path element");
336  GWEN_Buffer_free(buf2);
337  GWEN_Buffer_free(buf1);
338  return 0;
339  }
340  GWEN_Buffer_free(buf1);
341  buf1=buf2;
342  }
343  }
344 
345  /* call function */
346  if (elementFunction) {
347  data=(elementFunction)(GWEN_Buffer_GetStart(buf1), data, idx, flags);
348  if (!data) {
349  DBG_DEBUG(GWEN_LOGDOMAIN, "Error on path element \"%s\"",
350  GWEN_Buffer_GetStart(buf1));
351  GWEN_Buffer_free(buf1);
352  return 0;
353  }
354  }
355  DBG_DEBUG(GWEN_LOGDOMAIN, "Successfully handled element \"%s\"",
356  GWEN_Buffer_GetStart(buf1));
357  if (startAtRoot)
358  startAtRoot=0;
359  } /* while (*path) */
360 
361  GWEN_Buffer_free(buf1);
362  return data;
363 }
364 
365 
366 
367 
368 void *GWEN_Path_AppendPathElement(const char *entry,
369  void *data,
370  unsigned int flags) {
371  GWEN_BUFFER *ebuf;
372 
373  ebuf=(GWEN_BUFFER*)data;
374 
375  GWEN_Buffer_AppendString(ebuf, entry);
376  if (!(flags & GWEN_PATH_FLAGS_LAST) ||
377  !(flags & GWEN_PATH_FLAGS_VARIABLE))
378  GWEN_Buffer_AppendByte(ebuf, '/');
379  GWEN_Buffer_AllocRoom(ebuf, 1);
380  GWEN_Buffer_GetPosPointer(ebuf)[0]=0;
381  return data;
382 }
383 
384 
385 
386 int GWEN_Path_Convert(const char *path,
387  GWEN_BUFFER *buffer,
388  uint32_t flags) {
389  void *p;
390 
391  p=GWEN_Path_Handle(path,
392  buffer,
393  flags,
395  if (!p) {
396  return -1;
397  }
398  return 0;
399 }
400 
401 
402 
403 
404 
405 
406 
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:223
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:273
#define GWEN_PATH_FLAGS_CONVERT_LAST
Definition: path.h:133
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition: buffer.c:747
#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:368
int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1419
#define GWEN_PATH_FLAGS_INTERNAL
Definition: path.h:159
int GWEN_Path_Convert(const char *path, GWEN_BUFFER *buffer, uint32_t flags)
Definition: path.c:386
#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:1462
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:588
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:684
#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:192
#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:1326
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:380
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:83
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:1360
#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:188
void *(* GWEN_PATHIDXHANDLERPTR)(const char *entry, void *data, int idx, uint32_t flags)
Definition: path.h:184
void *(* GWEN_PATHHANDLERPTR)(const char *entry, void *data, uint32_t flags)
Definition: path.h:180
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1014