Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_fmap.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2020-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
/* Font re-mapping */
16
17
#include "strmio.h"
18
#include "stream.h"
19
#include "scanchar.h"
20
21
#include "pdf_int.h"
22
#include "pdf_types.h"
23
#include "pdf_array.h"
24
#include "pdf_dict.h"
25
#include "pdf_stack.h"
26
#include "pdf_file.h"
27
#include "pdf_misc.h"
28
#include "pdf_fmap.h"
29
30
typedef struct
31
{
32
    const char *keyname;
33
    const char *mappedname;
34
} pdfi_custom_fmap_entry;
35
36
pdfi_custom_fmap_entry pdfi_custom_fmap_entries[] =
37
{
38
  {"Helv", "Helvetica"},
39
  {NULL, NULL}
40
};
41
42
static inline bool pdfi_fmap_file_exists(pdf_context *ctx, pdf_string *fname)
43
0
{
44
0
    char nm[gp_file_name_sizeof];
45
0
    struct stat buf;
46
0
    int code = gs_error_invalidfileaccess;
47
48
0
    if (fname->length < gp_file_name_sizeof) {
49
0
        memcpy(nm, fname->data, fname->length);
50
0
        nm[fname->length] = '\0';
51
0
        code = gp_stat(ctx->memory, (const char *)nm, &buf);
52
0
    }
53
0
    return code >= 0;
54
0
}
55
56
static int
57
pdf_fontmap_open_file(pdf_context *ctx, const char *mapfilename, byte **buf, int *buflen)
58
16.3k
{
59
16.3k
    int code = 0;
60
16.3k
    stream *s;
61
16.3k
    char fname[gp_file_name_sizeof];
62
16.3k
    const char *path_pfx = "Init/";
63
16.3k
    const char *poststring = "\nendstream";
64
16.3k
    const int poststringlen = strlen(poststring);
65
16.3k
    fname[0] = '\0';
66
67
16.3k
    if (strlen(path_pfx) + strlen(mapfilename) + 1 > gp_file_name_sizeof)
68
0
        return_error(gs_error_invalidfileaccess);
69
70
16.3k
    code = pdfi_open_resource_file(ctx, mapfilename, strlen(mapfilename), &s);
71
16.3k
    if (code < 0) {
72
0
        strncat(fname, path_pfx, strlen(path_pfx));
73
0
        strncat(fname, (char *)mapfilename, strlen(mapfilename));
74
0
        code = pdfi_open_resource_file(ctx, fname, strlen(fname), &s);
75
0
    }
76
77
16.3k
    if (code >= 0) {
78
16.3k
        int i;
79
16.3k
        sfseek(s, 0, SEEK_END);
80
16.3k
        *buflen = sftell(s);
81
16.3k
        sfseek(s, 0, SEEK_SET);
82
16.3k
        *buf = gs_alloc_bytes(ctx->memory, *buflen + poststringlen, "pdf_cmap_open_file(buf)");
83
16.3k
        if (*buf != NULL) {
84
16.3k
            sfread((*buf), 1, *buflen, s);
85
16.3k
            memcpy((*buf) + *buflen, poststring, poststringlen);
86
16.3k
            *buflen += poststringlen;
87
            /* This is naff, but works for now
88
               When parsing Fontmap in PS, ";" is defined as "def"
89
               We don't need either, because the dictionary is built from the stack.
90
             */
91
54.7M
            for (i = 0; i < *buflen - 1; i++) {
92
54.7M
                if ((*buf)[i] == ';') {
93
1.47M
                    (*buf)[i] = ' ';
94
1.47M
                }
95
54.7M
            }
96
16.3k
        }
97
0
        else {
98
0
            code = gs_note_error(gs_error_VMerror);
99
0
        }
100
16.3k
        sfclose(s);
101
16.3k
    }
102
16.3k
    return code;
103
16.3k
}
104
105
static int
106
pdf_make_fontmap(pdf_context *ctx, const char *default_fmapname, int cidfmap)
107
16.3k
{
108
16.3k
    byte *fmapbuf = NULL;
109
16.3k
    int code, fmapbuflen;
110
16.3k
    pdf_c_stream *fmapstr = NULL;
111
16.3k
    pdf_stream fakedict = {0};
112
16.3k
    pdfi_custom_fmap_entry *pcfe = pdfi_custom_fmap_entries;
113
16.3k
    int i, j = 0;
114
16.3k
    char fmapname[gp_file_name_sizeof];
115
16.3k
    pdf_c_stream fakemainstream = {0};
116
16.3k
    int stacksize = pdfi_count_stack(ctx);
117
118
16.3k
    strncpy(fmapname, default_fmapname, strlen(default_fmapname) + 1);
119
120
16.3k
    code = pdfi_mark_stack(ctx, PDF_DICT_MARK);
121
16.3k
    if (code < 0)
122
0
        goto done;
123
124
16.3k
    do {
125
16.3k
        if (j < ctx->num_fontmapfiles) {
126
0
            memcpy(fmapname, ctx->fontmapfiles[j].data, ctx->fontmapfiles[j].size);
127
0
            fmapname[ctx->fontmapfiles[j].size] = '\0';
128
0
        }
129
130
16.3k
        code = pdf_fontmap_open_file(ctx, (const char *)fmapname, &fmapbuf, &fmapbuflen);
131
16.3k
        if (code < 0) {
132
0
            if (ctx->args.QUIET != true) {
133
0
                (void)outwrite(ctx->memory, "Warning: ", 9);
134
0
                if (cidfmap)
135
0
                    (void)outwrite(ctx->memory, "cidfmap file ", 13);
136
0
                else
137
0
                    (void)outwrite(ctx->memory, "Fontmap file \"", 14);
138
0
                (void)outwrite(ctx->memory, fmapname, strlen(fmapname));
139
0
                (void)outwrite(ctx->memory, "\" not found.\n", 13);
140
0
                code = 0;
141
0
            }
142
0
        }
143
16.3k
        else {
144
16.3k
            code = pdfi_open_memory_stream_from_memory(ctx, fmapbuflen, fmapbuf, &fmapstr, true);
145
16.3k
            if (code >= 0) {
146
147
16.3k
                if (ctx->main_stream == NULL) {
148
0
                    ctx->main_stream = &fakemainstream;
149
0
                }
150
151
16.3k
                code = pdfi_interpret_content_stream(ctx, fmapstr, &fakedict, NULL);
152
16.3k
                if (ctx->main_stream == &fakemainstream) {
153
0
                    ctx->main_stream = NULL;
154
0
                }
155
16.3k
                gs_free_object(ctx->memory, fmapbuf, "pdf_make_fontmap(fmapbuf)");
156
16.3k
            }
157
16.3k
        }
158
16.3k
        j++;
159
16.3k
    } while(j < ctx->num_fontmapfiles && cidfmap == false && code >= 0);
160
161
16.3k
    if (code >= 0) {
162
16.3k
        if (pdfi_count_stack(ctx) > stacksize) {
163
16.3k
            code = pdfi_dict_from_stack(ctx, 0, 0, true);
164
16.3k
            if (code < 0)
165
0
                goto done;
166
167
16.3k
            if (cidfmap == true) {
168
1.41k
                ctx->pdfcidfmap = (pdf_dict *)ctx->stack_top[-1];
169
1.41k
                pdfi_countup(ctx->pdfcidfmap);
170
1.41k
            }
171
14.8k
            else {
172
14.8k
                ctx->pdffontmap = (pdf_dict *)ctx->stack_top[-1];
173
14.8k
                pdfi_countup(ctx->pdffontmap);
174
14.8k
            }
175
16.3k
            pdfi_pop(ctx, 1);
176
16.3k
            code = 0;
177
178
            /* Add our internal aliases to the fontmap. */
179
16.3k
            if (cidfmap == false) {
180
29.7k
                for (i = 0; pcfe[i].keyname != NULL; i++) {
181
14.8k
                    pdf_obj *value;
182
14.8k
                    bool k;
183
184
                    /* We don't want to *replace* entries */
185
14.8k
                    if (pdfi_dict_known(ctx, ctx->pdffontmap, pcfe[i].keyname, &k) >= 0
186
14.8k
                        && k != true) {
187
14.8k
                        code = pdfi_name_alloc(ctx, (byte *)pcfe[i].mappedname, strlen(pcfe[i].mappedname), &value);
188
14.8k
                        if (code < 0)
189
0
                            continue;
190
14.8k
                        pdfi_countup(value);
191
                        /* If dict_put throws an error, we just carry on - hence the (void) */
192
14.8k
                        (void)pdfi_dict_put(ctx,  ctx->pdffontmap, pcfe[i].keyname, value);
193
14.8k
                        pdfi_countdown(value);
194
14.8k
                    }
195
14.8k
                }
196
14.8k
            }
197
16.3k
        }
198
0
        else {
199
0
            code = gs_note_error(gs_error_syntaxerror);
200
0
        }
201
16.3k
    }
202
16.3k
done:
203
    /* We always want to leave here with a valid map dictionary
204
       even if it's empty
205
     */
206
16.3k
    if (cidfmap == true) {
207
1.41k
        if (ctx->pdfcidfmap == NULL) {
208
0
            code = pdfi_dict_alloc(ctx, 0, &ctx->pdfcidfmap);
209
0
            pdfi_countup(ctx->pdfcidfmap);
210
0
        }
211
1.41k
    }
212
14.8k
    else {
213
14.8k
        if (ctx->pdffontmap == NULL) {
214
0
            code = pdfi_dict_alloc(ctx, 0, &ctx->pdffontmap);
215
0
            pdfi_countup(ctx->pdffontmap);
216
0
        }
217
14.8k
    }
218
16.3k
    pdfi_clearstack(ctx);
219
16.3k
    return code;
220
16.3k
}
221
222
enum {
223
  no_type_font = -1,
224
  type0_font = 0,
225
  type1_font = 1,
226
  cff_font = 2,
227
  type3_font = 3,
228
  tt_font = 42
229
};
230
231
/* For font file scanning we want to treat OTTO as TTF (rather than, for "normal"
232
   font loading, treat OTTO as CFF, hence we need a different type picker.
233
 */
