зеркало из https://github.com/mozilla/gecko-dev.git
Adding modular libMIME to the tree.
This commit is contained in:
Родитель
74ac3d86af
Коммит
60423f2184
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_ */
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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.
|
||||
*/
|
|
@ -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 "<", 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, "&"); out += PL_strlen (out);
|
||||
}
|
||||
else if (*this_start == '>')
|
||||
{
|
||||
PL_strcpy (out, ">"); out += PL_strlen (out);
|
||||
}
|
||||
else if (enriched_p &&
|
||||
this_start < data_end + 1 &&
|
||||
this_start[0] == '<' &&
|
||||
this_start[1] == '<')
|
||||
{
|
||||
PL_strcpy (out, "<"); 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 = "<", 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_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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 "<", 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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_ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче