file_util.c: refactor and fix checksum_hex2bin()
[project/opkg-lede.git] / libopkg / file_util.c
index 912b147ad306766f6275e93a3b9860de81b29242..3a1761eea76d331e15d8327bfb20ca8f86e52d92 100644 (file)
@@ -16,8 +16,6 @@
    General Public License for more details.
 */
 
-#include "config.h"
-
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "sprintf_alloc.h"
 #include "file_util.h"
-#ifdef HAVE_MD5
-#include "md5.h"
-#endif
+#include <libubox/md5.h>
 #include "libbb/libbb.h"
 
-#if defined HAVE_SHA256
 #include "sha256.h"
-#endif
 
 int file_exists(const char *file_name)
 {
@@ -65,17 +59,14 @@ int file_is_dir(const char *file_name)
 */
 char *file_read_line_alloc(FILE * fp)
 {
+       size_t buf_len, line_size;
        char buf[BUFSIZ];
-       unsigned int buf_len;
        char *line = NULL;
-       unsigned int line_size = 0;
        int got_nl = 0;
 
-       buf[0] = '\0';
-
        while (fgets(buf, BUFSIZ, fp)) {
                buf_len = strlen(buf);
-               if (buf[buf_len - 1] == '\n') {
+               if (buf_len > 0 && buf[buf_len - 1] == '\n') {
                        buf_len--;
                        buf[buf_len] = '\0';
                        got_nl = 1;
@@ -131,42 +122,43 @@ int file_mkdir_hier(const char *path, long mode)
        return make_directory(path, mode, FILEUTILS_RECUR);
 }
 
-#ifdef HAVE_MD5
+
+static int hex2bin(unsigned char x)
+{
+       if (x >= 'a' && x <= 'f')
+               return x - 'a' + 10;
+       else if (x >= 'A' && x <= 'F')
+               return x - 'A' + 10;
+       else if (x >= '0' && x <= '9')
+               return x - '0';
+       else
+               return 0;
+}
+
+static const unsigned char bin2hex[16] = {
+       '0', '1', '2', '3',
+       '4', '5', '6', '7',
+       '8', '9', 'a', 'b',
+       'c', 'd', 'e', 'f'
+};
+
 char *file_md5sum_alloc(const char *file_name)
 {
        static const int md5sum_bin_len = 16;
        static const int md5sum_hex_len = 32;
 
-       static const unsigned char bin2hex[16] = {
-               '0', '1', '2', '3',
-               '4', '5', '6', '7',
-               '8', '9', 'a', 'b',
-               'c', 'd', 'e', 'f'
-       };
-
-       int i, err;
-       FILE *file;
+       int i, len;
        char *md5sum_hex;
        unsigned char md5sum_bin[md5sum_bin_len];
 
-       md5sum_hex = xcalloc(1, md5sum_hex_len + 1);
+       len = md5sum(file_name, md5sum_bin);
 
-       file = fopen(file_name, "r");
-       if (file == NULL) {
-               opkg_perror(ERROR, "Failed to open file %s", file_name);
-               free(md5sum_hex);
-               return NULL;
-       }
-
-       err = md5_stream(file, md5sum_bin);
-       if (err) {
+       if (len) {
                opkg_msg(ERROR, "Could't compute md5sum for %s.\n", file_name);
-               fclose(file);
-               free(md5sum_hex);
                return NULL;
        }
 
-       fclose(file);
+       md5sum_hex = xcalloc(1, md5sum_hex_len + 1);
 
        for (i = 0; i < md5sum_bin_len; i++) {
                md5sum_hex[i * 2] = bin2hex[md5sum_bin[i] >> 4];
@@ -177,21 +169,12 @@ char *file_md5sum_alloc(const char *file_name)
 
        return md5sum_hex;
 }
-#endif
 
-#ifdef HAVE_SHA256
 char *file_sha256sum_alloc(const char *file_name)
 {
        static const int sha256sum_bin_len = 32;
        static const int sha256sum_hex_len = 64;
 
-       static const unsigned char bin2hex[16] = {
-               '0', '1', '2', '3',
-               '4', '5', '6', '7',
-               '8', '9', 'a', 'b',
-               'c', 'd', 'e', 'f'
-       };
-
        int i, err;
        FILE *file;
        char *sha256sum_hex;
@@ -227,57 +210,50 @@ char *file_sha256sum_alloc(const char *file_name)
        return sha256sum_hex;
 }
 
-#endif
-
 char *checksum_bin2hex(const char *src, size_t len)
 {
-       char *p;
-       static char buf[65];
-       static const unsigned char bin2hex[16] = {
-               '0', '1', '2', '3',
-               '4', '5', '6', '7',
-               '8', '9', 'a', 'b',
-               'c', 'd', 'e', 'f'
-       };
-
-       if (len > 32)
+       unsigned char *p;
+       static unsigned char buf[65];
+       const unsigned char *s = (unsigned char *)src;
+       if (!s || len > 32)
                return NULL;
 
-       for (p = buf; len > 0; src++, len--) {
-               *p++ = bin2hex[*src / 16];
-               *p++ = bin2hex[*src % 16];
+       for (p = buf; len > 0; s++, len--) {
+               *p++ = bin2hex[*s / 16];
+               *p++ = bin2hex[*s % 16];
        }
 
        *p = 0;
 
-       return buf;
+       return (char *)buf;
 }
 
 char *checksum_hex2bin(const char *src, size_t *len)
 {
-       char *p;
-       size_t slen;
-       static char buf[32];
+       static unsigned char buf[32];
+       size_t n = 0;
+
+       *len = 0;
+
+       if (!src)
+               return NULL;
 
        while (isspace(*src))
                src++;
 
-       slen = strlen(src);
-
-       if (slen > 64) {
-               *len = 0;
+       if (strlen(src) > sizeof(buf) * 2)
                return NULL;
-       }
 
-#define hex(c) \
-       (c >= 'a' ? (c - 'a') : (c >= 'A' ? (c - 'A') : (c - '0')))
+       while (*src) {
+               if (n >= sizeof(buf) || !isxdigit(src[0]) || !isxdigit(src[1]))
+                       return NULL;
 
-       for (p = buf, *len = 0;
-            slen > 0 && isxdigit(src[0]) && isxdigit(src[1]);
-            slen--, src += 2, (*len)++)
-               *p++ = hex(src[0]) * 16 + hex(src[1]);
+               buf[n++] = hex2bin(src[0]) * 16 + hex2bin(src[1]);
+               src += 2;
+       }
 
-       return buf;
+       *len = n;
+       return n ? (char *)buf : NULL;
 }
 
 int rm_r(const char *path)
@@ -361,3 +337,76 @@ int rm_r(const char *path)
 
        return ret;
 }
+
+static int urlencode_is_specialchar(char c)
+{
+       switch (c) {
+       case ':':
+       case '?':
+       case '#':
+       case '[':
+       case ']':
+       case '@':
+       case '!':
+       case '$':
+       case '&':
+       case '\'':
+       case '(':
+       case ')':
+       case '*':
+       case '+':
+       case ',':
+       case ';':
+       case '=':
+       case '%':
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
+char *urlencode_path(const char *filename)
+{
+       size_t len = 0;
+       const unsigned char *in;
+       unsigned char *copy, *out;
+
+       for (in = (unsigned char *)filename; *in != 0; in++)
+               len += urlencode_is_specialchar(*in) ? 3 : 1;
+
+       copy = xcalloc(1, len + 1);
+
+       for (in = (unsigned char *)filename, out = copy; *in != 0; in++) {
+               if (urlencode_is_specialchar(*in)) {
+                       *out++ = '%';
+                       *out++ = bin2hex[*in / 16];
+                       *out++ = bin2hex[*in % 16];
+               }
+               else {
+                       *out++ = *in;
+               }
+       }
+
+       return (char *)copy;
+}
+
+char *urldecode_path(const char *filename)
+{
+       unsigned char *copy = (unsigned char *)xstrdup(filename);
+       unsigned char *in, *out;
+
+       for (in = copy, out = copy; *in != 0; in++) {
+               if (*in == '%' && isxdigit(in[1]) && isxdigit(in[2])) {
+                       *out++ = hex2bin(in[1]) * 16 + hex2bin(in[2]);
+                       in += 2;
+               }
+               else {
+                       *out++ = *in;
+               }
+       }
+
+       *out = 0;
+
+       return (char *)copy;
+}