234
static int pdfi_font_scan_type_picker(byte *buf, int64_t buflen)
235
0
{
236
0
#define MAKEMAGIC(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
237
238
0
    if (buflen >= 4) {
239
0
        if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC(0, 1, 0, 0)
240
0
            || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 'r', 'u', 'e')
241
0
            || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 't', 'c', 'f')) {
242
0
            return tt_font;
243
0
        }
244
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('O', 'T', 'T', 'O')) {
245
0
            return tt_font;
246
0
        }
247
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC('%', '!', 'P', 0)) {
248
0
            return type1_font; /* pfa */
249
0
        }
250
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC(1, 0, 4, 0)) {
251
0
            return cff_font; /* 1C/CFF */
252
0
        }
253
0
        else if (MAKEMAGIC(buf[0], buf[1], 0, 0) == MAKEMAGIC(128, 1, 0, 0)) {
254
0
            return type1_font; /* pfb */
255
0
        }
256
0
    }
257
0
    return no_type_font;
258
0
#undef MAKEMAGIC
259
0
}
260
261
static int pdfi_add__to_native_fontmap(pdf_context *ctx, const char *fontname, const char *filepath, const int index)
262
0
{
263
0
    int code;
264
0
    pdf_string *fpstr;
265
266
0
    if (ctx->pdfnativefontmap == NULL) {
267
        /* 32 is just an arbitrary starting point */
268
0
        code = pdfi_dict_alloc(ctx, 32, &ctx->pdfnativefontmap);
269
0
        if (code < 0)
270
0
            return code;
271
0
        pdfi_countup(ctx->pdfnativefontmap);
272
0
    }
273
    /* index == -1 is a file with a single font in it */
274
0
    if (index == -1) {
275
0
        code = pdfi_object_alloc(ctx, PDF_STRING, strlen(filepath), (pdf_obj **)&fpstr);
276
0
        if (code < 0)
277
0
            return code;
278
0
        pdfi_countup(fpstr);
279
0
        memcpy(fpstr->data, filepath, fpstr->length);
280
0
        code = pdfi_dict_put(ctx, ctx->pdfnativefontmap, fontname, (pdf_obj *)fpstr);
281
0
        pdfi_countdown(fpstr);
282
0
    }
283
0
    else {
284
0
        pdf_dict *recdict;
285
0
        pdf_num *ind;
286
287
0
        code = pdfi_object_alloc(ctx, PDF_DICT, 2, (pdf_obj **)&recdict);
288
0
        if (code < 0)
289
0
            return code;
290
0
        pdfi_countup(recdict);
291
292
0
        code = pdfi_object_alloc(ctx, PDF_STRING, strlen(filepath), (pdf_obj **)&fpstr);
293
0
        if (code < 0) {
294
0
            pdfi_countdown(recdict);
295
0
            return code;
296
0
        }
297
0
        pdfi_countup(fpstr);
298
0
        memcpy(fpstr->data, filepath, fpstr->length);
299
0
        code = pdfi_dict_put(ctx, recdict, "Path", (pdf_obj *)fpstr);
300
0
        pdfi_countdown(fpstr);
301
0
        if (code < 0) {
302
0
            pdfi_countdown(recdict);
303
0
            return code;
304
0
        }
305
306
0
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)&ind);
307
0
        if (code < 0) {
308
0
            pdfi_countdown(recdict);
309
0
            return code;
310
0
        }
311
0
        ind->value.i = index;
312
0
        pdfi_countup(ind);
313
0
        code = pdfi_dict_put(ctx, recdict, "Index", (pdf_obj *)ind);
314
0
        pdfi_countdown(ind);
315
0
        if (code < 0) {
316
0
            pdfi_countdown(recdict);
317
0
            return code;
318
0
        }
319
0
        code = pdfi_dict_put(ctx, ctx->pdfnativefontmap, fontname, (pdf_obj *)recdict);
320
0
        pdfi_countdown(recdict);
321
0
    }
322
323
0
    return code;
324
0
}
325
326
static inline int
327
pdfi_end_ps_token(int c)
328
0
{
329
0
    return (c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA) || (c == '/')  || (c == '\0');
330
0
}
331
332
/* Naive way to find a Type 1 /FontName key */
333
static int pdfi_type1_add_to_native_map(pdf_context *ctx, stream *f, char *fname, char *pname, int pname_size)
334
0
{
335
0
    gs_string buf;
336
0
    uint count = 0;
337
0
    int code = gs_error_undefined;
338
0
    char *namestr = NULL, *enamestr;
339
0
    char *typestr;
340
0
    bool pin_eol = false; /* initialised just to placate coverity */
341
0
    int type = -1;
342
0
    buf.data = (byte *)pname;
343
0
    buf.size = pname_size;
344
345
    /* It's not an absolute requirement, but it is a de facto standard that
346
       /FontType and /FontName keys start in column 0 of their lines
347
     */
348
0
    while ((code = sreadline(f, NULL, NULL, NULL, &buf, NULL, &count, &pin_eol, NULL)) >= 0) {
349
0
        if (buf.size > 9 && memcmp(buf.data, "/FontName", 9) == 0) {
350
0
            namestr = (char *)buf.data + 9;
351
0
            while (pdfi_end_ps_token(*namestr))
352
0
                namestr++;
353
0
            if (*namestr != '\0') {
354
0
                while(*namestr == 0x20 || *namestr == 0x9)
355
0
                    namestr++;
356
0
                if (*namestr == '/')
357
0
                    namestr++;
358
0
                enamestr = namestr;
359
0
                while(!pdfi_end_ps_token((int)*enamestr))
360
0
                    enamestr++;
361
0
                count = enamestr - namestr > pname_size - 1 ? pname_size - 1 : enamestr - namestr;
362
0
                memcpy(pname, namestr, count);
363
0
                pname[count] = '\0';
364
0
                buf.data += count + 1;
365
0
                buf.size -= count + 1;
366
0
                if (type == 1)
367
0
                    break;
368
0
            }
369
0
        }
370
0
        else if (buf.size > 9 && memcmp(buf.data, "/FontType", 9) == 0) {
371
0
            typestr = (char *)buf.data + 9;
372
0
            while (pdfi_end_ps_token(*typestr))
373
0
                typestr++;
374
0
            if (*typestr != '\0') {
375
0
                while(*typestr == 0x20 || *typestr == 0x9)
376
0
                    namestr++;
377
0
                if (*typestr == '/')
378
0
                    typestr++;
379
0
                enamestr = typestr;
380
0
                while(!pdfi_end_ps_token((int)*enamestr))
381
0
                    enamestr++;
382
0
                count = enamestr - typestr > pname_size - 1 ? pname_size - 1 : enamestr - typestr;
383
0
                if (count == 1 && *typestr == '1') {
384
0
                    type = 1;
385
0
                    if (namestr != NULL)
386
0
                        break;
387
0
                }
388
0
            }
389
0
        }
390
0
        else if (buf.size >= 17 && memcmp(buf.data, "currentfile eexec", 17) == 0)
391
0
            break;
392
0
        count = 0;
393
0
    }
394
0
    if (type == 1 && namestr != NULL) {
395
0
        code = pdfi_add__to_native_fontmap(ctx, (const char *)pname, (const char *)fname, -1);
396
0
    }
397
0
    return code < 0 ? code : gs_error_handled;
398
0
}
399
400
static inline int
401
u16(const byte *p)
402
0
{
403
0
    return (p[0] << 8) | p[1];
404
0
}
405
406
static inline int
407
sru16(stream *s)
408
0
{
409
0
    byte p[2];
410
0
    int code = sfread(p, 1, 2, s);
411
412
0
    if (code < 0)
413
0
        return 0;
414
415
0
    return u16(p);
416
0
}
417
418
static inline int
419
u32(const byte *p)
420
0
{
421
0
    return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
422
0
}
423
424
static inline int
425
sru32(stream *s)
426
0
{
427
0
    byte p[4];
428
0
    int code = sfread(p, 1, 4, s);
429
0
    if (code < 0)
430
0
        return 0;
431
432
0
    return u32(p);
433
0
}
434
435
static int pdfi_ttf_add_to_native_map(pdf_context *ctx, stream *f, byte magic[4], char *fname, char *pname, int pname_size)
436
0
{
437
0
    int ntables, i, j, k, code2, code = gs_error_undefined;
438
0
    char table[4];
439
0
    int nte, storageOffset;
440
0
    bool include_index = false;
441
0
    uint32_t nfonts = 1, tableoffs;
442
0
    int findex;
443
0
    gs_offset_t l;
444
445
0
    code2 = sfseek(f, 0, SEEK_END);
446
0
    if (code2 < 0)
447
0
        return code;
448
0
    l = stell(f);
449
    /* 4 to skip the magic number */
450
0
    code2 = sfseek(f, 4, SEEK_SET);
451
0
    if (code2 < 0)
452
0
        return code;
453
454
0
    if (memcmp(magic, "ttcf", 4) == 0) {
455
0
        uint32_t ver;
456
0
        include_index = true;
457
0
        ver = sru32(f);
458
0
        if (ver != 0x00010000 && ver !=0x00020000) {
459
0
            dmprintf1(ctx->memory, "Unknown TTC header version %08X.\n", ver);
460
0
            return_error(gs_error_invalidaccess);
461
0
        }
462
0
        nfonts = sru32(f);
463
        /* There isn't a specific limit on the number of fonts,
464
           freetype limits to 255, so we'll do the same here
465
         */
466
0
        if (nfonts > 255)
467
0
            return_error(gs_error_invalidfont);
468
0
    }
469
470
0
    for (findex = 0; findex < nfonts; findex++) {
471
0
        if (include_index == true ) {
472
0
            if (findex * 4 > l)
473
0
                break;
474
0
            code2 = sfseek(f, findex * 4, SEEK_CUR);
475
0
            if (code2 < 0)
476
0
                return code2;
477
478
0
            tableoffs = sru32(f);
479
0
            if (tableoffs + 4 > l)
480
0
                break;
481
0
            code2 = sfseek(f, tableoffs + 4, SEEK_SET);
482
0
            if (code2 < 0)
483
0
                return code2;
484
0
        }
485
486
0
        ntables = sru16(f);
487
        /* Similar to above - no spec limit, but we do the same
488
           as freetype
489
         */
490
0
        if (ntables > 255)
491
0
            continue;
492
493
        /* Skip the remainder of the invariant header bytes */
494
0
        (void)sru16(f);
495
0
        (void)sru32(f);
496
497
0
        for (i = 0, code2 = 0; i < ntables && code2 >= 0; i++) {
498
0
            if (stell(f) + 4 > l) {
499
0
                code2 = gs_error_ioerror;
500
0
                continue;
501
0
            }
502
0
            code2 = sfread(table, 1, 4, f);
503
0
            if (code2 < 0)
504
0
                return code2;
505
0
            if (!memcmp(table, "name", 4)) {
506
0
                uint table_pos, table_len;
507
0
                byte *namet;
508
0
                (void)sru32(f); /* skip checksum */
509
510
0
                table_pos = sru32(f);
511
0
                table_len = sru32(f);
512
0
                if (table_pos + table_len > l) {
513
0
                    code2 = gs_error_ioerror;
514
0
                    continue;
515
0
                }
516
517
0
                code2 = sfseek(f, table_pos, SEEK_SET);
518
0
                if (code2 < 0)
519
0
                    continue;
520
521
0
                namet = (byte *)gs_alloc_bytes(ctx->memory, table_len, "pdfi_ttf_add_to_native_map");
522
0
                if (namet == NULL)
523
0
                    return_error(gs_error_VMerror);
524
0
                code2 = sfread(namet, 1, table_len, f);
525
0
                if (code2 < 0) {
526
0
                    gs_free_object(ctx->memory, namet,"pdfi_ttf_add_to_native_map");
527
0
                    continue;
528
0
                }
529
0
                nte = u16(namet + 2);
530
                /* Again, arbitrary limit... */
531
0
                if (nte > 255) {
532
0
                    gs_free_object(ctx->memory, namet,"pdfi_ttf_add_to_native_map");
533
0
                    continue;
534
0
                }
535
0
                storageOffset = u16(namet + 4);
536
537
0
                for (j = 0; j < nte; j++) {
538
0
                    byte *rec = namet + 6 + j * 12;
539
0
                    if (u16(rec + 6) == 6) {
540
0
                        int nl = u16(rec + 8);
541
0
                        int noffs = u16(rec + 10);
542
0
                        if (nl + noffs + storageOffset > table_len) {
543
0
                            break;
544
0
                        }
545
0
                        memcpy(pname, namet + storageOffset + noffs, nl);
546
0
                        pname[nl] = '\0';
547
0
                        for (k = 0; k < nl; k++)
548
0
                            if (pname[k] < 32 || pname[k] > 126) /* is it a valid name? */
549
0
                                break;
550
0
                        if (k == nl) {
551
0
                            code = 0;
552
0
                            break;
553
0
                       }
554
0
                    }
555
0
                }
556
0
                if (code == gs_error_undefined) {
557
0
                    for (j = 0; j < nte; j++) {
558
0
                        byte *rec = namet + 6 + j * 12;
559
0
                        if (u16(rec + 6) == 4) {
560
0
                            int nl = u16(rec + 8);
561
0
                            int noffs = u16(rec + 10);
562
0
                            if (nl + noffs + storageOffset > table_len) {
563
0
                                break;
564
0
                            }
565
0
                            memcpy(pname, namet + storageOffset + noffs, nl);
566
0
                            pname[nl] = '\0';
567
0
                            for (k = 0; k < nl; k++)
568
0
                                if (pname[k] < 32 || pname[k] > 126) /* is it a valid name? */
569
0
                                    break;
570
0
                            if (k == nl)
571
0
                                code = 0;
572
0
                            break;
573
0
                        }
574
0
                    }
575
0
                }
576
0
                gs_free_object(ctx->memory, namet, "pdfi_ttf_add_to_native_map");
577
0
                break;
578
0
            }
579
0
            else {
580
0
                sfseek(f, 12, SEEK_CUR);
581
0
            }
582
0
        }
583
0
        if (code >= 0)
584
0
            code = pdfi_add__to_native_fontmap(ctx, (const char *)pname, (const char *)fname, (include_index == true ? findex : -1));
585
0
    }
586
0
    return code;
587
0
}
588
589
static const char *font_scan_skip_list[] = {
590
  ".afm",
591
  ".bat",
592
  ".c",
593
  ".cmd",
594
  ".com",
595
  ".dir",
596
  ".dll",
597
  ".doc",
598
  ".drv",
599
  ".exe",
600
  ".fon",
601
  ".fot",
602
  ".h",
603
  ".o",
604
  ".obj",
605
  ".pfm",
606
  ".pss",
607
  ".txt",
608
  ".gz",
609
  ".pcf"
610
};
611
612
static bool font_scan_skip_file(char *fname)
613
0
{
614
0
    size_t l2, l = strlen(fname);
615
0
    bool skip = false;
616
0
    int i;
617
618
0
    for (i = 0; i < (sizeof(font_scan_skip_list)/sizeof(*font_scan_skip_list)); i++) {
619
0
        l2 = strlen(font_scan_skip_list[i]);
620
0
        if (memcmp(font_scan_skip_list[i], fname + l - l2, l2) == 0) {
621
0
            skip = true;
622
0
            break;
623
0
        }
624
0
    }
625
0
    return skip;
626
0
}
627
628
static int pdfi_generate_native_fontmap(pdf_context *ctx)
629
760k
{
630
760k
    file_enum *fe;
631
760k
    int i;
632
760k
    char *patrn= NULL;
633
760k
    char *result = NULL;
634
760k
    char *working = NULL;
635
760k
    byte magic[4]; /* We only (currently) use up to 4 bytes for type guessing */
636
760k
    stream *sf;
637
760k
    int code = 0, l;
638
760k
    uint nread;
639
640
760k
    if (ctx->pdfnativefontmap != NULL) /* Only run this once */
641
0
        return 0;
642
760k
    if (ctx->args.nonativefontmap == true) {
643
        /* Basically create an empty dictionary */
644
0
        code = pdfi_dict_alloc(ctx, 1, &ctx->pdfnativefontmap);
645
0
        if (code < 0)
646
0
            return code;
647
0
        pdfi_countup(ctx->pdfnativefontmap);
648
0
        return 0;
649
0
    }
650
651
760k
    patrn = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
652
760k
    result = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
653
760k
    working = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
654
760k
    if (patrn == NULL || result == NULL || working == NULL) {
655
0
        gs_free_object(ctx->memory, patrn, "pdfi_generate_native_fontmap");
656
0
        gs_free_object(ctx->memory, result, "pdfi_generate_native_fontmap");
657
0
        gs_free_object(ctx->memory, working, "pdfi_generate_native_fontmap");
658
0
        return_error(gs_error_VMerror);
659
0
    }
660
661
760k
    for (i = 0; i < ctx->search_paths.num_font_paths; i++) {
662
663
0
        memcpy(patrn, ctx->search_paths.font_paths[i].data, ctx->search_paths.font_paths[i].size);
664
0
        memcpy(patrn + ctx->search_paths.font_paths[i].size, "/*", 2);
665
0
        patrn[ctx->search_paths.font_paths[i].size + 2] = '\0';
666
667
0
        fe = gp_enumerate_files_init(ctx->memory, (const char *)patrn, strlen(patrn));
668
0
        while ((l = gp_enumerate_files_next(ctx->memory, fe, result, gp_file_name_sizeof - 1)) != ~(uint) 0) {
669
0
            int type;
670
0
            result[l] = '\0';
671
672
0
            if (font_scan_skip_file(result))
673
0
                continue;
674
675
0
            sf = sfopen(result, "r", ctx->memory);
676
0
            code = sgets(sf, magic, 4, &nread);
677
0
            if (code < 0 || nread < 4) {
678
0
                sfclose(sf);
679
0
                continue;
680
0
            }
681
682
0
            code = sfseek(sf, 0, SEEK_SET);
683
0
            if (code < 0) {
684
0
                sfclose(sf);
685
0
                continue;
686
0
            }
687
            /* Slightly naff: in this one case, we want to treat OTTO fonts
688
               as Truetype, so we lookup the TTF 'name' table - it's more efficient
689
               than decoding the CFF, and probably will give more expected results
690
             */
691
0
            if (memcmp(magic, "OTTO", 4) == 0 || memcmp(magic, "ttcf", 4) == 0) {
692
0
                type = tt_font;
693
0
            }
694
0
            else {
695
0
                type = pdfi_font_scan_type_picker((byte *)magic, 4);
696
0
            }
697
0
            switch(type) {
698
0
                case tt_font:
699
0
                  code = pdfi_ttf_add_to_native_map(ctx, sf, magic, result, working, gp_file_name_sizeof);
700
0
                  break;
701
0
                case cff_font:
702
0
                      code = gs_error_undefined;
703
0
                  break;
704
0
                case type1_font:
705
0
                default:
706
0
                  code = pdfi_type1_add_to_native_map(ctx, sf, result, working, gp_file_name_sizeof);
707
0
                  break;
708
0
            }
709
0
            sfclose(sf);
710
            /* We ignore most errors, on the basis it probably means it wasn't a valid font file */
711
0
            if (code == gs_error_VMerror)
712
0
                break;
713
0
            code = 0;
714
0
        }
715
        /* We only need to explicitly destroy the enumerator if we exit before enumeration is complete */
716
0
        if (code < 0)
717
0
            gp_enumerate_files_close(ctx->memory, fe);
718
0
    }
719
720
#if 0
721
    if (ctx->pdfnativefontmap != NULL) {
722
        uint64_t ind;
723
        int find = -1;
724
        pdf_name *key = NULL;
725
        pdf_obj *v = NULL;
726
        pdf_string *val = NULL;
727
        (void)pdfi_dict_key_first(ctx, ctx->pdfnativefontmap, (pdf_obj **) &key, &ind);
728
        (void)pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, key, (pdf_obj **)&v);
729
        for (j = 0; j < key->length; j++)
730
            dprintf1("%c", key->data[j]);
731
        if (pdfi_type_of(v) == PDF_DICT) {
732
            pdf_num *n;
733
            pdf_string *val2;
734
            code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
735
            if (code >= 0 && pdfi_type_of(n) == PDF_INT)
736
                find = n->value.i;
737
            else
738
                code = 0;
739
            (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
740
            val = val2;
741
        }
742
        else {
743
            val = (pdf_string *)v;
744
        }
745
        dprintf(" ");
746
        for (j = 0; j < val->length; j++)
747
            dprintf1("%c", val->data[j]);
748
        if (find != -1) {
749
            dprintf1("  Index = %d", find);
750
            find = -1;
751
        }
752
753
        dprintf("\n");
754
        pdfi_countdown(key);
755
        pdfi_countdown(val);
756
757
        while (pdfi_dict_key_next(ctx, ctx->pdfnativefontmap, (pdf_obj **) &key, &ind) >= 0 && ind > 0) {
758
            (void)pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, key, (pdf_obj **)&v);
759
            for (j = 0; j < key->length; j++)
760
                dprintf1("%c", key->data[j]);
761
            if (pdfi_type_of(v) == PDF_DICT) {
762
                pdf_num *n;
763
                pdf_string *val2;
764
                code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
765
                if (code >= 0 && pdfi_type_of(n) == PDF_INT)
766
                    find = n->value.i;
767
                else
768
                    code = 0;
769
                (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
770
                val = val2;
771
            }
772
            else {
773
                val = (pdf_string *)v;
774
            }
775
            dprintf("       ");
776
            for (j = 0; j < val->length; j++)
777
                dprintf1("%c", val->data[j]);
778
            if (find != -1) {
779
                dprintf1("  Index = %d", find);
780
                find = -1;
781
            }
782
            pdfi_countdown(key);
783
            pdfi_countdown(val);
784
            dprintf("\n");
785
        }
786
    }
787
#endif
788
789
760k
    gs_free_object(ctx->memory, patrn, "pdfi_generate_native_fontmap");
790
760k
    gs_free_object(ctx->memory, result, "pdfi_generate_native_fontmap");
791
760k
    gs_free_object(ctx->memory, working, "pdfi_generate_native_fontmap");
792
760k
    return 0;
793
760k
}
794
795
int
796
pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, int *findex)
797
760k
{
798
760k
    int code;
799
760k
    pdf_obj *mname;
800
801
760k
    *findex = -1;
802
803
760k
    if (ctx->pdffontmap == NULL) {
804
14.8k
        const char *fmap_default = "Fontmap.GS";
805
14.8k
        char *fmapname = (char *)fmap_default;
806
14.8k
        code = pdf_make_fontmap(ctx, fmapname, false);
807
14.8k
        if (code < 0) {
808
0
            return code;
809
0
        }
810
14.8k
    }
811
760k
    if (ctx->pdfnativefontmap == NULL) {
812
760k
        code = pdfi_generate_native_fontmap(ctx);
813
760k
        if (code < 0)
814
0
            return code;
815
760k
    }
816
817
760k
    if (ctx->pdfnativefontmap != NULL) {
818
0
        pdf_obj *record;
819
0
        code = pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, fname, &record);
820
0
        if (code >= 0) {
821
0
            if (pdfi_type_of(record) == PDF_STRING) {
822
0
                mname = record;
823
0
            }
824
0
            else if (pdfi_type_of(record) == PDF_DICT) {
825
0
                int64_t i64;
826
0
                code = pdfi_dict_get(ctx, (pdf_dict *)record, "Path", &mname);
827
0
                if (code >= 0)
828
0
                    code = pdfi_dict_get_int(ctx, (pdf_dict *)record, "Index", &i64);
829
0
                if (code < 0) {
830
0
                    pdfi_countdown(record);
831
0
                    return code;
832
0
                }
833
0
                *findex = (int)i64; /* Rangecheck? */
834
0
            }
835
0
            else {
836
0
                pdfi_countdown(record);
837
0
                code = gs_error_undefined;
838
0
            }
839
0
        }
840
0
    }
