X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fppd.c;h=63d5dd2feb8c165ec28a553680b6287fc387bb9c;hb=37a8aac24308a93cc5eec25d55798491a86c6221;hp=a70a0cfebdfb67e67e44d90d32ca9736d214a671;hpb=5a738aeaea5c4dd9384a8601cc5c99be683b69ca;p=thirdparty%2Fcups.git diff --git a/cups/ppd.c b/cups/ppd.c index a70a0cfeb..63d5dd2fe 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -1,82 +1,39 @@ /* - * "$Id: ppd.c 6937 2007-09-10 21:13:31Z mike $" + * PPD file routines for CUPS. * - * PPD file routines for the Common UNIX Printing System (CUPS). + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * Copyright 2007-2008 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * missing or damaged, see the license at "http://www.cups.org/". * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * PostScript is a trademark of Adobe Systems, Inc. * - * PostScript is a trademark of Adobe Systems, Inc. + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. * - * This code and any derivative of it may be used and distributed - * freely under the terms of the GNU General Public License when - * used with GNU Ghostscript or its derivatives. Use of the code - * (or any derivative of it) with software other than GNU - * GhostScript (or its derivatives) is governed by the CUPS license - * agreement. - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * ppdClose() - Free all memory used by the PPD file. - * ppdErrorString() - Returns the text assocated with a status. - * _ppdGetEncoding() - Get the CUPS encoding value for the given - * LanguageEncoding. - * ppdLastError() - Return the status from the last ppdOpen*(). - * ppdOpen() - Read a PPD file into memory. - * ppdOpen2() - Read a PPD file into memory. - * ppdOpenFd() - Read a PPD file into memory. - * ppdOpenFile() - Read a PPD file into memory. - * ppdSetConformance() - Set the conformance level for PPD files. - * ppd_add_attr() - Add an attribute to the PPD data. - * ppd_add_choice() - Add a choice to an option. - * ppd_add_size() - Add a page size. - * ppd_compare_attrs() - Compare two attributes. - * ppd_compare_choices() - Compare two choices... - * ppd_compare_consts() - Compare two constraints. - * ppd_compare_coptions() - Compare two custom options. - * ppd_compare_cparams() - Compare two custom parameters. - * ppd_compare_options() - Compare two options. - * ppd_decode() - Decode a string value... - * ppd_free_group() - Free a single UI group. - * ppd_free_option() - Free a single option. - * ppd_get_coption() - Get a custom option record. - * ppd_get_cparam() - Get a custom parameter record. - * ppd_get_group() - Find or create the named group as needed. - * ppd_get_option() - Find or create the named option as needed. - * ppd_hash_option() - Generate a hash of the option name... - * ppd_read() - Read a line from a PPD file, skipping comment - * lines as necessary. + * This file is subject to the Apple OS-Developed Software exception. */ /* * Include necessary headers. */ -#include "globals.h" -#include "debug.h" -#include +#include "cups-private.h" +#include "ppd-private.h" /* * Definitions... */ -#if defined(WIN32) || defined(__EMX__) -# define READ_BINARY "rb" /* Open a binary file for reading */ -# define WRITE_BINARY "wb" /* Open a binary file for writing */ -#else -# define READ_BINARY "r" /* Open a binary file for reading */ -# define WRITE_BINARY "w" /* Open a binary file for writing */ -#endif /* WIN32 || __EMX__ */ - #define ppd_free(p) if (p) free(p) /* Safe free macro */ #define PPD_KEYWORD 1 /* Line contained a keyword */ @@ -98,6 +55,18 @@ typedef struct _ppd_line_s } _ppd_line_t; +/* + * Local globals... + */ + +static _cups_threadkey_t ppd_globals_key = _CUPS_THREADKEY_INITIALIZER; + /* Thread local storage key */ +#ifdef HAVE_PTHREAD_H +static pthread_once_t ppd_globals_key_once = PTHREAD_ONCE_INIT; + /* One-time initialization object */ +#endif /* HAVE_PTHREAD_H */ + + /* * Local functions... */ @@ -109,12 +78,11 @@ static ppd_choice_t *ppd_add_choice(ppd_option_t *option, const char *name); static ppd_size_t *ppd_add_size(ppd_file_t *ppd, const char *name); static int ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b); static int ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b); -static int ppd_compare_consts(ppd_const_t *a, ppd_const_t *b); static int ppd_compare_coptions(ppd_coption_t *a, ppd_coption_t *b); -static int ppd_compare_cparams(ppd_cparam_t *a, ppd_cparam_t *b); static int ppd_compare_options(ppd_option_t *a, ppd_option_t *b); static int ppd_decode(char *string); +static void ppd_free_filters(ppd_file_t *ppd); static void ppd_free_group(ppd_group_t *group); static void ppd_free_option(ppd_option_t *option); static ppd_coption_t *ppd_get_coption(ppd_file_t *ppd, const char *name); @@ -122,14 +90,23 @@ static ppd_cparam_t *ppd_get_cparam(ppd_coption_t *opt, const char *param, const char *text); static ppd_group_t *ppd_get_group(ppd_file_t *ppd, const char *name, - const char *text, _cups_globals_t *cg, + const char *text, _ppd_globals_t *pg, cups_encoding_t encoding); static ppd_option_t *ppd_get_option(ppd_group_t *group, const char *name); +static _ppd_globals_t *ppd_globals_alloc(void); +#if defined(HAVE_PTHREAD_H) || defined(WIN32) +static void ppd_globals_free(_ppd_globals_t *g); +#endif /* HAVE_PTHREAD_H || WIN32 */ +#ifdef HAVE_PTHREAD_H +static void ppd_globals_init(void); +#endif /* HAVE_PTHREAD_H */ static int ppd_hash_option(ppd_option_t *option); static int ppd_read(cups_file_t *fp, _ppd_line_t *line, char *keyword, char *option, char *text, char **string, int ignoreblank, - _cups_globals_t *cg); + _ppd_globals_t *pg); +static int ppd_update_filters(ppd_file_t *ppd, + _ppd_globals_t *pg); /* @@ -143,7 +120,6 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ ppd_emul_t *emul; /* Current emulation */ ppd_group_t *group; /* Current group */ char **font; /* Current font */ - char **filter; /* Current filter */ ppd_attr_t **attr; /* Current attribute */ ppd_coption_t *coption; /* Current custom option */ ppd_cparam_t *cparam; /* Current custom parameter */ @@ -162,7 +138,8 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ _cupsStrFree(ppd->lang_encoding); _cupsStrFree(ppd->nickname); - _cupsStrFree(ppd->patches); + if (ppd->patches) + free(ppd->patches); _cupsStrFree(ppd->jcl_begin); _cupsStrFree(ppd->jcl_end); _cupsStrFree(ppd->jcl_ps); @@ -215,13 +192,7 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ * Free any filters... */ - if (ppd->num_filters > 0) - { - for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) - _cupsStrFree(*filter); - - ppd_free(ppd->filters); - } + ppd_free_filters(ppd); /* * Free any fonts... @@ -293,6 +264,33 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ cupsArrayDelete(ppd->coptions); + /* + * Free constraints... + */ + + if (ppd->cups_uiconstraints) + { + _ppd_cups_uiconsts_t *consts; /* Current constraints */ + + + for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints); + consts; + consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints)) + { + free(consts->constraints); + free(consts); + } + + cupsArrayDelete(ppd->cups_uiconstraints); + } + + /* + * Free any PPD cache/mapping data... + */ + + if (ppd->cache) + _ppdCacheDestroy(ppd->cache); + /* * Free the whole record... */ @@ -302,9 +300,9 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ /* - * 'ppdErrorString()' - Returns the text assocated with a status. + * 'ppdErrorString()' - Returns the text associated with a status. * - * @since CUPS 1.1.19@ + * @since CUPS 1.1.19/macOS 10.3@ */ const char * /* O - Status string */ @@ -332,11 +330,14 @@ ppdErrorString(ppd_status_t status) /* I - PPD status */ _("Illegal option keyword string"), _("Illegal translation string"), _("Illegal whitespace character"), - _("Bad custom parameter") + _("Bad custom parameter"), + _("Missing option keyword"), + _("Bad value string"), + _("Missing CloseGroup") }; - if (status < PPD_OK || status > PPD_ILLEGAL_WHITESPACE) + if (status < PPD_OK || status >= PPD_MAX_STATUS) return (_cupsLangString(cupsLangDefault(), _("Unknown"))); else return (_cupsLangString(cupsLangDefault(), messages[status])); @@ -351,17 +352,17 @@ ppdErrorString(ppd_status_t status) /* I - PPD status */ cups_encoding_t /* O - CUPS encoding value */ _ppdGetEncoding(const char *name) /* I - LanguageEncoding string */ { - if (!strcasecmp(name, "ISOLatin1")) + if (!_cups_strcasecmp(name, "ISOLatin1")) return (CUPS_ISO8859_1); - else if (!strcasecmp(name, "ISOLatin2")) + else if (!_cups_strcasecmp(name, "ISOLatin2")) return (CUPS_ISO8859_2); - else if (!strcasecmp(name, "ISOLatin5")) + else if (!_cups_strcasecmp(name, "ISOLatin5")) return (CUPS_ISO8859_5); - else if (!strcasecmp(name, "JIS83-RKSJ")) - return (CUPS_WINDOWS_932); - else if (!strcasecmp(name, "MacStandard")) + else if (!_cups_strcasecmp(name, "JIS83-RKSJ")) + return (CUPS_JIS_X0213); + else if (!_cups_strcasecmp(name, "MacStandard")) return (CUPS_MAC_ROMAN); - else if (!strcasecmp(name, "WindowsANSI")) + else if (!_cups_strcasecmp(name, "WindowsANSI")) return (CUPS_WINDOWS_1252); else return (CUPS_UTF8); @@ -369,67 +370,75 @@ _ppdGetEncoding(const char *name) /* I - LanguageEncoding string */ /* - * 'ppdLastError()' - Return the status from the last ppdOpen*(). - * - * @since CUPS 1.1.19@ + * '_ppdGlobals()' - Return a pointer to thread local storage */ -ppd_status_t /* O - Status code */ -ppdLastError(int *line) /* O - Line number */ +_ppd_globals_t * /* O - Pointer to global data */ +_ppdGlobals(void) { - _cups_globals_t *cg = _cupsGlobals(); - /* Global data */ + _ppd_globals_t *pg; /* Pointer to global data */ - if (line) - *line = cg->ppd_line; - - return (cg->ppd_status); -} +#ifdef HAVE_PTHREAD_H + /* + * Initialize the global data exactly once... + */ + pthread_once(&ppd_globals_key_once, ppd_globals_init); +#endif /* HAVE_PTHREAD_H */ -/* - * 'ppdOpen()' - Read a PPD file into memory. - */ + /* + * See if we have allocated the data yet... + */ -ppd_file_t * /* O - PPD file record */ -ppdOpen(FILE *fp) /* I - File to read from */ -{ - ppd_file_t *ppd; /* PPD file record */ - cups_file_t *cf; /* CUPS file */ + if ((pg = (_ppd_globals_t *)_cupsThreadGetData(ppd_globals_key)) == NULL) + { + /* + * No, allocate memory as set the pointer for the key... + */ + if ((pg = ppd_globals_alloc()) != NULL) + _cupsThreadSetData(ppd_globals_key, pg); + } /* - * Reopen the stdio file as a CUPS file... + * Return the pointer to the data... */ - if ((cf = cupsFileOpenFd(fileno(fp), "r")) == NULL) - return (NULL); + return (pg); +} - /* - * Load the PPD file using the newer API... - */ - ppd = ppdOpen2(cf); +/* + * 'ppdLastError()' - Return the status from the last ppdOpen*(). + * + * @since CUPS 1.1.19/macOS 10.3@ + */ + +ppd_status_t /* O - Status code */ +ppdLastError(int *line) /* O - Line number */ +{ + _ppd_globals_t *pg = _ppdGlobals(); + /* Global data */ - /* - * Close the CUPS file and return the PPD... - */ - cupsFileClose(cf); + if (line) + *line = pg->ppd_line; - return (ppd); + return (pg->ppd_status); } /* - * 'ppdOpen2()' - Read a PPD file into memory. + * '_ppdOpen()' - Read a PPD file into memory. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */ -ppdOpen2(cups_file_t *fp) /* I - File to read from */ +_ppdOpen( + cups_file_t *fp, /* I - File to read from */ + _ppd_localization_t localization) /* I - Localization to load */ { int i, j, k; /* Looping vars */ int count; /* Temporary count */ @@ -457,15 +466,19 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ppd_section_t section; /* Order dependency section */ ppd_profile_t *profile; /* Pointer to color profile */ char **filter; /* Pointer to filter */ - cups_lang_t *language; /* Default language */ struct lconv *loc; /* Locale data */ int ui_keyword; /* Is this line a UI keyword? */ + cups_lang_t *lang; /* Language data */ cups_encoding_t encoding; /* Encoding of PPD file */ - _cups_globals_t *cg = _cupsGlobals(); + _ppd_globals_t *pg = _ppdGlobals(); /* Global data */ char custom_name[PPD_MAX_NAME]; /* CustomFoo attribute name */ ppd_attr_t *custom_attr; /* CustomFoo attribute */ + char ll[7], /* Base language + '.' */ + ll_CC[7]; /* Language w/country + '.' */ + size_t ll_len = 0, /* Base language length */ + ll_CC_len = 0; /* Language w/country length */ static const char * const ui_keywords[] = { #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST @@ -527,14 +540,21 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ "PageSize" #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */ }; + static const char * const color_keywords[] = /* Keywords associated with color profiles */ + { + ".cupsICCProfile", + ".ColorModel", + }; + DEBUG_printf(("_ppdOpen(fp=%p)", fp)); + /* * Default to "OK" status... */ - cg->ppd_status = PPD_OK; - cg->ppd_line = 0; + pg->ppd_status = PPD_OK; + pg->ppd_line = 0; /* * Range check input... @@ -542,10 +562,39 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (fp == NULL) { - cg->ppd_status = PPD_NULL_FILE; + pg->ppd_status = PPD_NULL_FILE; return (NULL); } + /* + * If only loading a single localization set up the strings to match... + */ + + if (localization == _PPD_LOCALIZATION_DEFAULT) + { + if ((lang = cupsLangDefault()) == NULL) + return (NULL); + + snprintf(ll_CC, sizeof(ll_CC), "%s.", lang->language); + + /* + * + * + * Need to use a different base language for some locales... + */ + + if (!strcmp(lang->language, "zh_HK")) + strlcpy(ll, "zh_TW.", sizeof(ll)); + else + snprintf(ll, sizeof(ll), "%2.2s.", lang->language); + + ll_CC_len = strlen(ll_CC); + ll_len = strlen(ll); + + DEBUG_printf(("2_ppdOpen: Loading localizations matching \"%s\" and \"%s\"", + ll_CC, ll)); + } + /* * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'... */ @@ -553,9 +602,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ line.buffer = NULL; line.bufsize = 0; - mask = ppd_read(fp, &line, keyword, name, text, &string, 0, cg); + mask = ppd_read(fp, &line, keyword, name, text, &string, 0, pg); - DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask, keyword)); + DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\"...", mask, keyword)); if (mask == 0 || strcmp(keyword, "PPD-Adobe") || @@ -565,15 +614,16 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Either this is not a PPD file, or it is not a 4.x PPD file. */ - if (cg->ppd_status == PPD_OK) - cg->ppd_status = PPD_MISSING_PPDADOBE4; + if (pg->ppd_status == PPD_OK) + pg->ppd_status = PPD_MISSING_PPDADOBE4; _cupsStrFree(string); + ppd_free(line.buffer); return (NULL); } - DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword, string)); + DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string)); _cupsStrFree(string); @@ -583,25 +633,21 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if ((ppd = calloc(1, sizeof(ppd_file_t))) == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; + + _cupsStrFree(string); + ppd_free(line.buffer); return (NULL); } ppd->language_level = 2; ppd->color_device = 0; - ppd->colorspace = PPD_CS_GRAY; + ppd->colorspace = PPD_CS_N; ppd->landscape = -90; ppd->coptions = cupsArrayNew((cups_array_func_t)ppd_compare_coptions, NULL); - /* - * Get the default language for the user... - */ - - language = cupsLangDefault(); - loc = localeconv(); - /* * Read lines from the PPD file and add them to the file record... */ @@ -612,43 +658,27 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ choice = NULL; ui_keyword = 0; encoding = CUPS_ISO8859_1; + loc = localeconv(); - while ((mask = ppd_read(fp, &line, keyword, name, text, &string, 1, cg)) != 0) + while ((mask = ppd_read(fp, &line, keyword, name, text, &string, 1, pg)) != 0) { -#ifdef DEBUG - printf("mask = %x, keyword = \"%s\"", mask, keyword); - - if (name[0] != '\0') - printf(", name = \"%s\"", name); - - if (text[0] != '\0') - printf(", text = \"%s\"", text); + DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\", name=\"%s\", " + "text=\"%s\", string=%d chars...", mask, keyword, name, text, + string ? (int)strlen(string) : 0)); - if (string != NULL) - { - if (strlen(string) > 40) - printf(", string = %p", string); - else - printf(", string = \"%s\"", string); - } - - puts(""); -#endif /* DEBUG */ - - if (strcmp(keyword, "CloseUI") && strcmp(keyword, "CloseGroup") && - strcmp(keyword, "CloseSubGroup") && strncmp(keyword, "Default", 7) && - strcmp(keyword, "JCLCloseUI") && strcmp(keyword, "JCLOpenUI") && - strcmp(keyword, "OpenUI") && strcmp(keyword, "OpenGroup") && - strcmp(keyword, "OpenSubGroup") && string == NULL) + if (strncmp(keyword, "Default", 7) && !string && + pg->ppd_conform != PPD_CONFORM_RELAXED) { /* * Need a string value! */ - cg->ppd_status = PPD_MISSING_VALUE; + pg->ppd_status = PPD_MISSING_VALUE; goto error; } + else if (!string) + continue; /* * Certain main keywords (as defined by the PPD spec) may be used @@ -669,6 +699,50 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ui_keyword = 0; } + /* + * If we are filtering out keyword localizations, see if this line needs to + * be used... + */ + + if (localization != _PPD_LOCALIZATION_ALL && + (temp = strchr(keyword, '.')) != NULL && + ((temp - keyword) == 2 || (temp - keyword) == 5) && + _cups_isalpha(keyword[0]) && + _cups_isalpha(keyword[1]) && + (keyword[2] == '.' || + (keyword[2] == '_' && _cups_isalpha(keyword[3]) && + _cups_isalpha(keyword[4]) && keyword[5] == '.'))) + { + if (localization == _PPD_LOCALIZATION_NONE || + (localization == _PPD_LOCALIZATION_DEFAULT && + strncmp(ll_CC, keyword, ll_CC_len) && + strncmp(ll, keyword, ll_len))) + { + DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); + continue; + } + else if (localization == _PPD_LOCALIZATION_ICC_PROFILES) + { + /* + * Only load localizations for the color profile related keywords... + */ + + for (i = 0; + i < (int)(sizeof(color_keywords) / sizeof(color_keywords[0])); + i ++) + { + if (!_cups_strcasecmp(temp, color_keywords[i])) + break; + } + + if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0]))) + { + DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); + continue; + } + } + } + if (option == NULL && (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) == (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) @@ -685,16 +759,16 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ui_keyword = 1; - DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n", + DEBUG_printf(("2_ppdOpen: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!", keyword)); if (!group) { - if ((group = ppd_get_group(ppd, "General", _("General"), cg, + if ((group = ppd_get_group(ppd, "General", _("General"), pg, encoding)) == NULL) goto error; - DEBUG_printf(("Adding to group %s...\n", group->text)); + DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text)); option = ppd_get_option(group, keyword); group = NULL; } @@ -703,7 +777,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (option == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -729,7 +803,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ !strcmp(ppd->attrs[j]->name + 7, keyword) && ppd->attrs[j]->value) { - DEBUG_printf(("Setting Default%s to %s via attribute...\n", + DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...", option->keyword, ppd->attrs[j]->value)); strlcpy(option->defchoice, ppd->attrs[j]->value, sizeof(option->defchoice)); @@ -823,12 +897,11 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (ppd->num_profiles == 0) profile = malloc(sizeof(ppd_profile_t)); else - profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * - (ppd->num_profiles + 1)); + profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * (size_t)(ppd->num_profiles + 1)); if (!profile) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -858,11 +931,11 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (ppd->num_filters == 0) filter = malloc(sizeof(char *)); else - filter = realloc(ppd->filters, sizeof(char *) * (ppd->num_filters + 1)); + filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1)); if (filter == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -872,11 +945,10 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ppd->num_filters ++; /* - * Copy filter string and prevent it from being freed below... + * Retain a copy of the filter string... */ - *filter = string; - string = NULL; + *filter = _cupsStrRetain(string); } else if (!strcmp(keyword, "Throughput")) ppd->throughput = atoi(string); @@ -889,16 +961,15 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (ppd->num_fonts == 0) tempfonts = (char **)malloc(sizeof(char *)); else - tempfonts = (char **)realloc(ppd->fonts, - sizeof(char *) * (ppd->num_fonts + 1)); + tempfonts = (char **)realloc(ppd->fonts, sizeof(char *) * (size_t)(ppd->num_fonts + 1)); if (tempfonts == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } - + ppd->fonts = tempfonts; ppd->fonts[ppd->num_fonts] = _cupsStrAlloc(name); ppd->num_fonts ++; @@ -919,14 +990,14 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if ((coption = ppd_get_coption(ppd, keyword + 11)) == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } if ((cparam = ppd_get_cparam(coption, name, text)) == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -935,10 +1006,11 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Get the parameter data... */ - if (sscanf(string, "%d%32s%64s%64s", &corder, ctype, cminimum, + if (!string || + sscanf(string, "%d%32s%64s%64s", &corder, ctype, cminimum, cmaximum) != 4) { - cg->ppd_status = PPD_BAD_CUSTOM_PARAM; + pg->ppd_status = PPD_BAD_CUSTOM_PARAM; goto error; } @@ -995,7 +1067,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ } else { - cg->ppd_status = PPD_BAD_CUSTOM_PARAM; + pg->ppd_status = PPD_BAD_CUSTOM_PARAM; goto error; } @@ -1027,7 +1099,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ { ppd_option_t *custom_option; /* Custom option */ - DEBUG_puts("Processing Custom option..."); + DEBUG_puts("2_ppdOpen: Processing Custom option..."); /* * Get the option and custom option... @@ -1035,12 +1107,12 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (!ppd_get_coption(ppd, keyword + 6)) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } - if (option && !strcasecmp(option->keyword, keyword + 6)) + if (option && !_cups_strcasecmp(option->keyword, keyword + 6)) custom_option = option; else custom_option = ppdFindOption(ppd, keyword + 6); @@ -1051,19 +1123,23 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Add the "custom" option... */ - if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL) - { - DEBUG_puts("Unable to add Custom choice!"); + if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL) + if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL) + { + DEBUG_puts("1_ppdOpen: Unable to add Custom choice!"); - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; - goto error; - } + goto error; + } strlcpy(choice->text, text[0] ? text : _("Custom"), sizeof(choice->text)); choice->code = _cupsStrAlloc(string); + + if (custom_option->section == PPD_ORDER_JCL) + ppd_decode(choice->code); } /* @@ -1080,21 +1156,22 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ppd_add_size(ppd, "Custom"); - if (option && !strcasecmp(option->keyword, "PageRegion")) + if (option && !_cups_strcasecmp(option->keyword, "PageRegion")) custom_option = option; else custom_option = ppdFindOption(ppd, "PageRegion"); if (custom_option) { - if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL) - { - DEBUG_puts("Unable to add Custom choice!"); + if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL) + if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL) + { + DEBUG_puts("1_ppdOpen: Unable to add Custom choice!"); - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; - goto error; - } + goto error; + } strlcpy(choice->text, text[0] ? text : _("Custom"), sizeof(choice->text)); @@ -1108,7 +1185,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ else if (!strcmp(string, "Plus90")) ppd->landscape = 90; } - else if (!strcmp(keyword, "Emulators")) + else if (!strcmp(keyword, "Emulators") && string) { for (count = 1, sptr = string; sptr != NULL;) if ((sptr = strchr(sptr, ' ')) != NULL) @@ -1119,9 +1196,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ } ppd->num_emulations = count; - if ((ppd->emulations = calloc(count, sizeof(ppd_emul_t))) == NULL) + if ((ppd->emulations = calloc((size_t)count, sizeof(ppd_emul_t))) == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1164,22 +1241,53 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ } else if (!strcmp(keyword, "JobPatchFile")) { + /* + * CUPS STR #3421: Check for "*JobPatchFile: int: string" + */ + + if (isdigit(*string & 255)) + { + for (sptr = string + 1; isdigit(*sptr & 255); sptr ++); + + if (*sptr == ':') + { + /* + * Found "*JobPatchFile: int: string"... + */ + + pg->ppd_status = PPD_BAD_VALUE; + + goto error; + } + } + + if (!name[0] && pg->ppd_conform == PPD_CONFORM_STRICT) + { + /* + * Found "*JobPatchFile: string"... + */ + + pg->ppd_status = PPD_MISSING_OPTION_KEYWORD; + + goto error; + } + if (ppd->patches == NULL) - ppd->patches = _cupsStrAlloc(string); + ppd->patches = strdup(string); else { temp = realloc(ppd->patches, strlen(ppd->patches) + strlen(string) + 1); if (temp == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } ppd->patches = temp; - strcpy(ppd->patches + strlen(ppd->patches), string); + memcpy(ppd->patches + strlen(ppd->patches), string, strlen(string) + 1); } } else if (!strcmp(keyword, "OpenUI")) @@ -1188,9 +1296,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Don't allow nesting of options... */ - if (option && cg->ppd_conform == PPD_CONFORM_STRICT) + if (option && pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_NESTED_OPEN_UI; + pg->ppd_status = PPD_NESTED_OPEN_UI; goto error; } @@ -1199,26 +1307,26 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Add an option record to the current sub-group, group, or file... */ - DEBUG_printf(("name=\"%s\" (%d)\n", name, strlen(name))); + DEBUG_printf(("2_ppdOpen: name=\"%s\" (%d)", name, (int)strlen(name))); if (name[0] == '*') _cups_strcpy(name, name + 1); /* Eliminate leading asterisk */ - for (i = (int)strlen(name) - 1; i > 0 && isspace(name[i] & 255); i --) + for (i = (int)strlen(name) - 1; i > 0 && _cups_isspace(name[i]); i --) name[i] = '\0'; /* Eliminate trailing spaces */ - DEBUG_printf(("OpenUI of %s in group %s...\n", name, + DEBUG_printf(("2_ppdOpen: OpenUI of %s in group %s...", name, group ? group->text : "(null)")); if (subgroup != NULL) option = ppd_get_option(subgroup, name); else if (group == NULL) { - if ((group = ppd_get_group(ppd, "General", _("General"), cg, + if ((group = ppd_get_group(ppd, "General", _("General"), pg, encoding)) == NULL) goto error; - DEBUG_printf(("Adding to group %s...\n", group->text)); + DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text)); option = ppd_get_option(group, name); group = NULL; } @@ -1227,7 +1335,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (option == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1242,9 +1350,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ option->ui = PPD_UI_BOOLEAN; else if (string && !strcmp(string, "PickOne")) option->ui = PPD_UI_PICKONE; - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_OPEN_UI; + pg->ppd_status = PPD_BAD_OPEN_UI; goto error; } @@ -1256,7 +1364,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ !strcmp(ppd->attrs[j]->name + 7, name) && ppd->attrs[j]->value) { - DEBUG_printf(("Setting Default%s to %s via attribute...\n", + DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...", option->keyword, ppd->attrs[j]->value)); strlcpy(option->defchoice, ppd->attrs[j]->value, sizeof(option->defchoice)); @@ -1292,26 +1400,27 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * attribute... */ - if (!strcasecmp(name, "PageRegion")) - strcpy(custom_name, "CustomPageSize"); + if (!_cups_strcasecmp(name, "PageRegion")) + strlcpy(custom_name, "CustomPageSize", sizeof(custom_name)); else snprintf(custom_name, sizeof(custom_name), "Custom%s", name); if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL) { - if ((choice = ppd_add_choice(option, "Custom")) == NULL) - { - DEBUG_puts("Unable to add Custom choice!"); + if ((choice = ppdFindChoice(option, "Custom")) == NULL) + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + DEBUG_puts("1_ppdOpen: Unable to add Custom choice!"); - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; - goto error; - } + goto error; + } strlcpy(choice->text, custom_attr->text[0] ? custom_attr->text : _("Custom"), sizeof(choice->text)); - choice->code = _cupsStrAlloc(custom_attr->value); + choice->code = _cupsStrRetain(custom_attr->value); } } else if (!strcmp(keyword, "JCLOpenUI")) @@ -1320,9 +1429,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Don't allow nesting of options... */ - if (option && cg->ppd_conform == PPD_CONFORM_STRICT) + if (option && pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_NESTED_OPEN_UI; + pg->ppd_status = PPD_NESTED_OPEN_UI; goto error; } @@ -1331,7 +1440,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Find the JCL group, and add if needed... */ - group = ppd_get_group(ppd, "JCL", _("JCL"), cg, encoding); + group = ppd_get_group(ppd, "JCL", _("JCL"), pg, encoding); if (group == NULL) goto error; @@ -1347,7 +1456,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (option == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1364,7 +1473,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ option->ui = PPD_UI_PICKONE; else { - cg->ppd_status = PPD_BAD_OPEN_UI; + pg->ppd_status = PPD_BAD_OPEN_UI; goto error; } @@ -1374,7 +1483,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ !strcmp(ppd->attrs[j]->name + 7, name) && ppd->attrs[j]->value) { - DEBUG_printf(("Setting Default%s to %s via attribute...\n", + DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...", option->keyword, ppd->attrs[j]->value)); strlcpy(option->defchoice, ppd->attrs[j]->value, sizeof(option->defchoice)); @@ -1404,9 +1513,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ { if ((choice = ppd_add_choice(option, "Custom")) == NULL) { - DEBUG_puts("Unable to add Custom choice!"); + DEBUG_puts("1_ppdOpen: Unable to add Custom choice!"); - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1414,7 +1523,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ strlcpy(choice->text, custom_attr->text[0] ? custom_attr->text : _("Custom"), sizeof(choice->text)); - choice->code = _cupsStrAlloc(custom_attr->value); + choice->code = _cupsStrRetain(custom_attr->value); } } else if (!strcmp(keyword, "CloseUI") || !strcmp(keyword, "JCLCloseUI")) @@ -1432,14 +1541,14 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (group != NULL) { - cg->ppd_status = PPD_NESTED_OPEN_GROUP; + pg->ppd_status = PPD_NESTED_OPEN_GROUP; goto error; } if (!string) { - cg->ppd_status = PPD_BAD_OPEN_GROUP; + pg->ppd_status = PPD_BAD_OPEN_GROUP; goto error; } @@ -1463,7 +1572,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Find/add the group... */ - group = ppd_get_group(ppd, string, sptr, cg, encoding); + group = ppd_get_group(ppd, string, sptr, pg, encoding); if (group == NULL) goto error; @@ -1484,7 +1593,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (!sptr || sscanf(sptr, "%40s%40s", name, keyword) != 2) { - cg->ppd_status = PPD_BAD_ORDER_DEPENDENCY; + pg->ppd_status = PPD_BAD_ORDER_DEPENDENCY; goto error; } @@ -1577,11 +1686,11 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Set the default as part of the current option... */ - DEBUG_printf(("Setting %s to %s...\n", keyword, string)); + DEBUG_printf(("2_ppdOpen: Setting %s to %s...", keyword, string)); strlcpy(option->defchoice, string, sizeof(option->defchoice)); - DEBUG_printf(("%s is now %s...\n", keyword, option->defchoice)); + DEBUG_printf(("2_ppdOpen: %s is now %s...", keyword, option->defchoice)); } else { @@ -1594,7 +1703,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if ((toption = ppdFindOption(ppd, keyword + 7)) != NULL) { - DEBUG_printf(("Setting %s to %s...\n", keyword, string)); + DEBUG_printf(("2_ppdOpen: Setting %s to %s...", keyword, string)); strlcpy(toption->defchoice, string, sizeof(toption->defchoice)); } } @@ -1602,15 +1711,20 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ else if (!strcmp(keyword, "UIConstraints") || !strcmp(keyword, "NonUIConstraints")) { + if (!string) + { + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + goto error; + } + if (ppd->num_consts == 0) constraint = calloc(2, sizeof(ppd_const_t)); else - constraint = realloc(ppd->consts, - (ppd->num_consts + 2) * sizeof(ppd_const_t)); + constraint = realloc(ppd->consts, (size_t)(ppd->num_consts + 2) * sizeof(ppd_const_t)); if (constraint == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1625,7 +1739,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ { case 0 : /* Error */ case 1 : /* Error */ - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; case 2 : /* Two options... */ @@ -1633,11 +1747,11 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Check for broken constraints like "* Option"... */ - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && (!strcmp(constraint->option1, "*") || !strcmp(constraint->choice1, "*"))) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } @@ -1648,35 +1762,35 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (constraint->option1[0] == '*') _cups_strcpy(constraint->option1, constraint->option1 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } if (constraint->choice1[0] == '*') _cups_strcpy(constraint->option2, constraint->choice1 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } constraint->choice1[0] = '\0'; constraint->choice2[0] = '\0'; break; - + case 3 : /* Two options, one choice... */ /* * Check for broken constraints like "* Option"... */ - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && (!strcmp(constraint->option1, "*") || !strcmp(constraint->choice1, "*") || !strcmp(constraint->option2, "*"))) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } @@ -1687,18 +1801,18 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if (constraint->option1[0] == '*') _cups_strcpy(constraint->option1, constraint->option1 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } if (constraint->choice1[0] == '*') { - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && constraint->option2[0] == '*') { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } @@ -1710,109 +1824,63 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ { if (constraint->option2[0] == '*') _cups_strcpy(constraint->option2, constraint->option2 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } constraint->choice2[0] = '\0'; } break; - + case 4 : /* Two options, two choices... */ /* * Check for broken constraints like "* Option"... */ - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && (!strcmp(constraint->option1, "*") || !strcmp(constraint->choice1, "*") || !strcmp(constraint->option2, "*") || !strcmp(constraint->choice2, "*"))) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } if (constraint->option1[0] == '*') _cups_strcpy(constraint->option1, constraint->option1 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && constraint->choice1[0] == '*') { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } if (constraint->option2[0] == '*') _cups_strcpy(constraint->option2, constraint->option2 + 1); - else if (cg->ppd_conform == PPD_CONFORM_STRICT) + else if (pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } - if (cg->ppd_conform == PPD_CONFORM_STRICT && + if (pg->ppd_conform == PPD_CONFORM_STRICT && constraint->choice2[0] == '*') { - cg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; goto error; } break; } - /* - * For CustomPageSize and InputSlot/ManualFeed, create a duplicate - * constraint for PageRegion... - */ - - if (!strcasecmp(constraint->option1, "CustomPageSize") && - (!strcasecmp(constraint->option2, "InputSlot") || - !strcasecmp(constraint->option2, "ManualFeed"))) - { - ppd->num_consts ++; - - strcpy(constraint[1].option1, "PageRegion"); - strcpy(constraint[1].choice1, "Custom"); - strcpy(constraint[1].option2, constraint->option2); - strcpy(constraint[1].choice2, constraint->choice2); - } - else if (!strcasecmp(constraint->option2, "CustomPageSize") && - (!strcasecmp(constraint->option1, "InputSlot") || - !strcasecmp(constraint->option1, "ManualFeed"))) - { - ppd->num_consts ++; - - strcpy(constraint[1].option1, constraint->option1); - strcpy(constraint[1].choice1, constraint->choice1); - strcpy(constraint[1].option2, "PageRegion"); - strcpy(constraint[1].choice2, "Custom"); - } - - /* - * Handle CustomFoo option constraints... - */ - - if (!strncasecmp(constraint->option1, "Custom", 6) && - !strcasecmp(constraint->choice1, "True")) - { - _cups_strcpy(constraint->option1, constraint->option1 + 6); - strcpy(constraint->choice1, "Custom"); - } - - if (!strncasecmp(constraint->option2, "Custom", 6) && - !strcasecmp(constraint->choice2, "True")) - { - _cups_strcpy(constraint->option2, constraint->option2 + 6); - strcpy(constraint->choice2, "Custom"); - } - /* * Don't add this one as an attribute... */ @@ -1831,7 +1899,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Unable to add or find size! */ - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1853,7 +1921,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Unable to add or find size! */ - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1871,7 +1939,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ (PPD_KEYWORD | PPD_OPTION | PPD_STRING) && !strcmp(keyword, option->keyword)) { - DEBUG_printf(("group = %p, subgroup = %p\n", group, subgroup)); + DEBUG_printf(("2_ppdOpen: group=%p, subgroup=%p", group, subgroup)); if (!strcmp(keyword, "PageSize")) { @@ -1889,7 +1957,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ if ((choice = ppd_add_choice(option, name)) == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; goto error; } @@ -1898,9 +1966,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ cupsCharsetToUTF8((cups_utf8_t *)choice->text, text, sizeof(choice->text), encoding); else if (!strcmp(name, "True")) - strcpy(choice->text, _("Yes")); + strlcpy(choice->text, _("Yes"), sizeof(choice->text)); else if (!strcmp(name, "False")) - strcpy(choice->text, _("No")); + strlcpy(choice->text, _("No"), sizeof(choice->text)); else strlcpy(choice->text, name, sizeof(choice->text)); @@ -1922,21 +1990,29 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ _cupsStrFree(string); } - if (line.buffer) - free(line.buffer); + /* + * Check for a missing CloseGroup... + */ + + if (group && pg->ppd_conform == PPD_CONFORM_STRICT) + { + pg->ppd_status = PPD_MISSING_CLOSE_GROUP; + goto error; + } + + ppd_free(line.buffer); /* * Reset language preferences... */ - cupsLangFree(language); - #ifdef DEBUG if (!cupsFileEOF(fp)) - printf("Premature EOF at %lu...\n", (unsigned long)cupsFileTell(fp)); + DEBUG_printf(("1_ppdOpen: Premature EOF at %lu...\n", + (unsigned long)cupsFileTell(fp))); #endif /* DEBUG */ - if (cg->ppd_status != PPD_OK) + if (pg->ppd_status != PPD_OK) { /* * Had an error reading the PPD file, cannot continue! @@ -1947,6 +2023,17 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ return (NULL); } + /* + * Update the filters array as needed... + */ + + if (!ppd_update_filters(ppd, pg)) + { + ppdClose(ppd); + + return (NULL); + } + /* * Create the sorted options array and set the option back-pointer for * each choice and custom option... @@ -1977,14 +2064,6 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ } } - /* - * Sort the constraints... - */ - - if (ppd->num_consts > 1) - qsort(ppd->consts, ppd->num_consts, sizeof(ppd_const_t), - (int (*)(const void *, const void *))ppd_compare_consts); - /* * Create an array to track the marked choices... */ @@ -2003,19 +2082,62 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ error: - if (line.buffer) - free(line.buffer); - _cupsStrFree(string); + ppd_free(line.buffer); ppdClose(ppd); - cupsLangFree(language); - return (NULL); } +/* + * 'ppdOpen()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpen(FILE *fp) /* I - File to read from */ +{ + ppd_file_t *ppd; /* PPD file record */ + cups_file_t *cf; /* CUPS file */ + + + /* + * Reopen the stdio file as a CUPS file... + */ + + if ((cf = cupsFileOpenFd(fileno(fp), "r")) == NULL) + return (NULL); + + /* + * Load the PPD file using the newer API... + */ + + ppd = _ppdOpen(cf, _PPD_LOCALIZATION_DEFAULT); + + /* + * Close the CUPS file and return the PPD... + */ + + cupsFileClose(cf); + + return (ppd); +} + + +/* + * 'ppdOpen2()' - Read a PPD file into memory. + * + * @since CUPS 1.2/macOS 10.5@ + */ + +ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */ +ppdOpen2(cups_file_t *fp) /* I - File to read from */ +{ + return _ppdOpen(fp, _PPD_LOCALIZATION_DEFAULT); +} + + /* * 'ppdOpenFd()' - Read a PPD file into memory. */ @@ -2025,7 +2147,7 @@ ppdOpenFd(int fd) /* I - File to read from */ { cups_file_t *fp; /* CUPS file pointer */ ppd_file_t *ppd; /* PPD file record */ - _cups_globals_t *cg = _cupsGlobals(); + _ppd_globals_t *pg = _ppdGlobals(); /* Global data */ @@ -2033,7 +2155,7 @@ ppdOpenFd(int fd) /* I - File to read from */ * Set the line number to 0... */ - cg->ppd_line = 0; + pg->ppd_line = 0; /* * Range check input... @@ -2041,7 +2163,7 @@ ppdOpenFd(int fd) /* I - File to read from */ if (fd < 0) { - cg->ppd_status = PPD_NULL_FILE; + pg->ppd_status = PPD_NULL_FILE; return (NULL); } @@ -2058,7 +2180,7 @@ ppdOpenFd(int fd) /* I - File to read from */ } else { - cg->ppd_status = PPD_FILE_OPEN_ERROR; + pg->ppd_status = PPD_FILE_OPEN_ERROR; ppd = NULL; } @@ -2067,15 +2189,16 @@ ppdOpenFd(int fd) /* I - File to read from */ /* - * 'ppdOpenFile()' - Read a PPD file into memory. + * '_ppdOpenFile()' - Read a PPD file into memory. */ ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */ -ppdOpenFile(const char *filename) /* I - File to read from */ +_ppdOpenFile(const char *filename, /* I - File to read from */ + _ppd_localization_t localization) /* I - Localization to load */ { cups_file_t *fp; /* File pointer */ ppd_file_t *ppd; /* PPD file record */ - _cups_globals_t *cg = _cupsGlobals(); + _ppd_globals_t *pg = _ppdGlobals(); /* Global data */ @@ -2083,7 +2206,7 @@ ppdOpenFile(const char *filename) /* I - File to read from */ * Set the line number to 0... */ - cg->ppd_line = 0; + pg->ppd_line = 0; /* * Range check input... @@ -2091,7 +2214,7 @@ ppdOpenFile(const char *filename) /* I - File to read from */ if (filename == NULL) { - cg->ppd_status = PPD_NULL_FILE; + pg->ppd_status = PPD_NULL_FILE; return (NULL); } @@ -2102,13 +2225,13 @@ ppdOpenFile(const char *filename) /* I - File to read from */ if ((fp = cupsFileOpen(filename, "r")) != NULL) { - ppd = ppdOpen2(fp); + ppd = _ppdOpen(fp, localization); cupsFileClose(fp); } else { - cg->ppd_status = PPD_FILE_OPEN_ERROR; + pg->ppd_status = PPD_FILE_OPEN_ERROR; ppd = NULL; } @@ -2116,20 +2239,31 @@ ppdOpenFile(const char *filename) /* I - File to read from */ } +/* + * 'ppdOpenFile()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */ +ppdOpenFile(const char *filename) /* I - File to read from */ +{ + return _ppdOpenFile(filename, _PPD_LOCALIZATION_DEFAULT); +} + + /* * 'ppdSetConformance()' - Set the conformance level for PPD files. * - * @since CUPS 1.1.20@ + * @since CUPS 1.1.20/macOS 10.4@ */ void ppdSetConformance(ppd_conform_t c) /* I - Conformance level */ { - _cups_globals_t *cg = _cupsGlobals(); + _ppd_globals_t *pg = _ppdGlobals(); /* Global data */ - cg->ppd_conform = c; + pg->ppd_conform = c; } @@ -2170,7 +2304,7 @@ ppd_add_attr(ppd_file_t *ppd, /* I - PPD file data */ if (ppd->num_attrs == 0) ptr = malloc(sizeof(ppd_attr_t *)); else - ptr = realloc(ppd->attrs, (ppd->num_attrs + 1) * sizeof(ppd_attr_t *)); + ptr = realloc(ppd->attrs, (size_t)(ppd->num_attrs + 1) * sizeof(ppd_attr_t *)); if (ptr == NULL) return (NULL); @@ -2222,8 +2356,7 @@ ppd_add_choice(ppd_option_t *option, /* I - Option */ if (option->num_choices == 0) choice = malloc(sizeof(ppd_choice_t)); else - choice = realloc(option->choices, - sizeof(ppd_choice_t) * (option->num_choices + 1)); + choice = realloc(option->choices, sizeof(ppd_choice_t) * (size_t)(option->num_choices + 1)); if (choice == NULL) return (NULL); @@ -2253,7 +2386,7 @@ ppd_add_size(ppd_file_t *ppd, /* I - PPD file */ if (ppd->num_sizes == 0) size = malloc(sizeof(ppd_size_t)); else - size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1)); + size = realloc(ppd->sizes, sizeof(ppd_size_t) * (size_t)(ppd->num_sizes + 1)); if (size == NULL) return (NULL); @@ -2277,13 +2410,7 @@ static int /* O - Result of comparison */ ppd_compare_attrs(ppd_attr_t *a, /* I - First attribute */ ppd_attr_t *b) /* I - Second attribute */ { - int ret; /* Result of comparison */ - - - if ((ret = strcasecmp(a->name, b->name)) != 0) - return (ret); - else - return (strcasecmp(a->spec, b->spec)); + return (_cups_strcasecmp(a->name, b->name)); } @@ -2299,28 +2426,6 @@ ppd_compare_choices(ppd_choice_t *a, /* I - First choice */ } -/* - * 'ppd_compare_consts()' - Compare two constraints. - */ - -static int /* O - Result of comparison */ -ppd_compare_consts(ppd_const_t *a, /* I - First constraint */ - ppd_const_t *b) /* I - Second constraint */ -{ - int ret; /* Result of comparison */ - - - if ((ret = strcmp(a->option1, b->option1)) != 0) - return (ret); - else if ((ret = strcmp(a->choice1, b->choice1)) != 0) - return (ret); - else if ((ret = strcmp(a->option2, b->option2)) != 0) - return (ret); - else - return (strcmp(a->choice2, b->choice2)); -} - - /* * 'ppd_compare_coptions()' - Compare two custom options. */ @@ -2329,19 +2434,7 @@ static int /* O - Result of comparison */ ppd_compare_coptions(ppd_coption_t *a, /* I - First option */ ppd_coption_t *b) /* I - Second option */ { - return (strcasecmp(a->keyword, b->keyword)); -} - - -/* - * 'ppd_compare_cparams()' - Compare two custom parameters. - */ - -static int /* O - Result of comparison */ -ppd_compare_cparams(ppd_cparam_t *a, /* I - First parameter */ - ppd_cparam_t *b) /* I - Second parameter */ -{ - return (strcasecmp(a->name, b->name)); + return (_cups_strcasecmp(a->keyword, b->keyword)); } @@ -2353,7 +2446,7 @@ static int /* O - Result of comparison */ ppd_compare_options(ppd_option_t *a, /* I - First option */ ppd_option_t *b) /* I - Second option */ { - return (strcasecmp(a->keyword, b->keyword)); + return (_cups_strcasecmp(a->keyword, b->keyword)); } @@ -2381,20 +2474,20 @@ ppd_decode(char *string) /* I - String to decode */ inptr ++; while (isxdigit(*inptr & 255)) { - if (isalpha(*inptr)) - *outptr = (tolower(*inptr) - 'a' + 10) << 4; + if (_cups_isalpha(*inptr)) + *outptr = (char)((tolower(*inptr) - 'a' + 10) << 4); else - *outptr = (*inptr - '0') << 4; + *outptr = (char)((*inptr - '0') << 4); inptr ++; if (!isxdigit(*inptr & 255)) break; - if (isalpha(*inptr)) - *outptr |= tolower(*inptr) - 'a' + 10; + if (_cups_isalpha(*inptr)) + *outptr |= (char)(tolower(*inptr) - 'a' + 10); else - *outptr |= *inptr - '0'; + *outptr |= (char)(*inptr - '0'); inptr ++; outptr ++; @@ -2414,6 +2507,30 @@ ppd_decode(char *string) /* I - String to decode */ } +/* + * 'ppd_free_filters()' - Free the filters array. + */ + +static void +ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */ +{ + int i; /* Looping var */ + char **filter; /* Current filter */ + + + if (ppd->num_filters > 0) + { + for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) + _cupsStrFree(*filter); + + ppd_free(ppd->filters); + + ppd->num_filters = 0; + ppd->filters = NULL; + } +} + + /* * 'ppd_free_group()' - Free a single UI group. */ @@ -2500,7 +2617,7 @@ ppd_get_coption(ppd_file_t *ppd, /* I - PPD file */ strlcpy(copt->keyword, name, sizeof(copt->keyword)); - copt->params = cupsArrayNew((cups_array_func_t)ppd_compare_cparams, NULL); + copt->params = cupsArrayNew((cups_array_func_t)NULL, NULL); cupsArrayAdd(ppd->coptions, copt); @@ -2563,15 +2680,15 @@ static ppd_group_t * /* O - Named group */ ppd_get_group(ppd_file_t *ppd, /* I - PPD file */ const char *name, /* I - Name of group */ const char *text, /* I - Text for group */ - _cups_globals_t *cg, /* I - Global data */ + _ppd_globals_t *pg, /* I - Global data */ cups_encoding_t encoding) /* I - Encoding of text */ { int i; /* Looping var */ ppd_group_t *group; /* Group */ - DEBUG_printf(("ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)\n", - ppd, name, text, cg)); + DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)", + ppd, name, text, pg)); for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) if (!strcmp(group->name, name)) @@ -2579,24 +2696,23 @@ ppd_get_group(ppd_file_t *ppd, /* I - PPD file */ if (i == 0) { - DEBUG_printf(("Adding group %s...\n", name)); + DEBUG_printf(("8ppd_get_group: Adding group %s...", name)); - if (cg->ppd_conform == PPD_CONFORM_STRICT && strlen(text) >= sizeof(group->text)) + if (pg->ppd_conform == PPD_CONFORM_STRICT && strlen(text) >= sizeof(group->text)) { - cg->ppd_status = PPD_ILLEGAL_TRANSLATION; + pg->ppd_status = PPD_ILLEGAL_TRANSLATION; return (NULL); } - + if (ppd->num_groups == 0) group = malloc(sizeof(ppd_group_t)); else - group = realloc(ppd->groups, - (ppd->num_groups + 1) * sizeof(ppd_group_t)); + group = realloc(ppd->groups, (size_t)(ppd->num_groups + 1) * sizeof(ppd_group_t)); if (group == NULL) { - cg->ppd_status = PPD_ALLOC_ERROR; + pg->ppd_status = PPD_ALLOC_ERROR; return (NULL); } @@ -2628,7 +2744,7 @@ ppd_get_option(ppd_group_t *group, /* I - Group */ ppd_option_t *option; /* Option */ - DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n", + DEBUG_printf(("7ppd_get_option(group=%p(\"%s\"), name=\"%s\")", group, group->name, name)); for (i = group->num_options, option = group->options; i > 0; i --, option ++) @@ -2640,8 +2756,7 @@ ppd_get_option(ppd_group_t *group, /* I - Group */ if (group->num_options == 0) option = malloc(sizeof(ppd_option_t)); else - option = realloc(group->options, - (group->num_options + 1) * sizeof(ppd_option_t)); + option = realloc(group->options, (size_t)(group->num_options + 1) * sizeof(ppd_option_t)); if (option == NULL) return (NULL); @@ -2658,6 +2773,47 @@ ppd_get_option(ppd_group_t *group, /* I - Group */ } +/* + * 'ppd_globals_alloc()' - Allocate and initialize global data. + */ + +static _ppd_globals_t * /* O - Pointer to global data */ +ppd_globals_alloc(void) +{ + return ((_ppd_globals_t *)calloc(1, sizeof(_ppd_globals_t))); +} + + +/* + * 'ppd_globals_free()' - Free global data. + */ + +#if defined(HAVE_PTHREAD_H) || defined(WIN32) +static void +ppd_globals_free(_ppd_globals_t *pg) /* I - Pointer to global data */ +{ + free(pg); +} +#endif /* HAVE_PTHREAD_H || WIN32 */ + + +#ifdef HAVE_PTHREAD_H +/* + * 'ppd_globals_init()' - Initialize per-thread globals... + */ + +static void +ppd_globals_init(void) +{ + /* + * Register the global data for this thread... + */ + + pthread_key_create(&ppd_globals_key, (void (*)(void *))ppd_globals_free); +} +#endif /* HAVE_PTHREAD_H */ + + /* * 'ppd_hash_option()' - Generate a hash of the option name... */ @@ -2689,7 +2845,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ char *text, /* O - Human-readable text from line */ char **string, /* O - Code/string data */ int ignoreblank, /* I - Ignore blank lines? */ - _cups_globals_t *cg) /* I - Global data */ + _ppd_globals_t *pg) /* I - Global data */ { int ch, /* Character from file */ col, /* Column in line */ @@ -2711,7 +2867,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *string = NULL; col = 0; - startline = cg->ppd_line + 1; + startline = pg->ppd_line + 1; if (!line->buffer) { @@ -2750,8 +2906,8 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Don't allow lines longer than 256k! */ - cg->ppd_line = startline; - cg->ppd_status = PPD_LINE_TOO_LONG; + pg->ppd_line = startline; + pg->ppd_status = PPD_LINE_TOO_LONG; return (0); } @@ -2759,8 +2915,8 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ temp = realloc(line->buffer, line->bufsize); if (!temp) { - cg->ppd_line = startline; - cg->ppd_status = PPD_LINE_TOO_LONG; + pg->ppd_line = startline; + pg->ppd_status = PPD_LINE_TOO_LONG; return (0); } @@ -2775,7 +2931,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Line feed or carriage return... */ - cg->ppd_line ++; + pg->ppd_line ++; col = 0; if (ch == '\r') @@ -2804,14 +2960,14 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *lineptr++ = '\n'; } - else if (ch < ' ' && ch != '\t' && cg->ppd_conform == PPD_CONFORM_STRICT) + else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT) { /* * Other control characters... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_ILLEGAL_CHARACTER; + pg->ppd_line = startline; + pg->ppd_status = PPD_ILLEGAL_CHARACTER; return (0); } @@ -2821,7 +2977,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Any other character... */ - *lineptr++ = ch; + *lineptr++ = (char)ch; col ++; if (col > (PPD_MAX_LINE - 1)) @@ -2830,8 +2986,8 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Line is too long... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_LINE_TOO_LONG; + pg->ppd_line = startline; + pg->ppd_status = PPD_LINE_TOO_LONG; return (0); } @@ -2855,7 +3011,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ break; else if (ch == '\r' || ch == '\n') { - cg->ppd_line ++; + pg->ppd_line ++; col = 0; if (ch == '\r') @@ -2869,17 +3025,15 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ if (ch == 0x0a) cupsFileGetChar(fp); } - - ch = '\n'; } - else if (ch < ' ' && ch != '\t' && cg->ppd_conform == PPD_CONFORM_STRICT) + else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT) { /* * Other control characters... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_ILLEGAL_CHARACTER; + pg->ppd_line = startline; + pg->ppd_status = PPD_ILLEGAL_CHARACTER; return (0); } @@ -2893,8 +3047,8 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Line is too long... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_LINE_TOO_LONG; + pg->ppd_line = startline; + pg->ppd_status = PPD_LINE_TOO_LONG; return (0); } @@ -2914,7 +3068,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Line feed or carriage return... */ - cg->ppd_line ++; + pg->ppd_line ++; col = 0; if (ch == '\r') @@ -2931,14 +3085,14 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ break; } - else if (ch < ' ' && ch != '\t' && cg->ppd_conform == PPD_CONFORM_STRICT) + else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT) { /* * Other control characters... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_ILLEGAL_CHARACTER; + pg->ppd_line = startline; + pg->ppd_status = PPD_ILLEGAL_CHARACTER; return (0); } @@ -2952,8 +3106,8 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ * Line is too long... */ - cg->ppd_line = startline; - cg->ppd_status = PPD_LINE_TOO_LONG; + pg->ppd_line = startline; + pg->ppd_status = PPD_LINE_TOO_LONG; return (0); } @@ -2965,10 +3119,10 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *lineptr = '\0'; - DEBUG_printf(("LINE = \"%s\"\n", line)); + DEBUG_printf(("9ppd_read: LINE=\"%s\"", line->buffer)); /* - * The dynamically created PPDs for older style Mac OS X + * The dynamically created PPDs for older style macOS * drivers include a large blob of data inserted as comments * at the end of the file. As an optimization we can stop * reading the PPD when we get to the start of this data. @@ -2997,21 +3151,21 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ !strcmp(line->buffer, "*End")) && /* End of multi-line string */ ignoreblank) /* Ignore these? */ { - startline = cg->ppd_line + 1; + startline = pg->ppd_line + 1; continue; } if (!strcmp(line->buffer, "*")) /* (Bad) comment line */ { - if (cg->ppd_conform == PPD_CONFORM_RELAXED) + if (pg->ppd_conform == PPD_CONFORM_RELAXED) { - startline = cg->ppd_line + 1; + startline = pg->ppd_line + 1; continue; } else { - cg->ppd_line = startline; - cg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD; + pg->ppd_line = startline; + pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD; return (0); } @@ -3024,12 +3178,12 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ */ for (lineptr = line->buffer; *lineptr; lineptr ++) - if (!isspace(*lineptr & 255)) + if (*lineptr && !_cups_isspace(*lineptr)) break; if (*lineptr) { - cg->ppd_status = PPD_MISSING_ASTERISK; + pg->ppd_status = PPD_MISSING_ASTERISK; return (0); } else if (ignoreblank) @@ -3044,12 +3198,12 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ keyptr = keyword; - while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr & 255)) + while (*lineptr && *lineptr != ':' && !_cups_isspace(*lineptr)) { if (*lineptr <= ' ' || *lineptr > 126 || *lineptr == '/' || (keyptr - keyword) >= (PPD_MAX_NAME - 1)) { - cg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD; + pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD; return (0); } @@ -3063,26 +3217,24 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ mask |= PPD_KEYWORD; -/* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/ - - if (isspace(*lineptr & 255)) + if (_cups_isspace(*lineptr)) { /* * Get an option name... */ - while (isspace(*lineptr & 255)) + while (_cups_isspace(*lineptr)) lineptr ++; optptr = option; - while (*lineptr != '\0' && !isspace(*lineptr & 255) && *lineptr != ':' && + while (*lineptr && !_cups_isspace(*lineptr) && *lineptr != ':' && *lineptr != '/') { if (*lineptr <= ' ' || *lineptr > 126 || (optptr - option) >= (PPD_MAX_NAME - 1)) { - cg->ppd_status = PPD_ILLEGAL_OPTION_KEYWORD; + pg->ppd_status = PPD_ILLEGAL_OPTION_KEYWORD; return (0); } @@ -3091,19 +3243,17 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *optptr = '\0'; - if (isspace(*lineptr & 255) && cg->ppd_conform == PPD_CONFORM_STRICT) + if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_ILLEGAL_WHITESPACE; + pg->ppd_status = PPD_ILLEGAL_WHITESPACE; return (0); } - while (isspace(*lineptr & 255)) + while (_cups_isspace(*lineptr)) lineptr ++; mask |= PPD_OPTION; -/* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/ - if (*lineptr == '/') { /* @@ -3111,7 +3261,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ */ lineptr ++; - + textptr = text; while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':') @@ -3119,7 +3269,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ if (((unsigned char)*lineptr < ' ' && *lineptr != '\t') || (textptr - text) >= (PPD_MAX_LINE - 1)) { - cg->ppd_status = PPD_ILLEGAL_TRANSLATION; + pg->ppd_status = PPD_ILLEGAL_TRANSLATION; return (0); } @@ -3129,25 +3279,23 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *textptr = '\0'; textlen = ppd_decode(text); - if (textlen > PPD_MAX_TEXT && cg->ppd_conform == PPD_CONFORM_STRICT) + if (textlen > PPD_MAX_TEXT && pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_ILLEGAL_TRANSLATION; + pg->ppd_status = PPD_ILLEGAL_TRANSLATION; return (0); } - + mask |= PPD_TEXT; } - -/* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/ } - if (isspace(*lineptr & 255) && cg->ppd_conform == PPD_CONFORM_STRICT) + if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT) { - cg->ppd_status = PPD_ILLEGAL_WHITESPACE; + pg->ppd_status = PPD_ILLEGAL_WHITESPACE; return (0); } - while (isspace(*lineptr & 255)) + while (_cups_isspace(*lineptr)) lineptr ++; if (*lineptr == ':') @@ -3157,11 +3305,11 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ */ lineptr ++; - while (isspace(*lineptr & 255)) + while (_cups_isspace(*lineptr)) lineptr ++; strptr = lineptr + strlen(lineptr) - 1; - while (strptr >= lineptr && isspace(*strptr & 255)) + while (strptr >= lineptr && _cups_isspace(*strptr)) *strptr-- = '\0'; if (*strptr == '\"') @@ -3176,8 +3324,6 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *string = _cupsStrAlloc(lineptr); -/* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/ - mask |= PPD_STRING; } } @@ -3188,5 +3334,120 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ /* - * End of "$Id: ppd.c 6937 2007-09-10 21:13:31Z mike $". + * 'ppd_update_filters()' - Update the filters array as needed. + * + * This function re-populates the filters array with cupsFilter2 entries that + * have been stripped of the destination MIME media types and any maxsize hints. + * + * (All for backwards-compatibility) */ + +static int /* O - 1 on success, 0 on failure */ +ppd_update_filters(ppd_file_t *ppd, /* I - PPD file */ + _ppd_globals_t *pg) /* I - Global data */ +{ + ppd_attr_t *attr; /* Current cupsFilter2 value */ + char srcsuper[16], /* Source MIME media type */ + srctype[256], + dstsuper[16], /* Destination MIME media type */ + dsttype[256], + program[1024], /* Command to run */ + *ptr, /* Pointer into command to run */ + buffer[1024], /* Re-written cupsFilter value */ + **filter; /* Current filter */ + int cost; /* Cost of filter */ + + + DEBUG_printf(("4ppd_update_filters(ppd=%p, cg=%p)", ppd, pg)); + + /* + * See if we have any cupsFilter2 lines... + */ + + if ((attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) == NULL) + { + DEBUG_puts("5ppd_update_filters: No cupsFilter2 keywords present."); + return (1); + } + + /* + * Yes, free the cupsFilter-defined filters and re-build... + */ + + ppd_free_filters(ppd); + + do + { + /* + * Parse the cupsFilter2 string: + * + * src/type dst/type cost program + * src/type dst/type cost maxsize(n) program + */ + + DEBUG_printf(("5ppd_update_filters: cupsFilter2=\"%s\"", attr->value)); + + if (sscanf(attr->value, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", + srcsuper, srctype, dstsuper, dsttype, &cost, program) != 6) + { + DEBUG_puts("5ppd_update_filters: Bad cupsFilter2 line."); + pg->ppd_status = PPD_BAD_VALUE; + + return (0); + } + + DEBUG_printf(("5ppd_update_filters: srcsuper=\"%s\", srctype=\"%s\", " + "dstsuper=\"%s\", dsttype=\"%s\", cost=%d, program=\"%s\"", + srcsuper, srctype, dstsuper, dsttype, cost, program)); + + if (!strncmp(program, "maxsize(", 8) && + (ptr = strchr(program + 8, ')')) != NULL) + { + DEBUG_puts("5ppd_update_filters: Found maxsize(nnn)."); + + ptr ++; + while (_cups_isspace(*ptr)) + ptr ++; + + _cups_strcpy(program, ptr); + DEBUG_printf(("5ppd_update_filters: New program=\"%s\"", program)); + } + + /* + * Convert to cupsFilter format: + * + * src/type cost program + */ + + snprintf(buffer, sizeof(buffer), "%s/%s %d %s", srcsuper, srctype, cost, + program); + DEBUG_printf(("5ppd_update_filters: Adding \"%s\".", buffer)); + + /* + * Add a cupsFilter-compatible string to the filters array. + */ + + if (ppd->num_filters == 0) + filter = malloc(sizeof(char *)); + else + filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1)); + + if (filter == NULL) + { + DEBUG_puts("5ppd_update_filters: Out of memory."); + pg->ppd_status = PPD_ALLOC_ERROR; + + return (0); + } + + ppd->filters = filter; + filter += ppd->num_filters; + ppd->num_filters ++; + + *filter = _cupsStrAlloc(buffer); + } + while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL); + + DEBUG_puts("5ppd_update_filters: Completed OK."); + return (1); +}