home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / libc / src / base64.c next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.3 KB  |  404 lines

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