tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

btoa.c (5933B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "plgetopt.h"
      6 #include "secutil.h"
      7 #include "nssb64.h"
      8 #include <errno.h>
      9 
     10 #if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
     11 #if !defined(WIN32)
     12 extern int fread(char *, size_t, size_t, FILE *);
     13 extern int fwrite(char *, size_t, size_t, FILE *);
     14 extern int fprintf(FILE *, char *, ...);
     15 #endif
     16 #endif
     17 
     18 #if defined(WIN32)
     19 #include "fcntl.h"
     20 #include "io.h"
     21 #endif
     22 
     23 static PRInt32
     24 output_ascii(void *arg, const char *obuf, PRInt32 size)
     25 {
     26    FILE *outFile = arg;
     27    int nb;
     28 
     29    nb = fwrite(obuf, 1, size, outFile);
     30    if (nb != size) {
     31        PORT_SetError(SEC_ERROR_IO);
     32        return -1;
     33    }
     34 
     35    return nb;
     36 }
     37 
     38 static SECStatus
     39 encode_file(FILE *outFile, FILE *inFile)
     40 {
     41    NSSBase64Encoder *cx;
     42    int nb;
     43    SECStatus status = SECFailure;
     44    unsigned char ibuf[4096];
     45 
     46    cx = NSSBase64Encoder_Create(output_ascii, outFile);
     47    if (!cx) {
     48        return -1;
     49    }
     50 
     51    for (;;) {
     52        if (feof(inFile))
     53            break;
     54        nb = fread(ibuf, 1, sizeof(ibuf), inFile);
     55        if (nb != sizeof(ibuf)) {
     56            if (nb == 0) {
     57                if (ferror(inFile)) {
     58                    PORT_SetError(SEC_ERROR_IO);
     59                    goto loser;
     60                }
     61                /* eof */
     62                break;
     63            }
     64        }
     65 
     66        status = NSSBase64Encoder_Update(cx, ibuf, nb);
     67        if (status != SECSuccess)
     68            goto loser;
     69    }
     70 
     71    status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
     72    if (status != SECSuccess)
     73        return status;
     74 
     75    /*
     76     * Add a trailing CRLF.  Note this must be done *after* the call
     77     * to Destroy above (because only then are we sure all data has
     78     * been written out).
     79     */
     80    fwrite("\r\n", 1, 2, outFile);
     81    return SECSuccess;
     82 
     83 loser:
     84    (void)NSSBase64Encoder_Destroy(cx, PR_TRUE);
     85    return status;
     86 }
     87 
     88 static void
     89 Usage(char *progName)
     90 {
     91    fprintf(stderr,
     92            "Usage: %s [-i input] [-o output]\n",
     93            progName);
     94    fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
     95            "-i input");
     96    fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
     97            "-o output");
     98    fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
     99            "-w suffix");
    100    fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
    101            "");
    102 }
    103 
    104 int
    105 main(int argc, char **argv)
    106 {
    107    char *progName;
    108    SECStatus rv;
    109    FILE *inFile = NULL, *outFile = NULL;
    110    PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
    111    PLOptState *optstate = NULL;
    112    PLOptStatus status;
    113    char *suffix = NULL;
    114    int exitCode = -1;
    115 
    116    progName = strrchr(argv[0], '/');
    117    if (!progName)
    118        progName = strrchr(argv[0], '\\');
    119    progName = progName ? progName + 1 : argv[0];
    120 
    121    /* Parse command line arguments */
    122    optstate = PL_CreateOptState(argc, argv, "i:o:w:");
    123    PORT_Assert(optstate);
    124    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
    125        switch (optstate->option) {
    126            default:
    127                Usage(progName);
    128                goto loser;
    129                break;
    130 
    131            case 'i':
    132                inFile = fopen(optstate->value, "rb");
    133                if (!inFile) {
    134                    fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
    135                            progName, optstate->value);
    136                    goto loser;
    137                }
    138                break;
    139 
    140            case 'o':
    141                outFile = fopen(optstate->value, "wb");
    142                if (!outFile) {
    143                    fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
    144                            progName, optstate->value);
    145                    goto loser;
    146                }
    147                break;
    148 
    149            case 'w':
    150                if (!strcmp(optstate->value, "c"))
    151                    suffix = strdup("CERTIFICATE");
    152                else
    153                    suffix = strdup(optstate->value);
    154                break;
    155        }
    156    }
    157    if (status == PL_OPT_BAD)
    158        Usage(progName);
    159    if (!inFile) {
    160 #if defined(WIN32)
    161        /* If we're going to read binary data from stdin, we must put stdin
    162        ** into O_BINARY mode or else incoming \r\n's will become \n's.
    163        */
    164 
    165        int smrv = _setmode(_fileno(stdin), _O_BINARY);
    166        if (smrv == -1) {
    167            fprintf(stderr,
    168                    "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
    169                    progName);
    170            goto loser;
    171        }
    172 #endif
    173        inFile = stdin;
    174        closeIn = PR_FALSE;
    175    }
    176    if (!outFile) {
    177 #if defined(WIN32)
    178        /* We're going to write binary data to stdout. We must put stdout
    179        ** into O_BINARY mode or else outgoing \r\n's will become \r\r\n's.
    180        */
    181 
    182        int smrv = _setmode(_fileno(stdout), _O_BINARY);
    183        if (smrv == -1) {
    184            fprintf(stderr,
    185                    "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
    186                    progName);
    187            goto loser;
    188        }
    189 #endif
    190        outFile = stdout;
    191        closeOut = PR_FALSE;
    192    }
    193    if (suffix) {
    194        fprintf(outFile, "-----BEGIN %s-----\n", suffix);
    195    }
    196    rv = encode_file(outFile, inFile);
    197    if (rv != SECSuccess) {
    198        fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
    199                progName, PORT_GetError(), errno);
    200        goto loser;
    201    }
    202    if (suffix) {
    203        fprintf(outFile, "-----END %s-----\n", suffix);
    204    }
    205    exitCode = 0;
    206 loser:
    207    PL_DestroyOptState(optstate);
    208    if (inFile && closeIn) {
    209        fclose(inFile);
    210    }
    211    if (outFile && closeOut) {
    212        fclose(outFile);
    213    }
    214    if (suffix) {
    215        PORT_Free(suffix);
    216    }
    217    return exitCode;
    218 }