|
|
| version 1.105, 2017/02/06 12:27:29 | version 1.118, 2026/04/25 13:38:46 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: Charset connection implementation. | Parser: Charset connection implementation. |
| Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) | Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com) |
| Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru) | Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru> |
| */ | */ |
| #include "pa_charset.h" | #include "pa_charset.h" |
| Line 14 | Line 14 |
| volatile const char * IDENT_PA_CHARSET_C="$Id$" IDENT_PA_CHARSET_H; | volatile const char * IDENT_PA_CHARSET_C="$Id$" IDENT_PA_CHARSET_H; |
| #ifdef XML | #ifdef XML |
| #include "libxml/xmlmemory.h" | |
| #include "libxml/encoding.h" | #include "libxml/encoding.h" |
| #endif | #endif |
| //#define PA_PATCHED_LIBXML_BACKWARD | |
| // reduce memory usage by pre-calculation utf-8 string length | // reduce memory usage by pre-calculation utf-8 string length |
| #define PRECALCULATE_DEST_LENGTH | #define PRECALCULATE_DEST_LENGTH |
| Line 124 Charset::Charset(Request_charsets* achar | Line 123 Charset::Charset(Request_charsets* achar |
| // grab default onces [for UTF-8 so to be able to make a-z =>A-Z | // grab default onces [for UTF-8 so to be able to make a-z =>A-Z |
| memcpy(pcre_tables, pa_pcre_default_tables, sizeof(pcre_tables)); | memcpy(pcre_tables, pa_pcre_default_tables, sizeof(pcre_tables)); |
| } | } |
| #ifdef XML | |
| initTranscoder(FNAME, FNAME_CSTR); | |
| #endif | |
| } | } |
| void Charset::load_definition(Request_charsets& acharsets, const String& afile_spec) { | void Charset::load_definition(Request_charsets& acharsets, const String& afile_spec) { |
| Line 173 void Charset::load_definition(Request_ch | Line 168 void Charset::load_definition(Request_ch |
| case 8: | case 8: |
| // charset | // charset |
| if(tables.toTableSize>MAX_CHARSET_UNI_CODES) | if(tables.toTableSize>MAX_CHARSET_UNI_CODES) |
| throw Exception(PARSER_RUNTIME, &afile_spec, "charset must contain not more then %d unicode values", MAX_CHARSET_UNI_CODES); | throw Exception(PARSER_RUNTIME, &afile_spec, "charset must contain not more than %d unicode values", MAX_CHARSET_UNI_CODES); |
| XMLCh unicode=(XMLCh)to_wchar_code(cell); | XMLCh unicode=(XMLCh)to_wchar_code(cell); |
| if(!unicode && column==7/*unicode1 column*/) | if(!unicode && column==7/*unicode1 column*/) |
| Line 993 void Charset::store_Char(XMLByte*& outPt | Line 988 void Charset::store_Char(XMLByte*& outPt |
| static const Charset::Tables* tables[MAX_CHARSETS]; | static const Charset::Tables* tables[MAX_CHARSETS]; |
| #ifdef PA_PATCHED_LIBXML_BACKWARD | |
| #define declareXml256ioFuncs(i) \ | |
| static int xml256CharEncodingInputFunc##i( \ | |
| unsigned char *out, int *outlen, \ | |
| const unsigned char *in, int *inlen, void*) { \ | |
| return transcodeToUTF8( \ | |
| in, *inlen, \ | |
| out, *outlen, \ | |
| *tables[i]); \ | |
| } \ | |
| static int xml256CharEncodingOutputFunc##i( \ | |
| unsigned char *out, int *outlen, \ | |
| const unsigned char *in, int *inlen, void*) { \ | |
| return transcodeFromUTF8( \ | |
| in, *inlen, \ | |
| out, *outlen, \ | |
| *tables[i]); \ | |
| } | |
| #else | |
| #define declareXml256ioFuncs(i) \ | #define declareXml256ioFuncs(i) \ |
| static int xml256CharEncodingInputFunc##i( \ | static int xml256CharEncodingInputFunc##i( \ |
| unsigned char *out, int *outlen, \ | unsigned char *out, int *outlen, \ |
| Line 1033 static const Charset::Tables* tables[MAX | Line 1006 static const Charset::Tables* tables[MAX |
| *tables[i]); \ | *tables[i]); \ |
| } | } |
| #endif | |
| declareXml256ioFuncs(0) declareXml256ioFuncs(1) | declareXml256ioFuncs(0) declareXml256ioFuncs(1) |
| declareXml256ioFuncs(2) declareXml256ioFuncs(3) | declareXml256ioFuncs(2) declareXml256ioFuncs(3) |
| declareXml256ioFuncs(4) declareXml256ioFuncs(5) | declareXml256ioFuncs(4) declareXml256ioFuncs(5) |
| Line 1062 void Charset::addEncoding(char *name_cst | Line 1032 void Charset::addEncoding(char *name_cst |
| if(handlers_count==MAX_CHARSETS) | if(handlers_count==MAX_CHARSETS) |
| throw Exception(0, 0, "already allocated %d handlers, no space for new encoding '%s'", MAX_CHARSETS, name_cstr); | throw Exception(0, 0, "already allocated %d handlers, no space for new encoding '%s'", MAX_CHARSETS, name_cstr); |
| xmlCharEncodingHandler* handler=new xmlCharEncodingHandler; | ftranscoder_input=inputFuncs[handlers_count]; |
| { | ftranscoder_output=outputFuncs[handlers_count]; |
| handler->name=name_cstr; | ::tables[handlers_count++]=&tables; |
| handler->input=inputFuncs[handlers_count]; | |
| handler->output=outputFuncs[handlers_count]; | xmlCharEncodingHandler* handler=xmlNewCharEncodingHandler(name_cstr, ftranscoder_input, ftranscoder_output); |
| ::tables[handlers_count]=&tables; | if(!handler) |
| handlers_count++; | throw Exception(0, new String(name_cstr, String::L_TAINTED), "unable to register XML encoding handler"); |
| } | |
| xmlRegisterCharEncodingHandler(handler); | xmlRegisterCharEncodingHandler(handler); |
| } | |
| void Charset::initTranscoder(const String::Body NAME, const char* name_cstr) { | |
| ftranscoder=xmlFindCharEncodingHandler(name_cstr); | |
| transcoder(NAME); // check right way | |
| } | |
| xmlCharEncodingHandler& Charset::transcoder(const String::Body NAME) { | |
| if(!ftranscoder) | |
| throw Exception(PARSER_RUNTIME, new String(NAME, String::L_TAINTED), "unsupported encoding"); | |
| return *ftranscoder; | |
| } | } |
| String::C Charset::transcode_cstr(const xmlChar* s) { | String::C Charset::transcode_cstr(const xmlChar* s) { |
| Line 1098 String::C Charset::transcode_cstr(const | Line 1054 String::C Charset::transcode_cstr(const |
| char *out=new(PointerFreeGC) char[outlen+1]; | char *out=new(PointerFreeGC) char[outlen+1]; |
| int error; | int error; |
| if(xmlCharEncodingOutputFunc output=transcoder(FNAME).output) { | if(!fisUTF8) { |
| error=output( | error=ftranscoder_output((unsigned char*)out, &outlen, (const unsigned char*)s, &inlen); |
| (unsigned char*)out, &outlen, | |
| (const unsigned char*)s, &inlen | |
| #ifdef PA_PATCHED_LIBXML_BACKWARD | |
| ,0 | |
| #endif | |
| ); | |
| } else { | } else { |
| memcpy(out, s, outlen=inlen); | memcpy(out, s, outlen=inlen); |
| error=0; | error=0; |
| Line 1129 xmlChar* Charset::transcode_buf2xchar(co | Line 1079 xmlChar* Charset::transcode_buf2xchar(co |
| #ifndef NDEBUG | #ifndef NDEBUG |
| int saved_outlen; | int saved_outlen; |
| #endif | #endif |
| if(xmlCharEncodingInputFunc input=transcoder(FNAME).input) { | if(!fisUTF8) { |
| outlen=buf_size*6/*max UTF8 bytes per char*/; | outlen=buf_size*6/*max UTF8 bytes per char*/; |
| #ifndef NDEBUG | #ifndef NDEBUG |
| saved_outlen=outlen; | saved_outlen=outlen; |
| #endif | #endif |
| out=(xmlChar*)xmlMalloc(outlen+1); | out=(xmlChar*)xmlMalloc(outlen+1); |
| error=input( | error=ftranscoder_input(out, &outlen, (const unsigned char*)buf, (int*)&buf_size); |
| out, &outlen, | |
| (const unsigned char*)buf, (int*)&buf_size | |
| #ifdef PA_PATCHED_LIBXML_BACKWARD | |
| ,0 | |
| #endif | |
| ); | |
| } else { | } else { |
| outlen=buf_size; | outlen=buf_size; |
| #ifndef NDEBUG | #ifndef NDEBUG |
| Line 1218 size_t getUTF8CharPos(const XMLByte* src | Line 1162 size_t getUTF8CharPos(const XMLByte* src |
| } | } |
| // scan till end but position in bytes still too low | // scan till end but position in bytes still too low |
| throw Exception(0, 0, "Error convertion byte pos to char pos"); | throw Exception(0, 0, "Error conversion byte pos to char pos"); |
| } | } |
| size_t lengthUTF8(const XMLByte* srcBegin, const XMLByte* srcEnd){ | size_t lengthUTF8(const XMLByte* srcBegin, const XMLByte* srcEnd){ |
| Line 1246 const char *fixUTF8(const char *src){ | Line 1190 const char *fixUTF8(const char *src){ |
| do { | do { |
| if(error_offset){ | if(error_offset){ |
| strncpy(dst, src, error_offset); | memcpy(dst, src, error_offset); |
| dst+=error_offset; | dst+=error_offset; |
| src+=error_offset; | src+=error_offset; |