841
760k
    else {
842
760k
        code = gs_error_undefined;
843
760k
    }
844
845
760k
    if (code < 0) {
846
760k
        code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, fname, &mname);
847
760k
        if (code >= 0) {
848
            /* Fontmap can map in multiple "jump" i.e.
849
               name -> substitute name
850
               subsitute name -> file name
851
               So we want to loop until we no more hits.
852
             */
853
168k
            while(1) {
854
168k
                pdf_obj *mname2;
855
168k
                code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, (pdf_name *)mname, &mname2);
856
168k
                if (code < 0) break;
857
98
                pdfi_countdown(mname);
858
98
                mname = mname2;
859
98
            }
860
168k
        }
861
760k
    }
862
760k
    if (mname != NULL && pdfi_type_of(mname) == PDF_STRING && pdfi_fmap_file_exists(ctx, (pdf_string *)mname)) {
863
0
        *mapname = mname;
864
0
        code = 0;
865
0
    }
866
760k
    else if (mname != NULL && pdfi_type_of(mname) == PDF_NAME) { /* If we map to a name, we assume (for now) we have the font as a "built-in" */
867
168k
        *mapname = mname;
868
168k
        code = 0;
869
168k
    }
870
592k
    else {
871
592k
        pdfi_countdown(mname);
872
592k
        code = gs_note_error(gs_error_undefined);
873
592k
    }
