ftrfork.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 812 行 · 第 1/2 页
C
812 行
/***************************************************************************/
/* */
/* ftrfork.c */
/* */
/* Embedded resource forks accessor (body). */
/* */
/* Copyright 2004, 2005, 2006, 2007 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
/* derived from ftobjs.c. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
/***************************************************************************/
/* Development of the code in this file is support of */
/* Information-technology Promotion Agency, Japan. */
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Resource fork directory access ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
FT_Long rfork_offset,
FT_Long *map_offset,
FT_Long *rdata_pos )
{
FT_Error error;
unsigned char head[16], head2[16];
FT_Long map_pos, rdata_len;
int allzeros, allmatch, i;
FT_Long type_list;
FT_UNUSED( library );
error = FT_Stream_Seek( stream, rfork_offset );
if ( error )
return error;
error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
if ( error )
return error;
*rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
( head[1] << 16 ) |
( head[2] << 8 ) |
head[3] );
map_pos = rfork_offset + ( ( head[4] << 24 ) |
( head[5] << 16 ) |
( head[6] << 8 ) |
head[7] );
rdata_len = ( head[ 8] << 24 ) |
( head[ 9] << 16 ) |
( head[10] << 8 ) |
head[11];
/* map_len = head[12] .. head[15] */
if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos );
if ( error )
return error;
head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
if ( error )
return error;
allzeros = 1;
allmatch = 1;
for ( i = 0; i < 16; ++i )
{
if ( head2[i] != 0 )
allzeros = 0;
if ( head2[i] != head[i] )
allmatch = 0;
}
if ( !allzeros && !allmatch )
return FT_Err_Unknown_File_Format;
/* If we have reached this point then it is probably a mac resource */
/* file. Now, does it contain any interesting resources? */
/* Skip handle to next resource map, the file resource number, and */
/* attributes. */
(void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
+ 2 /* skip file resource number */
+ 2 ); /* skip attributes */
if ( FT_READ_USHORT( type_list ) )
return error;
if ( type_list == -1 )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos + type_list );
if ( error )
return error;
*map_offset = map_pos + type_list;
return FT_Err_Ok;
}
static int
ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,
FT_RFork_Ref* b )
{
if ( a->res_id < b->res_id )
return -1;
else if ( a->res_id > b->res_id )
return 1;
else
return 0;
}
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
FT_Long **offsets,
FT_Long *count )
{
FT_Error error;
int i, j, cnt, subcnt;
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
FT_Long *offsets_internal;
FT_RFork_Ref *ref;
error = FT_Stream_Seek( stream, map_offset );
if ( error )
return error;
if ( FT_READ_USHORT( cnt ) )
return error;
cnt++;
for ( i = 0; i < cnt; ++i )
{
if ( FT_READ_LONG( tag_internal ) ||
FT_READ_USHORT( subcnt ) ||
FT_READ_USHORT( rpos ) )
return error;
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
(char)( 0xff & ( tag_internal >> 24 ) ),
(char)( 0xff & ( tag_internal >> 16 ) ),
(char)( 0xff & ( tag_internal >> 8 ) ),
(char)( 0xff & ( tag_internal >> 0 ) ) ));
if ( tag_internal == tag )
{
*count = subcnt + 1;
rpos += map_offset;
error = FT_Stream_Seek( stream, rpos );
if ( error )
return error;
if ( FT_NEW_ARRAY( ref, *count ) )
return error;
for ( j = 0; j < *count; ++j )
{
if ( FT_READ_USHORT( ref[j].res_id ) )
goto Exit;
if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
goto Exit;
if ( FT_READ_LONG( temp ) )
goto Exit;
if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
goto Exit;
ref[j].offset = temp & 0xFFFFFFL;
}
ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
( int(*)(const void*, const void*) )
ft_raccess_sort_ref_by_id );
if ( FT_NEW_ARRAY( offsets_internal, *count ) )
goto Exit;
/* XXX: duplicated reference ID,
* gap between reference IDs are acceptable?
* further investigation on Apple implementation is needed.
*/
for ( j = 0; j < *count; ++j )
offsets_internal[j] = rdata_pos + ref[j].offset;
*offsets = offsets_internal;
error = FT_Err_Ok;
Exit:
FT_FREE( ref );
return error;
}
}
return FT_Err_Cannot_Open_Resource;
}
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Guessing functions ****/
/**** ****/
/**** When you add a new guessing function, ****/
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
typedef FT_Error
(*raccess_guess_func)( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
/*************************************************************************/
/**** ****/
/**** Helper functions ****/
/**** ****/
/*************************************************************************/
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char * file_name,
FT_Long *result_offset );
static char *
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion );
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Long i;
raccess_guess_func funcs[FT_RACCESS_N_RULES] =
{
raccess_guess_apple_double,
raccess_guess_apple_single,
raccess_guess_darwin_ufs_export,
raccess_guess_darwin_newvfs,
raccess_guess_darwin_hfsplus,
raccess_guess_vfat,
raccess_guess_linux_cap,
raccess_guess_linux_double,
raccess_guess_linux_netatalk,
};
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
if ( NULL != stream )
errors[i] = FT_Stream_Seek( stream, 0 );
else
errors[i] = FT_Err_Ok;
if ( errors[i] )
continue ;
errors[i] = (funcs[i])( library, stream, base_name,
&(new_names[i]), &(offsets[i]) );
}
return;
}
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
*result_file_name = NULL;
if ( NULL == stream )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?