source: trunk/poppler/freetype-2.1.10/src/base/ftrfork.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 22.5 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ftrfork.c                                                              */
4/*                                                                         */
5/*    Embedded resource forks accessor (body).                             */
6/*                                                                         */
7/*  Copyright 2004, 2005 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  FT_BASE_DEF( FT_Error )
136  FT_Raccess_Get_DataOffsets( FT_Library  library,
137                              FT_Stream   stream,
138                              FT_Long     map_offset,
139                              FT_Long     rdata_pos,
140                              FT_Long     tag,
141                              FT_Long   **offsets,
142                              FT_Long    *count )
143  {
144    FT_Error   error;
145    int        i, j, cnt, subcnt;
146    FT_Long    tag_internal, rpos;
147    FT_Memory  memory = library->memory;
148    FT_Long    temp;
149    FT_Long    *offsets_internal;
150
151
152    error = FT_Stream_Seek( stream, map_offset );
153    if ( error )
154      return error;
155
156    if ( FT_READ_USHORT( cnt ) )
157      return error;
158    cnt++;
159
160    for ( i = 0; i < cnt; ++i )
161    {
162      if ( FT_READ_LONG( tag_internal ) ||
163           FT_READ_USHORT( subcnt )     ||
164           FT_READ_USHORT( rpos )       )
165        return error;
166
167      FT_TRACE2(( "Resource tags: %c%c%c%c\n",
168                  (char)( 0xff & ( tag_internal >> 24 ) ),
169                  (char)( 0xff & ( tag_internal >> 16 ) ),
170                  (char)( 0xff & ( tag_internal >>  8 ) ),
171                  (char)( 0xff & ( tag_internal >>  0 ) ) ));
172
173      if ( tag_internal == tag )
174      {
175        *count = subcnt + 1;
176        rpos  += map_offset;
177
178        error = FT_Stream_Seek( stream, rpos );
179        if ( error )
180          return error;
181
182        if ( FT_ALLOC( offsets_internal, *count * sizeof( FT_Long ) ) )
183          return error;
184
185        for ( j = 0; j < *count; ++j )
186        {
187          (void)FT_STREAM_SKIP( 2 ); /* resource id */
188          (void)FT_STREAM_SKIP( 2 ); /* rsource name */
189
190          if ( FT_READ_LONG( temp ) )
191          {
192            FT_FREE( offsets_internal );
193            return error;
194          }
195
196          offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
197
198          (void)FT_STREAM_SKIP( 4 ); /* mbz */
199        }
200
201        *offsets = offsets_internal;
202
203        return FT_Err_Ok;
204      }
205    }
206
207    return FT_Err_Cannot_Open_Resource;
208  }
209
210
211#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
212
213  /*************************************************************************/
214  /*************************************************************************/
215  /*************************************************************************/
216  /****                                                                 ****/
217  /****                                                                 ****/
218  /****                     Guessing functions                          ****/
219  /****                                                                 ****/
220  /****            When you add a new guessing function,                ****/
221  /****           update FT_RACCESS_N_RULES in ftrfork.h.               ****/
222  /****                                                                 ****/
223  /*************************************************************************/
224  /*************************************************************************/
225  /*************************************************************************/
226
227  typedef FT_Error
228  (*raccess_guess_func)( FT_Library  library,
229                         FT_Stream   stream,
230                         char *      base_file_name,
231                         char      **result_file_name,
232                         FT_Long    *result_offset );
233
234
235  static FT_Error
236  raccess_guess_apple_double( FT_Library  library,
237                              FT_Stream   stream,
238                              char *      base_file_name,
239                              char      **result_file_name,
240                              FT_Long    *result_offset );
241
242  static FT_Error
243  raccess_guess_apple_single( FT_Library  library,
244                              FT_Stream   stream,
245                              char *      base_file_name,
246                              char      **result_file_name,
247                              FT_Long    *result_offset );
248
249  static FT_Error
250  raccess_guess_darwin_ufs_export( FT_Library  library,
251                                   FT_Stream   stream,
252                                   char *      base_file_name,
253                                   char      **result_file_name,
254                                   FT_Long    *result_offset );
255
256  static FT_Error
257  raccess_guess_darwin_hfsplus( FT_Library  library,
258                                FT_Stream   stream,
259                                char *      base_file_name,
260                                char      **result_file_name,
261                                FT_Long    *result_offset );
262
263  static FT_Error
264  raccess_guess_vfat( FT_Library  library,
265                      FT_Stream   stream,
266                      char *      base_file_name,
267                      char      **result_file_name,
268                      FT_Long    *result_offset );
269
270  static FT_Error
271  raccess_guess_linux_cap( FT_Library  library,
272                           FT_Stream   stream,
273                           char *      base_file_name,
274                           char      **result_file_name,
275                           FT_Long    *result_offset );
276
277  static FT_Error
278  raccess_guess_linux_double( FT_Library  library,
279                              FT_Stream   stream,
280                              char *      base_file_name,
281                              char      **result_file_name,
282                              FT_Long    *result_offset );
283
284  static FT_Error
285  raccess_guess_linux_netatalk( FT_Library  library,
286                                FT_Stream   stream,
287                                char *      base_file_name,
288                                char      **result_file_name,
289                                FT_Long    *result_offset );
290
291
292  /*************************************************************************/
293  /****                                                                 ****/
294  /****                       Helper functions                          ****/
295  /****                                                                 ****/
296  /*************************************************************************/
297
298  static FT_Error
299  raccess_guess_apple_generic( FT_Library  library,
300                               FT_Stream   stream,
301                               char *      base_file_name,
302                               FT_Int32    magic,
303                               FT_Long    *result_offset );
304
305  static FT_Error
306  raccess_guess_linux_double_from_file_name( FT_Library  library,
307                                             char *      file_name,
308                                             FT_Long    *result_offset );
309
310  static char *
311  raccess_make_file_name( FT_Memory    memory,
312                          const char  *original_name,
313                          const char  *insertion );
314
315
316  FT_BASE_DEF( void )
317  FT_Raccess_Guess( FT_Library  library,
318                    FT_Stream   stream,
319                    char*       base_name,
320                    char      **new_names,
321                    FT_Long    *offsets,
322                    FT_Error   *errors )
323  {
324    FT_Long  i;
325
326
327    raccess_guess_func  funcs[FT_RACCESS_N_RULES] =
328    {
329      raccess_guess_apple_double,
330      raccess_guess_apple_single,
331      raccess_guess_darwin_ufs_export,
332      raccess_guess_darwin_hfsplus,
333      raccess_guess_vfat,
334      raccess_guess_linux_cap,
335      raccess_guess_linux_double,
336      raccess_guess_linux_netatalk,
337    };
338
339    for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
340    {
341      new_names[i] = NULL;
342      errors[i] = FT_Stream_Seek( stream, 0 );
343      if ( errors[i] )
344        continue ;
345
346      errors[i] = (funcs[i])( library, stream, base_name,
347                              &(new_names[i]), &(offsets[i]) );
348    }
349
350    return;
351  }
352
353
354  static FT_Error
355  raccess_guess_apple_double( FT_Library  library,
356                              FT_Stream   stream,
357                              char *      base_file_name,
358                              char      **result_file_name,
359                              FT_Long    *result_offset )
360  {
361    FT_Int32  magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
362
363
364    *result_file_name = NULL;
365    return raccess_guess_apple_generic( library, stream, base_file_name,
366                                        magic, result_offset );
367  }
368
369
370  static FT_Error
371  raccess_guess_apple_single( FT_Library  library,
372                              FT_Stream   stream,
373                              char *      base_file_name,
374                              char      **result_file_name,
375                              FT_Long    *result_offset )
376  {
377    FT_Int32  magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
378
379
380    *result_file_name = NULL;
381    return raccess_guess_apple_generic( library, stream, base_file_name,
382                                        magic, result_offset );
383  }
384
385
386  static FT_Error
387  raccess_guess_darwin_ufs_export( FT_Library  library,
388                                   FT_Stream   stream,
389                                   char *      base_file_name,
390                                   char      **result_file_name,
391                                   FT_Long    *result_offset )
392  {
393    char*      newpath;
394    FT_Error   error;
395    FT_Memory  memory;
396
397    FT_UNUSED( stream );
398
399
400    memory  = library->memory;
401    newpath = raccess_make_file_name( memory, base_file_name, "._" );
402    if ( !newpath )
403      return FT_Err_Out_Of_Memory;
404
405    error = raccess_guess_linux_double_from_file_name( library, newpath,
406                                                       result_offset );
407    if ( !error )
408      *result_file_name = newpath;
409    else
410      FT_FREE( newpath );
411
412    return error;
413  }
414
415
416  static FT_Error
417  raccess_guess_darwin_hfsplus( FT_Library  library,
418                                FT_Stream   stream,
419                                char *      base_file_name,
420                                char      **result_file_name,
421                                FT_Long    *result_offset )
422  {
423    /*
424      Only meaningful on systems with hfs+ drivers (or Macs).
425     */
426    FT_Error   error;
427    char*      newpath;
428    FT_Memory  memory;
429
430    FT_UNUSED( stream );
431
432
433    memory = library->memory;
434
435    if ( FT_ALLOC( newpath,
436                   ft_strlen( base_file_name ) + ft_strlen( "/rsrc" ) + 1 ) )
437      return error;
438
439    ft_strcpy( newpath, base_file_name );
440    ft_strcat( newpath, "/rsrc" );
441    *result_file_name = newpath;
442    *result_offset = 0;
443    return FT_Err_Ok;
444  }
445
446
447  static FT_Error
448  raccess_guess_vfat( FT_Library  library,
449                      FT_Stream   stream,
450                      char *      base_file_name,
451                      char      **result_file_name,
452                      FT_Long    *result_offset )
453  {
454    char*      newpath;
455    FT_Memory  memory;
456
457    FT_UNUSED( stream );
458
459
460    memory = library->memory;
461
462    newpath = raccess_make_file_name( memory, base_file_name,
463                                      "resource.frk/" );
464    if ( !newpath )
465      return FT_Err_Out_Of_Memory;
466
467    *result_file_name = newpath;
468    *result_offset    = 0;
469
470    return FT_Err_Ok;
471  }
472
473
474  static FT_Error
475  raccess_guess_linux_cap( FT_Library  library,
476                           FT_Stream   stream,
477                           char *      base_file_name,
478                           char      **result_file_name,
479                           FT_Long    *result_offset )
480  {
481    char*      newpath;
482    FT_Memory  memory;
483
484    FT_UNUSED( stream );
485
486
487    memory = library->memory;
488
489    newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
490    if ( !newpath )
491      return FT_Err_Out_Of_Memory;
492
493    *result_file_name = newpath;
494    *result_offset    = 0;
495
496    return FT_Err_Ok;
497  }
498
499
500  static FT_Error
501  raccess_guess_linux_double( FT_Library  library,
502                              FT_Stream   stream,
503                              char *      base_file_name,
504                              char      **result_file_name,
505                              FT_Long    *result_offset )
506  {
507    char*      newpath;
508    FT_Error   error;
509    FT_Memory  memory;
510
511    FT_UNUSED( stream );
512
513
514    memory = library->memory;
515
516    newpath = raccess_make_file_name( memory, base_file_name, "%" );
517    if ( !newpath )
518      return FT_Err_Out_Of_Memory;
519
520    error = raccess_guess_linux_double_from_file_name( library, newpath,
521                                                       result_offset );
522    if ( !error )
523      *result_file_name = newpath;
524    else
525      FT_FREE( newpath );
526
527    return error;
528  }
529
530
531  static FT_Error
532  raccess_guess_linux_netatalk( FT_Library  library,
533                                FT_Stream   stream,
534                                char *      base_file_name,
535                                char      **result_file_name,
536                                FT_Long    *result_offset )
537  {
538    char*      newpath;
539    FT_Error   error;
540    FT_Memory  memory;
541
542    FT_UNUSED( stream );
543
544
545    memory = library->memory;
546
547    newpath = raccess_make_file_name( memory, base_file_name,
548                                      ".AppleDouble/" );
549    if ( !newpath )
550      return FT_Err_Out_Of_Memory;
551
552    error = raccess_guess_linux_double_from_file_name( library, newpath,
553                                                       result_offset );
554    if ( !error )
555      *result_file_name = newpath;
556    else
557      FT_FREE( newpath );
558
559    return error;
560  }
561
562
563  static FT_Error
564  raccess_guess_apple_generic( FT_Library  library,
565                               FT_Stream   stream,
566                               char *      base_file_name,
567                               FT_Int32    magic,
568                               FT_Long    *result_offset )
569  {
570    FT_Int32   magic_from_stream;
571    FT_Error   error;
572    FT_Int32   version_number = 0;
573    FT_UShort  n_of_entries;
574
575    int        i;
576    FT_UInt32  entry_id, entry_offset, entry_length = 0;
577
578    const FT_UInt32  resource_fork_entry_id = 0x2;
579
580    FT_UNUSED( library );
581    FT_UNUSED( base_file_name );
582    FT_UNUSED( version_number );
583    FT_UNUSED( entry_length   );
584
585
586    if ( FT_READ_LONG( magic_from_stream ) )
587      return error;
588    if ( magic_from_stream != magic )
589      return FT_Err_Unknown_File_Format;
590
591    if ( FT_READ_LONG( version_number ) )
592      return error;
593
594    /* filler */
595    error = FT_Stream_Skip( stream, 16 );
596    if ( error )
597      return error;
598
599    if ( FT_READ_USHORT( n_of_entries ) )
600      return error;
601    if ( n_of_entries == 0 )
602      return FT_Err_Unknown_File_Format;
603
604    for ( i = 0; i < n_of_entries; i++ )
605    {
606      if ( FT_READ_LONG( entry_id ) )
607        return error;
608      if ( entry_id == resource_fork_entry_id )
609      {
610        if ( FT_READ_LONG( entry_offset ) ||
611             FT_READ_LONG( entry_length ) )
612          continue;
613        *result_offset = entry_offset;
614
615        return FT_Err_Ok;
616      }
617      else
618        FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
619      }
620
621    return FT_Err_Unknown_File_Format;
622  }
623
624
625  static FT_Error
626  raccess_guess_linux_double_from_file_name( FT_Library  library,
627                                             char *      file_name,
628                                             FT_Long    *result_offset )
629  {
630    FT_Open_Args  args2;
631    FT_Stream     stream2;
632    char *        nouse = NULL;
633    FT_Error      error;
634
635
636    args2.flags    = FT_OPEN_PATHNAME;
637    args2.pathname = file_name;
638    error = FT_Stream_New( library, &args2, &stream2 );
639    if ( error )
640      return error;
641
642    error = raccess_guess_apple_double( library, stream2, file_name,
643                                        &nouse, result_offset );
644
645    FT_Stream_Close( stream2 );
646
647    return error;
648  }
649
650
651  static char*
652  raccess_make_file_name( FT_Memory    memory,
653                          const char  *original_name,
654                          const char  *insertion )
655  {
656    char*        new_name;
657    char*        tmp;
658    const char*  slash;
659    unsigned     new_length;
660    FT_ULong     error = FT_Err_Ok;
661
662    FT_UNUSED( error );
663
664
665    new_length = ft_strlen( original_name ) + ft_strlen( insertion );
666    if ( FT_ALLOC( new_name, new_length + 1 ) )
667      return NULL;
668
669    tmp = ft_strrchr( original_name, '/' );
670    if ( tmp )
671    {
672      ft_strncpy( new_name, original_name, tmp - original_name + 1 );
673      new_name[tmp - original_name + 1] = '\0';
674      slash = tmp + 1;
675    }
676    else
677    {
678      slash       = original_name;
679      new_name[0] = '\0';
680    }
681
682    ft_strcat( new_name, insertion );
683    ft_strcat( new_name, slash );
684
685    return new_name;
686  }
687
688
689#else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
690
691
692  /*************************************************************************/
693  /*                  Dummy function; just sets errors                     */
694  /*************************************************************************/
695
696  FT_BASE_DEF( void )
697  FT_Raccess_Guess( FT_Library  library,
698                    FT_Stream   stream,
699                    char*       base_name,
700                    char      **new_names,
701                    FT_Long    *offsets,
702                    FT_Error   *errors )
703  {
704    int  i;
705
706    FT_UNUSED( library );
707    FT_UNUSED( stream );
708    FT_UNUSED( base_name );
709
710
711    for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
712    {
713      new_names[i] = NULL;
714      offsets[i]   = 0;
715      errors[i]    = FT_Err_Unimplemented_Feature;
716    }
717  }
718
719
720#endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
721
722
723/* END */
Note: See TracBrowser for help on using the repository browser.