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

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 25.6 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ftrfork.c                                                              */
4/*                                                                         */
5/*    Embedded resource forks accessor (body).                             */
6/*                                                                         */
7/*  Copyright 2004, 2005, 2006, 2007 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 | 0x05 << 16 | 0x16 << 8 | 0x07 );
403
404
405    *result_file_name = NULL;
406    if ( NULL == stream )
407      return FT_Err_Cannot_Open_Stream;
408
409    return raccess_guess_apple_generic( library, stream, base_file_name,
410                                        magic, result_offset );
411  }
412
413
414  static FT_Error
415  raccess_guess_apple_single( FT_Library  library,
416                              FT_Stream   stream,
417                              char       *base_file_name,
418                              char      **result_file_name,
419                              FT_Long    *result_offset )
420  {
421    FT_Int32  magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
422
423
424    *result_file_name = NULL;
425    if ( NULL == stream )
426      return FT_Err_Cannot_Open_Stream;
427
428    return raccess_guess_apple_generic( library, stream, base_file_name,
429                                        magic, result_offset );
430  }
431
432
433  static FT_Error
434  raccess_guess_darwin_ufs_export( FT_Library  library,
435                                   FT_Stream   stream,
436                                   char       *base_file_name,
437                                   char      **result_file_name,
438                                   FT_Long    *result_offset )
439  {
440    char*      newpath;
441    FT_Error   error;
442    FT_Memory  memory;
443
444    FT_UNUSED( stream );
445
446
447    memory  = library->memory;
448    newpath = raccess_make_file_name( memory, base_file_name, "._" );
449    if ( !newpath )
450      return FT_Err_Out_Of_Memory;
451
452    error = raccess_guess_linux_double_from_file_name( library, newpath,
453                                                       result_offset );
454    if ( !error )
455      *result_file_name = newpath;
456    else
457      FT_FREE( newpath );
458
459    return error;
460  }
461
462
463  static FT_Error
464  raccess_guess_darwin_hfsplus( FT_Library  library,
465                                FT_Stream   stream,
466                                char       *base_file_name,
467                                char      **result_file_name,
468                                FT_Long    *result_offset )
469  {
470    /*
471      Only meaningful on systems with hfs+ drivers (or Macs).
472     */
473    FT_Error   error;
474    char*      newpath;
475    FT_Memory  memory;
476    FT_Long    base_file_len = ft_strlen( base_file_name );
477
478    FT_UNUSED( stream );
479
480
481    memory = library->memory;
482
483    if ( base_file_len + 6 > FT_INT_MAX )
484      return FT_Err_Array_Too_Large;
485
486    if ( FT_ALLOC( newpath, base_file_len + 6 ) )
487      return error;
488
489    FT_MEM_COPY( newpath, base_file_name, base_file_len );
490    FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
491
492    *result_file_name = newpath;
493    *result_offset    = 0;
494
495    return FT_Err_Ok;
496  }
497
498
499  static FT_Error
500  raccess_guess_darwin_newvfs( FT_Library  library,
501                               FT_Stream   stream,
502                               char       *base_file_name,
503                               char      **result_file_name,
504                               FT_Long    *result_offset )
505  {
506    /*
507      Only meaningful on systems with Mac OS X (> 10.1).
508     */
509    FT_Error   error;
510    char*      newpath;
511    FT_Memory  memory;
512    FT_Long    base_file_len = ft_strlen( base_file_name );
513
514    FT_UNUSED( stream );
515
516
517    memory = library->memory;
518
519    if ( base_file_len + 18 > FT_INT_MAX )
520      return FT_Err_Array_Too_Large;
521
522    if ( FT_ALLOC( newpath, base_file_len + 18 ) )
523      return error;
524
525    FT_MEM_COPY( newpath, base_file_name, base_file_len );
526    FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
527
528    *result_file_name = newpath;
529    *result_offset    = 0;
530
531    return FT_Err_Ok;
532  }
533
534
535  static FT_Error
536  raccess_guess_vfat( FT_Library  library,
537                      FT_Stream   stream,
538                      char       *base_file_name,
539                      char      **result_file_name,
540                      FT_Long    *result_offset )
541  {
542    char*      newpath;
543    FT_Memory  memory;
544
545    FT_UNUSED( stream );
546
547
548    memory = library->memory;
549
550    newpath = raccess_make_file_name( memory, base_file_name,
551                                      "resource.frk/" );
552    if ( !newpath )
553      return FT_Err_Out_Of_Memory;
554
555    *result_file_name = newpath;
556    *result_offset    = 0;
557
558    return FT_Err_Ok;
559  }
560
561
562  static FT_Error
563  raccess_guess_linux_cap( FT_Library  library,
564                           FT_Stream   stream,
565                           char       *base_file_name,
566                           char      **result_file_name,
567                           FT_Long    *result_offset )
568  {
569    char*      newpath;
570    FT_Memory  memory;
571
572    FT_UNUSED( stream );
573
574
575    memory = library->memory;
576
577    newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
578    if ( !newpath )
579      return FT_Err_Out_Of_Memory;
580
581    *result_file_name = newpath;
582    *result_offset    = 0;
583
584    return FT_Err_Ok;
585  }
586
587
588  static FT_Error
589  raccess_guess_linux_double( FT_Library  library,
590                              FT_Stream   stream,
591                              char       *base_file_name,
592                              char      **result_file_name,
593                              FT_Long    *result_offset )
594  {
595    char*      newpath;
596    FT_Error   error;
597    FT_Memory  memory;
598
599    FT_UNUSED( stream );
600
601
602    memory = library->memory;
603
604    newpath = raccess_make_file_name( memory, base_file_name, "%" );
605    if ( !newpath )
606      return FT_Err_Out_Of_Memory;
607
608    error = raccess_guess_linux_double_from_file_name( library, newpath,
609                                                       result_offset );
610    if ( !error )
611      *result_file_name = newpath;
612    else
613      FT_FREE( newpath );
614
615    return error;
616  }
617
618
619  static FT_Error
620  raccess_guess_linux_netatalk( FT_Library  library,
621                                FT_Stream   stream,
622                                char       *base_file_name,
623                                char      **result_file_name,
624                                FT_Long    *result_offset )
625  {
626    char*      newpath;
627    FT_Error   error;
628    FT_Memory  memory;
629
630    FT_UNUSED( stream );
631
632
633    memory = library->memory;
634
635    newpath = raccess_make_file_name( memory, base_file_name,
636                                      ".AppleDouble/" );
637    if ( !newpath )
638      return FT_Err_Out_Of_Memory;
639
640    error = raccess_guess_linux_double_from_file_name( library, newpath,
641                                                       result_offset );
642    if ( !error )
643      *result_file_name = newpath;
644    else
645      FT_FREE( newpath );
646
647    return error;
648  }
649
650
651  static FT_Error
652  raccess_guess_apple_generic( FT_Library  library,
653                               FT_Stream   stream,
654                               char       *base_file_name,
655                               FT_Int32    magic,
656                               FT_Long    *result_offset )
657  {
658    FT_Int32   magic_from_stream;
659    FT_Error   error;
660    FT_Int32   version_number = 0;
661    FT_UShort  n_of_entries;
662
663    int        i;
664    FT_UInt32  entry_id, entry_offset, entry_length = 0;
665
666    const FT_UInt32  resource_fork_entry_id = 0x2;
667
668    FT_UNUSED( library );
669    FT_UNUSED( base_file_name );
670    FT_UNUSED( version_number );
671    FT_UNUSED( entry_length   );
672
673
674    if ( FT_READ_LONG( magic_from_stream ) )
675      return error;
676    if ( magic_from_stream != magic )
677      return FT_Err_Unknown_File_Format;
678
679    if ( FT_READ_LONG( version_number ) )
680      return error;
681
682    /* filler */
683    error = FT_Stream_Skip( stream, 16 );
684    if ( error )
685      return error;
686
687    if ( FT_READ_USHORT( n_of_entries ) )
688      return error;
689    if ( n_of_entries == 0 )
690      return FT_Err_Unknown_File_Format;
691
692    for ( i = 0; i < n_of_entries; i++ )
693    {
694      if ( FT_READ_LONG( entry_id ) )
695        return error;
696      if ( entry_id == resource_fork_entry_id )
697      {
698        if ( FT_READ_LONG( entry_offset ) ||
699             FT_READ_LONG( entry_length ) )
700          continue;
701        *result_offset = entry_offset;
702
703        return FT_Err_Ok;
704      }
705      else
706        FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
707      }
708
709    return FT_Err_Unknown_File_Format;
710  }
711
712
713  static FT_Error
714  raccess_guess_linux_double_from_file_name( FT_Library  library,
715                                             char       *file_name,
716                                             FT_Long    *result_offset )
717  {
718    FT_Open_Args  args2;
719    FT_Stream     stream2;
720    char *        nouse = NULL;
721    FT_Error      error;
722
723
724    args2.flags    = FT_OPEN_PATHNAME;
725    args2.pathname = file_name;
726    error = FT_Stream_New( library, &args2, &stream2 );
727    if ( error )
728      return error;
729
730    error = raccess_guess_apple_double( library, stream2, file_name,
731                                        &nouse, result_offset );
732
733    FT_Stream_Free( stream2, 0 );
734
735    return error;
736  }
737
738
739  static char*
740  raccess_make_file_name( FT_Memory    memory,
741                          const char  *original_name,
742                          const char  *insertion )
743  {
744    char*        new_name;
745    char*        tmp;
746    const char*  slash;
747    unsigned     new_length;
748    FT_Error     error = FT_Err_Ok;
749
750    FT_UNUSED( error );
751
752
753    new_length = ft_strlen( original_name ) + ft_strlen( insertion );
754    if ( FT_ALLOC( new_name, new_length + 1 ) )
755      return NULL;
756
757    tmp = ft_strrchr( original_name, '/' );
758    if ( tmp )
759    {
760      ft_strncpy( new_name, original_name, tmp - original_name + 1 );
761      new_name[tmp - original_name + 1] = '\0';
762      slash = tmp + 1;
763    }
764    else
765    {
766      slash       = original_name;
767      new_name[0] = '\0';
768    }
769
770    ft_strcat( new_name, insertion );
771    ft_strcat( new_name, slash );
772
773    return new_name;
774  }
775
776
777#else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
778
779
780  /*************************************************************************/
781  /*                  Dummy function; just sets errors                     */
782  /*************************************************************************/
783
784  FT_BASE_DEF( void )
785  FT_Raccess_Guess( FT_Library  library,
786                    FT_Stream   stream,
787                    char       *base_name,
788                    char      **new_names,
789                    FT_Long    *offsets,
790                    FT_Error   *errors )
791  {
792    int  i;
793
794    FT_UNUSED( library );
795    FT_UNUSED( stream );
796    FT_UNUSED( base_name );
797
798
799    for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
800    {
801      new_names[i] = NULL;
802      offsets[i]   = 0;
803      errors[i]    = FT_Err_Unimplemented_Feature;
804    }
805  }
806
807
808#endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
809
810
811/* END */
Note: See TracBrowser for help on using the repository browser.