📄 sun2mime.c
字号:
/* * $Id: sun2mime.c,v 1.3 2000/06/07 16:10:01 evgeny Exp $ * * Copyright (c) 1994 HAL Computer Systems International, Ltd. * * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. * 1315 Dell Avenue * Campbell, CA 95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * 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. * * http://www.gnu.org/copyleft/gpl.html * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>/* * Name: sun2mime * * Function: Convert a mail message containing Sun mail attachments to a * MIME message. Input is file name, offset of start of message, * number of lines in the message, and output file name. * * Return code 0 = successful translation, 1 = something was wrong. * * Tom Lang * 8/94 */#include <errno.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#define XSUNATT "Content-Type: X-sun-attachment"#define XSUNDT "X-Sun-Data-Type: "#define XSUNDD "X-Sun-Data-Description: "#define XSUNDN "X-Sun-Data-Name: "#define XSUNEN "X-Sun-Encoding-Info: "#define XSUNCL "X-Sun-Content-Lines: "#define XSUNCLEN "X-Sun-Content-Length: "#define XSUNBDY "----------"#define XLINES "X-Lines: "#define CONTENTLENGTH "Content-Length: "#define CONTENTLINES "Content-Lines: "/*#define MIMEBDY "--bODY.pART.bOUNDARY"*/static char *mimebdy;#ifndef SEEK_SET#define SEEK_SET 0#endif/* Data type codes */#define T_UNK 0#define T_TEXT 1#define T_PS 2#define T_XBM 3#define T_XPM 4#define T_AUDIO 5#define T_GIF 6#define T_FRAME 7void convert();void convertPart();void convertText( int );void convertEncoded( int );void uu2base64();void setContentType( int, char *, int );void uuDecode( char * );int To64( FILE *, FILE *, int ); void copyPart( FILE * );void copyLines( FILE * );void findBegin( char * );/* * global variables */extern int debug1, debug2;static struct { int contentLength; int contentLines; int bannerLoc; int inconsistent; /* flag: inconsistent content-length or lines */ FILE *origFile; FILE *inFile; FILE *outFile; char line[2048];} g;/**************************************************************************/intsun2mime( char *in, int msgOffset, int bytes, char *out, char *bound ){ int inCount, outCount; char tmp[256]; struct stat stats; mimebdy = bound; g.inconsistent = 0; if(debug1 || debug2) { fprintf(stderr, "sun2mime called, offset = %i, length = %i\n", msgOffset, bytes); } /* * open the file to be converted */ if ((g.origFile = fopen( in, "r")) == NULL) { fprintf(stderr, "sun2mime: Message file: %s ", in); perror("Can't open for reading"); return(1); } /* * If file size was not passed in, figure it out now. */ if (bytes <= 0) { if (stat(in, &stats) == -1) { fprintf(stderr, "sun2mime: Message file: %s ", in); perror("Can't stat to find size"); return(1); } bytes = stats.st_size; } /* * Find the start of the message * (not necessarily the beginning of the file if this is a * Unix-style folder) */ fseek( g.origFile, msgOffset, SEEK_SET); if(debug2) { fgets(g.line, sizeof(g.line), g.origFile); fprintf(stderr, "First line:\n%s\n",g.line); fseek(g.origFile, msgOffset+bytes, SEEK_SET); if((fgets(g.line, sizeof(g.line), g.origFile)) != NULL) { fprintf(stderr, "First line of next msg:\n%s\n",g.line); } else { fprintf(stderr, "No data past end\n"); } fseek( g.origFile, msgOffset, SEEK_SET); } /* * open a temporary file to contain a copy of the input message. * note: this may be redundant, if the input message is the only * message in the file... */ tmpnam( tmp ); if((g.inFile = fopen( tmp, "w" )) == NULL) { perror("sun2mime: can't create temp file "); fclose(g.origFile); return(1); } /* * extract the message from the original input file */ while(bytes > 0) { inCount = (bytes>sizeof(g.line)) ? sizeof(g.line) : bytes; inCount = fread(g.line, 1, inCount, g.origFile); bytes -= inCount; if(bytes < 0) { fprintf(stderr, "sun2mime: WARNING: input file length not consistent\n"); } outCount = fwrite(g.line, 1, inCount, g.inFile); if(outCount != inCount) { fprintf(stderr, "sun2mime: WARNING: problem extracting msg\n"); } } fclose(g.origFile); fclose(g.inFile); if ((g.inFile = fopen( tmp, "r")) == NULL) { fprintf(stderr, "sun2mime: Message file: %s ", in); perror("Can't open for reading"); return(1); } /* * open a temporary file to contain the converted message * note: the name for this file was passed in from the caller */ if((g.outFile = fopen( out, "w" )) == NULL) { perror("sun2mime: can't create temp file "); fclose(g.inFile); return(1); } /* * read through the mail message headers. copy headers to output * until Sun-Attachment found or end of headers. */ if(debug2) { fprintf(stderr, "Looking for a Sun attachment\n"); } while((fgets(g.line, sizeof(g.line), g.inFile)) != NULL) { /* * look for blank line, indicating end of mail headers */ if( strlen(g.line) == 1 ) { fputc('\n', g.outFile); break; } /* * look for "Content-Type: X-Sun-Attachment" mail header * if found, call conversion routine, which will process * the rest of the message. */ if( strncasecmp( g.line, XSUNATT, sizeof(XSUNATT)-1 ) == 0 ) { convert(); break; } /* * copy header line to output, unless it's Content-Length, * Content-Lines, or X-Lines - this would be confusing... */ if((strncasecmp( g.line, CONTENTLENGTH, sizeof(CONTENTLENGTH)-1 ) != 0) && (strncasecmp( g.line, CONTENTLINES, sizeof(CONTENTLINES)-1 ) != 0) && (strncasecmp( g.line, XLINES, sizeof(XLINES)-1 ) != 0)) { fputs(g.line, g.outFile); } } /* * If previous loop terminated because end of headers reached * without finding that the message has Sun attachments, this * loop will copy the remainder of the message. Else, there * won't be anything left to copy. * * note: this function shouldn't be called unless there are * Sun attachments, so there shouldn't be anything left... */ while((fgets(g.line, sizeof(g.line), g.inFile)) != NULL) { fputs(g.line, g.outFile); } /* * close files */ fclose(g.inFile); unlink(tmp); /* delete temporary file */ fclose(g.outFile); return(0);}/* * subroutine: convert Sun attachment format to MIME format. */voidconvert() { /* * output standard headers */ if(debug1 || debug2) { fprintf(stderr, "Found a message with one or more Sun attachments\n"); } fputs("Mime-Version: 1.0\n", g.outFile); fputs("Content-Type: multipart/mixed;\n\tboundary=\"", g.outFile); fputs(mimebdy, g.outFile); fputs("\"\n", g.outFile); /* * copy rest of the mail message headers */ while((fgets(g.line, sizeof(g.line), g.inFile)) != NULL) { fputs(g.line, g.outFile); /* * look for blank line, indicating end of mail headers */ if( strlen(g.line) == 1 ) { break; } } /* * output informative message */ fputs("--", g.outFile); fputs(mimebdy, g.outFile); fputc('\n', g.outFile); fputs("Content-Type: text/plain\n", g.outFile); fputs("Content-Description: conversion information\n", g.outFile); fputc('\n', g.outFile); fputs("******************************************************************************\n", g.outFile); fputs("*** This message was converted from Sun mailtool format to MIME by Ishmail ***\n", g.outFile); g.bannerLoc = ftell(g.outFile); fputs("******************************************************************************\n", g.outFile); fputc('\n', g.outFile); /* * look for body parts, convert each one */ while((fgets(g.line, sizeof(g.line), g.inFile)) != NULL) { /* * look for body part boundary */ if( strncasecmp( g.line, XSUNBDY, sizeof(XSUNBDY)-1 ) == 0 ) { fputs("--", g.outFile); fputs(mimebdy, g.outFile); fputc('\n', g.outFile); if(debug1 || debug2) { fprintf(stderr, "Found a body part to convert\n"); } convertPart(); } /* * we don't expect to find extraneous lines between body * parts, if the content length is correct, but if there * are any - just copy them */ else fputs(g.line, g.outFile); } /* * output final body part boundary and trailing blank line */ fputs("--", g.outFile); fputs(mimebdy, g.outFile); fputs("--\n\n", g.outFile); /* * if inconsistent or missing content-length/lines info, * update the banner with a warning */ if (g.inconsistent) { fseek(g.outFile, g.bannerLoc, SEEK_SET); fputs("*** NOTE: Inconsistent content-length info makes the conversion suspect... ***\n",g.outFile); }}#define DESC_SIZE 256#define NAME_SIZE 256#define ENCODE_SIZE 128/* * subroutine: Determine body part type and process it. */voidconvertPart(){ int type; char *p; int isUU = 0; char desc[DESC_SIZE] = ""; char name[NAME_SIZE] = ""; char encoding[ENCODE_SIZE] = ""; /* * look through body part headers for: * data type * transfer encoding method * body part description * ... others silently ignored */ if(debug2) { fprintf(stderr, "Looking for body part headers...\n"); } while((fgets(g.line, sizeof(g.line), g.inFile)) != NULL) { /* * end of headers ? */ if( strlen(g.line) == 1 ) { if(debug2) { fprintf(stderr, "End of body part headers.\n"); } break; } /* * data type ? */ if( strncasecmp( g.line, XSUNDT, sizeof(XSUNDT)-1 ) == 0 ) { p = g.line + sizeof(XSUNDT)-1; if( strncasecmp( p, "text", sizeof("text")-1 ) == 0 ) { type = T_TEXT; } else if( strncasecmp( p, "postscript-file", sizeof("postscript-file")-1 ) == 0 ) { type = T_PS;#if 0 } else if( strncasecmp( p, "c-file", sizeof("c-file")-1 ) == 0 ) { type = T_TEXT;#endif } else if( strncasecmp( p, "xbm-file", sizeof("xbm-file")-1 ) == 0 ) { type = T_XBM; } else if( strncasecmp( p, "xpm-file", sizeof("xpm-file")-1 ) == 0 ) { type = T_XPM; } else if( strncasecmp( p, "audio-file", sizeof("audio-file")-1 ) == 0 ) { type = T_AUDIO; } else if( strncasecmp( p, "gif-file", sizeof("gif-file")-1 ) == 0 ) { type = T_GIF; } else if( strncasecmp( p, "framemaker-document", sizeof("framemaker-document")-1 ) == 0 ) { type = T_FRAME; } else { type = T_UNK; } if(debug2) { fprintf(stderr, "Data type header found, type = %i\n", type); } continue; } /* * data description ? */ if( strncasecmp( g.line, XSUNDD, sizeof(XSUNDD)-1) == 0 ) { p = g.line + sizeof(XSUNDD)-1; /* * truncate description, if necessary */ strncat( desc, p, DESC_SIZE ); p = strrchr( desc, '\n' ); if(p != NULL) *p = '\0'; if(debug2) { fprintf(stderr, "Description: %s\n",desc); } continue; } /* * data name ? */ if( strncasecmp( g.line, XSUNDN, sizeof(XSUNDN)-1) == 0 ) { p = g.line + sizeof(XSUNDN)-1; strncat( name, p, NAME_SIZE ); p = strrchr( name, '\n' ); if(p != NULL) *p = '\0'; if(debug2) { fprintf(stderr, "Data name: %s\n",name); } continue; } /* * transfer encoding ? */ if( strncasecmp( g.line, XSUNEN, sizeof(XSUNEN)-1) == 0 ) { p = g.line + sizeof(XSUNEN)-1; isUU = parseEncode( p, encoding ); if(debug2) { fprintf(stderr, "Transfer encoding: %s uuencode = %i\n",p, isUU); } } /* * content length ? */ if( strncasecmp( g.line, XSUNCLEN, sizeof(XSUNCLEN)-1) == 0 ) { p = g.line + sizeof(XSUNCLEN)-1; g.contentLength = atoi(p); if(debug2) { fprintf(stderr, "Content length: %i\n", g.contentLength); } } /* * content lines ? */ if( strncasecmp( g.line, XSUNCL, sizeof(XSUNCL)-1) == 0 ) { p = g.line + sizeof(XSUNCL)-1; g.contentLines = atoi(p); if(debug2) { fprintf(stderr, "Content lines: %i\n", g.contentLines); } } /* * we don't expect to find extraneous headers, * but if there are any - just copy them */ else fputs(g.line, g.outFile); } /* End - look through headers for this body part */ /* * Before processing the remainder of the body part, * see if it needs to be uudecoded (then base64 encoded) */ if( isUU ) { findBegin( &name[0] ); } /* * output content type header, based on input type code and * input transfer encoding. */ setContentType( type, name, isUU ); /* * output description and encoding headers, followed by blank line */ fprintf( g.outFile, "Content-Description: %s\n", desc ); if( strlen(encoding) > (int)0 ) fprintf( g.outFile, "Content-Transfer-Encoding: %s\n", encoding ); fputc('\n', g.outFile); /* * if uuencoded body part, decode and re-encode as base64 */ if ( isUU ) { uu2base64(); } /* * If not uuencoded, just pass the data through. It must just be * some form of ASCII text. */ else { copyPart( g.outFile ); } /* * body part processed, end it with a blank * line and return. */ fputc('\n', g.outFile);}/* * subroutine: parse the transfer encoding line, look for uuencode * return 1 is uuencoded, 0 otherwise * also, the string pointed to by "encoding" is appended to. * * input: updated string: return val: * uuencode base64 1 * <any>, uuencode base64 1 * <other> <input string> 0 * * The middle case is only seen with audio files, where <any> is * "adpcm-compress". The third case should never be seen, but if it is the * data will be passed through unchanged. */intparseEncode( char *line, char *encoding ){ char *p; /* * uuencode ? */ if( strncasecmp( line, "uuencode", sizeof("uuencode")-1 ) == 0 ) { /* * indicate what data will be after conversion */ strcpy( encoding, "base64"); return(1); } /* * two attributes, comma separated ? */ p = strchr( line, (int)',' ); if( p == NULL ) { strncpy( encoding, line, ENCODE_SIZE ); p = strrchr( encoding, '\n' ); if (p != NULL) *p = '\0'; return(0); } /* * <any>, uuencode ? */ p++; /* skip over the comma */ if( *p == ' ' ) p++; /* skip over blank, if any */ if( strncasecmp( p, "uuencode", sizeof("uuencode")-1 ) == 0 ) { /* * indicate what data will be after conversion */ strcpy( encoding, "base64"); return(1); } strncpy( encoding, line, ENCODE_SIZE ); p = strrchr( encoding, '\n' );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -