зеркало из https://github.com/mozilla/gecko-dev.git
344 строки
9.7 KiB
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;
|
|
}
|
|
|