1 /*---------------------------------------------------------------------------*
2  |              PDFlib - A library for generating PDF on the fly             |
3  +---------------------------------------------------------------------------+
4  | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
5  +---------------------------------------------------------------------------+
6  |                                                                           |
7  |    This software is subject to the PDFlib license. It is NOT in the       |
8  |    public domain. Extended versions and commercial licenses are           |
9  |    available, please check http://www.pdflib.com.                         |
10  |                                                                           |
11  *---------------------------------------------------------------------------*/
12 
13 /* $Id: p_util.c,v 1.169.2.34 2009/10/09 09:35:27 kurt Exp $
14  *
15  * PDFlib utility functions
16  *
17  */
18 
19 #define P_UTIL_C
20 
21 #include "p_intern.h"
22 #include "p_font.h"
23 #include "p_image.h"
24 #include "p_layer.h"
25 
26 
27 /* ------------------------- [hyper]textformat -----------------------------*/
28 
29 void
pdf_check_textformat(PDF * p,pdc_text_format textformat)30 pdf_check_textformat(PDF *p, pdc_text_format textformat)
31 {
32     if (!p->pdc->ptfrun && p->pdc->unicaplang && textformat != pdc_auto2)
33         pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "textformat", 0, 0, 0);
34 
35     pdc_logg_cond(p->pdc, 1, trc_encoding, "\tTextformat: \"%s\"\n",
36                        pdc_get_keyword(textformat, pdf_textformat_keylist));
37 }
38 
39 void
pdf_check_hypertextformat(PDF * p,pdc_text_format hypertextformat)40 pdf_check_hypertextformat(PDF *p, pdc_text_format hypertextformat)
41 {
42     if (!p->pdc->ptfrun && p->pdc->unicaplang && hypertextformat != pdc_auto2)
43         pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextformat",
44                   0, 0, 0);
45 
46     pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextformat: \"%s\"\n",
47 		   pdc_get_keyword(hypertextformat, pdf_textformat_keylist));
48 }
49 
50 
51 /* ------------------------- hypertextencoding -----------------------------*/
52 
53 void
pdf_check_hypertextencoding(PDF * p,pdc_encoding hypertextencoding)54 pdf_check_hypertextencoding(PDF *p, pdc_encoding hypertextencoding)
55 {
56     if (!p->pdc->ptfrun && p->pdc->unicaplang &&
57         hypertextencoding != pdc_unicode)
58         pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextencoding",
59                   0, 0, 0);
60 
61     pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextencoding: \"%s\"\n",
62                        pdc_get_user_encoding(p->pdc, hypertextencoding));
63 }
64 
65 
66 /* ----------------------- string utility functions -----------------------*/
67 
68 static void
pdf_set_convertflags(PDF * p,int * convflags)69 pdf_set_convertflags(PDF *p, int *convflags)
70 {
71     (void) p;
72     (void) convflags;
73 
74 }
75 
76 const char *
pdf__utf16_to_utf8(PDF * p,const char * utf16string,int len,int * size)77 pdf__utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size)
78 {
79     char *utf8string;
80     int convflags = PDC_CONV_WITHBOM | PDC_CONV_EBCDIC | PDC_CONV_TRY7BYTES;
81 
82     pdf_set_convertflags(p, &convflags);
83     utf8string = pdc_utf16_to_utf8(p->pdc, utf16string, len, convflags, size);
84 
85     pdf_insert_utilstring(p, utf8string, pdc_false);
86 
87     return utf8string;
88 }
89 
90 const char *
pdf__utf32_to_utf16(PDF * p,const char * utf32string,int len,const char * ordering,int * outlen)91 pdf__utf32_to_utf16(PDF *p, const char *utf32string, int len,
92                     const char *ordering, int *outlen)
93 {
94     char *utf16string = pdc_utf32_to_utf16(p->pdc, utf32string, len,
95                                            ordering, 0, outlen);
96 
97     pdf_insert_utilstring(p, utf16string, pdc_false);
98 
99     return utf16string;
100 }
101 
102 const char *
pdf__utf8_to_utf16(PDF * p,const char * utf8string,const char * ordering,int * outlen)103 pdf__utf8_to_utf16(PDF *p, const char *utf8string, const char *ordering,
104                    int *outlen)
105 {
106     char *utf16string;
107     int convflags = PDC_CONV_EBCDIC;
108 
109     pdf_set_convertflags(p, &convflags);
110     utf16string = pdc_utf8_to_utf16(p->pdc, utf8string, ordering,
111                                     convflags, outlen);
112 
113     pdf_insert_utilstring(p, utf16string, pdc_false);
114 
115     return utf16string;
116 }
117 
118 void
pdf_init_stringlists(PDF * p)119 pdf_init_stringlists(PDF *p)
120 {
121     p->stringlists_number = 0;
122     p->stringlists_capacity = 0;
123     p->stringlists = NULL;
124     p->stringlistsizes = NULL;
125     p->utilstrlist_index = -1;
126     p->utilstring_number = 0;
127 }
128 
129 int
pdf_insert_stringlist(PDF * p,char ** stringlist,int ns)130 pdf_insert_stringlist(PDF *p, char **stringlist, int ns)
131 {
132     static const char fn[] = "pdf_insert_stringlist";
133     int i;
134 
135     if (p->stringlists_number == p->stringlists_capacity)
136     {
137         int j = p->stringlists_capacity;
138 
139         if (!p->stringlists_capacity)
140         {
141             p->stringlists_capacity = STRINGLISTS_CHUNKSIZE;
142 
143             p->stringlists = (char ***) pdc_malloc(p->pdc,
144                 sizeof(char **) * p->stringlists_capacity, fn);
145 
146             p->stringlistsizes = (int *) pdc_malloc(p->pdc,
147                 sizeof(int) * p->stringlists_capacity, fn);
148         }
149         else
150         {
151             p->stringlists_capacity *= 2;
152             p->stringlists = (char ***) pdc_realloc(p->pdc, p->stringlists,
153                 sizeof(char **) * p->stringlists_capacity, fn);
154 
155             p->stringlistsizes = (int *) pdc_realloc(p->pdc, p->stringlistsizes,
156                 sizeof(int) * p->stringlists_capacity, fn);
157         }
158         for (i = j; i < p->stringlists_capacity; i++)
159         {
160             p->stringlists[i] = NULL;
161             p->stringlistsizes[i] = 0;
162         }
163     }
164 
165     i = p->stringlists_number;
166     p->stringlists[i] = stringlist;
167     p->stringlistsizes[i] = ns;
168     p->stringlists_number++;
169 
170     return i;
171 }
172 
173 void
pdf_cleanup_stringlists(PDF * p)174 pdf_cleanup_stringlists(PDF *p)
175 {
176     int i;
177 
178     if (p->stringlists)
179     {
180         for (i = 0; i < p->stringlists_number; i++)
181         {
182             if (p->stringlists[i])
183                 pdc_cleanup_optstringlist(p->pdc,
184                     p->stringlists[i], p->stringlistsizes[i]);
185         }
186         pdc_free(p->pdc, p->stringlists);
187         pdc_free(p->pdc, p->stringlistsizes);
188     }
189 
190     pdf_init_stringlists(p);
191 }
192 
193 #define PDF_MAX_UTILSTRLISTS 10
194 
195 int
pdf_insert_utilstring(PDF * p,const char * utilstring,pdc_bool kdup)196 pdf_insert_utilstring(PDF *p, const char *utilstring, pdc_bool kdup)
197 {
198     static const char fn[] = "pdf_insert_utilstring";
199     char **utilstrlist;
200     int i = 0;
201 
202     if (p->utilstrlist_index == -1)
203     {
204         utilstrlist = (char **) pdc_calloc(p->pdc,
205                                     PDF_MAX_UTILSTRLISTS * sizeof (char *), fn);
206         p->utilstrlist_index =
207             pdf_insert_stringlist(p, utilstrlist, PDF_MAX_UTILSTRLISTS);
208     }
209     utilstrlist = p->stringlists[p->utilstrlist_index];
210 
211     if (p->utilstring_number >= PDF_MAX_UTILSTRLISTS)
212         p->utilstring_number = 0;
213     i = p->utilstring_number;
214     if (utilstrlist[i] != NULL)
215         pdc_free(p->pdc, utilstrlist[i]);
216     if (kdup)
217         utilstrlist[i] = pdc_strdup_ext(p->pdc, utilstring, 0, fn);
218     else
219         utilstrlist[i] = (char *) utilstring;
220     p->utilstring_number++;
221 
222     return i;
223 }
224 
225 const char *
pdf_get_utilstring(PDF * p,int i)226 pdf_get_utilstring(PDF *p, int i)
227 {
228     if (p->utilstrlist_index > -1 && i > -1 && i < p->utilstring_number)
229     {
230         char **utilstrlist = p->stringlists[p->utilstrlist_index];
231         return utilstrlist[i];
232     }
233 
234     return NULL;
235 }
236 
237 /* ------------------------ name treatment -------------------------------*/
238 
239 void
pdf_put_pdfname(PDF * p,const char * name)240 pdf_put_pdfname(PDF *p, const char *name)
241 {
242     char *ascname = (char *) name;
243     int len = (int) strlen(ascname);
244 
245 
246     pdc_put_pdfname(p->out, ascname, len);
247 
248 }
249 
250 
251 /* ---------------------- hyper text treatment -------------------------------*/
252 
253 pdc_encoding
pdf_get_hypertextencoding_opt(PDF * p,pdc_resopt * resopts,int * codepage,pdc_bool verbose)254 pdf_get_hypertextencoding_opt(PDF *p, pdc_resopt *resopts, int *codepage,
255                               pdc_bool verbose)
256 {
257     char **strlist;
258     pdc_encoding htenc;
259 
260     if (pdc_get_optvalues("hypertextencoding", resopts, NULL, &strlist))
261     {
262         int cp;
263 
264         htenc = pdf_get_hypertextencoding(p, strlist[0], &cp, verbose);
265         pdf_check_hypertextencoding(p, htenc);
266 
267         if (codepage)
268             *codepage = cp;
269     }
270     else
271     {
272         htenc = pdf_get_hypertextencoding_param(p, codepage);
273     }
274 
275     return htenc;
276 }
277 
278 /* hypertext conversion for deprecated functions */
279 char *
pdf_convert_hypertext_depr(PDF * p,const char * text,int len)280 pdf_convert_hypertext_depr(PDF *p, const char *text, int len)
281 {
282     int outlen;
283 
284     pdf_get_hypertextencoding_param(p, NULL);
285 
286     return pdf_convert_hypertext(p, text, len, p->hypertextformat,
287                       p->hypertextencoding, p->hypertextcodepage, &outlen,
288                       PDC_UTF8_FLAG, pdc_true);
289 }
290 
291 /*
292  * Conversion to PDFDoc/EBCDIC or UTF-16/[EBCDIC-]UTF-8
293  */
294 char *
pdf_convert_hypertext(PDF * p,const char * text,int len,pdc_text_format hypertextformat,pdc_encoding hypertextencoding,int codepage,int * outlen,pdc_bool oututf8,pdc_bool verbose)295 pdf_convert_hypertext(PDF *p, const char *text, int len,
296     pdc_text_format hypertextformat, pdc_encoding hypertextencoding,
297     int codepage, int *outlen, pdc_bool oututf8, pdc_bool verbose)
298 {
299     pdc_encodingvector *inev = NULL, *outev = NULL;
300     pdc_byte *intext = (pdc_byte *) text, *outtext = NULL;
301     pdc_text_format textformat = pdc_utf16be;
302     int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
303 
304     *outlen = 0;
305 
306     if (text == NULL)
307         return NULL;
308 
309     if (len == 0)
310         len = (int) strlen(text);
311 
312     /* incoming encoding */
313     if (hypertextencoding >= 0)
314     {
315         inev = pdc_get_encoding_vector(p->pdc, hypertextencoding);
316     }
317 
318     /* PDFDocEncoding */
319     outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
320 
321     /* conversion to UTF-16-BE or PDFDocEncoding / EBCDIC */
322     pdf_set_convertflags(p, &convflags);
323     if (pdc_logg_is_enabled(p->pdc, 3, trc_text))
324         convflags |= PDC_CONV_LOGGING;
325 
326     pdc_convert_string(p->pdc, hypertextformat, codepage, inev,
327                        intext, len,
328                        &textformat, outev, &outtext, outlen,
329                        convflags, verbose);
330 
331 
332     /* conversion to UTF-8 if Unicode */
333     if (oututf8 && textformat == pdc_utf16be)
334     {
335         pdc_text_format outtextformat = PDC_UTF8;
336         pdc_byte *newtext = NULL;
337 
338         convflags = PDC_CONV_WITHBOM;
339         if (pdc_logg_is_enabled(p->pdc, 3, trc_text))
340             convflags |= PDC_CONV_LOGGING;
341 
342         pdc_convert_string(p->pdc, textformat, 0, NULL, outtext, *outlen,
343                            &outtextformat, NULL, &newtext, outlen,
344                            convflags, verbose);
345         pdc_free(p->pdc, outtext);
346         outtext = newtext;
347     }
348 
349     return (char *) outtext;
350 }
351 
352 
353 /*
354  * Conversion from [EBCDIC-]UTF-8 to UTF-16 and from EBCDIC to PDFDoc
355  */
356 
357 char *
pdf_convert_pdfstring(PDF * p,const char * text,int inlen,int convflags,int * outlen)358 pdf_convert_pdfstring(PDF *p, const char *text, int inlen, int convflags,
359                       int *outlen)
360 {
361     pdc_byte *newtext = NULL;
362 
363     if (pdc_is_utf8_bytecode(text))
364     {
365         pdc_text_format textformat = PDC_UTF8;
366         pdc_text_format outtextformat = pdc_utf16be;
367         pdc_encodingvector *outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
368 
369         pdf_set_convertflags(p, &convflags);
370 
371         pdc_convert_string(p->pdc, textformat, 0, NULL,
372                            (pdc_byte *) text, inlen,
373                            &outtextformat, outev, &newtext, outlen,
374                            convflags, pdc_true);
375     }
376     else
377     {
378         newtext = (pdc_byte *) text;
379         *outlen = inlen;
380     }
381 
382     return (char *) newtext;
383 }
384 
385 void
pdf_put_hypertext(PDF * p,const char * text)386 pdf_put_hypertext(PDF *p, const char *text)
387 {
388     int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
389     int inlen = (int) pdc_strlen(text);
390     int outlen;
391 
392     char *newtext = pdf_convert_pdfstring(p, text, inlen, convflags, &outlen);
393 
394     pdc_put_pdfstring(p->out, newtext, outlen);
395 
396     if (newtext != text)
397         pdc_free(p->pdc, newtext);
398 }
399 
400 void
pdf_put_pdffilename(PDF * p,const char * text)401 pdf_put_pdffilename(PDF *p, const char *text)
402 {
403     int convflags = PDC_CONV_FILENAME | PDC_CONV_TRYBYTES;
404     int inlen = (int) pdc_strlen(text);
405     int outlen;
406 
407     char *newtext = pdf_convert_pdfstring(p, text, inlen, convflags, &outlen);
408 
409     pdc_put_pdffilename(p->out, newtext, outlen);
410 
411     if (newtext != text)
412         pdc_free(p->pdc, newtext);
413 }
414 
415 void
pdf_put_pdfunifilename(PDF * p,const char * text)416 pdf_put_pdfunifilename(PDF *p, const char *text)
417 {
418     int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
419     int inlen = (int) pdc_strlen(text);
420     int outlen;
421 
422     char *newtext = pdf_convert_pdfstring(p, text, inlen, convflags, &outlen);
423 
424     pdc_put_pdffilename(p->out, newtext, outlen);
425 
426     if (newtext != text)
427         pdc_free(p->pdc, newtext);
428 }
429 
430 
431 /* ------------------------ name strings -------------------------------*/
432 
433 static void
pdf_prepare_name_string(PDF * p,const char * name,int len,int maxlen,char ** newname,int * newlen,pdc_encoding * htenc,int * htcp)434 pdf_prepare_name_string(PDF *p, const char *name, int len, int maxlen,
435                         char **newname, int *newlen,
436                         pdc_encoding *htenc, int *htcp)
437 {
438     if (name == NULL)
439     {
440         len = 0;
441         name = "";
442     }
443 
444     if (len < 0 || len > maxlen)
445     {
446         pdc_error(p->pdc, PDC_E_ILLARG_STRINGLEN,
447                   pdc_errprintf(p->pdc, "%d", len),
448                   pdc_errprintf(p->pdc, "%d", PDC_SHRT_MAX), 0, 0);
449     }
450 
451     *newname = (char *) name;
452     *newlen = len;
453     *htenc = pdc_invalidenc;
454     *htcp = 0;
455 
456     if (p->usehyptxtenc && !len && !pdc_is_utf8_bytecode(name))
457     {
458         *htenc = pdf_get_hypertextencoding_param(p, htcp);
459 
460     }
461 }
462 
463 char *
pdf_convert_name(PDF * p,const char * name,int len,int flags)464 pdf_convert_name(PDF *p, const char *name, int len, int flags)
465 {
466     char *resname;
467     char *newname;
468     int newlen;
469     pdc_encoding htenc;
470     int htcp;
471 
472     pdf_prepare_name_string(p, name, len, PDC_SHRT_MAX,
473                             &newname, &newlen, &htenc, &htcp);
474 
475     flags |= PDC_CONV_EBCDIC;
476     if (pdc_logg_is_enabled(p->pdc, 3, trc_text))
477         flags |= PDC_CONV_LOGGING;
478 
479     resname = pdc_convert_name_ext(p->pdc, newname, newlen, htenc, htcp, flags);
480     if (newname != name)
481         pdc_free(p->pdc, newname);
482 
483     return resname;
484 }
485 
486 const char *
pdf_convert_filename(PDF * p,const char * filename,int len,const char * paramname,int flags)487 pdf_convert_filename(PDF *p, const char *filename, int len,
488                      const char *paramname, int flags)
489 {
490     const char *resfilename;
491     char *newfilename;
492     int newlen;
493     pdc_encoding htenc;
494     int htcp;
495 
496     pdf_prepare_name_string(p, filename, len, PDC_FILENAMELEN - 1,
497                             &newfilename, &newlen, &htenc, &htcp);
498 
499     flags |= PDC_CONV_EBCDIC;
500     if (pdc_logg_is_enabled(p->pdc, 3, trc_filesearch))
501         flags |= PDC_CONV_LOGGING;
502 
503     resfilename = pdc_convert_filename_ext(p->pdc, newfilename, len,
504                                            paramname, htenc, htcp, flags);
505     if (newfilename != filename)
506         pdc_free(p->pdc, newfilename);
507 
508     return resfilename;
509 }
510 
511 void
pdf_add_pdflib_resource(PDF * p,const char * category,const char * resname)512 pdf_add_pdflib_resource(PDF *p, const char *category, const char *resname)
513 {
514     char *newresname;
515     int newlen;
516     pdc_encoding htenc;
517     int htcp;
518 
519     pdf_prepare_name_string(p, resname, 0, PDC_FILENAMELEN,
520                             &newresname, &newlen, &htenc, &htcp);
521     if (newlen)
522     {
523         char *tmpresname = pdc_utf16_to_utf8(p->pdc, newresname, newlen,
524                                              PDC_CONV_EBCDIC | PDC_CONV_WITHBOM,
525                                              &newlen);
526         pdc_free(p->pdc, newresname);
527         newresname = tmpresname;
528         newlen = 0;
529     }
530 
531     pdc_add_resource_ext(p->pdc, category, newresname, NULL, htenc, htcp);
532 
533     if (newresname != resname)
534         pdc_free(p->pdc, newresname);
535 }
536 
537 /* ------------------------ option text list -------------------------------*/
538 
539 int
pdf_get_opt_textlist(PDF * p,const char * keyword,pdc_resopt * resopts,pdc_encoding enc,int codepage,pdc_bool ishypertext,const char * fieldname,char ** text,char *** textlist)540 pdf_get_opt_textlist(PDF *p, const char *keyword, pdc_resopt *resopts,
541                      pdc_encoding enc, int codepage, pdc_bool ishypertext,
542                      const char *fieldname, char **text, char ***textlist)
543 {
544     pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_optlist);
545     int ns;
546     char **strlist;
547 
548     ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
549     if (ns)
550     {
551         pdc_byte *string = NULL;
552         pdc_encodingvector *inev = NULL, *outev = NULL;
553         pdc_text_format intextformat = pdc_bytes;
554         pdc_text_format outtextformat = pdc_utf16be;
555         pdc_text_format textformat;
556         int convflags = PDC_CONV_WITHBOM;
557         pdc_bool isutf8;
558         int i, outlen;
559 
560         /* whole option list or string list is in UTF-8 */
561         isutf8 = pdc_is_lastopt_utf8(resopts);
562 
563         /* Encoding */
564         if (ishypertext)
565         {
566             /* Initialize */
567             if (!isutf8)
568             {
569                 if (enc < 0 && enc != pdc_unicode && enc != pdc_cid)
570                     enc = pdf_get_hypertextencoding(p, "auto", &codepage,
571                                                     pdc_true);
572                 if (enc >= 0)
573                     inev = pdc_get_encoding_vector(p->pdc, enc);
574             }
575 
576             /* ugly solution of bug #2344 */
577             if (ishypertext == pdc_true)
578             {
579                 outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
580 
581                 /* conversion to PDFDocEncoding if possible */
582                 convflags |= PDC_CONV_TRYBYTES;
583             }
584             else if (ishypertext == pdc_undef)
585             {
586                 /* filename as hypertext */
587                 outtextformat = PDC_UTF8;
588                 convflags |= PDC_CONV_TRY7BYTES;
589             }
590         }
591         else
592         {
593             if (enc == pdc_invalidenc)
594             {
595                 if (fieldname)
596                 {
597                     pdc_cleanup_optionlist(p->pdc, resopts);
598                     pdc_error(p->pdc, PDF_E_FF_FONTMISSING, fieldname, 0, 0, 0);
599                 }
600                 return 0;
601             }
602             else if (enc >= 0 && !isutf8)
603             {
604                 /* bug #2069: always conversion to UTF-16BE */
605                 inev = pdc_get_encoding_vector(p->pdc, enc);
606             }
607         }
608 
609         if (logg1)
610         {
611             if (isutf8)
612             {
613                 pdc_logg(p->pdc, "\tOption \"%s\" is "PDC_UTF8_STRG" encoded\n",
614                          keyword);
615             }
616             else
617             {
618                 pdc_logg(p->pdc, "\tOption \"%s\" is %s encoded\n",
619                          keyword, pdc_get_user_encoding(p->pdc, enc));
620             }
621         }
622 
623         for (i = 0; i < ns; i++)
624         {
625             string = (pdc_byte *) strlist[i];
626 
627             {
628                 if (ishypertext || isutf8 || inev != NULL)
629                 {
630                     intextformat = isutf8 ?  PDC_UTF8 : pdc_bytes;
631 
632                     if (pdc_logg_is_enabled(p->pdc, 3, trc_text))
633                         convflags |= PDC_CONV_LOGGING;
634                     pdf_set_convertflags(p, &convflags);
635                     textformat = outtextformat;
636                     pdc_convert_string(p->pdc, intextformat, codepage, inev,
637                                 string, (int) strlen((char *) string),
638                                 &textformat, outev, &string, &outlen,
639                                 convflags, pdc_true);
640                     pdc_free(p->pdc, strlist[i]);
641                     strlist[i] = (char *) string;
642                 }
643             }
644         }
645 
646         if (text)
647             *text = strlist[0];
648         else
649             *textlist = strlist;
650 
651         if (fieldname)
652         {
653             strlist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
654             pdf_insert_stringlist(p, strlist, ns);
655         }
656     }
657 
658     return ns;
659 }
660 
661 char *
pdf_get_opt_filename(PDF * p,const char * keyword,pdc_resopt * resopts,pdc_encoding enc,int codepage)662 pdf_get_opt_filename(PDF *p, const char *keyword, pdc_resopt *resopts,
663                      pdc_encoding enc, int codepage)
664 {
665     pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_optlist);
666     pdc_bool logg3 = pdc_logg_is_enabled(p->pdc, 3, trc_text);
667     pdc_byte *filename = NULL;
668     char **strlist;
669 
670     if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
671     {
672         pdc_encodingvector *inev = NULL, *outev = NULL;
673         pdc_text_format intextformat = pdc_bytes;
674         pdc_text_format outtextformat = pdc_utf16; /* sic! */
675         int convflags = PDC_CONV_NOBOM | PDC_CONV_TRYBYTES | PDC_CONV_NEWALLOC;
676         pdc_bool isutf8;
677         int ic, outlen;
678 
679         /* whole option list or string list is in UTF-8 */
680         isutf8 = pdc_is_lastopt_utf8(resopts);
681 
682         if (!isutf8)
683         {
684             if (enc < 0 && enc != pdc_unicode && enc != pdc_cid)
685                 enc = pdf_get_hypertextencoding(p, "auto", &codepage,
686                                                 pdc_true);
687             if (enc >= 0)
688                 inev = pdc_get_encoding_vector(p->pdc, enc);
689         }
690         else
691         {
692             intextformat = PDC_UTF8;
693         }
694 
695         if (logg1)
696         {
697             if (isutf8)
698             {
699                 pdc_logg(p->pdc, "\tOption \"%s\" is "PDC_UTF8_STRG" encoded\n",
700                          keyword);
701             }
702             else
703             {
704                 pdc_logg(p->pdc, "\tOption \"%s\" is %s encoded\n",
705                          keyword, pdc_get_user_encoding(p->pdc, enc));
706             }
707         }
708 
709         outev = pdc_get_encoding_vector(p->pdc, pdc_winansi);
710 
711         if (logg3)
712             convflags |= PDC_CONV_LOGGING;
713         pdf_set_convertflags(p, &convflags);
714 
715         pdc_convert_string(p->pdc, intextformat, codepage, inev,
716                     (pdc_byte *) strlist[0], (int) strlen(strlist[0]),
717                     &outtextformat, outev, &filename, &outlen,
718                     convflags, pdc_true);
719 
720         if (outtextformat == pdc_utf16)
721         {
722             pdc_ushort uv, *unifilename = (pdc_ushort *) filename;
723             int code;
724 
725             if (p->compatibility < PDC_1_7)
726                 pdc_error(p->pdc, PDC_E_IO_UNSUPP_PDFUNINAME, 0, 0, 0, 0);
727 
728             /* we must replace non-WinAnsi characters by period
729              * and omit the BOM to get a WinAnsi string.
730              */
731             outlen /= 2;
732             for (ic = 0; ic < outlen; ic++)
733             {
734                 uv = unifilename[ic];
735 
736                 code = pdc_get_encoding_bytecode(p->pdc, outev, uv);
737                 if (code <= 0)
738                     uv = PDC_UNICODE_PERIOD;
739 
740                 filename[ic] = (char) uv;
741             }
742             filename[ic] = 0;
743         }
744 
745         if (logg3)
746             pdc_logg_hexdump(p->pdc, "output filename", "\t\t",
747                              (char *) filename, strlen((char *) filename));
748     }
749 
750     return (char *) filename;
751 }
752 
753 char *
pdf_get_opt_utf8name(PDF * p,const char * keyword,pdc_resopt * resopts)754 pdf_get_opt_utf8name(PDF *p, const char *keyword, pdc_resopt *resopts)
755 {
756     char **strlist = NULL;
757     char *utf8name = NULL;
758 
759     if (pdc_get_opt_utf8strings(p->pdc, keyword, resopts, PDC_OPT_SAVE1ELEM,
760                                 &strlist))
761     {
762         utf8name = strlist[0];
763     }
764 
765     return utf8name;
766 }
767 
768 
769 /* -------------------------- errorpolicy -------------------------------*/
770 
771 pdc_bool
pdf_get_errorpolicy(PDF * p,pdc_resopt * resopts,pdc_bool verbose)772 pdf_get_errorpolicy(PDF *p, pdc_resopt *resopts, pdc_bool verbose)
773 {
774     int errpol = (int) p->errorpolicy;
775 
776     if (resopts != NULL)
777         pdc_get_optvalues("errorpolicy", resopts, &errpol, NULL);
778 
779     if (errpol != (int) errpol_legacy)
780         verbose = errpol;
781 
782     return verbose;
783 }
784 
785 
786 /* -------------------------- handle check -------------------------------*/
787 
788 int
pdf_check_opt_handle(void * opaque,int handle,pdc_opttype type)789 pdf_check_opt_handle(void *opaque, int handle, pdc_opttype type)
790 {
791     PDF *p = (PDF*)opaque;
792     int minval = 0, maxval = 0;
793     pdc_bool empty = pdc_false;
794 
795     switch (type)
796     {
797 
798         case pdc_actionhandle:
799         maxval = pdf_get_max_action(p);
800         break;
801 
802         case pdc_bookmarkhandle:
803         maxval = p->outline_count;
804         break;
805 
806         case pdc_colorhandle:
807         maxval = p->colorspaces_number - 1;
808         break;
809 
810 
811         case pdc_fonthandle:
812         maxval = p->fonts_number - 1;
813         empty = !pdf_isvalid_font(p, handle);
814         break;
815 
816         case pdc_gstatehandle:
817         maxval = p->extgstates_number - 1;
818         break;
819 
820 
821         case pdc_imagehandle:
822         maxval = p->images_capacity - 1;
823         if (handle >= minval && handle <= maxval &&
824             (!p->images[handle].in_use ||
825               p->xobjects[p->images[handle].no].type == pdi_xobject))
826             empty = pdc_true;
827         break;
828 
829 
830         case pdc_pagehandle:
831         maxval = p->images_capacity - 1;
832         if (handle >= minval && handle <= maxval &&
833             (!p->images[handle].in_use ||
834               p->xobjects[p->images[handle].no].type != pdi_xobject))
835             empty = pdc_true;
836         break;
837 
838         case pdc_patternhandle:
839         maxval = p->pattern_number - 1;
840         break;
841 
842         case pdc_shadinghandle:
843         maxval = p->shadings_number - 1;
844         break;
845 
846 
847         case pdc_templatehandle:
848         maxval = p->images_capacity - 1;
849         if (handle >= minval && handle <= maxval &&
850             (!p->images[handle].in_use ||
851               p->xobjects[p->images[handle].no].type != form_xobject))
852             empty = pdc_true;
853         break;
854 
855 
856         case pdc_stringhandle:
857         if (p->utilstrlist_index == -1)
858             empty = pdc_true;
859         maxval = p->utilstring_number - 1;
860         break;
861 
862         default:
863         break;
864     }
865 
866     if (handle < minval || handle > maxval || empty)
867         return PDC_E_ILLARG_HANDLE;
868 
869     return 0;
870 }
871 
872 void
pdf_check_handle(PDF * p,int handle,pdc_opttype type)873 pdf_check_handle(PDF *p, int handle, pdc_opttype type)
874 {
875     if (pdf_check_opt_handle(p, handle, type))
876     {
877         if (p->pdc->hastobepos && type != pdc_stringhandle)
878             handle++;
879 
880         pdc_error(p->pdc, PDC_E_ILLARG_HANDLE,
881                   pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
882                                 pdc_get_handletype(type)),
883                   pdc_errprintf(p->pdc, "%d", handle), 0, 0);
884     }
885 }
886 
887 void
pdf_set_clientdata(PDF * p,pdc_clientdata * cdata)888 pdf_set_clientdata(PDF *p, pdc_clientdata *cdata)
889 {
890     memset(cdata, 0, sizeof(pdc_clientdata));
891 
892     cdata->maxaction = pdf_get_max_action(p);
893     cdata->maxbookmark = p->outline_count;
894     cdata->maxcolor = p->colorspaces_number - 1;
895     cdata->maxdocument = p->pdi_capacity - 1;
896     cdata->maxfont = p->fonts_number - 1;
897     cdata->maxgstate = p->extgstates_number - 1;
898     cdata->maximage = p->images_capacity - 1;
899     cdata->maxpage = p->images_capacity - 1;
900     cdata->maxpattern = p->pattern_number - 1;
901     cdata->maxshading = p->shadings_number - 1;
902     cdata->maxtemplate = p->images_capacity - 1;
903     cdata->maxstring = p->utilstring_number - 1;
904 
905     cdata->compatibility = p->compatibility;
906 }
907