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