From nobody Sun Apr 24 06:24:21 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id F0B6319964F3; Sun, 24 Apr 2022 06:24:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KmJ5K6QSmz3CWY; Sun, 24 Apr 2022 06:24:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650781461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5JihFdrrUM4Zz7gjTThPBdwwCnpQMvNjngHEPyjlaY8=; b=tYd0/AylWGYHEGXOOdNOBxJJQRr25jtQLvFOUZdAKjgRujMrsJeWoGgpf5hrRP3ZUqR+gQ 87b7Vh3Lg8HWpAZ1qn99rzXgmYc48TWCrPVN4ors5pkbFuU9v6UsKGhK2Cf2Zswt3dlel4 414bgDbihIgHnkteR/9d58aEYX+Dlu/3aUUDaANjM8dDXrdSJW1Z5DF+xQO5fSb96Bchx3 xwkJ/GoyOo/p+386SkHIADZ8WilP0Lhjc/x9NhhiWsbx596LEQEFEWiJ8tALqfyOvjVyIp LMEtLJkoZxiS2svb0Ss/ZSTAqKB2ZTr6X7NbFAMY09ukOfZJUePOxUZns/Kbyw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BC4AA213B4; Sun, 24 Apr 2022 06:24:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 23O6OLem043364; Sun, 24 Apr 2022 06:24:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 23O6OLbc043363; Sun, 24 Apr 2022 06:24:21 GMT (envelope-from git) Date: Sun, 24 Apr 2022 06:24:21 GMT Message-Id: <202204240624.23O6OLbc043363@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Piotr Pawel Stefaniak Subject: git: 8a65b02daca6 - main - bintrans: import mmencode.c for quoted-printable en/de-coding List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pstef X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8a65b02daca61a3940c7823425b8043015a2ac1e Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650781461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5JihFdrrUM4Zz7gjTThPBdwwCnpQMvNjngHEPyjlaY8=; b=G5uaQysFW8ZjM4M2aR9oMl6zul+4MpT1QTKU7Jvf6dwLBz0pK2IH2AQGo1XeKuZodGansi idoD6bxYiaIFvlXjQX+CTYL46JDdlYqJcmJZsNF8j+tvLIk1EVmap3gqGm5/fEOVNr4LhJ f564+53dsBZY4+hByR+spytIWeDv2sQRQhiWQzzBhQOCJoL2FG4X3otvfu7dy+Z3PeQ1o3 FmLmmi46iCUt42IK7OqFFVEoibEU2k/+JApCzCpVSQy7Pl9l6fsEDPK1iRfhPEIUqZBr/g vRipn7Vi5aD0v87dUq258gNQKy1OvWnVFjhjMgLRmX8qw3kUBBHnRvaoLGfkvA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1650781461; a=rsa-sha256; cv=none; b=RP4OswNriEewaUTVS1prEI+fAfOBR2FohH9/qjZLI//U+Z4brPboNZ6Ok2lZRF+u5vtl6F AKfEdvXSUHquTCHnt2KJ0NmIAmZjCgtLpBKmNARUrvR/tiZnIDvT0JF/E778v104MOCbkB 61rx/GSXwf5RYbg2It3pKFMivGQpyYQD1URkxDmWRgVghDSBBz09LISzHx0kuzq6YyY1DK cPBjPyXSfF3aW9BNw+ppzHGHgcOcr/0K1vgk94R+jor1G4mnb1Uusp04GZFX02Tx7QNlUT Wlyo+eysgAOdQ624GPjWz/AMqejbuVskgapH3aDjNMB0G/oe8kZIxuO4XCLmjA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by pstef: URL: https://cgit.FreeBSD.org/src/commit/?id=8a65b02daca61a3940c7823425b8043015a2ac1e commit 8a65b02daca61a3940c7823425b8043015a2ac1e Author: Piotr Pawel Stefaniak AuthorDate: 2022-04-15 12:08:05 +0000 Commit: Piotr Pawel Stefaniak CommitDate: 2022-04-24 06:19:48 +0000 bintrans: import mmencode.c for quoted-printable en/de-coding This is a preliminary commit in preparation for exposing a quoted-printable encoder and decoder through the new command bintrans. --- usr.bin/bintrans/mmencode.c | 530 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 530 insertions(+) diff --git a/usr.bin/bintrans/mmencode.c b/usr.bin/bintrans/mmencode.c new file mode 100644 index 000000000000..335fc5e76c1c --- /dev/null +++ b/usr.bin/bintrans/mmencode.c @@ -0,0 +1,530 @@ +/* +Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) + +Permission to use, copy, modify, and distribute this material +for any purpose and without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies, and that the name of Bellcore not be +used in advertising or publicity pertaining to this +material without the specific, prior written permission +of an authorized representative of Bellcore. BELLCORE +MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY +OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", +WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +*/ +#include +#include +#include + +extern char *index(); +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static char index_64[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +/* +char64(c) +char c; +{ + char *s = (char *) index(basis_64, c); + if (s) return(s-basis_64); + return(-1); +} +*/ + +/* the following gets a character, but fakes it properly into two chars if there's a newline character */ +static int InNewline=0; + +int nextcharin(infile, PortableNewlines) +FILE *infile; +int PortableNewlines; +{ + int c; + +#ifndef NEWLINE_CHAR + return(getc(infile)); +#else + if (!PortableNewlines) return(getc(infile)); + if (InNewline) { + InNewline = 0; + return(10); /* LF */ + } + c = getc(infile); + if (c == NEWLINE_CHAR) { + InNewline = 1; + return(13); /* CR */ + } + return(c); +#endif +} + +to64(infile, outfile, PortableNewlines) +FILE *infile, *outfile; +int PortableNewlines; +{ + int c1, c2, c3, ct=0; + InNewline = 0; /* always reset it */ + while ((c1 = nextcharin(infile, PortableNewlines)) != EOF) { + c2 = nextcharin(infile, PortableNewlines); + if (c2 == EOF) { + output64chunk(c1, 0, 0, 2, outfile); + } else { + c3 = nextcharin(infile, PortableNewlines); + if (c3 == EOF) { + output64chunk(c1, c2, 0, 1, outfile); + } else { + output64chunk(c1, c2, c3, 0, outfile); + } + } + ct += 4; + if (ct > 71) { + putc('\n', outfile); + ct = 0; + } + } + if (ct) putc('\n', outfile); + fflush(outfile); +} + +output64chunk(c1, c2, c3, pads, outfile) +FILE *outfile; +{ + putc(basis_64[c1>>2], outfile); + putc(basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)], outfile); + if (pads == 2) { + putc('=', outfile); + putc('=', outfile); + } else if (pads) { + putc(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile); + putc('=', outfile); + } else { + putc(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile); + putc(basis_64[c3 & 0x3F], outfile); + } +} + +PendingBoundary(s, Boundaries, BoundaryCt) +char *s; +char **Boundaries; +int *BoundaryCt; +{ + int i, len; + + if (s[0] != '-' || s[1] != '-') return(0); + + + for (i=0; i < *BoundaryCt; ++i) { + len = strlen(Boundaries[i]); + if (!strncmp(s, Boundaries[i], len)) { + if (s[len] == '-' && s[len+1] == '-') *BoundaryCt = i; + return(1); + } + } + return(0); +} + +/* If we're in portable newline mode, we have to convert CRLF to the + local newline convention on output */ + +static int CRpending = 0; + +#ifdef NEWLINE_CHAR +almostputc(c, outfile, PortableNewlines) +int c; +FILE *outfile; +int PortableNewlines; +{ + if (CRpending) { + if (c == 10) { + putc(NEWLINE_CHAR, outfile); + CRpending = 0; + } else { + putc(13, outfile); + if (c != 13) { + putc(c, outfile); + CRpending = 0; + } + } + } else { + if (PortableNewlines && c == 13) { + CRpending = 1; + } else { + putc(c, outfile); + } + } +} +#else +almostputc(c, outfile, PortableNewlines) +int c; +FILE *outfile; +int PortableNewlines; +{ + putc(c, outfile); +} +#endif + +from64(infile, outfile, boundaries, boundaryct, PortableNewlines) +FILE *infile, *outfile; +char **boundaries; +int *boundaryct; +int PortableNewlines; +{ + int c1, c2, c3, c4; + int newline = 1, DataDone = 0; + + /* always reinitialize */ + CRpending = 0; + while ((c1 = getc(infile)) != EOF) { + if (isspace(c1)) { + if (c1 == '\n') { + newline = 1; + } else { + newline = 0; + } + continue; + } + if (newline && boundaries && c1 == '-') { + char Buf[200]; + /* a dash is NOT base 64, so all bets are off if NOT a boundary */ + ungetc(c1, infile); + fgets(Buf, sizeof(Buf), infile); + if (boundaries + && (Buf[0] == '-') + && (Buf[1] == '-') + && PendingBoundary(Buf, boundaries, boundaryct)) { + return; + } + fprintf(stderr, "Ignoring unrecognized boundary line: %s\n", Buf); + continue; + } + if (DataDone) continue; + newline = 0; + do { + c2 = getc(infile); + } while (c2 != EOF && isspace(c2)); + do { + c3 = getc(infile); + } while (c3 != EOF && isspace(c3)); + do { + c4 = getc(infile); + } while (c4 != EOF && isspace(c4)); + if (c2 == EOF || c3 == EOF || c4 == EOF) { + fprintf(stderr, "Warning: base64 decoder saw premature EOF!\n"); + return; + } + if (c1 == '=' || c2 == '=') { + DataDone=1; + continue; + } + c1 = char64(c1); + c2 = char64(c2); + almostputc(((c1<<2) | ((c2&0x30)>>4)), outfile, PortableNewlines); + if (c3 == '=') { + DataDone = 1; + } else { + c3 = char64(c3); + almostputc((((c2&0XF) << 4) | ((c3&0x3C) >> 2)), outfile, PortableNewlines); + if (c4 == '=') { + DataDone = 1; + } else { + c4 = char64(c4); + almostputc((((c3&0x03) <<6) | c4), outfile, PortableNewlines); + } + } + } + if (CRpending) putc(13, outfile); /* Don't drop a lone trailing char 13 */ +} + +static char basis_hex[] = "0123456789ABCDEF"; +static char index_hex[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +}; + +/* The following version generated complaints on Solaris. */ +/* #define hexchar(c) (((c) < 0 || (c) > 127) ? -1 : index_hex[(c)]) */ +/* Since we're no longer ever calling it with anything signed, this should work: */ +#define hexchar(c) (((c) > 127) ? -1 : index_hex[(c)]) + +/* +hexchar(c) +char c; +{ + char *s; + if (islower(c)) c = toupper(c); + s = (char *) index(basis_hex, c); + if (s) return(s-basis_hex); + return(-1); +} +*/ + +toqp(infile, outfile) +FILE *infile, *outfile; +{ + int c, ct=0, prevc=255; + while ((c = getc(infile)) != EOF) { + if ((c < 32 && (c != '\n' && c != '\t')) + || (c == '=') + || (c >= 127) + /* Following line is to avoid single periods alone on lines, + which messes up some dumb smtp implementations, sigh... */ + || (ct == 0 && c == '.')) { + putc('=', outfile); + putc(basis_hex[c>>4], outfile); + putc(basis_hex[c&0xF], outfile); + ct += 3; + prevc = 'A'; /* close enough */ + } else if (c == '\n') { + if (prevc == ' ' || prevc == '\t') { + putc('=', outfile); /* soft & hard lines */ + putc(c, outfile); + } + putc(c, outfile); + ct = 0; + prevc = c; + } else { + if (c == 'F' && prevc == '\n') { + /* HORRIBLE but clever hack suggested by MTR for sendmail-avoidance */ + c = getc(infile); + if (c == 'r') { + c = getc(infile); + if (c == 'o') { + c = getc(infile); + if (c == 'm') { + c = getc(infile); + if (c == ' ') { + /* This is the case we are looking for */ + fputs("=46rom", outfile); + ct += 6; + } else { + fputs("From", outfile); + ct += 4; + } + } else { + fputs("Fro", outfile); + ct += 3; + } + } else { + fputs("Fr", outfile); + ct += 2; + } + } else { + putc('F', outfile); + ++ct; + } + ungetc(c, infile); + prevc = 'x'; /* close enough -- printable */ + } else { /* END horrible hack */ + putc(c, outfile); + ++ct; + prevc = c; + } + } + if (ct > 72) { + putc('=', outfile); + putc('\n', outfile); + ct = 0; + prevc = '\n'; + } + } + if (ct) { + putc('=', outfile); + putc('\n', outfile); + } +} + +fromqp(infile, outfile, boundaries, boundaryct) +FILE *infile, *outfile; +char **boundaries; +int *boundaryct; +{ + unsigned int c1, c2; + int sawnewline = 1, neednewline = 0; + /* The neednewline hack is necessary because the newline leading into + a multipart boundary is part of the boundary, not the data */ + + while ((c1 = getc(infile)) != EOF) { + if (sawnewline && boundaries && (c1 == '-')) { + char Buf[200]; + unsigned char *s; + + ungetc(c1, infile); + fgets(Buf, sizeof(Buf), infile); + if (boundaries + && (Buf[0] == '-') + && (Buf[1] == '-') + && PendingBoundary(Buf, boundaries, boundaryct)) { + return; + } + /* Not a boundary, now we must treat THIS line as q-p, sigh */ + if (neednewline) { + putc('\n', outfile); + neednewline = 0; + } + for (s=(unsigned char *) Buf; *s; ++s) { + if (*s == '=') { + if (!*++s) break; + if (*s == '\n') { + /* ignore it */ + sawnewline = 1; + } else { + c1 = hexchar(*s); + if (!*++s) break; + c2 = hexchar(*s); + putc(c1<<4 | c2, outfile); + } + } else { +#ifdef MSDOS + if (*s == '\n') + putc('\r', outfile); /* insert CR for binary-mode write */ +#endif + putc(*s, outfile); + } + } + } else { + if (neednewline) { + putc('\n', outfile); + neednewline = 0; + } + if (c1 == '=') { + sawnewline = 0; + c1 = getc(infile); + if (c1 == '\n') { + /* ignore it */ + sawnewline = 1; + } else { + c2 = getc(infile); + c1 = hexchar(c1); + c2 = hexchar(c2); + putc(c1<<4 | c2, outfile); + if (c2 == '\n') sawnewline = 1; + } + } else { + if (c1 == '\n') { + sawnewline = 1; + neednewline = 1; + } else { + sawnewline = 0; + putc(c1, outfile); + } + } + } + } + if (neednewline) { + putc('\n', outfile); + neednewline = 0; + } +} + +/* +Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) + +Permission to use, copy, modify, and distribute this material +for any purpose and without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies, and that the name of Bellcore not be +used in advertising or publicity pertaining to this +material without the specific, prior written permission +of an authorized representative of Bellcore. BELLCORE +MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY +OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", +WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +*/ +#include +#include +#ifdef MSDOS +#include +#endif + +#define BASE64 1 +#define QP 2 /* quoted-printable */ + +main(argc, argv) +int argc; +char **argv; +{ + int encode = 1, which = BASE64, i, portablenewlines = 0; + FILE *fp = stdin; + FILE *fpo = stdout; + + for (i=1; i= argc) { + fprintf(stderr, "mimencode: -o requires a file name.\n"); + exit(-1); + } + fpo = fopen(argv[i], "w"); + if (!fpo) { + perror(argv[i]); + exit(-1); + } + break; + case 'u': + encode = 0; + break; + case 'q': + which = QP; + break; + case 'p': + portablenewlines = 1; + break; + case 'b': + which = BASE64; + break; + default: + fprintf(stderr, + "Usage: mmencode [-u] [-q] [-b] [-p] [-o outputfile] [file name]\n"); + exit(-1); + } + } else { +#ifdef MSDOS + if (encode) + fp = fopen(argv[i], "rb"); + else + { + fp = fopen(argv[i], "rt"); + setmode(fileno(fpo), O_BINARY); + } /* else */ +#else + fp = fopen(argv[i], "r"); +#endif /* MSDOS */ + if (!fp) { + perror(argv[i]); + exit(-1); + } + } + } +#ifdef MSDOS + if (fp == stdin) setmode(fileno(fp), O_BINARY); +#endif /* MSDOS */ + if (which == BASE64) { + if (encode) { + to64(fp, fpo, portablenewlines); + } else { + from64(fp,fpo, (char **) NULL, (int *) 0, portablenewlines); + } + } else { + if (encode) toqp(fp, fpo); else fromqp(fp, fpo, NULL, 0); + } + return(0); +} +