mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 19:24:08 +00:00
Handle dictzip errors without program termination (Fix issue #207)
This commit is contained in:
parent
c45bf96701
commit
2d76ced4d3
|
@ -264,18 +264,24 @@ sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & wor
|
||||||
|
|
||||||
uint32_t articleOffset = decodeBase64( string( tab1 + 1, tab2 - tab1 - 1 ) );
|
uint32_t articleOffset = decodeBase64( string( tab1 + 1, tab2 - tab1 - 1 ) );
|
||||||
uint32_t articleSize = decodeBase64( tab2 + 1 );
|
uint32_t articleSize = decodeBase64( tab2 + 1 );
|
||||||
|
string articleText;
|
||||||
|
|
||||||
char * articleBody = dict_data_read_( dz, articleOffset, articleSize, 0, 0 );
|
char * articleBody = dict_data_read_( dz, articleOffset, articleSize, 0, 0 );
|
||||||
|
|
||||||
if ( !articleBody )
|
if ( !articleBody )
|
||||||
throw exCantReadFile( getDictionaryFilenames()[ 1 ] );
|
{
|
||||||
|
// throw exCantReadFile( getDictionaryFilenames()[ 1 ] );
|
||||||
|
articleText = string( "<div class=\"dictd_article\">DICTZIP error: " )
|
||||||
|
+ dict_error_str( dz ) + "</div>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//sprintf( buf, "Offset: %u, Size: %u\n", articleOffset, articleSize );
|
//sprintf( buf, "Offset: %u, Size: %u\n", articleOffset, articleSize );
|
||||||
|
|
||||||
string articleText = string( "<div class=\"dictd_article\">" ) +
|
articleText = string( "<div class=\"dictd_article\">" ) +
|
||||||
Html::preformat( articleBody ) + "</div>";
|
Html::preformat( articleBody ) + "</div>";
|
||||||
|
free( articleBody );
|
||||||
free( articleBody );
|
}
|
||||||
|
|
||||||
// Ok. Now, does it go to main articles, or to alternate ones? We list
|
// Ok. Now, does it go to main articles, or to alternate ones? We list
|
||||||
// main ones first, and alternates after.
|
// main ones first, and alternates after.
|
||||||
|
|
79
dictzip.c
79
dictzip.c
|
@ -173,7 +173,7 @@ static void err_fatal( const char *routine, const char *format, ... )
|
||||||
|
|
||||||
fflush( stderr );
|
fflush( stderr );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
exit ( 1 );
|
// exit ( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \doc |err_fatal_errno| flushes "stdout", prints a fatal error report on
|
/* \doc |err_fatal_errno| flushes "stdout", prints a fatal error report on
|
||||||
|
@ -212,7 +212,7 @@ static void err_fatal_errno( const char *routine, const char *format, ... )
|
||||||
|
|
||||||
fflush( stderr );
|
fflush( stderr );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
exit( 1 );
|
// exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \doc |err_internal| flushes "stdout", prints the fatal error message,
|
/* \doc |err_internal| flushes "stdout", prints the fatal error message,
|
||||||
|
@ -246,7 +246,7 @@ static void err_internal( const char *routine, const char *format, ... )
|
||||||
fprintf( stderr, "Aborting...\n" );
|
fprintf( stderr, "Aborting...\n" );
|
||||||
fflush( stderr );
|
fflush( stderr );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
abort();
|
// abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __func__
|
#ifndef __func__
|
||||||
|
@ -273,8 +273,11 @@ static int dict_read_header( const char *filename,
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
||||||
if (!(str = gd_fopen( filename, "rb" )))
|
if (!(str = gd_fopen( filename, "rb" )))
|
||||||
|
{
|
||||||
err_fatal_errno( __func__,
|
err_fatal_errno( __func__,
|
||||||
"Cannot open data file \"%s\" for read\n", filename );
|
"Cannot open data file \"%s\" for read\n", filename );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
header->filename = NULL;//str_find( filename );
|
header->filename = NULL;//str_find( filename );
|
||||||
header->headerLength = GZ_XLEN - 1;
|
header->headerLength = GZ_XLEN - 1;
|
||||||
|
@ -326,9 +329,13 @@ static int dict_read_header( const char *filename,
|
||||||
header->version |= getc( str ) << 8;
|
header->version |= getc( str ) << 8;
|
||||||
|
|
||||||
if (header->version != 1)
|
if (header->version != 1)
|
||||||
|
{
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"dzip header version %d not supported\n",
|
"dzip header version %d not supported\n",
|
||||||
header->version );
|
header->version );
|
||||||
|
fclose( str );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
header->chunkLength = getc( str ) << 0;
|
header->chunkLength = getc( str ) << 0;
|
||||||
header->chunkLength |= getc( str ) << 8;
|
header->chunkLength |= getc( str ) << 8;
|
||||||
|
@ -360,6 +367,8 @@ static int dict_read_header( const char *filename,
|
||||||
err_fatal (
|
err_fatal (
|
||||||
__func__,
|
__func__,
|
||||||
"too long FNAME field in dzip file \"%s\"\n", filename);
|
"too long FNAME field in dzip file \"%s\"\n", filename);
|
||||||
|
fclose( str );
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +388,8 @@ static int dict_read_header( const char *filename,
|
||||||
err_fatal (
|
err_fatal (
|
||||||
__func__,
|
__func__,
|
||||||
"too long COMMENT field in dzip file \"%s\"\n", filename);
|
"too long COMMENT field in dzip file \"%s\"\n", filename);
|
||||||
|
fclose( str );
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,9 +407,13 @@ static int dict_read_header( const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftell( str ) != header->headerLength + 1)
|
if (ftell( str ) != header->headerLength + 1)
|
||||||
|
{
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"File position (%lu) != header length + 1 (%d)\n",
|
"File position (%lu) != header length + 1 (%d)\n",
|
||||||
ftell( str ), header->headerLength + 1 );
|
ftell( str ), header->headerLength + 1 );
|
||||||
|
fclose( str );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
fseek( str, -8, SEEK_END );
|
fseek( str, -8, SEEK_END );
|
||||||
header->crc = getc( str ) << 0;
|
header->crc = getc( str ) << 0;
|
||||||
|
@ -543,6 +558,11 @@ char *dict_data_read_ (
|
||||||
end = start + size;
|
end = start + size;
|
||||||
|
|
||||||
buffer = xmalloc( size + 1 );
|
buffer = xmalloc( size + 1 );
|
||||||
|
if( !buffer )
|
||||||
|
{
|
||||||
|
strcpy( h->errorString, "Cannot allocate memory" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !size )
|
if ( !size )
|
||||||
{
|
{
|
||||||
|
@ -557,11 +577,16 @@ char *dict_data_read_ (
|
||||||
assert( h != NULL);
|
assert( h != NULL);
|
||||||
switch (h->type) {
|
switch (h->type) {
|
||||||
case DICT_GZIP:
|
case DICT_GZIP:
|
||||||
|
/*
|
||||||
err_fatal( __func__,
|
err_fatal( __func__,
|
||||||
"Cannot seek on pure gzip format files.\n"
|
"Cannot seek on pure gzip format files.\n"
|
||||||
"Use plain text (for performance)"
|
"Use plain text (for performance)"
|
||||||
" or dzip format (for space savings).\n" );
|
" or dzip format (for space savings).\n" );
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
|
strcpy( h->errorString, "Cannot seek on pure gzip format files" );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
case DICT_TEXT:
|
case DICT_TEXT:
|
||||||
{
|
{
|
||||||
#ifdef __WIN32
|
#ifdef __WIN32
|
||||||
|
@ -575,6 +600,7 @@ char *dict_data_read_ (
|
||||||
fread( buffer, size, 1, h->fd ) != 1 )
|
fread( buffer, size, 1, h->fd ) != 1 )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
strcpy( h->errorString, "Cannot read file" );
|
||||||
xfree( buffer );
|
xfree( buffer );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -592,9 +618,16 @@ char *dict_data_read_ (
|
||||||
h->zStream.next_out = NULL;
|
h->zStream.next_out = NULL;
|
||||||
h->zStream.avail_out = 0;
|
h->zStream.avail_out = 0;
|
||||||
if (inflateInit2( &h->zStream, -15 ) != Z_OK)
|
if (inflateInit2( &h->zStream, -15 ) != Z_OK)
|
||||||
|
/*
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"Cannot initialize inflation engine: %s\n",
|
"Cannot initialize inflation engine: %s\n",
|
||||||
h->zStream.msg );
|
h->zStream.msg );
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
sprintf( h->errorString, "Cannot initialize inflation engine: %s", h->zStream.msg );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
++h->initialized;
|
++h->initialized;
|
||||||
}
|
}
|
||||||
firstChunk = start / h->chunkLength;
|
firstChunk = start / h->chunkLength;
|
||||||
|
@ -643,9 +676,15 @@ char *dict_data_read_ (
|
||||||
inBuffer = h->cache[target].inBuffer;
|
inBuffer = h->cache[target].inBuffer;
|
||||||
|
|
||||||
if (h->chunks[i] >= OUT_BUFFER_SIZE ) {
|
if (h->chunks[i] >= OUT_BUFFER_SIZE ) {
|
||||||
|
/*
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
|
"h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
|
||||||
i, h->chunks[i], OUT_BUFFER_SIZE );
|
i, h->chunks[i], OUT_BUFFER_SIZE );
|
||||||
|
*/
|
||||||
|
sprintf( h->errorString, "h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
|
||||||
|
i, h->chunks[i], OUT_BUFFER_SIZE );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WIN32
|
#ifdef __WIN32
|
||||||
|
@ -670,11 +709,24 @@ char *dict_data_read_ (
|
||||||
h->zStream.next_out = (Bytef *)inBuffer;
|
h->zStream.next_out = (Bytef *)inBuffer;
|
||||||
h->zStream.avail_out = h->chunkLength;
|
h->zStream.avail_out = h->chunkLength;
|
||||||
if (inflate( &h->zStream, Z_PARTIAL_FLUSH ) != Z_OK)
|
if (inflate( &h->zStream, Z_PARTIAL_FLUSH ) != Z_OK)
|
||||||
err_fatal( __func__, "inflate: %s\n", h->zStream.msg );
|
{
|
||||||
|
// err_fatal( __func__, "inflate: %s\n", h->zStream.msg );
|
||||||
|
sprintf( h->errorString, "inflate: %s\n", h->zStream.msg );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (h->zStream.avail_in)
|
if (h->zStream.avail_in)
|
||||||
|
/*
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"inflate did not flush (%d pending, %d avail)\n",
|
"inflate did not flush (%d pending, %d avail)\n",
|
||||||
h->zStream.avail_in, h->zStream.avail_out );
|
h->zStream.avail_in, h->zStream.avail_out );
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
sprintf( h->errorString, "inflate did not flush (%d pending, %d avail)\n",
|
||||||
|
h->zStream.avail_in, h->zStream.avail_out );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
count = h->chunkLength - h->zStream.avail_out;
|
count = h->chunkLength - h->zStream.avail_out;
|
||||||
dict_data_filter( inBuffer, &count, h->chunkLength, postFilter );
|
dict_data_filter( inBuffer, &count, h->chunkLength, postFilter );
|
||||||
|
@ -689,9 +741,17 @@ char *dict_data_read_ (
|
||||||
pt += lastOffset - firstOffset;
|
pt += lastOffset - firstOffset;
|
||||||
} else {
|
} else {
|
||||||
if (count != h->chunkLength )
|
if (count != h->chunkLength )
|
||||||
|
/*
|
||||||
err_internal( __func__,
|
err_internal( __func__,
|
||||||
"Length = %d instead of %d\n",
|
"Length = %d instead of %d\n",
|
||||||
count, h->chunkLength );
|
count, h->chunkLength );
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
sprintf( h->errorString, "Length = %d instead of %d\n",
|
||||||
|
count, h->chunkLength );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
memcpy( pt, inBuffer + firstOffset,
|
memcpy( pt, inBuffer + firstOffset,
|
||||||
h->chunkLength - firstOffset );
|
h->chunkLength - firstOffset );
|
||||||
pt += h->chunkLength - firstOffset;
|
pt += h->chunkLength - firstOffset;
|
||||||
|
@ -708,9 +768,16 @@ char *dict_data_read_ (
|
||||||
*pt = '\0';
|
*pt = '\0';
|
||||||
break;
|
break;
|
||||||
case DICT_UNKNOWN:
|
case DICT_UNKNOWN:
|
||||||
err_fatal( __func__, "Cannot read unknown file type\n" );
|
// err_fatal( __func__, "Cannot read unknown file type\n" );
|
||||||
break;
|
strcpy( h->errorString, "Cannot read unknown file type" );
|
||||||
|
xfree( buffer );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *dict_error_str( dictData *data )
|
||||||
|
{
|
||||||
|
return data->errorString;
|
||||||
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ typedef struct dictData {
|
||||||
unsigned long compressedLength;
|
unsigned long compressedLength;
|
||||||
int stamp;
|
int stamp;
|
||||||
dictCache cache[DICT_CACHE_SIZE];
|
dictCache cache[DICT_CACHE_SIZE];
|
||||||
|
char errorString[512];
|
||||||
} dictData;
|
} dictData;
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,6 +97,8 @@ extern char *dict_data_read_ (
|
||||||
const char *preFilter,
|
const char *preFilter,
|
||||||
const char *postFilter );
|
const char *postFilter );
|
||||||
|
|
||||||
|
extern char *dict_error_str( dictData *data );
|
||||||
|
|
||||||
extern int mmap_mode;
|
extern int mmap_mode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
27
dsl.cc
27
dsl.cc
|
@ -503,20 +503,25 @@ void DslDictionary::loadArticle( uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !articleBody )
|
if ( !articleBody )
|
||||||
throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
articleData =
|
// throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
|
||||||
DslIconv::toWstring(
|
articleData = GD_NATIVE_TO_WS( L"\n\r\t" ) + gd::toWString( QString( "DICTZIP error: " ) + dict_error_str( dz ) );
|
||||||
DslIconv::getEncodingNameFor( DslEncoding( idxHeader.dslEncoding ) ),
|
|
||||||
articleBody, articleSize );
|
|
||||||
free( articleBody );
|
|
||||||
}
|
}
|
||||||
catch( ... )
|
else
|
||||||
{
|
{
|
||||||
free( articleBody );
|
try
|
||||||
throw;
|
{
|
||||||
|
articleData =
|
||||||
|
DslIconv::toWstring(
|
||||||
|
DslIconv::getEncodingNameFor( DslEncoding( idxHeader.dslEncoding ) ),
|
||||||
|
articleBody, articleSize );
|
||||||
|
free( articleBody );
|
||||||
|
}
|
||||||
|
catch( ... )
|
||||||
|
{
|
||||||
|
free( articleBody );
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,11 @@ void StardictDictionary::loadArticle( uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !articleBody )
|
if ( !articleBody )
|
||||||
throw exCantReadFile( getDictionaryFilenames()[ 2 ] );
|
{
|
||||||
|
// throw exCantReadFile( getDictionaryFilenames()[ 2 ] );
|
||||||
|
articleText = string( "<div class=\"sdict_m\">DICTZIP error: " ) + dict_error_str( dz ) + "</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
articleText.clear();
|
articleText.clear();
|
||||||
|
|
||||||
|
|
6
xdxf.cc
6
xdxf.cc
|
@ -545,7 +545,11 @@ void XdxfDictionary::loadArticle( uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !articleBody )
|
if ( !articleBody )
|
||||||
throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
|
{
|
||||||
|
// throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
|
||||||
|
articleText = string( "<div class=\"xdxf\">DICTZIP error: " ) + dict_error_str( dz ) + "</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
articleText = Xdxf2Html::convert( string( articleBody ), Xdxf2Html::XDXF, idxHeader.hasAbrv ? &abrv : NULL, this );
|
articleText = Xdxf2Html::convert( string( articleBody ), Xdxf2Html::XDXF, idxHeader.hasAbrv ? &abrv : NULL, this );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue