/*
- * "$Id: ppd.c 7906 2008-09-03 20:19:43Z mike $"
+ * PPD file routines for CUPS.
*
- * PPD file routines for CUPS.
+ * Copyright © 2007-2019 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
- * Copyright 2007-2011 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*
- * 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.
- *
- * 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_coptions() - Compare two custom options.
- * 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.
+ * PostScript is a trademark of Adobe Systems, Inc.
*/
/*
#include "cups-private.h"
#include "ppd-private.h"
+#include "debug-internal.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 */
#define PPD_OPTION 2 /* Line contained an option name */
#define PPD_TEXT 4 /* Line contained human-readable text */
} _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...
*/
ppd_coption_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);
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);
/*
ppdClose(ppd_file_t *ppd) /* I - PPD file record */
{
int i; /* Looping var */
- 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 */
* Free all strings at the top level...
*/
- _cupsStrFree(ppd->lang_encoding);
- _cupsStrFree(ppd->nickname);
- if (ppd->patches)
- free(ppd->patches);
- _cupsStrFree(ppd->jcl_begin);
- _cupsStrFree(ppd->jcl_end);
- _cupsStrFree(ppd->jcl_ps);
-
- /*
- * Free any emulations...
- */
-
- if (ppd->num_emulations > 0)
- {
- for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++)
- {
- _cupsStrFree(emul->start);
- _cupsStrFree(emul->stop);
- }
-
- ppd_free(ppd->emulations);
- }
+ free(ppd->lang_encoding);
+ free(ppd->nickname);
+ free(ppd->patches);
+ free(ppd->emulations);
+ free(ppd->jcl_begin);
+ free(ppd->jcl_end);
+ free(ppd->jcl_ps);
/*
* Free any UI groups, subgroups, and options...
for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
ppd_free_group(group);
- ppd_free(ppd->groups);
+ free(ppd->groups);
}
cupsArrayDelete(ppd->options);
*/
if (ppd->num_sizes > 0)
- ppd_free(ppd->sizes);
+ free(ppd->sizes);
/*
* Free any constraints...
*/
if (ppd->num_consts > 0)
- ppd_free(ppd->consts);
+ free(ppd->consts);
/*
* 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...
if (ppd->num_fonts > 0)
{
for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++)
- _cupsStrFree(*font);
+ free(*font);
- ppd_free(ppd->fonts);
+ free(ppd->fonts);
}
/*
*/
if (ppd->num_profiles > 0)
- ppd_free(ppd->profiles);
+ free(ppd->profiles);
/*
* Free any attributes...
{
for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++)
{
- _cupsStrFree((*attr)->value);
- ppd_free(*attr);
+ free((*attr)->value);
+ free(*attr);
}
- ppd_free(ppd->attrs);
+ free(ppd->attrs);
}
cupsArrayDelete(ppd->sorted_attrs);
case PPD_CUSTOM_PASSCODE :
case PPD_CUSTOM_PASSWORD :
case PPD_CUSTOM_STRING :
- _cupsStrFree(cparam->current.custom_string);
+ free(cparam->current.custom_string);
break;
default :
* Free the whole record...
*/
- ppd_free(ppd);
+ free(ppd);
}
/*
- * 'ppdErrorString()' - Returns the text assocated with a status.
+ * 'ppdErrorString()' - Returns the text associated with a status.
*
- * @since CUPS 1.1.19/Mac OS X 10.3@
+ * @since CUPS 1.1.19/macOS 10.3@
*/
const char * /* O - Status string */
_("Bad custom parameter"),
_("Missing option keyword"),
_("Bad value string"),
- _("Missing CloseGroup")
+ _("Missing CloseGroup"),
+ _("Bad CloseUI/JCLCloseUI"),
+ _("Missing CloseUI/JCLCloseUI")
};
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"))
+ else if (!_cups_strcasecmp(name, "JIS83-RKSJ"))
return (CUPS_JIS_X0213);
- else if (!strcasecmp(name, "MacStandard"))
+ 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);
/*
- * 'ppdLastError()' - Return the status from the last ppdOpen*().
- *
- * @since CUPS 1.1.19/Mac OS X 10.3@
+ * '_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/Mac OS X 10.5@
+ * @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 */
_ppd_line_t line; /* Line buffer */
ppd_file_t *ppd; /* PPD file record */
ppd_group_t *group, /* Current group */
/* Human-readable text from file */
*string, /* Code/text from file */
*sptr, /* Pointer into string */
- *nameptr, /* Pointer into name */
*temp, /* Temporary string pointer */
**tempfonts; /* Temporary fonts pointer */
float order; /* Order dependency number */
char **filter; /* Pointer to filter */
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
"PageSize"
#endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
};
+ static const char * const color_keywords[] = /* Keywords associated with color profiles */
+ {
+ ".cupsICCProfile",
+ ".ColorModel",
+ };
- DEBUG_printf(("ppdOpen2(fp=%p)", fp));
+ 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...
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);
+
+ /*
+ * <rdar://problem/22130168>
+ * <rdar://problem/27245567>
+ *
+ * Need to use a different base language for some locales...
+ */
+
+ if (!strcmp(lang->language, "zh_HK"))
+ { /* Traditional Chinese + variants */
+ strlcpy(ll_CC, "zh_TW.", sizeof(ll_CC));
+ strlcpy(ll, "zh_", sizeof(ll));
+ }
+ else if (!strncmp(lang->language, "zh", 2))
+ strlcpy(ll, "zh_", sizeof(ll)); /* Any Chinese variant */
+ else if (!strncmp(lang->language, "jp", 2))
+ { /* Any Japanese variant */
+ strlcpy(ll_CC, "ja", sizeof(ll_CC));
+ strlcpy(ll, "jp", sizeof(ll));
+ }
+ else if (!strncmp(lang->language, "nb", 2) || !strncmp(lang->language, "no", 2))
+ { /* Any Norwegian variant */
+ strlcpy(ll_CC, "nb", sizeof(ll_CC));
+ strlcpy(ll, "no", 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"'...
*/
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(("2ppdOpen2: mask=%x, keyword=\"%s\"...", mask, keyword));
+ DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\"...", mask, keyword));
if (mask == 0 ||
strcmp(keyword, "PPD-Adobe") ||
* 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);
+ free(string);
+ free(line.buffer);
return (NULL);
}
- DEBUG_printf(("2ppdOpen2: keyword=%s, string=%p", keyword, string));
-
- _cupsStrFree(string);
+ DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string));
/*
* Allocate memory for the PPD file record...
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);
+ free(string);
+ free(line.buffer);
return (NULL);
}
+ free(string);
+ string = NULL;
+
ppd->language_level = 2;
ppd->color_device = 0;
ppd->colorspace = PPD_CS_N;
ppd->landscape = -90;
- ppd->coptions = cupsArrayNew((cups_array_func_t)ppd_compare_coptions,
- NULL);
+ ppd->coptions = cupsArrayNew((cups_array_func_t)ppd_compare_coptions, NULL);
/*
* Read lines from the PPD file and add them to the file record...
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)
{
- DEBUG_printf(("2ppdOpen2: mask=%x, keyword=\"%s\", name=\"%s\", "
+ 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 (strncmp(keyword, "Default", 7) && !string &&
- cg->ppd_conform != PPD_CONFORM_RELAXED)
+ pg->ppd_conform != PPD_CONFORM_RELAXED)
{
/*
* Need a string value!
*/
- cg->ppd_status = PPD_MISSING_VALUE;
+ pg->ppd_status = PPD_MISSING_VALUE;
goto error;
}
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));
+ free(string);
+ string = NULL;
+ 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));
+ free(string);
+ string = NULL;
+ continue;
+ }
+ }
+ }
+
if (option == NULL &&
(mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
(PPD_KEYWORD | PPD_OPTION | PPD_STRING))
ui_keyword = 1;
- DEBUG_printf(("2ppdOpen2: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!",
+ 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(("2ppdOpen2: Adding to group %s...", group->text));
+ DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
option = ppd_get_option(group, keyword);
group = NULL;
}
if (option == NULL)
{
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
!strcmp(ppd->attrs[j]->name + 7, keyword) &&
ppd->attrs[j]->value)
{
- DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
+ 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));
* Say all PPD files are UTF-8, since we convert to UTF-8...
*/
- ppd->lang_encoding = _cupsStrAlloc("UTF-8");
+ ppd->lang_encoding = strdup("UTF-8");
encoding = _ppdGetEncoding(string);
}
else if (!strcmp(keyword, "LanguageVersion"))
cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding);
- ppd->nickname = _cupsStrAlloc((char *)utf8);
+ ppd->nickname = strdup((char *)utf8);
}
else
- ppd->nickname = _cupsStrAlloc(string);
+ ppd->nickname = strdup(string);
}
else if (!strcmp(keyword, "Product"))
ppd->product = string;
ppd->ttrasterizer = string;
else if (!strcmp(keyword, "JCLBegin"))
{
- ppd->jcl_begin = _cupsStrAlloc(string);
+ ppd->jcl_begin = strdup(string);
ppd_decode(ppd->jcl_begin); /* Decode quoted string */
}
else if (!strcmp(keyword, "JCLEnd"))
{
- ppd->jcl_end = _cupsStrAlloc(string);
+ ppd->jcl_end = strdup(string);
ppd_decode(ppd->jcl_end); /* Decode quoted string */
}
else if (!strcmp(keyword, "JCLToPSInterpreter"))
{
- ppd->jcl_ps = _cupsStrAlloc(string);
+ ppd->jcl_ps = strdup(string);
ppd_decode(ppd->jcl_ps); /* Decode quoted string */
}
else if (!strcmp(keyword, "AccurateScreensSupport"))
- ppd->accurate_screens = !strcmp(string, "True");
+ ppd->accurate_screens = !strcasecmp(string, "True");
else if (!strcmp(keyword, "ColorDevice"))
- ppd->color_device = !strcmp(string, "True");
+ ppd->color_device = !strcasecmp(string, "True");
else if (!strcmp(keyword, "ContoneOnly"))
- ppd->contone_only = !strcmp(string, "True");
+ ppd->contone_only = !strcasecmp(string, "True");
else if (!strcmp(keyword, "cupsFlipDuplex"))
- ppd->flip_duplex = !strcmp(string, "True");
+ ppd->flip_duplex = !strcasecmp(string, "True");
else if (!strcmp(keyword, "cupsManualCopies"))
- ppd->manual_copies = !strcmp(string, "True");
+ ppd->manual_copies = !strcasecmp(string, "True");
else if (!strcmp(keyword, "cupsModelNumber"))
ppd->model_number = atoi(string);
else if (!strcmp(keyword, "cupsColorProfile"))
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;
}
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;
}
ppd->num_filters ++;
/*
- * Copy filter string and prevent it from being freed below...
+ * Make a copy of the filter string...
*/
- *filter = string;
- string = NULL;
+ *filter = strdup(string);
}
else if (!strcmp(keyword, "Throughput"))
ppd->throughput = atoi(string);
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->fonts[ppd->num_fonts] = strdup(name);
ppd->num_fonts ++;
}
else if (!strncmp(keyword, "ParamCustom", 11))
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;
}
+ if (cparam->type != PPD_CUSTOM_UNKNOWN)
+ {
+ pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
+
+ goto error;
+ }
+
/*
* Get the parameter data...
*/
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;
}
}
else
{
- cg->ppd_status = PPD_BAD_CUSTOM_PARAM;
+ pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
goto error;
}
{
ppd_option_t *custom_option; /* Custom option */
- DEBUG_puts("2ppdOpen2: Processing Custom option...");
+ DEBUG_puts("2_ppdOpen: Processing Custom option...");
/*
* Get the option and custom option...
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);
if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
{
- DEBUG_puts("1ppdOpen2: 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;
}
strlcpy(choice->text, text[0] ? text : _("Custom"),
sizeof(choice->text));
- choice->code = _cupsStrAlloc(string);
+ choice->code = strdup(string);
if (custom_option->section == PPD_ORDER_JCL)
ppd_decode(choice->code);
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 ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
{
- DEBUG_puts("1ppdOpen2: 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;
}
else if (!strcmp(string, "Plus90"))
ppd->landscape = 90;
}
- else if (!strcmp(keyword, "Emulators") && string)
+ else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0)
{
- for (count = 1, sptr = string; sptr != NULL;)
- if ((sptr = strchr(sptr, ' ')) != NULL)
- {
- count ++;
- while (*sptr == ' ')
- sptr ++;
- }
-
- ppd->num_emulations = count;
- if ((ppd->emulations = calloc(count, sizeof(ppd_emul_t))) == NULL)
- {
- cg->ppd_status = PPD_ALLOC_ERROR;
-
- goto error;
- }
-
- for (i = 0, sptr = string; i < count; i ++)
- {
- for (nameptr = ppd->emulations[i].name;
- *sptr != '\0' && *sptr != ' ';
- sptr ++)
- if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1))
- *nameptr++ = *sptr;
-
- *nameptr = '\0';
-
- while (*sptr == ' ')
- sptr ++;
- }
- }
- else if (!strncmp(keyword, "StartEmulator_", 14))
- {
- ppd_decode(string);
+ /*
+ * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword
+ * to configure themselves
+ *
+ * The Emulators keyword was loaded but never used by anything in CUPS,
+ * and has no valid purpose in CUPS. The old code was removed due to a
+ * memory leak (Issue #5475), so the following (new) code supports a single
+ * name for the Emulators keyword, allowing these drivers to work until we
+ * remove PPD and driver support entirely in a future version of CUPS.
+ */
- for (i = 0; i < ppd->num_emulations; i ++)
- if (!strcmp(keyword + 14, ppd->emulations[i].name))
- {
- ppd->emulations[i].start = string;
- string = NULL;
- }
- }
- else if (!strncmp(keyword, "StopEmulator_", 13))
- {
- ppd_decode(string);
+ ppd->num_emulations = 1;
+ ppd->emulations = calloc(1, sizeof(ppd_emul_t));
- for (i = 0; i < ppd->num_emulations; i ++)
- if (!strcmp(keyword + 13, ppd->emulations[i].name))
- {
- ppd->emulations[i].stop = string;
- string = NULL;
- }
+ strlcpy(ppd->emulations[0].name, string, sizeof(ppd->emulations[0].name));
}
else if (!strcmp(keyword, "JobPatchFile"))
{
* Found "*JobPatchFile: int: string"...
*/
- cg->ppd_status = PPD_BAD_VALUE;
+ pg->ppd_status = PPD_BAD_VALUE;
goto error;
}
}
- if (!name[0] && cg->ppd_conform == PPD_CONFORM_STRICT)
+ if (!name[0] && pg->ppd_conform == PPD_CONFORM_STRICT)
{
/*
* Found "*JobPatchFile: string"...
*/
- cg->ppd_status = PPD_MISSING_OPTION_KEYWORD;
+ pg->ppd_status = PPD_MISSING_OPTION_KEYWORD;
goto error;
}
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"))
* 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;
}
* Add an option record to the current sub-group, group, or file...
*/
- DEBUG_printf(("2ppdOpen2: name=\"%s\" (%d)", name, (int)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 && _cups_isspace(name[i]); i --)
name[i] = '\0'; /* Eliminate trailing spaces */
- DEBUG_printf(("2ppdOpen2: OpenUI of %s in group %s...", 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(("2ppdOpen2: Adding to group %s...", group->text));
+ DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
option = ppd_get_option(group, name);
group = NULL;
}
if (option == NULL)
{
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
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;
}
!strcmp(ppd->attrs[j]->name + 7, name) &&
ppd->attrs[j]->value)
{
- DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
+ 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));
option->section = PPD_ORDER_ANY;
- _cupsStrFree(string);
+ free(string);
string = NULL;
/*
* 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 ((choice = ppdFindChoice(option, "Custom")) == NULL)
if ((choice = ppd_add_choice(option, "Custom")) == NULL)
{
- DEBUG_puts("1ppdOpen2: 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;
}
strlcpy(choice->text,
custom_attr->text[0] ? custom_attr->text : _("Custom"),
sizeof(choice->text));
- choice->code = _cupsStrRetain(custom_attr->value);
+ choice->code = strdup(custom_attr->value);
}
}
else if (!strcmp(keyword, "JCLOpenUI"))
* 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;
}
* 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;
if (option == NULL)
{
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
option->ui = PPD_UI_PICKONE;
else
{
- cg->ppd_status = PPD_BAD_OPEN_UI;
+ pg->ppd_status = PPD_BAD_OPEN_UI;
goto error;
}
!strcmp(ppd->attrs[j]->name + 7, name) &&
ppd->attrs[j]->value)
{
- DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
+ 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));
option->section = PPD_ORDER_JCL;
group = NULL;
- _cupsStrFree(string);
+ free(string);
string = NULL;
/*
{
if ((choice = ppd_add_choice(option, "Custom")) == NULL)
{
- DEBUG_puts("1ppdOpen2: 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;
}
strlcpy(choice->text,
custom_attr->text[0] ? custom_attr->text : _("Custom"),
sizeof(choice->text));
- choice->code = _cupsStrRetain(custom_attr->value);
+ choice->code = strdup(custom_attr->value);
}
}
- else if (!strcmp(keyword, "CloseUI") || !strcmp(keyword, "JCLCloseUI"))
+ else if (!strcmp(keyword, "CloseUI"))
{
+ if ((!option || option->section == PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
+ {
+ pg->ppd_status = PPD_BAD_CLOSE_UI;
+
+ goto error;
+ }
+
+ if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
+ {
+ /*
+ * "*DefaultOption: Custom..." may set the default to a custom value
+ * or (for a very small number of incompatible PPD files) select a
+ * standard choice for the option, which CUPS renames to "_Custom..."
+ * to avoid compatibility issues. See which this is...
+ */
+
+ char tchoice[PPD_MAX_NAME]; /* Temporary choice name */
+
+ snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
+
+ if (ppdFindChoice(option, tchoice))
+ {
+ strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
+
+ DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
+ }
+ }
+
option = NULL;
- _cupsStrFree(string);
+ free(string);
+ string = NULL;
+ }
+ else if (!strcmp(keyword, "JCLCloseUI"))
+ {
+ if ((!option || option->section != PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
+ {
+ pg->ppd_status = PPD_BAD_CLOSE_UI;
+
+ goto error;
+ }
+
+ if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
+ {
+ /*
+ * "*DefaultOption: Custom..." may set the default to a custom value
+ * or (for a very small number of incompatible PPD files) select a
+ * standard choice for the option, which CUPS renames to "_Custom..."
+ * to avoid compatibility issues. See which this is...
+ */
+
+ char tchoice[PPD_MAX_NAME]; /* Temporary choice name */
+
+ snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
+
+ if (ppdFindChoice(option, tchoice))
+ {
+ strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
+
+ DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
+ }
+ }
+
+ option = NULL;
+
+ free(string);
string = NULL;
}
else if (!strcmp(keyword, "OpenGroup"))
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;
}
* 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;
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (!strcmp(keyword, "CloseGroup"))
{
group = NULL;
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (!strcmp(keyword, "OrderDependency"))
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;
}
option->order = order;
}
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (!strncmp(keyword, "Default", 7))
* Set the default as part of the current option...
*/
- DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword, string));
-
- strlcpy(option->defchoice, string, sizeof(option->defchoice));
+ strlcpy(option->defchoice, string, sizeof(option->defchoice));
- DEBUG_printf(("2ppdOpen2: %s is now %s...", keyword, option->defchoice));
+ DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, option->defchoice));
}
else
{
ppd_option_t *toption; /* Temporary option */
-
if ((toption = ppdFindOption(ppd, keyword + 7)) != NULL)
{
- DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword, string));
- strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
+ if (!_cups_strcasecmp(string, "custom") || !_cups_strncasecmp(string, "custom.", 7))
+ {
+ /*
+ * "*DefaultOption: Custom..." may set the default to a custom value
+ * or (for a very small number of incompatible PPD files) select a
+ * standard choice for the option, which CUPS renames to "_Custom..."
+ * to avoid compatibility issues. See which this is...
+ */
+
+ snprintf(toption->defchoice, sizeof(toption->defchoice), "_%s", string);
+ if (!ppdFindChoice(toption, toption->defchoice))
+ strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
+ }
+ else
+ {
+ strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
+ }
+
+ DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, toption->defchoice));
}
}
}
{
if (!string)
{
- cg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
+ 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;
}
constraint->choice1, constraint->option2,
constraint->choice2))
{
- case 0 : /* Error */
- case 1 : /* Error */
- cg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
+ default : /* Error */
+ pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
goto error;
case 2 : /* Two options... */
* 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;
}
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;
}
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;
}
{
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;
* Don't add this one as an attribute...
*/
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (!strcmp(keyword, "PaperDimension"))
{
+ if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
+ {
+ char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
+ snprintf(cname, sizeof(cname), "_%s", name);
+ strlcpy(name, cname, sizeof(name));
+ }
+
if ((size = ppdPageSize(ppd, name)) == NULL)
size = ppd_add_size(ppd, name);
* Unable to add or find size!
*/
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
size->width = (float)_cupsStrScand(string, &sptr, loc);
size->length = (float)_cupsStrScand(sptr, NULL, loc);
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (!strcmp(keyword, "ImageableArea"))
{
+ if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
+ {
+ char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
+ snprintf(cname, sizeof(cname), "_%s", name);
+ strlcpy(name, cname, sizeof(name));
+ }
+
if ((size = ppdPageSize(ppd, name)) == NULL)
size = ppd_add_size(ppd, name);
* Unable to add or find size!
*/
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
size->right = (float)_cupsStrScand(sptr, &sptr, loc);
size->top = (float)_cupsStrScand(sptr, NULL, loc);
- _cupsStrFree(string);
+ free(string);
string = NULL;
}
else if (option != NULL &&
(PPD_KEYWORD | PPD_OPTION | PPD_STRING) &&
!strcmp(keyword, option->keyword))
{
- DEBUG_printf(("2ppdOpen2: group=%p, subgroup=%p", group, subgroup));
+ DEBUG_printf(("2_ppdOpen: group=%p, subgroup=%p", group, subgroup));
+
+ if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
+ {
+ char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
+ snprintf(cname, sizeof(cname), "_%s", name);
+ strlcpy(name, cname, sizeof(name));
+ }
if (!strcmp(keyword, "PageSize"))
{
if ((choice = ppd_add_choice(option, name)) == NULL)
{
- cg->ppd_status = PPD_ALLOC_ERROR;
+ pg->ppd_status = PPD_ALLOC_ERROR;
goto error;
}
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));
(mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING))
ppd_add_attr(ppd, keyword, name, text, string);
else
- _cupsStrFree(string);
+ free(string);
+ }
+
+ /*
+ * Check for a missing CloseUI/JCLCloseUI...
+ */
+
+ if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
+ {
+ pg->ppd_status = PPD_MISSING_CLOSE_UI;
+ goto error;
}
/*
* Check for a missing CloseGroup...
*/
- if (group && cg->ppd_conform == PPD_CONFORM_STRICT)
+ if (group && pg->ppd_conform == PPD_CONFORM_STRICT)
{
- cg->ppd_status = PPD_MISSING_CLOSE_GROUP;
+ pg->ppd_status = PPD_MISSING_CLOSE_GROUP;
goto error;
}
- ppd_free(line.buffer);
+ free(line.buffer);
/*
* Reset language preferences...
#ifdef DEBUG
if (!cupsFileEOF(fp))
- DEBUG_printf(("1ppdOpen2: Premature EOF at %lu...\n",
+ 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!
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...
error:
- _cupsStrFree(string);
- ppd_free(line.buffer);
+ free(string);
+ free(line.buffer);
ppdClose(ppd);
}
+/*
+ * '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.
*/
{
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 */
* Set the line number to 0...
*/
- cg->ppd_line = 0;
+ pg->ppd_line = 0;
/*
* Range check input...
if (fd < 0)
{
- cg->ppd_status = PPD_NULL_FILE;
+ pg->ppd_status = PPD_NULL_FILE;
return (NULL);
}
}
else
{
- cg->ppd_status = PPD_FILE_OPEN_ERROR;
+ pg->ppd_status = PPD_FILE_OPEN_ERROR;
ppd = NULL;
}
/*
- * '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 */
* Set the line number to 0...
*/
- cg->ppd_line = 0;
+ pg->ppd_line = 0;
/*
* Range check input...
if (filename == NULL)
{
- cg->ppd_status = PPD_NULL_FILE;
+ pg->ppd_status = PPD_NULL_FILE;
return (NULL);
}
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;
}
}
+/*
+ * '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/Mac OS X 10.4@
+ * @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;
}
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);
* Copy data over...
*/
+ if (!_cups_strcasecmp(spec, "custom") || !_cups_strncasecmp(spec, "custom.", 7))
+ {
+ temp->spec[0] = '_';
+ strlcpy(temp->spec + 1, spec, sizeof(temp->spec) - 1);
+ }
+ else {
+ strlcpy(temp->spec, spec, sizeof(temp->spec));
+ }
+
strlcpy(temp->name, name, sizeof(temp->name));
- strlcpy(temp->spec, spec, sizeof(temp->spec));
strlcpy(temp->text, text, sizeof(temp->text));
temp->value = (char *)value;
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);
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);
ppd_compare_attrs(ppd_attr_t *a, /* I - First attribute */
ppd_attr_t *b) /* I - Second attribute */
{
- return (strcasecmp(a->name, b->name));
+ return (_cups_strcasecmp(a->name, b->name));
}
ppd_compare_coptions(ppd_coption_t *a, /* I - First option */
ppd_coption_t *b) /* I - Second option */
{
- return (strcasecmp(a->keyword, b->keyword));
+ return (_cups_strcasecmp(a->keyword, b->keyword));
}
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));
}
while (isxdigit(*inptr & 255))
{
if (_cups_isalpha(*inptr))
- *outptr = (tolower(*inptr) - 'a' + 10) << 4;
+ *outptr = (char)((tolower(*inptr) - 'a' + 10) << 4);
else
- *outptr = (*inptr - '0') << 4;
+ *outptr = (char)((*inptr - '0') << 4);
inptr ++;
break;
if (_cups_isalpha(*inptr))
- *outptr |= tolower(*inptr) - 'a' + 10;
+ *outptr |= (char)(tolower(*inptr) - 'a' + 10);
else
- *outptr |= *inptr - '0';
+ *outptr |= (char)(*inptr - '0');
inptr ++;
outptr ++;
}
+/*
+ * '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 ++)
+ free(*filter);
+
+ free(ppd->filters);
+
+ ppd->num_filters = 0;
+ ppd->filters = NULL;
+ }
+}
+
+
/*
* 'ppd_free_group()' - Free a single UI group.
*/
i --, option ++)
ppd_free_option(option);
- ppd_free(group->options);
+ free(group->options);
}
if (group->num_subgroups > 0)
i --, subgroup ++)
ppd_free_group(subgroup);
- ppd_free(group->subgroups);
+ free(group->subgroups);
}
}
i > 0;
i --, choice ++)
{
- _cupsStrFree(choice->code);
+ free(choice->code);
}
- ppd_free(option->choices);
+ free(option->choices);
}
}
if ((cparam = calloc(1, sizeof(ppd_cparam_t))) == NULL)
return (NULL);
+ cparam->type = PPD_CUSTOM_UNKNOWN;
strlcpy(cparam->name, param, sizeof(cparam->name));
strlcpy(cparam->text, text[0] ? text : param, sizeof(cparam->text));
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 */
DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)",
- ppd, name, text, cg));
+ ppd, name, text, pg));
for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
if (!strcmp(group->name, 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);
}
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);
}
+/*
+ * '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...
*/
for (hash = option->keyword[0], k = option->keyword + 1; *k;)
- hash = 33 * hash + *k++;
+ hash = (int)(33U * (unsigned)hash) + *k++;
return (hash & 511);
}
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 */
*string = NULL;
col = 0;
- startline = cg->ppd_line + 1;
+ startline = pg->ppd_line + 1;
if (!line->buffer)
{
* 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);
}
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);
}
* Line feed or carriage return...
*/
- cg->ppd_line ++;
+ pg->ppd_line ++;
col = 0;
if (ch == '\r')
*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);
}
* Any other character...
*/
- *lineptr++ = ch;
+ *lineptr++ = (char)ch;
col ++;
if (col > (PPD_MAX_LINE - 1))
* 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);
}
break;
else if (ch == '\r' || ch == '\n')
{
- cg->ppd_line ++;
+ pg->ppd_line ++;
col = 0;
if (ch == '\r')
cupsFileGetChar(fp);
}
}
- 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);
}
* 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);
}
* Line feed or carriage return...
*/
- cg->ppd_line ++;
+ pg->ppd_line ++;
col = 0;
if (ch == '\r')
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);
}
* 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);
}
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.
!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);
}
if (*lineptr)
{
- cg->ppd_status = PPD_MISSING_ASTERISK;
+ pg->ppd_status = PPD_MISSING_ASTERISK;
return (0);
}
else if (ignoreblank)
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);
}
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);
}
*optptr = '\0';
- if (_cups_isspace(*lineptr) && 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);
}
*/
lineptr ++;
-
+
textptr = text;
while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':')
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);
}
*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;
}
}
- if (_cups_isspace(*lineptr) && 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);
}
lineptr ++;
}
- *string = _cupsStrAlloc(lineptr);
+ *string = strdup(lineptr);
mask |= PPD_STRING;
}
/*
- * End of "$Id: ppd.c 7906 2008-09-03 20:19:43Z 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 = strdup(buffer);
+ }
+ while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
+
+ DEBUG_puts("5ppd_update_filters: Completed OK.");
+ return (1);
+}