Author: zwoop
Date: Fri Jan 6 05:06:56 2012
New Revision: 1227955
URL: http://svn.apache.org/viewvc?rev=1227955&view=rev
Log:
TS-1057 Expose Base64-encoding through APIs. Author: Yakov Kopel and leif
Modified:
trafficserver/traffic/trunk/lib/ts/ink_base64.cc
trafficserver/traffic/trunk/lib/ts/ink_base64.h
trafficserver/traffic/trunk/proxy/InkAPI.cc
trafficserver/traffic/trunk/proxy/api/ts/ts.h.in
Modified: trafficserver/traffic/trunk/lib/ts/ink_base64.cc
URL:
http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_base64.cc?rev=1227955&r1=1227954&r2=1227955&view=diff
==============================================================================
--- trafficserver/traffic/trunk/lib/ts/ink_base64.cc (original)
+++ trafficserver/traffic/trunk/lib/ts/ink_base64.cc Fri Jan 6 05:06:56 2012
@@ -38,103 +38,29 @@
#include "ink_resource.h"
#include "ink_unused.h"
-/*-------------------------------------------------------------------------
- -------------------------------------------------------------------------*/
-
-#ifdef decode
-# undef decode
-#endif
-#define decode(A) ((unsigned int)codes[(unsigned char)input[A]])
-
-// NOTE: ink_base64_decode returns ats_xmalloc'd memory
-
-char *
-ink_base64_decode(const char *input, int input_len, int *output_len)
-{
- char *output;
- char *obuf;
- static bool initialized = FALSE;
- static char codes[256];
- int cc = 0;
- int len;
- int i;
-
- if (!initialized) {
- /* Build translation table */
- for (i = 0; i < 256; i++)
- codes[i] = 0;
- for (i = 'A'; i <= 'Z'; i++)
- codes[i] = cc++;
- for (i = 'a'; i <= 'z'; i++)
- codes[i] = cc++;
- for (i = '0'; i <= '9'; i++)
- codes[i] = cc++;
- codes[0 + '+'] = cc++;
- codes[0 + '/'] = cc++;
- initialized = TRUE;
- }
- // compute ciphertext length
- for (len = 0; len < input_len && input[len] != '='; len++);
-
- output = obuf = (char *)ats_malloc((len * 6) / 8 + 4);
- while (len > 0) {
- *output++ = decode(0) << 2 | decode(1) >> 4;
- *output++ = decode(1) << 4 | decode(2) >> 2;
- *output++ = decode(2) << 6 | decode(3);
- len -= 4;
- input += 4;
- }
-
- /*
- * We don't need to worry about leftover bits because
- * we've allocated a few extra characters and if there
- * are leftover bits they will be zeros because the extra
- * inputs will be '='s and '=' decodes to 0.
- */
-
- *output = '\0';
- *output_len = (int) (output - obuf);
- return obuf;
-}
-
-#undef decode
-
-/*-------------------------------------------------------------------------
- -------------------------------------------------------------------------*/
-// NOTE: ink_base64_encode returns ats_malloc'd memory
+// TODO: This code is not paritcularly "uniform", we ought to make them
+// more the same coding style (the uuencode one seems good'ish).
-char *
-ink_base64_encode(const char *input, int input_len, int *output_len)
-{
- return ink_base64_encode_unsigned((const unsigned char *) input, input_len,
output_len);
-}
-char *
-ink_base64_encode_unsigned(const unsigned char *input, int input_len, int
*output_len)
+size_t
+ats_base64_encode(const unsigned char *inBuffer, size_t inBufferSize, char
*outBuffer, size_t outBufSize)
{
- char *output;
- char *obuf;
- static char codes[66] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ static const char _codes[66] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ char *obuf = outBuffer;
char in_tail[4];
- int len;
-
- len = input_len;
-
- output = obuf = (char *)ats_malloc((len * 8) / 6 + 4);
- while (len > 2) {
- *output++ = codes[(input[0] >> 2) & 077];
- *output++ = codes[((input[0] & 03) << 4)
- | ((input[1] >> 4) & 017)];
+ if (outBufSize < ATS_BASE64_ENCODE_DSTLEN(inBufferSize))
+ return 0;
- *output++ = codes[((input[1] & 017) << 2)
- | ((input[2] >> 6) & 017)];
+ while (inBufferSize > 2) {
+ *obuf++ = _codes[(inBuffer[0] >> 2) & 077];
+ *obuf++ = _codes[((inBuffer[0] & 03) << 4) | ((inBuffer[1] >> 4) & 017)];
+ *obuf++ = _codes[((inBuffer[1] & 017) << 2) | ((inBuffer[2] >> 6) & 017)];
+ *obuf++ = _codes[inBuffer[2] & 077];
- *output++ = codes[input[2] & 077];
-
- len -= 3;
- input += 3;
+ inBufferSize -= 3;
+ inBuffer += 3;
}
/*
@@ -145,46 +71,43 @@ ink_base64_encode_unsigned(const unsigne
* If 1 char left, form 2 output chars, and add 2 pad chars to output.
* If 2 chars left, form 3 output chars, add 1 pad char to output.
*/
-
- if (len == 0) {
- *output_len = (int) (output - obuf);
- *output = '\0';
- return obuf;
+ if (inBufferSize == 0) {
+ *obuf = '\0';
+ return (obuf - outBuffer);
} else {
memset(in_tail, 0, sizeof(in_tail));
- memcpy(in_tail, input, len);
-
- *(output) = codes[(in_tail[0] >> 2) & 077];
-
- *(output + 1) = codes[((in_tail[0] & 03) << 4)
- | ((in_tail[1] >> 4) & 017)];
+ memcpy(in_tail, inBuffer, inBufferSize);
- *(output + 2) = codes[((in_tail[1] & 017) << 2)
- | ((in_tail[2] >> 6) & 017)];
+ *(obuf) = _codes[(in_tail[0] >> 2) & 077];
+ *(obuf + 1) = _codes[((in_tail[0] & 03) << 4) | ((in_tail[1] >> 4) & 017)];
+ *(obuf + 2) = _codes[((in_tail[1] & 017) << 2) | ((in_tail[2] >> 6) &
017)];
+ *(obuf + 3) = _codes[in_tail[2] & 077];
+
+ if (inBufferSize == 1)
+ *(obuf + 2) = '=';
+ *(obuf + 3) = '=';
+ *(obuf + 4) = '\0';
- *(output + 3) = codes[in_tail[2] & 077];
-
- if (len == 1)
- *(output + 2) = '=';
-
- *(output + 3) = '=';
-
- *(output + 4) = '\0';
-
- *output_len = (int) ((output + 4) - obuf);
- return obuf;
+ return ((obuf + 4) - outBuffer);
}
}
+size_t
+ats_base64_encode(const char *inBuffer, size_t inBufferSize, char *outBuffer,
size_t outBufSize)
+{
+ return ats_base64_encode((const unsigned char *)inBuffer, inBufferSize,
outBuffer, outBufSize);
+}
+
/*-------------------------------------------------------------------------
+ This is a reentrant, and malloc free implemetnation of ats_base64_decode.
-------------------------------------------------------------------------*/
+#ifdef DECODE
+#undef DECODE
+#endif
-// int ink_base64_decode()
-//
-// The above functions require malloc'ing buffer which isn't good for
-// Traffic Server performance and the the decode routine is not
-// reentrant. The following function fixes both those problems
+#define DECODE(x) printableToSixBit[(unsigned char)x]
+#define MAX_PRINT_VAL 63
/* Converts a printable character to it's six bit representation */
const unsigned char printableToSixBit[256] = {
@@ -201,38 +124,19 @@ const unsigned char printableToSixBit[25
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
-
-#ifdef DECODE
-#undef DECODE
-#endif
-
-#define DECODE(x) printableToSixBit[(unsigned char)x]
-#define MAX_PRINT_VAL 63
-
-int
-ink_base64_decode(const char *inBuffer, int outBufSize, unsigned char
*outBuffer)
+size_t
+ats_base64_decode(const char *inBuffer, size_t inBufferSize, unsigned char
*outBuffer, size_t outBufSize)
{
-
- int inBytes = 0;
- int decodedBytes = 0;
+ size_t decodedBytes = 0;
unsigned char *outStart = outBuffer;
int inputBytesDecoded = 0;
- // Figure out much encoded string is really there
- while (printableToSixBit[(uint8_t)inBuffer[inBytes]] <= MAX_PRINT_VAL) {
- inBytes++;
- }
-
// Make sure there is sufficient space in the output buffer
- // if not shorten the number of bytes in
- if ((((inBytes + 3) / 4) * 3) > outBufSize - 1) {
- inBytes = ((outBufSize - 1) * 4) / 3;
- }
-
- for (int i = 0; i < inBytes; i += 4) {
+ if (outBufSize < ATS_BASE64_DECODE_DSTLEN(inBufferSize))
+ return 0;
+ for (size_t i = 0; i < inBufferSize; i += 4) {
outBuffer[0] = (unsigned char) (DECODE(inBuffer[0]) << 2 |
DECODE(inBuffer[1]) >> 4);
-
outBuffer[1] = (unsigned char) (DECODE(inBuffer[1]) << 4 |
DECODE(inBuffer[2]) >> 2);
outBuffer[2] = (unsigned char) (DECODE(inBuffer[2]) << 6 |
DECODE(inBuffer[3]));
@@ -244,59 +148,14 @@ ink_base64_decode(const char *inBuffer,
// Check to see if we decoded a multiple of 4 four
// bytes
- if ((inBytes - inputBytesDecoded) & 0x3) {
+ if ((inBufferSize - inputBytesDecoded) & 0x3) {
if (DECODE(inBuffer[-2]) > MAX_PRINT_VAL) {
decodedBytes -= 2;
} else {
decodedBytes -= 1;
}
}
-
outStart[decodedBytes] = '\0';
return decodedBytes;
}
-
-
-char six2pr[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', '+', '/'
-};
-
-/*-------------------------------------------------------------------------
- -------------------------------------------------------------------------*/
-
-int
-ink_base64_uuencode(const char *bufin, int nbytes, unsigned char *outBuffer)
-{
-
- int i;
-
- for (i = 0; i < nbytes; i += 3) {
- *(outBuffer++) = six2pr[*bufin >> 2]; /* c1 */
- *(outBuffer++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)];
/*c2 */
- *(outBuffer++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];
/*c3 */
- *(outBuffer++) = six2pr[bufin[2] & 077]; /* c4 */
-
- bufin += 3;
- }
-
- /* If nbytes was not a multiple of 3, then we have encoded too
- * many characters. Adjust appropriately.
- */
- if (i == nbytes + 1) {
- /* There were only 2 bytes in that last group */
- outBuffer[-1] = '=';
- } else if (i == nbytes + 2) {
- /* There was only 1 byte in that last group */
- outBuffer[-1] = '=';
- outBuffer[-2] = '=';
- }
-
- *outBuffer = '\0';
-
- return TRUE;
-}
Modified: trafficserver/traffic/trunk/lib/ts/ink_base64.h
URL:
http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_base64.h?rev=1227955&r1=1227954&r2=1227955&view=diff
==============================================================================
--- trafficserver/traffic/trunk/lib/ts/ink_base64.h (original)
+++ trafficserver/traffic/trunk/lib/ts/ink_base64.h Fri Jan 6 05:06:56 2012
@@ -23,7 +23,7 @@
#ifndef _ink_base64_h_
#define _ink_base64_h_
-#include "ink_apidefs.h"
+
/*
* Base64 encoding and decoding as according to RFC1521. Similar to uudecode.
* See RFC1521 for specificiation.
@@ -36,14 +36,14 @@
* responsible for freeing the strings.
*
*/
+// Encodes / Decodes into user supplied buffer. Returns number of bytes
decoded
+size_t ats_base64_encode(const char *inBuffer, size_t inBufferSize, char
*outBuffer, size_t outBufSize);
+size_t ats_base64_encode(const unsigned char *inBuffer, size_t inBufferSize,
char *outBuffer, size_t outBufSize);
-// These functions return ats_malloc'd memory which caller needs to ats_free
-inkcoreapi char *ink_base64_decode(const char *input, int input_len, int
*output_len);
-char *ink_base64_encode(const char *input, int input_len, int *output_len);
-char *ink_base64_encode_unsigned(const unsigned char *input, int input_len,
int *output_len);
+size_t ats_base64_decode(const char *inBuffer, size_t inBufferSize, unsigned
char *outBuffer, size_t outBufSize);
-// Decodes into user supplied buffer. Returns number of bytes decoded
-inkcoreapi int ink_base64_decode(const char *inBuffer, int outBufSize,
unsigned char *outBuffer);
-int ink_base64_uuencode(const char *bufin, int nbytes, unsigned char
*outBuffer);
+// Little helper functions to calculate minimum required output buffer for
encoding/decoding.
+#define ATS_BASE64_ENCODE_DSTLEN(_length) ((_length * 8) / 6 + 4)
+#define ATS_BASE64_DECODE_DSTLEN(_length) (((_length + 3) / 4) * 3)
#endif
Modified: trafficserver/traffic/trunk/proxy/InkAPI.cc
URL:
http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/InkAPI.cc?rev=1227955&r1=1227954&r2=1227955&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/InkAPI.cc (original)
+++ trafficserver/traffic/trunk/proxy/InkAPI.cc Fri Jan 6 05:06:56 2012
@@ -1681,6 +1681,29 @@ _TSfree(void *ptr)
////////////////////////////////////////////////////////////////////
//
+// Encoding utility
+//
+////////////////////////////////////////////////////////////////////
+size_t
+TSBase64Decode(const char *input, size_t length, unsigned char *dst, size_t
dst_size)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void*)input) == TS_SUCCESS);
+ sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
+
+ return ats_base64_decode(input, length, dst, dst_size);
+}
+
+size_t
+TSBase64Encode(const char *input, size_t length, char *dst, size_t dst_size)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void*)input) == TS_SUCCESS);
+ sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
+
+ return ats_base64_encode(input, length, dst, dst_size);
+}
+
+////////////////////////////////////////////////////////////////////
+//
// API utility routines
//
////////////////////////////////////////////////////////////////////
Modified: trafficserver/traffic/trunk/proxy/api/ts/ts.h.in
URL:
http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/api/ts/ts.h.in?rev=1227955&r1=1227954&r2=1227955&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/api/ts/ts.h.in (original)
+++ trafficserver/traffic/trunk/proxy/api/ts/ts.h.in Fri Jan 6 05:06:56 2012
@@ -3016,6 +3016,10 @@ extern "C"
tsapi TSReturnCode TSHttpTxnCachedUrlSet(TSHttpTxn txnp, TSMBuffer bufp,
TSMLoc obj);
tsapi TSReturnCode TSHttpTxnPrivateSessionSet(TSHttpTxn txnp, int
private_session);
+ /* Expose internal Base64 Encoding / Decoding */
+ tsapi size_t TSBase64Decode(const char *input, size_t length, unsigned char
*dst, size_t dst_size);
+ tsapi size_t TSBase64Encode(const char *input, size_t length, char *dst,
size_t dst_size);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */