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 articleSize = decodeBase64( tab2 + 1 );
string articleText;
char * articleBody = dict_data_read_( dz, articleOffset, articleSize, 0, 0 );
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 );
string articleText = string( "<div class=\"dictd_article\">" ) +
Html::preformat( articleBody ) + "</div>";
free( articleBody );
articleText = string( "<div class=\"dictd_article\">" ) +
Html::preformat( articleBody ) + "</div>";
free( articleBody );
}
// Ok. Now, does it go to main articles, or to alternate ones? We list
// 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( stdout );
exit ( 1 );
// exit ( 1 );
}
/* \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( stdout );
exit( 1 );
// exit( 1 );
}
/* \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" );
fflush( stderr );
fflush( stdout );
abort();
// abort();
}
#ifndef __func__
@ -273,8 +273,11 @@ static int dict_read_header( const char *filename,
unsigned long offset;
if (!(str = gd_fopen( filename, "rb" )))
{
err_fatal_errno( __func__,
"Cannot open data file \"%s\" for read\n", filename );
return 1;
}
header->filename = NULL;//str_find( filename );
header->headerLength = GZ_XLEN - 1;
@ -326,9 +329,13 @@ static int dict_read_header( const char *filename,
header->version |= getc( str ) << 8;
if (header->version != 1)
{
err_internal( __func__,
"dzip header version %d not supported\n",
header->version );
fclose( str );
return 1;
}
header->chunkLength = getc( str ) << 0;
header->chunkLength |= getc( str ) << 8;
@ -360,6 +367,8 @@ static int dict_read_header( const char *filename,
err_fatal (
__func__,
"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 (
__func__,
"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)
{
err_internal( __func__,
"File position (%lu) != header length + 1 (%d)\n",
ftell( str ), header->headerLength + 1 );
fclose( str );
return 1;
}
fseek( str, -8, SEEK_END );
header->crc = getc( str ) << 0;
@ -543,6 +558,11 @@ char *dict_data_read_ (
end = start + size;
buffer = xmalloc( size + 1 );
if( !buffer )
{
strcpy( h->errorString, "Cannot allocate memory" );
return 0;
}
if ( !size )
{
@ -557,11 +577,16 @@ char *dict_data_read_ (
assert( h != NULL);
switch (h->type) {
case DICT_GZIP:
/*
err_fatal( __func__,
"Cannot seek on pure gzip format files.\n"
"Use plain text (for performance)"
" or dzip format (for space savings).\n" );
break;
*/
strcpy( h->errorString, "Cannot seek on pure gzip format files" );
xfree( buffer );
return 0;
case DICT_TEXT:
{
#ifdef __WIN32
@ -575,6 +600,7 @@ char *dict_data_read_ (
fread( buffer, size, 1, h->fd ) != 1 )
#endif
{
strcpy( h->errorString, "Cannot read file" );
xfree( buffer );
return 0;
}
@ -592,9 +618,16 @@ char *dict_data_read_ (
h->zStream.next_out = NULL;
h->zStream.avail_out = 0;
if (inflateInit2( &h->zStream, -15 ) != Z_OK)
/*
err_internal( __func__,
"Cannot initialize inflation engine: %s\n",
h->zStream.msg );
*/
{
sprintf( h->errorString, "Cannot initialize inflation engine: %s", h->zStream.msg );
xfree( buffer );
return 0;
}
++h->initialized;
}
firstChunk = start / h->chunkLength;
@ -643,9 +676,15 @@ char *dict_data_read_ (
inBuffer = h->cache[target].inBuffer;
if (h->chunks[i] >= OUT_BUFFER_SIZE ) {
/*
err_internal( __func__,
"h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
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
@ -670,11 +709,24 @@ char *dict_data_read_ (
h->zStream.next_out = (Bytef *)inBuffer;
h->zStream.avail_out = h->chunkLength;
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)
/*
err_internal( __func__,
"inflate did not flush (%d pending, %d avail)\n",
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;
dict_data_filter( inBuffer, &count, h->chunkLength, postFilter );
@ -689,9 +741,17 @@ char *dict_data_read_ (
pt += lastOffset - firstOffset;
} else {
if (count != h->chunkLength )
/*
err_internal( __func__,
"Length = %d instead of %d\n",
count, h->chunkLength );
*/
{
sprintf( h->errorString, "Length = %d instead of %d\n",
count, h->chunkLength );
xfree( buffer );
return 0;
}
memcpy( pt, inBuffer + firstOffset,
h->chunkLength - firstOffset );
pt += h->chunkLength - firstOffset;
@ -708,9 +768,16 @@ char *dict_data_read_ (
*pt = '\0';
break;
case DICT_UNKNOWN:
err_fatal( __func__, "Cannot read unknown file type\n" );
break;
// err_fatal( __func__, "Cannot read unknown file type\n" );
strcpy( h->errorString, "Cannot read unknown file type" );
xfree( buffer );
return 0;
}
return buffer;
}
char *dict_error_str( dictData *data )
{
return data->errorString;
}

View file

@ -80,6 +80,7 @@ typedef struct dictData {
unsigned long compressedLength;
int stamp;
dictCache cache[DICT_CACHE_SIZE];
char errorString[512];
} dictData;
@ -96,6 +97,8 @@ extern char *dict_data_read_ (
const char *preFilter,
const char *postFilter );
extern char *dict_error_str( dictData *data );
extern int mmap_mode;
#ifdef __cplusplus

27
dsl.cc
View file

@ -503,20 +503,25 @@ void DslDictionary::loadArticle( uint32_t address,
}
if ( !articleBody )
throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
try
{
articleData =
DslIconv::toWstring(
DslIconv::getEncodingNameFor( DslEncoding( idxHeader.dslEncoding ) ),
articleBody, articleSize );
free( articleBody );
// throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
articleData = GD_NATIVE_TO_WS( L"\n\r\t" ) + gd::toWString( QString( "DICTZIP error: " ) + dict_error_str( dz ) );
}
catch( ... )
else
{
free( articleBody );
throw;
try
{
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 )
throw exCantReadFile( getDictionaryFilenames()[ 2 ] );
{
// throw exCantReadFile( getDictionaryFilenames()[ 2 ] );
articleText = string( "<div class=\"sdict_m\">DICTZIP error: " ) + dict_error_str( dz ) + "</div>";
return;
}
articleText.clear();

View file

@ -545,7 +545,11 @@ void XdxfDictionary::loadArticle( uint32_t address,
}
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 );