1/***************************************************************************/
2/*                                                                         */
3/*  t1parse.c                                                              */
4/*                                                                         */
5/*    Type 1 parser (body).                                                */
6/*                                                                         */
7/*  Copyright 1996-2005, 2008, 2009, 2012, 2013 by                         */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19  /*************************************************************************/
20  /*                                                                       */
21  /* The Type 1 parser is in charge of the following:                      */
22  /*                                                                       */
23  /*  - provide an implementation of a growing sequence of objects called  */
24  /*    a `T1_Table' (used to build various tables needed by the loader).  */
25  /*                                                                       */
26  /*  - opening .pfb and .pfa files to extract their top-level and private */
27  /*    dictionaries.                                                      */
28  /*                                                                       */
29  /*  - read numbers, arrays & strings from any dictionary.                */
30  /*                                                                       */
31  /* See `t1load.c' to see how data is loaded from the font file.          */
32  /*                                                                       */
33  /*************************************************************************/
34
35
36#include "../../include/ft2build.h"
37#include "../../include/freetype/internal/ftdebug.h"
38#include "../../include/freetype/internal/ftstream.h"
39#include "../../include/freetype/internal/psaux.h"
40
41#include "t1parse.h"
42
43#include "t1errors.h"
44
45
46  /*************************************************************************/
47  /*                                                                       */
48  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
49  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
50  /* messages during execution.                                            */
51  /*                                                                       */
52#undef  FT_COMPONENT
53#define FT_COMPONENT  trace_t1parse
54
55
56  /*************************************************************************/
57  /*************************************************************************/
58  /*************************************************************************/
59  /*****                                                               *****/
60  /*****                   INPUT STREAM PARSER                         *****/
61  /*****                                                               *****/
62  /*************************************************************************/
63  /*************************************************************************/
64  /*************************************************************************/
65
66
67  /* see Adobe Technical Note 5040.Download_Fonts.pdf */
68
69  static FT_Error
70  read_pfb_tag( FT_Stream   stream,
71                FT_UShort  *atag,
72                FT_ULong   *asize )
73  {
74    FT_Error   error;
75    FT_UShort  tag;
76    FT_ULong   size;
77
78
79    *atag  = 0;
80    *asize = 0;
81
82    if ( !FT_READ_USHORT( tag ) )
83    {
84      if ( tag == 0x8001U || tag == 0x8002U )
85      {
86        if ( !FT_READ_ULONG_LE( size ) )
87          *asize = size;
88      }
89
90      *atag = tag;
91    }
92
93    return error;
94  }
95
96
97  static FT_Error
98  check_type1_format( FT_Stream    stream,
99                      const char*  header_string,
100                      size_t       header_length )
101  {
102    FT_Error   error;
103    FT_UShort  tag;
104    FT_ULong   dummy;
105
106
107    if ( FT_STREAM_SEEK( 0 ) )
108      goto Exit;
109
110    error = read_pfb_tag( stream, &tag, &dummy );
111    if ( error )
112      goto Exit;
113
114    /* We assume that the first segment in a PFB is always encoded as   */
115    /* text.  This might be wrong (and the specification doesn't insist */
116    /* on that), but we have never seen a counterexample.               */
117    if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )
118      goto Exit;
119
120    if ( !FT_FRAME_ENTER( header_length ) )
121    {
122      error = FT_Err_Ok;
123
124      if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )
125        error = FT_THROW( Unknown_File_Format );
126
127      FT_FRAME_EXIT();
128    }
129
130  Exit:
131    return error;
132  }
133
134
135  FT_LOCAL_DEF( FT_Error )
136  T1_New_Parser( T1_Parser      parser,
137                 FT_Stream      stream,
138                 FT_Memory      memory,
139                 PSAux_Service  psaux )
140  {
141    FT_Error   error;
142    FT_UShort  tag;
143    FT_ULong   size;
144
145
146    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
147
148    parser->stream       = stream;
149    parser->base_len     = 0;
150    parser->base_dict    = 0;
151    parser->private_len  = 0;
152    parser->private_dict = 0;
153    parser->in_pfb       = 0;
154    parser->in_memory    = 0;
155    parser->single_block = 0;
156
157    /* check the header format */
158    error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
159    if ( error )
160    {
161      if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
162        goto Exit;
163
164      error = check_type1_format( stream, "%!FontType", 10 );
165      if ( error )
166      {
167        FT_TRACE2(( "  not a Type 1 font\n" ));
168        goto Exit;
169      }
170    }
171
172    /******************************************************************/
173    /*                                                                */
174    /* Here a short summary of what is going on:                      */
175    /*                                                                */
176    /*   When creating a new Type 1 parser, we try to locate and load */
177    /*   the base dictionary if this is possible (i.e., for PFB       */
178    /*   files).  Otherwise, we load the whole font into memory.      */
179    /*                                                                */
180    /*   When `loading' the base dictionary, we only setup pointers   */
181    /*   in the case of a memory-based stream.  Otherwise, we         */
182    /*   allocate and load the base dictionary in it.                 */
183    /*                                                                */
184    /*   parser->in_pfb is set if we are in a binary (`.pfb') font.   */
185    /*   parser->in_memory is set if we have a memory stream.         */
186    /*                                                                */
187
188    /* try to compute the size of the base dictionary;     */
189    /* look for a Postscript binary file tag, i.e., 0x8001 */
190    if ( FT_STREAM_SEEK( 0L ) )
191      goto Exit;
192
193    error = read_pfb_tag( stream, &tag, &size );
194    if ( error )
195      goto Exit;
196
197    if ( tag != 0x8001U )
198    {
199      /* assume that this is a PFA file for now; an error will */
200      /* be produced later when more things are checked        */
201      if ( FT_STREAM_SEEK( 0L ) )
202        goto Exit;
203      size = stream->size;
204    }
205    else
206      parser->in_pfb = 1;
207
208    /* now, try to load `size' bytes of the `base' dictionary we */
209    /* found previously                                          */
210
211    /* if it is a memory-based resource, set up pointers */
212    if ( !stream->read )
213    {
214      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
215      parser->base_len  = size;
216      parser->in_memory = 1;
217
218      /* check that the `size' field is valid */
219      if ( FT_STREAM_SKIP( size ) )
220        goto Exit;
221    }
222    else
223    {
224      /* read segment in memory -- this is clumsy, but so does the format */
225      if ( FT_ALLOC( parser->base_dict, size )       ||
226           FT_STREAM_READ( parser->base_dict, size ) )
227        goto Exit;
228      parser->base_len = size;
229    }
230
231    parser->root.base   = parser->base_dict;
232    parser->root.cursor = parser->base_dict;
233    parser->root.limit  = parser->root.cursor + parser->base_len;
234
235  Exit:
236    if ( error && !parser->in_memory )
237      FT_FREE( parser->base_dict );
238
239    return error;
240  }
241
242
243  FT_LOCAL_DEF( void )
244  T1_Finalize_Parser( T1_Parser  parser )
245  {
246    FT_Memory  memory = parser->root.memory;
247
248
249    /* always free the private dictionary */
250    FT_FREE( parser->private_dict );
251
252    /* free the base dictionary only when we have a disk stream */
253    if ( !parser->in_memory )
254      FT_FREE( parser->base_dict );
255
256    parser->root.funcs.done( &parser->root );
257  }
258
259
260  FT_LOCAL_DEF( FT_Error )
261  T1_Get_Private_Dict( T1_Parser      parser,
262                       PSAux_Service  psaux )
263  {
264    FT_Stream  stream = parser->stream;
265    FT_Memory  memory = parser->root.memory;
266    FT_Error   error  = FT_Err_Ok;
267    FT_ULong   size;
268
269
270    if ( parser->in_pfb )
271    {
272      /* in the case of the PFB format, the private dictionary can be  */
273      /* made of several segments.  We thus first read the number of   */
274      /* segments to compute the total size of the private dictionary  */
275      /* then re-read them into memory.                                */
276      FT_Long    start_pos = FT_STREAM_POS();
277      FT_UShort  tag;
278
279
280      parser->private_len = 0;
281      for (;;)
282      {
283        error = read_pfb_tag( stream, &tag, &size );
284        if ( error )
285          goto Fail;
286
287        if ( tag != 0x8002U )
288          break;
289
290        parser->private_len += size;
291
292        if ( FT_STREAM_SKIP( size ) )
293          goto Fail;
294      }
295
296      /* Check that we have a private dictionary there */
297      /* and allocate private dictionary buffer        */
298      if ( parser->private_len == 0 )
299      {
300        FT_ERROR(( "T1_Get_Private_Dict:"
301                   " invalid private dictionary section\n" ));
302        error = FT_THROW( Invalid_File_Format );
303        goto Fail;
304      }
305
306      if ( FT_STREAM_SEEK( start_pos )                           ||
307           FT_ALLOC( parser->private_dict, parser->private_len ) )
308        goto Fail;
309
310      parser->private_len = 0;
311      for (;;)
312      {
313        error = read_pfb_tag( stream, &tag, &size );
314        if ( error || tag != 0x8002U )
315        {
316          error = FT_Err_Ok;
317          break;
318        }
319
320        if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
321                             size ) )
322          goto Fail;
323
324        parser->private_len += size;
325      }
326    }
327    else
328    {
329      /* We have already `loaded' the whole PFA font file into memory; */
330      /* if this is a memory resource, allocate a new block to hold    */
331      /* the private dict.  Otherwise, simply overwrite into the base  */
332      /* dictionary block in the heap.                                 */
333
334      /* first of all, look at the `eexec' keyword */
335      FT_Byte*  cur   = parser->base_dict;
336      FT_Byte*  limit = cur + parser->base_len;
337      FT_Byte   c;
338
339
340    Again:
341      for (;;)
342      {
343        c = cur[0];
344        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
345                                            /* whitespace + 4 chars        */
346        {
347          if ( cur[1] == 'e' &&
348               cur[2] == 'x' &&
349               cur[3] == 'e' &&
350               cur[4] == 'c' )
351            break;
352        }
353        cur++;
354        if ( cur >= limit )
355        {
356          FT_ERROR(( "T1_Get_Private_Dict:"
357                     " could not find `eexec' keyword\n" ));
358          error = FT_THROW( Invalid_File_Format );
359          goto Exit;
360        }
361      }
362
363      /* check whether `eexec' was real -- it could be in a comment */
364      /* or string (as e.g. in u003043t.gsf from ghostscript)       */
365
366      parser->root.cursor = parser->base_dict;
367      /* set limit to `eexec' + whitespace + 4 characters */
368      parser->root.limit  = cur + 10;
369
370      cur   = parser->root.cursor;
371      limit = parser->root.limit;
372
373      while ( cur < limit )
374      {
375        if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
376          goto Found;
377
378        T1_Skip_PS_Token( parser );
379        if ( parser->root.error )
380          break;
381        T1_Skip_Spaces  ( parser );
382        cur = parser->root.cursor;
383      }
384
385      /* we haven't found the correct `eexec'; go back and continue */
386      /* searching                                                  */
387
388      cur   = limit;
389      limit = parser->base_dict + parser->base_len;
390      goto Again;
391
392      /* now determine where to write the _encrypted_ binary private  */
393      /* dictionary.  We overwrite the base dictionary for disk-based */
394      /* resources and allocate a new block otherwise                 */
395
396    Found:
397      parser->root.limit = parser->base_dict + parser->base_len;
398
399      T1_Skip_PS_Token( parser );
400      cur   = parser->root.cursor;
401      limit = parser->root.limit;
402
403      /* according to the Type1 spec, the first cipher byte must not be  */
404      /* an ASCII whitespace character code (blank, tab, carriage return */
405      /* or line feed).  We have seen Type 1 fonts with two line feed    */
406      /* characters...  So skip now all whitespace character codes.      */
407      while ( cur < limit       &&
408              ( *cur == ' '  ||
409                *cur == '\t' ||
410                *cur == '\r' ||
411                *cur == '\n' ) )
412        ++cur;
413      if ( cur >= limit )
414      {
415        FT_ERROR(( "T1_Get_Private_Dict:"
416                   " `eexec' not properly terminated\n" ));
417        error = FT_THROW( Invalid_File_Format );
418        goto Exit;
419      }
420
421      size = (FT_ULong)( parser->base_len - ( cur - parser->base_dict ) );
422
423      if ( parser->in_memory )
424      {
425        /* note that we allocate one more byte to put a terminating `0' */
426        if ( FT_ALLOC( parser->private_dict, size + 1 ) )
427          goto Fail;
428        parser->private_len = size;
429      }
430      else
431      {
432        parser->single_block = 1;
433        parser->private_dict = parser->base_dict;
434        parser->private_len  = size;
435        parser->base_dict    = 0;
436        parser->base_len     = 0;
437      }
438
439      /* now determine whether the private dictionary is encoded in binary */
440      /* or hexadecimal ASCII format -- decode it accordingly              */
441
442      /* we need to access the next 4 bytes (after the final whitespace */
443      /* following the `eexec' keyword); if they all are hexadecimal    */
444      /* digits, then we have a case of ASCII storage                   */
445
446      if ( cur + 3 < limit                                &&
447           ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
448           ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
449      {
450        /* ASCII hexadecimal encoding */
451        FT_Long  len;
452
453
454        parser->root.cursor = cur;
455        (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
456                                                parser->private_dict,
457                                                parser->private_len,
458                                                &len,
459                                                0 );
460        parser->private_len = len;
461
462        /* put a safeguard */
463        parser->private_dict[len] = '\0';
464      }
465      else
466        /* binary encoding -- copy the private dict */
467        FT_MEM_MOVE( parser->private_dict, cur, size );
468    }
469
470    /* we now decrypt the encoded binary private dictionary */
471    psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
472
473    if ( parser->private_len < 4 )
474    {
475      FT_ERROR(( "T1_Get_Private_Dict:"
476                 " invalid private dictionary section\n" ));
477      error = FT_THROW( Invalid_File_Format );
478      goto Fail;
479    }
480
481    /* replace the four random bytes at the beginning with whitespace */
482    parser->private_dict[0] = ' ';
483    parser->private_dict[1] = ' ';
484    parser->private_dict[2] = ' ';
485    parser->private_dict[3] = ' ';
486
487    parser->root.base   = parser->private_dict;
488    parser->root.cursor = parser->private_dict;
489    parser->root.limit  = parser->root.cursor + parser->private_len;
490
491  Fail:
492  Exit:
493    return error;
494  }
495
496
497/* END */
498