3 Copyright (C) 2002, 2003, 2009 Niels Möller
5 This file is part of GNU Nettle.
7 GNU Nettle is free software: you can redistribute it and/or
8 modify it under the terms of either:
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
16 * the GNU General Public License as published by the Free
17 Software Foundation; either version 2 of the License, or (at your
18 option) any later version.
20 or both in parallel, as here.
22 GNU Nettle is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
27 You should have received copies of the GNU General Public License and
28 the GNU Lesser General Public License along with this program. If
29 not, see http://www.gnu.org/licenses/.
45 #include "nettle-internal.h"
48 sexp_output_init(struct sexp_output *output, FILE *f,
49 unsigned width, int prefer_hex)
52 output->line_width = width;
53 output->coding = NULL;
54 output->prefer_hex = prefer_hex;
59 output->soft_newline = 0;
63 sexp_output_hash_init(struct sexp_output *output,
64 const struct nettle_hash *hash, void *ctx)
72 sexp_put_raw_char(struct sexp_output *output, uint8_t c)
74 if (putc(c, output->f) < 0)
75 die("Write failed: %s\n", strerror(errno));
78 output->soft_newline = 0;
82 sexp_put_newline(struct sexp_output *output,
85 if (output->soft_newline)
86 output->soft_newline = 0;
91 sexp_put_raw_char(output, '\n');
94 for(i = 0; i < indent; i++)
95 sexp_put_raw_char(output, ' ');
101 /* Put a newline, but only if it is followed by another newline,
102 collaps to one newline only. */
104 sexp_put_soft_newline(struct sexp_output *output,
107 sexp_put_newline(output, indent);
108 output->soft_newline = 1;
112 sexp_put_char(struct sexp_output *output, uint8_t c)
116 /* Two is enough for both base16 and base64. */
122 done = output->coding->encode_update(&output->base64, encoded,
124 assert(done <= sizeof(encoded));
126 for (i = 0; i<done; i++)
128 if (output->line_width
129 && output->pos >= output->line_width
130 && output->pos >= (output->coding_indent + 10))
131 sexp_put_newline(output, output->coding_indent);
133 sexp_put_raw_char(output, encoded[i]);
136 else if (output->hash)
137 output->hash->update(output->ctx, 1, &c);
139 sexp_put_raw_char(output, c);
143 sexp_put_data(struct sexp_output *output,
144 unsigned length, const uint8_t *data)
148 for (i = 0; i<length; i++)
149 sexp_put_char(output, data[i]);
153 sexp_put_length(struct sexp_output *output,
160 unsigned next = digit * 10;
166 for (; digit; length %= digit, digit /= 10)
167 sexp_put_char(output, '0' + length / digit);
171 sexp_put_code_start(struct sexp_output *output,
172 const struct nettle_armor *coding)
174 assert(!output->coding);
176 output->coding_indent = output->pos;
178 output->coding = coding;
179 output->coding->encode_init(&output->base64);
183 sexp_put_code_end(struct sexp_output *output)
185 /* Enough for both hex and base64 */
186 uint8_t encoded[BASE64_ENCODE_FINAL_LENGTH];
189 assert(output->coding);
191 done = output->coding->encode_final(&output->base64, encoded);
193 assert(done <= sizeof(encoded));
195 output->coding = NULL;
197 sexp_put_data(output, done, encoded);
201 sexp_put_string(struct sexp_output *output, enum sexp_mode mode,
202 struct nettle_buffer *string)
205 sexp_put_data(output, 2,
206 (mode == SEXP_ADVANCED) ? "\"\"": "0:");
208 else if (mode == SEXP_ADVANCED)
211 int token = (string->contents[0] < '0' || string->contents[0] > '9');
212 int quote_friendly = 1;
213 #define CONTROL_SIZE 0x20
214 static const char escape_names[CONTROL_SIZE] =
216 0,0,0,0,0,0,0,0, 'b','t','n',0,'f','r',0,0,
217 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
220 for (i = 0; i<string->size; i++)
222 uint8_t c = string->contents[i];
224 if (token & !TOKEN_CHAR(c))
231 else if (c < CONTROL_SIZE && !escape_names[c])
237 sexp_put_data(output, string->size, string->contents);
239 else if (quote_friendly)
241 sexp_put_char(output, '"');
243 for (i = 0; i<string->size; i++)
246 uint8_t c = string->contents[i];
250 if (c == '\\' || c == '"')
252 else if (c < CONTROL_SIZE)
259 sexp_put_char(output, '\\');
261 sexp_put_char(output, c);
264 sexp_put_char(output, '"');
269 const struct nettle_armor *coding;
271 if (output->prefer_hex)
274 coding = &nettle_base16;
279 coding = &nettle_base64;
282 sexp_put_char(output, delimiter);
283 sexp_put_code_start(output, coding);
284 sexp_put_data(output, string->size, string->contents);
285 sexp_put_code_end(output);
286 sexp_put_char(output, delimiter);
292 sexp_put_length(output, string->size);
293 sexp_put_char(output, ':');
294 sexp_put_data(output, string->size, string->contents);
299 sexp_put_digest(struct sexp_output *output)
301 TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
302 TMP_ALLOC(digest, output->hash->digest_size);
304 assert(output->hash);
306 output->hash->digest(output->ctx, output->hash->digest_size, digest);
308 sexp_put_code_start(output, &nettle_base16);
309 sexp_put_data(output, output->hash->digest_size, digest);
310 sexp_put_code_end(output);