YAZ  5.34.0
uri.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdlib.h>
14 #include <yaz/srw.h>
15 #include <yaz/matchstr.h>
16 #include <yaz/yaz-iconv.h>
17 
18 static int hex_digit (int ch)
19 {
20  if (ch >= '0' && ch <= '9')
21  return ch - '0';
22  else if (ch >= 'a' && ch <= 'f')
23  return ch - 'a'+10;
24  else if (ch >= 'A' && ch <= 'F')
25  return ch - 'A'+10;
26  return -1;
27 }
28 
29 static void encode_uri_char(char *dst, char ch)
30 {
31  /* https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */
32  if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
33  (ch >= '0' && ch <= '9') || strchr("-._~", ch))
34  {
35  dst[0] = ch;
36  dst[1] = '\0';
37  }
38  else
39  {
40  dst[0] = '%';
41  sprintf(dst+1, "%02X", (unsigned char ) ch);
42  }
43 }
44 
45 void yaz_encode_uri_component(char *dst, const char *uri)
46 {
47  for (; *uri; uri++)
48  {
49  encode_uri_char(dst, *uri);
50  dst += strlen(dst);
51  }
52  *dst = '\0';
53 }
54 
55 static unsigned char decode_uri_char(const char *path, size_t *len)
56 {
57  unsigned char ch;
58  if (*path == '+')
59  {
60  ch = ' ';
61  *len = 1;
62  }
63  else if (*path == '%' && *len >= 3)
64  {
65  int d1 = hex_digit(path[1]);
66  int d2 = hex_digit(path[2]);
67  if (d1 >= 0 && d2 >= 0)
68  {
69  ch = d1 * 16 + d2;
70  *len = 3;
71  }
72  else
73  {
74  ch = *path;
75  *len = 1;
76  }
77  }
78  else
79  {
80  ch = *path;
81  *len = 1;
82  }
83  return ch;
84 }
85 
86 void yaz_decode_uri_component(char *dst, const char *uri, size_t len)
87 {
88  while (len)
89  {
90  size_t sz = len;
91  *dst++ = decode_uri_char(uri, &sz);
92  uri += sz;
93  len = len - sz;
94  }
95  *dst = '\0';
96 }
97 
98 void yaz_array_to_uri(char **path, ODR o, char **name, char **value)
99 {
100  size_t i, szp = 0, sz = 1;
101  for(i = 0; name[i]; i++)
102  sz += strlen(name[i]) + 3 + strlen(value[i]) * 3;
103  *path = (char *) odr_malloc(o, sz);
104 
105  for(i = 0; name[i]; i++)
106  {
107  size_t ilen;
108  if (i)
109  (*path)[szp++] = '&';
110  ilen = strlen(name[i]);
111  memcpy(*path+szp, name[i], ilen);
112  szp += ilen;
113  (*path)[szp++] = '=';
114 
115  yaz_encode_uri_component(*path + szp, value[i]);
116  szp += strlen(*path + szp);
117  }
118  (*path)[szp] = '\0';
119 }
120 
121 int yaz_uri_to_array(const char *path, ODR o, char ***name, char ***val)
122 {
123  int no = 2;
124  const char *cp;
125  *name = 0;
126  if (*path == '?')
127  path++;
128  if (!*path)
129  return 0;
130  cp = path;
131  while ((cp = strchr(cp, '&')))
132  {
133  cp++;
134  no++;
135  while (*cp && *cp != '=' && *cp != '&')
136  {
137  /* check that x-form names looks sane */
138  if (*cp <= ' ' || *cp >= 127)
139  return 0;
140  cp++;
141  }
142  }
143  *name = (char **) odr_malloc(o, no * sizeof(char*));
144  *val = (char **) odr_malloc(o, no * sizeof(char*));
145 
146  for (no = 0; *path; no++)
147  {
148  while (*path == '&')
149  path++;
150  if (!*path)
151  break;
152 
153  for (cp = path; *cp && *cp != '=' && *cp != '&'; cp++)
154  ;
155 
156  (*name)[no] = odr_strdupn(o, path, cp - path);
157  path = cp;
158  if (*path == '=')
159  {
160  size_t i = 0;
161  char *ret;
162  path++;
163  for (cp = path; *cp && *cp != '&'; cp++)
164  ;
165  (*val)[no] = ret = (char *) odr_malloc(o, cp - path + 1);
166  while (*path && *path != '&')
167  {
168  size_t l = 3;
169  ret[i++] = decode_uri_char(path, &l);
170  path += l;
171  }
172  ret[i] = '\0';
173  }
174  else
175  (*val)[no] = odr_strdup(o, "");
176  }
177  (*name)[no] = 0;
178  (*val)[no] = 0;
179  return no;
180 }
181 
182 
183 /*
184  * Local variables:
185  * c-basic-offset: 4
186  * c-file-style: "Stroustrup"
187  * indent-tabs-mode: nil
188  * End:
189  * vim: shiftwidth=4 tabstop=8 expandtab
190  */
191 
char * name
Definition: initopt.c:18
Header for YAZ iconv interface.
char * odr_strdupn(ODR o, const char *str, size_t n)
Definition: odr_mem.c:46
char * odr_strdup(ODR o, const char *str)
Definition: odr_mem.c:36
void * odr_malloc(ODR o, size_t size)
Definition: odr_mem.c:31
Header for SRW/SRU.
Definition: odr.h:125
void yaz_encode_uri_component(char *dst, const char *uri)
encodes URI component
Definition: uri.c:45
static unsigned char decode_uri_char(const char *path, size_t *len)
Definition: uri.c:55
static int hex_digit(int ch)
Definition: uri.c:18
int yaz_uri_to_array(const char *path, ODR o, char ***name, char ***val)
Definition: uri.c:121
void yaz_decode_uri_component(char *dst, const char *uri, size_t len)
decodes URI component
Definition: uri.c:86
static void encode_uri_char(char *dst, char ch)
Definition: uri.c:29
void yaz_array_to_uri(char **path, ODR o, char **name, char **value)
Definition: uri.c:98
Header for YAZ iconv interface.