]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/ppd.c
Changelog.
[thirdparty/cups.git] / cups / ppd.c
index abf6738dbece4fe32f1ff8ea910d5b5f3285749a..86220112716dfc580f0e81749c361e38400833c2 100644 (file)
@@ -1,19 +1,13 @@
 /*
  * PPD file routines for CUPS.
  *
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2019 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.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  *
  * 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.
  */
 
 /*
 
 #include "cups-private.h"
 #include "ppd-private.h"
+#include "debug-internal.h"
 
 
 /*
  * Definitions...
  */
 
-#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 */
@@ -88,9 +81,9 @@ static ppd_group_t    *ppd_get_group(ppd_file_t *ppd, const char *name,
                                       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)
+#if defined(HAVE_PTHREAD_H) || defined(_WIN32)
 static void            ppd_globals_free(_ppd_globals_t *g);
-#endif /* HAVE_PTHREAD_H || WIN32 */
+#endif /* HAVE_PTHREAD_H || _WIN32 */
 #ifdef HAVE_PTHREAD_H
 static void            ppd_globals_init(void);
 #endif /* HAVE_PTHREAD_H */
@@ -111,7 +104,6 @@ void
 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 */
   ppd_attr_t           **attr;         /* Current attribute */
@@ -130,28 +122,12 @@ ppdClose(ppd_file_t *ppd)         /* I - PPD file record */
   * 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->jcl_begin);
+  free(ppd->jcl_end);
+  free(ppd->jcl_ps);
 
  /*
   * Free any UI groups, subgroups, and options...
@@ -162,7 +138,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
     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);
@@ -173,14 +149,14 @@ ppdClose(ppd_file_t *ppd)         /* I - PPD file record */
   */
 
   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...
@@ -195,9 +171,9 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
   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);
   }
 
  /*
@@ -205,7 +181,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
   */
 
   if (ppd->num_profiles > 0)
-    ppd_free(ppd->profiles);
+    free(ppd->profiles);
 
  /*
   * Free any attributes...
@@ -215,11 +191,11 @@ ppdClose(ppd_file_t *ppd)         /* I - PPD file record */
   {
     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);
@@ -241,7 +217,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
         case PPD_CUSTOM_PASSCODE :
         case PPD_CUSTOM_PASSWORD :
         case PPD_CUSTOM_STRING :
-            _cupsStrFree(cparam->current.custom_string);
+            free(cparam->current.custom_string);
            break;
 
        default :
@@ -289,7 +265,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
   * Free the whole record...
   */
 
-  ppd_free(ppd);
+  free(ppd);
 }
 
 
@@ -327,7 +303,9 @@ ppdErrorString(ppd_status_t status) /* I - PPD status */
                  _("Bad custom parameter"),
                  _("Missing option keyword"),
                  _("Bad value string"),
-                 _("Missing CloseGroup")
+                 _("Missing CloseGroup"),
+                 _("Bad CloseUI/JCLCloseUI"),
+                 _("Missing CloseUI/JCLCloseUI")
                };
 
 
