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 }