Adding modular libMIME to the tree.

This commit is contained in:
rhp%netscape.com 1999-01-13 01:54:56 +00:00
Родитель 74ac3d86af
Коммит 60423f2184
83 изменённых файлов: 30779 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,23 @@
#!nmake
#
# 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.
DEPTH=..\..
IGNORE_MANIFEST=1
DIRS=src
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -0,0 +1,28 @@
#!nmake
#
# 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.
DEPTH=..\..\..
IGNORE_MANIFEST=1
EXPORTS = \
nsIStreamConverter.h \
$(NULL)
MODULE=mime
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- 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.
*/
#ifndef nsIStreamConverter_h_
#define nsIStreamConverter_h_
#ifndef nsIStreamConverter_h_
#define nsIStreamConverter_h_
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
// {C9CDF8E5-95FA-11d2-8807-00805F5A1FB8}
#define NS_ISTREAM_CONVERTER_IID \
{ 0xc9cdf8e5, 0x95fa, 0x11d2, \
{ 0x88, 0x7, 0x0, 0x80, 0x5f, 0x5a, 0x1f, 0xb8 } };
class nsIStreamConverter : public nsIStreamListener {
public:
//
// This is the output stream where the stream converter will write processed data after
// conversion.
//
NS_IMETHOD SetOutputStream(nsIOutputStream *outStream) = 0;
//
// The output listener can be set to allow for the flexibility of having the stream converter
// directly notify the listener of the output stream for any processed/converter data. If
// this output listener is not set, the data will be written into the output stream but it is
// the responsibility of the client of the stream converter to handle the resulting data.
//
NS_IMETHOD SetOutputListener(nsIStreamListener *outListner) = 0;
};
#endif /* nsIStreamConverter_h_ */

Просмотреть файл

@ -0,0 +1,21 @@
#ifndef nsRFC822toHTMLStreamConverter_h_
#define nsRFC822toHTMLStreamConverter_h_
#include "nsIStreamConverter.h"
//
// A specific stream converter will be specified for each format-in/format-out
// pairing.
//
// {22DB1685-AA68-11d2-8809-00805F5A1FB8}
#define NS_RFC822_HTML_STREAM_CONVERTER_CID \
{ 0x22db1685, 0xaa68, 0x11d2, \
{ 0x88, 0x9, 0x0, 0x80, 0x5f, 0x5a, 0x1f, 0xb8 } };
class nsRFC822toHTMLStreamConverter : public nsIStreamConverter {
public:
void *tagData;
};
#endif /* nsRFC822toHTMLStreamConverter_h_ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,103 @@
/* -*- 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.
*/
/*
* nsmsg.cpp - external libmsg calls
*/
#include "xp.h"
#include "xp_time.h"
#include "xplocale.h"
#include "prmem.h"
#include "plstr.h"
#include "msgcom.h"
extern "C" MSG_Pane * MSG_FindPane(MWContext* context, MSG_PaneType type)
{
return NULL;
/* return MSG_Pane::FindPane(context, type, FALSE); */
}
extern "C" XP_Bool
MSG_ShouldRot13Message(MSG_Pane* messagepane)
{
return FALSE;
/* return CastMessagePane(messagepane)->ShouldRot13Message(); */
}
size_t XP_StrfTime(MWContext* context, char *result, size_t maxsize, int format,
const struct tm *timeptr)
{
/* MOZ_FUNCTION_STUB; */
return 0;
}
extern "C"
const char* MSG_FormatDateFromContext(MWContext *context, time_t date)
{
/* fix i18n. Well, maybe. Isn't strftime() supposed to be i18n? */
/* ftong- Well.... strftime() in Mac and Window is not really i18n */
/* We need to use XP_StrfTime instead of strftime */
static char result[40]; /* 30 probably not enough */
time_t now = time ((time_t *) 0);
int32 offset = XP_LocalZoneOffset() * 60L; /* Number of seconds between
local and GMT. */
int32 secsperday = 24L * 60L * 60L;
int32 nowday = (now + offset) / secsperday;
int32 day = (date + offset) / secsperday;
if (day == nowday) {
XP_StrfTime(context, result, sizeof(result), XP_TIME_FORMAT,
localtime(&date));
} else if (day < nowday && day > nowday - 7) {
XP_StrfTime(context, result, sizeof(result), XP_WEEKDAY_TIME_FORMAT,
localtime(&date));
} else {
#if defined (XP_WIN)
if (date < 0 || date > 0x7FFFFFFF)
date = 0x7FFFFFFF;
#endif
XP_StrfTime(context, result, sizeof(result), XP_DATE_TIME_FORMAT,
localtime(&date));
}
return result;
}
extern "C" MSG_MessagePaneCallbacks*
MSG_GetMessagePaneCallbacks(MSG_Pane* messagepane,
void** closure)
{
return NULL;
/* return CastMessagePane(messagepane)->GetMessagePaneCallbacks(closure); */
}
extern "C" NET_StreamClass *
MIME_MessageConverter2 (int format_out, void *closure, URL_Struct *url, MWContext *context);
NET_StreamClass *
MIME_MessageConverter (int format_out, void *closure,
URL_Struct *url, MWContext *context)
{
return MIME_MessageConverter2 (format_out, closure, url, context);
}

Просмотреть файл

@ -0,0 +1,40 @@
/*
* 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.
*/
/*
* There are all of the styles one can modify for mail display!
*/
BLOCKQUOTE {
display: block;
margin-top: auto;
margin-bottom: auto;
BORDER-LEFT: #0000FF solid 1px;
MARGIN-LEFT: 20px;
PADDING-LEFT: 10px;
background-color: #FFFFCC;
font-size: 8pt;
font-family: arial;
font-variant: normal;
font-style: normal;
}
MAIL_BODY {
display: block;
background-color: cyan;
}

210
mailnews/mime/src/mail.js Normal file
Просмотреть файл

@ -0,0 +1,210 @@
/* -*- 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.
*/
var _dQueue = null;
var _interval = null;
var _wPrev = 0;
var _wH = 0;
var isNav4, isIE4;
if (parseInt(navigator.appVersion.charAt(0)) >= 4)
{
isNav4 = (navigator.appName == "Netscape") ? true : false;
isIE4 = (navigator.appName.indexOf("Microsoft") != -1) ? true : false;
}
function getTop(layer)
{
if (isNav4)
return layer.top;
return layer.style.pixelTop;
}
function Drift()
{
this.min = false; this.max = false;
this.tOffset = -.069; this.bOffset = 0;
this.lOffset = 0; this.interval = 200;
this.startDrift = startDrift;
return this;
}
var prefs;
function startDrift(layer)
{
if(_wH == 0)
{
if(isNav4)
_wH = window.innerHeight;
else
_wH = document.body.clientHeight;
}
layer.tOffset = getTop(layer);
if(!this.interval)
{
prefs = new Drift();
prefs.temp = true;
}
else
prefs = this;
layer.min = prefs.min;
layer.max = prefs.max;
if(prefs.tOffset != -.069)
layer.tOffset = prefs.tOffset; // offset from top of window
layer.bOffset = prefs.bOffset; // offset from bottom of window
layer.lOffset = prefs.lOffset; // for nested layers
if(_dQueue == null)
_dQueue = new Array();
_dQueue[_dQueue.length] = layer;
if (_interval == null)
_interval = setInterval("checkDrift()", prefs.interval);
if (prefs.temp)
prefs = null;
return (_dQueue.length-1);
}
var str, i, top, bottom;
function getClipHeight(layer)
{
if(isNav4)
return layer.clip.height;
str = layer.style.clip;
if(str)
{
i = str.indexOf("(");
top = parseInt(str.substring(i + 1, str.length));
i = str.indexOf(" ", i + 1); i = str.indexOf(" ", i + 1);
bottom = parseInt(str.substring(i + 1, str.length));
if(top < 0)
top = 0;
return (bottom-top);
}
return layer.style.pixelHeight;
}
var IMGW= 117;
var IMGH= 18;
var LSAFETY= 40;
var TSAFETY= 0;
var layer, dst, wOff;
function checkDrift()
{
alert("here\n");
for(i = 0; i < _dQueue.length; i++)
{
layer = _dQueue[i];
if (!layer) continue;
IMGH = layer.style.height;
IH= document.body.clientHeight;
IW= document.body.clientWidth;
PX= document.body.scrollLeft;
PY= document.body.scrollTop;
/* layer.style.pixelTop = (IH+PY-(IMGH+TSAFETY));
brand.style.left=(IW+PX-(IMGW+LSAFETY));
*/
layer.style.top = (IH+PY-(IMGH+TSAFETY));
}
return;
if(isNav4)
wOff = window.pageYOffset;
else
wOff = document.body.scrollTop;
for(i = 0; i < _dQueue.length; i++)
{
layer = _dQueue[i];
if (!layer) continue;
if(wOff > _wPrev)
{
if (getClipHeight(layer)+layer.bOffset+layer.tOffset > _wH)
{
if(wOff+_wH-layer.bOffset > getTop(layer)+layer.lOffset+getClipHeight(layer))
dst = wOff+_wH-layer.lOffset-getClipHeight(layer)-layer.bOffset;
}
else
dst = wOff-layer.lOffset+layer.tOffset;
}
else if (wOff < _wPrev)
{
if(getClipHeight(layer)+layer.bOffset+layer.tOffset <= _wH)
dst = wOff-layer.lOffset+layer.tOffset;
else if(wOff < getTop(layer)+layer.lOffset-layer.tOffset)
dst = wOff-layer.lOffset+layer.tOffset;
}
if (layer.max)
if (dst > layer.max)
dst = layer.max;
if (layer.min || layer.min == 0)
if(dst < layer.min)
dst = layer.min;
if(dst || dst == 0)
{
if (isNav4)
layer.top = dst;
else
layer.style.pixelTop = dst;
}
}
_wPrev = wOff;
}
function stopDrift(id)
{
_dQueue[id] = null;
}
function toggleAttachments()
{
alert("Cool Stuff!");
return;
var target = document.getElementById("attachPane");
IMGH = target.style.height;
IH= document.body.clientHeight;
IW= document.body.clientWidth;
PX= document.body.scrollLeft;
PY= document.body.scrollTop;
target.style.top = (IH+PY-(IMGH+TSAFETY));
alert("top = target.style.top\n");
return;
if (target.style.display == "")
target.style.display = "none";
else
{
if (!drifting) startDrift(target);
target.style.display = "";
drifting = 1;
}
}

Просмотреть файл

@ -0,0 +1,185 @@
# 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.
#
NODEPEND=1
IGNORE_MANIFEST = 1
#
# MIME.DLL
# ========
# This is a modular version of the old libmime component of
# the Communicator world.
#
# Notes:
# ======
# There have been several #ifdef's added to the source for various
# reasons. These include:
#
# RICHIE - General "commenting out" of code to get into a building state
# RICHIE_<module> - Removal of specific features. The feature is contained
# in the <module> part of the ifdef
#
#
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH=..\..\..
#//------------------------------------------------------------------------
#//
# New build system where zip dll is build indepenant of java stubs.
#//
#//------------------------------------------------------------------------
MODULE = mime
REQUIRES=
EXPORTS =
CSS = mail.css
JS = mail.js
# Put mime headers here!!!
# $(NULL)
DEFINES= -DEBUG_rhp -DHAVE_MIME_DATA_SLOT -D_IMPL_NS_HTML
#//------------------------------------------------------------------------
#//
#// Define the files necessary to build the target (ie. OBJS)
#//
#//------------------------------------------------------------------------
OBJS= \
.\$(OBJDIR)\mimecont.obj \
.\$(OBJDIR)\mimeebod.obj \
.\$(OBJDIR)\mimeenc.obj \
.\$(OBJDIR)\mimeeobj.obj \
.\$(OBJDIR)\mimehdrs.obj \
.\$(OBJDIR)\mimei.obj \
.\$(OBJDIR)\mimeiimg.obj \
.\$(OBJDIR)\mimeleaf.obj \
.\$(OBJDIR)\mimemalt.obj \
.\$(OBJDIR)\mimemapl.obj \
.\$(OBJDIR)\mimemdig.obj \
.\$(OBJDIR)\mimemmix.obj \
.\$(OBJDIR)\mimempar.obj \
.\$(OBJDIR)\mimemrel.obj \
.\$(OBJDIR)\mimemsg.obj \
.\$(OBJDIR)\mimemsig.obj \
.\$(OBJDIR)\mimemult.obj \
.\$(OBJDIR)\mimeobj.obj \
.\$(OBJDIR)\mimepbuf.obj \
.\$(OBJDIR)\mimesun.obj \
.\$(OBJDIR)\mimetenr.obj \
.\$(OBJDIR)\mimetext.obj \
.\$(OBJDIR)\mimethtm.obj \
.\$(OBJDIR)\mimetpla.obj \
.\$(OBJDIR)\mimetric.obj \
.\$(OBJDIR)\mimeunty.obj \
.\$(OBJDIR)\mimemoz.obj \
.\$(OBJDIR)\mimevcrd.obj \
# THIS WILL NEED WORK AFTER WE GET A LIBMSG MORE XP-COM-afied
# .\$(OBJDIR)\mimedrft.obj \
# XP-COM BRIDGES
.\$(OBJDIR)\comi18n.obj \
.\$(OBJDIR)\commsg.obj \
# SHOULD HAVE XP-COM INTERFACES FOR THIS STUFF AND SHOULD NOT BE
# A PART OF LIBMIME
.\$(OBJDIR)\oldvcc.obj \
.\$(OBJDIR)\oldvobj.obj \
# EXTERNAL (OLD) DEPENDENCIES - SHOULD EVENTUALLY BE REMOVED
# WHEN NEW WORLD FUNCTIONS ARE FOUND
.\$(OBJDIR)\oldnet.obj \
.\$(OBJDIR)\oldxp.obj \
.\$(OBJDIR)\oldi18n.obj \
.\$(OBJDIR)\oldmsg.obj \
.\$(OBJDIR)\oldmaddr.obj \
.\$(OBJDIR)\oldfile.obj \
# I18N STUFF THAT HAS TO BE REMOVED!
# .\$(OBJDIR)\cvchcode.obj \
# .\$(OBJDIR)\doc_ccc.obj \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
#//
#//------------------------------------------------------------------------
DLLNAME=mime.dll
LIBNAME=mime.lib
PDBFILE=mime.pdb
MAPFILE=mime.map
DEFFILE=mime.def
#//------------------------------------------------------------------------
#//
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
#// (these must be defined before the common makefiles are included)
#//
#//------------------------------------------------------------------------
#
DLL=.\$(OBJDIR)\$(DLLNAME)
#//------------------------------------------------------------------------
#//
#// Define any local options for the make tools
#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
#//
#//------------------------------------------------------------------------
LCFLAGS=-DNETSCAPE
MSGLIBS= \
$(NULL)
# These are the libraries we need to link with to create the dll
LLIBS= \
$(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\js32$(VERSION_NUMBER).lib \
$(DIST)\lib\netlib.lib \
$(DIST)\lib\xppref32.lib \
$(DIST)\lib\mimetype.lib \
$(DIST)\lib\xplib.lib \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\xpcom32.lib \
$(NULL)
LINCS=$(LINCS) -I. \
-I$(PUBLIC)\pref \
-I$(PUBLIC)\js \
-I$(PUBLIC)\security \
-I$(PUBLIC)\netlib \
-I$(PUBLIC)\xpcom \
-I$(PUBLIC)\raptor \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)/config/rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME) $(DIST)\bin
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBNAME) $(DIST)\lib
$(MAKE_INSTALL) .\$(CSS) $(DIST)\bin\res
$(MAKE_INSTALL) .\$(JS) $(DIST)\bin\res
clobber::
rm -f $(DIST)\bin\$(DLLNAME)
rm -f $(DIST)\lib\$(LIBNAME)

Просмотреть файл

@ -0,0 +1,19 @@
; 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.
LIBRARY mime.dll
EXPORTS
MIME_MessageConverter

Просмотреть файл

@ -0,0 +1,228 @@
/* -*- 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.
*/
#include "prmem.h"
#include "plstr.h"
#include "mimecont.h"
#define MIME_SUPERCLASS mimeObjectClass
MimeDefClass(MimeContainer, MimeContainerClass,
mimeContainerClass, &MIME_SUPERCLASS);
static int MimeContainer_initialize (MimeObject *);
static void MimeContainer_finalize (MimeObject *);
static int MimeContainer_add_child (MimeObject *, MimeObject *);
static int MimeContainer_parse_eof (MimeObject *, PRBool);
static int MimeContainer_parse_end (MimeObject *, PRBool);
static PRBool MimeContainer_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeContainer_debug_print (MimeObject *, FILE *, PRInt32 depth);
#endif
static int
MimeContainerClassInitialize(MimeContainerClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) &class->object;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeContainer_initialize;
oclass->finalize = MimeContainer_finalize;
oclass->parse_eof = MimeContainer_parse_eof;
oclass->parse_end = MimeContainer_parse_end;
oclass->displayable_inline_p = MimeContainer_displayable_inline_p;
class->add_child = MimeContainer_add_child;
#if defined(DEBUG) && defined(XP_UNIX)
oclass->debug_print = MimeContainer_debug_print;
#endif
return 0;
}
static int
MimeContainer_initialize (MimeObject *object)
{
/* This is an abstract class; it shouldn't be directly instanciated. */
PR_ASSERT(object->class != (MimeObjectClass *) &mimeContainerClass);
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeContainer_finalize (MimeObject *object)
{
MimeContainer *cont = (MimeContainer *) object;
/* Do this first so that children have their parse_eof methods called
in forward order (0-N) but are destroyed in backward order (N-0)
*/
if (!object->closed_p)
object->class->parse_eof (object, FALSE);
if (!object->parsed_p)
object->class->parse_end (object, FALSE);
if (cont->children)
{
int i;
for (i = cont->nchildren-1; i >= 0; i--)
{
MimeObject *kid = cont->children[i];
if (kid)
mime_free(kid);
cont->children[i] = 0;
}
FREEIF(cont->children);
cont->nchildren = 0;
}
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeContainer_parse_eof (MimeObject *object, PRBool abort_p)
{
MimeContainer *cont = (MimeContainer *) object;
int status;
/* We must run all of this object's parent methods first, to get all the
data flushed down its stream, so that the children's parse_eof methods
can access it. We do not access *this* object again after doing this,
only its children.
*/
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(object, abort_p);
if (status < 0) return status;
if (cont->children)
{
int i;
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
if (kid && !kid->closed_p)
{
int status = kid->class->parse_eof(kid, abort_p);
if (status < 0) return status;
}
}
}
return 0;
}
static int
MimeContainer_parse_end (MimeObject *object, PRBool abort_p)
{
MimeContainer *cont = (MimeContainer *) object;
int status;
/* We must run all of this object's parent methods first, to get all the
data flushed down its stream, so that the children's parse_eof methods
can access it. We do not access *this* object again after doing this,
only its children.
*/
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_end(object, abort_p);
if (status < 0) return status;
if (cont->children)
{
int i;
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
if (kid && !kid->parsed_p)
{
int status = kid->class->parse_end(kid, abort_p);
if (status < 0) return status;
}
}
}
return 0;
}
static int
MimeContainer_add_child (MimeObject *parent, MimeObject *child)
{
MimeContainer *cont = (MimeContainer *) parent;
MimeObject **old_kids, **new_kids;
PR_ASSERT(parent && child);
if (!parent || !child) return -1;
old_kids = cont->children;
new_kids = PR_MALLOC(sizeof(MimeObject *) * (cont->nchildren + 1));
if (!new_kids) return MK_OUT_OF_MEMORY;
if (cont->nchildren > 0)
XP_MEMCPY(new_kids, old_kids, sizeof(MimeObject *) * cont->nchildren);
new_kids[cont->nchildren] = child;
PR_Free(old_kids);
cont->children = new_kids;
cont->nchildren++;
child->parent = parent;
/* Copy this object's options into the child. */
child->options = parent->options;
return 0;
}
static PRBool
MimeContainer_displayable_inline_p (MimeObjectClass *class, MimeHeaders *hdrs)
{
return TRUE;
}
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeContainer_debug_print (MimeObject *obj, FILE *stream, PRInt32 depth)
{
MimeContainer *cont = (MimeContainer *) obj;
int i;
char *addr = mime_part_address(obj);
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream, "<%s %s (%d kid%s) 0x%08X>\n",
obj->class->class_name,
addr ? addr : "???",
cont->nchildren, (cont->nchildren == 1 ? "" : "s"),
(PRUint32) cont);
FREEIF(addr);
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
int status = kid->class->debug_print (kid, stream, depth+1);
if (status < 0) return status;
}
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
return 0;
}
#endif

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- 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.
*/
#ifndef _MIMECONT_H_
#define _MIMECONT_H_
#include "mimeobj.h"
/* MimeContainer is the class for the objects representing all MIME
types which can contain other MIME objects within them. In addition
to the methods inherited from MimeObject, it provides one method:
int add_child (MimeObject *parent, MimeObject *child)
Given a parent (a subclass of MimeContainer) this method adds the
child (any MIME object) to the parent's list of children.
The MimeContainer `finalize' method will finalize the children as well.
*/
typedef struct MimeContainerClass MimeContainerClass;
typedef struct MimeContainer MimeContainer;
struct MimeContainerClass {
MimeObjectClass object;
int (*add_child) (MimeObject *parent, MimeObject *child);
};
extern MimeContainerClass mimeContainerClass;
struct MimeContainer {
MimeObject object; /* superclass variables */
MimeObject **children; /* list of contained objects */
PRInt32 nchildren; /* how many */
};
#endif /* _MIMECONT_H_ */

1463
mailnews/mime/src/mimedrft.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,526 @@
/* -*- 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.
*/
#include "mimeebod.h"
#include "xpgetstr.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeObjectClass
MimeDefClass(MimeExternalBody, MimeExternalBodyClass,
mimeExternalBodyClass, &MIME_SUPERCLASS);
extern int MK_MSG_LINK_TO_DOCUMENT;
extern int MK_MSG_DOCUMENT_INFO;
#if defined(XP_MAC) && !defined(MOZILLA_30)
extern MimeObjectClass mimeMultipartAppleDoubleClass;
#endif
static int MimeExternalBody_initialize (MimeObject *);
static void MimeExternalBody_finalize (MimeObject *);
static int MimeExternalBody_parse_line (char *, PRInt32, MimeObject *);
static int MimeExternalBody_parse_eof (MimeObject *, PRBool);
static PRBool MimeExternalBody_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
#if 0
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeExternalBody_debug_print (MimeObject *, FILE *, PRInt32);
#endif
#endif /* 0 */
static int
MimeExternalBodyClassInitialize(MimeExternalBodyClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeExternalBody_initialize;
oclass->finalize = MimeExternalBody_finalize;
oclass->parse_line = MimeExternalBody_parse_line;
oclass->parse_eof = MimeExternalBody_parse_eof;
oclass->displayable_inline_p = MimeExternalBody_displayable_inline_p;
#if 0
#if defined(DEBUG) && defined(XP_UNIX)
oclass->debug_print = MimeExternalBody_debug_print;
#endif
#endif /* 0 */
return 0;
}
static int
MimeExternalBody_initialize (MimeObject *object)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeExternalBody_finalize (MimeObject *object)
{
MimeExternalBody *bod = (MimeExternalBody *) object;
if (bod->hdrs)
{
MimeHeaders_free(bod->hdrs);
bod->hdrs = 0;
}
FREEIF(bod->body);
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeExternalBody_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
MimeExternalBody *bod = (MimeExternalBody *) obj;
int status = 0;
PR_ASSERT(line && *line);
if (!line || !*line) return -1;
if (!obj->output_p) return 0;
/* If we're supposed to write this object, but aren't supposed to convert
it to HTML, simply pass it through unaltered. */
if (obj->options &&
!obj->options->write_html_p &&
obj->options->output_fn)
return MimeObject_write(obj, line, length, TRUE);
/* If we already have a `body' then we're done parsing headers, and all
subsequent lines get tacked onto the body. */
if (bod->body)
{
int L = PL_strlen(bod->body);
char *new_str = PR_Realloc(bod->body, L + length + 1);
if (!new_str) return MK_OUT_OF_MEMORY;
bod->body = new_str;
XP_MEMCPY(bod->body + L, line, length);
bod->body[L + length] = 0;
return 0;
}
/* Otherwise we don't yet have a body, which means we're not done parsing
our headers.
*/
if (!bod->hdrs)
{
bod->hdrs = MimeHeaders_new();
if (!bod->hdrs) return MK_OUT_OF_MEMORY;
}
status = MimeHeaders_parse_line(line, length, bod->hdrs);
if (status < 0) return status;
/* If this line is blank, we're now done parsing headers, and should
create a dummy body to show that. Gag.
*/
if (*line == CR || *line == LF)
{
bod->body = PL_strdup("");
if (!bod->body) return MK_OUT_OF_MEMORY;
}
return 0;
}
char *
MimeExternalBody_make_url(const char *ct,
const char *at, const char *exp, const char *size,
const char *perm, const char *dir, const char *mode,
const char *name, const char *url, const char *site,
const char *svr, const char *subj, const char *body)
{
char *s;
if (!at)
{
return 0;
}
else if (!PL_strcasecmp(at, "ftp") || !PL_strcasecmp(at, "anon-ftp"))
{
if (!site || !name)
return 0;
s = (char *) PR_MALLOC(PL_strlen(name) + PL_strlen(site) +
(dir ? PL_strlen(dir) : 0) + 20);
if (!s) return 0;
PL_strcpy(s, "ftp://");
PL_strcat(s, site);
PL_strcat(s, "/");
if (dir) PL_strcat(s, (dir[0] == '/' ? dir+1 : dir));
if (s[PL_strlen(s)-1] != '/')
PL_strcat(s, "/");
PL_strcat(s, name);
return s;
}
else if (!PL_strcasecmp(at, "local-file") || !PL_strcasecmp(at, "afs"))
{
char *s2;
if (!name)
return 0;
#ifdef XP_UNIX
if (!PL_strcasecmp(at, "afs")) /* only if there is a /afs/ directory */
{
XP_StatStruct st;
if (stat("/afs/.", &st))
return 0;
}
#else /* !XP_UNIX */
return 0; /* never, if not Unix. */
#endif /* !XP_UNIX */
s = (char *) PR_MALLOC(PL_strlen(name)*3 + 20);
if (!s) return 0;
PL_strcpy(s, "file:");
s2 = NET_Escape(name, URL_PATH);
if (s2) PL_strcat(s, s2);
FREEIF(s2);
return s;
}
else if (!PL_strcasecmp(at, "mail-server"))
{
char *s2;
if (!svr)
return 0;
s = (char *) PR_MALLOC(PL_strlen(svr)*4 +
(subj ? PL_strlen(subj)*4 : 0) +
(body ? PL_strlen(body)*4 : 0) + 20);
if (!s) return 0;
PL_strcpy(s, "mailto:");
s2 = NET_Escape(svr, URL_XALPHAS);
if (s2) PL_strcat(s, s2);
FREEIF(s2);
if (subj)
{
s2 = NET_Escape(subj, URL_XALPHAS);
PL_strcat(s, "?subject=");
if (s2) PL_strcat(s, s2);
FREEIF(s2);
}
if (body)
{
s2 = NET_Escape(body, URL_XALPHAS);
PL_strcat(s, (subj ? "&body=" : "?body="));
if (s2) PL_strcat(s, s2);
FREEIF(s2);
}
return s;
}
else if (!PL_strcasecmp(at, "url")) /* RFC 2017 */
{
if (url)
return PL_strdup(url); /* it's already quoted and everything */
else
return 0;
}
else
return 0;
}
#ifdef XP_MAC
#ifdef DEBUG
#pragma global_optimizer on
#pragma optimization_level 1
#endif /* DEBUG */
#endif /* XP_MAC */
static int
MimeExternalBody_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status = 0;
MimeExternalBody *bod = (MimeExternalBody *) obj;
if (obj->closed_p) return 0;
/* Run parent method first, to flush out any buffered data. */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
#if defined(XP_MAC) && !defined(MOZILLA_30)
if (obj->parent && mime_typep(obj->parent,
(MimeObjectClass*) &mimeMultipartAppleDoubleClass))
goto done;
#endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
if (!abort_p &&
obj->output_p &&
obj->options &&
obj->options->write_html_p)
{
PRBool all_headers_p = obj->options->headers == MimeHeadersAll;
MimeDisplayOptions newopt = *obj->options; /* copy it */
char *ct = MimeHeaders_get(obj->headers, HEADER_CONTENT_TYPE,
FALSE, FALSE);
char *at, *exp, *size, *perm;
char *url, *dir, *mode, *name, *site, *svr, *subj;
char *h = 0, *lname = 0, *lurl = 0, *body = 0;
MimeHeaders *hdrs = 0;
if (!ct) return MK_OUT_OF_MEMORY;
at = MimeHeaders_get_parameter(ct, "access-type", NULL, NULL);
exp = MimeHeaders_get_parameter(ct, "expiration", NULL, NULL);
size = MimeHeaders_get_parameter(ct, "size", NULL, NULL);
perm = MimeHeaders_get_parameter(ct, "permission", NULL, NULL);
dir = MimeHeaders_get_parameter(ct, "directory", NULL, NULL);
mode = MimeHeaders_get_parameter(ct, "mode", NULL, NULL);
name = MimeHeaders_get_parameter(ct, "name", NULL, NULL);
site = MimeHeaders_get_parameter(ct, "site", NULL, NULL);
svr = MimeHeaders_get_parameter(ct, "server", NULL, NULL);
subj = MimeHeaders_get_parameter(ct, "subject", NULL, NULL);
url = MimeHeaders_get_parameter(ct, "url", NULL, NULL);
FREEIF(ct);
/* the *internal* content-type */
ct = MimeHeaders_get(bod->hdrs, HEADER_CONTENT_TYPE,
TRUE, FALSE);
h = (char *) PR_MALLOC((at ? PL_strlen(at) : 0) +
(exp ? PL_strlen(exp) : 0) +
(size ? PL_strlen(size) : 0) +
(perm ? PL_strlen(perm) : 0) +
(dir ? PL_strlen(dir) : 0) +
(mode ? PL_strlen(mode) : 0) +
(name ? PL_strlen(name) : 0) +
(site ? PL_strlen(site) : 0) +
(svr ? PL_strlen(svr) : 0) +
(subj ? PL_strlen(subj) : 0) +
(url ? PL_strlen(url) : 0) + 100);
if (!h)
{
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
/* If there's a URL parameter, remove all whitespace from it.
(The URL parameter to one of these headers is stored with
lines broken every 40 characters or less; it's assumed that
all significant whitespace was URL-hex-encoded, and all the
rest of it was inserted just to keep the lines short.)
*/
if (url)
{
char *in, *out;
for (in = url, out = url; *in; in++)
if (!XP_IS_SPACE(*in))
*out++ = *in;
*out = 0;
}
hdrs = MimeHeaders_new();
if (!hdrs)
{
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
# define FROB(STR,VAR) \
if (VAR) \
{ \
PL_strcpy(h, STR ": "); \
PL_strcat(h, VAR); \
PL_strcat(h, LINEBREAK); \
status = MimeHeaders_parse_line(h, PL_strlen(h), hdrs); \
if (status < 0) goto FAIL; \
}
FROB("Access-Type", at);
FROB("URL", url);
FROB("Site", site);
FROB("Server", svr);
FROB("Directory", dir);
FROB("Name", name);
FROB("Type", ct);
FROB("Size", size);
FROB("Mode", mode);
FROB("Permission", perm);
FROB("Expiration", exp);
FROB("Subject", subj);
# undef FROB
PL_strcpy(h, LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), hdrs);
if (status < 0) goto FAIL;
lurl = MimeExternalBody_make_url(ct, at, exp, size, perm, dir, mode,
name, url, site, svr, subj, bod->body);
if (lurl)
{
lname = PL_strdup(XP_GetString(MK_MSG_LINK_TO_DOCUMENT));
}
else
{
lname = PL_strdup(XP_GetString(MK_MSG_DOCUMENT_INFO));
all_headers_p = TRUE;
}
all_headers_p = TRUE; /* #### just do this all the time? */
if (bod->body && all_headers_p)
{
char *s = bod->body;
while (XP_IS_SPACE(*s)) s++;
if (*s)
{
char *s2;
const char *pre = "<P><PRE>";
const char *suf = "</PRE>";
PRInt32 i;
for(i = PL_strlen(s)-1; i >= 0 && XP_IS_SPACE(s[i]); i--)
s[i] = 0;
s2 = NET_EscapeHTML(s);
if (!s2) goto FAIL;
body = (char *) PR_MALLOC(PL_strlen(pre) + PL_strlen(s2) +
PL_strlen(suf) + 1);
if (!body)
{
PR_Free(s2);
goto FAIL;
}
PL_strcpy(body, pre);
PL_strcat(body, s2);
PL_strcat(body, suf);
}
}
newopt.fancy_headers_p = TRUE;
newopt.headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome);
{
char p[] = "<P>";
status = MimeObject_write(obj, p, 3, FALSE);
if (status < 0) goto FAIL;
}
status = MimeHeaders_write_attachment_box (hdrs, &newopt, ct, 0,
lname, lurl, body);
if (status < 0) goto FAIL;
{
char p[] = "<P>";
status = MimeObject_write(obj, p, 3, FALSE);
if (status < 0) goto FAIL;
}
FAIL:
if (hdrs)
MimeHeaders_free(hdrs);
FREEIF(h);
FREEIF(lname);
FREEIF(lurl);
FREEIF(body);
FREEIF(ct);
FREEIF(at);
FREEIF(exp);
FREEIF(size);
FREEIF(perm);
FREEIF(dir);
FREEIF(mode);
FREEIF(name);
FREEIF(url);
FREEIF(site);
FREEIF(svr);
FREEIF(subj);
}
#if defined(XP_MAC) && !defined(MOZILLA_30)
done:
#endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
return status;
}
#ifdef XP_MAC
#ifdef DEBUG
#pragma global_optimizer reset
#endif /* DEBUG */
#endif /* XP_MAC */
#if 0
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeExternalBody_debug_print (MimeObject *obj, FILE *stream, PRInt32 depth)
{
MimeExternalBody *bod = (MimeExternalBody *) obj;
int i;
char *ct, *ct2;
char *addr = mime_part_address(obj);
if (obj->headers)
ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
if (bod->hdrs)
ct2 = MimeHeaders_get (bod->hdrs, HEADER_CONTENT_TYPE, FALSE, FALSE);
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream,
"<%s %s\n"
"\tcontent-type: %s\n"
"\tcontent-type: %s\n"
"\tBody:%s\n\t0x%08X>\n\n",
obj->class->class_name,
addr ? addr : "???",
ct ? ct : "<none>",
ct2 ? ct2 : "<none>",
bod->body ? bod->body : "<none>",
(PRUint32) obj);
FREEIF(addr);
FREEIF(ct);
FREEIF(ct2);
return 0;
}
#endif
#endif /* 0 */
static PRBool
MimeExternalBody_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs)
{
char *ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, FALSE, FALSE);
char *at = MimeHeaders_get_parameter(ct, "access-type", NULL, NULL);
PRBool inline_p = FALSE;
if (!at)
;
else if (!PL_strcasecmp(at, "ftp") ||
!PL_strcasecmp(at, "anon-ftp") ||
!PL_strcasecmp(at, "local-file") ||
!PL_strcasecmp(at, "mail-server") ||
!PL_strcasecmp(at, "url"))
inline_p = TRUE;
#ifdef XP_UNIX
else if (!PL_strcasecmp(at, "afs")) /* only if there is a /afs/ directory */
{
XP_StatStruct st;
if (!stat("/afs/.", &st))
inline_p = TRUE;
}
#endif /* XP_UNIX */
FREEIF(ct);
FREEIF(at);
return inline_p;
}

Просмотреть файл

@ -0,0 +1,47 @@
/* -*- 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.
*/
#ifndef _MIMEEBOD_H_
#define _MIMEEBOD_H_
#include "mimeobj.h"
/* The MimeExternalBody class implements the message/external-body MIME type.
(This is not to be confused with MimeExternalObject, which implements the
handler for application/octet-stream and other types with no more specific
handlers.)
*/
typedef struct MimeExternalBodyClass MimeExternalBodyClass;
typedef struct MimeExternalBody MimeExternalBody;
struct MimeExternalBodyClass {
MimeObjectClass object;
};
extern MimeExternalBodyClass mimeExternalBodyClass;
struct MimeExternalBody {
MimeObject object; /* superclass variables */
MimeHeaders *hdrs; /* headers within this external-body, which
describe the network data which this body
is a pointer to. */
char *body; /* The "phantom body" of this link. */
};
#endif /* _MIMEEBOD_H_ */

1114
mailnews/mime/src/mimeenc.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,275 @@
/* -*- 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.
*/
#include "mimeeobj.h"
#include "xpgetstr.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeLeafClass
MimeDefClass(MimeExternalObject, MimeExternalObjectClass,
mimeExternalObjectClass, &MIME_SUPERCLASS);
extern int MK_MSG_ATTACHMENT;
#if defined(XP_MAC) && !defined(MOZILLA_30)
extern MimeObjectClass mimeMultipartAppleDoubleClass;
#endif
static int MimeExternalObject_initialize (MimeObject *);
static void MimeExternalObject_finalize (MimeObject *);
static int MimeExternalObject_parse_begin (MimeObject *);
static int MimeExternalObject_parse_buffer (char *, PRInt32, MimeObject *);
static int MimeExternalObject_parse_line (char *, PRInt32, MimeObject *);
static int MimeExternalObject_parse_decoded_buffer (char*, PRInt32, MimeObject*);
static PRBool MimeExternalObject_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
static int
MimeExternalObjectClassInitialize(MimeExternalObjectClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeLeafClass *lclass = (MimeLeafClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeExternalObject_initialize;
oclass->finalize = MimeExternalObject_finalize;
oclass->parse_begin = MimeExternalObject_parse_begin;
oclass->parse_buffer = MimeExternalObject_parse_buffer;
oclass->parse_line = MimeExternalObject_parse_line;
oclass->displayable_inline_p = MimeExternalObject_displayable_inline_p;
lclass->parse_decoded_buffer = MimeExternalObject_parse_decoded_buffer;
return 0;
}
static int
MimeExternalObject_initialize (MimeObject *object)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeExternalObject_finalize (MimeObject *object)
{
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeExternalObject_parse_begin (MimeObject *obj)
{
int status;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
#if defined (XP_MAC) && !defined(MOZILLA_30)
if (obj->parent && mime_typep(obj->parent,
(MimeObjectClass *) &mimeMultipartAppleDoubleClass))
goto done;
#endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
/* If we're writing this object, and we're doing it in raw form, then
now is the time to inform the backend what the type of this data is.
*/
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p &&
!obj->options->state->first_data_written_p)
{
status = MimeObject_output_init(obj, 0);
if (status < 0) return status;
PR_ASSERT(obj->options->state->first_data_written_p);
}
/* If we're writing this object as HTML, do all the work now -- just write
out a table with a link in it. (Later calls to the `parse_buffer' method
will simply discard the data of the object itself.)
*/
if (obj->options &&
obj->output_p &&
obj->options->write_html_p &&
obj->options->output_fn)
{
MimeDisplayOptions newopt = *obj->options; /* copy it */
char *id = 0;
char *id_url = 0;
char *id_name = 0;
char *id_imap = 0;
PRBool all_headers_p = obj->options->headers == MimeHeadersAll;
id = mime_part_address (obj);
if (obj->options->missing_parts)
id_imap = mime_imap_part_address (obj);
if (! id) return MK_OUT_OF_MEMORY;
if (obj->options && obj->options->url)
{
const char *url = obj->options->url;
if (id_imap && id)
{
/* if this is an IMAP part. */
id_url = mime_set_url_imap_part(url, id_imap, id);
}
else
{
/* This is just a normal MIME part as usual. */
id_url = mime_set_url_part(url, id, TRUE);
}
if (!id_url)
{
PR_Free(id);
return MK_OUT_OF_MEMORY;
}
}
if (!PL_strcmp (id, "0"))
{
PR_Free(id);
id = PL_strdup(XP_GetString(MK_MSG_ATTACHMENT));
}
else
{
const char *p = "Part "; /* #### i18n */
char *s = (char *)PR_MALLOC(PL_strlen(p) + PL_strlen(id) + 1);
if (!s)
{
PR_Free(id);
PR_Free(id_url);
return MK_OUT_OF_MEMORY;
}
/* we have a valid id */
if (id)
id_name = mime_find_suggested_name_of_part(id, obj);
PL_strcpy(s, p);
PL_strcat(s, id);
PR_Free(id);
id = s;
}
if (all_headers_p &&
/* Don't bother showing all headers on this part if it's the only
part in the message: in that case, we've already shown these
headers. */
obj->options->state &&
obj->options->state->root == obj->parent)
all_headers_p = FALSE;
newopt.fancy_headers_p = TRUE;
newopt.headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome);
{
char p[] = "<P>";
status = MimeObject_write(obj, p, 3, FALSE);
if (status < 0) goto FAIL;
}
status = MimeHeaders_write_attachment_box (obj->headers, &newopt,
obj->content_type,
obj->encoding,
id_name? id_name : id, id_url, 0);
FREEIF(id_name);
if (status < 0) goto FAIL;
{
char p[] = "<P>";
status = MimeObject_write(obj, p, 3, FALSE);
if (status < 0) goto FAIL;
}
FAIL:
FREEIF(id);
FREEIF(id_url);
FREEIF(id_name);
if (status < 0) return status;
}
#if defined (XP_MAC) && !defined(MOZILLA_30)
done:
#endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
return 0;
}
static int
MimeExternalObject_parse_buffer (char *buffer, PRInt32 size, MimeObject *obj)
{
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p)
{
/* The data will be base64-decoded and passed to
MimeExternalObject_parse_decoded_buffer. */
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_buffer(buffer, size,
obj);
}
else
{
/* Otherwise, simply ignore the data. */
return 0;
}
}
static int
MimeExternalObject_parse_decoded_buffer (char *buf, PRInt32 size,
MimeObject *obj)
{
/* This is called (by MimeLeafClass->parse_buffer) with blocks of data
that have already been base64-decoded. This will only be called in
the case where we're not emitting HTML, and want access to the raw
data itself.
We override the `parse_decoded_buffer' method provided by MimeLeaf
because, unlike most children of MimeLeaf, we do not want to line-
buffer the decoded data -- we want to simply pass it along to the
backend, without going through our `parse_line' method.
*/
if (!obj->output_p ||
!obj->options ||
obj->options->write_html_p)
{
PR_ASSERT(0);
return -1;
}
return MimeObject_write(obj, buf, size, TRUE);
}
static int
MimeExternalObject_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
/* This method should never be called (externals do no line buffering).
*/
PR_ASSERT(0);
return -1;
}
static PRBool
MimeExternalObject_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs)
{
return FALSE;
}

Просмотреть файл

@ -0,0 +1,44 @@
/* -*- 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.
*/
#ifndef _MIMEEOBJ_H_
#define _MIMEEOBJ_H_
#include "mimeleaf.h"
/* The MimeExternalObject class represents MIME parts which contain data
which cannot be displayed inline -- application/octet-stream and any
other type that is not otherwise specially handled. (This is not to
be confused with MimeExternalBody, which is the handler for the
message/external-object MIME type only.)
*/
typedef struct MimeExternalObjectClass MimeExternalObjectClass;
typedef struct MimeExternalObject MimeExternalObject;
struct MimeExternalObjectClass {
MimeLeafClass leaf;
};
extern MimeExternalObjectClass mimeExternalObjectClass;
struct MimeExternalObject {
MimeLeaf leaf;
};
#endif /* _MIMEEOBJ_H_ */

Просмотреть файл

@ -0,0 +1,452 @@
/* -*- 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.
*/
/* mimefilt.c --- test harness for libmime.a
This program reads a message from stdin and writes the output of the MIME
parser on stdout.
Parameters can be passed to the parser through the usual URL mechanism:
mimefilt BASE-URL?headers=all&rot13 < in > out
Some parameters can't be affected that way, so some additional switches
may be passed on the command line after the URL:
-fancy whether fancy headers should be generated (default)
-no-fancy opposite; this uses the headers used in the cases of
FO_SAVE_AS_TEXT or FO_QUOTE_MESSAGE
-html whether we should convert to HTML (like FO_PRESENT);
this is the default if no ?part= is specified.
-raw don't convert to HTML (FO_SAVE_AS);
this is the default if a ?part= is specified.
-outline at the end, print a debugging overview of the MIME structure
Before any output comes a blurb listing the content-type, charset, and
various other info that would have been put in the generated URL struct.
It's printed to the beginning of the output because otherwise this out-
of-band data would have been lost. (So the output of this program is,
in fact, a raw HTTP response.)
*/
#include "mimemsg.h"
#include "prglobal.h"
#include "key.h"
#include "cert.h"
#include "secrng.h"
#include "secmod.h"
#include "pk11func.h"
#ifndef XP_UNIX
ERROR! This is a unix-only file for the "mimefilt" standalone program.
This does not go into libmime.a.
#endif
static char *
test_file_type (const char *filename, void *stream_closure)
{
const char *suf = PL_strrchr(filename, '.');
if (!suf)
return 0;
suf++;
if (!PL_strcasecmp(suf, "txt") ||
!PL_strcasecmp(suf, "text"))
return PL_strdup("text/plain");
else if (!PL_strcasecmp(suf, "htm") ||
!PL_strcasecmp(suf, "html"))
return PL_strdup("text/html");
else if (!PL_strcasecmp(suf, "gif"))
return PL_strdup("image/gif");
else if (!PL_strcasecmp(suf, "jpg") ||
!PL_strcasecmp(suf, "jpeg"))
return PL_strdup("image/jpeg");
else if (!PL_strcasecmp(suf, "pjpg") ||
!PL_strcasecmp(suf, "pjpeg"))
return PL_strdup("image/pjpeg");
else if (!PL_strcasecmp(suf, "xbm"))
return PL_strdup("image/x-xbitmap");
else if (!PL_strcasecmp(suf, "xpm"))
return PL_strdup("image/x-xpixmap");
else if (!PL_strcasecmp(suf, "xwd"))
return PL_strdup("image/x-xwindowdump");
else if (!PL_strcasecmp(suf, "bmp"))
return PL_strdup("image/x-MS-bmp");
else if (!PL_strcasecmp(suf, "au"))
return PL_strdup("audio/basic");
else if (!PL_strcasecmp(suf, "aif") ||
!PL_strcasecmp(suf, "aiff") ||
!PL_strcasecmp(suf, "aifc"))
return PL_strdup("audio/x-aiff");
else if (!PL_strcasecmp(suf, "ps"))
return PL_strdup("application/postscript");
else
return 0;
}
static char *
test_type_icon(const char *type, void *stream_closure)
{
if (!PL_strncasecmp(type, "text/", 5))
return PL_strdup("internal-gopher-text");
else if (!PL_strncasecmp(type, "image/", 6))
return PL_strdup("internal-gopher-image");
else if (!PL_strncasecmp(type, "audio/", 6))
return PL_strdup("internal-gopher-sound");
else if (!PL_strncasecmp(type, "video/", 6))
return PL_strdup("internal-gopher-movie");
else if (!PL_strncasecmp(type, "application/", 12))
return PL_strdup("internal-gopher-binary");
else
return PL_strdup("internal-gopher-unknown");
}
static int
test_output_fn(char *buf, PRInt32 size, void *closure)
{
FILE *out = (FILE *) closure;
if (out)
return fwrite(buf, sizeof(*buf), size, out);
else
return 0;
}
static int
test_output_init_fn (const char *type,
const char *charset,
const char *name,
const char *x_mac_type,
const char *x_mac_creator,
void *stream_closure)
{
FILE *out = (FILE *) stream_closure;
fprintf(out, "CONTENT-TYPE: %s", type);
if (charset)
fprintf(out, "; charset=\"%s\"", charset);
if (name)
fprintf(out, "; name=\"%s\"", name);
if (x_mac_type || x_mac_creator)
fprintf(out, "; x-mac-type=\"%s\"; x-mac-creator=\"%s\"",
x_mac_type ? x_mac_type : "",
x_mac_creator ? x_mac_type : "");
fprintf(out, CRLF CRLF);
return 0;
}
static int
test_set_html_state_fn (void *stream_closure,
PRBool layer_encapsulate_p,
PRBool start_p,
PRBool abort_p)
{
char random_close_tags[] =
"</TABLE></TABLE></TABLE></TABLE></TABLE></TABLE>"
"</DL></DL></DL></DL></DL></DL></DL></DL></DL></DL>"
"</DL></DL></DL></DL></DL></DL></DL></DL></DL></DL>"
"</B></B></B></B></B></B></B></B></B></B></B></B>"
"</PRE></PRE></PRE></PRE></PRE></PRE></PRE></PRE>"
"<BASEFONT SIZE=3></SCRIPT>";
return test_output_fn(random_close_tags, PL_strlen(random_close_tags),
stream_closure);
}
static void *
test_image_begin(const char *image_url, const char *content_type,
void *stream_closure)
{
return ((void *) PL_strdup(image_url));
}
static void
test_image_end(void *image_closure, int status)
{
char *url = (char *) image_closure;
if (url) PR_Free(url);
}
static char *
test_image_make_image_html(void *image_data)
{
char *url = (char *) image_data;
#if 0
const char *prefix = "<P><CENTER><IMG SRC=\"";
const char *suffix = "\"></CENTER><P>";
#else
const char *prefix = ("<P><CENTER><TABLE BORDER=2 CELLPADDING=20"
" BGCOLOR=WHITE>"
"<TR><TD ALIGN=CENTER>"
"an inlined image would have gone here for<BR>");
const char *suffix = "</TD></TR></TABLE></CENTER><P>";
#endif
char *buf;
buf = (char *) PR_MALLOC (PL_strlen (prefix) + PL_strlen (suffix) +
PL_strlen (url) + 20);
if (!buf) return 0;
*buf = 0;
PL_strcat (buf, prefix);
PL_strcat (buf, url);
PL_strcat (buf, suffix);
return buf;
}
static int test_image_write_buffer(char *buf, PRInt32 size, void *image_closure)
{
return 0;
}
static char *
test_passwd_prompt (PK11SlotInfo *slot, void *wincx)
{
char buf[2048], *s;
fprintf(stdout, "#### Password required: ");
s = fgets(buf, sizeof(buf)-1, stdin);
if (!s) return s;
if (s[strlen(s)-1] == '\r' ||
s[strlen(s)-1] == '\n')
s[strlen(s)-1] = '\0';
return s;
}
int
test(FILE *in, FILE *out,
const char *url,
PRBool fancy_headers_p,
PRBool html_p,
PRBool outline_p,
PRBool dexlate_p,
PRBool variable_width_plaintext_p)
{
int status = 0;
MimeObject *obj = 0;
MimeDisplayOptions *opt = PR_NEW(MimeDisplayOptions);
XP_MEMSET(opt, 0, sizeof(*opt));
if (dexlate_p) html_p = FALSE;
opt->fancy_headers_p = fancy_headers_p;
opt->headers = MimeHeadersSome;
opt->no_inline_p = FALSE;
opt->rot13_p = FALSE;
status = mime_parse_url_options(url, opt);
if (status < 0)
{
PR_Free(opt);
return MK_OUT_OF_MEMORY;
}
opt->url = url;
opt->write_html_p = html_p;
opt->dexlate_p = dexlate_p;
opt->output_init_fn = test_output_init_fn;
opt->output_fn = test_output_fn;
opt->set_html_state_fn = test_set_html_state_fn;
opt->charset_conversion_fn= 0;
opt->rfc1522_conversion_fn= 0;
opt->reformat_date_fn = 0;
opt->file_type_fn = test_file_type;
opt->type_description_fn = 0;
opt->type_icon_name_fn = test_type_icon;
opt->stream_closure = out;
opt->image_begin = test_image_begin;
opt->image_end = test_image_end;
opt->make_image_html = test_image_make_image_html;
opt->image_write_buffer = test_image_write_buffer;
opt->variable_width_plaintext_p = variable_width_plaintext_p;
obj = mime_new ((MimeObjectClass *)&mimeMessageClass,
(MimeHeaders *) NULL,
MESSAGE_RFC822);
if (!obj)
{
PR_Free(opt);
return MK_OUT_OF_MEMORY;
}
obj->options = opt;
status = obj->class->initialize(obj);
if (status >= 0)
status = obj->class->parse_begin(obj);
if (status < 0)
{
PR_Free(opt);
PR_Free(obj);
return MK_OUT_OF_MEMORY;
}
while (1)
{
char buf[255];
int size = fread(buf, sizeof(*buf), sizeof(buf), stdin);
if (size <= 0) break;
status = obj->class->parse_buffer(buf, size, obj);
if (status < 0)
{
mime_free(obj);
PR_Free(opt);
return status;
}
}
status = obj->class->parse_eof(obj, FALSE);
if (status >= 0)
status = obj->class->parse_end(obj, FALSE);
if (status < 0)
{
mime_free(obj);
PR_Free(opt);
return status;
}
if (outline_p)
{
fprintf(out, "\n\n"
"###############################################################\n");
obj->class->debug_print(obj, stderr, 0);
fprintf(out,
"###############################################################\n");
}
mime_free (obj);
PR_Free(opt);
return 0;
}
static char *
test_cdb_name_cb (void *arg, int vers)
{
static char f[1024];
if (vers <= 4)
sprintf(f, "%s/.netscape/cert.db", getenv("HOME"));
else
sprintf(f, "%s/.netscape/cert%d.db", getenv("HOME"), vers);
return f;
}
static char *
test_kdb_name_cb (void *arg, int vers)
{
static char f[1024];
if (vers <= 2)
sprintf(f, "%s/.netscape/key.db", getenv("HOME"));
else
sprintf(f, "%s/.netscape/key%d.db", getenv("HOME"), vers);
return f;
}
extern void SEC_Init(void);
int
main (int argc, char **argv)
{
PRInt32 i = 1;
char *url = "";
PRBool fancy_p = TRUE;
PRBool html_p = TRUE;
PRBool outline_p = FALSE;
PRBool dexlate_p = FALSE;
char filename[1000];
CERTCertDBHandle *cdb_handle;
SECKEYKeyDBHandle *kdb_handle;
PR_Init("mimefilt", 24, 1, 0);
cdb_handle = (CERTCertDBHandle *) malloc(sizeof(*cdb_handle));
memset(cdb_handle, 0, sizeof(*cdb_handle));
if (SECSuccess != CERT_OpenCertDB(cdb_handle, FALSE, test_cdb_name_cb, NULL))
CERT_OpenVolatileCertDB(cdb_handle);
CERT_SetDefaultCertDB(cdb_handle);
RNG_RNGInit();
kdb_handle = SECKEY_OpenKeyDB(PR_FALSE, test_kdb_name_cb, NULL);
SECKEY_SetDefaultKeyDB(kdb_handle);
PK11_SetPasswordFunc(test_passwd_prompt);
sprintf(filename, "%s/.netscape/secmodule.db", getenv("HOME"));
SECMOD_init(filename);
SEC_Init();
if (i < argc)
{
if (argv[i][0] == '-')
url = PL_strdup("");
else
url = argv[i++];
}
if (url &&
(PL_strstr(url, "?part=") ||
PL_strstr(url, "&part=")))
html_p = FALSE;
while (i < argc)
{
if (!PL_strcmp(argv[i], "-fancy"))
fancy_p = TRUE;
else if (!PL_strcmp(argv[i], "-no-fancy"))
fancy_p = FALSE;
else if (!PL_strcmp(argv[i], "-html"))
html_p = TRUE;
else if (!PL_strcmp(argv[i], "-raw"))
html_p = FALSE;
else if (!PL_strcmp(argv[i], "-outline"))
outline_p = TRUE;
else if (!PL_strcmp(argv[i], "-dexlate"))
dexlate_p = TRUE;
else
{
fprintf(stderr,
"usage: %s [ URL [ -fancy | -no-fancy | -html | -raw | -outline | -dexlate ]]\n"
" < message/rfc822 > output\n",
(PL_strrchr(argv[0], '/') ?
PL_strrchr(argv[0], '/') + 1 :
argv[0]));
i = 1;
goto FAIL;
}
i++;
}
i = test(stdin, stdout, url, fancy_p, html_p, outline_p, dexlate_p, TRUE);
fprintf(stdout, "\n");
fflush(stdout);
FAIL:
CERT_ClosePermCertDB(cdb_handle);
SECKEY_CloseKeyDB(kdb_handle);
exit(i);
}

2974
mailnews/mime/src/mimehdrs.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,85 @@
/* -*- 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.
*/
#ifndef _MIMEHDRS_H_
#define _MIMEHDRS_H_
// RICHIE
#include "modlmime.h"
/* This file defines the interface to message-header parsing and formatting
code, including conversion to HTML.
*/
/* Other structs defined later in this file.
*/
/* Creation and destruction.
*/
extern MimeHeaders *MimeHeaders_new (void);
extern void MimeHeaders_free (MimeHeaders *);
extern MimeHeaders *MimeHeaders_copy (MimeHeaders *);
/* Feed this method the raw data from which you would like a header
block to be parsed, one line at a time. Feed it a blank line when
you're done. Returns negative on allocation-related failure.
*/
extern int MimeHeaders_parse_line (const char *buffer, PRInt32 size,
MimeHeaders *hdrs);
/* Converts a MimeHeaders object into HTML, by writing to the provided
output function.
*/
extern int MimeHeaders_write_headers_html (MimeHeaders *hdrs,
MimeDisplayOptions *opt);
/* Writes the headers as text/plain.
This writes out a blank line after the headers, unless
dont_write_content_type is true, in which case the header-block
is not closed off, and none of the Content- headers are written.
*/
extern int MimeHeaders_write_raw_headers (MimeHeaders *hdrs,
MimeDisplayOptions *opt,
PRBool dont_write_content_type);
/* For drawing the tables that represent objects that can't be displayed
inline. */
extern int MimeHeaders_write_attachment_box(MimeHeaders *hdrs,
MimeDisplayOptions *opt,
const char *content_type,
const char *encoding,
const char *name,
const char *name_url,
const char *body);
#ifdef MOZ_SECURITY
HG77761
#endif
/* Does all the heuristic silliness to find the filename in the given headers.
*/
extern char *MimeHeaders_get_name(MimeHeaders *hdrs);
extern char *mime_decode_filename(char *name);
#endif /* _MIMEHDRS_H_ */

Просмотреть файл

@ -0,0 +1,64 @@
/* -*- 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.
*/
/*
* The purpose of this header file is to centralize all of the
* generated HTML/CSS for libmime.
*/
#ifndef _MIMEHTML_H_
#define _MIMEHTML_H_
/*
* HTML in mimehdrs.c
*/
#define MHTML_BLOCKQUOTE_BEGIN "<BLOCKQUOTE TYPE=CITE>"
#define MHTML_STYLE_IMPORT "<HTML><HEAD><LINK REL=\"stylesheet\" HREF=\"resource:/res/mail.css\">"
#define MHTML_JS_IMPORT "<SCRIPT LANGUAGE=\"JavaScript1.2\" SRC=\"resource:/res/mail.js\"></SCRIPT></HEAD>"
#define MHTML_HEADER_TABLE "<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>"
#define MHTML_TABLE_BEGIN "<TABLE><TR><TD>"
#define MHTML_TABLE_COLUMN_BEGIN "<TR><TD><B><I>"
#define MHTML_TABLE_COLUMN_END "</I></B></TD></TR>"
#define MHTML_TABLE_END "</TABLE>"
#define MHTML_COL_AND_TABLE_END "</td></tr></table>"
#define MHTML_TITLE "<TITLE>%s</TITLE>\n"
#define MHTML_CLIP_START "</TD><TD VALIGN=TOP><DIV "
#ifndef XP_MAC
#define MHTML_CLIP_DIM "CLIP=0,0,30,30 "
#else
#define MHTML_CLIP_DIM "CLIP=0,0,48,30 "
#endif
#define MHTML_NOATTACH_ID "ID=noattach%ld>"
#define MHTML_ENDBEGIN_DIV "</DIV><DIV LOCKED "
#define MHTML_ATTACH_ID "ID=attach%ld style=\"display: 'none';\" >"
#define MHTML_DISP_ICON_LINK "<a href=javascript:toggleAttachments(); onMouseOver=\"window.status='%s'; return true\"; onMouseOut=\"window.status=''; return true\" PRIVATE>"
#define MHTML_ATTACH_ICON "<IMG SRC=resource:/res/network/gopher-text.gif BORDER=0>"
#define MHTML_CLIP_END "</a></DIV>"
#define HEADER_START_JUNK "<TR><TH VALIGN=BASELINE ALIGN=RIGHT NOWRAP>"
#define HEADER_MIDDLE_JUNK ": </TH><TD>"
#define HEADER_END_JUNK "</TD></TR>"
/*
* HTML in mimemult.c
*/
#endif /* _MIMEHTML_H_ */

1179
mailnews/mime/src/mimei.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

430
mailnews/mime/src/mimei.h Normal file
Просмотреть файл

@ -0,0 +1,430 @@
/* -*- 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.
*/
#ifndef _MIMEI_H_
#define _MIMEI_H_
/*
This module, libmime, implements a general-purpose MIME parser.
One of the methods provided by this parser is the ability to emit
an HTML representation of it.
All Mozilla-specific code is (and should remain) isolated in the
file mimemoz.c. Generally, if the code involves images, netlib
streams it should be in mimemoz.c instead of in the main body of
the MIME parser.
The parser is object-oriented and fully buzzword-compliant.
There is a class for each MIME type, and each class is responsible
for parsing itself, and/or handing the input data off to one of its
child objects.
The class hierarchy is:
MimeObject (abstract)
|
|--- MimeContainer (abstract)
| |
| |--- MimeMultipart (abstract)
| | |
| | |--- MimeMultipartMixed
| | |
| | |--- MimeMultipartDigest
| | |
| | |--- MimeMultipartParallel
| | |
| | |--- MimeMultipartAlternative
| | |
| | |--- MimeMultipartRelated
| | |
| | |--- MimeMultipartAppleDouble
| | |
| | |--- MimeSunAttachment
| | |
| | |--- MimeMultipartSigned (abstract)
| | |
| | |--- MimeMultipartSigned
| |
| |--- MimeXlateed (abstract)
| | |
| | |--- MimeXlateed
| |
| |--- MimeMessage
| |
| |--- MimeUntypedText
|
|--- MimeLeaf (abstract)
| |
| |--- MimeInlineText (abstract)
| | |
| | |--- MimeInlineTextPlain
| | |
| | |--- MimeInlineTextHTML
| | |
| | |--- MimeInlineTextRichtext
| | | |
| | | |--- MimeInlineTextEnriched
| | |
| | |--- MimeInlineTextVCard
| | |
| | |--- MimeInlineTextCalendar
| |
| |--- MimeInlineImage
| |
| |--- MimeExternalObject
|
|--- MimeExternalBody
=========================================================================
The definition of these classes is somewhat idiosyncratic, since I defined
my own small object system, instead of giving the C++ virus another foothold.
(I would have liked to have written this in Java, but our runtime isn't
quite ready for prime time yet.)
There is one header file and one source file for each class (for example,
the MimeInlineText class is defined in "mimetext.h" and "mimetext.c".)
Each header file follows the following boiler-plate form:
TYPEDEFS: these come first to avoid circular dependencies.
typedef struct FoobarClass FoobarClass;
typedef struct Foobar Foobar;
CLASS DECLARATION:
Theis structure defines the callback routines and other per-class data
of the class defined in this module.
struct FoobarClass {
ParentClass superclass;
...any callbacks or class-variables...
};
CLASS DEFINITION:
This variable holds an instance of the one-and-only class record; the
various instances of this class point to this object. (One interrogates
the type of an instance by comparing the value of its class pointer with
the address of this variable.)
extern FoobarClass foobarClass;
INSTANCE DECLARATION:
Theis structure defines the per-instance data of an object, and a pointer
to the corresponding class record.
struct Foobar {
Parent parent;
...any instance variables...
};
Then, in the corresponding .c file, the following structure is used:
CLASS DEFINITION:
First we pull in the appropriate include file (which includes all necessary
include files for the parent classes) and then we define the class object
using the MimeDefClass macro:
#include "foobar.h"
#define MIME_SUPERCLASS parentlClass
MimeDefClass(Foobar, FoobarClass, foobarClass, &MIME_SUPERCLASS);
The definition of MIME_SUPERCLASS is just to move most of the knowlege of the
exact class hierarchy up to the file's header, instead of it being scattered
through the various methods; see below.
METHOD DECLARATIONS:
We will be putting function pointers into the class object, so we declare
them here. They can generally all be static, since nobody outside of this
file needs to reference them by name; all references to these routines should
be through the class object.
extern int FoobarMethod(Foobar *);
...etc...
CLASS INITIALIZATION FUNCTION:
The MimeDefClass macro expects us to define a function which will finish up
any initialization of the class object that needs to happen before the first
time it is instantiated. Its name must be of the form "<class>Initialize",
and it should initialize the various method slots in the class as
appropriate. Any methods or class variables which this class does not wish
to override will be automatically inherited from the parent class (by virtue
of its class-initialization function having been run first.) Each class
object will only be initialized once.
static int
FoobarClassInitialize(FoobarClass *class)
{
class->method = FoobarMethod.
...etc...
}
METHOD DEFINITIONS:
Next come the definitions of the methods we referred to in the class-init
function. The way to access earlier methods (methods defined on the
superclass) is to simply extract them from the superclass's object.
But note that you CANNOT get at methods by indirecting through
object->class->superclass: that will only work to one level, and will
go into a loop if some subclass tries to continue on this method.
The easiest way to do this is to make use of the MIME_SUPERCLASS macro that
was defined at the top of the file, as shown below. The alternative to that
involves typing the literal name of the direct superclass of the class
defined in this file, which will be a maintenance headache if the class
hierarchy changes. If you use the MIME_SUPERCLASS idiom, then a textual
change is required in only one place if this class's superclass changes.
static void
Foobar_finalize (MimeObject *object)
{
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object); // RIGHT
parentClass.whatnot.object.finalize(object); // (works...)
object->class->superclass->finalize(object); // WRONG!!
}
*/
#include "mimehdrs.h"
typedef struct MimeObject MimeObject;
typedef struct MimeObjectClass MimeObjectClass;
/* (I don't pretend to understand this.) */
#define cpp_stringify_noop_helper(x)#x
#define cpp_stringify(x) cpp_stringify_noop_helper(x)
/* Macro used for setting up class definitions.
*/
#define MimeDefClass(ITYPE,CTYPE,CVAR,CSUPER) \
static int CTYPE##Initialize(CTYPE *); \
CTYPE CVAR = { cpp_stringify(ITYPE), sizeof(ITYPE), \
(MimeObjectClass *) CSUPER, \
(int (*) (MimeObjectClass *)) CTYPE##Initialize, 0, }
/* Creates a new (subclass of) MimeObject of the given class, with the
given headers (which are copied.)
*/
extern MimeObject *mime_new (MimeObjectClass *class, MimeHeaders *hdrs,
const char *override_content_type);
/* Destroys a MimeObject (or subclass) and all data associated with it.
*/
extern void mime_free (MimeObject *object);
/* Given a content-type string, finds and returns an appropriate subclass
of MimeObject. A class object is returned. If `exact_match_p' is true,
then only fully-known types will be returned; that is, if it is true,
then "text/x-unknown" will return MimeInlineTextPlainType, but if it is
false, it will return NULL.
*/
extern MimeObjectClass *mime_find_class (const char *content_type,
MimeHeaders *hdrs,
MimeDisplayOptions *opts,
PRBool exact_match_p);
/* Given a content-type string, creates and returns an appropriate subclass
of MimeObject. The headers (from which the content-type was presumably
extracted) are copied.
*/
extern MimeObject *mime_create (const char *content_type, MimeHeaders *hdrs,
MimeDisplayOptions *opts);
/* Querying the type hierarchy */
extern PRBool mime_subclass_p(MimeObjectClass *child,
MimeObjectClass *parent);
extern PRBool mime_typep(MimeObject *obj, MimeObjectClass *class);
/* Returns a string describing the location of the part (like "2.5.3").
This is not a full URL, just a part-number.
*/
extern char *mime_part_address(MimeObject *obj);
/* Returns a string describing the location of the *IMAP* part (like "2.5.3").
This is not a full URL, just a part-number.
This part is explicitly passed in the X-Mozilla-IMAP-Part header.
Return value must be freed by the caller.
*/
extern char *mime_imap_part_address(MimeObject *obj);
/* Puts a part-number into a URL. If append_p is true, then the part number
is appended to any existing part-number already in that URL; otherwise,
it replaces it.
*/
extern char *mime_set_url_part(const char *url, char *part, PRBool append_p);
/* Puts an *IMAP* part-number into a URL.
*/
extern char *mime_set_url_imap_part(const char *url, char *part, char *libmimepart);
/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID
number matches, and returns the MimeObject (else NULL.)
(part is not a URL -- it's of the form "1.3.5".)
*/
extern MimeObject *mime_address_to_part(const char *part, MimeObject *obj);
/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID
number matches; if one is found, returns the Content-Name of that part.
Else returns NULL. (part is not a URL -- it's of the form "1.3.5".)
*/
extern char *mime_find_suggested_name_of_part(const char *part,
MimeObject *obj);
/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID
number matches; if one is found, returns the Content-Name of that part.
Else returns NULL. (part is not a URL -- it's of the form "1.3.5".)
*/
extern char *mime_find_content_type_of_part(const char *part, MimeObject *obj);
#ifdef MOZ_SECURITY
HG23957
#endif /* MOZ_SECURITY */
/* Parse the various "?" options off the URL and into the options struct.
*/
extern int mime_parse_url_options(const char *url, MimeDisplayOptions *);
#ifdef MOZ_SECURITY
HG22990
#endif
struct MimeParseStateObject {
MimeObject *root; /* The outermost parser object. */
PRBool separator_queued_p; /* Whether a separator should be written out
before the next text is written (this lets
us write separators lazily, so that one
doesn't appear at the end, and so that more
than one don't appear in a row.) */
PRBool separator_suppressed_p; /* Whether the currently-queued separator
should not be printed; this is a kludge to
prevent seps from being printed just after
a header block... */
PRBool first_part_written_p; /* State used for the `Show Attachments As
Links' kludge. */
PRBool post_header_html_run_p; /* Whether we've run the
options->generate_post_header_html_fn */
PRBool first_data_written_p; /* State used for Mozilla lazy-stream-
creation evilness. */
PRBool xlated_p; /* If options->dexlate_p is true, then this
will be set to indicate whether any
dexlateion did in fact occur.
*/
};
/* Some output-generation utility functions...
*/
extern int MimeObject_output_init(MimeObject *obj, const char *content_type);
/* The `user_visible_p' argument says whether the output that has just been
written will cause characters or images to show up on the screen, that
is, it should be FALSE if the stuff being written is merely structural
HTML or whitespace ("<P>", "</TABLE>", etc.) This information is used
when making the decision of whether a separating <HR> is needed.
*/
extern int MimeObject_write(MimeObject *, char *data, PRInt32 length,
PRBool user_visible_p);
extern int MimeOptions_write(MimeDisplayOptions *,
char *data, PRInt32 length,
PRBool user_visible_p);
/* Writes out the right kind of HR (or rather, queues it for writing.) */
extern int MimeObject_write_separator(MimeObject *);
/* Random junk
*/
extern int MK_OUT_OF_MEMORY;
#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF(obj) do { if (obj) { PR_Free (obj); obj = 0; }} while (0)
#ifndef MOZILLA_30
/* Turn this on if you want to play with the idea of displaying icons in the
headers to represent attachments, and put icons next to each attachment so
you can easily save them without having to bring up the "as links" view.
Right now, this is all really half-baked, half-implemented,
half-thought-out, and so on. But the current "attachment panel" needs to be
destroyed, and this is the only hope. */
#define JS_ATTACHMENT_MUMBO_JUMBO
extern PRBool MimeObjectChildIsMessageBody(MimeObject *obj,
PRBool *isAlterOrRelated);
#endif /* MOZILLA_30 */
/* Sends some mail, without user interaction. */
extern int
MimeSendMessage(MimeDisplayOptions* options, char* to, char* subject,
char* otherheaders, char* body);
/* #### These ought to be in libxp or nspr, not libmsg...*/
extern int msg_GrowBuffer (PRInt32 desired_size, PRInt32 element_size,
PRInt32 quantum, char **buffer, PRInt32 *size);
extern int msg_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size,
char **bufferP, PRInt32 *buffer_sizeP,
PRInt32 *buffer_fpP,
PRBool convert_newlines_p,
PRInt32 (*per_line_fn) (char *line,
PRUint32 line_length,
void *closure),
void *closure);
/* This is the data tagged to contexts and the declaration needs to be
in a header file since more than mimemoz.c needs to see it now...
*/
#ifdef HAVE_MIME_DATA_SLOT
# define LOCK_LAST_CACHED_MESSAGE
#endif
struct MimeDisplayData { /* This struct is what we hang off of
(context)->mime_data, to remember info
about the last MIME object we've
parsed and displayed. See
MimeGuessURLContentName() below.
*/
MimeObject *last_parsed_object;
char *last_parsed_url;
#ifdef LOCK_LAST_CACHED_MESSAGE
char *previous_locked_url;
#endif /* LOCK_LAST_CACHED_MESSAGE */
#ifndef MOZILLA_30
MSG_Pane* last_pane;
#endif /* MOZILLA_30 */
};
#endif /* _MIMEI_H_ */

Просмотреть файл

@ -0,0 +1,209 @@
/* -*- 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.
*/
#include "mimeiimg.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeLeafClass
MimeDefClass(MimeInlineImage, MimeInlineImageClass,
mimeInlineImageClass, &MIME_SUPERCLASS);
static int MimeInlineImage_initialize (MimeObject *);
static void MimeInlineImage_finalize (MimeObject *);
static int MimeInlineImage_parse_begin (MimeObject *);
static int MimeInlineImage_parse_line (char *, PRInt32, MimeObject *);
static int MimeInlineImage_parse_eof (MimeObject *, PRBool);
static int MimeInlineImage_parse_decoded_buffer (char *, PRInt32, MimeObject *);
static int
MimeInlineImageClassInitialize(MimeInlineImageClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeLeafClass *lclass = (MimeLeafClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeInlineImage_initialize;
oclass->finalize = MimeInlineImage_finalize;
oclass->parse_begin = MimeInlineImage_parse_begin;
oclass->parse_line = MimeInlineImage_parse_line;
oclass->parse_eof = MimeInlineImage_parse_eof;
lclass->parse_decoded_buffer = MimeInlineImage_parse_decoded_buffer;
return 0;
}
static int
MimeInlineImage_initialize (MimeObject *object)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeInlineImage_finalize (MimeObject *object)
{
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeInlineImage_parse_begin (MimeObject *obj)
{
MimeInlineImage *img = (MimeInlineImage *) obj;
MimeInlineImageClass *class;
int status;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
if (!obj->output_p) return 0;
if (!obj->options || !obj->options->output_fn)
return 0;
class = (MimeInlineImageClass *) obj->class;
if (obj->options &&
obj->options->image_begin &&
obj->options->write_html_p &&
obj->options->image_write_buffer)
{
char *html, *part, *image_url;
const char *ct;
part = mime_part_address(obj);
if (!part) return MK_OUT_OF_MEMORY;
image_url = mime_set_url_part(obj->options->url, part, TRUE);
if (!image_url)
{
PR_Free(part);
return MK_OUT_OF_MEMORY;
}
PR_Free(part);
ct = obj->content_type;
if (!ct) ct = IMAGE_GIF; /* Can't happen? Close enough. */
img->image_data =
obj->options->image_begin(image_url, ct, obj->options->stream_closure);
PR_Free(image_url);
if (!img->image_data) return MK_OUT_OF_MEMORY;
html = obj->options->make_image_html(img->image_data);
if (!html) return MK_OUT_OF_MEMORY;
status = MimeObject_write(obj, html, PL_strlen(html), TRUE);
PR_Free(html);
if (status < 0) return status;
}
return 0;
}
static int
MimeInlineImage_parse_eof (MimeObject *obj, PRBool abort_p)
{
MimeInlineImage *img = (MimeInlineImage *) obj;
int status;
if (obj->closed_p) return 0;
/* Force out any buffered data from the superclass (the base64 decoder.) */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) abort_p = TRUE;
if (img->image_data)
{
obj->options->image_end(img->image_data,
(status < 0 ? status : (abort_p ? -1 : 0)));
img->image_data = 0;
}
return status;
}
static int
MimeInlineImage_parse_decoded_buffer (char *buf, PRInt32 size, MimeObject *obj)
{
/* This is called (by MimeLeafClass->parse_buffer) with blocks of data
that have already been base64-decoded. Pass this raw image data
along to the backend-specific image display code.
*/
MimeInlineImage *img = (MimeInlineImage *) obj;
int status;
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p)
{
/* in this case, we just want the raw data...
Make the stream, if it's not made, and dump the data out.
*/
if (!obj->options->state->first_data_written_p)
{
status = MimeObject_output_init(obj, 0);
if (status < 0) return status;
PR_ASSERT(obj->options->state->first_data_written_p);
}
return MimeObject_write(obj, buf, size, TRUE);
}
if (!obj->options ||
!obj->options->image_write_buffer)
return 0;
/* If we don't have any image data, the image_end method must have already
been called, so don't call image_write_buffer again. */
if (!img->image_data) return 0;
/* Hand this data off to the backend-specific image display stream.
*/
status = obj->options->image_write_buffer (buf, size, img->image_data);
/* If the image display stream fails, then close the stream - but do not
return the failure status, and do not give up on parsing this object.
Just because the image data was corrupt doesn't mean we need to give up
on the whole document; we can continue by just skipping over the rest of
this part, and letting our parent continue.
*/
if (status < 0)
{
obj->options->image_end (img->image_data, status);
img->image_data = 0;
status = 0;
}
return status;
}
static int
MimeInlineImage_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
/* This method should never be called (inline images do no line buffering).
*/
PR_ASSERT(0);
return -1;
}

Просмотреть файл

@ -0,0 +1,45 @@
/* -*- 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.
*/
#ifndef _MIMEIIMG_H_
#define _MIMEIIMG_H_
#include "mimeleaf.h"
/* The MimeInlineImage class implements those MIME image types which can be
displayed inline (currently image/gif, image/jpeg, and image/xbm.)
*/
typedef struct MimeInlineImageClass MimeInlineImageClass;
typedef struct MimeInlineImage MimeInlineImage;
struct MimeInlineImageClass {
MimeLeafClass leaf;
};
extern MimeInlineImageClass mimeInlineImageClass;
struct MimeInlineImage {
MimeLeaf leaf;
/* Opaque data object for the backend-specific inline-image-display code
(internal-external-reconnect nastiness.) */
void *image_data;
};
#endif /* _MIMEIIMG_H_ */

Просмотреть файл

@ -0,0 +1,185 @@
/* -*- 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.
*/
#include "modmimee.h"
#include "mimeleaf.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeObjectClass
MimeDefClass(MimeLeaf, MimeLeafClass, mimeLeafClass, &MIME_SUPERCLASS);
static int MimeLeaf_initialize (MimeObject *);
static void MimeLeaf_finalize (MimeObject *);
static int MimeLeaf_parse_begin (MimeObject *);
static int MimeLeaf_parse_buffer (char *, PRInt32, MimeObject *);
static int MimeLeaf_parse_line (char *, PRInt32, MimeObject *);
static int MimeLeaf_parse_eof (MimeObject *, PRBool);
static PRBool MimeLeaf_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
static int
MimeLeafClassInitialize(MimeLeafClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeLeaf_initialize;
oclass->finalize = MimeLeaf_finalize;
oclass->parse_begin = MimeLeaf_parse_begin;
oclass->parse_buffer = MimeLeaf_parse_buffer;
oclass->parse_line = MimeLeaf_parse_line;
oclass->parse_eof = MimeLeaf_parse_eof;
oclass->displayable_inline_p = MimeLeaf_displayable_inline_p;
/* Default `parse_buffer' method is one which line-buffers the now-decoded
data and passes it on to `parse_line'. (We snarf the implementation of
this method from our superclass's implementation of `parse_buffer', which
inherited it from MimeObject.)
*/
class->parse_decoded_buffer =
((MimeObjectClass*)&MIME_SUPERCLASS)->parse_buffer;
return 0;
}
static int
MimeLeaf_initialize (MimeObject *obj)
{
/* This is an abstract class; it shouldn't be directly instanciated. */
PR_ASSERT(obj->class != (MimeObjectClass *) &mimeLeafClass);
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
}
static void
MimeLeaf_finalize (MimeObject *object)
{
MimeLeaf *leaf = (MimeLeaf *)object;
object->class->parse_eof (object, FALSE);
/* Free the decoder data, if it's still around. It was probably freed
in MimeLeaf_parse_eof(), but just in case... */
if (leaf->decoder_data)
{
MimeDecoderDestroy(leaf->decoder_data, TRUE);
leaf->decoder_data = 0;
}
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize (object);
}
static int
MimeLeaf_parse_begin (MimeObject *obj)
{
MimeLeaf *leaf = (MimeLeaf *) obj;
MimeDecoderData *(*fn) (int (*) (const char*, PRInt32, void*), void*) = 0;
/* Initialize a decoder if necessary.
*/
if (!obj->encoding)
;
else if (!PL_strcasecmp(obj->encoding, ENCODING_BASE64))
fn = &MimeB64DecoderInit;
else if (!PL_strcasecmp(obj->encoding, ENCODING_QUOTED_PRINTABLE))
fn = &MimeQPDecoderInit;
else if (!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE) ||
!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE2) ||
!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE3) ||
!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE4))
fn = &MimeUUDecoderInit;
if (fn)
{
leaf->decoder_data =
fn (/* The (int (*) ...) cast is to turn the `void' argument
into `MimeObject'. */
((int (*) (const char *, PRInt32, void *))
((MimeLeafClass *)obj->class)->parse_decoded_buffer),
obj);
if (!leaf->decoder_data)
return MK_OUT_OF_MEMORY;
}
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
}
static int
MimeLeaf_parse_buffer (char *buffer, PRInt32 size, MimeObject *obj)
{
MimeLeaf *leaf = (MimeLeaf *) obj;
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
/* If we're not supposed to write this object, bug out now.
*/
if (!obj->output_p ||
!obj->options ||
!obj->options->output_fn)
return 0;
if (leaf->decoder_data)
return MimeDecoderWrite (leaf->decoder_data, buffer, size);
else
return ((MimeLeafClass *)obj->class)->parse_decoded_buffer (buffer, size,
obj);
}
static int
MimeLeaf_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
PR_ASSERT(0);
/* This method shouldn't ever be called. */
return -1;
}
static int
MimeLeaf_parse_eof (MimeObject *obj, PRBool abort_p)
{
MimeLeaf *leaf = (MimeLeaf *) obj;
if (obj->closed_p) return 0;
/* Close off the decoder, to cause it to give up any buffered data that
it is still holding.
*/
if (leaf->decoder_data)
{
int status = MimeDecoderDestroy(leaf->decoder_data, FALSE);
leaf->decoder_data = 0;
if (status < 0) return status;
}
/* Now run the superclass's parse_eof, which will force out the line
buffer (which we may have just repopulated, above.)
*/
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof (obj, abort_p);
}
static PRBool
MimeLeaf_displayable_inline_p (MimeObjectClass *class, MimeHeaders *hdrs)
{
return TRUE;
}

Просмотреть файл

@ -0,0 +1,63 @@
/* -*- 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.
*/
#ifndef _MIMELEAF_H_
#define _MIMELEAF_H_
#include "mimeobj.h"
#include "modmimee.h"
/* MimeLeaf is the class for the objects representing all MIME types which
are not containers for other MIME objects. The implication of this is
that they are MIME types which can have Content-Transfer-Encodings
applied to their data. This class provides that service in its
parse_buffer() method:
int (*parse_decoded_buffer) (char *buf, PRInt32 size, MimeObject *obj)
The `parse_buffer' method of MimeLeaf passes each block of data through
the appropriate decoder (if any) and then calls `parse_decoded_buffer'
on each block (not line) of output.
The default `parse_decoded_buffer' method of MimeLeaf line-buffers the
now-decoded data, handing each line to the `parse_line' method in turn.
If different behavior is desired (for example, if a class wants access
to the decoded data before it is line-buffered) the `parse_decoded_buffer'
method should be overridden. (MimeExternalObject does this.)
*/
typedef struct MimeLeafClass MimeLeafClass;
typedef struct MimeLeaf MimeLeaf;
struct MimeLeafClass {
MimeObjectClass object;
/* This is the callback that is handed to the decoder. */
int (*parse_decoded_buffer) (char *buf, PRInt32 size, MimeObject *obj);
};
extern MimeLeafClass mimeLeafClass;
struct MimeLeaf {
MimeObject object; /* superclass variables */
/* If we're doing Base64, Quoted-Printable, or UU decoding, this is the
state object for the decoder. */
MimeDecoderData *decoder_data;
};
#endif /* _MIMELEAF_H_ */

Просмотреть файл

@ -0,0 +1,325 @@
/* -*- 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.
*/
#include "mimemalt.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartAlternative, MimeMultipartAlternativeClass,
mimeMultipartAlternativeClass, &MIME_SUPERCLASS);
static int MimeMultipartAlternative_initialize (MimeObject *);
static void MimeMultipartAlternative_finalize (MimeObject *);
static int MimeMultipartAlternative_parse_eof (MimeObject *, PRBool);
static int MimeMultipartAlternative_create_child(MimeObject *);
static int MimeMultipartAlternative_parse_child_line (MimeObject *, char *,
PRInt32, PRBool);
static int MimeMultipartAlternative_close_child(MimeObject *);
static PRBool MimeMultipartAlternative_display_part_p(MimeObject *self,
MimeHeaders *sub_hdrs);
static int MimeMultipartAlternative_discard_cached_part(MimeObject *);
static int MimeMultipartAlternative_display_cached_part(MimeObject *);
static int
MimeMultipartAlternativeClassInitialize(MimeMultipartAlternativeClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeMultipartAlternative_initialize;
oclass->finalize = MimeMultipartAlternative_finalize;
oclass->parse_eof = MimeMultipartAlternative_parse_eof;
mclass->create_child = MimeMultipartAlternative_create_child;
mclass->parse_child_line = MimeMultipartAlternative_parse_child_line;
mclass->close_child = MimeMultipartAlternative_close_child;
return 0;
}
static int
MimeMultipartAlternative_initialize (MimeObject *obj)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
PR_ASSERT(!malt->part_buffer);
malt->part_buffer = MimePartBufferCreate();
if (!malt->part_buffer)
return MK_OUT_OF_MEMORY;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
}
static void
MimeMultipartAlternative_cleanup(MimeObject *obj)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
if (malt->buffered_hdrs)
{
MimeHeaders_free(malt->buffered_hdrs);
malt->buffered_hdrs = 0;
}
if (malt->part_buffer)
{
MimePartBufferDestroy(malt->part_buffer);
malt->part_buffer = 0;
}
}
static void
MimeMultipartAlternative_finalize (MimeObject *obj)
{
MimeMultipartAlternative_cleanup(obj);
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(obj);
}
static int
MimeMultipartAlternative_parse_eof (MimeObject *obj, PRBool abort_p)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
int status = 0;
if (obj->closed_p) return 0;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
/* If there's a cached part we haven't written out yet, do it now.
*/
if (malt->buffered_hdrs && !abort_p)
{
status = MimeMultipartAlternative_display_cached_part(obj);
if (status < 0) return status;
}
MimeMultipartAlternative_cleanup(obj);
return status;
}
static int
MimeMultipartAlternative_create_child(MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
if (MimeMultipartAlternative_display_part_p (obj, mult->hdrs))
{
/* If this part is potentially displayable, begin populating the cache
with it. If there's something in the cache already, discard it
first. (Just because this part is displayable doesn't mean we will
display it -- of two consecutive displayable parts, it is the second
one that gets displayed.)
*/
int status;
mult->state = MimeMultipartPartFirstLine;
status = MimeMultipartAlternative_discard_cached_part(obj);
if (status < 0) return status;
PR_ASSERT(!malt->buffered_hdrs);
malt->buffered_hdrs = MimeHeaders_copy(mult->hdrs);
if (!malt->buffered_hdrs) return MK_OUT_OF_MEMORY;
return 0;
}
else
{
/* If this part is not displayable, then we're done -- all that is left
to do is to flush out the part that is currently in the cache.
*/
mult->state = MimeMultipartEpilogue;
return MimeMultipartAlternative_display_cached_part(obj);
}
}
static int
MimeMultipartAlternative_parse_child_line (MimeObject *obj,
char *line, PRInt32 length,
PRBool first_line_p)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
PR_ASSERT(malt->part_buffer);
if (!malt->part_buffer) return -1;
/* Push this line into the buffer for later retrieval. */
return MimePartBufferWrite (malt->part_buffer, line, length);
}
static int
MimeMultipartAlternative_close_child(MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
/* PR_ASSERT(malt->part_buffer); Some Mac brokenness trips this...
if (!malt->part_buffer) return -1; */
if (malt->part_buffer)
MimePartBufferClose(malt->part_buffer);
/* PR_ASSERT(mult->hdrs); I expect the Mac trips this too */
if (mult->hdrs)
MimeHeaders_free(mult->hdrs);
mult->hdrs = 0;
return 0;
}
static PRBool
MimeMultipartAlternative_display_part_p(MimeObject *self,
MimeHeaders *sub_hdrs)
{
char *ct = MimeHeaders_get (sub_hdrs, HEADER_CONTENT_TYPE, TRUE, FALSE);
/* RFC 1521 says:
Receiving user agents should pick and display the last format
they are capable of displaying. In the case where one of the
alternatives is itself of type "multipart" and contains unrecognized
sub-parts, the user agent may choose either to show that alternative,
an earlier alternative, or both.
Ugh. If there is a multipart subtype of alternative, we simply show
that, without descending into it to determine if any of its sub-parts
are themselves unknown.
*/
MimeObjectClass *class = mime_find_class (ct, sub_hdrs, self->options, TRUE);
PRBool result = (class
? class->displayable_inline_p(class, sub_hdrs)
: FALSE);
FREEIF(ct);
return result;
}
static int
MimeMultipartAlternative_discard_cached_part(MimeObject *obj)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
if (malt->buffered_hdrs)
{
MimeHeaders_free(malt->buffered_hdrs);
malt->buffered_hdrs = 0;
}
if (malt->part_buffer)
MimePartBufferReset (malt->part_buffer);
return 0;
}
static int
MimeMultipartAlternative_display_cached_part(MimeObject *obj)
{
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
int status;
char *ct = (malt->buffered_hdrs
? MimeHeaders_get (malt->buffered_hdrs, HEADER_CONTENT_TYPE,
TRUE, FALSE)
: 0);
const char *dct = (((MimeMultipartClass *) obj->class)->default_part_type);
MimeObject *body;
PRBool multipart_p;
/* Don't pass in NULL as the content-type (this means that the
auto-uudecode-hack won't ever be done for subparts of a
multipart, but only for untyped children of message/rfc822.
*/
body = mime_create(((ct && *ct) ? ct : (dct ? dct: TEXT_PLAIN)),
malt->buffered_hdrs, obj->options);
FREEIF(ct);
if (!body) return MK_OUT_OF_MEMORY;
multipart_p = mime_typep(body, (MimeObjectClass *) &mimeMultipartClass);
status = ((MimeContainerClass *) obj->class)->add_child(obj, body);
if (status < 0)
{
mime_free(body);
return status;
}
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
!multipart_p &&
obj->options->decompose_file_init_fn )
{
status = obj->options->decompose_file_init_fn (
obj->options->stream_closure,
malt->buffered_hdrs);
if (status < 0) return status;
}
#endif /* MIME_DRAFTS */
/* Now that we've added this new object to our list of children,
start its parser going. */
status = body->class->parse_begin(body);
if (status < 0) return status;
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
!multipart_p &&
obj->options->decompose_file_output_fn )
status = MimePartBufferRead (malt->part_buffer,
obj->options->decompose_file_output_fn,
obj->options->stream_closure);
else
#endif /* MIME_DRAFTS */
status = MimePartBufferRead (malt->part_buffer,
/* The (int (*) ...) cast is to turn the
`void' argument into `MimeObject'. */
((int (*) (char *, PRInt32, void *))
body->class->parse_buffer),
body);
if (status < 0) return status;
MimeMultipartAlternative_cleanup(obj);
/* Done parsing. */
status = body->class->parse_eof(body, FALSE);
if (status < 0) return status;
status = body->class->parse_end(body, FALSE);
if (status < 0) return status;
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
!multipart_p &&
obj->options->decompose_file_close_fn ) {
status = obj->options->decompose_file_close_fn ( obj->options->stream_closure );
if (status < 0) return status;
}
#endif /* MIME_DRAFTS */
return 0;
}

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- 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.
*/
#ifndef _MIMEMALT_H_
#define _MIMEMALT_H_
#include "mimemult.h"
#include "mimepbuf.h"
/* The MimeMultipartAlternative class implements the multipart/alternative
MIME container, which displays only one (the `best') of a set of enclosed
documents.
*/
typedef struct MimeMultipartAlternativeClass MimeMultipartAlternativeClass;
typedef struct MimeMultipartAlternative MimeMultipartAlternative;
struct MimeMultipartAlternativeClass {
MimeMultipartClass multipart;
};
extern MimeMultipartAlternativeClass mimeMultipartAlternativeClass;
struct MimeMultipartAlternative {
MimeMultipart multipart; /* superclass variables */
MimeHeaders *buffered_hdrs; /* The headers of the currently-pending
part. */
MimePartBufferData *part_buffer; /* The data of the current-pending part
(see mimepbuf.h) */
};
#endif /* _MIMEMALT_H_ */

Просмотреть файл

@ -0,0 +1,204 @@
/* -*- 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.
*/
#include "mimemapl.h"
#include "xpgetstr.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartAppleDouble, MimeMultipartAppleDoubleClass,
mimeMultipartAppleDoubleClass, &MIME_SUPERCLASS);
extern int MK_MSG_ATTACHMENT;
static int MimeMultipartAppleDouble_parse_begin (MimeObject *);
static PRBool MimeMultipartAppleDouble_output_child_p(MimeObject *,
MimeObject *);
static int
MimeMultipartAppleDoubleClassInitialize(MimeMultipartAppleDoubleClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->parse_begin = MimeMultipartAppleDouble_parse_begin;
mclass->output_child_p = MimeMultipartAppleDouble_output_child_p;
return 0;
}
static int
MimeMultipartAppleDouble_parse_begin (MimeObject *obj)
{
/* #### This method is identical to MimeExternalObject_parse_begin
which kinda s#$%s...
*/
int status;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
/* If we're writing this object, and we're doing it in raw form, then
now is the time to inform the backend what the type of this data is.
*/
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p &&
!obj->options->state->first_data_written_p)
{
status = MimeObject_output_init(obj, 0);
if (status < 0) return status;
PR_ASSERT(obj->options->state->first_data_written_p);
}
#if !defined(XP_MAC) && !defined(MOZILLA_30)
if (obj->options && obj->options->state)
{
obj->options->state->separator_suppressed_p = TRUE;
goto done;
}
/*
* It would be nice to not showing the resource fork links
* if we are displaying inline. But, there is no way we could
* know ahead of time that we could display the data fork and
* the data fork is always hidden on MAC platform.
*/
#endif
/* If we're writing this object as HTML, then emit a link for the
multipart/appledouble part (both links) that looks just like the
links that MimeExternalObject emits for external leaf parts.
*/
if (obj->options &&
obj->output_p &&
obj->options->write_html_p &&
obj->options->output_fn)
{
MimeDisplayOptions newopt = *obj->options; /* copy it */
char *id = 0;
char *id_url = 0;
char *id_imap = 0;
PRBool all_headers_p = obj->options->headers == MimeHeadersAll;
id = mime_part_address (obj);
if (! id) return MK_OUT_OF_MEMORY;
if (obj->options->missing_parts)
id_imap = mime_imap_part_address (obj);
if (obj->options && obj->options->url)
{
const char *url = obj->options->url;
if (id_imap && id)
{
/* if this is an IMAP part. */
id_url = mime_set_url_imap_part(url, id_imap, id);
}
else
{
/* This is just a normal MIME part as usual. */
id_url = mime_set_url_part(url, id, TRUE);
}
if (!id_url)
{
PR_Free(id);
return MK_OUT_OF_MEMORY;
}
}
if (!PL_strcmp (id, "0"))
{
PR_Free(id);
id = PL_strdup(XP_GetString(MK_MSG_ATTACHMENT));
}
else
{
const char *p = "Part "; /* #### i18n */
char *s = (char *)PR_MALLOC(PL_strlen(p) + PL_strlen(id) + 1);
if (!s)
{
PR_Free(id);
PR_Free(id_url);
return MK_OUT_OF_MEMORY;
}
PL_strcpy(s, p);
PL_strcat(s, id);
PR_Free(id);
id = s;
}
if (all_headers_p &&
/* Don't bother showing all headers on this part if it's the only
part in the message: in that case, we've already shown these
headers. */
obj->options->state &&
obj->options->state->root == obj->parent)
all_headers_p = FALSE;
newopt.fancy_headers_p = TRUE;
newopt.headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome);
{
char p[] = "<P>";
status = MimeObject_write(obj, p, 3, FALSE);
if (status < 0) goto FAIL;
}
status = MimeHeaders_write_attachment_box (obj->headers, &newopt,
obj->content_type,
obj->encoding,
id, id_url, 0);
if (status < 0) goto FAIL;
/* No <P> after the first attachment-box in an AppleDouble, to keep
them closer together. */
FAIL:
FREEIF(id);
FREEIF(id_url);
if (status < 0) return status;
}
#if !defined(XP_MAC) && !defined(MOZILLA_30)
done:
#endif
return 0;
}
static PRBool
MimeMultipartAppleDouble_output_child_p(MimeObject *obj, MimeObject *child)
{
MimeContainer *cont = (MimeContainer *) obj;
/* If this is the first child, and it's an application/applefile, then
don't emit a link for it. (There *should* be only two children, and
the first one should always be an application/applefile.)
*/
if (obj->output_p &&
obj->options &&
obj->options->write_html_p &&
cont->nchildren >= 1 &&
cont->children[0] == child &&
child->content_type &&
!PL_strcasecmp(child->content_type, APPLICATION_APPLEFILE))
return FALSE;
else
return TRUE;
}

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- 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.
*/
#ifndef _MIMEMAPL_H_
#define _MIMEMAPL_H_
#include "mimemult.h"
/* The MimeMultipartAppleDouble class implements the multipart/appledouble
MIME container, which provides a method of encapsulating and reconstructing
a two-forked Macintosh file.
*/
typedef struct MimeMultipartAppleDoubleClass MimeMultipartAppleDoubleClass;
typedef struct MimeMultipartAppleDouble MimeMultipartAppleDouble;
struct MimeMultipartAppleDoubleClass {
MimeMultipartClass multipart;
};
extern MimeMultipartAppleDoubleClass mimeMultipartAppleDoubleClass;
struct MimeMultipartAppleDouble {
MimeMultipart multipart;
};
#endif /* _MIMEMAPL_H_ */

Просмотреть файл

@ -0,0 +1,33 @@
/* -*- 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.
*/
#include "mimemdig.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartDigest, MimeMultipartDigestClass,
mimeMultipartDigestClass, &MIME_SUPERCLASS);
static int
MimeMultipartDigestClassInitialize(MimeMultipartDigestClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
mclass->default_part_type = MESSAGE_RFC822;
return 0;
}

Просмотреть файл

@ -0,0 +1,43 @@
/* -*- 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.
*/
#ifndef _MIMEMDIG_H_
#define _MIMEMDIG_H_
#include "mimemult.h"
/* The MimeMultipartDigest class implements the multipart/digest MIME
container, which is just like multipart/mixed, except that the default
type (for parts with no type explicitly specified) is message/rfc822
instead of text/plain.
*/
typedef struct MimeMultipartDigestClass MimeMultipartDigestClass;
typedef struct MimeMultipartDigest MimeMultipartDigest;
struct MimeMultipartDigestClass {
MimeMultipartClass multipart;
};
extern MimeMultipartDigestClass mimeMultipartDigestClass;
struct MimeMultipartDigest {
MimeMultipart multipart;
};
#endif /* _MIMEMDIG_H_ */

Просмотреть файл

@ -0,0 +1,31 @@
/* -*- 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.
*/
#include "mimemmix.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartMixed, MimeMultipartMixedClass,
mimeMultipartMixedClass, &MIME_SUPERCLASS);
static int
MimeMultipartMixedClassInitialize(MimeMultipartMixedClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
return 0;
}

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- 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.
*/
#ifndef _MIMEMMIX_H_
#define _MIMEMMIX_H_
#include "mimemult.h"
/* The MimeMultipartMixed class implements the multipart/mixed MIME container,
and is also used for any and all otherwise-unrecognised subparts of
multipart/.
*/
typedef struct MimeMultipartMixedClass MimeMultipartMixedClass;
typedef struct MimeMultipartMixed MimeMultipartMixed;
struct MimeMultipartMixedClass {
MimeMultipartClass multipart;
};
extern MimeMultipartMixedClass mimeMultipartMixedClass;
struct MimeMultipartMixed {
MimeMultipart multipart;
};
#endif /* _MIMEMMIX_H_ */

2755
mailnews/mime/src/mimemoz.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

108
mailnews/mime/src/mimemoz.h Normal file
Просмотреть файл

@ -0,0 +1,108 @@
/* -*- 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.
*/
#ifndef _MIMEMOZ_H_
#define _MIMEMOZ_H_
#include "xp.h"
#include "prtypes.h"
/* Mozilla-specific interfaces
*/
/* Given a URL, this might return a better suggested name to save it as.
When you have a URL, you can sometimes get a suggested name from
URL_s->content_name, but if you're saving a URL to disk before the
URL_Struct has been filled in by netlib, you don't have that yet.
So if you're about to prompt for a file name *before* you call FE_GetURL
with a format_out of FO_SAVE_AS, call this function first to see if it
can offer you advice about what the suggested name for that URL should be.
(This works by looking in a cache of recently-displayed MIME objects, and
seeing if this URL matches. If it does, the remembered content-name will
be used.)
*/
extern char *MimeGuessURLContentName(MWContext *context, const char *url);
/* Given a URL, return the content type for the mime part, if the passed context
recently parsed a message containing the part specified by the URL.
This is used to figure out if we need to open the url in a browser window,
or if we're just going to do a save as, anyay.
*/
extern char *MimeGetURLContentType(MWContext *context, const char *url);
/* Determines whether the given context is currently showing a text/html
message. (Used by libmsg to determine if replys should bring up the
text/html editor. */
extern PRBool MimeShowingTextHtml(MWContext* context);
/* Yeech, hack... Determine the URL to use to save just the HTML part of the
currently-displayed message to disk. If the current message doesn't have
a text/html part, returns NULL. Otherwise, the caller must free the
returned string using PR_Free(). */
extern char* MimeGetHtmlPartURL(MWContext* context);
/* Return how many attachments are in the currently-displayed message. */
extern int MimeGetAttachmentCount(MWContext* context);
/* Returns what attachments are being viewed in the currently-displayed
message. The returned data must be free'd using
MimeFreeAttachmentList(). */
extern int MimeGetAttachmentList(MWContext* context,
MSG_AttachmentData** data);
extern void MimeFreeAttachmentList(MSG_AttachmentData* data);
/* Call this when destroying a context; this frees up some memory.
*/
extern void MimeDestroyContextData(MWContext *context);
#ifdef MOZ_SECURITY
HG10034
#endif
/* Used only by libnet, this indicates that the user bonked on the "show me
details about attachments" button. */
extern int MIME_DisplayAttachmentPane(MWContext* context);
/* Used by libmsg, libmime, libi18n to strip out line continuations of a
message header. It does *NOT* allocate new buffer. It returns the
origial. */
extern char * MIME_StripContinuations(char *original);
/*
* This is currently the primary interface for stream converters
*/
NET_StreamClass *
MIME_MessageConverter (int format_out, void *closure,
URL_Struct *url, MWContext *context);
#endif /* _MIMEMOZ_H_ */

Просмотреть файл

@ -0,0 +1,31 @@
/* -*- 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.
*/
#include "mimempar.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartParallel, MimeMultipartParallelClass,
mimeMultipartParallelClass, &MIME_SUPERCLASS);
static int
MimeMultipartParallelClassInitialize(MimeMultipartParallelClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
return 0;
}

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- 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.
*/
#ifndef _MIMEMPAR_H_
#define _MIMEMPAR_H_
#include "mimemult.h"
/* The MimeMultipartParallel class implements the multipart/parallel MIME
container, which is currently no different from multipart/mixed, since
it's not clear that there's anything useful it could do differently.
*/
typedef struct MimeMultipartParallelClass MimeMultipartParallelClass;
typedef struct MimeMultipartParallel MimeMultipartParallel;
struct MimeMultipartParallelClass {
MimeMultipartClass multipart;
};
extern MimeMultipartParallelClass mimeMultipartParallelClass;
struct MimeMultipartParallel {
MimeMultipart multipart;
};
#endif /* _MIMEMPAR_H_ */

Просмотреть файл

@ -0,0 +1,935 @@
/* -*- 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.
*/
/* Thoughts on how to implement this:
= if the type of this multipart/related is not text/html, then treat
it the same as multipart/mixed.
= For each part in this multipart/related
= if this part is not the "top" part
= then save this part to a tmp file or a memory object,
kind-of like what we do for multipart/alternative sub-parts.
If this is an object we're blocked on (see below) send its data along.
= else
= emit this part (remember, it's of type text/html)
= at some point, layout may load a URL for <IMG SRC="cid:xxxx">.
we intercept that.
= if one of our cached parts has that cid, return the data for it.
= else, "block", the same way the image library blocks layout when it
doesn't yet have the size of the image.
= at some point, layout may load a URL for <IMG SRC="relative/yyy">.
we need to intercept that too.
= expand the URL, and compare it to our cached objects.
if it matches, return it.
= else block on it.
= once we get to the end, if we have any sub-part references that we're
still blocked on, map over them:
= if they're cid: references, close them ("broken image" results.)
= if they're URLs, then load them in the normal way.
--------------------------------------------------
Ok, that's fairly complicated. How about an approach where we go through
all the parts first, and don't emit until the end?
= if the type of this multipart/related is not text/html, then treat
it the same as multipart/mixed.
= For each part in this multipart/related
= save this part to a tmp file or a memory object,
like what we do for multipart/alternative sub-parts.
= Emit the "top" part (the text/html one)
= intercept all calls to NET_GetURL, to allow us to rewrite the URL.
(hook into netlib, or only into imglib's calls to GetURL?)
(make sure we're behaving in a context-local way.)
= when a URL is loaded, look through our cached parts for a match.
= if we find one, map that URL to a "cid:" URL
= else, let it load normally
= at some point, layout may load a URL for <IMG SRC="cid:xxxx">.
it will do this either because that's what was in the HTML, or because
that's how we "rewrote" the URLs when we intercepted NET_GetURL.
= if one of our cached parts has the requested cid, return the data
for it.
= else, generate a "broken image"
= free all the cached data
--------------------------------------------------
How hard would be an approach where we rewrite the HTML?
(Looks like it's not much easier, and might be more error-prone.)
= if the type of this multipart/related is not text/html, then treat
it the same as multipart/mixed.
= For each part in this multipart/related
= save this part to a tmp file or a memory object,
like what we do for multipart/alternative sub-parts.
= Parse the "top" part, and emit slightly different HTML:
= for each <IMG SRC>, <IMG LOWSRC>, <A HREF>? Any others?
= look through our cached parts for a matching URL
= if we find one, map that URL to a "cid:" URL
= else, let it load normally
= at some point, layout may load a URL for <IMG SRC="cid:xxxx">.
= if one of our cached parts has the requested cid, return the data
for it.
= else, generate a "broken image"
= free all the cached data
*/
#include "mimemrel.h"
#include "prmem.h"
#include "plstr.h"
extern int MK_UNABLE_TO_OPEN_TMP_FILE;
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartRelated, MimeMultipartRelatedClass,
mimeMultipartRelatedClass, &MIME_SUPERCLASS);
/* Stupid utility function. Really ought to be part of the standard string
package if you ask me...*/
static char* mime_strnchr(char* str, char c, int length)
{
int i;
for (i=0 ; i<length ; i++) {
if (*str == c) return str;
str++;
}
return NULL;
}
static int
MimeMultipartRelated_initialize(MimeObject* obj)
{
MimeMultipartRelated* relobj = (MimeMultipartRelated*) obj;
relobj->base_url = MimeHeaders_get(obj->headers, "Content-Base",
FALSE, FALSE);
/* rhp: need this for supporting Content-Location */
if (!relobj->base_url)
{
relobj->base_url = MimeHeaders_get(obj->headers, "Content-Location",
FALSE, FALSE);
}
/* rhp: need this for supporting Content-Location */
/* I used to have code here to test if the type was text/html. Then I
added multipart/alternative as being OK, too. Then I found that the
VCard spec seems to talk about having the first part of a
multipart/related be an application/directory. At that point, I decided
to punt. We handle anything as the first part, and stomp on the HTML it
generates to adjust tags to point into the other parts. This probably
works out to something reasonable in most cases. */
relobj->hash = XP_HashTableNew(20, XP_StringHash,
(XP_HashCompFunction) strcmp);
if (!relobj->hash) return MK_OUT_OF_MEMORY;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
}
PRBool mime_multipart_related_nukehash(XP_HashTable table, const void* key,
void* value, void* closure)
{
PR_Free((char*) key);
PR_Free((char*) value);
return TRUE;
}
static void
MimeMultipartRelated_finalize (MimeObject *obj)
{
MimeMultipartRelated* relobj = (MimeMultipartRelated*) obj;
FREEIF(relobj->base_url);
FREEIF(relobj->curtag);
if (relobj->hash) {
XP_MapRemhash(relobj->hash, mime_multipart_related_nukehash, NULL);
XP_HashTableDestroy(relobj->hash);
relobj->hash = NULL;
}
if (relobj->file_stream) {
PR_Close(relobj->file_stream);
relobj->file_stream = NULL;
}
if (relobj->file_buffer_name) {
PR_Delete(relobj->file_buffer_name);
PR_Free(relobj->file_buffer_name);
relobj->file_buffer_name = 0;
}
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(obj);
}
char * escape_unescaped_percents(const char *incomingURL);
/* This routine is only necessary because the mailbox URL fed to us
by the winfe can contain spaces and '>'s in it. It's a hack. */
static char *
escape_for_mrel_subst(char *inURL)
{
char *output, *inC, *outC, *temp;
/* PL_strlen asserts the presence of a string in inURL */
int size = PL_strlen(inURL) + 1;
for(inC = inURL; *inC; inC++)
if ((*inC == ' ') || (*inC == '>'))
size += 2; /* space -> '%20', '>' -> '%3E', etc. */
output = PR_MALLOC(size);
if (output)
{
/* Walk through the source string, copying all chars
except for spaces, which get escaped. */
inC = inURL;
outC = output;
while(*inC)
{
if (*inC == ' ')
{
*outC++ = '%'; *outC++ = '2'; *outC++ = '0';
}
else if (*inC == '>')
{
*outC++ = '%'; *outC++ = '3'; *outC++ = 'E';
}
else
*outC++ = *inC;
inC++;
}
*outC = '\0';
temp = escape_unescaped_percents(output);
if (temp)
{
FREEIF(output);
output = temp;
}
}
return output;
}
/* rhp - need to support start parameter */
#define HEADER_PARM_START "start" /* this goes in modlmodmime.h */
static PRBool
MimeStartParamExists(MimeObject *obj, MimeObject* child)
{
char *ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
char *st = (ct
? MimeHeaders_get_parameter(ct, HEADER_PARM_START, NULL, NULL)
: 0);
if (!st)
return FALSE;
FREEIF(st);
FREEIF(ct);
return TRUE;
}
static PRBool
MimeThisIsStartPart(MimeObject *obj, MimeObject* child)
{
PRBool rval = FALSE;
char *ct, *st, *cst;
ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
st = (ct
? MimeHeaders_get_parameter(ct, HEADER_PARM_START, NULL, NULL)
: 0);
if (!st)
return FALSE;
cst = MimeHeaders_get(child->headers, "Content-ID", FALSE, FALSE);
if (!cst)
rval = FALSE;
else
{
char *tmp = cst;
if (*tmp == '<')
{
int length;
tmp++;
length = PL_strlen(tmp);
if (length > 0 && tmp[length - 1] == '>')
{
tmp[length - 1] = '\0';
}
}
rval = (!PL_strcmp(st, tmp));
}
FREEIF(st);
FREEIF(ct);
FREEIF(cst);
return rval;
}
/* rhp - gotta support the "start" parameter */
static PRBool
MimeMultipartRelated_output_child_p(MimeObject *obj, MimeObject* child)
{
MimeMultipartRelated *relobj = (MimeMultipartRelated *) obj;
/* rhp - Changed from "if (relobj->head_loaded)" alone to support the
start parameter
*/
if (
(relobj->head_loaded) ||
(MimeStartParamExists(obj, child) && !MimeThisIsStartPart(obj, child))
)
{
/* This is a child part. Just remember the mapping between the URL
it represents and the part-URL to get it back. */
char* location = MimeHeaders_get(child->headers, "Content-Location",
FALSE, FALSE);
if (!location) {
char* tmp = MimeHeaders_get(child->headers, "Content-ID",
FALSE, FALSE);
if (tmp) {
char* tmp2 = tmp;
if (*tmp2 == '<') {
int length;
tmp2++;
length = PL_strlen(tmp2);
if (length > 0 && tmp2[length - 1] == '>') {
tmp2[length - 1] = '\0';
}
}
location = PR_smprintf("cid:%s", tmp2);
PR_Free(tmp);
}
}
if (location) {
char *absolute;
char *base_url = MimeHeaders_get(child->headers, "Content-Base",
FALSE, FALSE);
/* rhp: need this for supporting Content-Location */
if (!base_url)
{
base_url = MimeHeaders_get(child->headers, "Content-Location", FALSE, FALSE);
}
/* rhp: need this for supporting Content-Location */
absolute = NET_MakeAbsoluteURL(base_url ? base_url : relobj->base_url, location);
FREEIF(base_url);
PR_Free(location);
if (absolute) {
char* partnum = mime_part_address(child);
if (partnum) {
char* part;
part = mime_set_url_part(obj->options->url, partnum,
FALSE);
if (part) {
/* If there's a space in the url, escape the url.
(This happens primarily on Windows and Unix.) */
char *temp = part;
if (PL_strchr(part, ' ') || PL_strchr(part, '>') || PL_strchr(part, '%'))
temp = escape_for_mrel_subst(part);
XP_Puthash(relobj->hash, absolute, temp);
/* rhp - If this part ALSO has a Content-ID we need to put that into
the hash table and this is what this code does
*/
{
char *tloc;
char *tmp = MimeHeaders_get(child->headers, "Content-ID", FALSE, FALSE);
if (tmp)
{
char* tmp2 = tmp;
if (*tmp2 == '<')
{
int length;
tmp2++;
length = PL_strlen(tmp2);
if (length > 0 && tmp2[length - 1] == '>')
{
tmp2[length - 1] = '\0';
}
}
tloc = PR_smprintf("cid:%s", tmp2);
PR_Free(tmp);
if (tloc)
{
XP_Puthash(relobj->hash, tloc, PL_strdup(temp));
}
}
}
/* rhp - End of putting more stuff into the hash table */
/* The value string that is added to the hashtable will be deleted
by the hashtable at destruction time. So if we created an
escaped string for the hashtable, we have to delete the
part URL that was given to us. */
if (temp != part) PR_Free(part);
}
PR_Free(partnum);
}
}
}
} else {
/* Ah-hah! We're the head object. */
char* base_url;
relobj->head_loaded = TRUE;
relobj->headobj = child;
relobj->buffered_hdrs = MimeHeaders_copy(child->headers);
base_url = MimeHeaders_get(child->headers, "Content-Base",
FALSE, FALSE);
/* rhp: need this for supporting Content-Location */
if (!base_url)
{
base_url = MimeHeaders_get(child->headers, "Content-Location", FALSE, FALSE);
}
/* rhp: need this for supporting Content-Location */
if (base_url) {
/* If the head object has a base_url associated with it, use
that instead of any base_url that may have been associated
with the multipart/related. */
FREEIF(relobj->base_url);
relobj->base_url = base_url;
}
}
if (obj->options && !obj->options->write_html_p
#ifdef MIME_DRAFTS
&& !obj->options->decompose_file_p
#endif /* MIME_DRAFTS */
)
{
return TRUE;
}
return FALSE; /* Don't actually parse this child; we'll handle
all that at eof time. */
}
static int
MimeMultipartRelated_parse_child_line (MimeObject *obj,
char *line, PRInt32 length,
PRBool first_line_p)
{
MimeContainer *cont = (MimeContainer *) obj;
MimeMultipartRelated *relobj = (MimeMultipartRelated *) obj;
int status;
MimeObject *kid;
if (obj->options && !obj->options->write_html_p
#ifdef MIME_DRAFTS
&& !obj->options->decompose_file_p
#endif /* MIME_DRAFTS */
)
{
/* Oh, just go do the normal thing... */
return ((MimeMultipartClass*)&MIME_SUPERCLASS)->
parse_child_line(obj, line, length, first_line_p);
}
/* Throw it away if this isn't the head object. (Someday, maybe we'll
cache it instead.) */
PR_ASSERT(cont->nchildren > 0);
if (cont->nchildren <= 0)
return -1;
kid = cont->children[cont->nchildren-1];
PR_ASSERT(kid);
if (!kid) return -1;
if (kid != relobj->headobj) return 0;
/* Buffer this up (###tw much code duplication from mimemalt.c) */
/* If we don't yet have a buffer (either memory or file) try and make a
memory buffer. */
if (!relobj->head_buffer && !relobj->file_buffer_name) {
int target_size = 1024 * 50; /* try for 50k */
while (target_size > 0) {
relobj->head_buffer = (char *) PR_MALLOC(target_size);
if (relobj->head_buffer) break; /* got it! */
target_size -= (1024 * 5); /* decrease it and try again */
}
if (relobj->head_buffer) {
relobj->head_buffer_size = target_size;
} else {
relobj->head_buffer_size = 0;
}
relobj->head_buffer_fp = 0;
}
/* Ok, if at this point we still don't have either kind of buffer, try and
make a file buffer. */
if (!relobj->head_buffer && !relobj->file_buffer_name) {
relobj->file_buffer_name = WH_TempName(xpTemporary, "nsma");
if (!relobj->file_buffer_name) return MK_OUT_OF_MEMORY;
relobj->file_stream = PR_Open(relobj->file_buffer_name,
PR_RDWR | PR_CREATE_FILE,
0);
if (!relobj->file_stream) {
return MK_UNABLE_TO_OPEN_TMP_FILE;
}
}
PR_ASSERT(relobj->head_buffer || relobj->file_stream);
/* If this line will fit in the memory buffer, put it there.
*/
if (relobj->head_buffer &&
relobj->head_buffer_fp + length < relobj->head_buffer_size) {
XP_MEMCPY(relobj->head_buffer + relobj->head_buffer_fp, line, length);
relobj->head_buffer_fp += length;
} else {
/* Otherwise it won't fit; write it to the file instead. */
/* If the file isn't open yet, open it, and dump the memory buffer
to it. */
if (!relobj->file_stream) {
if (!relobj->file_buffer_name) {
relobj->file_buffer_name = WH_TempName (xpTemporary, "nsma");
}
if (!relobj->file_buffer_name) return MK_OUT_OF_MEMORY;
relobj->file_stream = PR_Open(relobj->file_buffer_name,
PR_RDWR | PR_CREATE_FILE,
0);
if (!relobj->file_stream) {
return MK_UNABLE_TO_OPEN_TMP_FILE;
}
if (relobj->head_buffer && relobj->head_buffer_fp) {
status = PR_Write (relobj->file_stream,
relobj->head_buffer,
relobj->head_buffer_fp);
if (status < 0) return status;
}
FREEIF(relobj->head_buffer);
relobj->head_buffer_fp = 0;
relobj->head_buffer_size = 0;
}
/* Dump this line to the file. */
status = PR_Write (relobj->file_stream, line, length);
if (status < 0) return status;
}
return 0;
}
static int
real_write(MimeMultipartRelated* relobj, char* buf, PRInt32 size)
{
MimeObject* obj = (MimeObject*) relobj;
void* closure = relobj->real_output_closure;
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->decompose_file_output_fn )
{
return obj->options->decompose_file_output_fn
(buf, size, obj->options->stream_closure);
}
else
#endif /* MIME_DRAFTS */
{
if (!closure) {
MimeObject* obj = (MimeObject*) relobj;
closure = obj->options->stream_closure;
}
return relobj->real_output_fn(buf, size, closure);
}
}
static int
push_tag(MimeMultipartRelated* relobj, const char* buf, PRInt32 size)
{
if (size + relobj->curtag_length > relobj->curtag_max) {
relobj->curtag_max += 2 * size;
if (relobj->curtag_max < 1024) relobj->curtag_max = 1024;
if (!relobj->curtag) {
relobj->curtag = (char*) PR_MALLOC(relobj->curtag_max);
} else {
relobj->curtag = (char*) PR_Realloc(relobj->curtag,
relobj->curtag_max);
}
if (!relobj->curtag) return MK_OUT_OF_MEMORY;
}
XP_MEMCPY(relobj->curtag + relobj->curtag_length, buf, size);
relobj->curtag_length += size;
return 0;
}
static int
flush_tag(MimeMultipartRelated* relobj)
{
int length = relobj->curtag_length;
char* buf;
int status;
if (relobj->curtag == NULL || length == 0) return 0;
status = push_tag(relobj, "", 1); /* Push on a trailing NULL. */
if (status < 0) return status;
buf = relobj->curtag;
PR_ASSERT(*buf == '<' && buf[length - 1] == '>');
while (*buf) {
char c;
char* absolute;
char* part_url;
char* ptr = buf;
char *ptr2;
PRBool isquote = FALSE;
while (*ptr && *ptr != '=') ptr++;
if (*ptr == '=') {
ptr++;
if (*ptr == '"') {
isquote = TRUE;
/* Take up the double quote and leading space here as well. */
/* Safe because there's a '>' at the end */
do {ptr++;} while (XP_IS_SPACE(*ptr));
}
}
status = real_write(relobj, buf, ptr - buf);
if (status < 0) return status;
buf = ptr;
if (!*buf) break;
if (isquote)
{
ptr = mime_strnchr(buf, '"', length - (buf - relobj->curtag));
} else {
for (ptr = buf; *ptr ; ptr++) {
if (*ptr == '>' || XP_IS_SPACE(*ptr)) break;
}
PR_ASSERT(*ptr);
}
if (!ptr || !*ptr) break;
while(buf < ptr)
{
/* ### mwelch For each word in the value string, see if
the word is a cid: URL. If so, attempt to
substitute the appropriate mailbox part URL in
its place. */
ptr2=buf; /* walk from the left end rightward */
while((ptr2<ptr) && (!XP_IS_SPACE(*ptr2)))
ptr2++;
/* Compare the beginning of the word with "cid:". Yuck. */
if (((ptr2 - buf) > 4) &&
(buf[0]=='c' && buf[1]=='i' && buf[2]=='d' && buf[3]==':'))
{
/* Null terminate the word so we can... */
c = *ptr2;
*ptr2 = '\0';
/* Construct a URL out of the word. */
absolute = NET_MakeAbsoluteURL(relobj->base_url, buf);
/* See if we have a mailbox part URL
corresponding to this cid. */
part_url = absolute ? XP_Gethash(relobj->hash, buf, NULL)
: NULL;
FREEIF(absolute);
/*If we found a mailbox part URL, write that out instead.*/
if (part_url)
{
status = real_write(relobj, part_url, PL_strlen(part_url));
if (status < 0) return status;
buf = ptr2; /* skip over the cid: URL we substituted */
}
/* Restore the character that we nulled. */
*ptr2 = c;
}
/* rhp - if we get here, we should still check against the hash table! */
else
{
char holder = *ptr2;
char *realout;
*ptr2 = '\0';
/* Construct a URL out of the word. */
absolute = NET_MakeAbsoluteURL(relobj->base_url, buf);
/* See if we have a mailbox part URL
corresponding to this cid. */
if (absolute)
realout = XP_Gethash(relobj->hash, absolute, NULL);
else
realout = XP_Gethash(relobj->hash, buf, NULL);
*ptr2 = holder;
FREEIF(absolute);
if (realout)
{
status = real_write(relobj, realout, PL_strlen(realout));
if (status < 0) return status;
buf = ptr2; /* skip over the cid: URL we substituted */
}
}
/* rhp - if we get here, we should still check against the hash table! */
/* Advance to the beginning of the next word, or to
the end of the value string. */
while((ptr2<ptr) && (XP_IS_SPACE(*ptr2)))
ptr2++;
/* Write whatever original text remains after
cid: URL substitution. */
status = real_write(relobj, buf, ptr2-buf);
if (status < 0) return status;
buf = ptr2;
}
}
if (buf && *buf) {
status = real_write(relobj, buf, PL_strlen(buf));
if (status < 0) return status;
}
relobj->curtag_length = 0;
return 0;
}
static int
mime_multipart_related_output_fn(char* buf, PRInt32 size, void *stream_closure)
{
MimeMultipartRelated *relobj = (MimeMultipartRelated *) stream_closure;
char* ptr;
PRInt32 delta;
int status;
while (size > 0) {
if (relobj->curtag_length > 0) {
ptr = mime_strnchr(buf, '>', size);
if (!ptr) {
return push_tag(relobj, buf, size);
}
delta = ptr - buf + 1;
status = push_tag(relobj, buf, delta);
if (status < 0) return status;
status = flush_tag(relobj);
if (status < 0) return status;
buf += delta;
size -= delta;
}
ptr = mime_strnchr(buf, '<', size);
if (ptr && ptr - buf >= size) ptr = 0;
if (!ptr) {
return real_write(relobj, buf, size);
}
delta = ptr - buf;
status = real_write(relobj, buf, delta);
if (status < 0) return status;
buf += delta;
size -= delta;
PR_ASSERT(relobj->curtag_length == 0);
status = push_tag(relobj, buf, 1);
if (status < 0) return status;
PR_ASSERT(relobj->curtag_length == 1);
buf++;
size--;
}
return 0;
}
static int
MimeMultipartRelated_parse_eof (MimeObject *obj, PRBool abort_p)
{
/* OK, all the necessary data has been collected. We now have to spew out
the HTML. We let it go through all the normal mechanisms (which
includes content-encoding handling), and intercept the output data to do
translation of the tags. Whee. */
MimeMultipartRelated *relobj = (MimeMultipartRelated *) obj;
int status = 0;
MimeObject *body;
char* ct;
const char* dct;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) goto FAIL;
if (!relobj->headobj) return 0;
ct = (relobj->buffered_hdrs
? MimeHeaders_get (relobj->buffered_hdrs, HEADER_CONTENT_TYPE,
TRUE, FALSE)
: 0);
dct = (((MimeMultipartClass *) obj->class)->default_part_type);
relobj->real_output_fn = obj->options->output_fn;
relobj->real_output_closure = obj->options->output_closure;
obj->options->output_fn = mime_multipart_related_output_fn;
obj->options->output_closure = obj;
body = mime_create(((ct && *ct) ? ct : (dct ? dct : TEXT_HTML)),
relobj->buffered_hdrs, obj->options);
if (!body) {
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
status = ((MimeContainerClass *) obj->class)->add_child(obj, body);
if (status < 0) {
mime_free(body);
goto FAIL;
}
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->decompose_file_init_fn &&
(relobj->file_buffer_name || relobj->head_buffer))
{
status = obj->options->decompose_file_init_fn ( obj->options->stream_closure,
relobj->buffered_hdrs );
if (status < 0) return status;
}
#endif /* MIME_DRAFTS */
/* Now that we've added this new object to our list of children,
start its parser going. */
status = body->class->parse_begin(body);
if (status < 0) goto FAIL;
if (relobj->head_buffer) {
/* Read it out of memory. */
PR_ASSERT(!relobj->file_buffer_name && !relobj->file_stream);
status = body->class->parse_buffer(relobj->head_buffer,
relobj->head_buffer_fp,
body);
} else if (relobj->file_buffer_name) {
/* Read it off disk.
*/
char *buf;
PRInt32 buf_size = 10 * 1024; /* 10k; tune this? */
PR_ASSERT(relobj->head_buffer_size == 0 &&
relobj->head_buffer_fp == 0);
PR_ASSERT(relobj->file_buffer_name);
if (!relobj->file_buffer_name) {
status = -1;
goto FAIL;
}
buf = (char *) PR_MALLOC(buf_size);
if (!buf) {
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
if (relobj->file_stream) {
PR_Close(relobj->file_stream);
}
relobj->file_stream = PR_Open(relobj->file_buffer_name,
PR_RDONLY, 0);
if (!relobj->file_stream) {
PR_Free(buf);
status = MK_UNABLE_TO_OPEN_TMP_FILE;
goto FAIL;
}
while(1) {
PRInt32 rstatus = PR_Read(relobj->file_stream,
buf, buf_size - 1);
if (rstatus <= 0) {
status = rstatus;
break;
} else {
/* It would be really nice to be able to yield here, and let
some user events and other input sources get processed.
Oh well. */
status = body->class->parse_buffer(buf, rstatus, body);
if (status < 0) break;
}
}
PR_Free(buf);
}
if (status < 0) goto FAIL;
/* Done parsing. */
status = body->class->parse_eof(body, FALSE);
if (status < 0) goto FAIL;
status = body->class->parse_end(body, FALSE);
if (status < 0) goto FAIL;
FAIL:
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->decompose_file_close_fn &&
(relobj->file_buffer_name || relobj->head_buffer)) {
status = obj->options->decompose_file_close_fn ( obj->options->stream_closure );
if (status < 0) return status;
}
#endif /* MIME_DRAFTS */
relobj->headobj = NULL;
obj->options->output_fn = relobj->real_output_fn;
obj->options->output_closure = relobj->real_output_closure;
return status;
}
static int
MimeMultipartRelatedClassInitialize(MimeMultipartRelatedClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeMultipartRelated_initialize;
oclass->finalize = MimeMultipartRelated_finalize;
oclass->parse_eof = MimeMultipartRelated_parse_eof;
mclass->output_child_p = MimeMultipartRelated_output_child_p;
mclass->parse_child_line = MimeMultipartRelated_parse_child_line;
return 0;
}

Просмотреть файл

@ -0,0 +1,73 @@
/* -*- 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.
*/
#ifndef _MIMEMREL_H_
#define _MIMEMREL_H_
#include "mimemult.h"
#include "xp_hash.h"
/* The MimeMultipartRelated class implements the multipart/related MIME
container, which allows `sibling' sub-parts to refer to each other.
*/
typedef struct MimeMultipartRelatedClass MimeMultipartRelatedClass;
typedef struct MimeMultipartRelated MimeMultipartRelated;
struct MimeMultipartRelatedClass {
MimeMultipartClass multipart;
};
extern MimeMultipartRelatedClass mimeMultipartRelatedClass;
struct MimeMultipartRelated {
MimeMultipart multipart; /* superclass variables */
char* base_url; /* Base URL (if any) for the whole
multipart/related. */
char* head_buffer; /* Buffer used to remember the text/html 'head'
part. */
PRInt32 head_buffer_fp; /* Active length. */
PRInt32 head_buffer_size; /* How big it is. */
char *file_buffer_name; /* The name of a temp file used when we
run out of room in the head_buffer. */
PRFileDesc *file_stream; /* A stream to it. */
MimeHeaders* buffered_hdrs; /* The headers of the 'head' part. */
PRBool head_loaded; /* Whether we've already passed the 'head'
part. */
MimeObject* headobj; /* The actual text/html head object. */
XP_HashTable hash; /* Conversion between URLs and part URLs. */
int (*real_output_fn) (char *buf, PRInt32 size, void *stream_closure);
void* real_output_closure;
char* curtag;
PRInt32 curtag_max;
PRInt32 curtag_length;
};
#endif /* _MIMEMREL_H_ */

606
mailnews/mime/src/mimemsg.c Normal file
Просмотреть файл

@ -0,0 +1,606 @@
/* -*- 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.
*/
#include "mimerosetta.h"
#include "mimemsg.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeContainerClass
MimeDefClass(MimeMessage, MimeMessageClass, mimeMessageClass,
&MIME_SUPERCLASS);
static int MimeMessage_initialize (MimeObject *);
static void MimeMessage_finalize (MimeObject *);
static int MimeMessage_add_child (MimeObject *, MimeObject *);
static int MimeMessage_parse_begin (MimeObject *);
static int MimeMessage_parse_line (char *, PRInt32, MimeObject *);
static int MimeMessage_parse_eof (MimeObject *, PRBool);
static int MimeMessage_close_headers (MimeObject *obj);
static int MimeMessage_write_headers_html (MimeObject *);
#ifdef MOZ_SECURITY
HG56268
#endif /* MOZ_SECURITY */
#ifdef XP_UNIX
extern void MimeHeaders_do_unix_display_hook_hack(MimeHeaders *);
#endif /* XP_UNIX */
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeMessage_debug_print (MimeObject *, FILE *, PRInt32 depth);
#endif
extern MimeObjectClass mimeMultipartClass;
static int
MimeMessageClassInitialize(MimeMessageClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeContainerClass *cclass = (MimeContainerClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeMessage_initialize;
oclass->finalize = MimeMessage_finalize;
oclass->parse_begin = MimeMessage_parse_begin;
oclass->parse_line = MimeMessage_parse_line;
oclass->parse_eof = MimeMessage_parse_eof;
cclass->add_child = MimeMessage_add_child;
#if defined(DEBUG) && defined(XP_UNIX)
oclass->debug_print = MimeMessage_debug_print;
#endif
return 0;
}
static int
MimeMessage_initialize (MimeObject *object)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeMessage_finalize (MimeObject *object)
{
MimeMessage *msg = (MimeMessage *)object;
if (msg->hdrs)
MimeHeaders_free(msg->hdrs);
msg->hdrs = 0;
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeMessage_parse_begin (MimeObject *obj)
{
int status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
/* Messages have separators before the headers, except for the outermost
message. */
return MimeObject_write_separator(obj);
}
static int
MimeMessage_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
MimeMessage *msg = (MimeMessage *) obj;
int status = 0;
PR_ASSERT(line && *line);
if (!line || !*line) return -1;
#ifdef MOZ_SECURITY
HG11013
#endif /* MOZ_SECURITY */
/* If we already have a child object, then we're done parsing headers,
and all subsequent lines get passed to the inferior object without
further processing by us. (Our parent will stop feeding us lines
when this MimeMessage part is out of data.)
*/
if (msg->container.nchildren)
{
MimeObject *kid = msg->container.children[0];
PRBool nl;
PR_ASSERT(kid);
if (!kid) return -1;
/* Don't allow MimeMessage objects to not end in a newline, since it
would be inappropriate for any following part to appear on the same
line as the last line of the message.
#### This assumes that the only time the `parse_line' method is
called with a line that doesn't end in a newline is when that line
is the last line.
*/
nl = (length > 0 && (line[length-1] == CR || line[length-1] == LF));
#ifdef MIME_DRAFTS
if ( !mime_typep (kid, (MimeObjectClass*) &mimeMessageClass) &&
obj->options &&
obj->options->decompose_file_p &&
! obj->options->is_multipart_msg &&
obj->options->decompose_file_output_fn )
{
if (!obj->options->dexlate_p) {
status = obj->options->decompose_file_output_fn (line,
length,
obj->options->stream_closure);
if (status < 0) return status;
if (!nl) {
status = obj->options->decompose_file_output_fn (LINEBREAK,
LINEBREAK_LEN,
obj->options->stream_closure);
if (status < 0) return status;
}
return status;
}
}
#endif /* MIME_DRAFTS */
if (nl)
return kid->class->parse_buffer (line, length, kid);
else
{
/* Hack a newline onto the end. */
char *s = PR_MALLOC(length + LINEBREAK_LEN + 1);
if (!s) return MK_OUT_OF_MEMORY;
XP_MEMCPY(s, line, length);
PL_strcpy(s + length, LINEBREAK);
status = kid->class->parse_buffer (s, length + LINEBREAK_LEN, kid);
PR_Free(s);
return status;
}
}
/* Otherwise we don't yet have a child object, which means we're not
done parsing our headers yet.
*/
if (!msg->hdrs)
{
msg->hdrs = MimeHeaders_new();
if (!msg->hdrs) return MK_OUT_OF_MEMORY;
}
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
! obj->options->is_multipart_msg &&
obj->options->done_parsing_outer_headers &&
obj->options->decompose_file_output_fn ) {
status = obj->options->decompose_file_output_fn ( line,
length,
obj->options->stream_closure );
if (status < 0) return status;
}
#endif /* MIME_DRAFTS */
status = MimeHeaders_parse_line(line, length, msg->hdrs);
if (status < 0) return status;
/* If this line is blank, we're now done parsing headers, and should
examine our content-type to create our "body" part.
*/
if (*line == CR || *line == LF)
{
status = MimeMessage_close_headers(obj);
if (status < 0) return status;
}
return 0;
}
static int
MimeMessage_close_headers (MimeObject *obj)
{
MimeMessage *msg = (MimeMessage *) obj;
int status = 0;
char *ct = 0; /* Content-Type header */
MimeObject *body;
if (msg->hdrs)
{
PRBool outer_p = !obj->headers; /* is this the outermost message? */
#ifdef MIME_DRAFTS
if (outer_p &&
obj->options &&
obj->options->decompose_file_p &&
obj->options->decompose_headers_info_fn)
{
#ifdef MOZ_SECURITY
HG09091
#endif /* MOZ_SECURITY */
status = obj->options->decompose_headers_info_fn (
obj->options->stream_closure,
msg->hdrs );
}
#endif /* MIME_DRAFTS */
/* If this is the outermost message, we need to run the
`generate_header' callback. This happens here instead of
in `parse_begin', because it's only now that we've parsed
our headers. However, since this is the outermost message,
we have yet to write any HTML, so that's fine.
*/
if (outer_p &&
obj->output_p &&
obj->options &&
obj->options->write_html_p &&
obj->options->generate_header_html_fn)
{
int status = 0;
char *html = 0;
/* The generate_header_html_fn might return HTML, so it's important
that the output stream be set up with the proper type before we
make the MimeObject_write() call below. */
if (!obj->options->state->first_data_written_p)
{
status = MimeObject_output_init (obj, TEXT_HTML);
if (status < 0) return status;
PR_ASSERT(obj->options->state->first_data_written_p);
}
html = obj->options->generate_header_html_fn(NULL,
obj->options->html_closure,
msg->hdrs);
if (html)
{
status = MimeObject_write(obj, html, PL_strlen(html), FALSE);
PR_Free(html);
if (status < 0) return status;
}
}
/* Find the content-type of the body of this message.
*/
{
PRBool ok = TRUE;
char *mv = MimeHeaders_get (msg->hdrs, HEADER_MIME_VERSION,
TRUE, FALSE);
#ifdef REQUIRE_MIME_VERSION_HEADER
/* If this is the outermost message, it must have a MIME-Version
header with the value 1.0 for us to believe what might be in
the Content-Type header. If the MIME-Version header is not
present, we must treat this message as untyped.
*/
ok = (mv && !PL_strcmp(mv, "1.0"));
#else
/* #### actually, we didn't check this in Mozilla 2.0, and checking
it now could cause some compatibility nonsense, so for now, let's
just believe any Content-Type header we see.
*/
ok = TRUE;
#endif
if (ok)
{
ct = MimeHeaders_get (msg->hdrs, HEADER_CONTENT_TYPE, TRUE, FALSE);
/* If there is no Content-Type header, but there is a MIME-Version
header, then assume that this *is* in fact a MIME message.
(I've seen messages with
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
and no Content-Type, and we should treat those as being of type
MimeInlineTextPlain rather than MimeUntypedText.)
*/
if (mv && !ct)
ct = PL_strdup(TEXT_PLAIN);
}
FREEIF(mv); /* done with this now. */
}
#ifdef MOZ_SECURITY
HG67023
#endif /* MOZ_SECURITY */
/* Emit the HTML for this message's headers. Do this before
creating the object representing the body.
*/
if (obj->output_p &&
obj->options &&
obj->options->write_html_p)
{
/* If citation headers are on, and this is not the outermost message,
turn them off. */
if (obj->options->headers == MimeHeadersCitation && !outer_p)
obj->options->headers = MimeHeadersSome;
/* Emit a normal header block. */
status = MimeMessage_write_headers_html(obj);
if (status < 0) return status;
}
else if (obj->output_p)
{
/* Dump the headers, raw. */
status = MimeObject_write(obj, "", 0, FALSE); /* initialize */
if (status < 0) return status;
status = MimeHeaders_write_raw_headers(msg->hdrs, obj->options,
obj->options->dexlate_p);
if (status < 0) return status;
}
#ifdef XP_UNIX
if (outer_p && obj->output_p)
/* Kludge from mimehdrs.c */
MimeHeaders_do_unix_display_hook_hack(msg->hdrs);
#endif /* XP_UNIX */
}
/* Never put out a separator after a message header block. */
if (obj->options && obj->options->state)
obj->options->state->separator_suppressed_p = TRUE;
#ifdef MIME_DRAFTS
if ( !obj->headers && /* outer most message header */
obj->options &&
obj->options->decompose_file_p &&
ct )
obj->options->is_multipart_msg = PL_strstr(ct, "multipart/") != NULL;
#endif /* MIME_DRAFTS */
body = mime_create(ct, msg->hdrs, obj->options);
FREEIF(ct);
if (!body) return MK_OUT_OF_MEMORY;
status = ((MimeContainerClass *) obj->class)->add_child (obj, body);
if (status < 0)
{
mime_free(body);
return status;
}
/* Now that we've added this new object to our list of children,
start its parser going. */
status = body->class->parse_begin(body);
if (status < 0) return status;
return 0;
}
static int
MimeMessage_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status;
PRBool outer_p;
MimeMessage *msg = (MimeMessage *)obj;
if (obj->closed_p) return 0;
/* Run parent method first, to flush out any buffered data. */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
outer_p = !obj->headers; /* is this the outermost message? */
if (outer_p &&
obj->options &&
obj->options->write_html_p &&
obj->options->generate_footer_html_fn)
{
char *html =
obj->options->generate_footer_html_fn (NULL,
obj->options->html_closure,
msg->hdrs);
if (html)
{
int status = MimeObject_write(obj, html, PL_strlen(html), FALSE);
PR_Free(html);
if (status < 0) return status;
}
}
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->done_parsing_outer_headers &&
! obj->options->is_multipart_msg &&
#ifdef MOZ_SECURITY
HG00234
#endif /* MOZ_SECURITY */
obj->options->decompose_file_close_fn ) {
status = obj->options->decompose_file_close_fn (
obj->options->stream_closure );
if ( status < 0 ) return status;
}
#endif /* MIME_DRAFTS */
/* Put out a separator after every message/rfc822 object. */
if (!abort_p)
{
status = MimeObject_write_separator(obj);
if (status < 0) return status;
}
return 0;
}
static int
MimeMessage_add_child (MimeObject *parent, MimeObject *child)
{
MimeContainer *cont = (MimeContainer *) parent;
PR_ASSERT(parent && child);
if (!parent || !child) return -1;
/* message/rfc822 containers can only have one child. */
PR_ASSERT(cont->nchildren == 0);
if (cont->nchildren != 0) return -1;
#ifdef MIME_DRAFTS
if ( parent->options &&
parent->options->decompose_file_p &&
! parent->options->is_multipart_msg &&
#ifdef MOZ_SECURITY
HG00234
#endif /* MOZ_SECURITY */
parent->options->decompose_file_init_fn ) {
int status = 0;
status = parent->options->decompose_file_init_fn (
parent->options->stream_closure,
((MimeMessage*)parent)->hdrs );
if ( status < 0 ) return status;
}
#endif /* MIME_DRAFTS */
return ((MimeContainerClass*)&MIME_SUPERCLASS)->add_child (parent, child);
}
static int
MimeMessage_write_headers_html (MimeObject *obj)
{
MimeMessage *msg = (MimeMessage *) obj;
#ifdef MOZ_SECURITY
HG33391
#endif /* MOZ_SECURITY */
int status;
if (!obj->options ||
!obj->options->output_fn)
return 0;
PR_ASSERT(obj->output_p && obj->options->write_html_p);
if (!obj->options->state->first_data_written_p)
{
status = MimeObject_output_init (obj, TEXT_HTML);
if (status < 0) return status;
PR_ASSERT(obj->options->state->first_data_written_p);
}
#ifdef MOZ_SECURITY
HG00919
#endif /* MOZ_SECURITY */
status = MimeHeaders_write_headers_html (msg->hdrs, obj->options);
if (status < 0) return status;
if (msg->xlation_stamped_p)
{
#ifdef MOZ_SECURITY
HG11995
#endif /* MOZ_SECURITY */
}
else
{
/* If we're not writing a xlation stamp, and this is the outermost
message, then now is the time to run the post_header_html_fn.
(Otherwise, it will be run when the xlation-stamp is finally
closed off, in MimeXlateed_emit_buffered_child() or
MimeMultipartSigned_emit_child().)
*/
if (obj->options &&
obj->options->state &&
obj->options->generate_post_header_html_fn &&
!obj->options->state->post_header_html_run_p)
{
char *html = 0;
PR_ASSERT(obj->options->state->first_data_written_p);
html = obj->options->generate_post_header_html_fn(NULL,
obj->options->html_closure,
msg->hdrs);
obj->options->state->post_header_html_run_p = TRUE;
if (html)
{
status = MimeObject_write(obj, html, PL_strlen(html), FALSE);
PR_Free(html);
if (status < 0) return status;
}
}
/* Write out a paragraph break between the headers and body. */
{
char s[] = "<P>";
status = MimeObject_write(obj, s, PL_strlen(s), FALSE);
if (status < 0) return status;
}
}
return 0;
}
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeMessage_debug_print (MimeObject *obj, FILE *stream, PRInt32 depth)
{
MimeMessage *msg = (MimeMessage *) obj;
char *addr = mime_part_address(obj);
int i;
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream, "<%s %s%s 0x%08X>\n",
obj->class->class_name,
addr ? addr : "???",
(msg->container.nchildren == 0 ? " (no body)" : ""),
(PRUint32) msg);
FREEIF(addr);
#if 0
if (msg->hdrs)
{
char *s;
depth++;
# define DUMP(HEADER) \
for (i=0; i < depth; i++) \
fprintf(stream, " "); \
s = MimeHeaders_get (msg->hdrs, HEADER, FALSE, TRUE); \
fprintf(stream, HEADER ": %s\n", s ? s : ""); \
FREEIF(s)
DUMP(HEADER_SUBJECT);
DUMP(HEADER_DATE);
DUMP(HEADER_FROM);
DUMP(HEADER_TO);
/* DUMP(HEADER_CC); */
DUMP(HEADER_NEWSGROUPS);
DUMP(HEADER_MESSAGE_ID);
# undef DUMP
fprintf(stream, "\n");
}
#endif
PR_ASSERT(msg->container.nchildren <= 1);
if (msg->container.nchildren == 1)
{
MimeObject *kid = msg->container.children[0];
int status = kid->class->debug_print (kid, stream, depth+1);
if (status < 0) return status;
}
return 0;
}
#endif

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- 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.
*/
#ifndef _MIMEMSG_H_
#define _MIMEMSG_H_
#include "mimecont.h"
/* The MimeMessage class implements the message/rfc822 and message/news
MIME containers, which is to say, mail and news messages.
*/
typedef struct MimeMessageClass MimeMessageClass;
typedef struct MimeMessage MimeMessage;
struct MimeMessageClass {
MimeContainerClass container;
};
extern MimeMessageClass mimeMessageClass;
struct MimeMessage {
MimeContainer container; /* superclass variables */
MimeHeaders *hdrs; /* headers of this message */
PRBool newline_p; /* whether the last line ended in a newline */
PRBool xlation_stamped_p; /* whether the header of this message has been
emitted expecting its child to emit HTML
which says that it is xlated. */
PRBool xlation_msg_signed_p; /* What the emitted xlation-stamp *says*. */
PRBool xlation_msg_xlated_p;
};
#endif /* _MIMEMSG_H_ */

Просмотреть файл

@ -0,0 +1,707 @@
/* -*- 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.
*/
#include "mimerosetta.h"
#include "modmimee.h"
#include "mimemsig.h"
#include "nspr.h"
#include "prmem.h"
#include "plstr.h"
#include "prerror.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeMultipartSigned, MimeMultipartSignedClass,
mimeMultipartSignedClass, &MIME_SUPERCLASS);
static int MimeMultipartSigned_initialize (MimeObject *);
static int MimeMultipartSigned_create_child (MimeObject *);
static int MimeMultipartSigned_close_child(MimeObject *);
static int MimeMultipartSigned_parse_line (char *, PRInt32, MimeObject *);
static int MimeMultipartSigned_parse_child_line (MimeObject *, char *, PRInt32,
PRBool);
static int MimeMultipartSigned_parse_eof (MimeObject *, PRBool);
static void MimeMultipartSigned_finalize (MimeObject *);
static int MimeMultipartSigned_emit_child (MimeObject *obj);
static int
MimeMultipartSignedClassInitialize(MimeMultipartSignedClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
oclass->initialize = MimeMultipartSigned_initialize;
oclass->parse_line = MimeMultipartSigned_parse_line;
oclass->parse_eof = MimeMultipartSigned_parse_eof;
oclass->finalize = MimeMultipartSigned_finalize;
mclass->create_child = MimeMultipartSigned_create_child;
mclass->parse_child_line = MimeMultipartSigned_parse_child_line;
mclass->close_child = MimeMultipartSigned_close_child;
PR_ASSERT(!oclass->class_initialized);
return 0;
}
static int
MimeMultipartSigned_initialize (MimeObject *object)
{
MimeMultipartSigned *sig = (MimeMultipartSigned *) object;
/* This is an abstract class; it shouldn't be directly instantiated. */
PR_ASSERT(object->class != (MimeObjectClass *) &mimeMultipartSignedClass);
sig->state = MimeMultipartSignedPreamble;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeMultipartSigned_cleanup (MimeObject *obj, PRBool finalizing_p)
{
MimeMultipart *mult = (MimeMultipart *) obj; /* #58075. Fix suggested by jwz */
MimeMultipartSigned *sig = (MimeMultipartSigned *) obj;
if (sig->part_buffer)
{
MimePartBufferDestroy(sig->part_buffer);
sig->part_buffer = 0;
}
if (sig->body_hdrs)
{
MimeHeaders_free (sig->body_hdrs);
sig->body_hdrs = 0;
}
if (sig->sig_hdrs)
{
MimeHeaders_free (sig->sig_hdrs);
sig->sig_hdrs = 0;
}
mult->state = MimeMultipartEpilogue; /* #58075. Fix suggested by jwz */
sig->state = MimeMultipartSignedEpilogue;
#ifdef MOZ_SECURITY
HG09003
#endif /* MOZ_SECURITY */
if (sig->sig_decoder_data)
{
MimeDecoderDestroy(sig->sig_decoder_data, TRUE);
sig->sig_decoder_data = 0;
}
}
static int
MimeMultipartSigned_parse_eof (MimeObject *obj, PRBool abort_p)
{
MimeMultipartSigned *sig = (MimeMultipartSigned *) obj;
int status = 0;
if (obj->closed_p) return 0;
/* Close off the signature, if we've gotten that far.
*/
if (sig->state == MimeMultipartSignedSignatureHeaders ||
sig->state == MimeMultipartSignedSignatureFirstLine ||
sig->state == MimeMultipartSignedSignatureLine ||
sig->state == MimeMultipartSignedEpilogue)
{
#ifdef MOZ_SECURITY
HG77782
#endif /* MOZ_SECURITY */
}
if (!abort_p)
{
/* Now that we've read both the signed object and the signature (and
have presumably verified the signature) write out a blurb, and then
the signed object.
*/
status = MimeMultipartSigned_emit_child(obj);
if (status < 0) return status;
}
MimeMultipartSigned_cleanup(obj, FALSE);
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
}
static void
MimeMultipartSigned_finalize (MimeObject *obj)
{
MimeMultipartSigned_cleanup(obj, TRUE);
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(obj);
}
static int
MimeMultipartSigned_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
MimeMultipartSigned *sig = (MimeMultipartSigned *) obj;
MimeMultipartParseState old_state = mult->state;
PRBool hash_line_p = TRUE;
PRBool no_headers_p = FALSE;
int status = 0;
/* First do the parsing for normal multipart/ objects by handing it off to
the superclass method. This includes calling the create_child and
close_child methods.
*/
status = (((MimeObjectClass *)(&MIME_SUPERCLASS))
->parse_line (line, length, obj));
if (status < 0) return status;
/* The instance variable MimeMultipartClass->state tracks motion through
the various stages of multipart/ parsing. The instance variable
MimeMultipartSigned->state tracks the difference between the first
part (the body) and the second part (the signature.) This second,
more specific state variable is updated by noticing the transitions
of the first, more general state variable.
*/
if (old_state != mult->state) /* there has been a state change */
{
switch (mult->state)
{
case MimeMultipartPreamble:
PR_ASSERT(0); /* can't move *in* to preamble state. */
sig->state = MimeMultipartSignedPreamble;
break;
case MimeMultipartHeaders:
/* If we're moving in to the Headers state, then that means
that this line is the preceeding boundary string (and we
should ignore it.)
*/
hash_line_p = FALSE;
if (sig->state == MimeMultipartSignedPreamble)
sig->state = MimeMultipartSignedBodyFirstHeader;
else if (sig->state == MimeMultipartSignedBodyFirstLine ||
sig->state == MimeMultipartSignedBodyLine)
sig->state = MimeMultipartSignedSignatureHeaders;
else if (sig->state == MimeMultipartSignedSignatureFirstLine ||
sig->state == MimeMultipartSignedSignatureLine)
sig->state = MimeMultipartSignedEpilogue;
break;
case MimeMultipartPartFirstLine:
if (sig->state == MimeMultipartSignedBodyFirstHeader)
{
sig->state = MimeMultipartSignedBodyFirstLine;
no_headers_p = TRUE;
}
else if (sig->state == MimeMultipartSignedBodyHeaders)
sig->state = MimeMultipartSignedBodyFirstLine;
else if (sig->state == MimeMultipartSignedSignatureHeaders)
sig->state = MimeMultipartSignedSignatureFirstLine;
else
sig->state = MimeMultipartSignedEpilogue;
break;
case MimeMultipartPartLine:
PR_ASSERT(sig->state == MimeMultipartSignedBodyFirstLine ||
sig->state == MimeMultipartSignedBodyLine ||
sig->state == MimeMultipartSignedSignatureFirstLine ||
sig->state == MimeMultipartSignedSignatureLine);
if (sig->state == MimeMultipartSignedBodyFirstLine)
sig->state = MimeMultipartSignedBodyLine;
else if (sig->state == MimeMultipartSignedSignatureFirstLine)
sig->state = MimeMultipartSignedSignatureLine;
break;
case MimeMultipartEpilogue:
sig->state = MimeMultipartSignedEpilogue;
break;
default: /* bad state */
PR_ASSERT(0);
return -1;
break;
}
}
/* Perform multipart/signed-related actions on this line based on the state
of the parser.
*/
switch (sig->state)
{
case MimeMultipartSignedPreamble:
/* Do nothing. */
break;
case MimeMultipartSignedBodyFirstLine:
/* We have just moved out of the MimeMultipartSignedBodyHeaders
state, so cache away the headers that apply only to the body part.
*/
PR_ASSERT(mult->hdrs);
PR_ASSERT(!sig->body_hdrs);
sig->body_hdrs = mult->hdrs;
mult->hdrs = 0;
/* fall through. */
case MimeMultipartSignedBodyFirstHeader:
case MimeMultipartSignedBodyHeaders:
case MimeMultipartSignedBodyLine:
if (!sig->xlation_closure)
{
/* RICHIE - Set error change */
PR_SetError(0, 0);
/* Initialize the signature verification library. */
sig->xlation_closure = (((MimeMultipartSignedClass *) obj->class)
->xlation_init) (obj);
if (!sig->xlation_closure)
{
status = PR_GetError();
PR_ASSERT(status < 0);
if (status >= 0) status = -1;
return status;
}
}
if (hash_line_p)
{
/* this is the first hashed line if this is the first header
(that is, if it's the first line in the header state after
a state change.)
*/
PRBool first_line_p
= (no_headers_p ||
sig->state == MimeMultipartSignedBodyFirstHeader);
if (sig->state == MimeMultipartSignedBodyFirstHeader)
sig->state = MimeMultipartSignedBodyHeaders;
/* The newline issues here are tricky, since both the newlines
before and after the boundary string are to be considered part
of the boundary: this is so that a part can be specified such
that it does not end in a trailing newline.
To implement this, we send a newline *before* each line instead
of after, except for the first line, which is not preceeded by a
newline.
For purposes of xlationgraphic hashing, we always hash line
breaks as CRLF -- the canonical, on-the-wire linebreaks, since
we have no idea of knowing what line breaks were used on the
originating system (SMTP rightly destroys that information.)
*/
/* Remove the trailing newline... */
if (length > 0 && line[length-1] == LF) length--;
if (length > 0 && line[length-1] == CR) length--;
PR_ASSERT(sig->xlation_closure);
if (!first_line_p)
{
/* Push out a preceeding newline... */
char nl[] = CRLF;
status = (((MimeMultipartSignedClass *) obj->class)
->xlation_data_hash (nl, 2, sig->xlation_closure));
if (status < 0) return status;
}
/* Now push out the line sans trailing newline. */
if (length > 0)
status = (((MimeMultipartSignedClass *) obj->class)
->xlation_data_hash (line,length, sig->xlation_closure));
if (status < 0) return status;
}
break;
case MimeMultipartSignedSignatureHeaders:
if (sig->xlation_closure &&
old_state != mult->state)
{
/* We have just moved out of the MimeMultipartSignedBodyLine
state, so tell the signature verification library that we've
reached the end of the signed data.
*/
status = (((MimeMultipartSignedClass *) obj->class)
->xlation_data_eof) (sig->xlation_closure, FALSE);
if (status < 0) return status;
}
break;
case MimeMultipartSignedSignatureFirstLine:
/* We have just moved out of the MimeMultipartSignedSignatureHeaders
state, so cache away the headers that apply only to the sig part.
*/
PR_ASSERT(mult->hdrs);
PR_ASSERT(!sig->sig_hdrs);
sig->sig_hdrs = mult->hdrs;
mult->hdrs = 0;
/* If the signature block has an encoding, set up a decoder for it.
(Similar logic is in MimeLeafClass->parse_begin.)
*/
{
MimeDecoderData *(*fn) (int (*) (const char*, PRInt32,void*), void*) = 0;
char *encoding = MimeHeaders_get (sig->sig_hdrs,
HEADER_CONTENT_TRANSFER_ENCODING,
TRUE, FALSE);
if (!encoding)
;
else if (!PL_strcasecmp(encoding, ENCODING_BASE64))
fn = &MimeB64DecoderInit;
else if (!PL_strcasecmp(encoding, ENCODING_QUOTED_PRINTABLE))
fn = &MimeQPDecoderInit;
else if (!PL_strcasecmp(encoding, ENCODING_UUENCODE) ||
!PL_strcasecmp(encoding, ENCODING_UUENCODE2) ||
!PL_strcasecmp(encoding, ENCODING_UUENCODE3) ||
!PL_strcasecmp(encoding, ENCODING_UUENCODE4))
fn = &MimeUUDecoderInit;
if (fn)
{
sig->sig_decoder_data =
fn (((int (*) (const char *, PRInt32, void *))
(((MimeMultipartSignedClass *) obj->class)
->xlation_signature_hash)),
sig->xlation_closure);
if (!sig->sig_decoder_data)
return MK_OUT_OF_MEMORY;
}
}
/* Show these headers to the xlation module. */
if (hash_line_p)
{
status = (((MimeMultipartSignedClass *) obj->class)
->xlation_signature_init) (sig->xlation_closure,
obj, sig->sig_hdrs);
if (status < 0) return status;
}
/* fall through. */
case MimeMultipartSignedSignatureLine:
if (hash_line_p)
{
/* Feed this line into the signature verification routines. */
if (sig->sig_decoder_data)
status = MimeDecoderWrite (sig->sig_decoder_data, line, length);
else
status = (((MimeMultipartSignedClass *) obj->class)
->xlation_signature_hash (line, length,
sig->xlation_closure));
if (status < 0) return status;
}
break;
case MimeMultipartSignedEpilogue:
/* Nothing special to do here. */
break;
default: /* bad state */
PR_ASSERT(0);
return -1;
}
return status;
}
static int
MimeMultipartSigned_create_child (MimeObject *parent)
{
/* Don't actually create a child -- we call the superclass create_child
method later, after we've fully parsed everything. (And we only call
it once, for part #1, and never for part #2 (the signature.))
*/
MimeMultipart *mult = (MimeMultipart *) parent;
mult->state = MimeMultipartPartFirstLine;
return 0;
}
static int
MimeMultipartSigned_close_child (MimeObject *obj)
{
/* The close_child method on MimeMultipartSigned doesn't actually do
anything to the children list, since the create_child method also
doesn't do anything.
*/
MimeMultipart *mult = (MimeMultipart *) obj;
MimeContainer *cont = (MimeContainer *) obj;
MimeMultipartSigned *msig = (MimeMultipartSigned *) obj;
if (msig->part_buffer)
/* Closes the tmp file, if there is one: doesn't free the part_buffer. */
MimePartBufferClose(msig->part_buffer);
if (mult->hdrs) /* duplicated from MimeMultipart_close_child, ugh. */
{
MimeHeaders_free(mult->hdrs);
mult->hdrs = 0;
}
/* Should be no kids yet. */
PR_ASSERT(cont->nchildren == 0);
if (cont->nchildren != 0) return -1;
return 0;
}
static int
MimeMultipartSigned_parse_child_line (MimeObject *obj,
char *line, PRInt32 length,
PRBool first_line_p)
{
MimeMultipartSigned *sig = (MimeMultipartSigned *) obj;
MimeContainer *cont = (MimeContainer *) obj;
int status = 0;
/* Shouldn't have made any sub-parts yet. */
PR_ASSERT(cont->nchildren == 0);
if (cont->nchildren != 0) return -1;
switch (sig->state)
{
case MimeMultipartSignedPreamble:
case MimeMultipartSignedBodyFirstHeader:
case MimeMultipartSignedBodyHeaders:
PR_ASSERT(0); /* How'd we get here? Oh well, fall through. */
case MimeMultipartSignedBodyFirstLine:
PR_ASSERT(first_line_p);
if (!sig->part_buffer)
{
sig->part_buffer = MimePartBufferCreate();
if (!sig->part_buffer)
return MK_OUT_OF_MEMORY;
}
/* fall through */
case MimeMultipartSignedBodyLine:
{
/* This is the first part; we are buffering it, and will emit it all
at the end (so that we know whether the signature matches before
showing anything to the user.)
*/
/* The newline issues here are tricky, since both the newlines
before and after the boundary string are to be considered part
of the boundary: this is so that a part can be specified such
that it does not end in a trailing newline.
To implement this, we send a newline *before* each line instead
of after, except for the first line, which is not preceeded by a
newline.
*/
/* Remove the trailing newline... */
if (length > 0 && line[length-1] == LF) length--;
if (length > 0 && line[length-1] == CR) length--;
PR_ASSERT(sig->part_buffer);
PR_ASSERT(first_line_p ==
(sig->state == MimeMultipartSignedBodyFirstLine));
if (!first_line_p)
{
/* Push out a preceeding newline... */
char nl[] = LINEBREAK;
status = MimePartBufferWrite (sig->part_buffer, nl, LINEBREAK_LEN);
if (status < 0) return status;
}
/* Now push out the line sans trailing newline. */
if (length > 0)
status = MimePartBufferWrite (sig->part_buffer, line, length);
if (status < 0) return status;
}
break;
case MimeMultipartSignedSignatureHeaders:
PR_ASSERT(0); /* How'd we get here? Oh well, fall through. */
case MimeMultipartSignedSignatureFirstLine:
case MimeMultipartSignedSignatureLine:
/* Nothing to do here -- hashing of the signature part is handled up
in MimeMultipartSigned_parse_line().
*/
break;
case MimeMultipartSignedEpilogue:
/* Too many kids? MimeMultipartSigned_create_child() should have
prevented us from getting here. */
PR_ASSERT(0);
return -1;
break;
default: /* bad state */
PR_ASSERT(0);
return -1;
break;
}
return status;
}
static int
MimeMultipartSigned_emit_child (MimeObject *obj)
{
MimeMultipartSigned *sig = (MimeMultipartSigned *) obj;
MimeMultipart *mult = (MimeMultipart *) obj;
MimeContainer *cont = (MimeContainer *) obj;
int status = 0;
MimeObject *body;
PR_ASSERT(sig->xlation_closure);
/* Emit some HTML saying whether the signature was cool.
But don't emit anything if in FO_QUOTE_MESSAGE mode.
*/
if (obj->options &&
obj->options->headers != MimeHeadersCitation &&
obj->options->write_html_p &&
obj->options->output_fn &&
obj->options->headers != MimeHeadersCitation &&
sig->xlation_closure)
{
char *html = (((MimeMultipartSignedClass *) obj->class)
->xlation_generate_html (sig->xlation_closure));
if (!html) return -1; /* MK_OUT_OF_MEMORY? */
status = MimeObject_write(obj, html, PL_strlen(html), FALSE);
PR_Free(html);
if (status < 0) return status;
/* Now that we have written out the xlation stamp, the outermost header
block is well and truly closed. If this is in fact the outermost
message, then run the post_header_html_fn now.
*/
if (obj->options &&
obj->options->state &&
obj->options->generate_post_header_html_fn &&
!obj->options->state->post_header_html_run_p)
{
MimeHeaders *outer_headers;
MimeObject *p;
for (p = obj; p->parent; p = p->parent)
outer_headers = p->headers;
PR_ASSERT(obj->options->state->first_data_written_p);
html = obj->options->generate_post_header_html_fn(NULL,
obj->options->html_closure,
outer_headers);
obj->options->state->post_header_html_run_p = TRUE;
if (html)
{
status = MimeObject_write(obj, html, PL_strlen(html), FALSE);
PR_Free(html);
if (status < 0) return status;
}
}
}
/* Oh, this is fairly nasty. We're skipping over our "create child" method
and using the one our superclass defines. Perhaps instead we should add
a new method on this class, and initialize that method to be the
create_child method of the superclass. Whatever.
*/
/* The superclass method expects to find the headers for the part that it's
to create in mult->hdrs, so ensure that they're there. */
PR_ASSERT(!mult->hdrs);
if (mult->hdrs) MimeHeaders_free(mult->hdrs);
mult->hdrs = sig->body_hdrs;
sig->body_hdrs = 0;
/* Run the superclass create_child method.
*/
status = (((MimeMultipartClass *)(&MIME_SUPERCLASS))->create_child(obj));
if (status < 0) return status;
/* Retrieve the child that it created.
*/
PR_ASSERT(cont->nchildren == 1);
if (cont->nchildren != 1) return -1;
body = cont->children[0];
PR_ASSERT(body);
if (!body) return -1;
#ifdef MIME_DRAFTS
if (body->options->decompose_file_p) {
body->options->signed_p = TRUE;
if (!mime_typep(body, (MimeObjectClass*)&mimeMultipartClass) &&
body->options->decompose_file_init_fn)
body->options->decompose_file_init_fn ( body->options->stream_closure, body->headers );
}
#endif /* MIME_DRAFTS */
/* If there's no part_buffer, this is a zero-length signed message? */
if (sig->part_buffer)
{
#ifdef MIME_DRAFTS
if (body->options->decompose_file_p &&
!mime_typep(body, (MimeObjectClass*)&mimeMultipartClass) &&
body->options->decompose_file_output_fn)
status = MimePartBufferRead (sig->part_buffer,
/* The (int (*) ...) cast is to turn the
`void' argument into `MimeObject'. */
((int (*) (char *, PRInt32, void *))
body->options->decompose_file_output_fn),
body->options->stream_closure);
else
#endif /* MIME_DRAFTS */
status = MimePartBufferRead (sig->part_buffer,
/* The (int (*) ...) cast is to turn the
`void' argument into `MimeObject'. */
((int (*) (char *, PRInt32, void *))
body->class->parse_buffer),
body);
if (status < 0) return status;
}
MimeMultipartSigned_cleanup(obj, FALSE);
/* Done parsing. */
status = body->class->parse_eof(body, FALSE);
if (status < 0) return status;
status = body->class->parse_end(body, FALSE);
if (status < 0) return status;
#ifdef MIME_DRAFTS
if (body->options->decompose_file_p &&
!mime_typep(body, (MimeObjectClass*)&mimeMultipartClass) &&
body->options->decompose_file_close_fn)
body->options->decompose_file_close_fn(body->options->stream_closure);
#endif /* MIME_DRAFTS */
/* Put out a separator after every multipart/signed object. */
status = MimeObject_write_separator(obj);
if (status < 0) return status;
return 0;
}

Просмотреть файл

@ -0,0 +1,144 @@
/* -*- 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.
*/
#ifndef _MIMEMSIG_H_
#define _MIMEMSIG_H_
#include "mimemult.h"
#include "mimepbuf.h"
#include "modmimee.h"
/* The MimeMultipartSigned class implements the multipart/signed MIME
container, which provides a general method of associating a xlationgraphic
signature to an arbitrary MIME object.
The MimeMultipartSigned class provides the following methods:
void *xlation_init (MimeObject *multipart_object)
This is called with the object, the object->headers of which should be
used to initialize the dexlateion engine. NULL indicates failure;
otherwise, an opaque closure object should be returned.
int xlation_data_hash (char *data, PRInt32 data_size,
void *xlation_closure)
This is called with the raw data, for which a signature has been computed.
The xlation module should examine this, and compute a signature for it.
int xlation_data_eof (void *xlation_closure, PRBool abort_p)
This is called when no more data remains. If `abort_p' is true, then the
xlation module may choose to discard any data rather than processing it,
as we're terminating abnormally.
int xlation_signature_init (void *xlation_closure,
MimeObject *multipart_object,
MimeHeaders *signature_hdrs)
This is called after xlation_data_eof() and just before the first call to
xlation_signature_hash(). The xlation module may wish to do some
initialization here, or may wish to examine the actual headers of the
signature object itself.
int xlation_signature_hash (char *data, PRInt32 data_size,
void *xlation_closure)
This is called with the raw data of the detached signature block. It will
be called after xlation_data_eof() has been called to signify the end of
the data which is signed. This data is the data of the signature itself.
int xlation_signature_eof (void *xlation_closure, PRBool abort_p)
This is called when no more signature data remains. If `abort_p' is true,
then the xlation module may choose to discard any data rather than
processing it, as we're terminating abnormally.
char * xlation_generate_html (void *xlation_closure)
This is called after `xlation_signature_eof' but before `xlation_free'.
The xlation module should return a newly-allocated string of HTML code
which explains the status of the dexlateion to the user (whether the
signature checks out, etc.)
void xlation_free (void *xlation_closure)
This will be called when we're all done, after `xlation_signature_eof' and
`xlation_emit_html'. It is intended to free any data represented by the
xlation_closure.
*/
typedef struct MimeMultipartSignedClass MimeMultipartSignedClass;
typedef struct MimeMultipartSigned MimeMultipartSigned;
typedef enum {
MimeMultipartSignedPreamble,
MimeMultipartSignedBodyFirstHeader,
MimeMultipartSignedBodyHeaders,
MimeMultipartSignedBodyFirstLine,
MimeMultipartSignedBodyLine,
MimeMultipartSignedSignatureHeaders,
MimeMultipartSignedSignatureFirstLine,
MimeMultipartSignedSignatureLine,
MimeMultipartSignedEpilogue
} MimeMultipartSignedParseState;
struct MimeMultipartSignedClass {
MimeMultipartClass multipart;
/* Callbacks used by dexlateion (really, signature verification) module. */
void * (*xlation_init) (MimeObject *multipart_object);
int (*xlation_data_hash) (char *data, PRInt32 data_size,
void *xlation_closure);
int (*xlation_signature_hash) (char *data, PRInt32 data_size,
void *xlation_closure);
int (*xlation_data_eof) (void *xlation_closure, PRBool abort_p);
int (*xlation_signature_eof) (void *xlation_closure, PRBool abort_p);
int (*xlation_signature_init) (void *xlation_closure,
MimeObject *multipart_object,
MimeHeaders *signature_hdrs);
char * (*xlation_generate_html) (void *xlation_closure);
void (*xlation_free) (void *xlation_closure);
};
extern MimeMultipartSignedClass mimeMultipartSignedClass;
struct MimeMultipartSigned {
MimeMultipart multipart;
MimeMultipartSignedParseState state; /* State of parser */
void *xlation_closure; /* Opaque data used by signature
verification module. */
MimeHeaders *body_hdrs; /* The headers of the signed object. */
MimeHeaders *sig_hdrs; /* The headers of the signature. */
MimePartBufferData *part_buffer; /* The buffered body of the signed
object (see mimepbuf.h) */
MimeDecoderData *sig_decoder_data; /* The signature is probably base64
encoded; this is the decoder used
to get raw bits out of it. */
};
#endif /* _MIMEMSIG_H_ */

Просмотреть файл

@ -0,0 +1,608 @@
/* -*- 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.
*/
#include "mimemult.h"
#include "modmime.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeContainerClass
MimeDefClass(MimeMultipart, MimeMultipartClass,
mimeMultipartClass, &MIME_SUPERCLASS);
static int MimeMultipart_initialize (MimeObject *);
static void MimeMultipart_finalize (MimeObject *);
static int MimeMultipart_parse_line (char *line, PRInt32 length, MimeObject *);
static int MimeMultipart_parse_eof (MimeObject *object, PRBool abort_p);
static MimeMultipartBoundaryType MimeMultipart_check_boundary(MimeObject *,
const char *,
PRInt32);
static int MimeMultipart_create_child(MimeObject *);
static PRBool MimeMultipart_output_child_p(MimeObject *, MimeObject *);
static int MimeMultipart_parse_child_line (MimeObject *, char *, PRInt32,
PRBool);
static int MimeMultipart_close_child(MimeObject *);
extern MimeObjectClass mimeMultipartAlternativeClass;
extern MimeObjectClass mimeMultipartRelatedClass;
extern MimeObjectClass mimeMultipartSignedClass;
extern MimeObjectClass mimeInlineTextVCardClass;
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeMultipart_debug_print (MimeObject *, FILE *, PRInt32);
#endif
static int
MimeMultipartClassInitialize(MimeMultipartClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeMultipart_initialize;
oclass->finalize = MimeMultipart_finalize;
oclass->parse_line = MimeMultipart_parse_line;
oclass->parse_eof = MimeMultipart_parse_eof;
mclass->check_boundary = MimeMultipart_check_boundary;
mclass->create_child = MimeMultipart_create_child;
mclass->output_child_p = MimeMultipart_output_child_p;
mclass->parse_child_line = MimeMultipart_parse_child_line;
mclass->close_child = MimeMultipart_close_child;
#if defined(DEBUG) && defined(XP_UNIX)
oclass->debug_print = MimeMultipart_debug_print;
#endif
return 0;
}
static int
MimeMultipart_initialize (MimeObject *object)
{
MimeMultipart *mult = (MimeMultipart *) object;
char *ct;
/* This is an abstract class; it shouldn't be directly instanciated. */
PR_ASSERT(object->class != (MimeObjectClass *) &mimeMultipartClass);
ct = MimeHeaders_get (object->headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
mult->boundary = (ct
? MimeHeaders_get_parameter (ct, HEADER_PARM_BOUNDARY, NULL, NULL)
: 0);
FREEIF(ct);
mult->state = MimeMultipartPreamble;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeMultipart_finalize (MimeObject *object)
{
MimeMultipart *mult = (MimeMultipart *) object;
object->class->parse_eof(object, FALSE);
FREEIF(mult->boundary);
if (mult->hdrs)
MimeHeaders_free(mult->hdrs);
mult->hdrs = 0;
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeMultipart_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
int status = 0;
MimeMultipartBoundaryType boundary;
PR_ASSERT(line && *line);
if (!line || !*line) return -1;
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
/* If we're supposed to write this object, but aren't supposed to convert
it to HTML, simply pass it through unaltered. */
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p &&
obj->options->output_fn)
return MimeObject_write(obj, line, length, TRUE);
if (mult->state == MimeMultipartEpilogue) /* already done */
boundary = MimeMultipartBoundaryTypeNone;
else
boundary = ((MimeMultipartClass *)obj->class)->check_boundary(obj, line,
length);
if (boundary == MimeMultipartBoundaryTypeTerminator ||
boundary == MimeMultipartBoundaryTypeSeparator)
{
/* Match! Close the currently-open part, move on to the next
state, and discard this line.
*/
if (mult->state != MimeMultipartPreamble)
status = ((MimeMultipartClass *)obj->class)->close_child(obj);
if (status < 0) return status;
if (boundary == MimeMultipartBoundaryTypeTerminator)
mult->state = MimeMultipartEpilogue;
else
{
mult->state = MimeMultipartHeaders;
/* Reset the header parser for this upcoming part. */
PR_ASSERT(!mult->hdrs);
if (mult->hdrs)
MimeHeaders_free(mult->hdrs);
mult->hdrs = MimeHeaders_new();
if (!mult->hdrs)
return MK_OUT_OF_MEMORY;
}
/* Now return, to ignore the boundary line itself. */
return 0;
}
/* Otherwise, this isn't a boundary string. So do whatever it is we
should do with this line (parse it as a header, feed it to the
child part, ignore it, etc.) */
switch (mult->state)
{
case MimeMultipartPreamble:
case MimeMultipartEpilogue:
/* Ignore this line. */
break;
case MimeMultipartHeaders:
/* Parse this line as a header for the sub-part. */
{
status = MimeHeaders_parse_line(line, length, mult->hdrs);
if (status < 0) return status;
/* If this line is blank, we're now done parsing headers, and should
now examine the content-type to create this "body" part.
*/
if (*line == CR || *line == LF)
{
status = ((MimeMultipartClass *) obj->class)->create_child(obj);
if (status < 0) return status;
PR_ASSERT(mult->state != MimeMultipartHeaders);
}
break;
}
case MimeMultipartPartFirstLine:
/* Hand this line off to the sub-part. */
status = (((MimeMultipartClass *) obj->class)->parse_child_line(obj,
line,
length,
TRUE));
if (status < 0) return status;
mult->state = MimeMultipartPartLine;
break;
case MimeMultipartPartLine:
/* Hand this line off to the sub-part. */
status = (((MimeMultipartClass *) obj->class)->parse_child_line(obj,
line,
length,
FALSE));
if (status < 0) return status;
break;
default:
PR_ASSERT(0);
return -1;
}
return 0;
}
static MimeMultipartBoundaryType
MimeMultipart_check_boundary(MimeObject *obj, const char *line, PRInt32 length)
{
MimeMultipart *mult = (MimeMultipart *) obj;
PRInt32 blen;
PRBool term_p;
if (!mult->boundary ||
line[0] != '-' ||
line[1] != '-')
return MimeMultipartBoundaryTypeNone;
/* This is a candidate line to be a boundary. Check it out... */
blen = PL_strlen(mult->boundary);
term_p = FALSE;
/* strip trailing whitespace (including the newline.) */
while(length > 2 && XP_IS_SPACE(line[length-1]))
length--;
/* Could this be a terminating boundary? */
if (length == blen + 4 &&
line[length-1] == '-' &&
line[length-2] == '-')
{
term_p = TRUE;
length -= 2;
}
if (blen == length-2 && !PL_strncmp(line+2, mult->boundary, length-2))
return (term_p
? MimeMultipartBoundaryTypeTerminator
: MimeMultipartBoundaryTypeSeparator);
else
return MimeMultipartBoundaryTypeNone;
}
static int
MimeMultipart_create_child(MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
#ifdef JS_ATTACHMENT_MUMBO_JUMBO
MimeContainer *cont = (MimeContainer *) obj;
#endif
int status;
char *ct = (mult->hdrs
? MimeHeaders_get (mult->hdrs, HEADER_CONTENT_TYPE,
TRUE, FALSE)
: 0);
const char *dct = (((MimeMultipartClass *) obj->class)->default_part_type);
MimeObject *body = NULL;
MimeObject *parent = NULL;
PRBool showIcon = TRUE;
mult->state = MimeMultipartPartFirstLine;
/* Don't pass in NULL as the content-type (this means that the
auto-uudecode-hack won't ever be done for subparts of a
multipart, but only for untyped children of message/rfc822.
*/
body = mime_create(((ct && *ct) ? ct : (dct ? dct: TEXT_PLAIN)),
mult->hdrs, obj->options);
FREEIF(ct);
if (!body) return MK_OUT_OF_MEMORY;
status = ((MimeContainerClass *) obj->class)->add_child(obj, body);
if (status < 0)
{
mime_free(body);
return status;
}
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->is_multipart_msg &&
obj->options->decompose_file_init_fn )
{
if ( !mime_typep(obj,(MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(obj,(MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(obj,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(body, (MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(body, (MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(body,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(body, (MimeObjectClass*)&mimeInlineTextVCardClass))
{
status = obj->options->decompose_file_init_fn ( obj->options->stream_closure, mult->hdrs );
if (status < 0) return status;
}
}
#endif /* MIME_DRAFTS */
/* Now that we've added this new object to our list of children,
start its parser going (if we want to display it.)
*/
body->output_p = (((MimeMultipartClass *) obj->class)
->output_child_p(obj, body));
if (body->output_p)
{
#ifdef JS_ATTACHMENT_MUMBO_JUMBO
int attachment_count = 0;
PRBool isMsgBody = FALSE, isAlternativeOrRelated = FALSE;
#endif
status = body->class->parse_begin(body);
if (status < 0) return status;
#ifdef JS_ATTACHMENT_MUMBO_JUMBO
isMsgBody = MimeObjectChildIsMessageBody
(obj, &isAlternativeOrRelated);
if (isAlternativeOrRelated)
attachment_count = 0;
else if (isMsgBody)
attachment_count = cont->nchildren - 1;
else
attachment_count = cont->nchildren;
if (attachment_count &&
obj->options && !obj->options->nice_html_only_p) {
/* This is not the first child, so it's an attachment. Cause the
"attachments in this message" icon(s) to become visible.
Excluding the following types to avoid inline graphics and dull items :
Headers: Content-Disposition: inline
Content-Type: text/x-vcard
Content-Type: text/html
Content-Type: text/plain
Content-Type: message/rfc822 */
char *tmp = NULL;
/* if (strncasestr(body->headers->all_headers, "DISPOSITION: INLINE", 300))
showIcon = FALSE; */
if (PL_strstr(body->content_type, "text/x-vcard"))
showIcon = FALSE;
else if (PL_strstr(body->content_type, "text/html"))
showIcon = FALSE;
else if (PL_strstr(body->content_type, "message/rfc822"))
showIcon = FALSE;
else if (PL_strstr(body->content_type, "multipart/signed"))
showIcon = FALSE;
else if (PL_strstr(body->content_type, "application/x-pkcs7-signature"))
showIcon = FALSE;
else if (PL_strstr(body->content_type, "multipart/mixed"))
showIcon = FALSE;
if (showIcon)
{
(obj)->showAttachmentIcon = TRUE;
parent = obj->parent;
while (parent) {
(parent)->showAttachmentIcon = TRUE;
parent = parent->parent;
}
}
if (obj->options->attachment_icon_layer_id)
{
/* RICHIECSS
tmp = PR_smprintf("\n\
<SCRIPT>\n\
window.document.layers[\"noattach-%ld\"].visibility = \"hide\";\n\
window.document.layers[\"attach-%ld\"].visibility = \"show\";\n\
</SCRIPT>\n",
*/
tmp = PR_smprintf("\n\
<SCRIPT>\n\
document.getElementById(\"noattach%ld\").style.display = \"none\";\n\
document.getElementById(\"attach%ld\").style.display = \"\";\n\
</SCRIPT>\n",
(long) obj->options->attachment_icon_layer_id,
(long) obj->options->attachment_icon_layer_id);
if (tmp) {
status = MimeObject_write(obj, tmp, PL_strlen(tmp), TRUE);
PR_Free(tmp);
if (status < 0)
return status;
}
}
}
#endif /* JS_ATTACHMENT_MUMBO_JUMBO */
}
return 0;
}
static PRBool
MimeMultipart_output_child_p(MimeObject *obj, MimeObject *child)
{
return TRUE;
}
static int
MimeMultipart_close_child(MimeObject *object)
{
MimeMultipart *mult = (MimeMultipart *) object;
MimeContainer *cont = (MimeContainer *) object;
if (!mult->hdrs)
return 0;
MimeHeaders_free(mult->hdrs);
mult->hdrs = 0;
PR_ASSERT(cont->nchildren > 0);
if (cont->nchildren > 0)
{
MimeObject *kid = cont->children[cont->nchildren-1];
if (kid)
{
int status;
status = kid->class->parse_eof(kid, FALSE);
if (status < 0) return status;
status = kid->class->parse_end(kid, FALSE);
if (status < 0) return status;
#ifdef MIME_DRAFTS
if ( object->options &&
object->options->decompose_file_p &&
object->options->is_multipart_msg &&
object->options->decompose_file_close_fn )
{
if ( !mime_typep(object,(MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(object,(MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(object,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(kid, (MimeObjectClass*)&mimeInlineTextVCardClass))
{
status = object->options->decompose_file_close_fn ( object->options->stream_closure );
if (status < 0) return status;
}
}
#endif /* MIME_DRAFTS */
}
}
return 0;
}
static int
MimeMultipart_parse_child_line (MimeObject *obj, char *line, PRInt32 length,
PRBool first_line_p)
{
MimeContainer *cont = (MimeContainer *) obj;
int status;
MimeObject *kid;
PR_ASSERT(cont->nchildren > 0);
if (cont->nchildren <= 0)
return -1;
kid = cont->children[cont->nchildren-1];
PR_ASSERT(kid);
if (!kid) return -1;
#ifdef MIME_DRAFTS
if ( obj->options &&
obj->options->decompose_file_p &&
obj->options->is_multipart_msg &&
obj->options->decompose_file_output_fn )
{
if (!mime_typep(obj,(MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(obj,(MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(obj,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartAlternativeClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartRelatedClass) &&
!mime_typep(kid,(MimeObjectClass*)&mimeMultipartSignedClass) &&
!mime_typep(kid, (MimeObjectClass*)&mimeInlineTextVCardClass))
return obj->options->decompose_file_output_fn (line, length, obj->options->stream_closure);
}
#endif /* MIME_DRAFTS */
/* The newline issues here are tricky, since both the newlines before
and after the boundary string are to be considered part of the
boundary: this is so that a part can be specified such that it
does not end in a trailing newline.
To implement this, we send a newline *before* each line instead
of after, except for the first line, which is not preceeded by a
newline.
*/
/* Remove the trailing newline... */
if (length > 0 && line[length-1] == LF) length--;
if (length > 0 && line[length-1] == CR) length--;
if (!first_line_p)
{
/* Push out a preceeding newline... */
char nl[] = LINEBREAK;
status = kid->class->parse_buffer (nl, LINEBREAK_LEN, kid);
if (status < 0) return status;
}
/* Now push out the line sans trailing newline. */
return kid->class->parse_buffer (line, length, kid);
}
static int
MimeMultipart_parse_eof (MimeObject *obj, PRBool abort_p)
{
MimeMultipart *mult = (MimeMultipart *) obj;
MimeContainer *cont = (MimeContainer *) obj;
if (obj->closed_p) return 0;
/* Push out one last newline if part of the last line is still in the
ibuffer. If this happens, this object does not end in a trailing newline
(and the parse_line method will be called with a string with no trailing
newline, which isn't the usual case.)
*/
if (!abort_p && obj->ibuffer_fp > 0)
{
int status = obj->class->parse_buffer (obj->ibuffer, obj->ibuffer_fp,
obj);
obj->ibuffer_fp = 0;
if (status < 0)
{
obj->closed_p = TRUE;
return status;
}
}
/* Now call parse_eof for our active child, if there is one.
*/
if (cont->nchildren > 0 &&
(mult->state == MimeMultipartPartLine ||
mult->state == MimeMultipartPartFirstLine))
{
MimeObject *kid = cont->children[cont->nchildren-1];
PR_ASSERT(kid);
if (kid)
{
int status = kid->class->parse_eof(kid, abort_p);
if (status < 0) return status;
}
}
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
}
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeMultipart_debug_print (MimeObject *obj, FILE *stream, PRInt32 depth)
{
MimeMultipart *mult = (MimeMultipart *) obj;
MimeContainer *cont = (MimeContainer *) obj;
char *addr = mime_part_address(obj);
int i;
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream, "<%s %s (%d kid%s) boundary=%s 0x%08X>\n",
obj->class->class_name,
addr ? addr : "???",
cont->nchildren, (cont->nchildren == 1 ? "" : "s"),
(mult->boundary ? mult->boundary : "(none)"),
(PRUint32) mult);
FREEIF(addr);
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
int status = kid->class->debug_print (kid, stream, depth+1);
if (status < 0) return status;
}
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
return 0;
}
#endif

Просмотреть файл

@ -0,0 +1,110 @@
/* -*- 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.
*/
#ifndef _MIMEMULT_H_
#define _MIMEMULT_H_
#include "mimecont.h"
/* The MimeMultipart class class implements the objects representing all of
the "multipart/" MIME types. In addition to the methods inherited from
MimeContainer, it provides the following methods and class variables:
int create_child (MimeObject *obj)
When it has been determined that a new sub-part should be created,
this method is called to do that. The default value for this method
does it in the usual multipart/mixed way. The headers of the object-
to-be-created may be found in the `hdrs' slot of the `MimeMultipart'
object.
PRBool output_child_p (MimeObject *parent, MimeObject *child)
Whether this child should be output. Default method always says `yes'.
int parse_child_line (MimeObject *obj, char *line, PRInt32 length,
PRBool first_line_p)
When we have a line which should be handed off to the currently-active
child object, this method is called to do that. The `first_line_p'
variable will be true only for the very first line handed off to this
sub-part. The default method simply passes the line to the most-
recently-added child object.
int close_child (MimeObject *self)
When we reach the end of a sub-part (a separator line) this method is
called to shut down the currently-active child. The default method
simply calls `parse_eof' on the most-recently-added child object.
MimeMultipartBoundaryType check_boundary (MimeObject *obj,
const char *line, PRInt32 length)
This method is used to examine a line and determine whether it is a
part boundary, and if so, what kind. It should return a member of
the MimeMultipartBoundaryType describing the line.
const char *default_part_type
This is the type which should be assumed for sub-parts which have
no explicit type specified. The default is "text/plain", but the
"multipart/digest" subclass overrides this to "message/rfc822".
*/
typedef struct MimeMultipartClass MimeMultipartClass;
typedef struct MimeMultipart MimeMultipart;
typedef enum {
MimeMultipartPreamble,
MimeMultipartHeaders,
MimeMultipartPartFirstLine,
MimeMultipartPartLine,
MimeMultipartEpilogue
} MimeMultipartParseState;
typedef enum {
MimeMultipartBoundaryTypeNone,
MimeMultipartBoundaryTypeSeparator,
MimeMultipartBoundaryTypeTerminator
} MimeMultipartBoundaryType;
struct MimeMultipartClass {
MimeContainerClass container;
const char *default_part_type;
int (*create_child) (MimeObject *);
PRBool (*output_child_p) (MimeObject *self, MimeObject *child);
int (*close_child) (MimeObject *);
int (*parse_child_line) (MimeObject *, char *line, PRInt32 length,
PRBool first_line_p);
MimeMultipartBoundaryType (*check_boundary) (MimeObject *, const char *line,
PRInt32 length);
};
extern MimeMultipartClass mimeMultipartClass;
struct MimeMultipart {
MimeContainer container; /* superclass variables */
char *boundary; /* Inter-part delimiter string */
MimeHeaders *hdrs; /* headers of the part currently
being parsed, if any */
MimeMultipartParseState state; /* State of parser */
};
#endif /* _MIMEMULT_H_ */

303
mailnews/mime/src/mimeobj.c Normal file
Просмотреть файл

@ -0,0 +1,303 @@
/* -*- 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.
*/
#include "mimeobj.h"
#include "prmem.h"
#include "plstr.h"
#ifndef MOZILLA_30
/* Way to destroy any notions of modularity or class hierarchy, Terry! */
# include "mimetpla.h"
# include "mimethtm.h"
# include "mimecont.h"
#endif /* !MOZILLA_30 */
MimeDefClass (MimeObject, MimeObjectClass, mimeObjectClass, NULL);
static int MimeObject_initialize (MimeObject *);
static void MimeObject_finalize (MimeObject *);
static int MimeObject_parse_begin (MimeObject *);
static int MimeObject_parse_buffer (char *, PRInt32, MimeObject *);
static int MimeObject_parse_line (char *, PRInt32, MimeObject *);
static int MimeObject_parse_eof (MimeObject *, PRBool);
static int MimeObject_parse_end (MimeObject *, PRBool);
static PRBool MimeObject_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeObject_debug_print (MimeObject *, FILE *, PRInt32 depth);
#endif
static int
MimeObjectClassInitialize(MimeObjectClass *class)
{
PR_ASSERT(!class->class_initialized);
class->initialize = MimeObject_initialize;
class->finalize = MimeObject_finalize;
class->parse_begin = MimeObject_parse_begin;
class->parse_buffer = MimeObject_parse_buffer;
class->parse_line = MimeObject_parse_line;
class->parse_eof = MimeObject_parse_eof;
class->parse_end = MimeObject_parse_end;
class->displayable_inline_p = MimeObject_displayable_inline_p;
#if defined(DEBUG) && defined(XP_UNIX)
class->debug_print = MimeObject_debug_print;
#endif
return 0;
}
static int
MimeObject_initialize (MimeObject *obj)
{
/* This is an abstract class; it shouldn't be directly instanciated. */
PR_ASSERT(obj->class != &mimeObjectClass);
/* Set up the content-type and encoding. */
if (!obj->content_type && obj->headers)
obj->content_type = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE,
TRUE, FALSE);
if (!obj->encoding && obj->headers)
obj->encoding = MimeHeaders_get (obj->headers,
HEADER_CONTENT_TRANSFER_ENCODING,
TRUE, FALSE);
/* Special case to normalize some types and encodings to a canonical form.
(These are nonstandard types/encodings which have been seen to appear in
multiple forms; we normalize them so that things like looking up icons
and extensions has consistent behavior for the receiver, regardless of
the "alias" type that the sender used.)
*/
if (!obj->content_type)
;
else if (!PL_strcasecmp(obj->content_type, APPLICATION_UUENCODE2) ||
!PL_strcasecmp(obj->content_type, APPLICATION_UUENCODE3) ||
!PL_strcasecmp(obj->content_type, APPLICATION_UUENCODE4))
{
PR_Free(obj->content_type);
obj->content_type = PL_strdup(APPLICATION_UUENCODE);
}
else if (!PL_strcasecmp(obj->content_type, IMAGE_XBM2) ||
!PL_strcasecmp(obj->content_type, IMAGE_XBM3))
{
PR_Free(obj->content_type);
obj->content_type = PL_strdup(IMAGE_XBM);
}
if (!obj->encoding)
;
else if (!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE2) ||
!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE3) ||
!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE4))
{
PR_Free(obj->encoding);
obj->encoding = PL_strdup(ENCODING_UUENCODE);
}
else if (!PL_strcasecmp(obj->encoding, ENCODING_COMPRESS2))
{
PR_Free(obj->encoding);
obj->encoding = PL_strdup(ENCODING_COMPRESS);
}
else if (!PL_strcasecmp(obj->encoding, ENCODING_GZIP2))
{
PR_Free(obj->encoding);
obj->encoding = PL_strdup(ENCODING_GZIP);
}
return 0;
}
static void
MimeObject_finalize (MimeObject *obj)
{
obj->class->parse_eof (obj, FALSE);
obj->class->parse_end (obj, FALSE);
if (obj->headers)
{
MimeHeaders_free(obj->headers);
obj->headers = 0;
}
/* Should have been freed by parse_eof, but just in case... */
PR_ASSERT(!obj->ibuffer);
PR_ASSERT(!obj->obuffer);
FREEIF (obj->ibuffer);
FREEIF (obj->obuffer);
FREEIF(obj->content_type);
FREEIF(obj->encoding);
if (obj->options && obj->options->state)
{
PR_Free(obj->options->state);
obj->options->state = 0;
}
}
static int
MimeObject_parse_begin (MimeObject *obj)
{
PR_ASSERT (!obj->closed_p);
/* If we haven't set up the state object yet, then this should be
the outermost object... */
if (obj->options && !obj->options->state)
{
PR_ASSERT(!obj->headers); /* should be the outermost object. */
obj->options->state = PR_NEW(MimeParseStateObject);
if (!obj->options->state) return MK_OUT_OF_MEMORY;
XP_MEMSET(obj->options->state, 0, sizeof(*obj->options->state));
obj->options->state->root = obj;
obj->options->state->separator_suppressed_p = TRUE; /* no first sep */
}
/* Decide whether this object should be output or not... */
if (!obj->options || !obj->options->output_fn)
obj->output_p = FALSE;
else if (!obj->options->part_to_load)
obj->output_p = TRUE;
else
{
char *id = mime_part_address(obj);
if (!id) return MK_OUT_OF_MEMORY;
obj->output_p = !PL_strcmp(id, obj->options->part_to_load);
PR_Free(id);
}
#ifndef MOZILLA_30
/* Way to destroy any notions of modularity or class hierarchy, Terry! */
if (obj->options && obj->options->nice_html_only_p) {
if (!mime_subclass_p(obj->class,
(MimeObjectClass*) &mimeInlineTextHTMLClass) &&
!mime_subclass_p(obj->class,
(MimeObjectClass*) &mimeInlineTextPlainClass) &&
!mime_subclass_p(obj->class,
(MimeObjectClass*) &mimeContainerClass)) {
obj->output_p = FALSE;
}
}
#endif /* !MOZILLA_30 */
return 0;
}
static int
MimeObject_parse_buffer (char *buffer, PRInt32 size, MimeObject *obj)
{
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
return msg_LineBuffer (buffer, size,
&obj->ibuffer, &obj->ibuffer_size, &obj->ibuffer_fp,
TRUE,
((int (*) (char *, PRInt32, void *))
/* This cast is to turn void into MimeObject */
obj->class->parse_line),
obj);
}
static int
MimeObject_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
/* This method should never be called. */
PR_ASSERT(0);
return -1;
}
static int
MimeObject_parse_eof (MimeObject *obj, PRBool abort_p)
{
if (obj->closed_p) return 0;
PR_ASSERT(!obj->parsed_p);
/* If there is still data in the ibuffer, that means that the last line of
this part didn't end in a newline; so push it out anyway (this means that
the parse_line method will be called with a string with no trailing
newline, which isn't the usual case.)
*/
if (!abort_p &&
obj->ibuffer_fp > 0)
{
int status = obj->class->parse_line (obj->ibuffer, obj->ibuffer_fp, obj);
obj->ibuffer_fp = 0;
if (status < 0)
{
obj->closed_p = TRUE;
return status;
}
}
obj->closed_p = TRUE;
return 0;
}
static int
MimeObject_parse_end (MimeObject *obj, PRBool abort_p)
{
if (obj->parsed_p)
{
PR_ASSERT(obj->closed_p);
return 0;
}
/* We won't be needing these buffers any more; nuke 'em. */
FREEIF(obj->ibuffer);
obj->ibuffer_fp = 0;
obj->ibuffer_size = 0;
FREEIF(obj->obuffer);
obj->obuffer_fp = 0;
obj->obuffer_size = 0;
obj->parsed_p = TRUE;
return 0;
}
static PRBool
MimeObject_displayable_inline_p (MimeObjectClass *class, MimeHeaders *hdrs)
{
PR_ASSERT(0); /* This method should never be called. */
return FALSE;
}
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeObject_debug_print (MimeObject *obj, FILE *stream, PRInt32 depth)
{
int i;
char *addr = mime_part_address(obj);
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream, "<%s %s 0x%08X>\n", obj->class->class_name,
addr ? addr : "???",
(PRUint32) obj);
FREEIF(addr);
return 0;
}
#endif

196
mailnews/mime/src/mimeobj.h Normal file
Просмотреть файл

@ -0,0 +1,196 @@
/* -*- 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.
*/
#ifndef _MIMEOBJ_H_
#define _MIMEOBJ_H_
#include "mimei.h"
/* MimeObject is the base-class for the objects representing all other
MIME types. It provides several methods:
int initialize (MimeObject *obj)
This is called from mime_new() when a new instance is allocated.
Subclasses should do whatever setup is necessary from this method,
and should call the superclass's initialize method, unless there's
a specific reason not to.
void finalize (MimeObject *obj)
This is called from mime_free() and should free all data associated
with the object. If the object points to other MIME objects, they
should be finalized as well (by calling mime_free(), not by calling
their finalize() methods directly.)
int parse_buffer (char *buf, PRInt32 size, MimeObject *obj)
This is the method by which you feed arbitrary data into the parser
for this object. Most subclasses will probably inherit this method
from the MimeObject base-class, which line-buffers the data and then
hands it off to the parse_line() method.
If this object uses a Content-Transfer-Encoding (base64, qp, uue)
then the data may be decoded by parse_buffer() before parse_line()
is called. (The MimeLeaf class provides this functionality.)
int parse_begin (MimeObject *obj)
Called after `init' but before `parse_line' or `parse_buffer'.
Can be used to initialize various parsing machinery.
int parse_line (char *line, PRInt32 length, MimeObject *obj)
This method is called (by parse_buffer()) for each complete line of
data handed to the parser, and is the method which most subclasses
will override to implement their parsers.
When handing data off to a MIME object for parsing, one should always
call the parse_buffer() method, and not call the parse_line() method
directly, since the parse_buffer() method may do other transformations
on the data (like base64 decoding.)
One should generally not call parse_line() directly, since that could
bypass decoding. One should call parse_buffer() instead.
int parse_eof (MimeObject *obj, PRBool abort_p)
This is called when there is no more data to be handed to the object:
when the parent object is done feeding data to an object being parsed.
Implementors of this method should be sure to also call the parse_eof()
methods of any sub-objects to which they have pointers.
This is also called by the finalize() method, just before object
destruction, if it has not already been called.
The `closed_p' instance variable is used to prevent multiple calls to
`parse_eof'.
int parse_end (MimeObject *obj)
Called after `parse_eof' but before `finalize'.
This can be used to free up any memory no longer needed now that parsing
is done (to avoid surprises due to unexpected method combination, it's
best to free things in this method in preference to `parse_eof'.)
Implementors of this method should be sure to also call the parse_end()
methods of any sub-objects to which they have pointers.
This is also called by the finalize() method, just before object
destruction, if it has not already been called.
The `parsed_p' instance variable is used to prevent multiple calls to
`parse_end'.
PRBool displayable_inline_p (MimeObjectClass *class, MimeHeaders *hdrs)
This method should return true if this class of object will be displayed
directly, as opposed to being displayed as a link. This information is
used by the "multipart/alternative" parser to decide which of its children
is the ``best'' one to display. Note that this is a class method, not
an object method -- there is not yet an instance of this class at the time
that it is called. The `hdrs' provided are the headers of the object that
might be instantiated -- from this, the method may extract additional
infomation that it might need to make its decision.
*/
/* this one is typdedef'ed in mimei.h, since it is the base-class. */
struct MimeObjectClass {
/* Note: the order of these first five slots is known by MimeDefClass().
Technically, these are part of the object system, not the MIME code.
*/
const char *class_name;
int instance_size;
struct MimeObjectClass *superclass;
int (*class_initialize) (MimeObjectClass *class);
PRBool class_initialized;
/* These are the methods shared by all MIME objects. See comment above.
*/
int (*initialize) (MimeObject *obj);
void (*finalize) (MimeObject *obj);
int (*parse_begin) (MimeObject *obj);
int (*parse_buffer) (char *buf, PRInt32 size, MimeObject *obj);
int (*parse_line) (char *line, PRInt32 length, MimeObject *obj);
int (*parse_eof) (MimeObject *obj, PRBool abort_p);
int (*parse_end) (MimeObject *obj, PRBool abort_p);
PRBool (*displayable_inline_p) (MimeObjectClass *class, MimeHeaders *hdrs);
#if defined(DEBUG) && defined(XP_UNIX)
int (*debug_print) (MimeObject *obj, FILE *stream, PRInt32 depth);
#endif
};
extern MimeObjectClass mimeObjectClass;
/* this one is typdedef'ed in mimei.h, since it is the base-class. */
struct MimeObject {
MimeObjectClass *class; /* Pointer to class object, for `type-of' */
MimeHeaders *headers; /* The header data associated with this object;
this is where the content-type, disposition,
description, and other meta-data live.
For example, the outermost message/rfc822 object
would have NULL here (since it has no parent,
thus no headers to describe it.) However, a
multipart/mixed object, which was the sole
child of that message/rfc822 object, would have
here a copy of the headers which began the
parent object (the headers which describe the
child.)
*/
char *content_type; /* The MIME content-type and encoding. */
char *encoding; /* In most cases, these will be the same as the
values to be found in the `headers' object,
but in some cases, the values in these slots
will be more correct than the headers.
*/
MimeObject *parent; /* Backpointer to a MimeContainer object. */
MimeDisplayOptions *options; /* Display preferences set by caller. */
PRBool closed_p; /* Whether it's done being written to. */
PRBool parsed_p; /* Whether the parser has been shut down. */
PRBool output_p; /* Whether it should be written. */
PRBool showAttachmentIcon;
/* Read-buffer and write-buffer (on input, `parse_buffer' uses ibuffer to
compose calls to `parse_line'; on output, `obuffer' is used in various
ways by various routines.) These buffers are created and grow as needed.
`ibuffer' should be generally be considered hands-off, and `obuffer'
should generally be considered fair game.
*/
char *ibuffer, *obuffer;
PRInt32 ibuffer_size, obuffer_size;
PRInt32 ibuffer_fp, obuffer_fp;
};
#define MimeObject_grow_obuffer(obj, desired_size) \
(((desired_size) >= (obj)->obuffer_size) ? \
msg_GrowBuffer ((desired_size), sizeof(char), 1024, \
&(obj)->obuffer, &(obj)->obuffer_size) \
: 0)
#endif /* _MIMEOBJ_H_ */

Просмотреть файл

@ -0,0 +1,288 @@
/* -*- 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.
*/
#include "mimepbuf.h"
#include "xp_file.h"
#include "prmem.h"
#include "plstr.h"
/* See mimepbuf.h for a description of the mission of this file.
Implementation:
When asked to buffer an object, we first try to malloc() a buffer to
hold the upcoming part. First we try to allocate a 50k buffer, and
then back off by 5k until we are able to complete the allocation,
or are unable to allocate anything.
As data is handed to us, we store it in the memory buffer, until the
size of the memory buffer is exceeded (including the case where no
memory buffer was able to be allocated at all.)
Once we've filled the memory buffer, we open a temp file on disk.
Anything that is currently in the memory buffer is then flushed out
to the disk file (and the memory buffer is discarded.) Subsequent
data that is passed in is appended to the file.
Thus only one of the memory buffer or the disk buffer ever exist at
the same time; and small parts tend to live completely in memory
while large parts tend to live on disk.
When we are asked to read the data back out of the buffer, we call
the provided read-function with either: the contents of the memory
buffer; or blocks read from the disk file.
*/
extern int MK_UNABLE_TO_OPEN_TMP_FILE;
#define TARGET_MEMORY_BUFFER_SIZE (1024 * 50) /* try for 50k mem buffer */
#define TARGET_MEMORY_BUFFER_QUANTUM (1024 * 5) /* decrease in steps of 5k */
#define DISK_BUFFER_SIZE (1024 * 10) /* read disk in 10k chunks */
struct MimePartBufferData
{
char *part_buffer; /* Buffer used for part-lookahead. */
PRInt32 part_buffer_fp; /* Active length. */
PRInt32 part_buffer_size; /* How big it is. */
char *file_buffer_name; /* The name of a temp file used when we
run out of room in the part_buffer. */
PRFileDesc *file_stream; /* A stream to it. */
};
MimePartBufferData *
MimePartBufferCreate (void)
{
MimePartBufferData *data = PR_NEW(MimePartBufferData);
if (!data) return 0;
XP_MEMSET(data, 0, sizeof(*data));
return data;
}
void
MimePartBufferClose (MimePartBufferData *data)
{
PR_ASSERT(data);
if (!data) return;
if (data->file_stream)
{
PR_Close(data->file_stream);
data->file_stream = 0;
}
}
void
MimePartBufferReset (MimePartBufferData *data)
{
PR_ASSERT(data);
if (!data) return;
FREEIF(data->part_buffer);
data->part_buffer_fp = 0;
if (data->file_stream)
{
PR_Close(data->file_stream);
data->file_stream = 0;
}
if (data->file_buffer_name)
{
PR_Delete(data->file_buffer_name);
PR_Free(data->file_buffer_name);
data->file_buffer_name = 0;
}
}
void
MimePartBufferDestroy (MimePartBufferData *data)
{
PR_ASSERT(data);
if (!data) return;
MimePartBufferReset (data);
PR_Free(data);
}
int
MimePartBufferWrite (MimePartBufferData *data,
const char *buf, PRInt32 size)
{
int status = 0;
PR_ASSERT(data && buf && size > 0);
if (!data || !buf || size <= 0)
return -1;
/* If we don't yet have a buffer (either memory or file) try and make a
memory buffer.
*/
if (!data->part_buffer &&
!data->file_buffer_name)
{
int target_size = TARGET_MEMORY_BUFFER_SIZE;
while (target_size > 0)
{
data->part_buffer = (char *) PR_MALLOC(target_size);
if (data->part_buffer) break; /* got it! */
target_size -= TARGET_MEMORY_BUFFER_QUANTUM; /* decrease it and try
again */
}
if (data->part_buffer)
data->part_buffer_size = target_size;
else
data->part_buffer_size = 0;
data->part_buffer_fp = 0;
}
/* Ok, if at this point we still don't have either kind of buffer, try and
make a file buffer. */
if (!data->part_buffer &&
!data->file_buffer_name)
{
data->file_buffer_name = WH_TempName(xpTemporary, "nsma");
if (!data->file_buffer_name) return MK_OUT_OF_MEMORY;
data->file_stream = PR_Open(data->file_buffer_name, PR_RDWR | PR_CREATE_FILE, 493);
if (!data->file_stream)
return MK_UNABLE_TO_OPEN_TMP_FILE;
}
PR_ASSERT(data->part_buffer || data->file_stream);
/* If this buf will fit in the memory buffer, put it there.
*/
if (data->part_buffer &&
data->part_buffer_fp + size < data->part_buffer_size)
{
XP_MEMCPY(data->part_buffer + data->part_buffer_fp,
buf, size);
data->part_buffer_fp += size;
}
/* Otherwise it won't fit; write it to the file instead. */
else
{
/* If the file isn't open yet, open it, and dump the memory buffer
to it. */
if (!data->file_stream)
{
if (!data->file_buffer_name)
data->file_buffer_name =
WH_TempName (xpTemporary, "nsma");
if (!data->file_buffer_name) return MK_OUT_OF_MEMORY;
data->file_stream = PR_Open(data->file_buffer_name, PR_RDWR | PR_CREATE_FILE, 493);
if (!data->file_stream)
return MK_UNABLE_TO_OPEN_TMP_FILE;
if (data->part_buffer && data->part_buffer_fp)
{
status = PR_Write (data->file_stream,
data->part_buffer,
data->part_buffer_fp);
if (status < 0) return status;
}
FREEIF(data->part_buffer);
data->part_buffer_fp = 0;
data->part_buffer_size = 0;
}
/* Dump this buf to the file. */
status = PR_Write (data->file_stream, buf, size);
if (status < 0) return status;
}
return 0;
}
int
MimePartBufferRead (MimePartBufferData *data,
int (*read_fn) (char *buf, PRInt32 size, void *closure),
void *closure)
{
int status = 0;
PR_ASSERT(data);
if (!data) return -1;
if (data->part_buffer)
{
/* Read it out of memory.
*/
PR_ASSERT(!data->file_buffer_name && !data->file_stream);
status = read_fn(data->part_buffer, data->part_buffer_fp, closure);
}
else if (data->file_buffer_name)
{
/* Read it off disk.
*/
char *buf;
PRInt32 buf_size = DISK_BUFFER_SIZE;
PR_ASSERT(data->part_buffer_size == 0 && data->part_buffer_fp == 0);
PR_ASSERT(!data->file_stream);
PR_ASSERT(data->file_buffer_name);
if (!data->file_buffer_name) return -1;
buf = (char *) PR_MALLOC(buf_size);
if (!buf) return MK_OUT_OF_MEMORY;
if (data->file_stream)
PR_Close(data->file_stream);
data->file_stream = PR_Open(data->file_buffer_name, PR_RDONLY, 0);
if (!data->file_stream)
{
PR_Free(buf);
return MK_UNABLE_TO_OPEN_TMP_FILE;
}
while(1)
{
PRInt32 rstatus = PR_Read(data->file_stream, buf, buf_size - 1);
if (rstatus <= 0)
{
status = rstatus;
break;
}
else
{
/* It would be really nice to be able to yield here, and let
some user events and other input sources get processed.
Oh well. */
status = read_fn (buf, rstatus, closure);
if (status < 0) break;
}
}
PR_Free(buf);
}
return 0;
}

Просмотреть файл

@ -0,0 +1,81 @@
/* -*- 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.
*/
#ifndef _MIMEPBUF_H_
#define _MIMEPBUF_H_
#include "mimei.h"
#include "mimerosetta.h"
/* This file provides the ability to save up the entire contents of a MIME
object (of arbitrary size), and then emit it all at once later. The
buffering is done in an efficient way that works well for both very large
and very small objects.
This is used in two places:
= The implementation of multipart/alternative uses this code to do a
one-part-lookahead. As it traverses its children, it moves forward
until it finds a part which cannot be displayed; and then it displays
the *previous* part (the last which *could* be displayed.) This code
is used to hold the previous part until it is needed.
*/
#ifdef MOZ_SECURITY
HG37486
#endif
/* An opaque object used to represent the buffered data.
*/
typedef struct MimePartBufferData MimePartBufferData;
/* Create an empty part buffer object.
*/
extern MimePartBufferData *MimePartBufferCreate (void);
/* Assert that the buffer is now full (EOF has been reached on the current
part.) This will free some resources, but leaves the part in the buffer.
After calling MimePartBufferReset, the buffer may be used to store a
different object.
*/
void MimePartBufferClose (MimePartBufferData *data);
/* Reset a part buffer object to the default state, discarding any currently-
buffered data.
*/
extern void MimePartBufferReset (MimePartBufferData *data);
/* Free the part buffer itself, and discard any buffered data.
*/
extern void MimePartBufferDestroy (MimePartBufferData *data);
/* Push a chunk of a MIME object into the buffer.
*/
extern int MimePartBufferWrite (MimePartBufferData *data,
const char *buf, PRInt32 size);
/* Read the contents of the buffer back out. This will invoke the provided
read_fn with successive chunks of data until the buffer has been drained.
The provided function may be called once, or multiple times.
*/
extern int
MimePartBufferRead (MimePartBufferData *data,
int (*read_fn) (char *buf, PRInt32 size, void *closure),
void *closure);
#endif /* _MIMEPBUF_H_ */

Просмотреть файл

@ -0,0 +1,17 @@
/* -*- 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.
*/

352
mailnews/mime/src/mimesun.c Normal file
Просмотреть файл

@ -0,0 +1,352 @@
/* -*- 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.
*/
#include "mimesun.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeMultipartClass
MimeDefClass(MimeSunAttachment, MimeSunAttachmentClass,
mimeSunAttachmentClass, &MIME_SUPERCLASS);
static MimeMultipartBoundaryType MimeSunAttachment_check_boundary(MimeObject *,
const char *,
PRInt32);
static int MimeSunAttachment_create_child(MimeObject *);
static int MimeSunAttachment_parse_child_line (MimeObject *, char *, PRInt32,
PRBool);
static int MimeSunAttachment_parse_begin (MimeObject *);
static int MimeSunAttachment_parse_eof (MimeObject *, PRBool);
static int
MimeSunAttachmentClassInitialize(MimeSunAttachmentClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeMultipartClass *mclass = (MimeMultipartClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->parse_begin = MimeSunAttachment_parse_begin;
oclass->parse_eof = MimeSunAttachment_parse_eof;
mclass->check_boundary = MimeSunAttachment_check_boundary;
mclass->create_child = MimeSunAttachment_create_child;
mclass->parse_child_line = MimeSunAttachment_parse_child_line;
return 0;
}
static int
MimeSunAttachment_parse_begin (MimeObject *obj)
{
int status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
/* Sun messages always have separators at the beginning. */
return MimeObject_write_separator(obj);
}
static int
MimeSunAttachment_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status = 0;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
/* Sun messages always have separators at the end. */
if (!abort_p)
{
status = MimeObject_write_separator(obj);
if (status < 0) return status;
}
return 0;
}
static MimeMultipartBoundaryType
MimeSunAttachment_check_boundary(MimeObject *obj, const char *line,
PRInt32 length)
{
/* ten dashes */
if (line &&
line[0] == '-' && line[1] == '-' && line[2] == '-' && line[3] == '-' &&
line[4] == '-' && line[5] == '-' && line[6] == '-' && line[7] == '-' &&
line[8] == '-' && line[9] == '-' &&
(line[10] == CR || line[10] == LF))
return MimeMultipartBoundaryTypeSeparator;
else
return MimeMultipartBoundaryTypeNone;
}
static int
MimeSunAttachment_create_child(MimeObject *obj)
{
MimeMultipart *mult = (MimeMultipart *) obj;
int status = 0;
char *sun_data_type = 0;
const char *mime_ct = 0, *sun_enc_info = 0, *mime_cte = 0;
char *mime_ct2 = 0; /* sometimes we need to copy; this is for freeing. */
MimeObject *child = 0;
mult->state = MimeMultipartPartLine;
sun_data_type = (mult->hdrs
? MimeHeaders_get (mult->hdrs, HEADER_X_SUN_DATA_TYPE,
TRUE, FALSE)
: 0);
if (sun_data_type)
{
int i;
static const struct { const char *in, *out; } sun_types[] = {
/* Convert recognised Sun types to the corresponding MIME types,
and convert unrecognized ones based on the file extension and
the mime.types file.
These are the magic types used by MailTool that I can determine.
The only actual written spec I've found only listed the first few.
The rest were found by inspection (both of real-world messages,
and by running `strings' on the MailTool binary, and on the file
/usr/openwin/lib/cetables/cetables (the "Class Engine", Sun's
equivalent to .mailcap and mime.types.)
*/
{ "default", TEXT_PLAIN },
{ "default-doc", TEXT_PLAIN },
{ "text", TEXT_PLAIN },
{ "scribe", TEXT_PLAIN },
{ "sgml", TEXT_PLAIN },
{ "tex", TEXT_PLAIN },
{ "troff", TEXT_PLAIN },
{ "c-file", TEXT_PLAIN },
{ "h-file", TEXT_PLAIN },
{ "readme-file", TEXT_PLAIN },
{ "shell-script", TEXT_PLAIN },
{ "cshell-script", TEXT_PLAIN },
{ "makefile", TEXT_PLAIN },
{ "hidden-docs", TEXT_PLAIN },
{ "message", MESSAGE_RFC822 },
{ "mail-message", MESSAGE_RFC822 },
{ "mail-file", TEXT_PLAIN },
{ "gif-file", IMAGE_GIF },
{ "jpeg-file", IMAGE_JPG },
{ "ppm-file", IMAGE_PPM },
{ "pgm-file", "image/x-portable-graymap" },
{ "pbm-file", "image/x-portable-bitmap" },
{ "xpm-file", "image/x-xpixmap" },
{ "ilbm-file", "image/ilbm" },
{ "tiff-file", "image/tiff" },
{ "photocd-file", "image/x-photo-cd" },
{ "sun-raster", "image/x-sun-raster" },
{ "audio-file", AUDIO_BASIC },
{ "postscript", APPLICATION_POSTSCRIPT },
{ "postscript-file", APPLICATION_POSTSCRIPT },
{ "framemaker-document", "application/x-framemaker" },
{ "sundraw-document", "application/x-sun-draw" },
{ "sunpaint-document", "application/x-sun-paint" },
{ "sunwrite-document", "application/x-sun-write" },
{ "islanddraw-document", "application/x-island-draw" },
{ "islandpaint-document", "application/x-island-paint" },
{ "islandwrite-document", "application/x-island-write" },
{ "sun-executable", APPLICATION_OCTET_STREAM },
{ "default-app", APPLICATION_OCTET_STREAM },
{ 0, 0 }};
for (i = 0; sun_types[i].in; i++)
if (!PL_strcasecmp(sun_data_type, sun_types[i].in))
{
mime_ct = sun_types[i].out;
break;
}
}
/* If we didn't find a type, look at the extension on the file name.
*/
if (!mime_ct &&
obj->options &&
obj->options->file_type_fn)
{
char *name = MimeHeaders_get_name(mult->hdrs);
if (name)
{
mime_ct2 = obj->options->file_type_fn(name,
obj->options->stream_closure);
mime_ct = mime_ct2;
PR_Free(name);
if (!mime_ct2 || !PL_strcasecmp (mime_ct2, UNKNOWN_CONTENT_TYPE))
{
FREEIF(mime_ct2);
mime_ct = APPLICATION_OCTET_STREAM;
}
}
}
if (!mime_ct)
mime_ct = APPLICATION_OCTET_STREAM;
FREEIF(sun_data_type);
/* Convert recognised Sun encodings to the corresponding MIME encodings.
However, if the X-Sun-Encoding-Info field contains more than one
encoding (that is, contains a comma) then assign it the encoding of
the *rightmost* element in the list; and change its Content-Type to
application/octet-stream. Examples:
Sun Type: Translates To:
================== ====================
type: TEXT type: text/plain
encoding: COMPRESS encoding: x-compress
type: POSTSCRIPT type: application/x-compress
encoding: COMPRESS,UUENCODE encoding: x-uuencode
type: TEXT type: application/octet-stream
encoding: UNKNOWN,UUENCODE encoding: x-uuencode
*/
sun_data_type = (mult->hdrs
? MimeHeaders_get (mult->hdrs, HEADER_X_SUN_ENCODING_INFO,
FALSE,FALSE)
: 0);
sun_enc_info = sun_data_type;
/* this "adpcm-compress" pseudo-encoding is some random junk that
MailTool adds to the encoding description of .AU files: we can
ignore it if it is the leftmost element of the encoding field.
(It looks like it's created via `audioconvert -f g721'. Why?
Who knows.)
*/
if (sun_enc_info && !PL_strncasecmp (sun_enc_info, "adpcm-compress", 14))
{
sun_enc_info += 14;
while (XP_IS_SPACE(*sun_enc_info) || *sun_enc_info == ',')
sun_enc_info++;
}
/* Extract the last element of the encoding field, changing the content
type if necessary (as described above.)
*/
if (sun_enc_info && *sun_enc_info)
{
const char *prev;
const char *end = PL_strrchr(sun_enc_info, ',');
if (end)
{
const char *start = sun_enc_info;
sun_enc_info = end + 1;
while (XP_IS_SPACE(*sun_enc_info))
sun_enc_info++;
for (prev = end-1; prev > start && *prev != ','; prev--)
;
if (*prev == ',') prev++;
if (!PL_strncasecmp (prev, "uuencode", end-prev))
mime_ct = APPLICATION_UUENCODE;
else if (!PL_strncasecmp (prev, "gzip", end-prev))
mime_ct = APPLICATION_GZIP;
else if (!PL_strncasecmp (prev, "compress", end-prev))
mime_ct = APPLICATION_COMPRESS;
else if (!PL_strncasecmp (prev, "default-compress", end-prev))
mime_ct = APPLICATION_COMPRESS;
else
mime_ct = APPLICATION_OCTET_STREAM;
}
}
/* Convert the remaining Sun encoding to a MIME encoding.
If it isn't known, change the content-type instead.
*/
if (!sun_enc_info || !*sun_enc_info)
;
else if (!PL_strcasecmp(sun_enc_info,"compress")) mime_cte = ENCODING_COMPRESS;
else if (!PL_strcasecmp(sun_enc_info,"uuencode")) mime_cte = ENCODING_UUENCODE;
else if (!PL_strcasecmp(sun_enc_info,"gzip")) mime_cte = ENCODING_GZIP;
else mime_ct = APPLICATION_OCTET_STREAM;
FREEIF(sun_data_type);
/* Now that we know its type and encoding, create a MimeObject to represent
this part.
*/
child = mime_create(mime_ct, mult->hdrs, obj->options);
if (!child)
{
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
/* Fake out the child's content-type and encoding (it probably doesn't have
one right now, because the X-Sun- headers aren't generally recognised by
the rest of this library.)
*/
FREEIF(child->content_type);
FREEIF(child->encoding);
PR_ASSERT(mime_ct);
child->content_type = (mime_ct ? PL_strdup(mime_ct) : 0);
child->encoding = (mime_cte ? PL_strdup(mime_cte) : 0);
status = ((MimeContainerClass *) obj->class)->add_child(obj, child);
if (status < 0)
{
mime_free(child);
child = 0;
goto FAIL;
}
/* Sun attachments always have separators between parts. */
status = MimeObject_write_separator(obj);
if (status < 0) goto FAIL;
/* And now that we've added this new object to our list of
children, start its parser going. */
status = child->class->parse_begin(child);
if (status < 0) goto FAIL;
FAIL:
FREEIF(mime_ct2);
FREEIF(sun_data_type);
return status;
}
static int
MimeSunAttachment_parse_child_line (MimeObject *obj, char *line, PRInt32 length,
PRBool first_line_p)
{
MimeContainer *cont = (MimeContainer *) obj;
MimeObject *kid;
/* This is simpler than MimeMultipart->parse_child_line in that it doesn't
play games about body parts without trailing newlines.
*/
PR_ASSERT(cont->nchildren > 0);
if (cont->nchildren <= 0)
return -1;
kid = cont->children[cont->nchildren-1];
PR_ASSERT(kid);
if (!kid) return -1;
return kid->class->parse_buffer (line, length, kid);
}

Просмотреть файл

@ -0,0 +1,69 @@
/* -*- 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.
*/
#ifndef _MIMESUN_H_
#define _MIMESUN_H_
#include "mimemult.h"
/* MimeSunAttachment is the class for X-Sun-Attachment message contents, which
is the Content-Type assigned by that pile of garbage called MailTool. This
is not a MIME type per se, but it's very similar to multipart/mixed, so it's
easy to parse. Lots of people use MailTool, so what the hell.
The format is this:
= Content-Type is X-Sun-Attachment
= parts are separated by lines of exactly ten dashes
= just after the dashes comes a block of headers, including:
X-Sun-Data-Type: (manditory)
Values are Text, Postscript, Scribe, SGML, TeX, Troff, DVI,
and Message.
X-Sun-Encoding-Info: (optional)
Ordered, comma-separated values, including Compress and Uuencode.
X-Sun-Data-Name: (optional)
File name, maybe.
X-Sun-Data-Description: (optional)
Longer text.
X-Sun-Content-Lines: (manditory, unless Length is present)
Number of lines in the body, not counting headers and the blank
line that follows them.
X-Sun-Content-Length: (manditory, unless Lines is present)
Bytes, presumably using Unix line terminators.
*/
typedef struct MimeSunAttachmentClass MimeSunAttachmentClass;
typedef struct MimeSunAttachment MimeSunAttachment;
struct MimeSunAttachmentClass {
MimeMultipartClass multipart;
};
extern MimeSunAttachmentClass mimeSunAttachmentClass;
struct MimeSunAttachment {
MimeMultipart multipart;
};
#endif /* _MIMESUN_H_ */

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- 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.
*/
#include "mimetenr.h"
/* All the magic for this class is in mimetric.c; since text/enriched and
text/richtext are so similar, it was easiest to implement them in the
same method (but this is a subclass anyway just for general goodness.)
*/
#define MIME_SUPERCLASS mimeInlineTextRichtextClass
MimeDefClass(MimeInlineTextEnriched, MimeInlineTextEnrichedClass,
mimeInlineTextEnrichedClass, &MIME_SUPERCLASS);
static int
MimeInlineTextEnrichedClassInitialize(MimeInlineTextEnrichedClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeInlineTextRichtextClass *rclass = (MimeInlineTextRichtextClass *) class;
PR_ASSERT(!oclass->class_initialized);
rclass->enriched_p = TRUE;
return 0;
}

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- 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.
*/
#ifndef _MIMETENR_H_
#define _MIMETENR_H_
#include "mimetric.h"
/* The MimeInlineTextEnriched class implements the text/enriched MIME content
type, as defined in RFC 1563. It does this largely by virtue of being a
subclass of the MimeInlineTextRichtext class.
*/
typedef struct MimeInlineTextEnrichedClass MimeInlineTextEnrichedClass;
typedef struct MimeInlineTextEnriched MimeInlineTextEnriched;
struct MimeInlineTextEnrichedClass {
MimeInlineTextRichtextClass text;
};
extern MimeInlineTextEnrichedClass mimeInlineTextEnrichedClass;
struct MimeInlineTextEnriched {
MimeInlineTextRichtext richtext;
};
#endif /* _MIMETENR_H_ */

Просмотреть файл

@ -0,0 +1,305 @@
/* -*- 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.
*/
#include "mimetext.h"
#include "libi18n.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeLeafClass
MimeDefClass(MimeInlineText, MimeInlineTextClass, mimeInlineTextClass,
&MIME_SUPERCLASS);
static int MimeInlineText_initialize (MimeObject *);
static void MimeInlineText_finalize (MimeObject *);
static int MimeInlineText_rot13_line (MimeObject *, char *line, PRInt32 length);
static int MimeInlineText_parse_eof (MimeObject *obj, PRBool abort_p);
static int MimeInlineText_parse_end (MimeObject *, PRBool);
static int MimeInlineText_parse_decoded_buffer (char *, PRInt32, MimeObject *);
static int MimeInlineText_rotate_convert_and_parse_line(char *, PRInt32,
MimeObject *);
static int
MimeInlineTextClassInitialize(MimeInlineTextClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
MimeLeafClass *lclass = (MimeLeafClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeInlineText_initialize;
oclass->finalize = MimeInlineText_finalize;
oclass->parse_eof = MimeInlineText_parse_eof;
oclass->parse_end = MimeInlineText_parse_end;
class->rot13_line = MimeInlineText_rot13_line;
lclass->parse_decoded_buffer = MimeInlineText_parse_decoded_buffer;
return 0;
}
static int
MimeInlineText_initialize (MimeObject *obj)
{
MimeInlineText *text = (MimeInlineText *) obj;
/* This is an abstract class; it shouldn't be directly instanciated. */
PR_ASSERT(obj->class != (MimeObjectClass *) &mimeInlineTextClass);
/* Figure out an appropriate charset for this object.
*/
if (!text->charset && obj->headers)
{
if (obj->options && obj->options->override_charset)
{
text->charset = PL_strdup(obj->options->override_charset);
}
else
{
char *ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE,
FALSE, FALSE);
if (ct)
{
text->charset = MimeHeaders_get_parameter (ct, "charset", NULL, NULL);
PR_Free(ct);
}
if (!text->charset)
{
/* If we didn't find "Content-Type: ...; charset=XX" then look
for "X-Sun-Charset: XX" instead. (Maybe this should be done
in MimeSunAttachmentClass, but it's harder there than here.)
*/
text->charset = MimeHeaders_get (obj->headers,
HEADER_X_SUN_CHARSET,
FALSE, FALSE);
}
if (!text->charset)
{
if (obj->options && obj->options->default_charset)
text->charset = PL_strdup(obj->options->default_charset);
/* Do not label US-ASCII if the app default charset is multibyte.
Perhaps US-ASCII label should be removed for all cases.
*/
else if (MULTIBYTE & INTL_DefaultDocCharSetID(0))
;
else
text->charset = PL_strdup("US-ASCII");
}
}
}
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
}
static void
MimeInlineText_finalize (MimeObject *obj)
{
MimeInlineText *text = (MimeInlineText *) obj;
obj->class->parse_eof (obj, FALSE);
obj->class->parse_end (obj, FALSE);
FREEIF(text->charset);
/* Should have been freed by parse_eof, but just in case... */
PR_ASSERT(!text->cbuffer);
FREEIF (text->cbuffer);
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize (obj);
}
static int
MimeInlineText_parse_eof (MimeObject *obj, PRBool abort_p)
{
if (obj->closed_p) return 0;
PR_ASSERT(!obj->parsed_p);
/* If there is still data in the ibuffer, that means that the last line of
this part didn't end in a newline; so push it out anyway (this means that
the parse_line method will be called with a string with no trailing
newline, which isn't the usual case.) We do this here, rather than in
MimeObject_parse_eof, because MimeObject likes to shove things through
parse_line, and we have to shove it through the magic rotating-and-converting
code. So, we do that and digest the buffer before MimeObject has a chance
to do the wrong thing. See bug #26276 for more painful details.
*/
if (!abort_p &&
obj->ibuffer_fp > 0)
{
int status = MimeInlineText_rotate_convert_and_parse_line (obj->ibuffer,
obj->ibuffer_fp,
obj);
obj->ibuffer_fp = 0;
if (status < 0)
{
obj->closed_p = TRUE;
return status;
}
}
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof (obj, abort_p);
}
static int
MimeInlineText_parse_end (MimeObject *obj, PRBool abort_p)
{
MimeInlineText *text = (MimeInlineText *) obj;
if (obj->parsed_p)
{
PR_ASSERT(obj->closed_p);
return 0;
}
/* We won't be needing this buffer any more; nuke it. */
FREEIF(text->cbuffer);
text->cbuffer_size = 0;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_end (obj, abort_p);
}
/* This maps A-M to N-Z and N-Z to A-M. All other characters are left alone.
(Comments in GNUS imply that for Japanese, one should rotate by 47?)
*/
static const unsigned char MimeInlineText_rot13_table[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63, 64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95, 96,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 97, 98,
99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 123, 124, 125, 126,
127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255 };
static int
MimeInlineText_rot13_line (MimeObject *obj, char *line, PRInt32 length)
{
unsigned char *s, *end;
PR_ASSERT(line);
if (!line) return -1;
s = (unsigned char *) line;
end = s + length;
while (s < end)
{
*s = MimeInlineText_rot13_table[*s];
s++;
}
return 0;
}
static int
MimeInlineText_parse_decoded_buffer (char *buf, PRInt32 size, MimeObject *obj)
{
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
/* MimeLeaf takes care of this. */
PR_ASSERT(obj->output_p && obj->options && obj->options->output_fn);
if (!obj->options) return -1;
/* If we're supposed to write this object, but aren't supposed to convert
it to HTML, simply pass it through unaltered. */
if (!obj->options->write_html_p)
return MimeObject_write(obj, buf, size, TRUE);
/* This is just like the parse_decoded_buffer method we inherit from the
MimeLeaf class, except that we line-buffer to our own wrapper on the
`parse_line' method instead of calling the `parse_line' method directly.
*/
return msg_LineBuffer (buf, size,
&obj->ibuffer, &obj->ibuffer_size, &obj->ibuffer_fp,
TRUE,
((int (*) (char *, PRInt32, void *))
/* This cast is to turn void into MimeObject */
MimeInlineText_rotate_convert_and_parse_line),
obj);
}
#define MimeInlineText_grow_cbuffer(text, desired_size) \
(((desired_size) >= (text)->cbuffer_size) ? \
msg_GrowBuffer ((desired_size), sizeof(char), 100, \
&(text)->cbuffer, &(text)->cbuffer_size) \
: 0)
static int
MimeInlineText_rotate_convert_and_parse_line(char *line, PRInt32 length,
MimeObject *obj)
{
int status;
MimeInlineText *text = (MimeInlineText *) obj;
MimeInlineTextClass *textc = (MimeInlineTextClass *) obj->class;
char *converted = 0;
PR_ASSERT(!obj->closed_p);
if (obj->closed_p) return -1;
/* Rotate the line, if desired (this happens on the raw data, before any
charset conversion.) */
if (obj->options && obj->options->rot13_p)
{
status = textc->rot13_line(obj, line, length);
if (status < 0) return status;
}
/* Now convert to the canonical charset, if desired.
*/
if (obj->options && obj->options->charset_conversion_fn)
{
PRInt32 converted_len = 0;
const char *output_charset = (obj->options->override_charset
? obj->options->override_charset
: obj->options->default_charset);
status = obj->options->charset_conversion_fn(line, length,
text->charset,
output_charset,
&converted,
&converted_len,
obj->options->stream_closure);
if (status < 0)
{
FREEIF(converted);
return status;
}
if (converted)
{
line = converted;
length = converted_len;
}
}
/* Now that the line has been converted, call the subclass's parse_line
method with the decoded data. */
status = obj->class->parse_line(line, length, obj);
FREEIF(converted);
return status;
}

Просмотреть файл

@ -0,0 +1,78 @@
/* -*- 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.
*/
#ifndef _MIMETEXT_H_
#define _MIMETEXT_H_
#include "mimeleaf.h"
/* The MimeInlineText class is the superclass of all handlers for the
MIME text/ content types (which convert various text formats to HTML,
in one form or another.)
It provides two services:
= if ROT13 decoding is desired, the text will be rotated before
the `parse_line' method it called;
= text will be converted from the message's charset to the "target"
charset before the `parse_line' method is called.
The contract with charset-conversion is that the converted data will
be such that one may interpret any octets (8-bit bytes) in the data
which are in the range of the ASCII characters (0-127) as ASCII
characters. It is explicitly legal, for example, to scan through
the string for "<" and replace it with "&lt;", and to search for things
that look like URLs and to wrap them with interesting HTML tags.
The charset to which we convert will probably be UTF-8 (an encoding of
the Unicode character set, with the feature that all octets with the
high bit off have the same interpretations as ASCII.)
#### NOTE: if it turns out that we use JIS (ISO-2022-JP) as the target
encoding, then this is not quite true; it is safe to search for the
low ASCII values (under hex 0x40, octal 0100, which is '@') but it
is NOT safe to search for values higher than that -- they may be
being used as the subsequent bytes in a multi-byte escape sequence.
It's a nice coincidence that HTML's critical characters ("<", ">",
and "&") have values under 0x40...
*/
typedef struct MimeInlineTextClass MimeInlineTextClass;
typedef struct MimeInlineText MimeInlineText;
struct MimeInlineTextClass {
MimeLeafClass leaf;
int (*rot13_line) (MimeObject *obj, char *line, PRInt32 length);
int (*convert_line_charset) (MimeObject *obj, char *line, PRInt32 length);
};
extern MimeInlineTextClass mimeInlineTextClass;
struct MimeInlineText {
MimeLeaf leaf; /* superclass variables */
char *charset; /* The charset from the content-type of this
object, or the caller-specified overrides
or defaults.
*/
char *cbuffer; /* Buffer used for charset conversion. */
PRInt32 cbuffer_size;
};
#endif /* _MIMETEXT_H_ */

Просмотреть файл

@ -0,0 +1,160 @@
/* -*- 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.
*/
#include "mimethtm.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeInlineTextClass
MimeDefClass(MimeInlineTextHTML, MimeInlineTextHTMLClass,
mimeInlineTextHTMLClass, &MIME_SUPERCLASS);
static int MimeInlineTextHTML_parse_line (char *, PRInt32, MimeObject *);
static int MimeInlineTextHTML_parse_eof (MimeObject *, PRBool);
static int MimeInlineTextHTML_parse_begin (MimeObject *obj);
static int
MimeInlineTextHTMLClassInitialize(MimeInlineTextHTMLClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->parse_begin = MimeInlineTextHTML_parse_begin;
oclass->parse_line = MimeInlineTextHTML_parse_line;
oclass->parse_eof = MimeInlineTextHTML_parse_eof;
return 0;
}
static int
MimeInlineTextHTML_parse_begin (MimeObject *obj)
{
int status = ((MimeObjectClass*)&mimeLeafClass)->parse_begin(obj);
if (status < 0) return status;
if (!obj->output_p) return 0;
/* If this HTML part has a Content-Base header, and if we're displaying
to the screen (that is, not writing this part "raw") then translate
that Content-Base header into a <BASE> tag in the HTML.
*/
if (obj->options &&
obj->options->write_html_p &&
obj->options->output_fn)
{
char *base_hdr = MimeHeaders_get (obj->headers, HEADER_CONTENT_BASE,
FALSE, FALSE);
/* rhp - for MHTML Spec changes!!! */
if (!base_hdr)
{
base_hdr = MimeHeaders_get (obj->headers, "Content-Location", FALSE, FALSE);
}
/* rhp - for MHTML Spec changes!!! */
/* Encapsulate the entire text/html part inside an in-flow
layer. This will provide it a private coordinate system and
prevent it from escaping the bounds of its clipping so that
it might, for example, spoof a mail header. */
if (obj->options->set_html_state_fn)
{
status = obj->options->set_html_state_fn(obj->options->stream_closure,
TRUE, /* layer_encapulate_p */
TRUE, /* start_p */
FALSE); /* abort_p */
if (status < 0) return status;
}
if (base_hdr)
{
char *buf = (char *) PR_MALLOC(PL_strlen(base_hdr) + 20);
const char *in;
char *out;
if (!buf)
return MK_OUT_OF_MEMORY;
/* The value of the Content-Base header is a number of "words".
Whitespace in this header is not significant -- it is assumed
that any real whitespace in the URL has already been encoded,
and whitespace has been inserted to allow the lines in the
mail header to be wrapped reasonably. Creators are supposed
to insert whitespace every 40 characters or less.
*/
PL_strcpy(buf, "<BASE HREF=\"");
out = buf + PL_strlen(buf);
for (in = base_hdr; *in; in++)
/* ignore whitespace and quotes */
if (!XP_IS_SPACE(*in) && *in != '"')
*out++ = *in;
/* Close the tag and argument. */
*out++ = '"';
*out++ = '>';
*out++ = 0;
PR_Free(base_hdr);
status = MimeObject_write(obj, buf, PL_strlen(buf), FALSE);
PR_Free(buf);
if (status < 0) return status;
}
}
return 0;
}
static int
MimeInlineTextHTML_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
if (!obj->output_p) return 0;
if (obj->options && obj->options->output_fn)
return MimeObject_write(obj, line, length, TRUE);
else
return 0;
}
/* This method is the same as that of MimeInlineTextRichtext (and thus
MimeInlineTextEnriched); maybe that means that MimeInlineTextHTML
should share a common parent with them which is not also shared by
MimeInlineTextPlain?
*/
static int
MimeInlineTextHTML_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status;
if (obj->closed_p) return 0;
/* Run parent method first, to flush out any buffered data. */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
if (obj->output_p &&
obj->options &&
obj->options->write_html_p &&
obj->options->set_html_state_fn)
{
return obj->options->set_html_state_fn(obj->options->stream_closure,
TRUE, /* layer_encapulate_p */
FALSE, /* start_p */
abort_p);
}
return 0;
}

Просмотреть файл

@ -0,0 +1,40 @@
/* -*- 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.
*/
#ifndef _MIMETHTM_H_
#define _MIMETHTM_H_
#include "mimetext.h"
/* The MimeInlineTextHTML class implements the text/html MIME content type.
*/
typedef struct MimeInlineTextHTMLClass MimeInlineTextHTMLClass;
typedef struct MimeInlineTextHTML MimeInlineTextHTML;
struct MimeInlineTextHTMLClass {
MimeInlineTextClass text;
};
extern MimeInlineTextHTMLClass mimeInlineTextHTMLClass;
struct MimeInlineTextHTML {
MimeInlineText text;
};
#endif /* _MIMETHTM_H_ */

Просмотреть файл

@ -0,0 +1,137 @@
/* -*- 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.
*/
#include "mimetpla.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeInlineTextClass
MimeDefClass(MimeInlineTextPlain, MimeInlineTextPlainClass,
mimeInlineTextPlainClass, &MIME_SUPERCLASS);
static int MimeInlineTextPlain_parse_begin (MimeObject *);
static int MimeInlineTextPlain_parse_line (char *, PRInt32, MimeObject *);
static int MimeInlineTextPlain_parse_eof (MimeObject *, PRBool);
static int
MimeInlineTextPlainClassInitialize(MimeInlineTextPlainClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->parse_begin = MimeInlineTextPlain_parse_begin;
oclass->parse_line = MimeInlineTextPlain_parse_line;
oclass->parse_eof = MimeInlineTextPlain_parse_eof;
return 0;
}
static int
MimeInlineTextPlain_parse_begin (MimeObject *obj)
{
int status = 0;
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
if (status < 0) return status;
if (!obj->output_p) return 0;
if (obj->options &&
obj->options->write_html_p &&
obj->options->output_fn)
{
char* strs[4];
char* s;
strs[0] = "<PRE>";
strs[1] = "<PRE VARIABLE>";
strs[2] = "<PRE WRAP>";
strs[3] = "<PRE VARIABLE WRAP>";
s = PL_strdup(strs[(obj->options->variable_width_plaintext_p ? 1 : 0) +
(obj->options->wrap_long_lines_p ? 2 : 0)]);
if (!s) return MK_OUT_OF_MEMORY;
status = MimeObject_write(obj, s, PL_strlen(s), FALSE);
PR_Free(s);
if (status < 0) return status;
/* text/plain objects always have separators before and after them.
Note that this is not the case for text/enriched objects. */
status = MimeObject_write_separator(obj);
if (status < 0) return status;
}
return 0;
}
static int
MimeInlineTextPlain_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status;
if (obj->closed_p) return 0;
/* Run parent method first, to flush out any buffered data. */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
if (!obj->output_p) return 0;
if (obj->options &&
obj->options->write_html_p &&
obj->options->output_fn &&
!abort_p)
{
char s[] = "</PRE>";
status = MimeObject_write(obj, s, PL_strlen(s), FALSE);
if (status < 0) return status;
/* text/plain objects always have separators before and after them.
Note that this is not the case for text/enriched objects.
*/
status = MimeObject_write_separator(obj);
if (status < 0) return status;
}
return 0;
}
static int
MimeInlineTextPlain_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
int status;
PR_ASSERT(length > 0);
if (length <= 0) return 0;
status = MimeObject_grow_obuffer (obj, length * 2 + 40);
if (status < 0) return status;
/* Copy `line' to `out', quoting HTML along the way.
Note: this function does no charset conversion; that has already
been done.
*/
*obj->obuffer = 0;
status = NET_ScanForURLs (
#ifndef MOZILLA_30
(obj->options ? obj->options->pane : 0),
#endif /* !MOZILLA_30 */
line, length, obj->obuffer, obj->obuffer_size - 10,
(obj->options ?
obj->options->dont_touch_citations_p : FALSE));
if (status < 0) return status;
PR_ASSERT(*line == 0 || *obj->obuffer);
return MimeObject_write(obj, obj->obuffer, PL_strlen(obj->obuffer), TRUE);
}

Просмотреть файл

@ -0,0 +1,41 @@
/* -*- 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.
*/
#ifndef _MIMETPLA_H_
#define _MIMETPLA_H_
#include "mimetext.h"
/* The MimeInlineTextHTML class implements the text/plain MIME content type,
and is also used for all otherwise-unknown text/ subtypes.
*/
typedef struct MimeInlineTextPlainClass MimeInlineTextPlainClass;
typedef struct MimeInlineTextPlain MimeInlineTextPlain;
struct MimeInlineTextPlainClass {
MimeInlineTextClass text;
};
extern MimeInlineTextPlainClass mimeInlineTextPlainClass;
struct MimeInlineTextPlain {
MimeInlineText text;
};
#endif /* _MIMETPLA_H_ */

Просмотреть файл

@ -0,0 +1,357 @@
/* -*- 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.
*/
#include "mimetric.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeInlineTextClass
MimeDefClass(MimeInlineTextRichtext, MimeInlineTextRichtextClass,
mimeInlineTextRichtextClass, &MIME_SUPERCLASS);
static int MimeInlineTextRichtext_parse_line (char *, PRInt32, MimeObject *);
static int MimeInlineTextRichtext_parse_begin (MimeObject *);
static int MimeInlineTextRichtext_parse_eof (MimeObject *, PRBool);
static int
MimeInlineTextRichtextClassInitialize(MimeInlineTextRichtextClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->parse_begin = MimeInlineTextRichtext_parse_begin;
oclass->parse_line = MimeInlineTextRichtext_parse_line;
oclass->parse_eof = MimeInlineTextRichtext_parse_eof;
return 0;
}
/* This function has this clunky interface because it needs to be called
from outside this module (no MimeObject, etc.)
*/
int
MimeRichtextConvert (char *line, PRInt32 length,
int (*output_fn) (char *buf, PRInt32 size, void *closure),
void *closure,
char **obufferP,
PRInt32 *obuffer_sizeP,
PRBool enriched_p)
{
/* RFC 1341 (the original MIME spec) defined text/richtext.
RFC 1563 superceded text/richtext with text/enriched.
The changes from text/richtext to text/enriched are:
- CRLF semantics are different
- << maps to <
- These tags were added:
<VERBATIM>, <NOFILL>, <PARAM>, <FLUSHBOTH>
- These tags were removed:
<COMMENT>, <OUTDENT>, <OUTDENTRIGHT>, <SAMEPAGE>, <SUBSCRIPT>,
<SUPERSCRIPT>, <HEADING>, <FOOTING>, <PARAGRAPH>, <SIGNATURE>,
<LT>, <NL>, <NP>
This method implements them both.
draft-resnick-text-enriched-03.txt is a proposed update to 1563.
- These tags were added:
<FONTFAMILY>, <COLOR>, <PARAINDENT>, <LANG>.
However, all of these rely on the magic <PARAM> tag, which we
don't implement, so we're ignoring all of these.
Interesting fact: it's by Peter W. Resnick from Qualcomm (Eudora).
And it also says "It is fully expected that other text formatting
standards like HTML and SGML will supplant text/enriched in
Internet mail."
*/
int status = 0;
char *out;
const char *data_end;
const char *last_end;
const char *this_start;
const char *this_end;
int desired_size;
desired_size = length * 4;
if (desired_size >= *obuffer_sizeP)
status = msg_GrowBuffer (desired_size, sizeof(char), 1024,
obufferP, obuffer_sizeP);
if (status < 0) return status;
if (enriched_p)
{
for (this_start = line; this_start < line + length; this_start++)
if (!XP_IS_SPACE (*this_start)) break;
if (this_start >= line + length) /* blank line */
{
PL_strcpy (*obufferP, "<BR>");
return output_fn (*obufferP, PL_strlen(*obufferP), closure);
}
}
out = *obufferP;
*out = 0;
data_end = line + length;
last_end = line;
this_start = last_end;
this_end = this_start;
while (this_end < data_end)
{
/* Skip forward to next special character. */
while (this_start < data_end &&
*this_start != '<' && *this_start != '>' &&
*this_start != '&')
this_start++;
this_end = this_start;
/* Skip to the end of the tag. */
if (this_start < data_end && *this_start == '<')
{
this_end++;
while (this_end < data_end &&
!XP_IS_SPACE (*this_end) &&
*this_end != '<' && *this_end != '>' &&
*this_end != '&')
this_end++;
}
this_end++;
/* Push out the text preceeding the tag. */
if (last_end && last_end != this_start)
{
XP_MEMCPY (out, last_end, this_start - last_end);
out += this_start - last_end;
*out = 0;
}
if (this_start >= data_end)
break;
else if (*this_start == '&')
{
PL_strcpy (out, "&amp;"); out += PL_strlen (out);
}
else if (*this_start == '>')
{
PL_strcpy (out, "&gt;"); out += PL_strlen (out);
}
else if (enriched_p &&
this_start < data_end + 1 &&
this_start[0] == '<' &&
this_start[1] == '<')
{
PL_strcpy (out, "&lt;"); out += PL_strlen (out);
}
else if (this_start != this_end)
{
/* Push out this ID. */
const char *old = this_start + 1;
char *tag_open = 0;
char *tag_close = 0;
if (*old == '/')
{
/* This is </tag> */
old++;
}
switch (*old)
{
case 'b': case 'B':
if (!PL_strncasecmp ("BIGGER>", old, 7))
tag_open = "<FONT SIZE=\"+1\">", tag_close = "</FONT>";
else if (!PL_strncasecmp ("BLINK>", old, 5))
/* Of course, both text/richtext and text/enriched must be
enhanced *somehow*... Or else what would people think. */
tag_open = "<BLINK>", tag_close = "</BLINK>";
else if (!PL_strncasecmp ("BOLD>", old, 5))
tag_open = "<B>", tag_close = "</B>";
break;
case 'c': case 'C':
if (!PL_strncasecmp ("CENTER>", old, 7))
tag_open = "<CENTER>", tag_close = "</CENTER>";
else if (!enriched_p &&
!PL_strncasecmp ("COMMENT>", old, 8))
tag_open = "<!-- ", tag_close = " -->";
break;
case 'e': case 'E':
if (!PL_strncasecmp ("EXCERPT>", old, 8))
tag_open = "<BLOCKQUOTE>", tag_close = "</BLOCKQUOTE>";
break;
case 'f': case 'F':
if (!PL_strncasecmp ("FIXED>", old, 6))
tag_open = "<TT>", tag_close = "</TT>";
else if (enriched_p &&
!PL_strncasecmp ("FLUSHBOTH>", old, 10))
tag_open = "<P ALIGN=LEFT>", tag_close = "</P>";
else if (!PL_strncasecmp ("FLUSHLEFT>", old, 10))
tag_open = "<P ALIGN=LEFT>", tag_close = "</P>";
else if (!PL_strncasecmp ("FLUSHRIGHT>", old, 11))
tag_open = "<P ALIGN=RIGHT>", tag_close = "</P>";
else if (!enriched_p &&
!PL_strncasecmp ("FOOTING>", old, 8))
tag_open = "<H6>", tag_close = "</H6>";
break;
case 'h': case 'H':
if (!enriched_p &&
!PL_strncasecmp ("HEADING>", old, 8))
tag_open = "<H6>", tag_close = "</H6>";
break;
case 'i': case 'I':
if (!PL_strncasecmp ("INDENT>", old, 7))
tag_open = "<UL>", tag_close = "</UL>";
else if (!PL_strncasecmp ("INDENTRIGHT>", old, 12))
tag_open = 0, tag_close = 0;
/* else if (!enriched_p &&
!PL_strncasecmp ("ISO-8859-", old, 9))
tag_open = 0, tag_close = 0; */
else if (!PL_strncasecmp ("ITALIC>", old, 7))
tag_open = "<I>", tag_close = "</I>";
break;
case 'l': case 'L':
if (!enriched_p &&
!PL_strncasecmp ("LT>", old, 3))
tag_open = "&lt;", tag_close = 0;
break;
case 'n': case 'N':
if (!enriched_p &&
!PL_strncasecmp ("NL>", old, 3))
tag_open = "<BR>", tag_close = 0;
if (enriched_p &&
!PL_strncasecmp ("NOFILL>", old, 7))
tag_open = "<NOBR>", tag_close = "</NOBR>";
/* else if (!enriched_p &&
!PL_strncasecmp ("NO-OP>", old, 6))
tag_open = 0, tag_close = 0; */
/* else if (!enriched_p &&
!PL_strncasecmp ("NP>", old, 3))
tag_open = 0, tag_close = 0; */
break;
case 'o': case 'O':
if (!enriched_p &&
!PL_strncasecmp ("OUTDENT>", old, 8))
tag_open = 0, tag_close = 0;
else if (!enriched_p &&
!PL_strncasecmp ("OUTDENTRIGHT>", old, 13))
tag_open = 0, tag_close = 0;
break;
case 'p': case 'P':
if (enriched_p &&
!PL_strncasecmp ("PARAM>", old, 6))
tag_open = "<!-- ", tag_close = " -->";
else if (!enriched_p &&
!PL_strncasecmp ("PARAGRAPH>", old, 10))
tag_open = "<P>", tag_close = 0;
break;
case 's': case 'S':
if (!enriched_p &&
!PL_strncasecmp ("SAMEPAGE>", old, 9))
tag_open = 0, tag_close = 0;
else if (!enriched_p &&
!PL_strncasecmp ("SIGNATURE>", old, 10))
tag_open = "<I><FONT SIZE=\"-1\">", tag_close = "</FONT></I>";
else if (!PL_strncasecmp ("SMALLER>", old, 8))
tag_open = "<FONT SIZE=\"-1\">", tag_close = "</FONT>";
else if (!enriched_p &&
!PL_strncasecmp ("SUBSCRIPT>", old, 10))
tag_open = "<SUB>", tag_close = "</SUB>";
else if (!enriched_p &&
!PL_strncasecmp ("SUPERSCRIPT>", old, 12))
tag_open = "<SUP>", tag_close = "</SUP>";
break;
case 'u': case 'U':
if (!PL_strncasecmp ("UNDERLINE>", old, 10))
tag_open = "<U>", tag_close = "</U>";
/* else if (!enriched_p &&
!PL_strncasecmp ("US-ASCII>", old, 10))
tag_open = 0, tag_close = 0; */
break;
case 'v': case 'V':
if (enriched_p &&
!PL_strncasecmp ("VERBATIM>", old, 9))
tag_open = "<PRE>", tag_close = "</PRE>";
break;
}
if (this_start[1] == '/')
{
if (tag_close) PL_strcpy (out, tag_close);
out += PL_strlen (out);
}
else
{
if (tag_open) PL_strcpy (out, tag_open);
out += PL_strlen (out);
}
}
/* now go around again */
last_end = this_end;
this_start = last_end;
}
*out = 0;
return output_fn (*obufferP, out - *obufferP, closure);
}
static int
MimeInlineTextRichtext_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
PRBool enriched_p = (((MimeInlineTextRichtextClass *) obj->class)
->enriched_p);
return MimeRichtextConvert (line, length,
obj->options->output_fn,
obj->options->stream_closure,
&obj->obuffer, &obj->obuffer_size,
enriched_p);
}
static int
MimeInlineTextRichtext_parse_begin (MimeObject *obj)
{
int status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
char s[] = "";
if (status < 0) return status;
return MimeObject_write(obj, s, 0, TRUE); /* force out any separators... */
}
/* This method is largely the same as that of MimeInlineTextHTML; maybe that
means that MimeInlineTextRichtext and MimeInlineTextEnriched should share
a common parent with it which is not also shared by MimeInlineTextPlain?
*/
static int
MimeInlineTextRichtext_parse_eof (MimeObject *obj, PRBool abort_p)
{
int status;
if (obj->closed_p) return 0;
/* Run parent method first, to flush out any buffered data. */
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
if (obj->options &&
obj->options->write_html_p &&
obj->options->set_html_state_fn)
{
return obj->options->set_html_state_fn(obj->options->stream_closure,
FALSE, /* layer_encapulate_p */
FALSE, /* start_p */
abort_p);
}
return 0;
}

Просмотреть файл

@ -0,0 +1,52 @@
/* -*- 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.
*/
#ifndef _MIMETRIC_H_
#define _MIMETRIC_H_
#include "mimetext.h"
/* The MimeInlineTextRichtext class implements the (obsolete and deprecated)
text/richtext MIME content type, as defined in RFC 1341, and also the
text/enriched MIME content type, as defined in RFC 1563.
*/
typedef struct MimeInlineTextRichtextClass MimeInlineTextRichtextClass;
typedef struct MimeInlineTextRichtext MimeInlineTextRichtext;
struct MimeInlineTextRichtextClass {
MimeInlineTextClass text;
PRBool enriched_p; /* Whether we should act like text/enriched instead. */
};
extern MimeInlineTextRichtextClass mimeInlineTextRichtextClass;
struct MimeInlineTextRichtext {
MimeInlineText text;
};
extern int
MimeRichtextConvert (char *line, PRInt32 length,
int (*output_fn) (char *buf, PRInt32 size, void *closure),
void *closure,
char **obufferP,
PRInt32 *obuffer_sizeP,
PRBool enriched_p);
#endif /* _MIMETRIC_H_ */

Просмотреть файл

@ -0,0 +1,488 @@
/* -*- 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.
*/
#include "mimeunty.h"
#include "prmem.h"
#include "plstr.h"
#define MIME_SUPERCLASS mimeContainerClass
MimeDefClass(MimeUntypedText, MimeUntypedTextClass,
mimeUntypedTextClass, &MIME_SUPERCLASS);
static int MimeUntypedText_initialize (MimeObject *);
static void MimeUntypedText_finalize (MimeObject *);
static int MimeUntypedText_parse_begin (MimeObject *);
static int MimeUntypedText_parse_line (char *, PRInt32, MimeObject *);
static int MimeUntypedText_open_subpart (MimeObject *obj,
MimeUntypedTextSubpartType ttype,
const char *type,
const char *enc,
const char *name,
const char *desc);
static int MimeUntypedText_close_subpart (MimeObject *obj);
static PRBool MimeUntypedText_uu_begin_line_p(const char *line, PRInt32 length,
MimeDisplayOptions *opt,
char **type_ret,
char **name_ret);
static PRBool MimeUntypedText_uu_end_line_p(const char *line, PRInt32 length);
static PRBool MimeUntypedText_binhex_begin_line_p(const char *line,
PRInt32 length,
MimeDisplayOptions *opt);
static PRBool MimeUntypedText_binhex_end_line_p(const char *line,
PRInt32 length);
static int
MimeUntypedTextClassInitialize(MimeUntypedTextClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) class;
PR_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeUntypedText_initialize;
oclass->finalize = MimeUntypedText_finalize;
oclass->parse_begin = MimeUntypedText_parse_begin;
oclass->parse_line = MimeUntypedText_parse_line;
return 0;
}
static int
MimeUntypedText_initialize (MimeObject *object)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeUntypedText_finalize (MimeObject *object)
{
MimeUntypedText *uty = (MimeUntypedText *) object;
if (uty->open_hdrs)
{
/* Oops, those shouldn't still be here... */
MimeHeaders_free(uty->open_hdrs);
uty->open_hdrs = 0;
}
/* What about the open_subpart? We're gonna have to assume that it
is also on the MimeContainer->children list, and will get cleaned
up by that class. */
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeUntypedText_parse_begin (MimeObject *obj)
{
return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
}
static int
MimeUntypedText_parse_line (char *line, PRInt32 length, MimeObject *obj)
{
MimeUntypedText *uty = (MimeUntypedText *) obj;
int status = 0;
char *name = 0, *type = 0;
PRBool begin_line_p = FALSE;
PR_ASSERT(line && *line);
if (!line || !*line) return -1;
/* If we're supposed to write this object, but aren't supposed to convert
it to HTML, simply pass it through unaltered. */
if (obj->output_p &&
obj->options &&
!obj->options->write_html_p &&
obj->options->output_fn)
return MimeObject_write(obj, line, length, TRUE);
/* Open a new sub-part if this line demands it.
*/
if (line[0] == 'b' &&
MimeUntypedText_uu_begin_line_p(line, length, obj->options,
&type, &name))
{
/* Close the old part and open a new one. */
status = MimeUntypedText_open_subpart (obj,
MimeUntypedTextSubpartTypeUUE,
type, ENCODING_UUENCODE,
name, NULL);
FREEIF(name);
FREEIF(type);
if (status < 0) return status;
begin_line_p = TRUE;
}
else if (line[0] == '(' && line[1] == 'T' &&
MimeUntypedText_binhex_begin_line_p(line, length, obj->options))
{
/* Close the old part and open a new one. */
status = MimeUntypedText_open_subpart (obj,
MimeUntypedTextSubpartTypeBinhex,
APPLICATION_BINHEX, NULL,
NULL, NULL);
if (status < 0) return status;
begin_line_p = TRUE;
}
/* Open a text/plain sub-part if there is no sub-part open.
*/
if (!uty->open_subpart)
{
PR_ASSERT(!begin_line_p);
status = MimeUntypedText_open_subpart (obj,
MimeUntypedTextSubpartTypeText,
TEXT_PLAIN, NULL, NULL, NULL);
PR_ASSERT(uty->open_subpart);
if (!uty->open_subpart) return -1;
if (status < 0) return status;
}
/* Hand this line to the currently-open sub-part.
*/
status = uty->open_subpart->class->parse_buffer(line, length,
uty->open_subpart);
if (status < 0) return status;
/* Close this sub-part if this line demands it.
*/
if (begin_line_p)
;
else if (line[0] == 'e' &&
uty->type == MimeUntypedTextSubpartTypeUUE &&
MimeUntypedText_uu_end_line_p(line, length))
{
status = MimeUntypedText_close_subpart (obj);
if (status < 0) return status;
PR_ASSERT(!uty->open_subpart);
}
else if (uty->type == MimeUntypedTextSubpartTypeBinhex &&
MimeUntypedText_binhex_end_line_p(line, length))
{
status = MimeUntypedText_close_subpart (obj);
if (status < 0) return status;
PR_ASSERT(!uty->open_subpart);
}
return 0;
}
static int
MimeUntypedText_close_subpart (MimeObject *obj)
{
MimeUntypedText *uty = (MimeUntypedText *) obj;
int status;
if (uty->open_subpart)
{
status = uty->open_subpart->class->parse_eof(uty->open_subpart, FALSE);
uty->open_subpart = 0;
PR_ASSERT(uty->open_hdrs);
if (uty->open_hdrs)
{
MimeHeaders_free(uty->open_hdrs);
uty->open_hdrs = 0;
}
uty->type = MimeUntypedTextSubpartTypeText;
if (status < 0) return status;
/* Never put out a separator between sub-parts of UntypedText.
(This bypasses the rule that text/plain subparts always
have separators before and after them.)
*/
if (obj->options && obj->options->state)
obj->options->state->separator_suppressed_p = TRUE;
}
PR_ASSERT(!uty->open_hdrs);
return 0;
}
static int
MimeUntypedText_open_subpart (MimeObject *obj,
MimeUntypedTextSubpartType ttype,
const char *type,
const char *enc,
const char *name,
const char *desc)
{
MimeUntypedText *uty = (MimeUntypedText *) obj;
int status = 0;
char *h = 0;
if (!type || !*type || !PL_strcasecmp(type, UNKNOWN_CONTENT_TYPE))
type = APPLICATION_OCTET_STREAM;
if (enc && !*enc)
enc = 0;
if (desc && !*desc)
desc = 0;
if (name && !*name)
name = 0;
if (uty->open_subpart)
{
status = MimeUntypedText_close_subpart (obj);
if (status < 0) return status;
}
PR_ASSERT(!uty->open_subpart);
PR_ASSERT(!uty->open_hdrs);
/* To make one of these implicitly-typed sub-objects, we make up a fake
header block, containing only the minimum number of MIME headers needed.
We could do most of this (Type and Encoding) by making a null header
block, and simply setting obj->content_type and obj->encoding; but making
a fake header block is better for two reasons: first, it means that
something will actually be displayed when in `Show All Headers' mode;
and second, it's the only way to communicate the filename parameter,
aside from adding a new slot to MimeObject (which is something to be
avoided when possible.)
*/
uty->open_hdrs = MimeHeaders_new();
if (!uty->open_hdrs) return MK_OUT_OF_MEMORY;
h = (char *) PR_MALLOC(PL_strlen(type) +
(enc ? PL_strlen(enc) : 0) +
(desc ? PL_strlen(desc) : 0) +
(name ? PL_strlen(name) : 0) +
100);
if (!h) return MK_OUT_OF_MEMORY;
PL_strcpy(h, HEADER_CONTENT_TYPE ": ");
PL_strcat(h, type);
PL_strcat(h, LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), uty->open_hdrs);
if (status < 0) goto FAIL;
if (enc)
{
PL_strcpy(h, HEADER_CONTENT_TRANSFER_ENCODING ": ");
PL_strcat(h, enc);
PL_strcat(h, LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), uty->open_hdrs);
if (status < 0) goto FAIL;
}
if (desc)
{
PL_strcpy(h, HEADER_CONTENT_DESCRIPTION ": ");
PL_strcat(h, desc);
PL_strcat(h, LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), uty->open_hdrs);
if (status < 0) goto FAIL;
}
if (name)
{
PL_strcpy(h, HEADER_CONTENT_DISPOSITION ": inline; filename=\"");
PL_strcat(h, name);
PL_strcat(h, "\"" LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), uty->open_hdrs);
if (status < 0) goto FAIL;
}
/* push out a blank line. */
PL_strcpy(h, LINEBREAK);
status = MimeHeaders_parse_line(h, PL_strlen(h), uty->open_hdrs);
if (status < 0) goto FAIL;
/* Create a child... */
{
PRBool horrid_kludge = (obj->options && obj->options->state &&
obj->options->state->first_part_written_p);
if (horrid_kludge)
obj->options->state->first_part_written_p = FALSE;
uty->open_subpart = mime_create(type, uty->open_hdrs, obj->options);
if (horrid_kludge)
obj->options->state->first_part_written_p = TRUE;
if (!uty->open_subpart)
{
status = MK_OUT_OF_MEMORY;
goto FAIL;
}
}
/* Add it to the list... */
status = ((MimeContainerClass *) obj->class)->add_child(obj,
uty->open_subpart);
if (status < 0)
{
mime_free(uty->open_subpart);
uty->open_subpart = 0;
goto FAIL;
}
/* And start its parser going. */
status = uty->open_subpart->class->parse_begin(uty->open_subpart);
if (status < 0)
{
/* MimeContainer->finalize will take care of shutting it down now. */
uty->open_subpart = 0;
goto FAIL;
}
uty->type = ttype;
FAIL:
FREEIF(h);
if (status < 0 && uty->open_hdrs)
{
MimeHeaders_free(uty->open_hdrs);
uty->open_hdrs = 0;
}
return status;
}
static PRBool
MimeUntypedText_uu_begin_line_p(const char *line, PRInt32 length,
MimeDisplayOptions *opt,
char **type_ret, char **name_ret)
{
const char *s;
char *name = 0;
char *type = 0;
if (type_ret) *type_ret = 0;
if (name_ret) *name_ret = 0;
if (PL_strncmp (line, "begin ", 6)) return FALSE;
/* ...then three or four octal digits. */
s = line + 6;
if (*s < '0' || *s > '7') return FALSE;
s++;
if (*s < '0' || *s > '7') return FALSE;
s++;
if (*s < '0' || *s > '7') return FALSE;
s++;
if (*s == ' ')
s++;
else
{
if (*s < '0' || *s > '7') return FALSE;
s++;
if (*s != ' ') return FALSE;
}
while (XP_IS_SPACE(*s))
s++;
name = (char *) PR_MALLOC(((line+length)-s) + 1);
if (!name) return FALSE; /* grr... */
XP_MEMCPY(name, s, (line+length)-s);
name[(line+length)-s] = 0;
/* take off newline. */
if (name[PL_strlen(name)-1] == LF) name[PL_strlen(name)-1] = 0;
if (name[PL_strlen(name)-1] == CR) name[PL_strlen(name)-1] = 0;
/* Now try and figure out a type.
*/
if (opt && opt->file_type_fn)
type = opt->file_type_fn(name, opt->stream_closure);
else
type = 0;
if (name_ret)
*name_ret = name;
else
FREEIF(name);
if (type_ret)
*type_ret = type;
else
FREEIF(type);
return TRUE;
}
static PRBool
MimeUntypedText_uu_end_line_p(const char *line, PRInt32 length)
{
#if 0
/* A strictly conforming uuencode end line. */
return (line[0] == 'e' &&
line[1] == 'n' &&
line[2] == 'd' &&
(line[3] == 0 || XP_IS_SPACE(line[3])));
#else
/* ...but, why don't we accept any line that begins with the three
letters "END" in any case: I've seen lots of partial messages
that look like
BEGIN----- Cut Here-----
begin 644 foo.gif
Mxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Mxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Mxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
END------- Cut Here-----
so let's be lenient here. (This is only for the untyped-text-plain
case -- the uudecode parser itself is strict.)
*/
return (line[0] == ' ' ||
line[0] == '\t' ||
((line[0] == 'e' || line[0] == 'E') &&
(line[1] == 'n' || line[1] == 'N') &&
(line[2] == 'd' || line[2] == 'D')));
#endif
}
#define BINHEX_MAGIC "(This file must be converted with BinHex 4.0)"
#define BINHEX_MAGIC_LEN 45
static PRBool
MimeUntypedText_binhex_begin_line_p(const char *line, PRInt32 length,
MimeDisplayOptions *opt)
{
if (length <= BINHEX_MAGIC_LEN)
return FALSE;
while(length > 0 && XP_IS_SPACE(line[length-1]))
length--;
if (length != BINHEX_MAGIC_LEN)
return FALSE;
if (!PL_strncmp(line, BINHEX_MAGIC, BINHEX_MAGIC_LEN))
return TRUE;
else
return FALSE;
}
static PRBool
MimeUntypedText_binhex_end_line_p(const char *line, PRInt32 length)
{
if (length > 0 && line[length-1] == LF) length--;
if (length > 0 && line[length-1] == CR) length--;
if (length != 0 && length != 64)
return TRUE;
else
return FALSE;
}

Просмотреть файл

@ -0,0 +1,79 @@
/* -*- 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.
*/
#ifndef _MIMEUNTY_H_
#define _MIMEUNTY_H_
#include "mimecont.h"
/* The MimeUntypedText class is used for untyped message contents, that is,
it is the class used for the body of a message/rfc822 object which had
*no* Content-Type header, as opposed to an unrecognized content-type.
Such a message, technically, does not contain MIME data (it follows only
RFC 822, not RFC 1521.)
This is a container class, and the reason for that is that it loosely
parses the body of the message looking for ``sub-parts'' and then
creates appropriate containers for them.
More specifically, it looks for uuencoded data. It may do more than that
some day.
Basically, the algorithm followed is:
if line is "begin 644 foo.gif"
if there is an open sub-part, close it
add a sub-part with type: image/gif; encoding: x-uue
hand this line to it
and hand subsequent lines to that subpart
else if there is an open uuencoded sub-part, and line is "end"
hand this line to it
close off the uuencoded sub-part
else if there is an open sub-part
hand this line to it
else
open a text/plain subpart
hand this line to it
Adding other types than uuencode to this (for example, PGP) would be
pretty straightforward.
*/
typedef struct MimeUntypedTextClass MimeUntypedTextClass;
typedef struct MimeUntypedText MimeUntypedText;
struct MimeUntypedTextClass {
MimeContainerClass container;
};
extern MimeUntypedTextClass mimeUntypedTextClass;
typedef enum {
MimeUntypedTextSubpartTypeText, /* text/plain */
MimeUntypedTextSubpartTypeUUE, /* uuencoded data */
MimeUntypedTextSubpartTypeBinhex /* Mac BinHex data */
} MimeUntypedTextSubpartType;
struct MimeUntypedText {
MimeContainer container; /* superclass variables */
MimeObject *open_subpart; /* The part still-being-parsed */
MimeUntypedTextSubpartType type; /* What kind of type it is */
MimeHeaders *open_hdrs; /* The faked-up headers describing it */
};
#endif /* _MIMEUNTY_H_ */

1740
mailnews/mime/src/mimevcrd.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- 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.
*/
#ifndef _MIMEVCRD_H_
#define _MIMEVCRD_H_
#include "mimetext.h"
/* The MimeInlineTextHTML class implements the text/x-vcard and (maybe?
someday?) the application/directory MIME content types.
*/
typedef struct MimeInlineTextVCardClass MimeInlineTextVCardClass;
typedef struct MimeInlineTextVCard MimeInlineTextVCard;
struct MimeInlineTextVCardClass {
MimeInlineTextClass text;
char* vCardString;
};
extern MimeInlineTextVCardClass mimeInlineTextVCardClass;
struct MimeInlineTextVCard {
MimeInlineText text;
};
#endif /* _MIMEVCRD_H_ */

Просмотреть файл

@ -0,0 +1,471 @@
/* -*- 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.
*/
#ifndef _LIBMIME_H_
#define _LIBMIME_H_
#include "xp.h"
#include "prtypes.h"
#ifndef MOZILLA_30
# define MIME_DRAFTS
#endif
/* Opaque object describing a block of message headers, and a couple of
routines for extracting data from one.
*/
typedef struct MimeHeaders
{
char *all_headers; /* A char* of the entire header section. */
PRInt32 all_headers_fp; /* The length (it is not NULL-terminated.) */
PRInt32 all_headers_size; /* The size of the allocated block. */
PRBool done_p; /* Whether we've read the end-of-headers marker
(the terminating blank line.) */
char **heads; /* An array of length n_headers which points
to the beginning of each distinct header:
just after the newline which terminated
the previous one. This is to speed search.
This is not initialized until all the
headers have been read.
*/
PRInt32 heads_size; /* The length (and consequently, how many
distinct headers are in here.) */
char *obuffer; /* This buffer is used for output. */
PRInt32 obuffer_size;
PRInt32 obuffer_fp;
char *munged_subject; /* What a hack. This is a place to write down
the subject header, after it's been
charset-ified and stuff. Remembered so that
we can later use it to generate the
<TITLE> tag. */
} MimeHeaders;
typedef struct MimeDisplayOptions MimeDisplayOptions;
typedef struct MimeParseStateObject MimeParseStateObject;
#ifndef MOZILLA_30
typedef struct MSG_AttachmentData MSG_AttachmentData;
#endif
#ifdef RICHIE
XP_BEGIN_PROTOS
#endif
/* Given the name of a header, returns the contents of that header as
a newly-allocated string (which the caller must free.) If the header
is not present, or has no contents, NULL is returned.
If `strip_p' is TRUE, then the data returned will be the first token
of the header; else it will be the full text of the header. (This is
useful for getting just "text/plain" from "text/plain; name=foo".)
If `all_p' is FALSE, then the first header encountered is used, and
any subsequent headers of the same name are ignored. If TRUE, then
all headers of the same name are appended together (this is useful
for gathering up all CC headers into one, for example.)
*/
extern char *MimeHeaders_get(MimeHeaders *hdrs,
const char *header_name,
PRBool strip_p,
PRBool all_p);
/* Given a header of the form of the MIME "Content-" headers, extracts a
named parameter from it, if it exists. For example,
MimeHeaders_get_parameter("text/plain; charset=us-ascii", "charset")
would return "us-ascii".
Returns NULL if there is no match, or if there is an allocation failure.
RFC2231 - MIME Parameter Value and Encoded Word Extensions: Character Sets,
Languages, and Continuations
RFC2231 has added the character sets, languages, and continuations mechanism.
charset, and language information may also be returned to the caller.
For example,
MimeHeaders_get_parameter("text/plain; name*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A", "name")
MimeHeaders_get_parameter("text/plain; name*0*=us-ascii'en-us'This%20is%20; CRLFLWSPname*1*=%2A%2A%2Afun%2A%2A%2A", "name")
would return "This is ***fun***" and *charset = "us-ascii", *language = "en-us"
*/
extern char *MimeHeaders_get_parameter (const char *header_value,
const char *parm_name,
char **charset,
char **language);
extern MimeHeaders *MimeHeaders_copy (MimeHeaders *srcHeaders);
extern void MimeHeaders_free (MimeHeaders *hdrs);
/* Some defines for various standard header field names.
*/
#define HEADER_BCC "BCC"
#define HEADER_CC "CC"
#define HEADER_CONTENT_BASE "Content-Base"
#define HEADER_CONTENT_DESCRIPTION "Content-Description"
#define HEADER_CONTENT_DISPOSITION "Content-Disposition"
#define HEADER_CONTENT_ENCODING "Content-Encoding"
#define HEADER_CONTENT_LENGTH "Content-Length"
#define HEADER_CONTENT_NAME "Content-Name"
#define HEADER_CONTENT_TRANSFER_ENCODING "Content-Transfer-Encoding"
#define HEADER_CONTENT_TYPE "Content-Type"
#define HEADER_DATE "Date"
#define HEADER_DISTRIBUTION "Distribution"
#define HEADER_FCC "FCC"
#define HEADER_FOLLOWUP_TO "Followup-To"
#define HEADER_FROM "From"
#define HEADER_LINES "Lines"
#define HEADER_MESSAGE_ID "Message-ID"
#define HEADER_MIME_VERSION "MIME-Version"
#define HEADER_NEWSGROUPS "Newsgroups"
#define HEADER_ORGANIZATION "Organization"
#define HEADER_REFERENCES "References"
#define HEADER_REPLY_TO "Reply-To"
#define HEADER_RESENT_COMMENTS "Resent-Comments"
#define HEADER_RESENT_DATE "Resent-Date"
#define HEADER_RESENT_FROM "Resent-From"
#define HEADER_RESENT_MESSAGE_ID "Resent-Message-ID"
#define HEADER_RESENT_SENDER "Resent-Sender"
#define HEADER_RESENT_TO "Resent-To"
#define HEADER_RESENT_CC "Resent-CC"
#define HEADER_SENDER "Sender"
#define HEADER_SUBJECT "Subject"
#define HEADER_TO "To"
#define HEADER_X_MAILER "X-Mailer"
#define HEADER_X_NEWSREADER "X-Newsreader"
#define HEADER_X_POSTING_SOFTWARE "X-Posting-Software"
#define HEADER_X_MOZILLA_STATUS "X-Mozilla-Status"
#define HEADER_X_MOZILLA_NEWSHOST "X-Mozilla-News-Host"
#define HEADER_X_MOZILLA_DRAFT_INFO "X-Mozilla-Draft-Info"
#define HEADER_X_UIDL "X-UIDL"
#define HEADER_XREF "XREF"
#define HEADER_X_SUN_CHARSET "X-Sun-Charset"
#define HEADER_X_SUN_CONTENT_LENGTH "X-Sun-Content-Length"
#define HEADER_X_SUN_CONTENT_LINES "X-Sun-Content-Lines"
#define HEADER_X_SUN_DATA_DESCRIPTION "X-Sun-Data-Description"
#define HEADER_X_SUN_DATA_NAME "X-Sun-Data-Name"
#define HEADER_X_SUN_DATA_TYPE "X-Sun-Data-Type"
#define HEADER_X_SUN_ENCODING_INFO "X-Sun-Encoding-Info"
#define HEADER_X_PRIORITY "X-Priority"
#define HEADER_PARM_BOUNDARY "BOUNDARY"
#define HEADER_PARM_FILENAME "FILENAME"
#define HEADER_PARM_NAME "NAME"
#define HEADER_PARM_TYPE "TYPE"
typedef enum {
MimeHeadersAll, /* Show all headers */
MimeHeadersSome, /* Show all "interesting" headers */
MimeHeadersSomeNoRef, /* Same, but suppress the `References' header
(for when we're printing this message.) */
MimeHeadersMicro, /* Show a one-line header summary */
MimeHeadersMicroPlus, /* Same, but show the full recipient list as
well (To, CC, etc.) */
MimeHeadersCitation /* A one-line summary geared toward use in a
reply citation ("So-and-so wrote:") */
} MimeHeadersState;
/* The signature for various callbacks in the MimeDisplayOptions structure.
*/
typedef char *(*MimeHTMLGeneratorFunction) (const char *data, void *closure,
MimeHeaders *headers);
struct MimeDisplayOptions
{
const char *url; /* Base URL for the document. This string should
be freed by the caller, after the parser
completes (possibly at the same time as the
MimeDisplayOptions itself.) */
#ifndef MOZILLA_30
MSG_Pane* pane; /* The libmsg pane object that corresponds to
what we're showing. This is used by very
little... */
#endif /* !MOZILLA_30 */
MimeHeadersState headers; /* How headers should be displayed. */
PRBool fancy_headers_p; /* Whether to do clever formatting of headers
using tables, instead of spaces. */
#ifndef MOZILLA_30
PRBool output_vcard_buttons_p; /* Whether to output the buttons */
/* on vcards. */
#endif /* !MOZILLA_30 */
PRBool fancy_links_p; /* Whether to insert fancy links, so you can
do things like click on an email address to
add it to your address book. Something you
don't want to do while printing. */
PRBool variable_width_plaintext_p; /* Whether text/plain messages should
be in variable width, or fixed. */
PRBool wrap_long_lines_p; /* Whether to wrap long lines in text/plain
messages. */
PRBool rot13_p; /* Whether text/plain parts should be rotated
Set by "?rot13=true" */
PRBool no_inline_p; /* Whether inline display of attachments should
be suppressed. Set by "?inline=false" */
char *part_to_load; /* The particular part of the multipart which
we are extracting. Set by "?part=3.2.4" */
PRBool write_html_p; /* Whether the output should be HTML, or raw. */
PRBool dexlate_p; /* Whether all traces of xlateion should be
eradicated -- this is only meaningful when
write_html_p is FALSE; we set this when
attaching a message for forwarding, since
forwarding someone else a message that wasn't
xlated for them doesn't work. We have to
dexlate it before sending it.
*/
#ifndef MOZILLA_30
PRBool nice_html_only_p; /* If TRUE, then we only should write html if
it's pretty HTML (stuff that we're willing
to get shipped out in mail messages). If we
can't generate nice stuff for some part,
then don't say anything at all. */
PRBool dont_touch_citations_p; /* If TRUE, then we should leave citations
alone in plaintext parts. If FALSE, then
go ahead and tweak the fonts according
to preferences. */
#endif /* !MOZILLA_30 */
char *default_charset; /* If this is non-NULL, then it is the charset to
assume when no other one is specified via a
`charset' parameter.
*/
char *override_charset; /* If this is non-NULL, then we will assume that
all data is in this charset, regardless of what
the `charset' parameter of that part says.
This overrides `default_charset' as well.
(This is to cope with the fact that, in the
real world, many messages are mislabelled with
the wrong charset.)
*/
/* =======================================================================
Stream-related callbacks; for these functions, the `closure' argument
is what is found in `options->stream_closure'. (One possible exception
is for output_fn; see "output_closure" below.)
*/
void *stream_closure;
/* For setting up the display stream, so that the MIME parser can inform
the caller of the type of the data it will be getting. */
int (*output_init_fn) (const char *type,
const char *charset,
const char *name,
const char *x_mac_type,
const char *x_mac_creator,
void *stream_closure);
/* How the MIME parser feeds its output (HTML or raw) back to the caller. */
int (*output_fn) (char *buf, PRInt32 size, void *closure);
/* Closure to pass to the above output_fn. If NULL, then the
stream_closure is used. */
void *output_closure;
/* A callback used to encapsulate an HTML section and to reset the
HTML parser to its default state at the end of a section.
start_p indicates whether this is being called just before the
start or immediately after the end of the encapsulated HTML.
layer_encapsulate_p indicates whether or not to put special
ILAYER container tags around the HTML -- Also, when start_p is
FALSE, this function should close off any tags we've left open,
reset the font size and face, etc. This may be called multiple
times -- in particular, it will be called at the end of each
message part which might contain human-generated (and thus
arbitrarily buggy) markup. The `abort_p' argument specifies
whether it's ok for data to be discarded.
*/
int (*set_html_state_fn) (void *stream_closure,
PRBool layer_encapsulate_p,
PRBool start_p,
PRBool abort_p);
/* A hook for the caller to perform charset-conversion before HTML is
returned. Each set of characters which originated in a mail message
(body or headers) will be run through this filter before being converted
into HTML. (This should return bytes which may appear in an HTML file,
ie, we must be able to scan through the string to search for "<" and
turn it in to "&lt;", and so on.)
`input' is a non-NULL-terminated string of a single line from the message.
`input_length' is how long it is.
`input_charset' is a string representing the charset of this string (as
specified by MIME headers.)
`output_charset' is the charset to which conversion is desired.
`output_ret' is where a newly-malloced string is returned. It may be
NULL if no translation is needed.
`output_size_ret' is how long the returned string is (it need not be
NULL-terminated.).
*/
int (*charset_conversion_fn) (const char *input_line, PRInt32 input_length,
const char *input_charset,
const char *output_charset,
char **output_ret, PRInt32 *output_size_ret,
void *stream_closure);
/* A hook for the caller to perform both charset-conversion and decoding of
MIME-2 header fields (using RFC-1522 encoding.) Arguments and returned
values are as for `charset_conversion_fn'.
*/
int (*rfc1522_conversion_fn) (const char *input_line, PRInt32 input_length,
const char *input_charset,
const char *output_charset,
char **output_ret, PRInt32 *output_size_ret,
void *stream_closure);
/* A hook for the caller to translate a time string into a prettier or more
compact or localized form. */
char *(*reformat_date_fn) (const char *old_date, void *stream_closure);
/* A hook for the caller to turn a file name into a content-type. */
char *(*file_type_fn) (const char *filename, void *stream_closure);
/* A hook for the caller to turn a content-type into descriptive text. */
char *(*type_description_fn) (const char *content_type,void *stream_closure);
/* A hook for the caller to turn a content-type into an image icon. */
char *(*type_icon_name_fn) (const char *content_type, void *stream_closure);
/* A hook by which the user may be prompted for a password by the security
library. (This is really of type `SECKEYGetPasswordKey'; see sec.h.) */
void *(*passwd_prompt_fn)(void *arg1, void *arg2);
void *passwd_prompt_fn_arg;
/* =======================================================================
Various callbacks; for all of these functions, the `closure' argument
is what is found in `html_closure'.
*/
void *html_closure;
/* For emitting some HTML before the start of the outermost message
(this is called before any HTML is written to layout.) */
MimeHTMLGeneratorFunction generate_header_html_fn;
/* For emitting some HTML after the outermost header block, but before
the body of the first message. */
MimeHTMLGeneratorFunction generate_post_header_html_fn;
/* For emitting some HTML at the very end (this is called after libmime
has written everything it's going to write.) */
MimeHTMLGeneratorFunction generate_footer_html_fn;
/* For turning a message ID into a loadable URL. */
MimeHTMLGeneratorFunction generate_reference_url_fn;
/* For turning a mail address into a mailto URL. */
MimeHTMLGeneratorFunction generate_mailto_url_fn;
/* For turning a newsgroup name into a news URL. */
MimeHTMLGeneratorFunction generate_news_url_fn;
/* =======================================================================
Callbacks to handle the backend-specific inlined image display
(internal-external-reconnect junk.) For `image_begin', the `closure'
argument is what is found in `stream_closure'; but for all of the
others, the `closure' argument is the data that `image_begin' returned.
*/
/* Begins processing an embedded image; the URL and content_type are of the
image itself. */
void *(*image_begin) (const char *image_url, const char *content_type,
void *stream_closure);
/* Stop processing an image. */
void (*image_end) (void *image_closure, int status);
/* Dump some raw image data down the stream. */
int (*image_write_buffer) (char *buf, PRInt32 size, void *image_closure);
/* What HTML should be dumped out for this image. */
char *(*make_image_html) (void *image_closure);
/* =======================================================================
Other random opaque state.
*/
MimeParseStateObject *state; /* Some state used by libmime internals;
initialize this to 0 and leave it alone.
*/
#ifdef MIME_DRAFTS
/* =======================================================================
Mail Draft hooks -- 09-19-1996
*/
PRBool decompose_file_p; /* are we decomposing a mime msg
into separate files */
PRBool done_parsing_outer_headers; /* are we done parsing the outer message
headers; this is really useful when
we have multiple Message/RFC822
headers */
PRBool is_multipart_msg; /* are we decomposing a multipart
message */
int decompose_init_count; /* used for non multipart message only
*/
PRBool signed_p; /* to tell draft this is a signed
message */
/* Callback to gather the outer most headers so we could use the
information to initialize the addressing/subject/newsgroups fields
for the composition window. */
int (*decompose_headers_info_fn) (void *closure,
MimeHeaders *headers);
/* Callbacks to create temporary files for drafts attachments. */
int (*decompose_file_init_fn) (void *stream_closure,
MimeHeaders *headers );
int (*decompose_file_output_fn) (char *buf, PRInt32 size,
void *stream_closure);
int (*decompose_file_close_fn) (void *stream_closure);
#endif /* MIME_DRAFTS */
PRInt32 attachment_icon_layer_id; /* Hackhackhack. This is zero if we have
not yet emitted the attachment layer
stuff. If we have, then this is the
id number for that layer, which is a
unique random number every time, to keep
evil people from writing javascript code
to hack it. */
PRBool missing_parts; /* Whether or not this message is going to contain
missing parts (from IMAP Mime Parts On Demand) */
};
#ifdef RICHIE
XP_BEGIN_PROTOS
#endif
#endif /* _MODLMIME_H_ */

Просмотреть файл

@ -0,0 +1,94 @@
/* -*- 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.
*/
#ifndef MIME_H
#define MIME_H
#include "ntypes.h"
#include "mimeenc.h"
XP_BEGIN_PROTOS
extern PUBLIC const char *FE_UsersOrganization(void);
/* Returns the appropriate contents of a From: field of a mail message
originating from the current user. This calls FE_UsersFullName()
and FE_UsersMailAddress() and correctly munges the values, using
MSG_MakeFullAddress()
A new string is returned, which you must free when you're done with it.
*/
extern PUBLIC char *MIME_MakeFromField (PRInt16 csid);
/* Convert a block of text to the MIME quoted-printable encoding.
Returns a new string and its size, or NULL if it couldn't allocate.
*/
extern PUBLIC void MIME_EncodeQuotedPrintableString(const unsigned char *input,
PRUint32 input_size,
unsigned char **output,
PRUint32 *output_size);
/* Convert a block of text to the MIME base64 encoding.
Returns a new string and its size, or NULL if it couldn't allocate.
*/
extern PUBLIC void MIME_EncodeBase64String(const unsigned char *input,
PRUint32 input_size,
unsigned char **output,
PRUint32 *output_size);
/* build a mailto: url address given a to field
*
* returns a malloc'd string
*/
extern char *
MIME_BuildMailtoURLAddress(const char * to);
/* build a news: url address to post to, given a partial news-post
* URL and the newsgroups line
*
* returns a malloc'd string
*/
extern char *
MIME_BuildNewspostURLAddress(const char *partial_newspost_url,
const char *newsgroups);
/* If the argument is true, we use quoted-printable encoding on mail and
news messages which have 8bit characters in them. Otherwise, we assume
that the mail and news transport will not strip the eighth bit (a bad
assumption.) */
extern void MIME_ConformToStandard (PRBool conform_p);
/* for right now, only the XFE uses this */
extern PRBool Get_MIME_ConformToStandard();
/* Generate headers for a form post to a mailto: URL.
This lets the URL specify additional headers, but is careful to
ignore headers which would be dangerous. It may modify the URL
(because of CC) so a new URL to actually post to is returned.
*/
extern int MIME_GenerateMailtoFormPostHeaders (const char *old_post_url,
const char *referer,
char **new_post_url_return,
char **headers_return);
#define IMAP_EXTERNAL_CONTENT_HEADER "X-Mozilla-IMAP-Part"
XP_END_PROTOS
#endif /* mime.h */

Просмотреть файл

@ -0,0 +1,89 @@
/* -*- 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.
*/
/* -*- Mode: C; tab-width: 4 -*-
mimeenc.c --- MIME encoders and decoders, version 2 (see mimei.h)
Copyright © 1996 Netscape Communications Corporation, all rights reserved.
Created: Jamie Zawinski <jwz@netscape.com>, 15-May-96.
*/
#ifndef _MIMEENC_H_
#define _MIMEENC_H_
#include "prtypes.h"
/* This file defines interfaces to generic implementations of Base64,
Quoted-Printable, and UU decoders; and of Base64 and Quoted-Printable
encoders.
*/
/* Opaque objects used by the encoder/decoder to store state. */
typedef struct MimeDecoderData MimeDecoderData;
typedef struct MimeEncoderData MimeEncoderData;
#ifdef RICHIE
XP_BEGIN_PROTOS
#endif
/* functions for creating that opaque data.
*/
MimeDecoderData *MimeB64DecoderInit(int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
MimeDecoderData *MimeQPDecoderInit (int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
MimeDecoderData *MimeUUDecoderInit (int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
MimeEncoderData *MimeB64EncoderInit(int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
MimeEncoderData *MimeQPEncoderInit (int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
MimeEncoderData *MimeUUEncoderInit (char *filename,
int (*output_fn) (const char *buf,
PRInt32 size,
void *closure),
void *closure);
/* Push data through the encoder/decoder, causing the above-provided write_fn
to be called with encoded/decoded data. */
int MimeDecoderWrite (MimeDecoderData *data, const char *buffer, PRInt32 size);
int MimeEncoderWrite (MimeEncoderData *data, const char *buffer, PRInt32 size);
/* When you're done encoding/decoding, call this to free the data. If
abort_p is FALSE, then calling this may cause the write_fn to be called
one last time (as the last buffered data is flushed out.)
*/
int MimeDecoderDestroy(MimeDecoderData *data, PRBool abort_p);
int MimeEncoderDestroy(MimeEncoderData *data, PRBool abort_p);
#ifdef RICHIE
XP_END_PROTOS
#endif
#endif /* _MODMIMEE_H_ */

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- 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.
*/
/* msgutils.h --- various and sundry
*/
XP_BEGIN_PROTOS
extern int msg_GrowBuffer (PRUint32 desired_size,
PRUint32 element_size, PRUint32 quantum,
char **buffer, PRUint32 *size);
extern int msg_LineBuffer (const char *net_buffer, int32 net_buffer_size,
char **bufferP, uint32 *buffer_sizeP,
uint32 *buffer_fpP,
XP_Bool convert_newlines_p,
PRInt32 (*per_line_fn) (char *line, PRUint32
line_length, void *closure),
void *closure);
extern int msg_ReBuffer (const char *net_buffer, int32 net_buffer_size,
uint32 desired_buffer_size,
char **bufferP, uint32 *buffer_sizeP,
uint32 *buffer_fpP,
int32 (*per_buffer_fn) (char *buffer,
uint32 buffer_size,
void *closure),
void *closure);
extern NET_StreamClass *msg_MakeRebufferingStream (NET_StreamClass *next,
URL_Struct *url,
MWContext *context);
/* Given a string and a length, removes any "Re:" strings from the front.
(If the length is not given, then XP_STRLEN() is used on the string.)
It also deals with that "Re[2]:" thing that some mailers do.
Returns TRUE if it made a change, FALSE otherwise.
The string is not altered: the pointer to its head is merely advanced,
and the length correspondingly decreased.
*/
extern XP_Bool msg_StripRE(const char **stringP, uint32 *lengthP);
/*
* Does in-place modification of input param to conform with son-of-1036 rules
*/
extern void msg_MakeLegalNewsgroupComponent (char *name);
/*
* UnHex a char hex value into an integer value.
*/
extern int msg_UnHex(char c);
XP_END_PROTOS

Просмотреть файл

@ -0,0 +1,246 @@
/* -*- 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.
*/
#include "xp.h"
#include "prmem.h"
#include "plstr.h"
// For xp to ns file translation
#include "oldnsINetFile.h"
#include "nsVoidArray.h"
#include "direct.h"
// The nsINetfile
static nsINetFile *fileMgr = nsnull;
typedef struct _xp_to_nsFile {
nsFile *nsFp;
XP_File xpFp;
} xpNSFile;
// Array of translation structs from xp to ns file.
static nsVoidArray switchBack;
// Utility routine to remove a transator object from the array and free it.
nsresult deleteTrans(nsFile *nsFp) {
xpNSFile *trans = nsnull;
if (!nsFp)
return NS_OK;
for (PRInt32 i = switchBack.Count(); i > 0; i--) {
trans = (xpNSFile*)switchBack.ElementAt(i-1);
if (trans && trans->nsFp == nsFp) {
switchBack.RemoveElement(trans);
if (trans->xpFp) {
PR_Free(trans->xpFp);
trans->xpFp = nsnull;
}
PR_Free(trans);
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
PRIVATE
char *xpFileTypeToName(XP_FileType type) {
char *name = nsnull;
switch (type) {
case (xpCache):
return PL_strdup(CACHE_DIR_TOK);
break;
case (xpCacheFAT):
return PL_strdup(CACHE_DIR_TOK CACHE_DB_F_TOK);
break;
case (xpProxyConfig):
break;
case (xpURL):
break;
case (xpJSConfig):
break;
case (xpTemporary):
break;
case (xpJSCookieFilters):
break;
case (xpFileToPost):
break;
case (xpMimeTypes):
break;
case (xpHTTPCookie):
return PL_strdup("%USER%%COOKIE_F%");
case (xpHTTPCookiePermission):
return PL_strdup("%USER%%COOKIE_PERMISSION_F%");
case (xpHTTPSingleSignon):
return PL_strdup("%USER%%SIGNON_F%");
default:
break;
}
return nsnull;
}
// Utility routine to convert an xpFile pointer to a ns file pointer.
nsFile * XpToNsFp(XP_File xpFp) {
nsFile *nsFp = nsnull;
xpNSFile *trans = nsnull;
if (!xpFp)
return nsnull;
for (PRInt32 i = switchBack.Count(); i > 0; i--) {
trans = (xpNSFile*)switchBack.ElementAt(i-1);
if (trans && trans->xpFp == xpFp) {
nsFp = trans->nsFp;
break;
}
}
return nsFp;
}
extern "C" XP_File
NET_I_XP_FileOpen(const char * name, XP_FileType type, const XP_FilePerm perm)
{
XP_File xpFp;
xpNSFile *trans = (xpNSFile*)PR_Malloc(sizeof(xpNSFile));
nsFile *nsFp = nsnull;
nsresult rv;
nsFileMode mode;
char *aName = nsnull;
if (!fileMgr) {
if (NS_NewINetFile(&fileMgr, nsnull) != NS_OK) {
return NULL;
}
}
// Just get some random address.
xpFp = (XP_File) PR_Malloc(1);
trans->xpFp= xpFp;
if (!PL_strcasecmp(perm,XP_FILE_READ)) {
mode = nsRead;
} else if (!PL_strcasecmp(perm,XP_FILE_WRITE)) {
mode = nsOverWrite;
} else if (!PL_strcasecmp(perm,XP_FILE_WRITE_BIN)) {
mode = nsOverWrite;
} else {
mode = nsReadWrite;
}
/* call OpenFile with nsNetFile syntax if necesary. */
if ( (!name || !*name)
|| type == xpCache ) {
char *tmpName = xpFileTypeToName(type);
nsString newName = tmpName;
PR_FREEIF(tmpName)
if (newName.Length() < 1) {
PR_Free(trans);
PR_Free(xpFp);
return NULL;
}
newName.Append(name);
aName = newName.ToNewCString();
}
rv = fileMgr->OpenFile( (aName ? aName : name), mode, &nsFp);
if (aName)
delete aName;
if (NS_OK != rv) {
return NULL;
}
trans->nsFp = nsFp;
switchBack.AppendElement(trans);
return xpFp;
}
extern "C" char *
NET_I_XP_FileReadLine(char *outBuf, int outBufLen, XP_File fp) {
nsFile *nsFp = XpToNsFp(fp); // nsnull ok.
PRInt32 readBytes;
nsresult rv;
NS_PRECONDITION( (nsFp != nsnull), "Null pointer");
if (!nsFp)
return NULL;
if (!fileMgr)
return NULL;
rv = fileMgr->FileReadLine( nsFp, &outBuf, &outBufLen, &readBytes);
if (NS_OK != rv) {
return NULL;
}
return outBuf;
}
extern "C" int
NET_I_XP_FileWrite(const char *buf, int bufLen, XP_File fp) {
nsFile *nsFp = XpToNsFp(fp); // nsnull ok.
PRInt32 wroteBytes;
PRInt32 len;
nsresult rv;
if (bufLen < 0)
len = PL_strlen(buf);
else
len = bufLen;
if (!nsFp)
return -1;
if (!fileMgr)
return NULL;
rv = fileMgr->FileWrite(nsFp, buf, &len, &wroteBytes);;
if (rv != NS_OK)
return NULL;
return (int) wroteBytes;
}
extern "C" int
NET_I_XP_FileClose(XP_File fp) {
nsFile *nsFp = XpToNsFp(fp); // nsnull ok.
nsresult rv;
NS_PRECONDITION( (nsFp != nsnull), "Null pointer");
if (!fileMgr) {
if (NS_NewINetFile(&fileMgr, nsnull) != NS_OK) {
return 0;
}
}
rv = fileMgr->CloseFile(nsFp);
if (rv != NS_OK)
return 0;
deleteTrans(nsFp);
fp = nsnull;
return 1;
}

Просмотреть файл

@ -0,0 +1,95 @@
/* -*- 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.
*/
#include "xp.h"
#include "prmem.h"
#include "plstr.h"
#include "intl_csi.h"
INTL_CharSetInfo
LO_GetDocumentCharacterSetInfo(MWContext *context)
{
/* MOZ_FUNCTION_STUB; */
return NULL;
}
void
INTL_CharSetIDToName(int16 csid, char *charset)
{
if (charset) {
PR_ASSERT(INTL_CsidToCharsetNamePt(csid));
if (INTL_CsidToCharsetNamePt(csid))
PL_strcpy(charset,(char *)INTL_CsidToCharsetNamePt(csid));
else
charset = NULL;
}
}
/* INTL_ResourceCharSet(void) */
char *INTL_ResourceCharSet(void)
{
return ("iso-8859-1");
}
/* ----------- CSI CSID ----------- */
void
INTL_SetCSIDocCSID (INTL_CharSetInfo c, int16 doc_csid)
{
return;
}
int16
INTL_GetCSIDocCSID(INTL_CharSetInfo c)
{
return 0;
}
unsigned char *INTL_ConvertLineWithoutAutoDetect(
int16 fromcsid,
int16 tocsid,
unsigned char *pSrc,
uint32 block_size)
{
return NULL;
}
/*
* INTL_DocToWinCharSetID,
* Based on DefaultDocCSID, it determines which Win CSID to use for Display
*/
int16
INTL_DocToWinCharSetID(int16 csid)
{
/* MOZ_FUNCTION_STUB; */
return CS_FE_ASCII;
}
int16
INTL_DefaultDocCharSetID(iDocumentContext context)
{
return CS_DEFAULT;
}
unsigned char *INTL_ConvMailToWinCharCode(
iDocumentContext context,
unsigned char *bit7buff,
uint32 block_size
)
{
return NULL;
}

Просмотреть файл

@ -0,0 +1,888 @@
/* -*- 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.
*/
/* -*- Mode: C; tab-width: 4 -*-
addr.c --- parsing RFC822 addresses.
*/
#include "oldmsg.h"
#include "plstr.h"
#include "prmem.h"
#undef FREEIF
#define FREEIF(obj) do { if (obj) { PR_Free (obj); obj = 0; }} while (0)
extern int MK_OUT_OF_MEMORY;
static int msg_quote_phrase_or_addr (char *address, int32 length,
XP_Bool addr_p);
static int msg_parse_rfc822_addresses (const char *line,
char **names,
char **addresses,
XP_Bool quote_names_p,
XP_Bool quote_addrs_p,
XP_Bool first_only_p);
/* Given a string which contains a list of RFC822 addresses, parses it into
their component names and mailboxes.
The returned value is the number of addresses, or a negative error code;
the names and addresses are returned into the provided pointers as
consecutive null-terminated strings. It is up to the caller to free them.
Note that some of the strings may be zero-length.
Either of the provided pointers may be NULL if the caller is not interested
in those components.
quote_names_p and quote_addrs_p control whether the returned strings should
be quoted as RFC822 entities, or returned in a more human-presentable (but
not necessarily parsable) form.
If first_only_p is true, then only the first element of the list is
returned; we don't bother parsing the rest.
*/
int
msg_parse_rfc822_addresses (const char *line,
char **names,
char **addresses,
XP_Bool quote_names_p,
XP_Bool quote_addrs_p,
XP_Bool first_only_p)
{
uint32 addr_count = 0;
uint32 line_length;
const char *line_end;
const char *this_start;
char *name_buf = 0, *name_out, *name_start;
char *addr_buf = 0, *addr_out, *addr_start;
XP_ASSERT (line);
if (! line)
return -1;
if (names)
*names = 0;
if (addresses)
*addresses = 0;
line_length = XP_STRLEN (line);
if (line_length == 0)
return 0;
name_buf = (char *) XP_ALLOC (line_length * 2 + 10);
if (! name_buf)
return MK_OUT_OF_MEMORY;
addr_buf = (char *) XP_ALLOC (line_length * 2 + 10);
if (! addr_buf)
{
FREEIF (name_buf);
return MK_OUT_OF_MEMORY;
}
line_end = line;
addr_out = addr_buf;
name_out = name_buf;
name_start = name_buf;
addr_start = addr_buf;
this_start = line;
/* Skip over extra whitespace or commas before addresses. */
while (*line_end &&
(XP_IS_SPACE (*line_end) || *line_end == ','))
line_end++;
while (*line_end)
{
uint32 paren_depth = 0;
const char *oparen = 0;
const char *mailbox_start = 0;
const char *mailbox_end = 0;
while (*line_end &&
!(*line_end == ',' &&
paren_depth <= 0 && /* comma is ok inside () */
(!mailbox_start || mailbox_end))) /* comma is ok inside <> */
{
if (*line_end == '\\')
{
line_end++;
if (!*line_end) /* otherwise, we walk off end of line, right? */
break;
}
else if (*line_end == '"')
{
int leave_quotes = 0;
line_end++; /* remove open " */
/* handle '"John.Van Doe"@space.com' case */
if (!mailbox_start)
{
char *end_quote = strchr(line_end, '"');
char *mailbox = end_quote ? strchr(end_quote, '<') : NULL,
*comma = end_quote ? strchr(end_quote, ',') : NULL;
if (!mailbox || (comma && comma < mailbox))
{
leave_quotes = 1; /* no mailbox for this address */
*addr_out++ = '"';
}
}
while (*line_end && *line_end != '"')
{
if (*line_end == '\\')
line_end++;
if (paren_depth == 0)
*addr_out++ = *line_end;
line_end++;
}
if (*line_end) line_end++; /* remove close " */
if (leave_quotes) *addr_out++ = '"';
continue;
}
if (*line_end == '(')
{
if (paren_depth == 0)
oparen = line_end;
paren_depth++;
}
else if (*line_end == '<' && paren_depth == 0)
{
mailbox_start = line_end;
}
else if (*line_end == '>' && mailbox_start && paren_depth == 0)
{
mailbox_end = line_end;
}
else if (*line_end == ')' && paren_depth > 0)
{
paren_depth--;
if (paren_depth == 0)
{
const char *s = oparen + 1;
/* Copy the characters inside the parens onto the
"name" buffer. */
/* Push out some whitespace before the paren, if
there is non-whitespace there already. */
if (name_out > name_start &&
!XP_IS_SPACE (name_out [-1]))
*name_out++ = ' ';
/* Skip leading whitespace. */
while (XP_IS_SPACE (*s) && s < line_end)
s++;
while (s < line_end)
{
if (*s == '\"')
{
/* Strip out " within () unless backslashed */
s++;
continue;
}
if (*s == '\\') /* remove one \ */
s++;
if (XP_IS_SPACE (*s) &&
name_out > name_start &&
XP_IS_SPACE (name_out[-1]))
/* collapse consecutive whitespace */;
else
*name_out++ = *s;
s++;
}
oparen = 0;
}
}
else
{
/* If we're not inside parens or a <mailbox>, tack this
on to the end of the addr_buf. */
if (paren_depth == 0 &&
(!mailbox_start || mailbox_end))
{
/* Eat whitespace at the beginning of the line,
and eat consecutive whitespace within the line. */
if (XP_IS_SPACE (*line_end) &&
(addr_out == addr_start ||
XP_IS_SPACE (addr_out[-1])))
/* skip it */;
else
*addr_out++ = *line_end;
}
}
line_end++;
}
/* Now we have extracted a single address from the comma-separated
list of addresses. The characters have been divided among the
various buffers: the parts inside parens have been placed in the
name_buf, and everything else has been placed in the addr_buf.
Quoted strings and backslashed characters have been `expanded.'
If there was a <mailbox> spec in it, we have remembered where it was.
Copy that on to the addr_buf, replacing what was there, and copy the
characters not inside <> onto the name_buf, replacing what is there
now (which was just the parenthesized parts.) (And we need to do the
quote and backslash hacking again, since we're coming from the
original source.)
Otherwise, we're already done - the addr_buf and name_buf contain
the right data already (de-quoted.)
*/
if (mailbox_end)
{
const char *s;
XP_ASSERT (*mailbox_start == '<');
XP_ASSERT (*mailbox_end == '>');
/* First, copy the name.
*/
name_out = name_start;
s = this_start;
/* Skip leading whitespace. */
while (XP_IS_SPACE (*s) && s < mailbox_start)
s++;
/* Copy up to (not including) the < */
while (s < mailbox_start)
{
if (*s == '\"')
{
s++;
continue;
}
if (*s == '\\')
s++;
if (XP_IS_SPACE (*s) &&
name_out > name_start &&
XP_IS_SPACE (name_out[-1]))
/* collapse consecutive whitespace */;
else
*name_out++ = *s;
s++;
}
/* Trim trailing whitespace. */
while (name_out > name_start && XP_IS_SPACE (name_out[-1]))
name_out--;
/* Push out one space. */
*name_out++ = ' ';
s = mailbox_end+1;
/* Skip whitespace after > */
while (XP_IS_SPACE (*s) && s < line_end)
s++;
/* Copy from just after > to the end. */
while (s < line_end)
{
if (*s == '\"')
{
s++;
continue;
}
if (*s == '\\')
s++;
if (XP_IS_SPACE (*s) &&
name_out > name_start &&
XP_IS_SPACE (name_out[-1]))
/* collapse consecutive whitespace */;
else
*name_out++ = *s;
s++;
}
/* Trim trailing whitespace. */
while (name_out > name_start && XP_IS_SPACE (name_out[-1]))
name_out--;
/* null-terminate. */
*name_out++ = 0;
/* Now, copy the address.
*/
mailbox_start++;
addr_out = addr_start;
s = mailbox_start;
/* Skip leading whitespace. */
while (XP_IS_SPACE (*s) && s < mailbox_end)
s++;
/* Copy up to (not including) the > */
while (s < mailbox_end)
{
if (*s == '\"')
{
s++;
continue;
}
if (*s == '\\')
s++;
*addr_out++ = *s++;
}
/* Trim trailing whitespace. */
while (addr_out > addr_start && XP_IS_SPACE (addr_out[-1]))
addr_out--;
/* null-terminate. */
*addr_out++ = 0;
}
else /* No component of <mailbox> form. */
{
/* Trim trailing whitespace. */
while (addr_out > addr_start && XP_IS_SPACE (addr_out[-1]))
addr_out--;
/* null-terminate. */
*addr_out++ = 0;
/* Trim trailing whitespace. */
while (name_out > name_start && XP_IS_SPACE (name_out[-1]))
name_out--;
/* null-terminate. */
*name_out++ = 0;
/* Attempt to deal with the simple error case of a missing comma.
We can only really deal with this in the non-<> case.
If there is no name, and if the address doesn't contain
double-quotes, but the address does contain whitespace,
then assume that the whitespace is an address delimiter.
*/
if (!name_start || !*name_start)
{
char *s;
char *space = 0;
for (s = addr_start; s < addr_out; s++)
if (*s == '\\')
s++;
else if (!space && XP_IS_SPACE (*s))
space = s;
else if (*s == '"')
{
space = 0;
break;
}
if (space)
{
for (s = space; s < addr_out; s++)
if (*s == '\\')
s++;
else if (XP_IS_SPACE (*s))
{
*s = 0;
*name_out++ = 0;
addr_count++;
}
}
}
}
/* Now re-quote the names and addresses if necessary.
*/
if (quote_names_p && names)
{
int L = name_out - name_start - 1;
L = msg_quote_phrase_or_addr (name_start, L, FALSE);
name_out = name_start + L + 1;
}
if (quote_addrs_p && addresses)
{
int L = addr_out - addr_start - 1;
L = msg_quote_phrase_or_addr (addr_start, L, TRUE);
addr_out = addr_start + L + 1;
}
addr_count++;
if (first_only_p)
/* If we only want the first address, we can stop now. */
break;
if (*line_end)
line_end++;
/* Skip over extra whitespace or commas between addresses. */
while (*line_end &&
(XP_IS_SPACE (*line_end) || *line_end == ','))
line_end++;
this_start = line_end;
name_start = name_out;
addr_start = addr_out;
}
/* Make one more pass through and convert all whitespace characters
to SPC. We could do that in the first pass, but this is simpler. */
{
char *s;
for (s = name_buf; s < name_out; s++)
if (XP_IS_SPACE (*s) && *s != ' ')
*s = ' ';
for (s = addr_buf; s < addr_out; s++)
if (XP_IS_SPACE (*s) && *s != ' ')
*s = ' ';
}
/* #### Should we bother realloc'ing them smaller? */
if (names)
*names = name_buf;
else
PR_Free (name_buf);
if (addresses)
*addresses = addr_buf;
else
PR_Free (addr_buf);
return addr_count;
}
int
MSG_ParseRFC822Addresses (const char *line,
char **names,
char **addresses)
{
return msg_parse_rfc822_addresses(line, names, addresses, TRUE, TRUE, FALSE);
}
/* Given a single mailbox, this quotes the characters in it which need
to be quoted; it writes into `address' and returns a new length.
`address' is assumed to be long enough; worst case, its size will
be (N*2)+2.
*/
static int
msg_quote_phrase_or_addr (char *address, int32 length, XP_Bool addr_p)
{
int quotable_count = 0;
int unquotable_count = 0;
int32 i, new_length;
char *in, *out;
XP_Bool atsign = FALSE;
/* If the entire address is quoted, fall out now. */
if (address[0] == '"' && address[length - 1] == '"')
return length;
for (i = 0, in = address; i < length; i++, in++)
{
if (*in == 0)
return length; /* #### horrible kludge... */
else if (*in == '@' && !atsign && addr_p)
/* Exactly one unquoted at-sign is allowed in an address. */
atsign = TRUE;
else if (*in == '\\' || *in == '"')
/* If the name contains backslashes or quotes, they must be escaped. */
unquotable_count++;
else if (*in >= 127 || *in < 0 ||
*in == '[' || *in == ']' || *in == '(' || *in == ')' ||
*in == '<' || *in == '>' || *in == '@' || *in == ',' ||
*in == ';' || *in == '$')
/* If the name contains control chars or RFC822 specials, it needs to
be enclosed in quotes. Double-quotes and backslashes will be dealt
with seperately.
The ":" character is explicitly not in this list, though RFC822 says
it should be quoted, because that has been seen to break VMS
systems. (Rather, it has been seen that there are Unix SMTP servers
which accept RCPT TO:<host::user> but not RCPT TO:<"host::user"> or
RCPT TO:<host\:\:user>, which is the syntax that VMS/DECNET hosts
use.
For future reference: it is also claimed that some VMS SMTP servers
allow \ quoting but not "" quoting; and that sendmail uses self-
contradcitory quoting conventions that violate both RFCs 821 and
822, so any address quoting on a sendmail system will lose badly.
*/
quotable_count++;
else if (addr_p && *in == ' ')
/* Naked spaces are allowed in names, but not addresses. */
quotable_count++;
else if (!addr_p &&
(*in == '.' || *in == '!' || *in == '$' || *in == '%'))
/* Naked dots are allowed in addresses, but not in names.
The other characters (!$%) are technically allowed in names, but
are surely going to cause someone trouble, so we quote them anyway.
*/
quotable_count++;
}
if (quotable_count == 0 && unquotable_count == 0)
return length;
/* Add 2 to the length for the quotes, plus one for each character
which will need a backslash as well. */
new_length = length + unquotable_count + 2;
/* Now walk through the string backwards (so that we can use the same
block.) First put on the terminating quote, then push out each
character, backslashing as necessary. Then a final quote.
Uh, except, put the second quote just before the last @ if there
is one.
*/
out = address + new_length - 1;
in = address + length - 1;
if (!atsign)
*out-- = '"';
while (out > address)
{
XP_ASSERT(in >= address);
*out-- = *in;
if (atsign && *in == '@')
{
*out-- = '"';
atsign = FALSE;
}
if (*in == '\\' || *in == '"')
{
XP_ASSERT(out > address);
*out-- = '\\';
}
in--;
}
XP_ASSERT(in == address - 1);
XP_ASSERT(out == address);
*out = '"';
address[new_length] = 0;
return new_length;
}
/* Given a name or address that might have been quoted
it will take out the escape and double quotes
The caller is responsible for freeing the resulting
string.
*/
int
MSG_UnquotePhraseOrAddr (char *line, char** lineout)
{
int outlen = 0;
char *lineptr = NULL;
char *tmpLine = NULL;
char *outptr = NULL;
int result = 0;
(*lineout) = NULL;
if (line) {
/* if the first character isnt a double quote
then there is nothing to do */
if (*line != '"')
{
(*lineout) = XP_STRDUP (line);
if (!lineout)
return -1;
else
return 0;
}
/* dont count the first character that is the double quote */
lineptr = line;
lineptr++;
/* count up how many characters we are going to output */
while (*lineptr) {
/* if the character is an '\' then
output the escaped character */
if (*lineptr == '\\')
lineptr++;
outlen++;
lineptr++;
}
tmpLine = (char *) XP_ALLOC (outlen + 1);
if (!tmpLine)
return -1;
XP_MEMSET(tmpLine, 0, outlen);
/* dont output the first double quote */
line++;
lineptr = line;
outptr = (tmpLine);
while ((*lineptr) != '\0') {
/* if the character is an '\' then
output the character that was escaped */
/* if it was part of the quote then don't
output it */
if (*lineptr == '\\' || *lineptr == '"') {
lineptr++;
}
*outptr = *lineptr;
if (*lineptr != '\0') {
outptr++;
lineptr++;
}
}
*outptr = '\0';
if (tmpLine)
(*lineout) = XP_STRDUP (tmpLine);
else
result = -1;
PR_FREEIF (tmpLine);
}
return result;
}
/* Given a string which contains a list of RFC822 addresses, returns a
comma-seperated list of just the `mailbox' portions.
*/
char *
MSG_ExtractRFC822AddressMailboxes (const char *line)
{
char *addrs = 0;
char *result, *s, *out;
uint32 i, size = 0;
int status = MSG_ParseRFC822Addresses (line, 0, &addrs);
if (status <= 0)
return 0;
s = addrs;
for (i = 0; (int) i < status; i++)
{
uint32 j = XP_STRLEN (s);
s += j + 1;
size += j + 2;
}
result = (char*)XP_ALLOC (size + 1);
if (! result)
{
PR_Free (addrs);
return 0;
}
out = result;
s = addrs;
for (i = 0; (int) i < status; i++)
{
uint32 j = XP_STRLEN (s);
XP_MEMCPY (out, s, j);
out += j;
if ((int) (i+1) < status)
{
*out++ = ',';
*out++ = ' ';
}
s += j + 1;
}
*out = 0;
PR_Free (addrs);
return result;
}
/* Given a string which contains a list of RFC822 addresses, returns a
comma-seperated list of just the `user name' portions. If any of
the addresses doesn't have a name, then the mailbox is used instead.
The names are *unquoted* and therefore cannot be re-parsed in any way.
They are, however, nice and human-readable.
*/
char *
MSG_ExtractRFC822AddressNames (const char *line)
{
char *names = 0;
char *addrs = 0;
char *result, *s1, *s2, *out;
uint32 i, size = 0;
int status = msg_parse_rfc822_addresses(line, &names, &addrs, FALSE, FALSE,
FALSE);
if (status <= 0)
return 0;
s1 = names;
s2 = addrs;
for (i = 0; (int) i < status; i++)
{
uint32 j1 = XP_STRLEN (s1);
uint32 j2 = XP_STRLEN (s2);
s1 += j1 + 1;
s2 += j2 + 1;
size += (j1 ? j1 : j2) + 2;
}
result = (char*)XP_ALLOC (size + 1);
if (! result)
{
PR_Free (names);
PR_Free (addrs);
return 0;
}
out = result;
s1 = names;
s2 = addrs;
for (i = 0; (int) i < status; i++)
{
uint32 j1 = XP_STRLEN (s1);
uint32 j2 = XP_STRLEN (s2);
if (j1)
{
XP_MEMCPY (out, s1, j1);
out += j1;
}
else
{
XP_MEMCPY (out, s2, j2);
out += j2;
}
if ((int) (i+1) < status)
{
*out++ = ',';
*out++ = ' ';
}
s1 += j1 + 1;
s2 += j2 + 1;
}
*out = 0;
PR_Free (names);
PR_Free (addrs);
return result;
}
/* Like MSG_ExtractRFC822AddressNames(), but only returns the first name
in the list, if there is more than one.
*/
char *
MSG_ExtractRFC822AddressName (const char *line)
{
char *name = 0;
char *addr = 0;
int status = msg_parse_rfc822_addresses(line, &name, &addr, FALSE, FALSE,
TRUE);
if (status <= 0)
return 0;
/* This can happen if there is an address like "From: foo bar" which
we parse as two addresses (that's a syntax error.) In that case,
we'll return just the first one (the rest is after the NULL.)
XP_ASSERT(status == 1);
*/
if (name && *name)
{
FREEIF(addr);
return name;
}
else
{
FREEIF(name);
return addr;
}
}
static char *
msg_format_rfc822_addresses (const char *names, const char *addrs,
int count, XP_Bool wrap_lines_p)
{
char *result, *out;
const char *s1, *s2;
uint32 i, size = 0;
uint32 column = 10;
if (count <= 0)
return 0;
s1 = names;
s2 = addrs;
for (i = 0; (int) i < count; i++)
{
uint32 j1 = XP_STRLEN (s1);
uint32 j2 = XP_STRLEN (s2);
s1 += j1 + 1;
s2 += j2 + 1;
size += j1 + j2 + 10;
}
result = (char *) XP_ALLOC (size + 1);
if (! result) return 0;
out = result;
s1 = names;
s2 = addrs;
for (i = 0; (int) i < count; i++)
{
char *o;
uint32 j1 = XP_STRLEN (s1);
uint32 j2 = XP_STRLEN (s2);
if (wrap_lines_p && i > 0 &&
(column + j1 + j2 + 3 +
(((int) (i+1) < count) ? 2 : 0)
> 76))
{
if (out > result && out[-1] == ' ')
out--;
*out++ = CR;
*out++ = LF;
*out++ = '\t';
column = 8;
}
o = out;
if (j1)
{
XP_MEMCPY (out, s1, j1);
out += j1;
*out++ = ' ';
*out++ = '<';
}
XP_MEMCPY (out, s2, j2);
out += j2;
if (j1)
*out++ = '>';
if ((int) (i+1) < count)
{
*out++ = ',';
*out++ = ' ';
}
s1 += j1 + 1;
s2 += j2 + 1;
column += (out - o);
}
*out = 0;
return result;
}
/* Given a string which contains a list of RFC822 addresses, returns a new
string with the same data, but inserts missing commas, parses and reformats
it, and wraps long lines with newline-tab.
*/
char *
MSG_ReformatRFC822Addresses (const char *line)
{
char *names = 0;
char *addrs = 0;
char *result;
int status = MSG_ParseRFC822Addresses (line, &names, &addrs);
if (status <= 0)
return 0;
result = msg_format_rfc822_addresses (names, addrs, status, TRUE);
PR_Free (names);
PR_Free (addrs);
return result;
}

377
mailnews/mime/src/oldmsg.c Normal file
Просмотреть файл

@ -0,0 +1,377 @@
/* -*- 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.
*/
/*
* nsmsg.cpp - external libmsg calls
*/
#include "xp.h"
#include "prmem.h"
#include "plstr.h"
extern int MK_OUT_OF_MEMORY;
/* from libmsg/msgutils.c */
int
msg_GrowBuffer (PRUint32 desired_size, PRUint32 element_size, PRUint32 quantum,
char **buffer, PRUint32 *size)
{
if (*size <= desired_size)
{
char *new_buf;
PRUint32 increment = desired_size - *size;
if (increment < quantum) /* always grow by a minimum of N bytes */
increment = quantum;
new_buf = (*buffer
? (char *) PR_Realloc (*buffer, (*size + increment)
* (element_size / sizeof(char)))
: (char *) PR_MALLOC ((*size + increment)
* (element_size / sizeof(char))));
if (! new_buf)
return MK_OUT_OF_MEMORY;
*buffer = new_buf;
*size += increment;
}
return 0;
}
/* The opposite of msg_LineBuffer(): takes small buffers and packs them
up into bigger buffers before passing them along.
Pass in a desired_buffer_size 0 to tell it to flush (for example, in
in the very last call to this function.)
*/
int
msg_ReBuffer (const char *net_buffer, int32 net_buffer_size,
uint32 desired_buffer_size,
char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP,
int32 (*per_buffer_fn) (char *buffer, uint32 buffer_size,
void *closure),
void *closure)
{
int status = 0;
if (desired_buffer_size >= (*buffer_sizeP))
{
status = msg_GrowBuffer (desired_buffer_size, sizeof(char), 1024,
bufferP, buffer_sizeP);
if (status < 0) return status;
}
do
{
int32 size = *buffer_sizeP - *buffer_fpP;
if (size > net_buffer_size)
size = net_buffer_size;
if (size > 0)
{
XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, size);
(*buffer_fpP) += size;
net_buffer += size;
net_buffer_size -= size;
}
if (*buffer_fpP > 0 &&
*buffer_fpP >= desired_buffer_size)
{
status = (*per_buffer_fn) ((*bufferP), (*buffer_fpP), closure);
*buffer_fpP = 0;
if (status < 0) return status;
}
}
while (net_buffer_size > 0);
return 0;
}
/* from libmsg/msgutils.c */
static int
msg_convert_and_send_buffer(char* buf, int length, PRBool convert_newlines_p,
PRInt32 (*per_line_fn) (char *line,
PRUint32 line_length,
void *closure),
void *closure)
{
/* Convert the line terminator to the native form.
*/
char* newline;
PR_ASSERT(buf && length > 0);
if (!buf || length <= 0) return -1;
newline = buf + length;
PR_ASSERT(newline[-1] == CR || newline[-1] == LF);
if (newline[-1] != CR && newline[-1] != LF) return -1;
if (!convert_newlines_p)
{
}
#if (LINEBREAK_LEN == 1)
else if ((newline - buf) >= 2 &&
newline[-2] == CR &&
newline[-1] == LF)
{
/* CRLF -> CR or LF */
buf [length - 2] = LINEBREAK[0];
length--;
}
else if (newline > buf + 1 &&
newline[-1] != LINEBREAK[0])
{
/* CR -> LF or LF -> CR */
buf [length - 1] = LINEBREAK[0];
}
#else
else if (((newline - buf) >= 2 && newline[-2] != CR) ||
((newline - buf) >= 1 && newline[-1] != LF))
{
/* LF -> CRLF or CR -> CRLF */
length++;
buf[length - 2] = LINEBREAK[0];
buf[length - 1] = LINEBREAK[1];
}
#endif
return (*per_line_fn)(buf, length, closure);
}
/* from libmsg/msgutils.c */
int
msg_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size,
char **bufferP, PRUint32 *buffer_sizeP, PRUint32 *buffer_fpP,
PRBool convert_newlines_p,
PRInt32 (*per_line_fn) (char *line, PRUint32 line_length,
void *closure),
void *closure)
{
int status = 0;
if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR &&
net_buffer_size > 0 && net_buffer[0] != LF) {
/* The last buffer ended with a CR. The new buffer does not start
with a LF. This old buffer should be shipped out and discarded. */
PR_ASSERT(*buffer_sizeP > *buffer_fpP);
if (*buffer_sizeP <= *buffer_fpP) return -1;
status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP,
convert_newlines_p,
per_line_fn, closure);
if (status < 0) return status;
*buffer_fpP = 0;
}
while (net_buffer_size > 0)
{
const char *net_buffer_end = net_buffer + net_buffer_size;
const char *newline = 0;
const char *s;
for (s = net_buffer; s < net_buffer_end; s++)
{
/* Move forward in the buffer until the first newline.
Stop when we see CRLF, CR, or LF, or the end of the buffer.
*But*, if we see a lone CR at the *very end* of the buffer,
treat this as if we had reached the end of the buffer without
seeing a line terminator. This is to catch the case of the
buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n".
*/
if (*s == CR || *s == LF)
{
newline = s;
if (newline[0] == CR)
{
if (s == net_buffer_end - 1)
{
/* CR at end - wait for the next character. */
newline = 0;
break;
}
else if (newline[1] == LF)
/* CRLF seen; swallow both. */
newline++;
}
newline++;
break;
}
}
/* Ensure room in the net_buffer and append some or all of the current
chunk of data to it. */
{
const char *end = (newline ? newline : net_buffer_end);
PRUint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1;
if (desired_size >= (*buffer_sizeP))
{
status = msg_GrowBuffer (desired_size, sizeof(char), 1024,
bufferP, buffer_sizeP);
if (status < 0) return status;
}
XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer));
(*buffer_fpP) += (end - net_buffer);
}
/* Now *bufferP contains either a complete line, or as complete
a line as we have read so far.
If we have a line, process it, and then remove it from `*bufferP'.
Then go around the loop again, until we drain the incoming data.
*/
if (!newline)
return 0;
status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP,
convert_newlines_p,
per_line_fn, closure);
if (status < 0) return status;
net_buffer_size -= (newline - net_buffer);
net_buffer = newline;
(*buffer_fpP) = 0;
}
return 0;
}
struct msg_rebuffering_stream_data
{
uint32 desired_size;
char *buffer;
uint32 buffer_size;
uint32 buffer_fp;
NET_StreamClass *next_stream;
};
static int32
msg_rebuffering_stream_write_next_chunk (char *buffer, uint32 buffer_size,
void *closure)
{
struct msg_rebuffering_stream_data *sd =
(struct msg_rebuffering_stream_data *) closure;
XP_ASSERT (sd);
if (!sd) return -1;
if (!sd->next_stream) return -1;
return (*sd->next_stream->put_block) (sd->next_stream->data_object,
buffer, buffer_size);
}
static int
msg_rebuffering_stream_write_chunk (void *stream,
const char* net_buffer,
int32 net_buffer_size)
{
struct msg_rebuffering_stream_data *sd =
(struct msg_rebuffering_stream_data *) stream;
XP_ASSERT (sd);
if (!sd) return -1;
return msg_ReBuffer (net_buffer, net_buffer_size,
sd->desired_size,
&sd->buffer, &sd->buffer_size, &sd->buffer_fp,
msg_rebuffering_stream_write_next_chunk,
sd);
}
XP_Bool ValidateDocData(MWContext *window_id)
{
printf("ValidateDocData not implemented, stubbed in webshell/tests/viewer/nsStubs.cpp\n");
return PR_TRUE;
}
static void
msg_rebuffering_stream_abort (void *stream, int status)
{
struct msg_rebuffering_stream_data *sd =
(struct msg_rebuffering_stream_data *) stream;
if (!sd) return;
PR_FREEIF (sd->buffer);
if (sd->next_stream)
{
if (ValidateDocData(sd->next_stream->window_id)) /* otherwise doc_data is gone ! */
(*sd->next_stream->abort) (sd->next_stream->data_object, status);
PR_Free (sd->next_stream);
}
PR_Free (sd);
}
static void
msg_rebuffering_stream_complete (void *stream)
{
struct msg_rebuffering_stream_data *sd =
(struct msg_rebuffering_stream_data *) stream;
if (!sd) return;
sd->desired_size = 0;
msg_rebuffering_stream_write_chunk (stream, "", 0);
PR_FREEIF (sd->buffer);
if (sd->next_stream)
{
(*sd->next_stream->complete) (sd->next_stream->data_object);
PR_Free (sd->next_stream);
}
PR_Free (sd);
}
static unsigned int
msg_rebuffering_stream_write_ready (void *stream)
{
struct msg_rebuffering_stream_data *sd =
(struct msg_rebuffering_stream_data *) stream;
if (sd && sd->next_stream)
return ((*sd->next_stream->is_write_ready)
(sd->next_stream->data_object));
else
return (MAX_WRITE_READY);
}
NET_StreamClass *
msg_MakeRebufferingStream (NET_StreamClass *next_stream,
URL_Struct *url,
MWContext *context)
{
NET_StreamClass *stream;
struct msg_rebuffering_stream_data *sd;
XP_ASSERT (next_stream);
stream = XP_NEW (NET_StreamClass);
if (!stream) return 0;
sd = XP_NEW (struct msg_rebuffering_stream_data);
if (! sd)
{
PR_Free (stream);
return 0;
}
XP_MEMSET (sd, 0, sizeof(*sd));
XP_MEMSET (stream, 0, sizeof(*stream));
sd->next_stream = next_stream;
sd->desired_size = 10240;
stream->name = "ReBuffering Stream";
stream->complete = msg_rebuffering_stream_complete;
stream->abort = msg_rebuffering_stream_abort;
stream->put_block = msg_rebuffering_stream_write_chunk;
stream->is_write_ready = msg_rebuffering_stream_write_ready;
stream->data_object = sd;
stream->window_id = context;
return stream;
}

181
mailnews/mime/src/oldmsg.h Normal file
Просмотреть файл

@ -0,0 +1,181 @@
/* -*- 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.
*/
/*
msg.h --- internal defs for the msg library
*/
#ifndef _MSG_H_
#define _MSG_H_
#include "xp.h"
#include "msgcom.h"
#include "msgnet.h"
#include "msgutils.h"
#include "xpgetstr.h"
#ifdef XP_CPLUSPLUS
class MessageDBView;
class MSG_SendPart;
#endif
#define MANGLE_INTERNAL_ENVELOPE_LINES /* We always need to do this, for now */
#undef FIXED_SEPARATORS /* this doesn't work yet */
#define EMIT_CONTENT_LENGTH /* Experimental; and anyway, we only
emit it, we don't parse it, so this
is only the first step. */
/* hack - this string gets appended to the beginning of an attachment field
during a forward quoted operation */
#define MSG_FORWARD_COOKIE "$forward_quoted$"
/* The PRINTF macro is for debugging messages of unusual events (summary */
/* files out of date or invalid or the like. It's so that as I use the mail */
/* to actually read my e-mail, I can look at the shell output whenever */
/* something unusual happens so I can get some clues as to what's going on. */
/* Please don't remove any PRINTF calls you see, and be sparing of adding */
/* any additional ones. Thanks. - Terry */
#ifdef DEBUG
#define PRINTF(msg) XP_Trace msg
#else
#define PRINTF(msg)
#endif
#ifdef FREEIF
#undef FREEIF
#endif
#define FREEIF(obj) do { if (obj) { XP_FREE (obj); obj = 0; }} while (0)
/* The Netscape-specific header fields that we use for storing our
various bits of state in mail folders.
*/
#define X_MOZILLA_STATUS "X-Mozilla-Status"
#define X_MOZILLA_STATUS_FORMAT X_MOZILLA_STATUS ": %04.4x"
#define X_MOZILLA_STATUS_LEN /*1234567890123456*/ 16
#define X_MOZILLA_STATUS2 "X-Mozilla-Status2"
#define X_MOZILLA_STATUS2_FORMAT X_MOZILLA_STATUS2 ": %08.8x"
#define X_MOZILLA_STATUS2_LEN /*12345678901234567*/ 17
#define X_MOZILLA_DRAFT_INFO "X-Mozilla-Draft-Info"
#define X_MOZILLA_DRAFT_INFO_LEN /*12345678901234567890*/ 20
#define X_MOZILLA_NEWSHOST "X-Mozilla-News-Host"
#define X_MOZILLA_NEWSHOST_LEN /*1234567890123456789*/ 19
#define X_UIDL "X-UIDL"
#define X_UIDL_LEN /*123456*/ 6
#define CONTENT_LENGTH "Content-Length"
#define CONTENT_LENGTH_LEN /*12345678901234*/ 14
/* Provide a common means of detecting empty lines in a message. i.e. to detect the end of headers among other things...*/
#define EMPTY_MESSAGE_LINE(buf) (buf[0] == CR || buf[0] == LF || buf[0] == '\0')
typedef int32 MsgChangeCookie; /* used to unregister change notification */
/* The three ways the list of newsgroups can be pruned.
*/
typedef enum
{
MSG_ShowAll,
MSG_ShowSubscribed,
MSG_ShowSubscribedWithArticles
} MSG_NEWSGROUP_DISPLAY_STYLE;
/* The three ways to deliver a message.
*/
typedef enum
{
MSG_DeliverNow,
MSG_QueueForLater,
MSG_SaveAs,
MSG_SaveAsDraft,
MSG_SaveAsTemplate
} MSG_Deliver_Mode;
/* A little enum for things we'd like to learn lazily.
* e.g. displaying recipients for this pane? Yes we are,
* no we're not, haven't figured it out yet
*/
typedef enum
{
msg_No,
msg_Yes,
msg_DontKnow
} msg_YesNoDontKnow;
/* The MSG_REPLY_TYPE shares the same space as MSG_CommandType, to avoid
possible weird errors, but is restricted to the `composition' commands
(MSG_ReplyToSender through MSG_ForwardMessage.)
*/
typedef MSG_CommandType MSG_REPLY_TYPE;
/* The list of all message flags to not write to disk. */
#define MSG_FLAG_RUNTIME_ONLY (MSG_FLAG_ELIDED)
/* ===========================================================================
Structures.
===========================================================================
*/
/* Used for the various things that parse RFC822 headers...
*/
typedef struct message_header
{
const char *value; /* The contents of a header (after ": ") */
int32 length; /* The length of the data (it is not NULL-terminated.) */
} message_header;
XP_BEGIN_PROTOS
/* we'll need this for localized folder names */
extern int MK_MSG_INBOX_L10N_NAME;
extern int MK_MSG_OUTBOX_L10N_NAME; /* win16 variations are in allxpstr.h */
extern int MK_MSG_OUTBOX_L10N_NAME_OLD;
extern int MK_MSG_TRASH_L10N_NAME;
extern int MK_MSG_DRAFTS_L10N_NAME;
extern int MK_MSG_SENT_L10N_NAME;
extern int MK_MSG_TEMPLATES_L10N_NAME;
#define INBOX_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_INBOX_L10N_NAME)
#define QUEUE_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_OUTBOX_L10N_NAME)
#define QUEUE_FOLDER_NAME_OLD MSG_GetSpecialFolderName(MK_MSG_OUTBOX_L10N_NAME_OLD)
#define TRASH_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_TRASH_L10N_NAME)
#define DRAFTS_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_DRAFTS_L10N_NAME)
#define SENT_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_SENT_L10N_NAME)
#define TEMPLATES_FOLDER_NAME MSG_GetSpecialFolderName(MK_MSG_TEMPLATES_L10N_NAME)
#ifdef XP_OS2
#define INBOX_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_INBOX_L10N_NAME)
#define QUEUE_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_OUTBOX_L10N_NAME)
#define QUEUE_FOLDER_PRETTY_NAME_OLD MSG_GetSpecialFolderPrettyName(MK_MSG_OUTBOX_L10N_NAME_OLD)
#define TRASH_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_TRASH_L10N_NAME)
#define DRAFTS_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_DRAFTS_L10N_NAME)
#define SENT_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_SENT_L10N_NAME)
#define TEMPLATES_FOLDER_PRETTY_NAME MSG_GetSpecialFolderPrettyName(MK_MSG_TEMPLATES_L10N_NAME)
#endif
XP_END_PROTOS
#endif /* !_MSG_H_ */

1346
mailnews/mime/src/oldnet.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,161 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.
*/
#ifndef __nsINetFile_h
#define __nsINetFile_h
#include "nsISupports.h"
#include "nsString.h"
#include "prio.h"
// These defines are for temporary use until we get a real dir manager.
#define USER_DIR_TOK "%USER%"
#define CACHE_DIR_TOK "%CACHE_D%"
#define DEF_DIR_TOK "%DEF_D%"
#define COOKIE_FILE_TOK "%COOKIE_F%"
#ifdef XP_PC
#define COOKIE_FILE "cookies.txt"
#else
#define COOKIE_FILE "cookies"
#endif
#ifdef CookieManagement
#define COOKIE_PERMISSION_FILE_TOK "%COOKIE_PERMISSION_F%"
#ifdef XP_PC
#define COOKIE_PERMISSION_FILE "cookperm.txt"
#else
#define COOKIE_PERMISSION_FILE "cookperm"
#endif
#endif
#ifdef SingleSignon
#define SIGNON_FILE_TOK "%SIGNON_F%"
#ifdef XP_PC
#define SIGNON_FILE "signons.txt"
#else
#define SIGNON_FILE "signons"
#endif
#endif
#define CACHE_DB_F_TOK "%CACHE_DB_F%"
#define CACHE_DB_FILE "fat.db"
// {9E04ADC2-2B1D-11d2-B6EB-00805F8A2676}
#define NS_INETFILE_IID \
{ 0x9e04adc2, 0x2b1d, 0x11d2, \
{0xb6, 0xeb, 0x00, 0x80, 0x5f, 0x8a, 0x26, 0x76} }
// Represents a file for use with nsINetFile routines.
typedef struct _nsFile {
PRFileDesc *fd;
} nsFile;
// Represents a directory for use with nsINetFile routines.
typedef struct _nsDir {
PRDir *dir;
} nsDir;
// Open flags. Used with nsINetFile::OpenFile.
typedef enum {
nsRead = 1,
nsWrite = 2,
nsReadWrite = 3,
nsReadBinary = 5,
nsWriteBinary = 6,
nsReadWriteBinary = 7,
nsOverWrite = 8
} nsFileMode;
class nsINetFile: public nsISupports {
public:
/*
* File methods
*/
// Convert a generic file names into a platform file path
// Currently generic file location information is prepended to the
// begining of aName. For example, if I wanted to open the cookie file,
// I'd pass in "%USER%\cookies.txt . aName is platform specific.
NS_IMETHOD GetFilePath(const char *aName, char **aRes) = 0;
NS_IMETHOD GetTemporaryFilePath(const char *aName, char **aRes) = 0;
NS_IMETHOD GetUniqueFilePath(const char *aName, char **aRes) = 0;
NS_IMETHOD GetCacheFileName(char *aDirTok, char **aRes) = 0;
// Open a file
NS_IMETHOD OpenFile(const char *aPath, nsFileMode aMode,
nsFile** aRes) = 0;
// Close a file
NS_IMETHOD CloseFile(nsFile* aFile) = 0;
// Read a file
NS_IMETHOD FileRead(nsFile *aFile, char **aBuf,
PRInt32 *aBuflen,
PRInt32 *aBytesRead) = 0;
NS_IMETHOD FileReadLine(nsFile *aFile, char **aBuf,
PRInt32 *aBuflen,
PRInt32 *aBytesRead) = 0;
// Write a file
NS_IMETHOD FileWrite(nsFile *aFile, const char *aBuf,
PRInt32 *aLen,
PRInt32 *aBytesWritten) = 0;
// Sync a file with disk
NS_IMETHOD FileSync(nsFile *aFile) = 0;
// Remove a file
NS_IMETHOD FileRemove(const char *aPath) = 0;
// Rename a file
NS_IMETHOD FileRename(const char *aPathOld, const char *aPathNew) = 0;
/*
* Directory Methods
*/
// Open a directory
NS_IMETHOD OpenDir(const char *aPath, nsDir** aRes) = 0;
// Close a directory
NS_IMETHOD CloseDir(nsDir *aDir) = 0;
// Create a directory
NS_IMETHOD CreateDir(const char *aPath, PRBool aRecurse) = 0;
// Assocaite a token with a directory.
NS_IMETHOD SetDirectory(const char *aToken, const char *aDir) = 0;
// Associate a filename with a token, and optionally a dir token.
NS_IMETHOD SetFileAssoc(const char *aToken, const char *aFile, const char *aDirToken) = 0;
};
/**
* Create an instance of the INetFile
*
*/
extern "C" NS_NET nsresult NS_NewINetFile(nsINetFile** aInstancePtrResult,
nsISupports* aOuter);
extern "C" NS_NET nsresult NS_InitINetFile(void);
extern "C" NS_NET nsresult NS_ShutdownINetFile();
#endif __nsINetFile_h

1617
mailnews/mime/src/oldvcc.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1590
mailnews/mime/src/oldvobj.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

256
mailnews/mime/src/oldxp.c Normal file
Просмотреть файл

@ -0,0 +1,256 @@
/* -*- 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.
*/
/*
* i18n.c - I18N depencencies
*/
#include "xp.h"
#include "prmem.h"
#include "plstr.h"
void *
FE_SetTimeout(TimeoutCallbackFunction func, void * closure, uint32 msecs)
{
return NULL;
}
/* RICHIE - THIS HACK MUST GO!!! - INCLUDING FILE TO TRY TO KEEP DIRECTORY CLEAN */
#include "..\..\..\lib\xp\xp_time.c"
char
*XP_GetStringForHTML (int i, PRInt16 wincsid, char* english)
{
return english;
}
char *XP_AppendStr(char *in, const char *append)
{
int alen, inlen;
alen = PL_strlen(append);
if (in) {
inlen = PL_strlen(in);
in = (char*) PR_Realloc(in,inlen+alen+1);
if (in) {
memcpy(in+inlen, append, alen+1);
}
} else {
in = (char*) PR_Malloc(alen+1);
if (in) {
memcpy(in, append, alen+1);
}
}
return in;
}
#define MOZ_FUNCTION_STUB
char *
WH_TempName(XP_FileType type, const char * prefix)
{
MOZ_FUNCTION_STUB;
return NULL;
}
/*
// The caller is responsible for PR_Free()ing the return string
*/
PUBLIC char *
WH_FileName (const char *NetName, XP_FileType type)
{
MOZ_FUNCTION_STUB;
if (type == xpHTTPCookie) {
#ifdef XP_PC
return PL_strdup("cookies.txt");
#else
return PL_strdup("cookies");
#endif
} else if (type == xpCacheFAT) {
;// sprintf(newName, "%s\\fat.db", (const char *)theApp.m_pCacheDir);
} else if ((type == xpURL) || (type == xpFileToPost)) {
/*
* This is the body of XP_NetToDosFileName(...) which is implemented
* for Windows only in fegui.cpp
*/
XP_Bool bChopSlash = FALSE;
char *p, *newName;
if(!NetName)
return NULL;
// If the name is only '/' or begins '//' keep the
// whole name else strip the leading '/'
if(NetName[0] == '/')
bChopSlash = TRUE;
// save just / as a path
if(NetName[0] == '/' && NetName[1] == '\0')
bChopSlash = FALSE;
// spanky Win9X path name
if(NetName[0] == '/' && NetName[1] == '/')
bChopSlash = FALSE;
if(bChopSlash)
newName = PL_strdup(&(NetName[1]));
else
newName = PL_strdup(NetName);
if(!newName)
return NULL;
if( newName[1] == '|' )
newName[1] = ':';
for(p = newName; *p; p++){
if( *p == '/' )
*p = '\\';
}
return(newName);
}
return NULL;
}
PUBLIC XP_File
XP_FileOpen(const char * name, XP_FileType type, const XP_FilePerm perm)
{
MOZ_FUNCTION_STUB;
switch (type) {
case xpURL:
case xpFileToPost:
case xpHTTPCookie:
{
XP_File fp;
char* newName = WH_FileName(name, type);
if (!newName) return NULL;
fp = fopen(newName, (char *) perm);
PR_Free(newName);
return fp;
}
default:
break;
}
return NULL;
}
PUBLIC XP_Dir
XP_OpenDir(const char * name, XP_FileType type)
{
MOZ_FUNCTION_STUB;
return NULL;
}
PUBLIC void
XP_CloseDir(XP_Dir dir)
{
MOZ_FUNCTION_STUB;
}
PUBLIC XP_DirEntryStruct *
XP_ReadDir(XP_Dir dir)
{
MOZ_FUNCTION_STUB;
return NULL;
}
PUBLIC int
XP_FileRemove(const char * name, XP_FileType type)
{
if (PR_Delete(name) == PR_SUCCESS)
return 0;
return -1;
}
/* If you want to trace netlib, set this to 1, or use CTRL-ALT-T
* stroke (preferred method) to toggle it on and off */
int MKLib_trace_flag=0;
/* Used by NET_NTrace() */
PRIVATE void net_Trace(char *msg) {
#if defined(WIN32) && defined(DEBUG)
OutputDebugString(msg);
OutputDebugString("\n");
#else
PR_LogPrint(msg);
#endif
}
/* #define'd in mktrace.h to TRACEMSG */
void _MK_TraceMsg(char *fmt, ...) {
va_list ap;
char buf[512];
va_start(ap, fmt);
PR_vsnprintf(buf, sizeof(buf), fmt, ap);
net_Trace(buf);
}
PUBLIC int
XP_Stat(const char * name, XP_StatStruct * info, XP_FileType type)
{
int result = -1;
MOZ_FUNCTION_STUB;
switch (type) {
case xpURL:
case xpFileToPost: {
char *newName = WH_FileName(name, type);
if (!newName) return -1;
result = _stat( newName, info );
PR_Free(newName);
break;
}
default:
break;
}
return result;
}
char *XP_STRNCPY_SAFE (char *dest, const char *src, size_t destLength)
{
char *result = strncpy (dest, src, --destLength);
dest[destLength] = '\0';
return result;
}
int
RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
{
size_t i;
char *ptr = (char *) dest;
for (i=0; i<len; i++)
{
*(ptr+i) = 1;
}
return 0;
}