summaryrefslogtreecommitdiff
path: root/Utilities/cmlibrhash/librhash/hex.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibrhash/librhash/hex.c')
-rw-r--r--Utilities/cmlibrhash/librhash/hex.c170
1 files changed, 96 insertions, 74 deletions
diff --git a/Utilities/cmlibrhash/librhash/hex.c b/Utilities/cmlibrhash/librhash/hex.c
index c941149ab3..f0bbf043ed 100644
--- a/Utilities/cmlibrhash/librhash/hex.c
+++ b/Utilities/cmlibrhash/librhash/hex.c
@@ -1,71 +1,57 @@
/* hex.c - conversion for hexadecimal and base32 strings.
*
- * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
+ * Copyright (c) 2008, Aleksey Kravchenko <rhash.admin@gmail.com>
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
-#include <string.h>
-#include <ctype.h>
#include "hex.h"
-
-/**
-* Convert a byte to a hexadecimal number. The result, consisting of two
-* hexadecimal digits is stored into a buffer.
- *
- * @param dest the buffer to receive two symbols of hex representation
- * @param byte the byte to decode
- * @param upper_case flag to print string in uppercase
- * @return pointer to the chararcter just after the written number (dest + 2)
- */
-char* rhash_print_hex_byte(char *dest, const unsigned char byte, int upper_case)
-{
- const char add = (upper_case ? 'A' - 10 : 'a' - 10);
- unsigned char c = (byte >> 4) & 15;
- *dest++ = (c > 9 ? c + add : c + '0');
- c = byte & 15;
- *dest++ = (c > 9 ? c + add : c + '0');
- return dest;
-}
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
/**
* Store hexadecimal representation of a binary string to given buffer.
*
- * @param dest the buffer to receive hexadecimal representation
+ * @param dst the buffer to receive hexadecimal representation
* @param src binary string
- * @param len string length
+ * @param length string length
* @param upper_case flag to print string in uppercase
*/
-void rhash_byte_to_hex(char *dest, const unsigned char *src, unsigned len, int upper_case)
+void rhash_byte_to_hex(char* dst, const unsigned char* src, size_t length, int upper_case)
{
- while (len-- > 0) {
- dest = rhash_print_hex_byte(dest, *src++, upper_case);
+ const char hex_add = (upper_case ? 'A' - 10 : 'a' - 10);
+ for (; length > 0; src++, length--) {
+ const unsigned char hi = (*src >> 4) & 15;
+ const unsigned char lo = *src & 15;
+ *dst++ = (hi > 9 ? hi + hex_add : hi + '0');
+ *dst++ = (lo > 9 ? lo + hex_add : lo + '0');
}
- *dest = '\0';
+ *dst = '\0';
}
/**
* Encode a binary string to base32.
*
- * @param dest the buffer to store result
+ * @param dst the buffer to store result
* @param src binary string
- * @param len string length
+ * @param length string length
* @param upper_case flag to print string in uppercase
*/
-void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, int upper_case)
+void rhash_byte_to_base32(char* dst, const unsigned char* src, size_t length, int upper_case)
{
const char a = (upper_case ? 'A' : 'a');
unsigned shift = 0;
unsigned char word;
- const unsigned char* e = src + len;
+ const unsigned char* e = src + length;
while (src < e) {
if (shift > 3) {
word = (*src & (0xFF >> shift));
@@ -79,25 +65,25 @@ void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, in
word = ( *src >> ( (8 - shift) & 7 ) ) & 0x1F;
if (shift == 0) src++;
}
- *dest++ = ( word < 26 ? word + a : word + '2' - 26 );
+ *dst++ = ( word < 26 ? word + a : word + '2' - 26 );
}
- *dest = '\0';
+ *dst = '\0';
}
/**
* Encode a binary string to base64.
* Encoded output length is always a multiple of 4 bytes.
*
- * @param dest the buffer to store result
+ * @param dst the buffer to store result
* @param src binary string
- * @param len string length
+ * @param length string length
*/
-void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len)
+void rhash_byte_to_base64(char* dst, const unsigned char* src, size_t length)
{
static const char* tail = "0123456789+/";
unsigned shift = 0;
unsigned char word;
- const unsigned char* e = src + len;
+ const unsigned char* e = src + length;
while (src < e) {
if (shift > 2) {
word = (*src & (0xFF >> shift));
@@ -111,45 +97,80 @@ void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len)
word = ( *src >> ( (8 - shift) & 7 ) ) & 0x3F;
if (shift == 0) src++;
}
- *dest++ = ( word < 52 ? (word < 26 ? word + 'A' : word - 26 + 'a') : tail[word - 52]);
+ *dst++ = ( word < 52 ? (word < 26 ? word + 'A' : word - 26 + 'a') : tail[word - 52]);
}
if (shift > 0) {
- *dest++ = '=';
- if (shift == 4) *dest++ = '=';
+ *dst++ = '=';
+ if (shift == 4) *dst++ = '=';
}
- *dest = '\0';
+ *dst = '\0';
}
-/* unsafe characters are "<>{}[]%#/|\^~`@:;?=&+ */
-#define IS_GOOD_URL_CHAR(c) (isalnum((unsigned char)c) || strchr("$-_.!'(),", c))
+size_t rhash_base64_url_encoded_helper(char* dst, const unsigned char* src, size_t length, int url_encode, int upper_case)
+{
+#define B64_CHUNK_SIZE 120
+ char buffer[164];
+ assert((BASE64_LENGTH(B64_CHUNK_SIZE) + 4) <= sizeof(buffer));
+ assert((B64_CHUNK_SIZE % 6) == 0);
+ if (url_encode) {
+ size_t result_length = 0;
+ for (; length > 0; src += B64_CHUNK_SIZE) {
+ size_t chunk_size = (length < B64_CHUNK_SIZE ? length : B64_CHUNK_SIZE);
+ size_t encoded_length;
+ rhash_byte_to_base64(buffer, src, chunk_size);
+ encoded_length = rhash_urlencode(dst, buffer, BASE64_LENGTH(chunk_size), upper_case);
+ result_length += encoded_length;
+ dst += encoded_length;
+ length -= chunk_size;
+ }
+ return result_length;
+ }
+ rhash_byte_to_base64(dst, src, length);
+ return BASE64_LENGTH(length);
+}
+
+/* RFC 3986: safe url characters are ascii alpha-numeric and "-._~", other characters should be percent-encoded */
+static unsigned url_safe_char_mask[4] = { 0, 0x03ff6000, 0x87fffffe, 0x47fffffe };
+#define IS_URL_GOOD_CHAR(c) ((unsigned)(c) < 128 && (url_safe_char_mask[c >> 5] & (1 << (c & 31))))
/**
- * URL-encode a string.
+ * URL-encode specified binary string.
*
- * @param dst buffer to receive result or NULL to calculate
- * the lengths of encoded string
- * @param filename the file name
+ * @param dst (nullable) buffer to output encoded string to,
+ * NULL to just calculate the lengths of encoded string
+ * @param src binary string to encode
+ * @param size size of the binary string
+ * @param upper_case flag to output hex-codes in uppercase
* @return the length of the result string
*/
-int rhash_urlencode(char *dst, const char *name)
+size_t rhash_urlencode(char* dst, const char* src, size_t size, int upper_case)
{
- const char *start;
+ const char* start;
+ size_t i;
if (!dst) {
- int len;
- for (len = 0; *name; name++) len += (IS_GOOD_URL_CHAR(*name) ? 1 : 3);
- return len;
- }
- /* encode URL as specified by RFC 1738 */
- for (start = dst; *name; name++) {
- if ( IS_GOOD_URL_CHAR(*name) ) {
- *dst++ = *name;
- } else {
- *dst++ = '%';
- dst = rhash_print_hex_byte(dst, *name, 'A');
+ size_t length = size;
+ for (i = 0; i < size; i++)
+ if (!IS_URL_GOOD_CHAR(src[i]))
+ length += 2;
+ return length;
+ } else {
+ const char hex_add = (upper_case ? 'A' - 10 : 'a' - 10);
+ start = dst;
+ /* percent-encode all but unreserved URL characters */
+ for (i = 0; i < size; i++) {
+ if (IS_URL_GOOD_CHAR(src[i])) {
+ *dst++ = src[i];
+ } else {
+ unsigned char hi = ((unsigned char)(src[i]) >> 4) & 0x0f;
+ unsigned char lo = (unsigned char)(src[i]) & 0x0f;
+ *dst++ = '%';
+ *dst++ = (hi > 9 ? hi + hex_add : hi + '0');
+ *dst++ = (lo > 9 ? lo + hex_add : lo + '0');
+ }
}
+ *dst = 0;
}
- *dst = 0;
- return (int)(dst - start);
+ return dst - start;
}
/**
@@ -160,10 +181,11 @@ int rhash_urlencode(char *dst, const char *name)
* @param number the number to print
* @return length of the printed number (without trailing '\0')
*/
-int rhash_sprintI64(char *dst, uint64_t number)
+int rhash_sprintI64(char* dst, uint64_t number)
{
/* The biggest number has 20 digits: 2^64 = 18 446 744 073 709 551 616 */
- char buf[24], *p;
+ char buf[24];
+ char* p;
size_t length;
if (dst == NULL) {