Handle dictzip errors without program termination (Fix issue #207)

This commit is contained in:
Abs62 2013-03-15 16:27:32 +04:00
parent c45bf96701
commit 2d76ced4d3
6 changed files with 114 additions and 25 deletions

View file

@ -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.

View file

@ -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;
}

View file

@ -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
View file

@ -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;
}
} }
} }

View file

@ -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();

View file

@ -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 );