tor-browser

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

atob.c (4796B)


      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_binary(void *arg, const unsigned 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 PRBool
     39 isBase64Char(char c)
     40 {
     41    return ((c >= 'A' && c <= 'Z') ||
     42            (c >= 'a' && c <= 'z') ||
     43            (c >= '0' && c <= '9') ||
     44            c == '+' || c == '/' ||
     45            c == '=');
     46 }
     47 
     48 static SECStatus
     49 decode_file(FILE *outFile, FILE *inFile)
     50 {
     51    NSSBase64Decoder *cx;
     52    SECStatus status = SECFailure;
     53    char ibuf[4096];
     54    const char *ptr;
     55 
     56    cx = NSSBase64Decoder_Create(output_binary, outFile);
     57    if (!cx) {
     58        return -1;
     59    }
     60 
     61    for (;;) {
     62        if (feof(inFile))
     63            break;
     64        if (!fgets(ibuf, sizeof(ibuf), inFile)) {
     65            if (ferror(inFile)) {
     66                PORT_SetError(SEC_ERROR_IO);
     67                goto loser;
     68            }
     69            /* eof */
     70            break;
     71        }
     72        for (ptr = ibuf; *ptr; ++ptr) {
     73            char c = *ptr;
     74            if (c == '\n' || c == '\r') {
     75                break; /* found end of line */
     76            }
     77            if (!isBase64Char(c)) {
     78                ptr = ibuf; /* ignore line */
     79                break;
     80            }
     81        }
     82        if (ibuf == ptr) {
     83            continue; /* skip empty or non-base64 line */
     84        }
     85 
     86        status = NSSBase64Decoder_Update(cx, ibuf, ptr - ibuf);
     87        if (status != SECSuccess)
     88            goto loser;
     89    }
     90 
     91    return NSSBase64Decoder_Destroy(cx, PR_FALSE);
     92 
     93 loser:
     94    (void)NSSBase64Decoder_Destroy(cx, PR_TRUE);
     95    return status;
     96 }
     97 
     98 static void
     99 Usage(char *progName)
    100 {
    101    fprintf(stderr,
    102            "Usage: %s [-i input] [-o output]\n",
    103            progName);
    104    fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
    105            "-i input");
    106    fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
    107            "-o output");
    108 }
    109 
    110 int
    111 main(int argc, char **argv)
    112 {
    113    char *progName;
    114    SECStatus rv;
    115    FILE *inFile = NULL, *outFile = NULL;
    116    PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
    117    PLOptState *optstate = NULL;
    118    PLOptStatus status;
    119    int exitCode = -1;
    120 
    121    progName = strrchr(argv[0], '/');
    122    progName = progName ? progName + 1 : argv[0];
    123 
    124    /* Parse command line arguments */
    125    optstate = PL_CreateOptState(argc, argv, "?hi:o:");
    126    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
    127        switch (optstate->option) {
    128            case '?':
    129            case 'h':
    130                Usage(progName);
    131                goto loser;
    132                break;
    133 
    134            case 'i':
    135                inFile = fopen(optstate->value, "r");
    136                if (!inFile) {
    137                    fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
    138                            progName, optstate->value);
    139                    goto loser;
    140                }
    141                break;
    142 
    143            case 'o':
    144                outFile = fopen(optstate->value, "wb");
    145                if (!outFile) {
    146                    fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
    147                            progName, optstate->value);
    148                    goto loser;
    149                }
    150                break;
    151        }
    152    }
    153    if (!inFile) {
    154        inFile = stdin;
    155        closeIn = PR_FALSE;
    156    }
    157    if (!outFile) {
    158 #if defined(WIN32)
    159        int smrv = _setmode(_fileno(stdout), _O_BINARY);
    160        if (smrv == -1) {
    161            fprintf(stderr,
    162                    "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
    163                    progName);
    164            goto loser;
    165        }
    166 #endif
    167        outFile = stdout;
    168        closeOut = PR_FALSE;
    169    }
    170    rv = decode_file(outFile, inFile);
    171    if (rv != SECSuccess) {
    172        fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
    173                progName, PORT_GetError(), errno);
    174        goto loser;
    175    }
    176    exitCode = 0;
    177 loser:
    178    if (optstate) {
    179        PL_DestroyOptState(optstate);
    180    }
    181    if (inFile && closeIn) {
    182        fclose(inFile);
    183    }
    184    if (outFile && closeOut) {
    185        fclose(outFile);
    186    }
    187    return exitCode;
    188 }