LCOV - code coverage report
Current view: directory - nsprpub/lib/libc/src - base64.c (source / functions) Found Hit Coverage
Test: app.info Lines: 151 130 86.1 %
Date: 2012-06-02 Functions: 11 11 100.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          104661 : encode3to4
      48                 : (
      49                 :     const unsigned char    *src,
      50                 :     unsigned char          *dest
      51                 : )
      52                 : {
      53          104661 :     PRUint32 b32 = (PRUint32)0;
      54          104661 :     PRIntn i, j = 18;
      55                 : 
      56          418644 :     for( i = 0; i < 3; i++ )
      57                 :     {
      58          313983 :         b32 <<= 8;
      59          313983 :         b32 |= (PRUint32)src[i];
      60                 :     }
      61                 : 
      62          523305 :     for( i = 0; i < 4; i++ )
      63                 :     {
      64          418644 :         dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
      65          418644 :         j -= 6;
      66                 :     }
      67                 : 
      68                 :     return;
      69                 : }
      70                 : 
      71                 : static void
      72            1728 : encode2to4
      73                 : (
      74                 :     const unsigned char    *src,
      75                 :     unsigned char          *dest
      76                 : )
      77                 : {
      78            1728 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
      79            1728 :     dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
      80            1728 :     dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
      81            1728 :     dest[3] = (unsigned char)'=';
      82                 :     return;
      83                 : }
      84                 : 
      85                 : static void
      86             789 : encode1to4
      87                 : (
      88                 :     const unsigned char    *src,
      89                 :     unsigned char          *dest
      90                 : )
      91                 : {
      92             789 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
      93             789 :     dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
      94             789 :     dest[2] = (unsigned char)'=';
      95             789 :     dest[3] = (unsigned char)'=';
      96                 :     return;
      97                 : }
      98                 : 
      99                 : static void
     100           12536 : encode
     101                 : (
     102                 :     const unsigned char    *src,
     103                 :     PRUint32                srclen,
     104                 :     unsigned char          *dest
     105                 : )
     106                 : {
     107          129733 :     while( srclen >= 3 )
     108                 :     {
     109          104661 :         encode3to4(src, dest);
     110          104661 :         src += 3;
     111          104661 :         dest += 4;
     112          104661 :         srclen -= 3;
     113                 :     }
     114                 : 
     115           12536 :     switch( srclen )
     116                 :     {
     117                 :         case 2:
     118            1728 :             encode2to4(src, dest);
     119            1728 :             break;
     120                 :         case 1:
     121             789 :             encode1to4(src, dest);
     122             789 :             break;
     123                 :         case 0:
     124           10019 :             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           12536 : PL_Base64Encode
     146                 : (
     147                 :     const char *src,
     148                 :     PRUint32    srclen,
     149                 :     char       *dest
     150                 : )
     151                 : {
     152           12536 :     if( 0 == srclen )
     153                 :     {
     154               1 :         size_t len = strlen(src);
     155               1 :         srclen = len;
     156                 :         /* Detect truncation. */
     157               1 :         if( srclen != len )
     158                 :         {
     159               0 :             return (char *)0;
     160                 :         }
     161                 :     }
     162                 : 
     163           12536 :     if( (char *)0 == dest )
     164                 :     {
     165                 :         PRUint32 destlen;
     166                 :         /* Ensure all PRUint32 values stay within range. */
     167             415 :         if( srclen > (PR_UINT32_MAX/4) * 3 )
     168                 :         {
     169               0 :             return (char *)0;
     170                 :         }
     171             415 :         destlen = ((srclen + 2)/3) * 4;
     172             415 :         dest = (char *)PR_MALLOC(destlen + 1);
     173             415 :         if( (char *)0 == dest )
     174                 :         {
     175               0 :             return (char *)0;
     176                 :         }
     177             415 :         dest[ destlen ] = (char)0; /* null terminate */
     178                 :     }
     179                 : 
     180           12536 :     encode((const unsigned char *)src, srclen, (unsigned char *)dest);
     181           12536 :     return dest;
     182                 : }
     183                 : 
     184                 : static PRInt32
     185          357277 : codetovalue
     186                 : (
     187                 :     unsigned char c
     188                 : )
     189                 : {
     190          357277 :     if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
     191                 :     {
     192          218231 :         return (PRInt32)(c - (unsigned char)'A');
     193                 :     }
     194          139046 :     else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
     195                 :     {
     196          108557 :         return ((PRInt32)(c - (unsigned char)'a') +26);
     197                 :     }
     198           30489 :     else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
     199                 :     {
     200           25442 :         return ((PRInt32)(c - (unsigned char)'0') +52);
     201                 :     }
     202            5047 :     else if( (unsigned char)'+' == c )
     203                 :     {
     204            1682 :         return (PRInt32)62;
     205                 :     }
     206            3365 :     else if( (unsigned char)'/' == c )
     207                 :     {
     208            3365 :         return (PRInt32)63;
     209                 :     }
     210                 :     else
     211                 :     {
     212               0 :         return -1;
     213                 :     }
     214                 : }
     215                 : 
     216                 : static PRStatus
     217           88533 : decode4to3
     218                 : (
     219                 :     const unsigned char    *src,
     220                 :     unsigned char          *dest
     221                 : )
     222                 : {
     223           88533 :     PRUint32 b32 = (PRUint32)0;
     224                 :     PRInt32 bits;
     225                 :     PRIntn i;
     226                 : 
     227          442665 :     for( i = 0; i < 4; i++ )
     228                 :     {
     229          354132 :         bits = codetovalue(src[i]);
     230          354132 :         if( bits < 0 )
     231                 :         {
     232               0 :             return PR_FAILURE;
     233                 :         }
     234                 : 
     235          354132 :         b32 <<= 6;
     236          354132 :         b32 |= bits;
     237                 :     }
     238                 : 
     239           88533 :     dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
     240           88533 :     dest[1] = (unsigned char)((b32 >>  8) & 0xFF);
     241           88533 :     dest[2] = (unsigned char)((b32      ) & 0xFF);
     242                 : 
     243           88533 :     return PR_SUCCESS;
     244                 : }
     245                 : 
     246                 : static PRStatus
     247             511 : decode3to2
     248                 : (
     249                 :     const unsigned char    *src,
     250                 :     unsigned char          *dest
     251                 : )
     252                 : {
     253             511 :     PRUint32 b32 = (PRUint32)0;
     254                 :     PRInt32 bits;
     255                 :     PRUint32 ubits;
     256                 : 
     257             511 :     bits = codetovalue(src[0]);
     258             511 :     if( bits < 0 )
     259                 :     {
     260               0 :         return PR_FAILURE;
     261                 :     }
     262                 : 
     263             511 :     b32 = (PRUint32)bits;
     264             511 :     b32 <<= 6;
     265                 : 
     266             511 :     bits = codetovalue(src[1]);
     267             511 :     if( bits < 0 )
     268                 :     {
     269               0 :         return PR_FAILURE;
     270                 :     }
     271                 : 
     272             511 :     b32 |= (PRUint32)bits;
     273             511 :     b32 <<= 4;
     274                 : 
     275             511 :     bits = codetovalue(src[2]);
     276             511 :     if( bits < 0 )
     277                 :     {
     278               0 :         return PR_FAILURE;
     279                 :     }
     280                 : 
     281             511 :     ubits = (PRUint32)bits;
     282             511 :     b32 |= (ubits >> 2);
     283                 : 
     284             511 :     dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
     285             511 :     dest[1] = (unsigned char)((b32     ) & 0xFF);
     286                 : 
     287             511 :     return PR_SUCCESS;
     288                 : }
     289                 : 
     290                 : static PRStatus
     291             806 : decode2to1
     292                 : (
     293                 :     const unsigned char    *src,
     294                 :     unsigned char          *dest
     295                 : )
     296                 : {
     297                 :     PRUint32 b32;
     298                 :     PRUint32 ubits;
     299                 :     PRInt32 bits;
     300                 : 
     301             806 :     bits = codetovalue(src[0]);
     302             806 :     if( bits < 0 )
     303                 :     {
     304               0 :         return PR_FAILURE;
     305                 :     }
     306                 : 
     307             806 :     ubits = (PRUint32)bits;
     308             806 :     b32 = (ubits << 2);
     309                 : 
     310             806 :     bits = codetovalue(src[1]);
     311             806 :     if( bits < 0 )
     312                 :     {
     313               0 :         return PR_FAILURE;
     314                 :     }
     315                 : 
     316             806 :     ubits = (PRUint32)bits;
     317             806 :     b32 |= (ubits >> 4);
     318                 : 
     319             806 :     dest[0] = (unsigned char)b32;
     320                 : 
     321             806 :     return PR_SUCCESS;
     322                 : }
     323                 : 
     324                 : static PRStatus
     325            4099 : decode
     326                 : (
     327                 :     const unsigned char    *src,
     328                 :     PRUint32                srclen,
     329                 :     unsigned char          *dest
     330                 : )
     331                 : {
     332                 :     PRStatus rv;
     333                 : 
     334           96731 :     while( srclen >= 4 )
     335                 :     {
     336           88533 :         rv = decode4to3(src, dest);
     337           88533 :         if( PR_SUCCESS != rv )
     338                 :         {
     339               0 :             return PR_FAILURE;
     340                 :         }
     341                 : 
     342           88533 :         src += 4;
     343           88533 :         dest += 3;
     344           88533 :         srclen -= 4;
     345                 :     }
     346                 : 
     347            4099 :     switch( srclen )
     348                 :     {
     349                 :         case 3:
     350             511 :             rv = decode3to2(src, dest);
     351             511 :             break;
     352                 :         case 2:
     353             806 :             rv = decode2to1(src, dest);
     354             806 :             break;
     355                 :         case 1:
     356               0 :             rv = PR_FAILURE;
     357               0 :             break;
     358                 :         case 0:
     359            2782 :             rv = PR_SUCCESS;
     360            2782 :             break;
     361                 :         default:
     362               0 :             PR_NOT_REACHED("coding error");
     363                 :     }
     364                 : 
     365            4099 :     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            4099 : PL_Base64Decode
     383                 : (
     384                 :     const char *src,
     385                 :     PRUint32    srclen,
     386                 :     char       *dest
     387                 : )
     388                 : {
     389                 :     PRStatus status;
     390            4099 :     PRBool allocated = PR_FALSE;
     391                 : 
     392            4099 :     if( (char *)0 == src )
     393                 :     {
     394               0 :         return (char *)0;
     395                 :     }
     396                 : 
     397            4099 :     if( 0 == srclen )
     398                 :     {
     399               9 :         size_t len = strlen(src);
     400               9 :         srclen = len;
     401                 :         /* Detect truncation. */
     402               9 :         if( srclen != len )
     403                 :         {
     404               0 :             return (char *)0;
     405                 :         }
     406                 :     }
     407                 : 
     408            4099 :     if( srclen && (0 == (srclen & 3)) )
     409                 :     {
     410            4090 :         if( (char)'=' == src[ srclen-1 ] )
     411                 :         {
     412            1317 :             if( (char)'=' == src[ srclen-2 ] )
     413                 :             {
     414             806 :                 srclen -= 2;
     415                 :             }
     416                 :             else
     417                 :             {
     418             511 :                 srclen -= 1;
     419                 :             }
     420                 :         }
     421                 :     }
     422                 : 
     423            4099 :     if( (char *)0 == dest )
     424                 :     {
     425                 :         /* The following computes ((srclen * 3) / 4) without overflow. */
     426            3027 :         PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4;
     427            3027 :         dest = (char *)PR_MALLOC(destlen + 1);
     428            3027 :         if( (char *)0 == dest )
     429                 :         {
     430               0 :             return (char *)0;
     431                 :         }
     432            3027 :         dest[ destlen ] = (char)0; /* null terminate */
     433            3027 :         allocated = PR_TRUE;
     434                 :     }
     435                 : 
     436            4099 :     status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
     437            4099 :     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            4099 :     return dest;
     448                 : }

Generated by: LCOV version 1.7