874
760k
    return code;
875
760k
}
876
877
int
878
pdf_fontmap_lookup_cidfont(pdf_context *ctx, pdf_dict *font_dict, pdf_name *name, pdf_obj **mapname, int *findex)
879
4.93k
{
880
4.93k
    int code = 0;
881
4.93k
    pdf_obj *cidname = NULL;
882
4.93k
    pdf_obj *mname;
883
884
4.93k
    if (ctx->pdfcidfmap == NULL) {
885
1.41k
        const char *cidfmap_default = "cidfmap";
886
1.41k
        char *cidfmapname = (char *)cidfmap_default;
887
1.41k
        code = pdf_make_fontmap(ctx, cidfmapname, true);
888
1.41k
        if (code < 0) {
889
0
            return code;
890
0
        }
891
1.41k
    }
892
4.93k
    if (name == NULL || pdfi_type_of(name) != PDF_NAME) {
893
2.54k
        code = pdfi_dict_get(ctx, font_dict, "BaseFont", &cidname);
894
2.54k
        if (code < 0 || pdfi_type_of(cidname) != PDF_NAME) {
895
6
            pdfi_countdown(cidname);
896
6
            return_error(gs_error_undefined);
897
6
        }
898
899
2.54k
    }
900
2.38k
    else {
901
2.38k
        cidname = (pdf_obj *)name;
902
2.38k
        pdfi_countup(cidname);
903
2.38k
    }
904
905
4.92k
    code = pdfi_dict_get_by_key(ctx, ctx->pdfcidfmap, (pdf_name *)cidname, &mname);
906
4.92k
    pdfi_countdown(cidname);
907
4.92k
    if (code < 0)
908
4.92k
        return code;
909
    /* As above cidfmap can map in multiple "jump" i.e.
910
       name -> substitute name
911
       subsitute name -> "record"
912
       So we want to loop until we no more hits.
913
     */
914
0
    while(1) {
915
0
        pdf_obj *mname2;
916
0
        code = pdfi_dict_get_by_key(ctx, ctx->pdfcidfmap, (pdf_name *)mname, &mname2);
917
0
        if (code < 0) break;
918
0
        pdfi_countdown(mname);
919
0
        mname = mname2;
920
0
    }
921
0
    if (pdfi_type_of(mname) == PDF_DICT) {
922
0
        pdf_dict *rec = (pdf_dict *)mname;
923
0
        pdf_name *filetype;
924
0
        pdf_name *path = NULL;
925
0
        pdf_array *mcsi = NULL;
926
0
        pdf_dict *ocsi = NULL;
927
0
        pdf_string *ord1 = NULL, *ord2 = NULL;
928
0
        int64_t i64;
929
930
0
        code = pdfi_dict_get(ctx, rec, "FileType", (pdf_obj **)&filetype);
931
        /* We only handle TTF files, just now */
932
0
        if (code < 0 || pdfi_type_of(filetype) != PDF_NAME || filetype->length != 8 || memcmp(filetype->data, "TrueType", 8) != 0) {
933
0
            pdfi_countdown(filetype);
934
0
            pdfi_countdown(rec);
935
0
            return_error(gs_error_undefined);
936
0
        }
937
0
        pdfi_countdown(filetype);
938
939
0
        code = pdfi_dict_get(ctx, rec, "CSI", (pdf_obj **)&mcsi);
940
0
        if (code < 0 || pdfi_type_of(mcsi) != PDF_ARRAY) {
941
0
            pdfi_countdown(mcsi);
942
0
            pdfi_countdown(rec);
943
0
            return_error(gs_error_undefined);
944
0
        }
945
946
0
        code = pdfi_dict_get(ctx, font_dict, "CIDSystemInfo", (pdf_obj **)&ocsi);
947
0
        if (code < 0 || pdfi_type_of(ocsi) != PDF_DICT) {
948
0
            pdfi_countdown(ocsi);
949
0
            pdfi_countdown(mcsi);
950
0
            pdfi_countdown(rec);
951
0
            return_error(gs_error_undefined);
952
0
        }
953
0
        code = pdfi_dict_get(ctx, ocsi, "Ordering", (pdf_obj **)&ord1);
954
0
        if (code < 0 || pdfi_type_of(ord1) != PDF_STRING) {
955
0
            pdfi_countdown(ord1);
956
0
            pdfi_countdown(ocsi);
957
0
            pdfi_countdown(mcsi);
958
0
            pdfi_countdown(rec);
959
0
            return_error(gs_error_undefined);
960
0
        }
961
0
        code = pdfi_array_get(ctx, mcsi, 0, (pdf_obj **)&ord2);
962
0
        if (code < 0 || pdfi_type_of(ord2) != PDF_STRING) {
963
0
            pdfi_countdown(ord1);
964
0
            pdfi_countdown(ord2);
965
0
            pdfi_countdown(ocsi);
966
0
            pdfi_countdown(mcsi);
967
0
            pdfi_countdown(rec);
968
0
            return_error(gs_error_undefined);
969
0
        }
970
0
        if (pdfi_string_cmp(ord1, ord2) != 0) {
971
0
            pdfi_countdown(ord1);
972
0
            pdfi_countdown(ord2);
973
0
            pdfi_countdown(ocsi);
974
0
            pdfi_countdown(mcsi);
975
0
            pdfi_countdown(rec);
976
0
            return_error(gs_error_undefined);
977
0
        }
978
0
        pdfi_countdown(ord1);
979
0
        pdfi_countdown(ord2);
980
981
0
        code = pdfi_dict_get(ctx, rec, "Path", (pdf_obj **)&path);
982
0
        if (code < 0 || pdfi_type_of(path) != PDF_STRING || !pdfi_fmap_file_exists(ctx, (pdf_string *)path)) {
983
0
            pdfi_countdown(rec);
984
0
            return_error(gs_error_undefined);
985
0
        }
986
987
0
        *mapname = (pdf_obj *)path;
988
0
        code = pdfi_dict_get_int(ctx, rec, "Index", &i64);
989
0
        *findex = (code < 0) ? 0 : (int)i64; /* rangecheck? */
990
0
        code = 0;
991
992
0
    }
993
0
    else {
994
0
        *mapname = (pdf_obj *)mname;
995
0
        code = 0;
996
0
    }
997
998
0
    return code;
999
0
}