aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/buffer.c21
-rw-r--r--src/util/strings.c158
-rw-r--r--src/util/test_strings.c14
3 files changed, 183 insertions, 10 deletions
diff --git a/src/util/buffer.c b/src/util/buffer.c
index 2af972413..662e4d0f2 100644
--- a/src/util/buffer.c
+++ b/src/util/buffer.c
@@ -32,7 +32,8 @@
32 * @param capacity the capacity (in bytes) to allocate for @a buf 32 * @param capacity the capacity (in bytes) to allocate for @a buf
33 */ 33 */
34void 34void
35GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity) 35GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf,
36 size_t capacity)
36{ 37{
37 /* Buffer should be zero-initialized */ 38 /* Buffer should be zero-initialized */
38 GNUNET_assert (0 == buf->mem); 39 GNUNET_assert (0 == buf->mem);
@@ -257,25 +258,25 @@ GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf,
257 * 258 *
258 * @param buf buffer to write to 259 * @param buf buffer to write to
259 * @param data data to read from 260 * @param data data to read from
260 * @param len number of bytes to copy from @a data to @a buf 261 * @param data_len number of bytes to copy from @a data to @a buf
261 */ 262 */
262void 263void
263GNUNET_buffer_write_data_encoded (struct GNUNET_Buffer *buf, 264GNUNET_buffer_write_data_encoded (struct GNUNET_Buffer *buf,
264 const char *data, 265 const void *data,
265 size_t len) 266 size_t data_len)
266{ 267{
267 size_t outlen = len * 8; 268 size_t outlen = data_len * 8;
268 char *p = buf->mem + buf->position;
269 269
270 if (outlen % 5 > 0) 270 if (outlen % 5 > 0)
271 outlen += 5 - outlen % 5; 271 outlen += 5 - outlen % 5;
272 outlen /= 5; 272 outlen /= 5;
273 273 GNUNET_buffer_ensure_remaining (buf,
274 GNUNET_buffer_ensure_remaining (buf, outlen); 274 outlen);
275 GNUNET_assert (NULL != 275 GNUNET_assert (NULL !=
276 GNUNET_STRINGS_data_to_string (data, 276 GNUNET_STRINGS_data_to_string (data,
277 len, 277 data_len,
278 p, 278 (buf->mem
279 + buf->position),
279 outlen)); 280 outlen));
280 buf->position += outlen; 281 buf->position += outlen;
281 GNUNET_assert (buf->position <= buf->capacity); 282 GNUNET_assert (buf->position <= buf->capacity);
diff --git a/src/util/strings.c b/src/util/strings.c
index 41180dd71..9d6f4039e 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -29,6 +29,7 @@
29#include <iconv.h> 29#include <iconv.h>
30#endif 30#endif
31#include "gnunet_crypto_lib.h" 31#include "gnunet_crypto_lib.h"
32#include "gnunet_buffer_lib.h"
32#include "gnunet_strings_lib.h" 33#include "gnunet_strings_lib.h"
33#include <unicase.h> 34#include <unicase.h>
34#include <unistr.h> 35#include <unistr.h>
@@ -2088,4 +2089,161 @@ GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2088} 2089}
2089 2090
2090 2091
2092/**
2093 * url/percent encode (RFC3986).
2094 *
2095 * @param data the data to encode
2096 * @param len the length of the input
2097 * @param output where to write the output (*output should be NULL,
2098 * is allocated)
2099 * @return the size of the output
2100 */
2101size_t
2102GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out)
2103{
2104 const char *rpos = data;
2105 *out = GNUNET_malloc (len + 1); /* output should always fit into input */
2106 char *wpos = *out;
2107 size_t resl = 0;
2108
2109 while ('\0' != *rpos)
2110 {
2111 unsigned int num;
2112 switch (*rpos)
2113 {
2114 case '%':
2115 if (1 != sscanf (rpos + 1, "%2x", &num))
2116 break;
2117 *wpos = (char) ((unsigned char) num);
2118 wpos++;
2119 resl++;
2120 rpos += 3;
2121 break;
2122 /* TODO: add bad sequence handling */
2123 /* intentional fall through! */
2124 default:
2125 *wpos = *rpos;
2126 wpos++;
2127 resl++;
2128 rpos++;
2129 }
2130 }
2131 *wpos = '\0'; /* add 0-terminator */
2132 return resl;
2133}
2134
2135
2136/**
2137 * url/percent encode (RFC3986).
2138 *
2139 * @param data the data to decode
2140 * @param len the length of the input
2141 * @param output where to write the output (*output should be NULL,
2142 * is allocated)
2143 * @return the size of the output
2144 */
2145size_t
2146GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out)
2147{
2148 struct GNUNET_Buffer buf = { 0 };
2149 const uint8_t *i8 = (uint8_t *) data;
2150
2151 while (0 != *i8)
2152 {
2153 if (0 == (0x80 & *i8))
2154 {
2155 /* traditional ASCII */
2156 if (isalnum (*i8) || (*i8 == '-') || (*i8 == '_') || (*i8 == '.') ||
2157 (*i8 == '~') )
2158 GNUNET_buffer_write (&buf, (const char*) i8, 1);
2159 else if (*i8 == ' ')
2160 GNUNET_buffer_write (&buf, "+", 1);
2161 else
2162 GNUNET_buffer_write_fstr (&buf,
2163 "%%%X%X",
2164 *i8 >> 4,
2165 *i8 & 15);
2166 i8++;
2167 continue;
2168 }
2169 if (0x80 + 0x40 == ((0x80 + 0x40 + 0x20) & *i8))
2170 {
2171 /* 2-byte value, percent-encode */
2172 GNUNET_buffer_write_fstr (&buf,
2173 "%%%X%X",
2174 *i8 >> 4,
2175 *i8 & 15);
2176 i8++;
2177 GNUNET_buffer_write_fstr (&buf,
2178 "%%%X%X",
2179 *i8 >> 4,
2180 *i8 & 15);
2181 i8++;
2182 continue;
2183 }
2184 if (0x80 + 0x40 + 0x20 == ((0x80 + 0x40 + 0x20 + 0x10) & *i8))
2185 {
2186 /* 3-byte value, percent-encode */
2187 for (unsigned int i = 0; i<3; i++)
2188 {
2189 GNUNET_buffer_write_fstr (&buf,
2190 "%%%X%X",
2191 *i8 >> 4,
2192 *i8 & 15);
2193 i8++;
2194 }
2195 continue;
2196 }
2197 if (0x80 + 0x40 + 0x20 + 0x10 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08) & *i8))
2198 {
2199 /* 4-byte value, percent-encode */
2200 for (unsigned int i = 0; i<4; i++)
2201 {
2202 GNUNET_buffer_write_fstr (&buf,
2203 "%%%X%X",
2204 *i8 >> 4,
2205 *i8 & 15);
2206 i8++;
2207 }
2208 continue;
2209 }
2210 if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08
2211 + 0x04) & *i8))
2212 {
2213 /* 5-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2214 for (unsigned int i = 0; i<5; i++)
2215 {
2216 GNUNET_buffer_write_fstr (&buf,
2217 "%%%X%X",
2218 *i8 >> 4,
2219 *i8 & 15);
2220 i8++;
2221 }
2222 continue;
2223 }
2224 if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 + 0x04 == ((0x80 + 0x40 + 0x20 + 0x10
2225 + 0x08 + 0x04 + 0x02)
2226 & *i8))
2227 {
2228 /* 6-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2229 for (unsigned int i = 0; i<6; i++)
2230 {
2231 GNUNET_buffer_write_fstr (&buf,
2232 "%%%X%X",
2233 *i8 >> 4,
2234 *i8 & 15);
2235 i8++;
2236 }
2237 continue;
2238 }
2239 /* really, really invalid UTF-8: fail */
2240 GNUNET_break (0);
2241 GNUNET_buffer_clear (&buf);
2242 return 0;
2243 }
2244 *out = GNUNET_buffer_reap_str (&buf);
2245 return strlen (*out);
2246}
2247
2248
2091/* end of strings.c */ 2249/* end of strings.c */
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index 90d06a473..753ec6908 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -39,6 +39,10 @@
39#define WANTB(a, b, l) if (0 != memcmp (a, b, l)) { GNUNET_break (0); return 1; \ 39#define WANTB(a, b, l) if (0 != memcmp (a, b, l)) { GNUNET_break (0); return 1; \
40} else { } 40} else { }
41 41
42#define URLENCODE_TEST_VECTOR_PLAIN "Asbjlaw=ljsdlasjd?人aslkdsa"
43
44#define URLENCODE_TEST_VECTOR_ENCODED "Asbjlaw\%3Dljsdlasjd\%3F\%E4\%BA\%BAaslkdsa"
45
42int 46int
43main (int argc, char *argv[]) 47main (int argc, char *argv[])
44{ 48{
@@ -137,6 +141,16 @@ main (int argc, char *argv[])
137 GNUNET_STRINGS_fancy_time_to_relative ("15 m", &rtx)); 141 GNUNET_STRINGS_fancy_time_to_relative ("15 m", &rtx));
138 GNUNET_assert (rt.rel_value_us == rtx.rel_value_us); 142 GNUNET_assert (rt.rel_value_us == rtx.rel_value_us);
139 143
144 GNUNET_assert (0 != GNUNET_STRINGS_urlencode (URLENCODE_TEST_VECTOR_PLAIN,
145 strlen (URLENCODE_TEST_VECTOR_PLAIN),
146 &b));
147 WANT (URLENCODE_TEST_VECTOR_ENCODED, b);
148 GNUNET_free (b);
149 GNUNET_assert (0 != GNUNET_STRINGS_urldecode (URLENCODE_TEST_VECTOR_ENCODED,
150 strlen (URLENCODE_TEST_VECTOR_ENCODED),
151 &b));
152 WANT (URLENCODE_TEST_VECTOR_PLAIN, b);
153 GNUNET_free (b);
140 return 0; 154 return 0;
141} 155}
142 156