/* 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))); }
/* buf -> mz_mbNullConv -> frombuf -> INTL_TextToUnicode -> ucs2buf -> INTL_UnicodeToStr -> tobuf */ PRIVATE unsigned char* mz_AnyToAnyThroughUCS2(CCCDataObject obj, const unsigned char *buf, int32 bufsz) { /* buffers */ unsigned char* fromBuf = NULL; INTL_Unicode* ucs2Buf = NULL; unsigned char* toBuf = NULL; /* buffers' length */ uint32 ucs2BufLen = 0; uint32 fromBufLen = 0; uint32 toBufLen = 0; /* from & to csid */ uint16 fromCsid = INTL_GetCCCFromCSID(obj); uint16 toCsid = INTL_GetCCCToCSID(obj); /* get the fromBuf */ if( !( fromBuf = mz_mbNullConv( obj, buf, bufsz) ) ) return NULL; /* map fromBuf -> ucs2Buf */ fromBufLen = INTL_GetCCCLen(obj); ucs2BufLen = INTL_TextToUnicodeLen( fromCsid, fromBuf, fromBufLen ); if( !( ucs2Buf = XP_ALLOC( (ucs2BufLen + 1 ) * 2)) ){ return NULL; } /* be care, the return value is HOW MANY UNICODE IN THIS UCS2BUF, not how many bytes */ ucs2BufLen = INTL_TextToUnicode( fromCsid, fromBuf, fromBufLen, ucs2Buf, ucs2BufLen ); /* map ucs2Buf -> toBuf */ toBufLen = INTL_UnicodeToStrLen( toCsid, ucs2Buf, ucs2BufLen ); /* we get BYTES here :) */ if( !( toBuf = XP_ALLOC( toBufLen + 1 ) ) ) return NULL; INTL_UnicodeToStr( toCsid, ucs2Buf, ucs2BufLen, toBuf, toBufLen ); /* clean up after myself */ free( fromBuf ); free( ucs2Buf ); /* In order to let the caller know how long the buffer is, i have to set its tail NULL. */ toBuf[ toBufLen ] = 0; return toBuf; }
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)); } }
PRIVATE unsigned char * mz_hz2gb(CCCDataObject obj, const unsigned char *gbbuf, int32 gbbufsz) { unsigned char *start, *p, *q; unsigned char *output; int i, j, len; unsigned char *uncvtbuf = INTL_GetCCCUncvtbuf(obj); q = output = XP_ALLOC(strlen((char*)uncvtbuf) + gbbufsz + 1); if (q == NULL) return NULL; start = NULL; for (j = 0; j < 2; j++) { len = 0; if (j == 0) len = strlen((char *)uncvtbuf); if (len) p = (unsigned char *) uncvtbuf; else { p = (unsigned char *) gbbuf ; len = gbbufsz; j = 100; /* quit this loop next time */ } for (i = 0; i < len;) { if (start) { if (*p == '~' && *(p+1) == '}') /* switch back to ASCII mode */ { for (; start < p; start++) *q++ = *start | 0x80; p += 2; i += 2; start = NULL; } else if (*p == 0x0D && *(p+1) == 0x0A) /* Unix or Mac return */ { for (; start < p; start++) *q++ = *start | 0x80; i += 2; *q++ = *p++; /* 0x0D */ *q++ = *p++; /* 0x0A */ start = NULL; /* reset start if we see normal line return */ } else if (*p == 0x0A) /* Unix or Mac return */ { for (; start < p; start++) *q++ = *start | 0x80; i ++; *q++ = *p++; /* LF */ start = NULL; /* reset start if we see normal line return */ } else if (*p == 0x0D) /* Unix or Mac return */ { for (; start < p; start++) *q++ = *start | 0x80; i ++; *q++ = *p++; /* LF */ start = NULL; /* reset start if we see normal line return */ } else { i ++ ; p ++ ; } } else { if (*p == '~' && *(p+1) == '{') /* switch to GB mode */ { start = p + 2; p += 2; i += 2; } else if (*p == '~' && *(p+1) == 0x0D && *(p+2) == 0x0A) /* line-continuation marker */ { i += 3; p += 3; } else if (*p == '~' && *(p+1) == 0x0A) /* line-continuation marker */ { i += 2; p += 2; } else if (*p == '~' && *(p+1) == 0x0D) /* line-continuation marker */ { i += 2; p += 2; } else if (*p == '~' && *(p+1) == '~') /* ~~ means ~ */ { *q++ = '~'; p += 2; i += 2; } else { i ++; *q++ = *p++; } } } } *q = '\0'; INTL_SetCCCLen(obj, q - output); if (start) { /* Consider UNCVTBUF_SIZE is only 8 byte long, it's not enough for HZ anyway. Let's convert leftover to GB first and deal with unfinished buffer in the coming block. */ INTL_SetCCCLen(obj, INTL_GetCCCLen(obj) + p - start); for (; start < p; start++) *q++ = *start | 0x80; *q = '\0'; q = uncvtbuf; XP_STRCPY((char *)q, "~{"); } return output; }
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)); } }