summaryrefslogtreecommitdiffstats
path: root/lib/libshout-idjc/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libshout-idjc/src/util.c')
-rw-r--r--lib/libshout-idjc/src/util.c544
1 files changed, 295 insertions, 249 deletions
diff --git a/lib/libshout-idjc/src/util.c b/lib/libshout-idjc/src/util.c
index fdc217845b..5ab06d547e 100644
--- a/lib/libshout-idjc/src/util.c
+++ b/lib/libshout-idjc/src/util.c
@@ -1,7 +1,7 @@
/* util.c: libshout utility/portability functions
*
- * Copyright (C) 2002-2003 the Icecast team <team@icecast.org>,
- * Copyright (C) 2012 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
+ * Copyright 2002-2003 the Icecast team <team@icecast.org>,
+ * Copyright 2012-2015 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,310 +19,356 @@
*/
#ifdef HAVE_CONFIG_H
- #include <config.h>
+# include <config.h>
#endif
+#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
+# include <sys/socket.h>
#endif
+
#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
+# include <winsock2.h>
#endif
-#include <shout/shout.h>
+#include <shoutidjc/shout.h>
+
#include "util.h"
+/* first all static tables, then the code */
+
+static const char hexchars[16] = {
+ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
+};
+
+/* For the next to tables see RFC3986 section 2.2 and 2.3. */
+static const char safechars[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const char safechars_plus_gen_delims_minus_3F_and_23[256] = {
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 2x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 3x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /* 5x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, /* 7x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ax */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* bx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* cx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* dx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ex */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* fx */
+};
+
+static const char base64table[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+
char *_shout_util_strdup(const char *s)
{
if (!s)
- return NULL;
+ return NULL;
- return strdup(s);
+ return strdup(s);
}
int _shout_util_read_header(int sock, char *buff, unsigned long len)
{
- int read_bytes, ret;
- unsigned long pos;
- char c;
-
- read_bytes = 1;
- pos = 0;
- ret = 0;
-
- while ((read_bytes == 1) && (pos < (len - 1))) {
- read_bytes = 0;
-
- if ((read_bytes = recv(sock, &c, 1, 0))) {
- if (c != '\r')
- buff[pos++] = c;
- if ((pos > 1) && (buff[pos - 1] == '\n' && buff[pos - 2] == '\n')) {
- ret = 1;
- break;
- }
- } else {
- break;
- }
- }
-
- if (ret) buff[pos] = '\0';
-
- return ret;
+ int read_bytes, ret;
+ unsigned long pos;
+ char c;
+
+ read_bytes = 1;
+ pos = 0;
+ ret = 0;
+
+ while ((read_bytes == 1) && (pos < (len - 1))) {
+ read_bytes = 0;
+
+ if ((read_bytes = recv(sock, &c, 1, 0))) {
+ if (c != '\r')
+ buff[pos++] = c;
+ if ((pos > 1) && (buff[pos - 1] == '\n' &&
+ buff[pos - 2] == '\n')) {
+ ret = 1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (ret)
+ buff[pos] = '\0';
+
+ return ret;
}
-static char base64table[65] = {
- 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
-};
-
/* This isn't efficient, but it doesn't need to be */
char *_shout_util_base64_encode(char *data)
{
- int len = strlen(data);
- char *out = malloc(len*4/3 + 4);
- char *result = out;
- int chunk;
-
- while(len > 0) {
- chunk = (len >3)?3:len;
- *out++ = base64table[(*data & 0xFC)>>2];
- *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
-
- switch(chunk) {
- case 3:
- *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
- *out++ = base64table[(*(data+2)) & 0x3F];
- break;
- case 2:
- *out++ = base64table[((*(data+1) & 0x0F)<<2)];
- *out++ = '=';
- break;
- case 1:
- *out++ = '=';
- *out++ = '=';
- break;
- }
- data += chunk;
- len -= chunk;
- }
- *out = 0;
-
- return result;
+ size_t len = strlen(data);
+ char *out = malloc(len * 4 / 3 + 4);
+ char *result = out;
+ size_t chunk;
+
+ while (len > 0) {
+ chunk = (len > 3) ? 3 : len;
+ *out++ = base64table[(*data & 0xFC) >> 2];
+ *out++ = base64table[((*data & 0x03) << 4) | ((*(data + 1) & 0xF0) >> 4)];
+
+ switch (chunk) {
+ case 3:
+ *out++ = base64table[((*(data + 1) & 0x0F) << 2) | ((*(data + 2) & 0xC0) >> 6)];
+ *out++ = base64table[(*(data + 2)) & 0x3F];
+ break;
+ case 2:
+ *out++ = base64table[((*(data + 1) & 0x0F) << 2)];
+ *out++ = '=';
+ break;
+ case 1:
+ *out++ = '=';
+ *out++ = '=';
+ break;
+ }
+ data += chunk;
+ len -= chunk;
+ }
+ *out = 0;
+
+ return result;
}
-static char urltable[16] = {
- '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
-};
+/* modified from libshout1, which credits Rick Franchuk <rickf@transpect.net>.
+ * Caller must free result.
+ */
+static char *_url_encode_with_table(const char *data, const char table[256])
+{
+ const char *p;
+ char *q, *dest;
+ int digit;
+ size_t n;
+
+ for (p = data, n = 0; *p; p++) {
+ n++;
+ if (!table[(unsigned char)(*p)])
+ n += 2;
+ }
+
+ if (!(dest = malloc(n+1))) return NULL;
+
+ for (p = data, q = dest; *p; p++, q++) {
+ if (table[(unsigned char)(*p)]) {
+ *q = *p;
+ } else {
+ *q++ = '%';
+ digit = (*p >> 4) & 0xF;
+ *q++ = hexchars[digit];
+ digit = *p & 0xf;
+ *q = hexchars[digit];
+ n += 2;
+ }
+ }
+ *q = '\0';
+
+ return dest;
+}
-static char safechars[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
+char *_shout_util_url_encode(const char *data)
+{
+ return _url_encode_with_table(data, safechars);
+}
-/* modified from libshout1, which credits Rick Franchuk <rickf@transpect.net>.
- * Caller must free result. */
-char *_shout_util_url_encode(const char *data) {
- const char *p;
- char *q, *dest;
- int digit;
- size_t n;
-
- for (p = data, n = 0; *p; p++) {
- n++;
- if (!safechars[(unsigned char)(*p)])
- n += 2;
- }
- if (!(dest = malloc(n+1)))
- return NULL;
-
- for (p = data, q = dest; *p; p++, q++) {
- if (safechars[(unsigned char)(*p)]) {
- *q = *p;
- } else {
- *q++ = '%';
- digit = (*p >> 4) & 0xF;
- *q++ = urltable[digit];
- digit = *p & 0xf;
- *q = urltable[digit];
- n += 2;
- }
- }
- *q = '\0';
-
- return dest;
+char *_shout_util_url_encode_resource(const char *data)
+{
+ return _url_encode_with_table(data, safechars_plus_gen_delims_minus_3F_and_23);
}
util_dict *_shout_util_dict_new(void)
{
- return (util_dict *)calloc(1, sizeof(util_dict));
+ return (util_dict*)calloc(1, sizeof(util_dict));
}
void _shout_util_dict_free(util_dict *dict)
{
- util_dict *next;
+ util_dict *next;
- while (dict) {
- next = dict->next;
+ while (dict) {
+ next = dict->next;
if (dict->key)
- free (dict->key);
+ free(dict->key);
if (dict->val)
- free (dict->val);
- free (dict);
+ free(dict->val);
+ free(dict);
- dict = next;
- }
+ dict = next;
+ }
}
const char *_shout_util_dict_get(util_dict *dict, const char *key)
{
- while (dict) {
- if (dict->key && !strcmp(key, dict->key))
- return dict->val;
- dict = dict->next;
- }
+ while (dict) {
+ if (dict->key && !strcmp(key, dict->key))
+ return dict->val;
+ dict = dict->next;
+ }
- return NULL;
+ return NULL;
}
int _shout_util_dict_set(util_dict *dict, const char *key, const char *val)
{
- util_dict *prev;
-
- if (!dict || !key)
- return SHOUTERR_INSANE;
-
- prev = NULL;
- while (dict) {
- if (!dict->key || !strcmp(dict->key, key))
- break;
- prev = dict;
- dict = dict->next;
- }
-
- if (!dict) {
- dict = _shout_util_dict_new();
- if (!dict)
- return SHOUTERR_MALLOC;
- if (prev)
- prev->next = dict;
- }
-
- if (dict->key)
- free (dict->val);
- else if (!(dict->key = strdup(key))) {
- if (prev)
- prev->next = NULL;
- _shout_util_dict_free (dict);
-
- return SHOUTERR_MALLOC;
- }
-
- dict->val = strdup(val);
- if (!dict->val) {
- return SHOUTERR_MALLOC;
- }
-
- return SHOUTERR_SUCCESS;
+ util_dict *prev;
+
+ if (!dict || !key) {
+ return SHOUTERR_INSANE;
+ }
+
+ prev = NULL;
+ while (dict) {
+ if (!dict->key || !strcmp(dict->key, key))
+ break;
+ prev = dict;
+ dict = dict->next;
+ }
+
+ if (!dict) {
+ dict = _shout_util_dict_new();
+ if (!dict)
+ return SHOUTERR_MALLOC;
+ if (prev)
+ prev->next = dict;
+ }
+
+ if (dict->key) {
+ free(dict->val);
+ } else if (!(dict->key = strdup(key))) {
+ if (prev)
+ prev->next = NULL;
+ _shout_util_dict_free(dict);
+
+ return SHOUTERR_MALLOC;
+ }
+
+ dict->val = strdup(val);
+ if (!dict->val) {
+ return SHOUTERR_MALLOC;
+ }
+
+ return SHOUTERR_SUCCESS;
}
/* given a dictionary, URL-encode each key and val and stringify them in order as
- key=val&key=val... if val is set, or just key&key if val is NULL.
- TODO: Memory management needs overhaul. */
+ * key=val&key=val... if val is set, or just key&key if val is NULL.
+ *
+ * TODO: Memory management needs overhaul.
+ */
char *_shout_util_dict_urlencode(util_dict *dict, char delim)
{
- size_t reslen, resoffset;
- char *res, *tmp;
- char *enc;
- int start = 1;
-
- for (res = NULL; dict; dict = dict->next) {
- /* encode key */
- if (!dict->key)
- continue;
- if (!(enc = _shout_util_url_encode(dict->key))) {
- if (res)
- free(res);
- return NULL;
- }
- if (start) {
- reslen = strlen(enc) + 1;
- if (!(res = malloc(reslen))) {
- free(enc);
- return NULL;
- }
- snprintf(res, reslen, "%s", enc);
- free(enc);
- start = 0;
- } else {
- resoffset = strlen(res);
- reslen = resoffset + strlen(enc) + 2;
- if (!(tmp = realloc(res, reslen))) {
- free(enc);
- free(res);
- return NULL;
- } else
- res = tmp;
- snprintf(res + resoffset, reslen - resoffset, "%c%s", delim, enc);
- free(enc);
- }
-
- /* encode value */
- if (!dict->val)
- continue;
- if (!(enc = _shout_util_url_encode(dict->val))) {
- free(res);
- return NULL;
- }
-
- resoffset = strlen(res);
- reslen = resoffset + strlen(enc) + 2;
- if (!(tmp = realloc(res, reslen))) {
- free(enc);
- free(res);
- return NULL;
- } else
- res = tmp;
- snprintf(res + resoffset, reslen - resoffset, "=%s", enc);
- free(enc);
- }
-
- return res;
+ size_t reslen, resoffset;
+ char *res, *tmp;
+ char *enc;
+ int start = 1;
+
+ for (res = NULL; dict; dict = dict->next) {
+ /* encode key */
+ if (!dict->key)
+ continue;
+ if (!(enc = _shout_util_url_encode(dict->key))) {
+ if (res)
+ free(res);
+ return NULL;
+ }
+ if (start) {
+ reslen = strlen(enc) + 1;
+ if (!(res = malloc(reslen))) {
+ free(enc);
+ return NULL;
+ }
+ snprintf(res, reslen, "%s", enc);
+ free(enc);
+ start = 0;
+ } else {
+ resoffset = strlen(res);
+ reslen = resoffset + strlen(enc) + 2;
+ if (!(tmp = realloc(res, reslen))) {
+ free(enc);
+ free(res);
+ return NULL;
+ } else {
+ res = tmp;
+ }
+ snprintf(res + resoffset, reslen - resoffset, "%c%s", delim, enc);
+ free(enc);
+ }
+
+ /* encode value */
+ if (!dict->val)
+ continue;
+ if (!(enc = _shout_util_url_encode(dict->val))) {
+ free(res);
+ return NULL;
+ }
+
+ resoffset = strlen(res);
+ reslen = resoffset + strlen(enc) + 2;
+ if (!(tmp = realloc(res, reslen))) {
+ free(enc);
+ free(res);
+ return NULL;
+ } else {
+ res = tmp;
+ }
+ snprintf(res + resoffset, reslen - resoffset, "=%s", enc);
+ free(enc);
+ }
+
+ return res;
}
-const char *_shout_util_dict_next(util_dict **dict, const char **key, const char **val) {
- *key = NULL;
- *val = NULL;
-
- if (!dict)
- return NULL;
- *dict = (*dict)->next;
- while (*dict && !(*dict)->key)
- *dict = (*dict)->next;
- if (!*dict)
- return NULL;
- *key = (*dict)->key;
- *val = (*dict)->val;
- return *key;
+const char *_shout_util_dict_next(util_dict **dict, const char **key, const char **val)
+{
+ *key = NULL;
+ *val = NULL;
+
+ if (!dict)
+ return NULL;
+ *dict = (*dict)->next;
+ while (*dict && !(*dict)->key)
+ *dict = (*dict)->next;
+ if (!*dict)
+ return NULL;
+ *key = (*dict)->key;
+ *val = (*dict)->val;
+ return *key;
}