|
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 == '+' |
|
45 || c == '/' |
|
46 || c == '='); |
|
47 } |
|
48 |
|
49 static SECStatus |
|
50 decode_file(FILE *outFile, FILE *inFile) |
|
51 { |
|
52 NSSBase64Decoder *cx; |
|
53 SECStatus status = SECFailure; |
|
54 char ibuf[4096]; |
|
55 const char *ptr; |
|
56 |
|
57 cx = NSSBase64Decoder_Create(output_binary, outFile); |
|
58 if (!cx) { |
|
59 return -1; |
|
60 } |
|
61 |
|
62 for (;;) { |
|
63 if (feof(inFile)) 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) goto loser; |
|
88 } |
|
89 |
|
90 return NSSBase64Decoder_Destroy(cx, PR_FALSE); |
|
91 |
|
92 loser: |
|
93 (void) NSSBase64Decoder_Destroy(cx, PR_TRUE); |
|
94 return status; |
|
95 } |
|
96 |
|
97 static void Usage(char *progName) |
|
98 { |
|
99 fprintf(stderr, |
|
100 "Usage: %s [-i input] [-o output]\n", |
|
101 progName); |
|
102 fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n", |
|
103 "-i input"); |
|
104 fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", |
|
105 "-o output"); |
|
106 exit(-1); |
|
107 } |
|
108 |
|
109 int main(int argc, char **argv) |
|
110 { |
|
111 char *progName; |
|
112 SECStatus rv; |
|
113 FILE *inFile, *outFile; |
|
114 PLOptState *optstate; |
|
115 PLOptStatus status; |
|
116 |
|
117 inFile = 0; |
|
118 outFile = 0; |
|
119 progName = strrchr(argv[0], '/'); |
|
120 progName = progName ? progName+1 : argv[0]; |
|
121 |
|
122 /* Parse command line arguments */ |
|
123 optstate = PL_CreateOptState(argc, argv, "?hi:o:"); |
|
124 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
|
125 switch (optstate->option) { |
|
126 case '?': |
|
127 case 'h': |
|
128 Usage(progName); |
|
129 break; |
|
130 |
|
131 case 'i': |
|
132 inFile = fopen(optstate->value, "r"); |
|
133 if (!inFile) { |
|
134 fprintf(stderr, "%s: unable to open \"%s\" for reading\n", |
|
135 progName, optstate->value); |
|
136 return -1; |
|
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 return -1; |
|
146 } |
|
147 break; |
|
148 } |
|
149 } |
|
150 if (!inFile) inFile = stdin; |
|
151 if (!outFile) { |
|
152 #if defined(WIN32) |
|
153 int smrv = _setmode(_fileno(stdout), _O_BINARY); |
|
154 if (smrv == -1) { |
|
155 fprintf(stderr, |
|
156 "%s: Cannot change stdout to binary mode. Use -o option instead.\n", |
|
157 progName); |
|
158 return smrv; |
|
159 } |
|
160 #endif |
|
161 outFile = stdout; |
|
162 } |
|
163 rv = decode_file(outFile, inFile); |
|
164 if (rv != SECSuccess) { |
|
165 fprintf(stderr, "%s: lossage: error=%d errno=%d\n", |
|
166 progName, PORT_GetError(), errno); |
|
167 return -1; |
|
168 } |
|
169 return 0; |
|
170 } |