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