YAZ 5.35.1
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
18static 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
29static 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
45void 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
55static 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
86void 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
98void 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
121int 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.
void * odr_malloc(ODR o, size_t size)
Definition odr_mem.c:31
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
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.