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 + -
显示快捷键?