source: trunk/poppler/freetype2/src/base/ftrfork.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

File size: 25.8 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ftrfork.c                                                              */
4/*                                                                         */
5/*    Embedded resource forks accessor (body).                             */
6/*                                                                         */
7/*  Copyright 2004, 2005, 2006, 2007, 2008 by                              */
8/*  Masatake YAMATO and Redhat K.K.                                        */
9/*                                                                         */
10/*  FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are     */
11/*  derived from ftobjs.c.                                                 */
12/*                                                                         */
13/*  This file is part of the FreeType project, and may only be used,       */
14/*  modified, and distributed under the terms of the FreeType project      */
15/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
16/*  this file you indicate that you have read the license and              */
17/*  understand and accept it fully.                                        */
18/*                                                                         */
19/***************************************************************************/
20
21/***************************************************************************/
22/* Development of the code in this file is support of                      */
23/* Information-technology Promotion Agency, Japan.                         */
24/***************************************************************************/
25
26
27#include <ft2build.h>
28#include FT_INTERNAL_DEBUG_H
29#include FT_INTERNAL_STREAM_H
30#include FT_INTERNAL_RFORK_H
31
32
33#undef  FT_COMPONENT
34#define FT_COMPONENT  trace_raccess
35
36
37  /*************************************************************************/
38  /*************************************************************************/
39  /*************************************************************************/
40  /****                                                                 ****/
41  /****                                                                 ****/
42  /****               Resource fork directory access                    ****/
43  /****                                                                 ****/
44  /****                                                                 ****/
45  /*************************************************************************/
46  /*************************************************************************/
47  /*************************************************************************/
48
49  FT_BASE_DEF( FT_Error )
50  FT_Raccess_Get_HeaderInfo( FT_Library  library,
51                             FT_Stream   stream,
52                             FT_Long     rfork_offset,
53                             FT_Long    *map_offset,
54                             FT_Long    *rdata_pos )
55  {
56    FT_Error       error;
57    unsigned char  head[16], head2[16];
58    FT_Long        map_pos, rdata_len;
59    int            allzeros, allmatch, i;
60    FT_Long        type_list;
61
62    FT_UNUSED( library );
63
64
65    error = FT_Stream_Seek( stream, rfork_offset );
66    if ( error )
67      return error;
68
69    error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
70    if ( error )
71      return error;
72
73    *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
74                                  ( head[1] << 16 ) |
75                                  ( head[2] <<  8 ) |
76                                    head[3]         );
77    map_pos    = rfork_offset + ( ( head[4] << 24 ) |
78                                  ( head[5] << 16 ) |
79                                  ( head[6] <<  8 ) |
80                                    head[7]         );
81    rdata_len = ( head[ 8] << 24 ) |
82                ( head[ 9] << 16 ) |
83                ( head[10] <<  8 ) |
84                  head[11];
85
86    /* map_len = head[12] .. head[15] */
87
88    if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
89      return FT_Err_Unknown_File_Format;
90
91    error = FT_Stream_Seek( stream, map_pos );
92    if ( error )
93      return error;
94
95    head2[15] = (FT_Byte)( head[15] + 1 );       /* make it be different */
96
97    error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
98    if ( error )
99      return error;
100
101    allzeros = 1;
102    allmatch = 1;
103    for ( i = 0; i < 16; ++i )
104    {
105      if ( head2[i] != 0 )
106        allzeros = 0;
107      if ( head2[i] != head[i] )
108        allmatch = 0;
109    }
110    if ( !allzeros && !allmatch )
111      return FT_Err_Unknown_File_Format;
112
113    /* If we have reached this point then it is probably a mac resource */
114    /* file.  Now, does it contain any interesting resources?           */
115    /* Skip handle to next resource map, the file resource number, and  */
116    /* attributes.                                                      */
117    (void)FT_STREAM_SKIP( 4        /* skip handle to next resource map */
118                          + 2      /* skip file resource number */
119                          + 2 );   /* skip attributes */
120
121    if ( FT_READ_USHORT( type_list ) )
122      return error;
123    if ( type_list == -1 )
124      return FT_Err_Unknown_File_Format;
125
126    error = FT_Stream_Seek( stream, map_pos + type_list );
127    if ( error )
128      return error;
129
130    *map_offset = map_pos + type_list;
131    return FT_Err_Ok;
132  }
133
134
135  static int
136  ft_raccess_sort_ref_by_id( FT_RFork_Ref*  a,
137                             FT_RFork_Ref*  b )
138  {
139    if ( a->res_id < b->res_id )
140      return -1;
141    else if ( a->res_id > b->res_id )
142      return 1;
143    else
144      return 0;
145  }
146
147
148  FT_BASE_DEF( FT_Error )
149  FT_Raccess_Get_DataOffsets( FT_Library  library,
150                              FT_Stream   stream,
151                              FT_Long     map_offset,
152                              FT_Long     rdata_pos,
153                              FT_Long     tag,
154                              FT_Long   **offsets,
155                              FT_Long    *count )
156  {
157    FT_Error      error;
158    int           i, j, cnt, subcnt;
159    FT_Long       tag_internal, rpos;
160    FT_Memory     memory = library->memory;
161    FT_Long       temp;
162    FT_Long       *offsets_internal;
163    FT_RFork_Ref  *ref;
164
165
166    error = FT_Stream_Seek( stream, map_offset );
167    if ( error )
168      return error;
169
170    if ( FT_READ_USHORT( cnt ) )
171      return error;
172    cnt++;
173
174    for ( i = 0; i < cnt; ++i )
175    {
176      if ( FT_READ_LONG( tag_internal ) ||
177           FT_READ_USHORT( subcnt )     ||
178           FT_READ_USHORT( rpos )       )
179        return error;
180
181      FT_TRACE2(( "Resource tags: %c%c%c%c\n",
182                  (char)( 0xff & ( tag_internal >> 24 ) ),
183                  (char)( 0xff & ( tag_internal >> 16 ) ),
184                  (char)( 0xff & ( tag_internal >>  8 ) ),
185                  (char)( 0xff & ( tag_internal >>  0 ) ) ));
186
187      if ( tag_internal == tag )
188      {
189        *count = subcnt + 1;
190        rpos  += map_offset;
191
192        error = FT_Stream_Seek( stream, rpos );
193        if ( error )
194          return error;
195
196        if ( FT_NEW_ARRAY( ref, *count ) )
197          return error;
198
199        for ( j = 0; j < *count; ++j )
200        {
201          if ( FT_READ_USHORT( ref[j].res_id ) )
202            goto Exit;
203          if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
204            goto Exit;
205          if ( FT_READ_LONG( temp ) )
206            goto Exit;
207          if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
208            goto Exit;
209
210          ref[j].offset = temp & 0xFFFFFFL;
211        }
212
213        ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
214                  ( int(*)(const void*, const void*) )
215                  ft_raccess_sort_ref_by_id );
216
217        if ( FT_NEW_ARRAY( offsets_internal, *count ) )
218          goto Exit;
219
220        /* XXX: duplicated reference ID,
221         *      gap between reference IDs are acceptable?
222         *      further investigation on Apple implementation is needed.
223         */
224        for ( j = 0; j < *count; ++j )
225          offsets_internal[j] = rdata_pos + ref[j].offset;
226
227        *offsets = offsets_internal;
228        error    = FT_Err_Ok;
229
230      Exit:
231        FT_FREE( ref );
232        return error;
233      }
234    }
235
236    return FT_Err_Cannot_Open_Resource;
237  }
238
239
240#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
241
242  /*************************************************************************/
243  /*************************************************************************/
244  /*************************************************************************/
245  /****                                                                 ****/
246  /****                                                                 ****/
247  /****                     Guessing functions                          ****/
248  /****                                                                 ****/
249  /****            When you add a new guessing function,                ****/
250  /****           update FT_RACCESS_N_RULES in ftrfork.h.               ****/
251  /****                                                                 ****/
252  /*************************************************************************/
253  /*************************************************************************/
254  /*************************************************************************/
255
256  typedef FT_Error
257  (*raccess_guess_func)( FT_Library  library,
258                         FT_Stream   stream,
259                         char       *base_file_name,
260                         char      **result_file_name,
261                         FT_Long    *result_offset );
262
263
264  static FT_Error
265  raccess_guess_apple_double( FT_Library  library,
266                              FT_Stream   stream,
267                              char       *base_file_name,
268                              char      **result_file_name,
269                              FT_Long    *result_offset );
270
271  static FT_Error
272  raccess_guess_apple_single( FT_Library  library,
273                              FT_Stream   stream,
274                              char       *base_file_name,
275                              char      **result_file_name,
276                              FT_Long    *result_offset );
277
278  static FT_Error
279  raccess_guess_darwin_ufs_export( FT_Library  library,
280                                   FT_Stream   stream,
281                                   char       *base_file_name,
282                                   char      **result_file_name,
283                                   FT_Long    *result_offset );
284
285  static FT_Error
286  raccess_guess_darwin_newvfs( FT_Library  library,
287                               FT_Stream   stream,
288                               char       *base_file_name,
289                               char      **result_file_name,
290                               FT_Long    *result_offset );
291
292  static FT_Error
293  raccess_guess_darwin_hfsplus( FT_Library  library,
294                                FT_Stream   stream,
295                                char       *base_file_name,
296                                char      **result_file_name,
297                                FT_Long    *result_offset );
298
299  static FT_Error
300  raccess_guess_vfat( FT_Library  library,
301                      FT_Stream   stream,
302                      char       *base_file_name,
303                      char      **result_file_name,
304                      FT_Long    *result_offset );
305
306  static FT_Error
307  raccess_guess_linux_cap( FT_Library  library,
308                           FT_Stream   stream,
309                           char       *base_file_name,
310                           char      **result_file_name,
311                           FT_Long    *result_offset );
312
313  static FT_Error
314  raccess_guess_linux_double( FT_Library  library,
315                              FT_Stream   stream,
316                              char       *base_file_name,
317                              char      **result_file_name,
318                              FT_Long    *result_offset );
319
320  static FT_Error
321  raccess_guess_linux_netatalk( FT_Library  library,
322                                FT_Stream   stream,
323                                char       *base_file_name,
324                                char      **result_file_name,
325                                FT_Long    *result_offset );
326
327
328  /*************************************************************************/
329  /****                                                                 ****/
330  /****                       Helper functions                          ****/
331  /****                                                                 ****/
332  /*************************************************************************/
333
334  static FT_Error
335  raccess_guess_apple_generic( FT_Library  library,
336                               FT_Stream   stream,
337                               char       *base_file_name,
338                               FT_Int32    magic,
339                               FT_Long    *result_offset );
340
341  static FT_Error
342  raccess_guess_linux_double_from_file_name( FT_Library  library,
343                                             char *      file_name,
344                                             FT_Long    *result_offset );
345
346  static char *
347  raccess_make_file_name( FT_Memory    memory,
348                          const char  *original_name,
349                          const char  *insertion );
350
351
352  FT_BASE_DEF( void )
353  FT_Raccess_Guess( FT_Library  library,
354                    FT_Stream   stream,
355                    char*       base_name,
356                    char      **new_names,
357                    FT_Long    *offsets,
358                    FT_Error   *errors )
359  {
360    FT_Long  i;
361
362
363    raccess_guess_func  funcs[FT_RACCESS_N_RULES] =
364    {
365      raccess_guess_apple_double,
366      raccess_guess_apple_single,
367      raccess_guess_darwin_ufs_export,
368      raccess_guess_darwin_newvfs,
369      raccess_guess_darwin_hfsplus,
370      raccess_guess_vfat,
371      raccess_guess_linux_cap,
372      raccess_guess_linux_double,
373      raccess_guess_linux_netatalk,
374    };
375
376    for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
377    {
378      new_names[i] = NULL;
379      if ( NULL != stream )
380        errors[i] = FT_Stream_Seek( stream, 0 );
381      else
382        errors[i] = FT_Err_Ok;
383
384      if ( errors[i] )
385        continue ;
386
387      errors[i] = (funcs[i])( library, stream, base_name,
388                              &(new_names[i]), &(offsets[i]) );
389    }
390
391    return;
392  }
393
394
395  static FT_Error
396  raccess_guess_apple_double( FT_Library  library,
397                              FT_Stream   stream,
398                              char       *base_file_name,
399                              char      **result_file_name,
400                              FT_Long    *result_offset )
401  {
402    FT_Int32  magic = ( 0x00 << 24 ) |
403                      ( 0x05 << 16 ) |
404                      ( 0x16 <<  8 ) |
405                        0x07;
406
407
408    *result_file_name = NULL;
409    if ( NULL == stream )
410      return FT_Err_Cannot_Open_Stream;
411
412    return raccess_guess_apple_generic( library, stream, base_file_name,
413                                        magic, result_offset );
414  }
415
416
417  static FT_Error
418  raccess_guess_apple_single( FT_Library  library,
419                              FT_Stream   stream,
420                              char       *base_file_name,
421                              char      **result_file_name,
422                              FT_Long    *result_offset )
423  {
424    FT_Int32  magic = ( 0x00 << 24 ) |
425                      ( 0x05 << 16 ) |
426                      ( 0x16 <<  8 ) |
427                        0x00;
428
429
430    *result_file_name = NULL;
431    if ( NULL == stream )
432      return FT_Err_Cannot_Open_Stream;
433
434    return raccess_guess_apple_generic( library, stream, base_file_name,
435                                        magic, result_offset );
436  }
437
438
439  static FT_Error
440  raccess_guess_darwin_ufs_export( FT_Library  library,
441                                   FT_Stream   stream,
442                                   char       *base_file_name,
443                                   char      **result_file_name,
444                                   FT_Long    *result_offset )
445  {
446    char*      newpath;
447    FT_Error   error;
448    FT_Memory  memory;
449
450    FT_UNUSED( stream );
451
452
453    memory  = library->memory;
454    newpath = raccess_make_file_name( memory, base_file_name, "._" );
455    if ( !newpath )
456      return FT_Err_Out_Of_Memory;
457
458    error = raccess_guess_linux_double_from_file_name( library, newpath,
459                                                       result_offset );
460    if ( !error )
461      *result_file_name = newpath;
462    else
463      FT_FREE( newpath );
464
465    return error;
466  }
467
468
469  static FT_Error
470  raccess_guess_darwin_hfsplus( FT_Library  library,
471                                FT_Stream   stream,
472                                char       *base_file_name,
473                                char      **result_file_name,
474                                FT_Long    *result_offset )
475  {
476    /*
477      Only meaningful on systems with hfs+ drivers (or Macs).
478     */
479    FT_Error   error;
480    char*      newpath;
481    FT_Memory  memory;
482    FT_Long    base_file_len = ft_strlen( base_file_name );
483
484    FT_UNUSED( stream );
485
486
487    memory = library->memory;
488
489    if ( base_file_len + 6 > FT_INT_MAX )
490      return FT_Err_Array_Too_Large;
491
492    if ( FT_ALLOC( newpath, base_file_len + 6 ) )
493      return error;
494
495    FT_MEM_COPY( newpath, base_file_name, base_file_len );
496    FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
497
498    *result_file_name = newpath;
499    *result_offset    = 0;
500
501    return FT_Err_Ok;
502  }
503
504
505  static FT_Error
506  raccess_guess_darwin_newvfs( FT_Library  library,
507                               FT_Stream   stream,
508                               char       *base_file_name,
509                               char      **result_file_name,
510                               FT_Long    *result_offset )
511  {
512    /*
513      Only meaningful on systems with Mac OS X (> 10.1).
514     */
515    FT_Error   error;
516    char*      newpath;
517    FT_Memory  memory;
518    FT_Long    base_file_len = ft_strlen( base_file_name );
519
520    FT_UNUSED( stream );
521
522
523    memory = library->memory;
524
525    if ( base_file_len + 18 > FT_INT_MAX )
526      return FT_Err_Array_Too_Large;
527
528    if ( FT_ALLOC( newpath, base_file_len + 18 ) )
529      return error;
530
531    FT_MEM_COPY( newpath, base_file_name, base_file_len );
532    FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
533
534    *result_file_name = newpath;
535    *result_offset    = 0;
536
537    return FT_Err_Ok;
538  }
539
540
541  static FT_Error
542  raccess_guess_vfat( FT_Library  library,
543                      FT_Stream   stream,
544                      char       *base_file_name,
545                      char      **result_file_name,
546                      FT_Long    *result_offset )
547  {
548    char*      newpath;
549    FT_Memory  memory;
550
551    FT_UNUSED( stream );
552
553
554    memory = library->memory;
555
556    newpath = raccess_make_file_name( memory, base_file_name,
557                                      "resource.frk/" );
558    if ( !newpath )
559      return FT_Err_Out_Of_Memory;
560
561    *result_file_name = newpath;
562    *result_offset    = 0;
563
564    return FT_Err_Ok;
565  }
566
567
568  static FT_Error
569  raccess_guess_linux_cap( FT_Library  library,
570                           FT_Stream   stream,
571                           char       *base_file_name,
572                           char      **result_file_name,
573                           FT_Long    *result_offset )
574  {
575    char*      newpath;
576    FT_Memory  memory;
577
578    FT_UNUSED( stream );
579
580
581    memory = library->memory;
582
583    newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
584    if ( !newpath )
585      return FT_Err_Out_Of_Memory;
586
587    *result_file_name = newpath;
588    *result_offset    = 0;
589
590    return FT_Err_Ok;
591  }
592
593
594  static FT_Error
595  raccess_guess_linux_double( FT_Library  library,
596                              FT_Stream   stream,
597                              char       *base_file_name,
598                              char      **result_file_name,
599                              FT_Long    *result_offset )
600  {
601    char*      newpath;
602    FT_Error   error;
603    FT_Memory  memory;
604
605    FT_UNUSED( stream );
606
607
608    memory = library->memory;
609
610    newpath = raccess_make_file_name( memory, base_file_name, "%" );
611    if ( !newpath )
612      return FT_Err_Out_Of_Memory;
613
614    error = raccess_guess_linux_double_from_file_name( library, newpath,
615                                                       result_offset );
616    if ( !error )
617      *result_file_name = newpath;
618    else
619      FT_FREE( newpath );
620
621    return error;
622  }
623
624
625  static FT_Error
626  raccess_guess_linux_netatalk( FT_Library  library,
627                                FT_Stream   stream,
628                                char       *base_file_name,
629                                char      **result_file_name,
630                                FT_Long    *result_offset )
631  {
632    char*      newpath;
633    FT_Error   error;
634    FT_Memory  memory;
635
636    FT_UNUSED( stream );
637
638
639    memory = library->memory;
640
641    newpath = raccess_make_file_name( memory, base_file_name,
642                                      ".AppleDouble/" );
643    if ( !newpath )
644      return FT_Err_Out_Of_Memory;
645
646    error = raccess_guess_linux_double_from_file_name( library, newpath,
647                                                       result_offset );
648    if ( !error )
649      *result_file_name = newpath;
650    else
651      FT_FREE( newpath );
652
653    return error;
654  }
655
656
657  static FT_Error
658  raccess_guess_apple_generic( FT_Library  library,
659                               FT_Stream   stream,
660                               char       *base_file_name,
661                               FT_Int32    magic,
662                               FT_Long    *result_offset )
663  {
664    FT_Int32   magic_from_stream;
665    FT_Error   error;
666    FT_Int32   version_number = 0;
667    FT_UShort  n_of_entries;
668
669    int        i;
670    FT_UInt32  entry_id, entry_offset, entry_length = 0;
671
672    const FT_UInt32  resource_fork_entry_id = 0x2;
673
674    FT_UNUSED( library );
675    FT_UNUSED( base_file_name );
676    FT_UNUSED( version_number );
677    FT_UNUSED( entry_length   );
678
679
680    if ( FT_READ_LONG( magic_from_stream ) )
681      return error;
682    if ( magic_from_stream != magic )
683      return FT_Err_Unknown_File_Format;
684
685    if ( FT_READ_LONG( version_number ) )
686      return error;
687
688    /* filler */
689    error = FT_Stream_Skip( stream, 16 );
690    if ( error )
691      return error;
692
693    if ( FT_READ_USHORT( n_of_entries ) )
694      return error;
695    if ( n_of_entries == 0 )
696      return FT_Err_Unknown_File_Format;
697
698    for ( i = 0; i < n_of_entries; i++ )
699    {
700      if ( FT_READ_LONG( entry_id ) )
701        return error;
702      if ( entry_id == resource_fork_entry_id )
703      {
704        if ( FT_READ_LONG( entry_offset ) ||
705             FT_READ_LONG( entry_length ) )
706          continue;
707        *result_offset = entry_offset;
708
709        return FT_Err_Ok;
710      }
711      else
712        FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
713      }
714
715    return FT_Err_Unknown_File_Format;
716  }
717
718
719  static FT_Error
720  raccess_guess_linux_double_from_file_name( FT_Library  library,
721                                             char       *file_name,
722                                             FT_Long    *result_offset )
723  {
724    FT_Open_Args  args2;
725    FT_Stream     stream2;
726    char *        nouse = NULL;
727    FT_Error      error;
728
729
730    args2.flags    = FT_OPEN_PATHNAME;
731    args2.pathname = file_name;
732    error = FT_Stream_New( library, &args2, &stream2 );
733    if ( error )
734      return error;
735
736    error = raccess_guess_apple_double( library, stream2, file_name,
737                                        &nouse, result_offset );
738
739    FT_Stream_Free( stream2, 0 );
740
741    return error;
742  }
743
744
745  static char*
746  raccess_make_file_name( FT_Memory    memory,
747                          const char  *original_name,
748                          const char  *insertion )
749  {
750    char*        new_name;
751    char*        tmp;
752    const char*  slash;
753    unsigned     new_length;
754    FT_Error     error = FT_Err_Ok;
755
756    FT_UNUSED( error );
757
758
759    new_length = ft_strlen( original_name ) + ft_strlen( insertion );
760    if ( FT_ALLOC( new_name, new_length + 1 ) )
761      return NULL;
762
763    tmp = ft_strrchr( original_name, '/' );
764    if ( tmp )
765    {
766      ft_strncpy( new_name, original_name, tmp - original_name + 1 );
767      new_name[tmp - original_name + 1] = '\0';
768      slash = tmp + 1;
769    }
770    else
771    {
772      slash       = original_name;
773      new_name[0] = '\0';
774    }
775
776    ft_strcat( new_name, insertion );
777    ft_strcat( new_name, slash );
778
779    return new_name;
780  }
781
782
783#else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
784
785
786  /*************************************************************************/
787  /*                  Dummy function; just sets errors                     */
788  /*************************************************************************/
789
790  FT_BASE_DEF( void )
791  FT_Raccess_Guess( FT_Library  library,
792                    FT_Stream   stream,
793                    char       *base_name,
794                    char      **new_names,
795                    FT_Long    *offsets,
796                    FT_Error   *errors )
797  {
798    int  i;
799
800    FT_UNUSED( library );
801    FT_UNUSED( stream );
802    FT_UNUSED( base_name );
803
804
805    for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
806    {
807      new_names[i] = NULL;
808      offsets[i]   = 0;
809      errors[i]    = FT_Err_Unimplemented_Feature;
810    }
811  }
812
813
814#endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
815
816
817/* END */
Note: See TracBrowser for help on using the repository browser.