aboutsummaryrefslogtreecommitdiff
path: root/src/util/strings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/strings.c')
-rw-r--r--src/util/strings.c158
1 files changed, 158 insertions, 0 deletions
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 */