@@ -435,7 +413,6 @@ _ppdOpen(
     _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 */
@@ -453,7 +430,6 @@ _ppdOpen(
                                        /* 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 */
@@ -627,16 +603,14 @@ _ppdOpen(
     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(("2_ppdOpen: keyword=%s, string=%p", keyword, string));
 
-  _cupsStrFree(string);
-
  /*
   * Allocate memory for the PPD file record...
   */
@@ -645,18 +619,20 @@ _ppdOpen(
   {
     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...
@@ -843,7 +819,7 @@ _ppdOpen(
       * 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"))
@@ -864,10 +840,10 @@ _ppdOpen(
 
 
         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;
@@ -877,17 +853,17 @@ _ppdOpen(
       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"))
@@ -955,10 +931,10 @@ _ppdOpen(
       ppd->num_filters ++;
 
      /*
-      * Retain a copy of the filter string...
+      * Make a copy of the filter string...
       */
 
-      *filter = _cupsStrRetain(string);
+      *filter = strdup(string);
     }
     else if (!strcmp(keyword, "Throughput"))
       ppd->throughput = atoi(string);
@@ -981,7 +957,7 @@ _ppdOpen(
       }
 
       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))
@@ -1146,7 +1122,7 @@ _ppdOpen(
        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);
@@ -1195,59 +1171,23 @@ _ppdOpen(
       else if (!strcmp(string, "Plus90"))
         ppd->landscape = 90;
     }
-    else if (!strcmp(keyword, "Emulators") && string)
-    {
-      for (count = 1, sptr = string; sptr != NULL;)
-        if ((sptr = strchr(sptr, ' ')) != NULL)
-       {
-         count ++;
-         while (*sptr == ' ')
-           sptr ++;
-       }
-
-      ppd->num_emulations = count;
-      if ((ppd->emulations = calloc((size_t)count, sizeof(ppd_emul_t))) == NULL)
-      {
-        pg->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))
+    else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0)
     {
-      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"))
     {
@@ -1402,7 +1342,7 @@ _ppdOpen(
 
       option->section = PPD_ORDER_ANY;
 
-      _cupsStrFree(string);
+      free(string);
       string = NULL;
 
      /*
@@ -1430,7 +1370,7 @@ _ppdOpen(
        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"))
@@ -1509,7 +1449,7 @@ _ppdOpen(
       option->section = PPD_ORDER_JCL;
       group = NULL;
 
-      _cupsStrFree(string);
+      free(string);
       string = NULL;
 
      /*
@@ -1533,14 +1473,35 @@ _ppdOpen(
        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;
+      }
+
       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;
+      }
+
+      option = NULL;
+
+      free(string);
       string = NULL;
     }
     else if (!strcmp(keyword, "OpenGroup"))
@@ -1587,14 +1548,14 @@ _ppdOpen(
       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"))
@@ -1652,7 +1613,7 @@ _ppdOpen(
        option->order   = order;
       }
 
-      _cupsStrFree(string);
+      free(string);
       string = NULL;
     }
     else if (!strncmp(keyword, "Default", 7))
@@ -1895,7 +1856,7 @@ _ppdOpen(
       * Don't add this one as an attribute...
       */
 
-      _cupsStrFree(string);
+      free(string);
       string = NULL;
     }
     else if (!strcmp(keyword, "PaperDimension"))
@@ -1917,7 +1878,7 @@ _ppdOpen(
       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"))
@@ -1941,7 +1902,7 @@ _ppdOpen(
       size->right  = (float)_cupsStrScand(sptr, &sptr, loc);
       size->top    = (float)_cupsStrScand(sptr, NULL, loc);
 
-      _cupsStrFree(string);
+      free(string);
       string = NULL;
     }
     else if (option != NULL &&
@@ -1997,7 +1958,17 @@ _ppdOpen(
         (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;
   }
 
  /*
@@ -2010,7 +1981,7 @@ _ppdOpen(
     goto error;
   }
 
-  ppd_free(line.buffer);
+  free(line.buffer);
 
  /*
   * Reset language preferences...
@@ -2092,8 +2063,8 @@ _ppdOpen(
 
   error:
 
-  _cupsStrFree(string);
-  ppd_free(line.buffer);
+  free(string);
+  free(line.buffer);
 
   ppdClose(ppd);
 
@@ -2531,9 +2502,9 @@ ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */
   if (ppd->num_filters > 0)
   {
     for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++)
-      _cupsStrFree(*filter);
+      free(*filter);
 
-    ppd_free(ppd->filters);
+    free(ppd->filters);
 
     ppd->num_filters = 0;
     ppd->filters     = NULL;
@@ -2560,7 +2531,7 @@ ppd_free_group(ppd_group_t *group)        /* I - Group to free */
         i --, option ++)
       ppd_free_option(option);
 
-    ppd_free(group->options);
+    free(group->options);
   }
 
   if (group->num_subgroups > 0)
@@ -2570,7 +2541,7 @@ ppd_free_group(ppd_group_t *group)        /* I - Group to free */
         i --, subgroup ++)
       ppd_free_group(subgroup);
 
-    ppd_free(group->subgroups);
+    free(group->subgroups);
   }
 }
 
@@ -2592,10 +2563,10 @@ ppd_free_option(ppd_option_t *option)   /* I - Option to free */
          i > 0;
          i --, choice ++)
     {
-      _cupsStrFree(choice->code);
+      free(choice->code);
     }
 
-    ppd_free(option->choices);
+    free(option->choices);
   }
 }
 
@@ -2798,13 +2769,13 @@ ppd_globals_alloc(void)
  * 'ppd_globals_free()' - Free global data.
  */
 
-#if defined(HAVE_PTHREAD_H) || defined(WIN32)
+#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 */
+#endif /* HAVE_PTHREAD_H || _WIN32 */
 
 
 #ifdef HAVE_PTHREAD_H
@@ -3332,7 +3303,7 @@ ppd_read(cups_file_t    *fp,              /* I - File to read from */
        lineptr ++;
       }
 
-      *string = _cupsStrAlloc(lineptr);
+      *string = strdup(lineptr);
 
       mask |= PPD_STRING;
     }
@@ -3454,7 +3425,7 @@ ppd_update_filters(ppd_file_t     *ppd,   /* I - PPD file */
     filter           += ppd->num_filters;
     ppd->num_filters ++;
 
-    *filter = _cupsStrAlloc(buffer);
+    *filter = strdup(buffer);
   }
   while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);