• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_base64.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /*
00025  * Base64 encoding and decoding as according to RFC1521.  Similar to uudecode.
00026  *
00027  * RFC 1521 requires inserting line breaks for long lines.  The basic web
00028  * authentication scheme does not require them.  This implementation is
00029  * intended for web-related use, and line breaks are not implemented.
00030  *
00031  * These routines return char*'s to malloc-ed strings.  The caller is
00032  * responsible for freeing the strings.
00033  */
00034 #include "libts.h"
00035 #include "ink_assert.h"
00036 
00037 // TODO: The code here seems a bit klunky, and could probably be improved a bit.
00038 
00039 bool
00040 ats_base64_encode(const unsigned char *inBuffer, size_t inBufferSize, char *outBuffer, size_t outBufSize, size_t *length)
00041 {
00042   static const char _codes[66] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00043   char *obuf = outBuffer;
00044   char in_tail[4];
00045 
00046   if (outBufSize < ATS_BASE64_ENCODE_DSTLEN(inBufferSize))
00047     return false;
00048 
00049   while (inBufferSize > 2) {
00050     *obuf++ = _codes[(inBuffer[0] >> 2) & 077];
00051     *obuf++ = _codes[((inBuffer[0] & 03) << 4) | ((inBuffer[1] >> 4) & 017)];
00052     *obuf++ = _codes[((inBuffer[1] & 017) << 2) | ((inBuffer[2] >> 6) & 017)];
00053     *obuf++ = _codes[inBuffer[2] & 077];
00054 
00055     inBufferSize -= 3;
00056     inBuffer += 3;
00057   }
00058 
00059   /*
00060    * We've done all the input groups of three chars.  We're left
00061    * with 0, 1, or 2 input chars.  We have to add zero-bits to the
00062    * right if we don't have enough input chars.
00063    * If 0 chars left, we're done.
00064    * If 1 char left, form 2 output chars, and add 2 pad chars to output.
00065    * If 2 chars left, form 3 output chars, add 1 pad char to output.
00066    */
00067   if (inBufferSize == 0) {
00068     *obuf = '\0';
00069     if (length)
00070       *length = (obuf - outBuffer);
00071   } else {
00072     memset(in_tail, 0, sizeof(in_tail));
00073     memcpy(in_tail, inBuffer, inBufferSize);
00074 
00075     *(obuf) = _codes[(in_tail[0] >> 2) & 077];
00076     *(obuf + 1) = _codes[((in_tail[0] & 03) << 4) | ((in_tail[1] >> 4) & 017)];
00077     *(obuf + 2) = _codes[((in_tail[1] & 017) << 2) | ((in_tail[2] >> 6) & 017)];
00078     *(obuf + 3) = _codes[in_tail[2] & 077];
00079 
00080     if (inBufferSize == 1)
00081       *(obuf + 2) = '=';
00082     *(obuf + 3) = '=';
00083     *(obuf + 4) = '\0';
00084 
00085     if (length)
00086       *length = (obuf + 4) - outBuffer;
00087   }
00088 
00089   return true;
00090 }
00091 
00092 bool
00093 ats_base64_encode(const char *inBuffer, size_t inBufferSize, char *outBuffer, size_t outBufSize, size_t *length)
00094 {
00095   return ats_base64_encode((const unsigned char *)inBuffer, inBufferSize, outBuffer, outBufSize, length);
00096 }
00097 
00098 
00099 /*-------------------------------------------------------------------------
00100   This is a reentrant, and malloc free implemetnation of ats_base64_decode.
00101   -------------------------------------------------------------------------*/
00102 #ifdef DECODE
00103 #undef DECODE
00104 #endif
00105 
00106 #define DECODE(x) printableToSixBit[(unsigned char)x]
00107 #define MAX_PRINT_VAL 63
00108 
00109 /* Converts a printable character to it's six bit representation */
00110 const unsigned char printableToSixBit[256] = {
00111   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00112   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 62, 64, 63,
00113   52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00114   10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63, 64, 26, 27,
00115   28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
00116   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00117   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00118   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00119   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00120   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00121   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
00122 };
00123 
00124 bool
00125 ats_base64_decode(const char *inBuffer, size_t inBufferSize, unsigned char *outBuffer, size_t outBufSize, size_t *length)
00126 {
00127   size_t inBytes = 0;
00128   size_t decodedBytes = 0;
00129   unsigned char *buf = outBuffer;
00130   int inputBytesDecoded = 0;
00131 
00132   // Make sure there is sufficient space in the output buffer
00133   if (outBufSize < ATS_BASE64_DECODE_DSTLEN(inBufferSize))
00134     return false;
00135 
00136   // Ignore any trailing ='s or other undecodable characters.
00137   // TODO: Perhaps that ought to be an error instead?
00138   while (printableToSixBit[(uint8_t)inBuffer[inBytes]] <= MAX_PRINT_VAL)
00139     ++inBytes;
00140 
00141   for (size_t i = 0; i < inBytes; i += 4) {
00142     buf[0] = (unsigned char) (DECODE(inBuffer[0]) << 2 | DECODE(inBuffer[1]) >> 4);
00143     buf[1] = (unsigned char) (DECODE(inBuffer[1]) << 4 | DECODE(inBuffer[2]) >> 2);
00144     buf[2] = (unsigned char) (DECODE(inBuffer[2]) << 6 | DECODE(inBuffer[3]));
00145 
00146     buf += 3;
00147     inBuffer += 4;
00148     decodedBytes += 3;
00149     inputBytesDecoded += 4;
00150   }
00151 
00152   // Check to see if we decoded a multiple of 4 four
00153   //    bytes
00154   if ((inBytes - inputBytesDecoded) & 0x3) {
00155     if (DECODE(inBuffer[-2]) > MAX_PRINT_VAL) {
00156       decodedBytes -= 2;
00157     } else {
00158       decodedBytes -= 1;
00159     }
00160   }
00161   outBuffer[decodedBytes] = '\0';
00162 
00163   if (length)
00164     *length = decodedBytes;
00165 
00166   return true;
00167 }

Generated by  doxygen 1.7.1