From eb9690cc6fbe39621584b5e18c7cf821671a007a Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 31 Jan 1999 18:05:23 +0000 Subject: [PATCH] Added base64.c to the distribution --- citadel/ChangeLog | 1 + citadel/Makefile.in | 9 +- citadel/base64.c | 323 ++++++++++++++++++++++++++++++++++++++++++ citadel/copyright.txt | 3 + citadel/mime_parser.c | 15 +- 5 files changed, 334 insertions(+), 17 deletions(-) create mode 100644 citadel/base64.c diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 73269b3d5..2abd6e269 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,6 +1,7 @@ Sat Jan 30 18:39:53 EST 1999 Art Cancro * Look for citadel.rc in current directory if not found elsewhere * More work on the MIME parser + * Added base64.c to the distribution 1999-01-29 Nathan Bryant * fixes for IRIX (thanks to wr and family for use of the Indy): diff --git a/citadel/Makefile.in b/citadel/Makefile.in index 7bfc5c038..150d6bc44 100644 --- a/citadel/Makefile.in +++ b/citadel/Makefile.in @@ -22,8 +22,8 @@ CLIENT_TARGETS=citadel whobbs SERVER_TARGETS=citserver setup SERV_MODULES=modules/serv_chat.so \ modules/serv_upgrade.so modules/serv_expire.so -UTIL_TARGETS=aidepost netmailer netproc netsetup msgform \ - readlog rcit stats citmail netpoll mailinglist userlist sendcommand +UTIL_TARGETS=aidepost netmailer netproc netsetup msgform readlog rcit \ + stats citmail netpoll mailinglist userlist sendcommand base64 PROXY_TARGETS=proxy prefix=@prefix@ @@ -57,7 +57,7 @@ SOURCES=aidepost.c citadel.c citmail.c citserver.c client_chat.c commands.c \ room_ops.c rooms.c routines.c routines2.c serv_chat.c \ serv_info.c serv_test.c serv_upgrade.c setup.c snprintf.c stats.c \ support.c sysdep.c tools.c user_ops.c userlist.c serv_expire.c \ - whobbs.c sendcommand.c mime_parser.c + whobbs.c sendcommand.c mime_parser.c base64.c DEP_FILES=$(SOURCES:.c=.d) @@ -160,6 +160,9 @@ sendcommand: sendcommand.o ipc_c_tcp.o tools.o config.o $(SNPRINTF) $(CC) sendcommand.o ipc_c_tcp.o tools.o config.o \ $(SNPRINTF) $(LDFLAGS) -o sendcommand +base64: base64.o + $(CC) base64.o $(LDFLAGS) -o base64 + userlist: userlist.o ipc_c_tcp.o tools.o $(SNPRINTF) $(CC) userlist.o ipc_c_tcp.o tools.o \ $(SNPRINTF) $(LDFLAGS) -o userlist diff --git a/citadel/base64.c b/citadel/base64.c new file mode 100644 index 000000000..5925f977a --- /dev/null +++ b/citadel/base64.c @@ -0,0 +1,323 @@ +/* + + Encode or decode file as MIME base64 (RFC 1341) + + by John Walker + http://www.fourmilab.ch/ + + This program is in the public domain. + +*/ + +#define REVDATE "11th August 1997" + +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +#define LINELEN 72 /* Encoded line length (max 76) */ + +typedef unsigned char byte; /* Byte type */ + +static FILE *fi = stdin; /* Input file */ +static FILE *fo = stdout; /* Output file */ +static byte iobuf[256]; /* I/O buffer */ +static int iolen = 0; /* Bytes left in I/O buffer */ +static int iocp = 256; /* Character removal pointer */ +static int ateof = FALSE; /* EOF encountered */ +static byte dtable[256]; /* Encode / decode table */ +static int linelength = 0; /* Length of encoded output line */ +static char eol[] = "\r\n"; /* End of line sequence */ +static int errcheck = TRUE; /* Check decode input for errors ? */ + +/* INBUF -- Fill input buffer with data */ + +static int inbuf(void) +{ + int l; + + if (ateof) { + return FALSE; + } + l = fread(iobuf, 1, 256, fi); /* Read input buffer */ + if (l <= 0) { + if (ferror(fi)) { + exit(1); + } + ateof = TRUE; + return FALSE; + } + iolen = l; + iocp = 0; + return TRUE; +} + +/* INCHAR -- Return next character from input */ + +static int inchar(void) +{ + if (iocp >= iolen) { + if (!inbuf()) { + return EOF; + } + } + + return iobuf[iocp++]; +} + +/* OCHAR -- Output an encoded character, inserting line breaks + where required. */ + +static void ochar(int c) +{ + if (linelength >= LINELEN) { + if (fputs(eol, fo) == EOF) { + exit(1); + } + linelength = 0; + } + if (putc(((byte) c), fo) == EOF) { + exit(1); + } + linelength++; +} + +/* ENCODE -- Encode binary file into base64. */ + +static void encode(void) +{ + int i, hiteof = FALSE; + + /* Fill dtable with character encodings. */ + + for (i = 0; i < 26; i++) { + dtable[i] = 'A' + i; + dtable[26 + i] = 'a' + i; + } + for (i = 0; i < 10; i++) { + dtable[52 + i] = '0' + i; + } + dtable[62] = '+'; + dtable[63] = '/'; + + while (!hiteof) { + byte igroup[3], ogroup[4]; + int c, n; + + igroup[0] = igroup[1] = igroup[2] = 0; + for (n = 0; n < 3; n++) { + c = inchar(); + if (c == EOF) { + hiteof = TRUE; + break; + } + igroup[n] = (byte) c; + } + if (n > 0) { + ogroup[0] = dtable[igroup[0] >> 2]; + ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = dtable[igroup[2] & 0x3F]; + + /* Replace characters in output stream with "=" pad + characters if fewer than three characters were + read from the end of the input stream. */ + + if (n < 3) { + ogroup[3] = '='; + if (n < 2) { + ogroup[2] = '='; + } + } + for (i = 0; i < 4; i++) { + ochar(ogroup[i]); + } + } + } + if (fputs(eol, fo) == EOF) { + exit(1); + } +} + +/* INSIG -- Return next significant input */ + +static int insig(void) +{ + int c; + + /*CONSTANTCONDITION*/ + while (TRUE) { + c = inchar(); + if (c == EOF || (c > ' ')) { + return c; + } + } + /*NOTREACHED*/ +} + +/* DECODE -- Decode base64. */ + +static void decode(void) +{ + int i; + + for (i = 0; i < 255; i++) { + dtable[i] = 0x80; + } + for (i = 'A'; i <= 'Z'; i++) { + dtable[i] = 0 + (i - 'A'); + } + for (i = 'a'; i <= 'z'; i++) { + dtable[i] = 26 + (i - 'a'); + } + for (i = '0'; i <= '9'; i++) { + dtable[i] = 52 + (i - '0'); + } + dtable['+'] = 62; + dtable['/'] = 63; + dtable['='] = 0; + + /*CONSTANTCONDITION*/ + while (TRUE) { + byte a[4], b[4], o[3]; + + for (i = 0; i < 4; i++) { + int c = insig(); + + if (c == EOF) { + if (errcheck && (i > 0)) { + fprintf(stderr, "Input file incomplete.\n"); + exit(1); + } + return; + } + if (dtable[c] & 0x80) { + if (errcheck) { + fprintf(stderr, "Illegal character '%c' in input file.\n", c); + exit(1); + } + /* Ignoring errors: discard invalid character. */ + i--; + continue; + } + a[i] = (byte) c; + b[i] = (byte) dtable[c]; + } + o[0] = (b[0] << 2) | (b[1] >> 4); + o[1] = (b[1] << 4) | (b[2] >> 2); + o[2] = (b[2] << 6) | b[3]; + i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3); + if (fwrite(o, i, 1, fo) == EOF) { + exit(1); + } + if (i < 3) { + return; + } + } +} + +/* USAGE -- Print how-to-call information. */ + +static void usage(char *pname) +{ + fprintf(stderr, "%s -- Encode/decode file as base64. Call:\n", pname); + fprintf(stderr, + " %s [-e[ncode] / -d[ecode]] [-n] [infile] [outfile]\n", pname); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -D Decode base64 encoded file\n"); + fprintf(stderr, " -E Encode file into base64\n"); + fprintf(stderr, " -N Ignore errors when decoding\n"); + fprintf(stderr, " -U Print this message\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "by John Walker\n"); + fprintf(stderr, " WWW: http://www.fourmilab.ch/\n"); +} + +/* Main program */ + +int main(int argc, char *argv[]) +{ + int i, f = 0, decoding = FALSE; + char *cp, opt; + + for (i = 1; i < argc; i++) { + cp = argv[i]; + if (*cp == '-') { + opt = *(++cp); + if (islower(opt)) { + opt = toupper(opt); + } + switch (opt) { + + case 'D': /* -D Decode */ + decoding = TRUE; + break; + + case 'E': /* -E Encode */ + decoding = FALSE; + break; + + case 'N': /* -N Suppress error checking */ + errcheck = FALSE; + break; + + case 'U': /* -U Print how-to-call information */ + case '?': + usage(argv[0]); + return 0; + } + } else { + switch (f) { + + /** Warning! On systems which distinguish text mode and + binary I/O (MS-DOS, Macintosh, etc.) the modes in these + open statements will have to be made conditional based + upon whether an encode or decode is being done, which + will have to be specified earlier. But it's worse: if + input or output is from standard input or output, the + mode will have to be changed on the fly, which is + generally system and compiler dependent. 'Twasn't me + who couldn't conform to Unix CR/LF convention, so + don't ask me to write the code to work around + Apple and Microsoft's incompatible standards. **/ + + case 0: + if (strcmp(cp, "-") != 0) { + if ((fi = fopen(cp, "r")) == NULL) { + fprintf(stderr, "Cannot open input file %s\n", cp); + return 2; + } + } + f++; + break; + + case 1: + if (strcmp(cp, "-") != 0) { + if ((fo = fopen(cp, "w")) == NULL) { + fprintf(stderr, "Cannot open output file %s\n", cp); + return 2; + } + } + f++; + break; + + default: + fprintf(stderr, "Too many file names specified.\n"); + usage(argv[0]); + return 2; + } + } + } + + if (decoding) { + decode(); + } else { + encode(); + } + return 0; +} diff --git a/citadel/copyright.txt b/citadel/copyright.txt index 8a2a1cc37..fc7cf3a6a 100644 --- a/citadel/copyright.txt +++ b/citadel/copyright.txt @@ -7,6 +7,9 @@ Portions (c) 1998 by: Brian Costello Nathan Bryant +base64 encoding/decoding for MIME parser, public domain by: + John Walker + ------------------------------------------------------------------------------ The entire package is free software; you can redistribute diff --git a/citadel/mime_parser.c b/citadel/mime_parser.c index 2882033a5..9b21b25fc 100644 --- a/citadel/mime_parser.c +++ b/citadel/mime_parser.c @@ -11,7 +11,6 @@ #include #include -#include /* stu */ #include #include #include @@ -98,11 +97,6 @@ void mime_decode(char *partnum, size_t blocksize; int write_error = 0; - - int stu; - int stu2 = 0; - - /* If this part is not encoded, send as-is */ if (strlen(encoding)==0) { CallBack(name, filename, partnum, part_start, @@ -145,7 +139,7 @@ void mime_decode(char *partnum, close(sendpipe[1]); /* Close the ends we're not using */ close(recvpipe[0]); if (!strcasecmp(encoding, "base64")) - execlp("/usr/local/base64/base64", "base64", "-d", NULL); + execlp("./base64", "base64", "-d", NULL); else if (!strcasecmp(encoding, "7bit")) execlp("/bin/dd", "dd", NULL); lprintf(5, "ERROR: cannot exec decoder for %s\n", encoding); @@ -186,13 +180,6 @@ void mime_decode(char *partnum, lprintf(9, "Decoded length = %d\n", bytes_recv); - if (strlen(filename) ==0) sprintf(filename, "noname%d", stu2++); - chdir("stu"); - stu = creat(filename, 0666); - write(stu, decoded, bytes_recv); - close(stu); - chdir(".."); - if (bytes_recv > 0) CallBack(name, filename, partnum, decoded, content_type, bytes_recv); -- 2.39.2