gecko-dev/lib/libi18n/net_junk.c

344 строки
9.7 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* net_junk.c */
/*#include "intlpriv.h"*/
#include "xp.h"
#include "intl_csi.h"
#include "libi18n.h"
#include "net_junk.h"
#include "libmocha.h"
MODULE_PRIVATE int16 PeekMetaCharsetTag (char *, uint32);
MODULE_PRIVATE int16 DetectUCS2 (CCCDataObject, unsigned char *, int32);
typedef struct {
Stream *current_stream;
Stream *next_stream;
CCCDataObject obj;
} NetStreamData;
extern unsigned char *One2OneCCC(CCCDataObject,unsigned char *,int32);
PRIVATE int net_AutoCharCodeConv (NET_StreamClass *stream, const char *s, int32 l);
PRIVATE int net_1to1CCC (NET_StreamClass *stream, const unsigned char *s, int32 l);
PRIVATE void net_CvtCharCodeComplete (NET_StreamClass *stream)
{
NetStreamData *nsd=stream->data_object;
unsigned char *uncvtbuf;
uncvtbuf = INTL_GetCCCUncvtbuf(nsd->obj);
/* pass downstream any uncoverted characters */
if (uncvtbuf[0] != '\0')
(*nsd->next_stream->put_block)(nsd->next_stream,
(const char *)uncvtbuf, strlen((char *)uncvtbuf));
(*nsd->next_stream->complete)(nsd->next_stream);
XP_FREE(nsd->next_stream);
XP_FREE(nsd->obj);
XP_FREE(nsd);
return;
}
PRIVATE void net_CvtCharCodeAbort (NET_StreamClass *stream, int status)
{
NetStreamData *nsd=stream->data_object;
(*nsd->next_stream->abort)(nsd->next_stream, status);
XP_FREE(nsd->next_stream);
XP_FREE(nsd->obj);
XP_FREE(nsd);
return;
}
PRIVATE int
net_CharCodeConv( NET_StreamClass *stream,
const unsigned char *buf, /* buffer for conversion */
int32 bufsz) /* buffer size in bytes */
{
NetStreamData *nsd=stream->data_object;
unsigned char *tobuf;
int rv;
CCCFunc cvtfunc;
cvtfunc = INTL_GetCCCCvtfunc(nsd->obj);
tobuf = (unsigned char *)cvtfunc(nsd->obj, buf, bufsz);
if (tobuf) {
rv = (*nsd->next_stream->put_block) (nsd->next_stream,
(const char *)tobuf, INTL_GetCCCLen(nsd->obj));
if (tobuf != buf)
XP_FREE(tobuf);
return(rv);
} else {
return(INTL_GetCCCRetval(nsd->obj));
}
}
/* Null Char Code Conversion module -- pass unconverted data downstream */
/* PRIVATE */ int
net_NoCharCodeConv (NET_StreamClass *stream, const char *s, int32 l)
{
NetStreamData*nsd=stream->data_object;
return((*nsd->next_stream->put_block)(nsd->next_stream,s,l));
}
PRIVATE int
net_AutoCharCodeConv (NET_StreamClass *stream, const char *s, int32 l)
{
NetStreamData*nsd=stream->data_object;
int16 doc_csid;
unsigned char *tobuf = NULL;
int rv;
CCCFunc cvtfunc;
cvtfunc = INTL_GetCCCCvtfunc(nsd->obj);
/* for debugging -- erik */
#if 0
{
static FILE *f = NULL;
if (!f)
{
f = fopen("/tmp/zzz", "w");
}
if (f && s && (l > 0))
{
(void) fwrite(s, 1, l, f);
}
}
#endif /* 0 */
if (cvtfunc != NULL)
tobuf = (unsigned char *)cvtfunc(nsd->obj, (unsigned char *)s, l);
else
{
/* Look at the first block and see if we determine
* what the charset is from that block.
*/
/* Somehow NET_PlainTextConverter() put a "<plaintext>" in the
first block. Try to bypass that block
We need this so we can detect UCS2 for the NT UCS2 plantext
*/
if((l == 11) && (strncmp(s, "<plaintext>", 11)==0))
{
return((*nsd->next_stream->put_block)(nsd->next_stream,s,l));
}
/* check for unicode (ucs2) */
doc_csid = DetectUCS2(nsd->obj, (unsigned char *)s, l);
if(doc_csid == CS_DEFAULT)
{
doc_csid = PeekMetaCharsetTag((char *)s, l) ;
if (doc_csid == CS_ASCII) /* the header said ascii. */
{
nsd->current_stream->put_block = (MKStreamWriteFunc) net_NoCharCodeConv;
return((*nsd->next_stream->put_block)(nsd->next_stream,s,l));
}
}
/* We looked at the first block but did not determine
* what the charset is. Install the default converter
* now. It could be a standard or an auto-detecting converter.
*/
if (doc_csid != CS_DEFAULT)
{
(void) INTL_GetCharCodeConverter(doc_csid, 0, nsd->obj);
INTL_CallCCCReportAutoDetect(nsd->obj, doc_csid);
}
else
(void) INTL_GetCharCodeConverter(INTL_GetCCCDefaultCSID(nsd->obj),0,nsd->obj);
cvtfunc = INTL_GetCCCCvtfunc(nsd->obj);
/* If no conversion needed, change put_block module for successive
* data blocks. For current data block, return unmodified buffer.
*/
if (cvtfunc == NULL)
{
return((*nsd->next_stream->put_block)(nsd->next_stream,s,l));
}
/* For initial block, must call converter directly. Success calls
* to the converter will be called directly from net_CharCodeConv()
*/
}
if (tobuf == NULL)
tobuf = (unsigned char *)cvtfunc(nsd->obj, (unsigned char *)s, l);
if (tobuf) {
rv = (*nsd->next_stream->put_block) (nsd->next_stream,
(const char *)tobuf, INTL_GetCCCLen(nsd->obj));
if (tobuf != (unsigned char*)s)
XP_FREE(tobuf);
return(rv);
} else {
return(INTL_GetCCCRetval(nsd->obj));
}
}
/* One-byte-to-one-byte Char Code Conversion module.
* Table driven. Table provided by FE.
*/
PRIVATE int
net_1to1CCC (NET_StreamClass *stream, const unsigned char *s, int32 l)
{
NetStreamData *nsd=stream->data_object;
(void) One2OneCCC (nsd->obj, (unsigned char *)s, l);
return((*nsd->next_stream->put_block)(nsd->next_stream,
(const char *)s, INTL_GetCCCLen(nsd->obj)));
}
/*
* We are always ready for writing, but the next stream might not
* be so, since we aren't willing to buffer, tell netlib the
* next stream's buffer size
*/
PRIVATE unsigned int net_CvtCharCodeWriteReady (NET_StreamClass *stream)
{
NetStreamData *nsd=stream->data_object;
return ((*nsd->next_stream->is_write_ready)(nsd->next_stream));
}
PRIVATE void
net_report_autodetect(void *closure, CCCDataObject obj, uint16 doc_csid)
{
NetStreamData *nsd = (NetStreamData *)closure;
iDocumentContext doc_context = nsd->current_stream->window_id;
CCCFunc cvtfunc = INTL_GetCCCCvtfunc(obj);
INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(doc_context);
INTL_SetCSIDocCSID(c, doc_csid);
/* I hope it is okay, to set the win_csid */
INTL_SetCSIWinCSID(c, INTL_GetCCCToCSID(obj));
if (cvtfunc == NULL)
nsd->current_stream->put_block = (MKStreamWriteFunc) net_NoCharCodeConv;
}
PUBLIC Stream *
INTL_ConvCharCode (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *mwcontext)
{
NetStreamData *nsd;
CCCDataObject obj;
Stream *stream;
iDocumentContext doc_context = (iDocumentContext)mwcontext;
INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(doc_context);
XP_Bool is_metacharset_reload;
uint16 default_doc_csid = INTL_DefaultDocCharSetID(mwcontext);
/*
Should this be ?
uint16 default_doc_csid = FE_DefaultDocCharSetID(mwcontext);
*/
TRACEMSG(("Setting up display stream. Have URL: %s\n", URL_s->address));
stream = XP_NEW_ZAP(Stream);
if(stream == NULL)
return(NULL);
stream->name = "CharCodeConverter";
stream->complete = (MKStreamCompleteFunc) net_CvtCharCodeComplete;
stream->abort = (MKStreamAbortFunc) net_CvtCharCodeAbort;
stream->is_write_ready = (MKStreamWriteReadyFunc) net_CvtCharCodeWriteReady;
stream->window_id = doc_context;
/* initialize the doc_csid (etc.) unless if this is a reload caused by meta charset */
if ((NET_RESIZE_RELOAD == URL_s->resize_reload)
&& (METACHARSET_FORCERELAYOUT == INTL_GetCSIRelayoutFlag(c)))
is_metacharset_reload = TRUE;
else
is_metacharset_reload = FALSE;
INTL_CSIInitialize(c, is_metacharset_reload, URL_s->charset,
mwcontext->type, default_doc_csid);
obj = INTL_CreateDocumentCCC(c, default_doc_csid);
if (obj == NULL) {
XP_FREE(stream);
return(NULL);
}
nsd = XP_NEW_ZAP(NetStreamData);
if(nsd == NULL) {
XP_FREE(stream);
XP_FREE(obj);
return(NULL);
}
nsd->current_stream = stream;
nsd->obj = obj;
stream->data_object = nsd; /* document info object */
INTL_SetCCCReportAutoDetect(obj, net_report_autodetect, nsd);
if (INTL_GetCSIDocCSID(c) == CS_DEFAULT || INTL_GetCSIDocCSID(c) == CS_UNKNOWN)
{
/* we know the default converter but do not install it yet.
* Instead wait until the first block and see if we can determine
* what the actual charset is from http/meta tags or from the
* first block. By delaying we can avoid a reload if
* we get a different charset from http/meta tag or the first block.
*/
stream->put_block = (MKStreamWriteFunc) net_AutoCharCodeConv;
}
else
{
if (INTL_GetCCCCvtfunc(obj) == NULL)
stream->put_block = (MKStreamWriteFunc) net_NoCharCodeConv;
else if (INTL_GetCCCCvtfunc(obj) == (CCCFunc)One2OneCCC)
stream->put_block = (MKStreamWriteFunc) net_1to1CCC;
else
stream->put_block = (MKStreamWriteFunc) net_CharCodeConv;
}
TRACEMSG(("Returning stream from NET_CvtCharCodeConverter\n"));
/* remap content type to be to INTERNAL_PARSER
*/
StrAllocCopy(URL_s->content_type, INTERNAL_PARSER);
#ifdef JSDEBUGGER
nsd->next_stream = LM_StreamBuilder(format_out, NULL, URL_s, mwcontext);
#else
nsd->next_stream = NET_StreamBuilder(format_out, URL_s, doc_context);
#endif /* JSDEBUGGER */
if(!nsd->next_stream)
{
XP_FREE(obj);
XP_FREE(stream);
XP_FREE(nsd);
return(NULL);
}
return stream;
}