nssb64e.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:21k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * Base64 encoding (binary to ascii).
  35.  *
  36.  * $Id: nssb64e.c,v 1.1 2000/04/06 00:39:49 repka%netscape.com Exp $
  37.  */
  38. #include "nssb64.h"
  39. #include "nspr.h"
  40. #include "secitem.h"
  41. #include "secerr.h"
  42. /*
  43.  * XXX See the big comment at the top of nssb64d.c about moving the
  44.  * bulk of this code over into NSPR (the PL part).  It all applies
  45.  * here but I didn't want to duplicate it, to avoid divergence problems.
  46.  */ 
  47. /*
  48.  **************************************************************
  49.  * XXX Beginning of base64 encoding code to be moved into NSPR.
  50.  */
  51. struct PLBase64EncodeStateStr {
  52.     unsigned chunks;
  53.     unsigned saved;
  54.     unsigned char buf[3];
  55. };
  56. /*
  57.  * This typedef would belong in the NSPR header file (i.e. plbase64.h).
  58.  */
  59. typedef struct PLBase64EncoderStr PLBase64Encoder;
  60. /*
  61.  * The following implementation of base64 encoding was based on code
  62.  * found in libmime (specifically, in mimeenc.c).  It has been adapted to
  63.  * use PR types and naming as well as to provide other necessary semantics
  64.  * (like buffer-in/buffer-out in addition to "streaming" without undue
  65.  * performance hit of extra copying if you made the buffer versions
  66.  * use the output_fn).  It also incorporates some aspects of the current
  67.  * NSPR base64 encoding code.  As such, you may find similarities to
  68.  * both of those implementations.  I tried to use names that reflected
  69.  * the original code when possible.  For this reason you may find some
  70.  * inconsistencies -- libmime used lots of "in" and "out" whereas the
  71.  * NSPR version uses "src" and "dest"; sometimes I changed one to the other
  72.  * and sometimes I left them when I thought the subroutines were at least
  73.  * self-consistent.
  74.  */
  75. PR_BEGIN_EXTERN_C
  76. /*
  77.  * Opaque object used by the encoder to store state.
  78.  */
  79. struct PLBase64EncoderStr {
  80.     /*
  81.      * The one or two bytes pending.  (We need 3 to create a "token",
  82.      * and hold the leftovers here.  in_buffer_count is *only* ever
  83.      * 0, 1, or 2.
  84.      */
  85.     unsigned char in_buffer[2];
  86.     int in_buffer_count;
  87.     /*
  88.      * If the caller wants linebreaks added, line_length specifies
  89.      * where they come out.  It must be a multiple of 4; if the caller
  90.      * provides one that isn't, we round it down to the nearest
  91.      * multiple of 4.
  92.      *
  93.      * The value of current_column counts how many characters have been
  94.      * added since the last linebreaks (or since the beginning, on the
  95.      * first line).  It is also always a multiple of 4; it is unused when
  96.      * line_length is 0.
  97.      */ 
  98.     PRUint32 line_length;
  99.     PRUint32 current_column;
  100.     /*
  101.      * Where to write the encoded data (used when streaming, not when
  102.      * doing all in-memory (buffer) operations).
  103.      *
  104.      * Note that this definition is chosen to be compatible with PR_Write.
  105.      */
  106.     PRInt32 (*output_fn) (void *output_arg, const char *buf, PRInt32 size);
  107.     void *output_arg;
  108.     /*
  109.      * Where the encoded output goes -- either temporarily (in the streaming
  110.      * case, staged here before it goes to the output function) or what will
  111.      * be the entire buffered result for users of the buffer version.
  112.      */
  113.     char *output_buffer;
  114.     PRUint32 output_buflen; /* the total length of allocated buffer */
  115.     PRUint32 output_length; /* the length that is currently populated */
  116. };
  117. PR_END_EXTERN_C
  118. /*
  119.  * Table to convert a binary value to its corresponding ascii "code".
  120.  */
  121. static unsigned char base64_valuetocode[64] =
  122.     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  123. #define B64_PAD '='
  124. #define B64_CR 'r'
  125. #define B64_LF 'n'
  126. static PRStatus
  127. pl_base64_encode_buffer (PLBase64Encoder *data, const unsigned char *in,
  128.  PRUint32 size)
  129. {
  130.     const unsigned char *end = in + size;
  131.     char *out = data->output_buffer + data->output_length;
  132.     int i = data->in_buffer_count;
  133.     PRUint32 n = 0;
  134.     int off;
  135.     PRUint32 output_threshold;
  136.     /* If this input buffer is too small, wait until next time. */
  137.     if (size < (3 - i)) {
  138. data->in_buffer[i++] = in[0];
  139. if (size > 1)
  140.     data->in_buffer[i++] = in[1];
  141. PR_ASSERT(i < 3);
  142. data->in_buffer_count = i;
  143. return PR_SUCCESS;
  144.     }
  145.     /* If there are bytes that were put back last time, take them now. */
  146.     if (i > 0) {
  147. n = data->in_buffer[0];
  148. if (i > 1)
  149.     n = (n << 8) | data->in_buffer[1];
  150. data->in_buffer_count = 0;
  151.     }
  152.     /* If our total is not a multiple of three, put one or two bytes back. */
  153.     off = (size + i) % 3;
  154.     if (off > 0) {
  155. size -= off;
  156. data->in_buffer[0] = in[size];
  157. if (off > 1)
  158.     data->in_buffer[1] = in[size + 1];
  159. data->in_buffer_count = off;
  160. end -= off;
  161.     }
  162.     output_threshold = data->output_buflen - 3;
  163.     /*
  164.      * Populate the output buffer with base64 data, one line (or buffer)
  165.      * at a time.
  166.      */
  167.     while (in < end) {
  168. int j, k;
  169. while (i < 3) {
  170.     n = (n << 8) | *in++;
  171.     i++;
  172. }
  173. i = 0;
  174. if (data->line_length > 0) {
  175.     if (data->current_column >= data->line_length) {
  176. data->current_column = 0;
  177. *out++ = B64_CR;
  178. *out++ = B64_LF;
  179. data->output_length += 2;
  180.     }
  181.     data->current_column += 4; /* the bytes we are about to add */
  182. }
  183. for (j = 18; j >= 0; j -= 6) {
  184.     k = (n >> j) & 0x3F;
  185.     *out++ = base64_valuetocode[k];
  186. }
  187. n = 0;
  188. data->output_length += 4;
  189. if (data->output_length >= output_threshold) {
  190.     PR_ASSERT(data->output_length <= data->output_buflen);
  191.     if (data->output_fn != NULL) {
  192. PRInt32 output_result;
  193. output_result = data->output_fn (data->output_arg,
  194.  data->output_buffer,
  195.  (PRInt32) data->output_length);
  196. if (output_result < 0)
  197.     return PR_FAILURE;
  198. out = data->output_buffer;
  199. data->output_length = 0;
  200.     } else {
  201. /*
  202.  * Check that we are about to exit the loop.  (Since we
  203.  * are over the threshold, there isn't enough room in the
  204.  * output buffer for another trip around.)
  205.  */
  206. PR_ASSERT(in == end);
  207. if (in < end) {
  208.     PR_SetError (PR_BUFFER_OVERFLOW_ERROR, 0);
  209.     return PR_FAILURE;
  210. }
  211.     }
  212. }
  213.     }
  214.     return PR_SUCCESS;
  215. }
  216. static PRStatus
  217. pl_base64_encode_flush (PLBase64Encoder *data)
  218. {
  219.     int i = data->in_buffer_count;
  220.     if (i == 0 && data->output_length == 0)
  221. return PR_SUCCESS;
  222.     if (i > 0) {
  223. char *out = data->output_buffer + data->output_length;
  224. PRUint32 n;
  225. int j, k;
  226. n = ((PRUint32) data->in_buffer[0]) << 16;
  227. if (i > 1)
  228.     n |= ((PRUint32) data->in_buffer[1] << 8);
  229. data->in_buffer_count = 0;
  230. if (data->line_length > 0) {
  231.     if (data->current_column >= data->line_length) {
  232. data->current_column = 0;
  233. *out++ = B64_CR;
  234. *out++ = B64_LF;
  235. data->output_length += 2;
  236.     }
  237. }
  238. /*
  239.  * This will fill in more than we really have data for, but the
  240.  * valid parts will end up in the correct position and the extras
  241.  * will be over-written with pad characters below.
  242.  */
  243. for (j = 18; j >= 0; j -= 6) {
  244.     k = (n >> j) & 0x3F;
  245.     *out++ = base64_valuetocode[k];
  246. }
  247. /* Pad with equal-signs. */
  248. if (i == 1)
  249.     out[-2] = B64_PAD;
  250. out[-1] = B64_PAD;
  251. data->output_length += 4;
  252.     }
  253.     if (data->output_fn != NULL) {
  254. PRInt32 output_result;
  255. output_result = data->output_fn (data->output_arg, data->output_buffer,
  256.  (PRInt32) data->output_length);
  257. data->output_length = 0;
  258. if (output_result < 0)
  259.     return PR_FAILURE;
  260.     }
  261.     return PR_SUCCESS;
  262. }
  263. /*
  264.  * The maximum space needed to hold the output of the encoder given input
  265.  * data of length "size", and allowing for CRLF added at least every
  266.  * line_length bytes (we will add it at nearest lower multiple of 4).
  267.  * There is no trailing CRLF.
  268.  */
  269. static PRUint32
  270. PL_Base64MaxEncodedLength (PRUint32 size, PRUint32 line_length)
  271. {
  272.     PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder;
  273.     tokens = (size + 2) / 3;
  274.     if (line_length == 0)
  275. return tokens * 4;
  276.     if (line_length < 4) /* too small! */
  277. line_length = 4;
  278.     tokens_per_line = line_length / 4;
  279.     full_lines = tokens / tokens_per_line;
  280.     remainder = (tokens - (full_lines * tokens_per_line)) * 4;
  281.     line_break_chars = full_lines * 2;
  282.     if (remainder == 0)
  283. line_break_chars -= 2;
  284.     return (full_lines * tokens_per_line * 4) + line_break_chars + remainder;
  285. }
  286. /*
  287.  * A distinct internal creation function for the buffer version to use.
  288.  * (It does not want to specify an output_fn, and we want the normal
  289.  * Create function to require that.)  All common initialization of the
  290.  * encoding context should be done *here*.
  291.  *
  292.  * Save "line_length", rounded down to nearest multiple of 4 (if not
  293.  * already even multiple).  Allocate output_buffer, if not provided --
  294.  * based on given size if specified, otherwise based on line_length.
  295.  */
  296. static PLBase64Encoder *
  297. pl_base64_create_encoder (PRUint32 line_length, char *output_buffer,
  298.   PRUint32 output_buflen)
  299. {
  300.     PLBase64Encoder *data;
  301.     PRUint32 line_tokens;
  302.     data = PR_NEWZAP(PLBase64Encoder);
  303.     if (data == NULL)
  304. return NULL;
  305.     if (line_length > 0 && line_length < 4) /* too small! */
  306. line_length = 4;
  307.     line_tokens = line_length / 4;
  308.     data->line_length = line_tokens * 4;
  309.     if (output_buffer == NULL) {
  310. if (output_buflen == 0) {
  311.     if (data->line_length > 0) /* need to include room for CRLF */
  312. output_buflen = data->line_length + 2;
  313.     else
  314. output_buflen = 64; /* XXX what is a good size? */
  315. }
  316. output_buffer = (char *) PR_Malloc(output_buflen);
  317. if (output_buffer == NULL) {
  318.     PR_Free(data);
  319.     return NULL;
  320. }
  321.     }
  322.     data->output_buffer = output_buffer;
  323.     data->output_buflen = output_buflen;
  324.     return data;
  325. }
  326. /*
  327.  * Function to start a base64 encoding context.
  328.  * An "output_fn" is required; the "output_arg" parameter to that is optional.
  329.  * If linebreaks in the encoded output are desired, "line_length" specifies
  330.  * where to place them -- it will be rounded down to the nearest multiple of 4
  331.  * (if it is not already an even multiple of 4).  If it is zero, no linebreaks
  332.  * will be added.  (FYI, a linebreak is CRLF -- two characters.)
  333.  */
  334. static PLBase64Encoder *
  335. PL_CreateBase64Encoder (PRInt32 (*output_fn) (void *, const char *, PRInt32),
  336. void *output_arg, PRUint32 line_length)
  337. {
  338.     PLBase64Encoder *data;
  339.     if (output_fn == NULL) {
  340. PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
  341. return NULL;
  342.     }
  343.     data = pl_base64_create_encoder (line_length, NULL, 0);
  344.     if (data == NULL)
  345. return NULL;
  346.     data->output_fn = output_fn;
  347.     data->output_arg = output_arg;
  348.     return data;
  349. }
  350. /*
  351.  * Push data through the encoder, causing the output_fn (provided to Create)
  352.  * to be called with the encoded data.
  353.  */
  354. static PRStatus
  355. PL_UpdateBase64Encoder (PLBase64Encoder *data, const unsigned char *buffer,
  356. PRUint32 size)
  357. {
  358.     /* XXX Should we do argument checking only in debug build? */
  359.     if (data == NULL || buffer == NULL || size == 0) {
  360. PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
  361. return PR_FAILURE;
  362.     }
  363.     return pl_base64_encode_buffer (data, buffer, size);
  364. }
  365. /*
  366.  * When you're done encoding, call this to free the data.  If "abort_p"
  367.  * is false, then calling this may cause the output_fn to be called
  368.  * one last time (as the last buffered data is flushed out).
  369.  */
  370. static PRStatus
  371. PL_DestroyBase64Encoder (PLBase64Encoder *data, PRBool abort_p)
  372. {
  373.     PRStatus status = PR_SUCCESS;
  374.     /* XXX Should we do argument checking only in debug build? */
  375.     if (data == NULL) {
  376. PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
  377. return PR_FAILURE;
  378.     }
  379.     /* Flush out the last few buffered characters. */
  380.     if (!abort_p)
  381. status = pl_base64_encode_flush (data);
  382.     if (data->output_buffer != NULL)
  383. PR_Free(data->output_buffer);
  384.     PR_Free(data);
  385.     return status;
  386. }
  387. /*
  388.  * Perform base64 encoding from an input buffer to an output buffer.
  389.  * The output buffer can be provided (as "dest"); you can also pass in
  390.  * a NULL and this function will allocate a buffer large enough for you,
  391.  * and return it.  If you do provide the output buffer, you must also
  392.  * provide the maximum length of that buffer (as "maxdestlen").
  393.  * The actual encoded length of output will be returned to you in
  394.  * "output_destlen".
  395.  *
  396.  * If linebreaks in the encoded output are desired, "line_length" specifies
  397.  * where to place them -- it will be rounded down to the nearest multiple of 4
  398.  * (if it is not already an even multiple of 4).  If it is zero, no linebreaks
  399.  * will be added.  (FYI, a linebreak is CRLF -- two characters.)
  400.  *
  401.  * Return value is NULL on error, the output buffer (allocated or provided)
  402.  * otherwise.
  403.  */
  404. static char *
  405. PL_Base64EncodeBuffer (const unsigned char *src, PRUint32 srclen,
  406.        PRUint32 line_length, char *dest, PRUint32 maxdestlen,
  407.        PRUint32 *output_destlen)
  408. {
  409.     PRUint32 need_length;
  410.     PLBase64Encoder *data = NULL;
  411.     PRStatus status;
  412.     PR_ASSERT(srclen > 0);
  413.     if (srclen == 0)
  414. return dest;
  415.     /*
  416.      * How much space could we possibly need for encoding this input?
  417.      */
  418.     need_length = PL_Base64MaxEncodedLength (srclen, line_length);
  419.     /*
  420.      * Make sure we have at least that much, if output buffer provided.
  421.      */
  422.     if (dest != NULL) {
  423. PR_ASSERT(maxdestlen >= need_length);
  424. if (maxdestlen < need_length) {
  425.     PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
  426.     return NULL;
  427. }
  428.     } else {
  429. maxdestlen = need_length;
  430.     }
  431.     data = pl_base64_create_encoder(line_length, dest, maxdestlen);
  432.     if (data == NULL)
  433. return NULL;
  434.     status = pl_base64_encode_buffer (data, src, srclen);
  435.     /*
  436.      * We do not wait for Destroy to flush, because Destroy will also
  437.      * get rid of our encoder context, which we need to look at first!
  438.      */
  439.     if (status == PR_SUCCESS)
  440. status = pl_base64_encode_flush (data);
  441.     if (status != PR_SUCCESS) {
  442. (void) PL_DestroyBase64Encoder (data, PR_TRUE);
  443. return NULL;
  444.     }
  445.     dest = data->output_buffer;
  446.     /* Must clear this or Destroy will free it. */
  447.     data->output_buffer = NULL;
  448.     *output_destlen = data->output_length;
  449.     status = PL_DestroyBase64Encoder (data, PR_FALSE);
  450.     if (status == PR_FAILURE) {
  451. PR_Free(dest);
  452. return NULL;
  453.     }
  454.     return dest;
  455. }
  456. /*
  457.  * XXX End of base64 encoding code to be moved into NSPR.
  458.  ********************************************************
  459.  */
  460. /*
  461.  * This is the beginning of the NSS cover functions.  These will
  462.  * provide the interface we want to expose as NSS-ish.  For example,
  463.  * they will operate on our Items, do any special handling or checking
  464.  * we want to do, etc.
  465.  */
  466. PR_BEGIN_EXTERN_C
  467. /*
  468.  * A boring cover structure for now.  Perhaps someday it will include
  469.  * some more interesting fields.
  470.  */
  471. struct NSSBase64EncoderStr {
  472.     PLBase64Encoder *pl_data;
  473. };
  474. PR_END_EXTERN_C
  475. /*
  476.  * Function to start a base64 encoding context.
  477.  */
  478. NSSBase64Encoder *
  479. NSSBase64Encoder_Create (PRInt32 (*output_fn) (void *, const char *, PRInt32),
  480.  void *output_arg)
  481. {
  482.     PLBase64Encoder *pl_data;
  483.     NSSBase64Encoder *nss_data;
  484.     nss_data = PORT_ZNew(NSSBase64Encoder);
  485.     if (nss_data == NULL)
  486. return NULL;
  487.     pl_data = PL_CreateBase64Encoder (output_fn, output_arg, 64);
  488.     if (pl_data == NULL) {
  489. PORT_Free(nss_data);
  490. return NULL;
  491.     }
  492.     nss_data->pl_data = pl_data;
  493.     return nss_data;
  494. }
  495. /*
  496.  * Push data through the encoder, causing the output_fn (provided to Create)
  497.  * to be called with the encoded data.
  498.  */
  499. SECStatus
  500. NSSBase64Encoder_Update (NSSBase64Encoder *data, const unsigned char *buffer,
  501.  PRUint32 size)
  502. {
  503.     PRStatus pr_status;
  504.     /* XXX Should we do argument checking only in debug build? */
  505.     if (data == NULL) {
  506. PORT_SetError (SEC_ERROR_INVALID_ARGS);
  507. return SECFailure;
  508.     }
  509.     pr_status = PL_UpdateBase64Encoder (data->pl_data, buffer, size);
  510.     if (pr_status == PR_FAILURE)
  511. return SECFailure;
  512.     return SECSuccess;
  513. }
  514. /*
  515.  * When you're done encoding, call this to free the data.  If "abort_p"
  516.  * is false, then calling this may cause the output_fn to be called
  517.  * one last time (as the last buffered data is flushed out).
  518.  */
  519. SECStatus
  520. NSSBase64Encoder_Destroy (NSSBase64Encoder *data, PRBool abort_p)
  521. {
  522.     PRStatus pr_status;
  523.     /* XXX Should we do argument checking only in debug build? */
  524.     if (data == NULL) {
  525. PORT_SetError (SEC_ERROR_INVALID_ARGS);
  526. return SECFailure;
  527.     }
  528.     pr_status = PL_DestroyBase64Encoder (data->pl_data, abort_p);
  529.     PORT_Free(data);
  530.     if (pr_status == PR_FAILURE)
  531. return SECFailure;
  532.     return SECSuccess;
  533. }
  534. /*
  535.  * Perform base64 encoding of binary data "inItem" to an ascii string.
  536.  * The output buffer may be provided (as "outStrOpt"); you can also pass
  537.  * in a NULL and the buffer will be allocated for you.  The result will
  538.  * be null-terminated, and if the buffer is provided, "maxOutLen" must
  539.  * specify the maximum length of the buffer and will be checked to
  540.  * supply sufficient space space for the encoded result.  (If "outStrOpt"
  541.  * is NULL, "maxOutLen" is ignored.)
  542.  *
  543.  * If "outStrOpt" is NULL, allocation will happen out of the passed-in
  544.  * "arenaOpt", if *it* is non-NULL, otherwise standard allocation (heap)
  545.  * will be used.
  546.  *
  547.  * Return value is NULL on error, the output buffer (allocated or provided)
  548.  * otherwise.
  549.  */
  550. char *
  551. NSSBase64_EncodeItem (PRArenaPool *arenaOpt, char *outStrOpt,
  552.       unsigned int maxOutLen, SECItem *inItem)
  553. {
  554.     char *out_string = outStrOpt;
  555.     PRUint32 max_out_len;
  556.     PRUint32 out_len;
  557.     void *mark = NULL;
  558.     char *dummy;
  559.     PORT_Assert(inItem != NULL && inItem->data != NULL && inItem->len != 0);
  560.     if (inItem == NULL || inItem->data == NULL || inItem->len == 0) {
  561. PORT_SetError (SEC_ERROR_INVALID_ARGS);
  562. return NULL;
  563.     }
  564.     max_out_len = PL_Base64MaxEncodedLength (inItem->len, 64);
  565.     if (arenaOpt != NULL)
  566. mark = PORT_ArenaMark (arenaOpt);
  567.     if (out_string == NULL) {
  568. if (arenaOpt != NULL)
  569.     out_string = PORT_ArenaAlloc (arenaOpt, max_out_len + 1);
  570. else
  571.     out_string = PORT_Alloc (max_out_len + 1);
  572. if (out_string == NULL) {
  573.     if (arenaOpt != NULL)
  574. PORT_ArenaRelease (arenaOpt, mark);
  575.     return NULL;
  576. }
  577.     } else {
  578. if ((max_out_len + 1) > maxOutLen) {
  579.     PORT_SetError (SEC_ERROR_OUTPUT_LEN);
  580.     return NULL;
  581. }
  582. max_out_len = maxOutLen;
  583.     }
  584.     dummy = PL_Base64EncodeBuffer (inItem->data, inItem->len, 64,
  585.    out_string, max_out_len, &out_len);
  586.     if (dummy == NULL) {
  587. if (arenaOpt != NULL) {
  588.     PORT_ArenaRelease (arenaOpt, mark);
  589. } else {
  590.     PORT_Free (out_string);
  591. }
  592. return NULL;
  593.     }
  594.     if (arenaOpt != NULL)
  595. PORT_ArenaUnmark (arenaOpt, mark);
  596.     out_string[out_len] = '';
  597.     return out_string;
  598. }
  599. /*
  600.  * XXX Everything below is deprecated.  If you add new stuff, put it
  601.  * *above*, not below.
  602.  */
  603. /*
  604.  * XXX The following "BTOA" functions are provided for backward compatibility
  605.  * with current code.  They should be considered strongly deprecated.
  606.  * When we can convert all our code over to using the new NSSBase64Encoder_
  607.  * functions defined above, we should get rid of these altogether.  (Remove
  608.  * protoypes from base64.h as well -- actually, remove that file completely).
  609.  * If someone thinks either of these functions provides such a very useful
  610.  * interface (though, as shown, the same functionality can already be
  611.  * obtained by calling NSSBase64_EncodeItem directly), fine -- but then
  612.  * that API should be provided with a nice new NSSFoo name and using
  613.  * appropriate types, etc.
  614.  */
  615. #include "base64.h"
  616. /*
  617. ** Return an PORT_Alloc'd ascii string which is the base64 encoded
  618. ** version of the input string.
  619. */
  620. char *
  621. BTOA_DataToAscii(const unsigned char *data, unsigned int len)
  622. {
  623.     SECItem binary_item;
  624.     binary_item.data = (unsigned char *)data;
  625.     binary_item.len = len;
  626.     return NSSBase64_EncodeItem (NULL, NULL, 0, &binary_item);
  627. }
  628. /*
  629. ** Convert from binary encoding of an item to ascii.
  630. */
  631. char *
  632. BTOA_ConvertItemToAscii (SECItem *binary_item)
  633. {
  634.     return NSSBase64_EncodeItem (NULL, NULL, 0, binary_item);
  635. }