1231 lines
33 KiB
C
1231 lines
33 KiB
C
|
/*
|
||
|
* This file is part of uudeview, the simple and friendly multi-part multi-
|
||
|
* file uudecoder program (c) 1994 by Frank Pilhofer. The author may be
|
||
|
* contacted by his email address, fp@informatik.uni-frankfurt.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>
|
||
|
|
||
|
/* for braindead systems */
|
||
|
#ifndef SEEK_SET
|
||
|
#ifdef L_BEGIN
|
||
|
#define SEEK_SET L_BEGIN
|
||
|
#else
|
||
|
#define SEEK_SET 0
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
char * uuencode_id = "$Id$";
|
||
|
|
||
|
#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 EOLSTRING
|
||
|
static unsigned char *eolstring = (unsigned char *) EOLSTRING;
|
||
|
#else
|
||
|
static 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_TYPE(y) (((y)==B64ENCODED) ? "Base64" : \
|
||
|
((y)==UU_ENCODED) ? CTE_UUENC : \
|
||
|
((y)==XX_ENCODED) ? CTE_XXENC : \
|
||
|
((y)==BH_ENCODED) ? CTE_BINHEX : "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'
|
||
|
};
|
||
|
|
||
|
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", "video/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[5] = { 0, 45, 57, 45, 45 };
|
||
|
|
||
|
/*
|
||
|
* 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)
|
||
|
{
|
||
|
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)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodeStream()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* select charset
|
||
|
*/
|
||
|
|
||
|
table = etables[encoding];
|
||
|
|
||
|
if (table==NULL || bpl[encoding]==0) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodeStream()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
while (!feof (infile) && (linperfile <= 0 || line < linperfile)) {
|
||
|
if ((count = fread (itemp, 1, bpl[encoding], infile)) != bpl[encoding]) {
|
||
|
if (count == 0)
|
||
|
break;
|
||
|
else if (ferror (infile))
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
optr = otemp;
|
||
|
llen = 0;
|
||
|
|
||
|
/*
|
||
|
* Busy Callback
|
||
|
*/
|
||
|
|
||
|
if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_NOTE,
|
||
|
uustring (S_ENCODE_CANCEL));
|
||
|
return UURET_CANCEL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* for UU and XX, encode the number of bytes as first character
|
||
|
*/
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
*optr++ = table[count];
|
||
|
llen++;
|
||
|
}
|
||
|
|
||
|
for (index=0; index<=count-3; index+=3, llen+=4) {
|
||
|
*optr++ = table[itemp[index] >> 2];
|
||
|
*optr++ = table[((itemp[index ] & 0x03) << 4) | (itemp[index+1] >> 4)];
|
||
|
*optr++ = table[((itemp[index+1] & 0x0f) << 2) | (itemp[index+2] >> 6)];
|
||
|
*optr++ = table[ itemp[index+2] & 0x3f];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Special handling for incomplete lines
|
||
|
*/
|
||
|
if (index != count) {
|
||
|
if (encoding == B64ENCODED) {
|
||
|
if (count - index == 2) {
|
||
|
*optr++ = table[itemp[index] >> 2];
|
||
|
*optr++ = table[((itemp[index ] & 0x03) << 4) |
|
||
|
((itemp[index+1] & 0xf0) >> 4)];
|
||
|
*optr++ = table[((itemp[index+1] & 0x0f) << 2)];
|
||
|
*optr++ = '=';
|
||
|
}
|
||
|
else if (count - index == 1) {
|
||
|
*optr++ = table[ itemp[index] >> 2];
|
||
|
*optr++ = table[(itemp[index] & 0x03) << 4];
|
||
|
*optr++ = '=';
|
||
|
*optr++ = '=';
|
||
|
}
|
||
|
llen += 4;
|
||
|
}
|
||
|
else {
|
||
|
if (count - index == 2) {
|
||
|
*optr++ = table[itemp[index] >> 2];
|
||
|
*optr++ = table[((itemp[index ] & 0x03) << 4) |
|
||
|
( itemp[index+1] >> 4)];
|
||
|
*optr++ = table[((itemp[index+1] & 0x0f) << 2)];
|
||
|
*optr++ = table[0];
|
||
|
}
|
||
|
else if (count - index == 1) {
|
||
|
*optr++ = table[ itemp[index] >> 2];
|
||
|
*optr++ = table[(itemp[index] & 0x03) << 4];
|
||
|
*optr++ = table[0];
|
||
|
*optr++ = table[0];
|
||
|
}
|
||
|
llen += 4;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* end of line
|
||
|
*/
|
||
|
tptr = eolstring;
|
||
|
|
||
|
while (*tptr)
|
||
|
*optr++ = *tptr++;
|
||
|
|
||
|
*optr++ = '\0';
|
||
|
llen += strlen ((char *) eolstring);
|
||
|
|
||
|
if (fwrite (otemp, 1, llen, outfile) != llen)
|
||
|
return UURET_IOERR;
|
||
|
|
||
|
line++;
|
||
|
}
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Encode as MIME multipart/mixed sub-message.
|
||
|
*/
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUEncodeMulti (FILE *outfile, FILE *infile, char *infname, int encoding,
|
||
|
char *outfname, char *mimetype, int filemode)
|
||
|
{
|
||
|
mimemap *miter=mimetable;
|
||
|
struct stat finfo;
|
||
|
int res, themode;
|
||
|
FILE *theifile;
|
||
|
char *ptr;
|
||
|
|
||
|
if (outfile==NULL ||
|
||
|
(infile == NULL && infname==NULL) ||
|
||
|
(outfname==NULL && infname==NULL) ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodeMulti()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
progress.action = 0;
|
||
|
|
||
|
if (infile==NULL) {
|
||
|
if (stat (infname, &finfo) == -1) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_STAT_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if ((theifile = fopen (infname, "rb")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
|
||
|
progress.fsize = (long) finfo.st_size;
|
||
|
}
|
||
|
else {
|
||
|
if (fstat (fileno (infile), &finfo) != 0) {
|
||
|
themode = (filemode)?filemode:0644;
|
||
|
progress.fsize = -1;
|
||
|
}
|
||
|
else {
|
||
|
themode = (int) finfo.st_mode & 0777;
|
||
|
progress.fsize = (long) finfo.st_size;
|
||
|
}
|
||
|
theifile = infile;
|
||
|
}
|
||
|
|
||
|
if (progress.fsize <= 0)
|
||
|
progress.fsize = -1;
|
||
|
|
||
|
_FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
|
||
|
|
||
|
progress.partno = 1;
|
||
|
progress.numparts = 1;
|
||
|
progress.percent = 0;
|
||
|
progress.foffset = 0;
|
||
|
progress.action = UUACT_ENCODING;
|
||
|
|
||
|
/*
|
||
|
* If not given from outside, select an appropriate Content-Type by
|
||
|
* looking at the file's extension. If it is unknown, default to
|
||
|
* Application/Octet-Stream
|
||
|
*/
|
||
|
|
||
|
if (mimetype == NULL) {
|
||
|
if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) {
|
||
|
while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
|
||
|
miter++;
|
||
|
mimetype = miter->mimetype;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* print sub-header
|
||
|
*/
|
||
|
|
||
|
fprintf (outfile, "Content-Type: %s%s",
|
||
|
(mimetype)?mimetype:"Application/Octet-Stream",
|
||
|
eolstring);
|
||
|
fprintf (outfile, "Content-Transfer-Encoding: %s%s",
|
||
|
CTE_TYPE(encoding), eolstring);
|
||
|
fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s",
|
||
|
UUFNameFilter ((outfname)?outfname:infname), eolstring);
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
fprintf (outfile, "begin %o %s%s",
|
||
|
(themode) ? themode : 0644,
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
}
|
||
|
if ((res = UUEncodeStream (outfile, theifile, encoding, 0)) != UURET_OK) {
|
||
|
if (res != UURET_CANCEL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_ERR_ENCODING),
|
||
|
UUFNameFilter ((infname)?infname:outfname),
|
||
|
(res==UURET_IOERR)?strerror(uu_errno):UUstrerror(res));
|
||
|
}
|
||
|
progress.action = 0;
|
||
|
return res;
|
||
|
}
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
fprintf (outfile, "%c%s",
|
||
|
(encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
|
||
|
eolstring);
|
||
|
fprintf (outfile, "end%s", eolstring);
|
||
|
}
|
||
|
/*
|
||
|
* empty line at end does no harm
|
||
|
*/
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
if (infile==NULL)
|
||
|
fclose (theifile);
|
||
|
|
||
|
progress.action = 0;
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Encode as MIME message/partial
|
||
|
*/
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUEncodePartial (FILE *outfile, FILE *infile,
|
||
|
char *infname, int encoding,
|
||
|
char *outfname, char *mimetype,
|
||
|
int filemode, int partno, long linperfile)
|
||
|
{
|
||
|
mimemap *miter=mimetable;
|
||
|
static FILE *theifile;
|
||
|
int themode, numparts;
|
||
|
struct stat finfo;
|
||
|
long thesize;
|
||
|
char *ptr;
|
||
|
int res;
|
||
|
|
||
|
if ((outfname==NULL&&infname==NULL) || partno<=0 ||
|
||
|
(infile == NULL&&infname==NULL) || outfile==NULL ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodePartial()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* The first part needs a set of headers
|
||
|
*/
|
||
|
|
||
|
progress.action = 0;
|
||
|
|
||
|
if (partno == 1) {
|
||
|
if (infile==NULL) {
|
||
|
if (stat (infname, &finfo) == -1) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_STAT_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if ((theifile = fopen (infname, "rb")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
|
||
|
thesize = (long) finfo.st_size;
|
||
|
}
|
||
|
else {
|
||
|
if (fstat (fileno (infile), &finfo) != 0) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_WARNING,
|
||
|
uustring (S_STAT_ONE_PART));
|
||
|
numparts = 1;
|
||
|
themode = (filemode)?filemode:0644;
|
||
|
thesize = 0;
|
||
|
}
|
||
|
else {
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
themode = (int) finfo.st_mode & 0777;
|
||
|
thesize = (long) finfo.st_size;
|
||
|
}
|
||
|
theifile = infile;
|
||
|
}
|
||
|
|
||
|
_FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
|
||
|
|
||
|
progress.totsize = (thesize>0) ? thesize : -1;
|
||
|
progress.partno = 1;
|
||
|
progress.numparts = numparts;
|
||
|
progress.percent = 0;
|
||
|
progress.foffset = 0;
|
||
|
|
||
|
/*
|
||
|
* If not given from outside, select an appropriate Content-Type by
|
||
|
* looking at the file's extension. If it is unknown, default to
|
||
|
* Application/Octet-Stream
|
||
|
*/
|
||
|
|
||
|
if (mimetype == NULL) {
|
||
|
if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) {
|
||
|
while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
|
||
|
miter++;
|
||
|
mimetype = miter->mimetype;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* print sub-header
|
||
|
*/
|
||
|
|
||
|
fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
|
||
|
fprintf (outfile, "Content-Type: %s%s",
|
||
|
(mimetype)?mimetype:"Application/Octet-Stream",
|
||
|
eolstring);
|
||
|
fprintf (outfile, "Content-Transfer-Encoding: %s%s",
|
||
|
CTE_TYPE(encoding), eolstring);
|
||
|
fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s",
|
||
|
UUFNameFilter ((outfname)?outfname:infname), eolstring);
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
/*
|
||
|
* for the first part of UU or XX messages, print a begin line
|
||
|
*/
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
fprintf (outfile, "begin %o %s%s",
|
||
|
(themode) ? themode : ((filemode)?filemode:0644),
|
||
|
UUFNameFilter ((outfname)?outfname:infname), eolstring);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* update progress information
|
||
|
*/
|
||
|
|
||
|
progress.partno = partno;
|
||
|
progress.percent = 0;
|
||
|
progress.foffset = ftell (theifile);
|
||
|
|
||
|
if (progress.totsize <= 0)
|
||
|
progress.fsize = -1;
|
||
|
else if (linperfile <= 0)
|
||
|
progress.fsize = progress.totsize;
|
||
|
else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize)
|
||
|
progress.fsize = progress.totsize - progress.foffset;
|
||
|
else
|
||
|
progress.fsize = linperfile*bpl[encoding];
|
||
|
|
||
|
progress.action = UUACT_ENCODING;
|
||
|
|
||
|
if ((res = UUEncodeStream (outfile, theifile,
|
||
|
encoding, linperfile)) != UURET_OK) {
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
if (res != UURET_CANCEL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_ERR_ENCODING),
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
(res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
|
||
|
}
|
||
|
progress.action = 0;
|
||
|
return res;
|
||
|
}
|
||
|
/*
|
||
|
* print end line
|
||
|
*/
|
||
|
if (feof (theifile) &&
|
||
|
(encoding == UU_ENCODED || encoding == XX_ENCODED)) {
|
||
|
fprintf (outfile, "%c%s",
|
||
|
(encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
|
||
|
eolstring);
|
||
|
fprintf (outfile, "end%s", eolstring);
|
||
|
}
|
||
|
/*
|
||
|
* empty line at end does no harm
|
||
|
*/
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
if (infile==NULL) {
|
||
|
if (res != UURET_OK) {
|
||
|
progress.action = 0;
|
||
|
fclose (theifile);
|
||
|
return res;
|
||
|
}
|
||
|
if (feof (theifile)) {
|
||
|
progress.action = 0;
|
||
|
fclose (theifile);
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
return UURET_CONT;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* leave progress.action as-is
|
||
|
*/
|
||
|
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* send output to a stream, don't do any headers at all
|
||
|
*/
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUEncodeToStream (FILE *outfile, FILE *infile,
|
||
|
char *infname, int encoding,
|
||
|
char *outfname, int filemode)
|
||
|
{
|
||
|
struct stat finfo;
|
||
|
FILE *theifile;
|
||
|
int themode;
|
||
|
int res;
|
||
|
|
||
|
if (outfile==NULL ||
|
||
|
(infile == NULL&&infname==NULL) ||
|
||
|
(outfname==NULL&&infname==NULL) ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodeToStream()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
progress.action = 0;
|
||
|
|
||
|
if (infile==NULL) {
|
||
|
if (stat (infname, &finfo) == -1) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_STAT_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if ((theifile = fopen (infname, "rb")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
|
||
|
progress.fsize = (long) finfo.st_size;
|
||
|
}
|
||
|
else {
|
||
|
if (fstat (fileno (infile), &finfo) == -1) {
|
||
|
/* gotta live with it */
|
||
|
themode = 0644;
|
||
|
progress.fsize = -1;
|
||
|
}
|
||
|
else {
|
||
|
themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
|
||
|
progress.fsize = (long) finfo.st_size;
|
||
|
}
|
||
|
theifile = infile;
|
||
|
}
|
||
|
|
||
|
if (progress.fsize <= 0)
|
||
|
progress.fsize = -1;
|
||
|
|
||
|
_FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
|
||
|
|
||
|
progress.partno = 1;
|
||
|
progress.numparts = 1;
|
||
|
progress.percent = 0;
|
||
|
progress.foffset = 0;
|
||
|
progress.action = UUACT_ENCODING;
|
||
|
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
fprintf (outfile, "begin %o %s%s",
|
||
|
(themode) ? themode : 0644,
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
}
|
||
|
if ((res = UUEncodeStream (outfile, theifile, encoding, 0)) != UURET_OK) {
|
||
|
if (res != UURET_CANCEL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_ERR_ENCODING),
|
||
|
UUFNameFilter ((infname)?infname:outfname),
|
||
|
(res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
|
||
|
}
|
||
|
progress.action = 0;
|
||
|
return res;
|
||
|
}
|
||
|
if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
|
||
|
fprintf (outfile, "%c%s",
|
||
|
(encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
|
||
|
eolstring);
|
||
|
fprintf (outfile, "end%s", eolstring);
|
||
|
}
|
||
|
/*
|
||
|
* empty line at end does no harm
|
||
|
*/
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
progress.action = 0;
|
||
|
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Encode to files on disk, don't generate any headers
|
||
|
*/
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUEncodeToFile (FILE *infile, char *infname, int encoding,
|
||
|
char *outfname, char *diskname, long linperfile)
|
||
|
{
|
||
|
int part, numparts, len, filemode, res;
|
||
|
char *oname=NULL, *optr, *ptr;
|
||
|
FILE *theifile, *outfile;
|
||
|
struct stat finfo;
|
||
|
|
||
|
if ((diskname==NULL&&infname==NULL) ||
|
||
|
(outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUEncodeToFile()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
if (diskname) {
|
||
|
if ((ptr = strchr (diskname, '/')) == NULL)
|
||
|
ptr = strchr (diskname, '\\');
|
||
|
if (ptr) {
|
||
|
len = strlen (diskname) + ((uuencodeext)?strlen(uuencodeext):3) + 5;
|
||
|
|
||
|
if ((oname = malloc (len)) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_OUT_OF_MEMORY), len);
|
||
|
return UURET_NOMEM;
|
||
|
}
|
||
|
sprintf (oname, "%s", diskname);
|
||
|
}
|
||
|
else {
|
||
|
len = ((uusavepath)?strlen(uusavepath):0) + strlen (diskname)
|
||
|
+ ((uuencodeext)?strlen(uuencodeext):0) + 5;
|
||
|
|
||
|
if ((oname = malloc (len)) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_OUT_OF_MEMORY), len);
|
||
|
return UURET_NOMEM;
|
||
|
}
|
||
|
sprintf (oname, "%s%s", (uusavepath)?uusavepath:"", diskname);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
len = ((uusavepath) ? strlen (uusavepath) : 0) +
|
||
|
strlen(UUFNameFilter(infname)) +
|
||
|
((uuencodeext)?strlen(uuencodeext):0) + 5;
|
||
|
|
||
|
if ((oname = malloc (len)) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_OUT_OF_MEMORY), len);
|
||
|
return UURET_NOMEM;
|
||
|
}
|
||
|
optr = UUFNameFilter (infname);
|
||
|
sprintf (oname, "%s%s",
|
||
|
(uusavepath)?uusavepath:"",
|
||
|
(*optr=='.')?optr+1:optr);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* optr points after the last dot, so that we can print the part number
|
||
|
* there.
|
||
|
*/
|
||
|
|
||
|
optr = _FP_strrchr (oname, '.');
|
||
|
if (optr==NULL || strchr (optr, '/')!=NULL || strchr (optr, '\\')!=NULL) {
|
||
|
optr = oname + strlen (oname);
|
||
|
*optr++ = '.';
|
||
|
}
|
||
|
else if (optr==oname || *(optr-1)=='/' || *(optr-1)=='\\') {
|
||
|
optr = oname + strlen (oname);
|
||
|
*optr++ = '.';
|
||
|
}
|
||
|
else
|
||
|
optr++;
|
||
|
|
||
|
progress.action = 0;
|
||
|
|
||
|
if (infile==NULL) {
|
||
|
if (stat (infname, &finfo) == -1) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_STAT_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
_FP_free (oname);
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if ((theifile = fopen (infname, "rb")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
_FP_free (oname);
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size + (linperfile*bpl[encoding]-1)) /
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
filemode = (int) finfo.st_mode & 0777;
|
||
|
progress.totsize = (long) finfo.st_size;
|
||
|
}
|
||
|
else {
|
||
|
if (fstat (fileno (infile), &finfo) == -1) {
|
||
|
/* gotta live with it */
|
||
|
filemode = 0644;
|
||
|
numparts = -1;
|
||
|
progress.totsize = -1;
|
||
|
}
|
||
|
else {
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
filemode = (int) finfo.st_mode & 0777;
|
||
|
progress.totsize = -1;
|
||
|
}
|
||
|
theifile = infile;
|
||
|
}
|
||
|
|
||
|
_FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
|
||
|
|
||
|
progress.totsize = (progress.totsize<=0) ? -1 : progress.totsize;
|
||
|
progress.numparts = numparts;
|
||
|
|
||
|
for (part=1; !feof (theifile); part++) {
|
||
|
/*
|
||
|
* Attach extension
|
||
|
*/
|
||
|
if (progress.numparts==1 && progress.totsize!=-1 && uuencodeext!=NULL)
|
||
|
strcpy (optr, uuencodeext);
|
||
|
else
|
||
|
sprintf (optr, "%03d", part);
|
||
|
|
||
|
/*
|
||
|
* check if target file exists
|
||
|
*/
|
||
|
|
||
|
if (!uu_overwrite) {
|
||
|
if (stat (oname, &finfo) == 0) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_TARGET_EXISTS), oname);
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
progress.action = 0;
|
||
|
free (oname);
|
||
|
return UURET_EXISTS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* update progress information
|
||
|
*/
|
||
|
|
||
|
progress.action = 0;
|
||
|
progress.partno = part;
|
||
|
progress.percent = 0;
|
||
|
progress.foffset = ftell (theifile);
|
||
|
|
||
|
if (progress.totsize == -1)
|
||
|
progress.fsize = -1;
|
||
|
else if (linperfile <= 0)
|
||
|
progress.fsize = progress.totsize;
|
||
|
else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize)
|
||
|
progress.fsize = progress.totsize - progress.foffset;
|
||
|
else
|
||
|
progress.fsize = linperfile*bpl[encoding];
|
||
|
|
||
|
progress.action = UUACT_ENCODING;
|
||
|
|
||
|
if ((outfile = fopen (oname, "w")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_TARGET),
|
||
|
oname, strerror (uu_errno = errno));
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
progress.action = 0;
|
||
|
free (oname);
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
fprintf (outfile, "_=_ %s", eolstring);
|
||
|
if (numparts == -1)
|
||
|
fprintf (outfile, "_=_ Part %03d of file %s%s",
|
||
|
part, UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
else
|
||
|
fprintf (outfile, "_=_ Part %03d of %03d of file %s%s",
|
||
|
part, numparts,
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
fprintf (outfile, "_=_ %s", eolstring);
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
if (part==1 && (encoding == UU_ENCODED || encoding == XX_ENCODED)) {
|
||
|
fprintf (outfile, "begin %o %s%s",
|
||
|
(filemode)?filemode : 0644,
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
}
|
||
|
if ((res = UUEncodeStream (outfile, theifile,
|
||
|
encoding, linperfile)) != UURET_OK) {
|
||
|
if (res != UURET_CANCEL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_ERR_ENCODING),
|
||
|
UUFNameFilter ((infname)?infname:outfname),
|
||
|
(res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
|
||
|
}
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
progress.action = 0;
|
||
|
fclose (outfile);
|
||
|
unlink (oname);
|
||
|
_FP_free (oname);
|
||
|
return res;
|
||
|
}
|
||
|
if (feof (theifile) &&
|
||
|
(encoding == UU_ENCODED || encoding == XX_ENCODED)) {
|
||
|
fprintf (outfile, "%c%s",
|
||
|
(encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
|
||
|
eolstring);
|
||
|
fprintf (outfile, "end%s", eolstring);
|
||
|
}
|
||
|
/*
|
||
|
* empty line at end does no harm
|
||
|
*/
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
fclose (outfile);
|
||
|
}
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
progress.action = 0;
|
||
|
_FP_free (oname);
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Encode a MIME Mail message or Newsgroup posting and send to a
|
||
|
* stream. Still needs a somewhat smart MDA, since we only gene-
|
||
|
* rate a minimum set of headers.
|
||
|
*/
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUE_PrepSingle (FILE *outfile, FILE *infile,
|
||
|
char *infname, int encoding,
|
||
|
char *outfname, int filemode,
|
||
|
char *destination, char *from,
|
||
|
char *subject, int isemail)
|
||
|
{
|
||
|
mimemap *miter=mimetable;
|
||
|
char *subline, *oname;
|
||
|
char *mimetype, *ptr;
|
||
|
int res, len;
|
||
|
|
||
|
if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUE_PrepSingle()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
oname = UUFNameFilter ((outfname)?outfname:infname);
|
||
|
len = ((subject)?strlen(subject):0) + strlen(oname) + 40;
|
||
|
|
||
|
if ((ptr = _FP_strrchr (oname, '.'))) {
|
||
|
while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
|
||
|
miter++;
|
||
|
mimetype = miter->mimetype;
|
||
|
}
|
||
|
else
|
||
|
mimetype = NULL;
|
||
|
|
||
|
if ((subline = (char *) malloc (len)) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_OUT_OF_MEMORY), len);
|
||
|
return UURET_NOMEM;
|
||
|
}
|
||
|
|
||
|
if (subject)
|
||
|
sprintf (subline, "%s (001/001) - [ %s ]", subject, oname);
|
||
|
else
|
||
|
sprintf (subline, "[ %s ] (001/001)", oname);
|
||
|
|
||
|
fprintf (outfile, "Subject: %s%s", subline, eolstring);
|
||
|
|
||
|
if (from) {
|
||
|
fprintf (outfile, "From: %s%s", from, eolstring);
|
||
|
}
|
||
|
if (destination) {
|
||
|
fprintf (outfile, "%s: %s%s",
|
||
|
(isemail)?"To":"Newsgroups",
|
||
|
destination, eolstring);
|
||
|
}
|
||
|
fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
|
||
|
fprintf (outfile, "Content-Type: %s; name=\"%s\"%s",
|
||
|
(mimetype)?mimetype:"Application/Octet-Stream",
|
||
|
UUFNameFilter ((outfname)?outfname:infname),
|
||
|
eolstring);
|
||
|
fprintf (outfile, "Content-Transfer-Encoding: %s%s",
|
||
|
CTE_TYPE(encoding), eolstring);
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
res = UUEncodeToStream (outfile, infile, infname, encoding,
|
||
|
outfname, filemode);
|
||
|
|
||
|
_FP_free (subline);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
int UUEXPORT
|
||
|
UUE_PrepPartial (FILE *outfile, FILE *infile,
|
||
|
char *infname, int encoding,
|
||
|
char *outfname, int filemode,
|
||
|
int partno, long linperfile, long filesize,
|
||
|
char *destination, char *from, char *subject,
|
||
|
int isemail)
|
||
|
{
|
||
|
static int numparts, themode;
|
||
|
static char mimeid[64];
|
||
|
static FILE *theifile;
|
||
|
struct stat finfo;
|
||
|
char *subline, *oname;
|
||
|
long thesize;
|
||
|
int res, len;
|
||
|
|
||
|
if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
|
||
|
(encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_PARM_CHECK), "UUE_PrepPartial()");
|
||
|
return UURET_ILLVAL;
|
||
|
}
|
||
|
|
||
|
oname = UUFNameFilter ((outfname)?outfname:infname);
|
||
|
len = ((subject)?strlen(subject):0) + strlen (oname) + 40;
|
||
|
|
||
|
/*
|
||
|
* if first part, get information about the file
|
||
|
*/
|
||
|
if (partno == 1) {
|
||
|
if (infile==NULL) {
|
||
|
if (stat (infname, &finfo) == -1) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_STAT_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if ((theifile = fopen (infname, "rb")) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_NOT_OPEN_FILE),
|
||
|
infname, strerror (uu_errno=errno));
|
||
|
return UURET_IOERR;
|
||
|
}
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
|
||
|
thesize = (long) finfo.st_size;
|
||
|
}
|
||
|
else {
|
||
|
if (fstat (fileno (infile), &finfo) != 0) {
|
||
|
if (filesize <= 0) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_WARNING,
|
||
|
uustring (S_STAT_ONE_PART));
|
||
|
numparts = 1;
|
||
|
themode = (filemode)?filemode:0644;
|
||
|
thesize = 0;
|
||
|
}
|
||
|
else {
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) ((filesize+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
themode = (filemode)?filemode:0644;
|
||
|
thesize = filesize;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (linperfile <= 0)
|
||
|
numparts = 1;
|
||
|
else
|
||
|
numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
|
||
|
(linperfile*bpl[encoding]));
|
||
|
|
||
|
filemode = (int) finfo.st_mode & 0777;
|
||
|
thesize = (long) finfo.st_size;
|
||
|
}
|
||
|
theifile = infile;
|
||
|
}
|
||
|
/*
|
||
|
* if there's one part only, don't use Message/Partial
|
||
|
*/
|
||
|
|
||
|
if (numparts == 1) {
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
return UUE_PrepSingle (outfile, infile, infname, encoding,
|
||
|
outfname, filemode, destination,
|
||
|
from, subject, isemail);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* we also need a unique ID
|
||
|
*/
|
||
|
sprintf (mimeid, "UUDV-%ld.%ld.%s",
|
||
|
(long) time(NULL), thesize,
|
||
|
(strlen(oname)>16)?"oops":oname);
|
||
|
}
|
||
|
|
||
|
if ((subline = (char *) malloc (len)) == NULL) {
|
||
|
UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
|
||
|
uustring (S_OUT_OF_MEMORY), len);
|
||
|
if (infile==NULL) fclose (theifile);
|
||
|
return UURET_NOMEM;
|
||
|
}
|
||
|
|
||
|
if (subject)
|
||
|
sprintf (subline, "%s (%03d/%03d) - [ %s ]",
|
||
|
subject, partno, numparts, oname);
|
||
|
else
|
||
|
sprintf (subline, "[ %s ] (%03d/%03d)",
|
||
|
oname, partno, numparts);
|
||
|
|
||
|
fprintf (outfile, "Subject: %s%s", subline, eolstring);
|
||
|
|
||
|
if (from) {
|
||
|
fprintf (outfile, "From: %s%s", from, eolstring);
|
||
|
}
|
||
|
if (destination) {
|
||
|
fprintf (outfile, "%s: %s%s",
|
||
|
(isemail)?"To":"Newsgroups",
|
||
|
destination, eolstring);
|
||
|
}
|
||
|
fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
|
||
|
fprintf (outfile, "Content-Type: Message/Partial; number=%d; total=%d;%s",
|
||
|
partno, numparts, eolstring);
|
||
|
fprintf (outfile, "\tid=\"%s\"%s",
|
||
|
mimeid, eolstring);
|
||
|
fprintf (outfile, "%s", eolstring);
|
||
|
|
||
|
res = UUEncodePartial (outfile, theifile,
|
||
|
infname, encoding,
|
||
|
(outfname)?outfname:infname, NULL,
|
||
|
themode, partno, linperfile);
|
||
|
|
||
|
_FP_free (subline);
|
||
|
|
||
|
if (infile==NULL) {
|
||
|
if (res != UURET_OK) {
|
||
|
fclose (theifile);
|
||
|
return res;
|
||
|
}
|
||
|
if (feof (theifile)) {
|
||
|
fclose (theifile);
|
||
|
return UURET_OK;
|
||
|
}
|
||
|
return UURET_CONT;
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|