uuencode.c
来自「UUDeview是一个编码解码器」· C语言 代码 · 共 1,795 行 · 第 1/4 页
C
1,795 行
/* * This file is part of uudeview, the simple and friendly multi-part multi- * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef SYSTEM_WINDLL#include <windows.h>#endif#ifdef SYSTEM_OS2#include <os2.h>#endif#include <sys/types.h>#include <sys/stat.h>#include <ctype.h>#include <stdio.h>#include <time.h>#ifdef STDC_HEADERS#include <stdlib.h>#include <string.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#include <uudeview.h>#include <uuint.h>#include <fptools.h>#include <uustring.h>#include <crc32.h>/* for braindead systems */#ifndef SEEK_SET#ifdef L_BEGIN#define SEEK_SET L_BEGIN#else#define SEEK_SET 0#endif#endifchar * uuencode_id = "$Id: uuencode.c,v 1.22 2002/04/02 10:04:52 fp Exp $";#if 0/* * the End-Of-Line string. MIME enforces CRLF, so that's what we use. Some * implementations of uudecode will complain about a missing end line, since * they look for "end^J" but find "end^J^M". We don't care - especially be- * cause they still decode the file properly despite this complaint. */#ifndef EOLSTRING#define EOLSTRING "\015\012"#endif#else/* * Argh. Some delivery software (inews) has problems with the CRLF * line termination. Let's try native EOL and see if we run into * any problems. * This involves opening output files in text mode instead of binary */#ifndef EOLSTRING#define EOLSTRING "\n"#endif#endif/* * ========================================================================= * User-configurable settings end here. Don't spy below unless you know what * you're doing. * ========================================================================= *//* * Define End-Of-Line sequence */#ifdef EOLSTRINGstatic unsigned char *eolstring = (unsigned char *) EOLSTRING;#elsestatic unsigned char *eolstring = (unsigned char *) "\012";#endif/* * Content-Transfer-Encoding types for non-MIME encodings */#define CTE_UUENC "x-uuencode"#define CTE_XXENC "x-xxencode"#define CTE_BINHEX "x-binhex"#define CTE_YENC "x-yenc"#define CTE_TYPE(y) (((y)==B64ENCODED) ? "Base64" : \ ((y)==UU_ENCODED) ? CTE_UUENC : \ ((y)==XX_ENCODED) ? CTE_XXENC : \ ((y)==PT_ENCODED) ? "8bit" : \ ((y)==QP_ENCODED) ? "quoted-printable" : \ ((y)==BH_ENCODED) ? CTE_BINHEX : \ ((y)==YENC_ENCODED) ? CTE_YENC : "x-oops")/* * encoding tables */unsigned char UUEncodeTable[64] = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',']', '^', '_'}; unsigned char B64EncodeTable[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};unsigned char XXEncodeTable[64] = { '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};unsigned char BHEncodeTable[64] = { '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '0', '1', '2', '3', '4', '5', '6', '8', '9', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '[', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'p', 'q', 'r'};unsigned char HexEncodeTable[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};typedef struct { char *extension; char *mimetype;} mimemap;/* * This table maps a file's extension into a Content-Type. The current * official list can be downloaded as * ftp://ftp.isi.edu/in-notes/iana/assignments/media-type * I haven't listed any text types since it doesn't make sense to encode * them. Everything not on the list gets mapped to application/octet-stream */static mimemap mimetable[] = { { "gif", "image/gif" }, /* Grafics Interchange Format */ { "jpg", "image/jpeg" }, /* JFIF encoded files */ { "jpeg", "image/jpeg" }, { "tif", "image/tiff" }, /* Tag Image File Format */ { "tiff", "image/tiff" }, { "cgm", "image/cgm" }, /* Computer Graphics Metafile */ { "au", "audio/basic" }, /* 8kHz ulaw audio data */ { "mov", "video/quicktime" }, /* Apple Quicktime */ { "qt", "video/quicktime" }, /* Also infrequently used */ { "mpeg", "video/mpeg" }, /* Motion Picture Expert Group */ { "mpg", "video/mpeg" }, { "mp2", "video/mpeg" }, /* dito, MPEG-2 encoded files */ { "mp3", "audio/mpeg" }, /* dito, MPEG-3 encoded files */ { "ps", "application/postscript" }, /* Postscript Language */ { "zip", "application/zip" }, /* ZIP archive */ { "doc", "application/msword"},/* assume Microsoft Word */ { NULL, NULL }};/* * the order of the following two tables must match the * Encoding Types definition in uudeview.h *//* * encoded bytes per line */static int bpl[8] = { 0, 45, 57, 45, 45, 0, 0, 128 };/* * tables */static unsigned char *etables[5] = { NULL, UUEncodeTable, B64EncodeTable, XXEncodeTable, BHEncodeTable};/* * variables to malloc upon initialization */char *uuestr_itemp;char *uuestr_otemp;/* * Encode one part of the data stream */static int UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile, crc32_t *crc, crc32_t *pcrc){ unsigned char *itemp = (char *) uuestr_itemp; unsigned char *otemp = (char *) uuestr_otemp; unsigned char *optr, *table, *tptr; int index, count; long line=0; size_t llen; if (outfile==NULL || infile==NULL || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeStream()"); return UURET_ILLVAL; } /* * Special handling for plain text and quoted printable. Text is * read line oriented. */ if (encoding == PT_ENCODED || encoding == QP_ENCODED) { while (!feof (infile) && (linperfile <= 0 || line < linperfile)) { if (_FP_fgets (itemp, 255, infile) == NULL) { break; } itemp[255] = '\0'; count = strlen (itemp); llen = 0; optr = otemp; /* * Busy Callback */ if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) { UUMessage (uuencode_id, __LINE__, UUMSG_NOTE, uustring (S_ENCODE_CANCEL)); return UURET_CANCEL; } if (encoding == PT_ENCODED) { /* * If there is a line feed, replace by eolstring */ if (count > 0 && itemp[count-1] == '\n') { itemp[--count] = '\0'; if (fwrite (itemp, 1, count, outfile) != count || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } } else { if (fwrite (itemp, 1, count, outfile) != llen) { return UURET_IOERR; } } } else if (encoding == QP_ENCODED) { for (index=0; index<count; index++) { if (llen == 0 && itemp[index] == '.') { /* * Special rule: encode '.' at the beginning of a line, so * that some mailers aren't confused. */ *optr++ = '='; *optr++ = HexEncodeTable[itemp[index] >> 4]; *optr++ = HexEncodeTable[itemp[index] & 0x0f]; llen += 3; } else if ((itemp[index] >= 33 && itemp[index] <= 60) || (itemp[index] >= 62 && itemp[index] <= 126) || itemp[index] == 9 || itemp[index] == 32) { *optr++ = itemp[index]; llen++; } else if (itemp[index] == '\n') { /* * If the last character before EOL was a space or tab, * we must encode it. If llen > 74, there's no space to do * that, so generate a soft line break instead. */ if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32)) { *(optr-1) = '='; if (llen <= 74) { *optr++ = HexEncodeTable[itemp[index-1] >> 4]; *optr++ = HexEncodeTable[itemp[index-1] & 0x0f]; llen += 2; } } if (fwrite (otemp, 1, llen, outfile) != llen || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } /* * Fix the soft line break condition from above */ if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32) && *(optr-1) == '=') { otemp[0] = '='; otemp[1] = HexEncodeTable[itemp[index-1] >> 4]; otemp[2] = HexEncodeTable[itemp[index-1] & 0x0f]; if (fwrite (otemp, 1, 3, outfile) != 3 || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } } optr = otemp; llen = 0; } else { *optr++ = '='; *optr++ = HexEncodeTable[itemp[index] >> 4]; *optr++ = HexEncodeTable[itemp[index] & 0x0f]; llen += 3; } /* * Lines must be shorter than 76 characters (not counting CRLF). * If the line grows longer than that, we must include a soft * line break. */ if (itemp[index+1] != 0 && itemp[index+1] != '\n' && (llen >= 75 || (!((itemp[index+1] >= 33 && itemp[index+1] <= 60) || (itemp[index+1] >= 62 && itemp[index+1] <= 126)) && llen >= 73))) { *optr++ = '='; llen++; if (fwrite (otemp, 1, llen, outfile) != llen || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } optr = otemp; llen = 0; } } } line++; } return UURET_OK; } /* * Special handling for yEnc */ if (encoding == YENC_ENCODED) { llen = 0; optr = otemp; while (!feof (infile) && (linperfile <= 0 || line < linperfile)) { if ((count = fread (itemp, 1, 128, infile)) != 128) { if (count == 0) { break; } else if (ferror (infile)) { return UURET_IOERR; } } if (pcrc) *pcrc = crc32(*pcrc, itemp, count); if (crc) *crc = crc32(*crc, itemp, count); line++; /* * Busy Callback */ if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) { UUMessage (uuencode_id, __LINE__, UUMSG_NOTE, uustring (S_ENCODE_CANCEL)); return UURET_CANCEL; } for (index=0; index<count; index++) { if (llen > 127) { if (fwrite (otemp, 1, llen, outfile) != llen || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?