LCOV - app.info - nsprpub/lib/libc/src/base64.c

LCOV - code coverage report
| Current view: | directory - nsprpub/lib/libc/src - base64.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 151 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 11 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is the Netscape Portable Runtime (NSPR).
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998-2000
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "plbase64.h"
          39                 : #include "prlog.h" /* For PR_NOT_REACHED */
          40                 : #include "prmem.h" /* for malloc / PR_MALLOC */
          41                 :
          42                 : #include <string.h> /* for strlen */
          43                 :
          44                 : static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
          45                 :
          46                 : static void
          47               0 : encode3to4
          48                 : (
          49                 :     const unsigned char    *src,
          50                 :     unsigned char          *dest
          51                 : )
          52                 : {
          53               0 :     PRUint32 b32 = (PRUint32)0;
          54               0 :     PRIntn i, j = 18;
          55                 :
          56               0 :     for( i = 0; i < 3; i++ )
          57                 :     {
          58               0 :         b32 <<= 8;
          59               0 :         b32 |= (PRUint32)src[i];
          60                 :     }
          61                 :
          62               0 :     for( i = 0; i < 4; i++ )
          63                 :     {
          64               0 :         dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
          65               0 :         j -= 6;
          66                 :     }
          67                 :
          68                 :     return;
          69                 : }
          70                 :
          71                 : static void
          72               0 : encode2to4
          73                 : (
          74                 :     const unsigned char    *src,
          75                 :     unsigned char          *dest
          76                 : )
          77                 : {
          78               0 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
          79               0 :     dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
          80               0 :     dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
          81               0 :     dest[3] = (unsigned char)'=';
          82                 :     return;
          83                 : }
          84                 :
          85                 : static void
          86               0 : encode1to4
          87                 : (
          88                 :     const unsigned char    *src,
          89                 :     unsigned char          *dest
          90                 : )
          91                 : {
          92               0 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
          93               0 :     dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
          94               0 :     dest[2] = (unsigned char)'=';
          95               0 :     dest[3] = (unsigned char)'=';
          96                 :     return;
          97                 : }
          98                 :
          99                 : static void
         100               0 : encode
         101                 : (
         102                 :     const unsigned char    *src,
         103                 :     PRUint32                srclen,
         104                 :     unsigned char          *dest
         105                 : )
         106                 : {
         107               0 :     while( srclen >= 3 )
         108                 :     {
         109               0 :         encode3to4(src, dest);
         110               0 :         src += 3;
         111               0 :         dest += 4;
         112               0 :         srclen -= 3;
         113                 :     }
         114                 :
         115               0 :     switch( srclen )
         116                 :     {
         117                 :         case 2:
         118               0 :             encode2to4(src, dest);
         119               0 :             break;
         120                 :         case 1:
         121               0 :             encode1to4(src, dest);
         122               0 :             break;
         123                 :         case 0:
         124               0 :             break;
         125                 :         default:
         126               0 :             PR_NOT_REACHED("coding error");
         127                 :     }
         128                 :
         129                 :     return;
         130                 : }
         131                 :
         132                 : /*
         133                 :  * PL_Base64Encode
         134                 :  *
         135                 :  * If the destination argument is NULL, a return buffer is
         136                 :  * allocated, and the data therein will be null-terminated.
         137                 :  * If the destination argument is not NULL, it is assumed to
         138                 :  * be of sufficient size, and the contents will not be null-
         139                 :  * terminated by this routine.
         140                 :  *
         141                 :  * Returns null if the allocation fails.
         142                 :  */
         143                 :
         144                 : PR_IMPLEMENT(char *)
         145               0 : PL_Base64Encode
         146                 : (
         147                 :     const char *src,
         148                 :     PRUint32    srclen,
         149                 :     char       *dest
         150                 : )
         151                 : {
         152               0 :     if( 0 == srclen )
         153                 :     {
         154               0 :         size_t len = strlen(src);
         155               0 :         srclen = len;
         156                 :         /* Detect truncation. */
         157               0 :         if( srclen != len )
         158                 :         {
         159               0 :             return (char *)0;
         160                 :         }
         161                 :     }
         162                 :
         163               0 :     if( (char *)0 == dest )
         164                 :     {
         165                 :         PRUint32 destlen;
         166                 :         /* Ensure all PRUint32 values stay within range. */
         167               0 :         if( srclen > (PR_UINT32_MAX/4) * 3 )
         168                 :         {
         169               0 :             return (char *)0;
         170                 :         }
         171               0 :         destlen = ((srclen + 2)/3) * 4;
         172               0 :         dest = (char *)PR_MALLOC(destlen + 1);
         173               0 :         if( (char *)0 == dest )
         174                 :         {
         175               0 :             return (char *)0;
         176                 :         }
         177               0 :         dest[ destlen ] = (char)0; /* null terminate */
         178                 :     }
         179                 :
         180               0 :     encode((const unsigned char *)src, srclen, (unsigned char *)dest);
         181               0 :     return dest;
         182                 : }
         183                 :
         184                 : static PRInt32
         185               0 : codetovalue
         186                 : (
         187                 :     unsigned char c
         188                 : )
         189                 : {
         190               0 :     if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
         191                 :     {
         192               0 :         return (PRInt32)(c - (unsigned char)'A');
         193                 :     }
         194               0 :     else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
         195                 :     {
         196               0 :         return ((PRInt32)(c - (unsigned char)'a') +26);
         197                 :     }
         198               0 :     else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
         199                 :     {
         200               0 :         return ((PRInt32)(c - (unsigned char)'0') +52);
         201                 :     }
         202               0 :     else if( (unsigned char)'+' == c )
         203                 :     {
         204               0 :         return (PRInt32)62;
         205                 :     }
         206               0 :     else if( (unsigned char)'/' == c )
         207                 :     {
         208               0 :         return (PRInt32)63;
         209                 :     }
         210                 :     else
         211                 :     {
         212               0 :         return -1;
         213                 :     }
         214                 : }
         215                 :
         216                 : static PRStatus
         217               0 : decode4to3
         218                 : (
         219                 :     const unsigned char    *src,
         220                 :     unsigned char          *dest
         221                 : )
         222                 : {
         223               0 :     PRUint32 b32 = (PRUint32)0;
         224                 :     PRInt32 bits;
         225                 :     PRIntn i;
         226                 :
         227               0 :     for( i = 0; i < 4; i++ )
         228                 :     {
         229               0 :         bits = codetovalue(src[i]);
         230               0 :         if( bits < 0 )
         231                 :         {
         232               0 :             return PR_FAILURE;
         233                 :         }
         234                 :
         235               0 :         b32 <<= 6;
         236               0 :         b32 |= bits;
         237                 :     }
         238                 :
         239               0 :     dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
         240               0 :     dest[1] = (unsigned char)((b32 >>  8) & 0xFF);
         241               0 :     dest[2] = (unsigned char)((b32      ) & 0xFF);
         242                 :
         243               0 :     return PR_SUCCESS;
         244                 : }
         245                 :
         246                 : static PRStatus
         247               0 : decode3to2
         248                 : (
         249                 :     const unsigned char    *src,
         250                 :     unsigned char          *dest
         251                 : )
         252                 : {
         253               0 :     PRUint32 b32 = (PRUint32)0;
         254                 :     PRInt32 bits;
         255                 :     PRUint32 ubits;
         256                 :
         257               0 :     bits = codetovalue(src[0]);
         258               0 :     if( bits < 0 )
         259                 :     {
         260               0 :         return PR_FAILURE;
         261                 :     }
         262                 :
         263               0 :     b32 = (PRUint32)bits;
         264               0 :     b32 <<= 6;
         265                 :
         266               0 :     bits = codetovalue(src[1]);
         267               0 :     if( bits < 0 )
         268                 :     {
         269               0 :         return PR_FAILURE;
         270                 :     }
         271                 :
         272               0 :     b32 |= (PRUint32)bits;
         273               0 :     b32 <<= 4;
         274                 :
         275               0 :     bits = codetovalue(src[2]);
         276               0 :     if( bits < 0 )
         277                 :     {
         278               0 :         return PR_FAILURE;
         279                 :     }
         280                 :
         281               0 :     ubits = (PRUint32)bits;
         282               0 :     b32 |= (ubits >> 2);
         283                 :
         284               0 :     dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
         285               0 :     dest[1] = (unsigned char)((b32     ) & 0xFF);
         286                 :
         287               0 :     return PR_SUCCESS;
         288                 : }
         289                 :
         290                 : static PRStatus
         291               0 : decode2to1
         292                 : (
         293                 :     const unsigned char    *src,
         294                 :     unsigned char          *dest
         295                 : )
         296                 : {
         297                 :     PRUint32 b32;
         298                 :     PRUint32 ubits;
         299                 :     PRInt32 bits;
         300                 :
         301               0 :     bits = codetovalue(src[0]);
         302               0 :     if( bits < 0 )
         303                 :     {
         304               0 :         return PR_FAILURE;
         305                 :     }
         306                 :
         307               0 :     ubits = (PRUint32)bits;
         308               0 :     b32 = (ubits << 2);
         309                 :
         310               0 :     bits = codetovalue(src[1]);
         311               0 :     if( bits < 0 )
         312                 :     {
         313               0 :         return PR_FAILURE;
         314                 :     }
         315                 :
         316               0 :     ubits = (PRUint32)bits;
         317               0 :     b32 |= (ubits >> 4);
         318                 :
         319               0 :     dest[0] = (unsigned char)b32;
         320                 :
         321               0 :     return PR_SUCCESS;
         322                 : }
         323                 :
         324                 : static PRStatus
         325               0 : decode
         326                 : (
         327                 :     const unsigned char    *src,
         328                 :     PRUint32                srclen,
         329                 :     unsigned char          *dest
         330                 : )
         331                 : {
         332                 :     PRStatus rv;
         333                 :
         334               0 :     while( srclen >= 4 )
         335                 :     {
         336               0 :         rv = decode4to3(src, dest);
         337               0 :         if( PR_SUCCESS != rv )
         338                 :         {
         339               0 :             return PR_FAILURE;
         340                 :         }
         341                 :
         342               0 :         src += 4;
         343               0 :         dest += 3;
         344               0 :         srclen -= 4;
         345                 :     }
         346                 :
         347               0 :     switch( srclen )
         348                 :     {
         349                 :         case 3:
         350               0 :             rv = decode3to2(src, dest);
         351               0 :             break;
         352                 :         case 2:
         353               0 :             rv = decode2to1(src, dest);
         354               0 :             break;
         355                 :         case 1:
         356               0 :             rv = PR_FAILURE;
         357               0 :             break;
         358                 :         case 0:
         359               0 :             rv = PR_SUCCESS;
         360               0 :             break;
         361                 :         default:
         362               0 :             PR_NOT_REACHED("coding error");
         363                 :     }
         364                 :
         365               0 :     return rv;
         366                 : }
         367                 :
         368                 : /*
         369                 :  * PL_Base64Decode
         370                 :  *
         371                 :  * If the destination argument is NULL, a return buffer is
         372                 :  * allocated and the data therein will be null-terminated.
         373                 :  * If the destination argument is not null, it is assumed
         374                 :  * to be of sufficient size, and the data will not be null-
         375                 :  * terminated by this routine.
         376                 :  *
         377                 :  * Returns null if the allocation fails, or if the source string is
         378                 :  * not well-formed.
         379                 :  */
         380                 :
         381                 : PR_IMPLEMENT(char *)
         382               0 : PL_Base64Decode
         383                 : (
         384                 :     const char *src,
         385                 :     PRUint32    srclen,
         386                 :     char       *dest
         387                 : )
         388                 : {
         389                 :     PRStatus status;
         390               0 :     PRBool allocated = PR_FALSE;
         391                 :
         392               0 :     if( (char *)0 == src )
         393                 :     {
         394               0 :         return (char *)0;
         395                 :     }
         396                 :
         397               0 :     if( 0 == srclen )
         398                 :     {
         399               0 :         size_t len = strlen(src);
         400               0 :         srclen = len;
         401                 :         /* Detect truncation. */
         402               0 :         if( srclen != len )
         403                 :         {
         404               0 :             return (char *)0;
         405                 :         }
         406                 :     }
         407                 :
         408               0 :     if( srclen && (0 == (srclen & 3)) )
         409                 :     {
         410               0 :         if( (char)'=' == src[ srclen-1 ] )
         411                 :         {
         412               0 :             if( (char)'=' == src[ srclen-2 ] )
         413                 :             {
         414               0 :                 srclen -= 2;
         415                 :             }
         416                 :             else
         417                 :             {
         418               0 :                 srclen -= 1;
         419                 :             }
         420                 :         }
         421                 :     }
         422                 :
         423               0 :     if( (char *)0 == dest )
         424                 :     {
         425                 :         /* The following computes ((srclen * 3) / 4) without overflow. */
         426               0 :         PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4;
         427               0 :         dest = (char *)PR_MALLOC(destlen + 1);
         428               0 :         if( (char *)0 == dest )
         429                 :         {
         430               0 :             return (char *)0;
         431                 :         }
         432               0 :         dest[ destlen ] = (char)0; /* null terminate */
         433               0 :         allocated = PR_TRUE;
         434                 :     }
         435                 :
         436               0 :     status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
         437               0 :     if( PR_SUCCESS != status )
         438                 :     {
         439               0 :         if( PR_TRUE == allocated )
         440                 :         {
         441               0 :             PR_DELETE(dest);
         442                 :         }
         443                 :
         444               0 :         return (char *)0;
         445                 :     }
         446                 :
         447               0 :     return dest;
         448                 : }

Generated by: LCOV version 1.7