2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2020 Baptiste Daroussin <bapt@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 extern int main_quotedprintable(int, char *[]);
39 if ('0' <= c && c <= '9')
41 return (10 + c - 'A');
46 decode_char(const char *s)
48 return (16 * hexval(toupper(s[1])) + hexval(toupper(s[2])));
53 decode_quoted_printable(const char *body, FILE *fpo)
55 while (*body != '\0') {
58 if (strlen(body) < 2) {
63 if (body[1] == '\r' && body[2] == '\n') {
67 if (body[1] == '\n') {
71 if (strchr("0123456789ABCDEFabcdef", body[1]) == NULL) {
75 if (strchr("0123456789ABCDEFabcdef", body[2]) == NULL) {
79 fputc(decode_char(body), fpo);
91 encode_quoted_printable(const char *body, FILE *fpo)
94 const char *end = body + strlen(body);
97 while (*body != '\0') {
102 if (!isascii(*body) ||
104 (*body == '.' && body + 1 < end &&
105 (body[1] == '\n' || body[1] == '\r'))) {
106 fprintf(fpo, "=%02X", (unsigned char)*body);
109 } else if (*body < 33 && *body != '\n') {
110 if ((*body == ' ' || *body == '\t') &&
112 (body[1] != '\n' && body[1] != '\r')) {
116 fprintf(fpo, "=%02X", (unsigned char)*body);
120 } else if (*body == '\n') {
121 if (prev == ' ' || prev == '\t') {
137 qp(FILE *fp, FILE *fpo, bool encode)
142 void (*codec)(const char *line, FILE *f);
144 codec = encode ? encode_quoted_printable : decode_quoted_printable ;
146 while ((linelen = getline(&line, &linecap, fp)) > 0)
155 "usage: bintrans qp [-u] [-o outputfile] [file name]\n");
159 main_quotedprintable(int argc, char *argv[])
166 for (i = 1; i < argc; ++i) {
167 if (argv[i][0] == '-') {
168 switch (argv[i][1]) {
171 fprintf(stderr, "qp: -o requires a file name.\n");
174 fpo = fopen(argv[i], "w");
188 fp = fopen(argv[i], "r");
197 return (EXIT_SUCCESS);