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 + -
显示快捷键?