pjs/lib/libmsg/ad_strm.c

720 строки
17 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/**
* Apple Double encode/decode stream
* ----------------------------------
*
* 11sep95 mym created.
*/
#include "msg.h"
#include "appledbl.h"
#include "m_binhex.h"
#include "m_cvstrm.h"
#include "ad_codes.h"
/* for XP_GetString() */
#include "xpgetstr.h"
extern int MK_MSG_SAVE_ATTACH_AS;
#ifdef XP_MAC
#pragma warn_unusedarg off
extern int MK_UNABLE_TO_OPEN_TMP_FILE;
extern int MK_MIME_ERROR_WRITING_FILE;
/* ---------------------------------------------------------------------------------
**
** The codes for Apple-double encoding stream. --- it's only useful on Mac OS
**
** ---------------------------------------------------------------------------------
*/
#define WORKING_BUFF_SIZE 8192
typedef struct _AppledoubleEncodeObject
{
appledouble_encode_object ap_encode_obj;
char* buff; /* the working buff. */
int32 s_buff; /* the working buff size. */
XP_File fp; /* file to hold the encoding */
char *fname; /* and the file name. */
} AppleDoubleEncodeObject;
/*
Let's go "l" characters forward of the encoding for this write.
Note:
"s" is just a dummy paramter.
*/
PRIVATE int
net_AppleDouble_Encode_Write (
void *stream, const char* s, int32 l)
{
int status = 0;
AppleDoubleEncodeObject * obj = (AppleDoubleEncodeObject*)stream;
int32 count, size;
while (l > 0)
{
size = obj->s_buff * 11 / 16;
size = MIN(l, size);
status = ap_encode_next(&(obj->ap_encode_obj),
obj->buff,
size,
&count);
if (status == noErr || status == errDone)
{
/*
* we get the encode data, so call the next stream to write it to the disk.
*/
if (XP_FileWrite(obj->buff, count, obj->fp) != count)
return errFileWrite;
}
if (status != noErr ) /* abort when error / done? */
break;
l -= size;
}
return status;
}
/*
** is the stream ready for writing?
*/
PRIVATE unsigned int net_AppleDouble_Encode_Ready (void *stream)
{
return(MAX_WRITE_READY); /* always ready for writing */
}
PRIVATE void net_AppleDouble_Encode_Complete (void *stream)
{
AppleDoubleEncodeObject * obj = (AppleDoubleEncodeObject*)stream;
ap_encode_end(&(obj->ap_encode_obj), false); /* this is a normal ending */
if (obj->fp)
{
XP_FileClose(obj->fp); /* done with the target file */
FREEIF(obj->fname); /* and the file name too */
}
FREEIF(obj->buff); /* free the working buff. */
XP_FREE(obj);
}
PRIVATE void net_AppleDouble_Encode_Abort (void *stream, int status)
{
AppleDoubleEncodeObject * obj = (AppleDoubleEncodeObject*)stream;
ap_encode_end(&(obj->ap_encode_obj), true); /* it is an aborting exist... */
if (obj->fp)
{
XP_FileClose(obj->fp);
XP_FileRemove (obj->fname, xpURL); /* remove the partial file. */
FREEIF(obj->fname);
}
FREEIF(obj->buff); /* free the working buff. */
XP_FREE(obj);
}
/*
** fe_MakeAppleDoubleEncodeStream
** ------------------------------
**
** Will create a apple double encode stream:
**
** -> take the filename as the input source (it needs to be a mac file.)
** -> take a file name for the temp file we are generating.
*/
PUBLIC NET_StreamClass *
fe_MakeAppleDoubleEncodeStream (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id,
char* src_filename,
char* dst_filename,
char* separator)
{
AppleDoubleEncodeObject* obj;
NET_StreamClass* stream;
char* working_buff = NULL;
int bSize = WORKING_BUFF_SIZE;
TRACEMSG(("Setting up apple encode stream. Have URL: %s\n", URL_s->address));
stream = XP_NEW(NET_StreamClass);
if(stream == NULL)
return(NULL);
obj = XP_NEW(AppleDoubleEncodeObject);
if (obj == NULL)
{
XP_FREE (stream);
return(NULL);
}
while (!working_buff && (bSize >= 512))
{
working_buff = (char *)XP_ALLOC(bSize);
if (!working_buff)
bSize /= 2;
}
if (working_buff == NULL)
{
XP_FREE (obj);
XP_FREE (stream);
return (NULL);
}
stream->name = "Apple Double Encode";
stream->complete = (MKStreamCompleteFunc) net_AppleDouble_Encode_Complete;
stream->abort = (MKStreamAbortFunc) net_AppleDouble_Encode_Abort;
stream->put_block = (MKStreamWriteFunc) net_AppleDouble_Encode_Write;
stream->is_write_ready = (MKStreamWriteReadyFunc) net_AppleDouble_Encode_Ready;
stream->data_object = obj;
stream->window_id = window_id;
obj->fp = XP_FileOpen(dst_filename, xpFileToPost, XP_FILE_WRITE_BIN);
if (obj->fp == NULL)
{
XP_FREE (working_buff);
XP_FREE (obj);
XP_FREE (stream);
return (NULL);
}
obj->fname = XP_STRDUP(dst_filename);
obj->buff = working_buff;
obj->s_buff = bSize;
/*
** setup all the need information on the apple double encoder.
*/
ap_encode_init(&(obj->ap_encode_obj),
src_filename, /* pass the file name of the source. */
separator);
TRACEMSG(("Returning stream from NET_AppleDoubleEncoder\n"));
return stream;
}
#endif
/*
** ---------------------------------------------------------------------------------
**
** The codes for the Apple sigle/double decoding.
**
** ---------------------------------------------------------------------------------
*/
typedef struct AppleDoubleDecodeObject
{
appledouble_decode_object ap_decode_obj;
char* in_buff; /* the temporary buff to accumulate */
/* the input, make sure the call to */
/* the dedcoder engine big enough buff */
int32 bytes_in_buff; /* the count for the temporary buff. */
NET_StreamClass* binhex_stream; /* a binhex encode stream to convert */
/* the decoded mac file to binhex. */
} AppleDoubleDecodeObject;
PRIVATE int
net_AppleDouble_Decode_Write (
void *stream, const char* s, int32 l)
{
int status = NOERR;
AppleDoubleDecodeObject * obj = (AppleDoubleDecodeObject*) stream;
int32 size;
/*
** To force an effecient decoding, we should
** make sure that the buff pass to the decode next is great than 1024 bytes.
*/
if (obj->bytes_in_buff + l > 1024)
{
size = 1024 - obj->bytes_in_buff;
XP_MEMCPY(obj->in_buff+obj->bytes_in_buff,
s,
size);
s += size;
l -= size;
status = ap_decode_next(&(obj->ap_decode_obj),
obj->in_buff,
1024);
obj->bytes_in_buff = 0;
}
if (l > 1024)
{
/* we are sure that obj->bytes_in_buff == 0 at this point. */
status = ap_decode_next(&(obj->ap_decode_obj),
(char *)s,
l);
}
else
{
/* and we are sure we will not get overflow with the buff. */
XP_MEMCPY(obj->in_buff+obj->bytes_in_buff,
s,
l);
obj->bytes_in_buff += l;
}
return status;
}
PRIVATE unsigned int
net_AppleDouble_Decode_Ready (NET_StreamClass *stream)
{
return(MAX_WRITE_READY); /* always ready for writing */
}
PRIVATE void
net_AppleDouble_Decode_Complete (void *stream)
{
AppleDoubleDecodeObject *obj = (AppleDoubleDecodeObject *)stream;
if (obj->bytes_in_buff)
{
ap_decode_next(&(obj->ap_decode_obj), /* do the last calls. */
(char *)obj->in_buff,
obj->bytes_in_buff);
obj->bytes_in_buff = 0;
}
ap_decode_end(&(obj->ap_decode_obj), FALSE); /* it is a normal clean up cases.*/
if (obj->binhex_stream)
XP_FREE(obj->binhex_stream);
if (obj->in_buff)
XP_FREE(obj->in_buff);
XP_FREE(obj);
}
PRIVATE void
net_AppleDouble_Decode_Abort (
void *stream, int status)
{
AppleDoubleDecodeObject *obj = (AppleDoubleDecodeObject *)stream;
ap_decode_end(&(obj->ap_decode_obj), TRUE); /* it is an abort. */
if (obj->binhex_stream)
XP_FREE(obj->binhex_stream);
if (obj->in_buff)
XP_FREE(obj->in_buff);
XP_FREE(obj);
}
/*
** fe_MakeAppleDoubleDecodeStream_1
** ---------------------------------
**
** Create the apple double decode stream.
**
** In the Mac OS, it will create a stream to decode to an apple file;
**
** In other OS, the stream will decode apple double object,
** then encode it in binhex format, and save to the file.
*/
#ifndef XP_MAC
static void
simple_copy(MWContext* context, char* saveName, void* closure)
{
/* just copy the filename to the closure, so the caller can get it. */
XP_STRCPY(closure, saveName);
}
#endif
PUBLIC NET_StreamClass *
fe_MakeAppleDoubleDecodeStream_1 (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id)
{
#ifdef XP_MAC
return fe_MakeAppleDoubleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
false,
NULL);
#else
#if 0 /* just a test in the mac OS */
NET_StreamClass *p;
char* url;
StandardFileReply reply;
StandardPutFile("\pSave binhex encoded file as:", "\pUntitled", &reply);
if (!reply.sfGood)
{
return NULL;
}
url = my_PathnameFromFSSpec(&(reply.sfFile));
p = fe_MakeAppleDoubleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
true,
url+7);
XP_FREE(url);
return (p);
#else /* for the none mac-os to get a file name */
NET_StreamClass *p;
char* filename;
filename = XP_ALLOC(1024);
if (filename == NULL)
return NULL;
if (FE_PromptForFileName(window_id,
XP_GetString(MK_MSG_SAVE_ATTACH_AS),
0,
FALSE,
FALSE,
simple_copy,
filename) == -1)
{
return NULL;
}
p = fe_MakeAppleDoubleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
TRUE,
filename);
XP_FREE(filename);
return (p);
#endif
#endif
}
PUBLIC NET_StreamClass *
fe_MakeAppleDoubleDecodeStream (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id,
XP_Bool write_as_binhex,
char *dst_filename)
{
AppleDoubleDecodeObject* obj;
NET_StreamClass* stream;
TRACEMSG(("Setting up apple double decode stream. Have URL: %s\n", URL_s->address));
stream = XP_NEW(NET_StreamClass);
if(stream == NULL)
return(NULL);
obj = XP_NEW(AppleDoubleDecodeObject);
if (obj == NULL)
{
XP_FREE(stream);
return(NULL);
}
stream->name = "AppleDouble Decode";
stream->complete = (MKStreamCompleteFunc) net_AppleDouble_Decode_Complete;
stream->abort = (MKStreamAbortFunc) net_AppleDouble_Decode_Abort;
stream->put_block = (MKStreamWriteFunc) net_AppleDouble_Decode_Write;
stream->is_write_ready = (MKStreamWriteReadyFunc) net_AppleDouble_Decode_Ready;
stream->data_object = obj;
stream->window_id = window_id;
/*
** setup all the need information on the apple double encoder.
*/
obj->in_buff = (char *)XP_ALLOC(1024);
if (obj->in_buff == NULL)
{
XP_FREE(obj);
XP_FREE(stream);
return (NULL);
}
obj->bytes_in_buff = 0;
if (write_as_binhex)
{
obj->binhex_stream =
fe_MakeBinHexEncodeStream(format_out,
data_obj,
URL_s,
window_id,
dst_filename);
if (obj->binhex_stream == NULL)
{
XP_FREE(obj);
XP_FREE(stream);
XP_FREE(obj->in_buff);
return NULL;
}
ap_decode_init(&(obj->ap_decode_obj),
FALSE,
TRUE,
obj->binhex_stream);
}
else
{
obj->binhex_stream = NULL;
ap_decode_init(&(obj->ap_decode_obj),
FALSE,
FALSE,
window_id);
/*
* jt 8/8/97 -- I think this should be set to true. But'
* let's not touch it for now.
*
* obj->ap_decode_obj.is_binary = TRUE;
*/
}
if (dst_filename)
{
XP_STRNCPY_SAFE(obj->ap_decode_obj.fname, dst_filename,
sizeof(obj->ap_decode_obj.fname));
}
#ifdef XP_MAC
obj->ap_decode_obj.mSpec = (FSSpec*)( URL_s->fe_data );
#endif
TRACEMSG(("Returning stream from NET_AppleDoubleDecode\n"));
return stream;
}
/*
** fe_MakeAppleSingleDecodeStream_1
** --------------------------------
**
** Create the apple single decode stream.
**
** In the Mac OS, it will create a stream to decode object to an apple file;
**
** In other OS, the stream will decode apple single object,
** then encode context in binhex format, and save to the file.
*/
PUBLIC NET_StreamClass *
fe_MakeAppleSingleDecodeStream_1 (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id)
{
#ifdef XP_MAC
return fe_MakeAppleSingleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
FALSE,
NULL);
#else
#if 0 /* just a test in the mac OS */
NET_StreamClass *p;
char* url;
StandardFileReply reply;
StandardPutFile("\pSave binhex encoded file as:", "\pUntitled", &reply);
if (!reply.sfGood)
{
return NULL;
}
url = my_PathnameFromFSSpec(&(reply.sfFile));
p = fe_MakeAppleSingleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
true,
url+7);
XP_FREE(url);
return (p);
#else /* for the none mac-os to get a file name */
NET_StreamClass *p;
char* filename;
char* defaultPath = 0;
defaultPath = URL_s->content_name;
#ifdef XP_WIN16
if (XP_FileNameContainsBadChars(defaultPath))
defaultPath = 0;
#endif
filename = XP_ALLOC(1024);
if (filename == NULL)
return NULL;
if (FE_PromptForFileName(window_id,
XP_GetString(MK_MSG_SAVE_ATTACH_AS),
defaultPath,
FALSE,
FALSE,
simple_copy,
filename) == -1)
{
return NULL;
}
p = fe_MakeAppleSingleDecodeStream(format_out,
data_obj,
URL_s,
window_id,
FALSE,
filename);
XP_FREE(filename);
return (p);
#endif
#endif
}
/*
** Create the Apple Doube Decode stream.
**
*/
PUBLIC NET_StreamClass *
fe_MakeAppleSingleDecodeStream (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id,
XP_Bool write_as_binhex,
char *dst_filename)
{
AppleDoubleDecodeObject* obj;
NET_StreamClass* stream;
int encoding = kEncodeNone; /* default is that we don't know the encoding */
TRACEMSG(("Setting up apple single decode stream. Have URL: %s\n", URL_s->address));
stream = XP_NEW(NET_StreamClass);
if(stream == NULL)
return(NULL);
obj = XP_NEW(AppleDoubleDecodeObject);
if (obj == NULL)
{
XP_FREE(stream);
return(NULL);
}
stream->name = "AppleSingle Decode";
stream->complete = (MKStreamCompleteFunc) net_AppleDouble_Decode_Complete;
stream->abort = (MKStreamAbortFunc) net_AppleDouble_Decode_Abort;
stream->put_block = (MKStreamWriteFunc) net_AppleDouble_Decode_Write;
stream->is_write_ready = (MKStreamWriteReadyFunc) net_AppleDouble_Decode_Ready;
stream->data_object = obj;
stream->window_id = window_id;
/*
** setup all the need information on the apple double encoder.
*/
obj->in_buff = (char *)XP_ALLOC(1024);
if (obj->in_buff == NULL)
{
XP_FREE(obj);
XP_FREE(stream);
return (NULL);
}
obj->bytes_in_buff = 0;
if (write_as_binhex)
{
obj->binhex_stream =
fe_MakeBinHexEncodeStream(format_out,
data_obj,
URL_s,
window_id,
dst_filename);
if (obj->binhex_stream == NULL)
{
XP_FREE(obj);
XP_FREE(stream);
XP_FREE(obj->in_buff);
return NULL;
}
ap_decode_init(&(obj->ap_decode_obj),
TRUE,
TRUE,
obj->binhex_stream);
}
else
{
obj->binhex_stream = NULL;
ap_decode_init(&(obj->ap_decode_obj),
TRUE,
FALSE,
window_id);
#ifndef XP_MAC
obj->ap_decode_obj.is_binary = TRUE;
#endif
}
if (dst_filename)
{
XP_STRNCPY_SAFE(obj->ap_decode_obj.fname, dst_filename,
sizeof(obj->ap_decode_obj.fname));
}
/* If we are of a broken content-type, impose its encoding. */
if (URL_s->content_type
&& !XP_STRNCASECMP(URL_s->content_type, "x-uuencode-apple-single", 23))
obj->ap_decode_obj.encoding = kEncodeUU;
else
obj->ap_decode_obj.encoding = kEncodeNone;
TRACEMSG(("Returning stream from NET_AppleSingleDecode\n"));
return stream;
}