/* * Copyright (c) 2014 Cesanta Software Limited * All rights reserved */ #include "net_skeleton.h" #include "util.h" const char *ns_skip(const char *s, const char *end, const char *delims, struct ns_str *v) { v->p = s; while (s < end && strchr(delims, * (unsigned char *) s) == NULL) s++; v->len = s - v->p; while (s < end && strchr(delims, * (unsigned char *) s) != NULL) s++; return s; } static int lowercase(const char *s) { return tolower(* (const unsigned char *) s); } int ns_ncasecmp(const char *s1, const char *s2, size_t len) { int diff = 0; if (len > 0) do { diff = lowercase(s1++) - lowercase(s2++); } while (diff == 0 && s1[-1] != '\0' && --len > 0); return diff; } int ns_vcasecmp(const struct ns_str *str2, const char *str1) { size_t n1 = strlen(str1), n2 = str2->len; return n1 == n2 ? ns_ncasecmp(str1, str2->p, n1) : n1 > n2 ? 1 : -1; } int ns_vcmp(const struct ns_str *str2, const char *str1) { size_t n1 = strlen(str1), n2 = str2->len; return n1 == n2 ? memcmp(str1, str2->p, n2) : n1 > n2 ? 1 : -1; } #ifdef _WIN32 static void to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) { char buf[MAX_PATH_SIZE * 2], buf2[MAX_PATH_SIZE * 2], *p; strncpy(buf, path, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; /* Trim trailing slashes. Leave backslash for paths like "X:\" */ p = buf + strlen(buf) - 1; while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0'; /* * Convert to Unicode and back. If doubly-converted string does not * match the original, something is fishy, reject. */ memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), NULL, NULL); if (strcmp(buf, buf2) != 0) { wbuf[0] = L'\0'; } } #endif /* _WIN32 */ int ns_stat(const char *path, ns_stat_t *st) { #ifdef _WIN32 wchar_t wpath[MAX_PATH_SIZE]; to_wchar(path, wpath, ARRAY_SIZE(wpath)); DBG(("[%ls] -> %d", wpath, _wstati64(wpath, st))); return _wstati64(wpath, st); #else return stat(path, st); #endif } FILE *ns_fopen(const char *path, const char *mode) { #ifdef _WIN32 wchar_t wpath[MAX_PATH_SIZE], wmode[10]; to_wchar(path, wpath, ARRAY_SIZE(wpath)); to_wchar(mode, wmode, ARRAY_SIZE(wmode)); return _wfopen(wpath, wmode); #else return fopen(path, mode); #endif } int ns_open(const char *path, int flag, int mode) { #ifdef _WIN32 wchar_t wpath[MAX_PATH_SIZE]; to_wchar(path, wpath, ARRAY_SIZE(wpath)); return _wopen(wpath, flag, mode); #else return open(path, flag, mode); #endif } void ns_base64_encode(const unsigned char *src, int src_len, char *dst) { static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int i, j, a, b, c; for (i = j = 0; i < src_len; i += 3) { a = src[i]; b = i + 1 >= src_len ? 0 : src[i + 1]; c = i + 2 >= src_len ? 0 : src[i + 2]; dst[j++] = b64[a >> 2]; dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; if (i + 1 < src_len) { dst[j++] = b64[(b & 15) << 2 | (c >> 6)]; } if (i + 2 < src_len) { dst[j++] = b64[c & 63]; } } while (j % 4 != 0) { dst[j++] = '='; } dst[j++] = '\0'; } /* Convert one byte of encoded base64 input stream to 6-bit chunk */ static unsigned char from_b64(unsigned char ch) { /* Inverse lookup map */ static const unsigned char tab[128] = { 255, 255, 255, 255, 255, 255, 255, 255, /* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 16 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 24 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 32 */ 255, 255, 255, 62, 255, 255, 255, 63, /* 40 */ 52, 53, 54, 55, 56, 57, 58, 59, /* 48 */ 60, 61, 255, 255, 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */ 255, 0, 1, 2, 3, 4, 5, 6, /* 64 */ 7, 8, 9, 10, 11, 12, 13, 14, /* 72 */ 15, 16, 17, 18, 19, 20, 21, 22, /* 80 */ 23, 24, 25, 255, 255, 255, 255, 255, /* 88 */ 255, 26, 27, 28, 29, 30, 31, 32, /* 96 */ 33, 34, 35, 36, 37, 38, 39, 40, /* 104 */ 41, 42, 43, 44, 45, 46, 47, 48, /* 112 */ 49, 50, 51, 255, 255, 255, 255, 255, /* 120 */ }; return tab[ch & 127]; } void ns_base64_decode(const unsigned char *s, int len, char *dst) { unsigned char a, b, c, d; while (len >= 4 && (a = from_b64(s[0])) != 255 && (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 && (d = from_b64(s[3])) != 255) { if (a == 200 || b == 200) break; /* '=' can't be there */ *dst++ = a << 2 | b >> 4; if (c == 200) break; *dst++ = b << 4 | c >> 2; if (d == 200) break; *dst++ = c << 6 | d; s += 4; len -=4; } *dst = 0; }