]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/mime.c
Move debug printfs to internal usage only.
[thirdparty/cups.git] / scheduler / mime.c
index fc1f3fac750d72260e2a30db9c19bbe573fc6081..d60d4efb955a3ea4382c40eb0e53cdc3f00cdc08 100644 (file)
@@ -1,59 +1,27 @@
 /*
- * "$Id: mime.c 5495 2006-05-05 17:58:07Z mike $"
+ * MIME database file routines for CUPS.
  *
- *   MIME database file routines for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2014 by Apple Inc.
+ * Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products 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 please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
- *
- * Contents:
- *
- *   mimeDelete()       - Delete (free) a MIME database.
- *   mimeDeleteFilter() - Delete a filter from the MIME database.
- *   mimeDeleteType()   - Delete a type from the MIME database.
- *   mimeFirstFilter()  - Get the first filter in the MIME database.
- *   mimeFirstType()    - Get the first type in the MIME database.
- *   mimeLoad()         - Create a new MIME database from disk.
- *   mimeMerge()        - Merge a MIME database from disk with the current one.
- *   mimeNew()          - Create a new, empty MIME database.
- *   mimeNextFilter()   - Get the next filter in the MIME database.
- *   mimeNextType()     - Get the next type in the MIME database.
- *   mimeNumFilters()   - Get the number of filters in a MIME database.
- *   mimeNumTypes()     - Get the number of types in a MIME database.
- *   add_fcache()       - Add a filter to the filter cache.
- *   compare_fcache()   - Compare two filter cache entries.
- *   delete_fcache()    - Free all memory used by the filter cache.
- *   delete_rules()     - Free all memory for the given rule tree.
- *   load_convs()       - Load a xyz.convs file...
- *   load_types()       - Load a xyz.types file...
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
  */
 
 /*
  * Include necessary headers...
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
+#include <cups/string-private.h>
 #include <cups/dir.h>
-#include <cups/string.h>
-#include "mime.h"
+#include "mime-private.h"
+
+
+/*
+ * Debug macros that used to be private API...
+ */
+
+#define DEBUG_puts(x)
+#define DEBUG_printf(...)
 
 
 /*
@@ -71,15 +39,15 @@ typedef struct _mime_fcache_s               /**** Filter cache structure ****/
  * Local functions...
  */
 
-static const char *add_fcache(cups_array_t *filtercache, const char *name,
-                             const char *filterpath);
-static int     compare_fcache(_mime_fcache_t *a, _mime_fcache_t *b);
-static void    delete_fcache(cups_array_t *filtercache);
-static void    delete_rules(mime_magic_t *rules);
-static void    load_convs(mime_t *mime, const char *filename,
-                          const char *filterpath,
-                          cups_array_t *filtercache);
-static void    load_types(mime_t *mime, const char *filename);
+static const char *mime_add_fcache(cups_array_t *filtercache, const char *name,
+                                  const char *filterpath);
+static int     mime_compare_fcache(_mime_fcache_t *a, _mime_fcache_t *b);
+static void    mime_delete_fcache(cups_array_t *filtercache);
+static void    mime_delete_rules(mime_magic_t *rules);
+static void    mime_load_convs(mime_t *mime, const char *filename,
+                               const char *filterpath,
+                               cups_array_t *filtercache);
+static void    mime_load_types(mime_t *mime, const char *filename);
 
 
 /*
@@ -93,6 +61,8 @@ mimeDelete(mime_t *mime)              /* I - MIME database */
   mime_filter_t        *filter;                /* Current filter */
 
 
+  DEBUG_printf(("mimeDelete(mime=%p)", mime));
+
   if (!mime)
     return;
 
@@ -133,9 +103,23 @@ void
 mimeDeleteFilter(mime_t        *mime,  /* I - MIME database */
                 mime_filter_t *filter) /* I - Filter */
 {
+  DEBUG_printf(("mimeDeleteFilter(mime=%p, filter=%p(%s/%s->%s/%s, cost=%d, "
+                "maxsize=" CUPS_LLFMT "))", mime, filter,
+               filter ? filter->src->super : "???",
+               filter ? filter->src->type : "???",
+               filter ? filter->dst->super : "???",
+               filter ? filter->dst->super : "???",
+               filter ? filter->cost : -1,
+               filter ? CUPS_LLCAST filter->maxsize : CUPS_LLCAST -1));
+
   if (!mime || !filter)
     return;
 
+#ifdef DEBUG
+  if (!cupsArrayFind(mime->filters, filter))
+    DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database.");
+#endif /* DEBUG */
+
   cupsArrayRemove(mime->filters, filter);
   free(filter);
 
@@ -146,6 +130,7 @@ mimeDeleteFilter(mime_t        *mime,       /* I - MIME database */
 
   if (mime->srcs)
   {
+    DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache.");
     cupsArrayDelete(mime->srcs);
     mime->srcs = NULL;
   }
@@ -160,16 +145,48 @@ void
 mimeDeleteType(mime_t      *mime,      /* I - MIME database */
               mime_type_t *mt)         /* I - Type */
 {
+  DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime, mt,
+                mt ? mt->super : "???", mt ? mt->type : "???"));
+
   if (!mime || !mt)
     return;
 
+#ifdef DEBUG
+  if (!cupsArrayFind(mime->types, mt))
+    DEBUG_puts("1mimeDeleteFilter: Type not in MIME database.");
+#endif /* DEBUG */
+
   cupsArrayRemove(mime->types, mt);
 
-  delete_rules(mt->rules);
+  mime_delete_rules(mt->rules);
   free(mt);
 }
 
 
+/*
+ * '_mimeError()' - Show an error message.
+ */
+
+void
+_mimeError(mime_t     *mime,           /* I - MIME database */
+           const char *message,                /* I - Printf-style message string */
+          ...)                         /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Argument pointer */
+  char         buffer[8192];           /* Message buffer */
+
+
+  if (mime->error_cb)
+  {
+    va_start(ap, message);
+    vsnprintf(buffer, sizeof(buffer), message, ap);
+    va_end(ap);
+
+    (*mime->error_cb)(mime->error_ctx, buffer);
+  }
+}
+
+
 /*
  * 'mimeFirstFilter()' - Get the first filter in the MIME database.
  */
@@ -177,10 +194,21 @@ mimeDeleteType(mime_t      *mime, /* I - MIME database */
 mime_filter_t *                                /* O - Filter or NULL */
 mimeFirstFilter(mime_t *mime)          /* I - MIME database */
 {
+  DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("7mimeFirstFilter: Returning NULL.");
     return (NULL);
+  }
   else
-    return ((mime_filter_t *)cupsArrayFirst(mime->filters));
+  {
+    mime_filter_t *first = (mime_filter_t *)cupsArrayFirst(mime->filters);
+                                       /* First filter */
+
+    DEBUG_printf(("7mimeFirstFilter: Returning %p.", first));
+    return (first);
+  }
 }
 
 
@@ -191,104 +219,187 @@ mimeFirstFilter(mime_t *mime)           /* I - MIME database */
 mime_type_t *                          /* O - Type or NULL */
 mimeFirstType(mime_t *mime)            /* I - MIME database */
 {
+  DEBUG_printf(("6mimeFirstType(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("7mimeFirstType: Returning NULL.");
     return (NULL);
+  }
   else
-    return ((mime_type_t *)cupsArrayFirst(mime->types));
+  {
+    mime_type_t *first = (mime_type_t *)cupsArrayFirst(mime->types);
+                                       /* First type */
+
+    DEBUG_printf(("7mimeFirstType: Returning %p.", first));
+    return (first);
+  }
 }
 
 
 /*
  * 'mimeLoad()' - Create a new MIME database from disk.
+ *
+ * This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to
+ * create a MIME database from a single directory.
  */
 
 mime_t *                               /* O - New MIME database */
 mimeLoad(const char *pathname,         /* I - Directory to load */
          const char *filterpath)       /* I - Directory to load */
 {
-  return (mimeMerge(NULL, pathname, filterpath));
+  mime_t *mime;                                /* New MIME database */
+
+  DEBUG_printf(("mimeLoad(pathname=\"%s\", filterpath=\"%s\")", pathname,
+                filterpath));
+
+  mime = mimeLoadFilters(mimeLoadTypes(NULL, pathname), pathname, filterpath);
+  DEBUG_printf(("1mimeLoad: Returning %p.", mime));
+
+  return (mime);
 }
 
 
 /*
- * 'mimeMerge()' - Merge a MIME database from disk with the current one.
+ * 'mimeLoadFilters()' - Load filter definitions from disk.
+ *
+ * This function loads all of the .convs files from the specified directory.
+ * Use @link mimeLoadTypes@ to load all types before you load the filters.
  */
 
-mime_t *                               /* O - Updated MIME database */
-mimeMerge(mime_t     *mime,            /* I - MIME database to add to */
-          const char *pathname,                /* I - Directory to load */
-          const char *filterpath)      /* I - Directory to load */
+mime_t *                               /* O - MIME database */
+mimeLoadFilters(mime_t     *mime,      /* I - MIME database */
+                const char *pathname,  /* I - Directory to load from */
+                const char *filterpath)        /* I - Default filter program directory */
 {
   cups_dir_t   *dir;                   /* Directory */
   cups_dentry_t        *dent;                  /* Directory entry */
-  char         filename[1024];         /* Full filename of types/converts file */
+  char         filename[1024];         /* Full filename of .convs file */
   cups_array_t *filtercache;           /* Filter cache */
 
 
+  DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")",
+               mime, pathname, filterpath));
+
  /*
-  * First open the directory specified by pathname...  Return NULL if nothing
-  * was read or if the pathname is NULL...
+  * Range check input...
   */
 
-  if (!pathname)
-    return (NULL);
-
-  if ((dir = cupsDirOpen(pathname)) == NULL)
-    return (NULL);
+  if (!mime || !pathname || !filterpath)
+  {
+    DEBUG_puts("1mimeLoadFilters: Bad arguments.");
+    return (mime);
+  }
 
  /*
-  * If "mime" is NULL, make a new, blank database...
+  * Then open the directory specified by pathname...
   */
 
-  if (!mime)
-    mime = mimeNew();
-  if (!mime)
-    return (NULL);
+  if ((dir = cupsDirOpen(pathname)) == NULL)
+  {
+    DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname,
+                  strerror(errno)));
+    _mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno));
+    return (mime);
+  }
 
  /*
-  * Read all the .types files...
+  * Read all the .convs files...
   */
 
+  filtercache = cupsArrayNew((cups_array_func_t)mime_compare_fcache, NULL);
+
   while ((dent = cupsDirRead(dir)) != NULL)
   {
     if (strlen(dent->filename) > 6 &&
-        !strcmp(dent->filename + strlen(dent->filename) - 6, ".types"))
+        !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs"))
     {
      /*
-      * Load a mime.types file...
+      * Load a mime.convs file...
       */
 
       snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
-      load_types(mime, filename);
+      DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename));
+      mime_load_convs(mime, filename, filterpath, filtercache);
     }
   }
 
-  cupsDirRewind(dir);
+  mime_delete_fcache(filtercache);
+
+  cupsDirClose(dir);
+
+  return (mime);
+}
+
+
+/*
+ * 'mimeLoadTypes()' - Load type definitions from disk.
+ *
+ * This function loads all of the .types files from the specified directory.
+ * Use @link mimeLoadFilters@ to load all filters after you load the types.
+ */
+
+mime_t *                               /* O - MIME database */
+mimeLoadTypes(mime_t     *mime,                /* I - MIME database or @code NULL@ to create a new one */
+              const char *pathname)    /* I - Directory to load from */
+{
+  cups_dir_t   *dir;                   /* Directory */
+  cups_dentry_t        *dent;                  /* Directory entry */
+  char         filename[1024];         /* Full filename of .types file */
+
+
+  DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime, pathname));
 
  /*
-  * Read all the .convs files...
+  * First open the directory specified by pathname...
   */
 
-  filtercache = cupsArrayNew((cups_array_func_t)compare_fcache, NULL);
+  if ((dir = cupsDirOpen(pathname)) == NULL)
+  {
+    DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname,
+                  strerror(errno)));
+    DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime));
+    _mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno));
+    return (mime);
+  }
+
+ /*
+  * If "mime" is NULL, make a new, empty database...
+  */
+
+  if (!mime)
+    mime = mimeNew();
+
+  if (!mime)
+  {
+    cupsDirClose(dir);
+    DEBUG_puts("1mimeLoadTypes: Returning NULL.");
+    return (NULL);
+  }
+
+ /*
+  * Read all the .types files...
+  */
 
   while ((dent = cupsDirRead(dir)) != NULL)
   {
     if (strlen(dent->filename) > 6 &&
-        !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs"))
+        !strcmp(dent->filename + strlen(dent->filename) - 6, ".types"))
     {
      /*
-      * Load a mime.convs file...
+      * Load a mime.types file...
       */
 
       snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
-      load_convs(mime, filename, filterpath, filtercache);
+      DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename));
+      mime_load_types(mime, filename);
     }
   }
 
-  delete_fcache(filtercache);
-
   cupsDirClose(dir);
 
+  DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime));
+
   return (mime);
 }
 
@@ -311,10 +422,21 @@ mimeNew(void)
 mime_filter_t *                                /* O - Filter or NULL */
 mimeNextFilter(mime_t *mime)           /* I - MIME database */
 {
+  DEBUG_printf(("6mimeNextFilter(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("7mimeNextFilter: Returning NULL.");
     return (NULL);
+  }
   else
-    return ((mime_filter_t *)cupsArrayNext(mime->filters));
+  {
+    mime_filter_t *next = (mime_filter_t *)cupsArrayNext(mime->filters);
+                                       /* Next filter */
+
+    DEBUG_printf(("7mimeNextFilter: Returning %p.", next));
+    return (next);
+  }
 }
 
 
@@ -325,10 +447,21 @@ mimeNextFilter(mime_t *mime)              /* I - MIME database */
 mime_type_t *                          /* O - Type or NULL */
 mimeNextType(mime_t *mime)             /* I - MIME database */
 {
+  DEBUG_printf(("6mimeNextType(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("7mimeNextType: Returning NULL.");
     return (NULL);
+  }
   else
-    return ((mime_type_t *)cupsArrayNext(mime->types));
+  {
+    mime_type_t *next = (mime_type_t *)cupsArrayNext(mime->types);
+                                       /* Next type */
+
+    DEBUG_printf(("7mimeNextType: Returning %p.", next));
+    return (next);
+  }
 }
 
 
@@ -339,10 +472,19 @@ mimeNextType(mime_t *mime)                /* I - MIME database */
 int
 mimeNumFilters(mime_t *mime)           /* I - MIME database */
 {
+  DEBUG_printf(("mimeNumFilters(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("1mimeNumFilters: Returning 0.");
     return (0);
+  }
   else
+  {
+    DEBUG_printf(("1mimeNumFilters: Returning %d.",
+                  cupsArrayCount(mime->filters)));
     return (cupsArrayCount(mime->filters));
+  }
 }
 
 
@@ -353,33 +495,70 @@ mimeNumFilters(mime_t *mime)              /* I - MIME database */
 int
 mimeNumTypes(mime_t *mime)             /* I - MIME database */
 {
+  DEBUG_printf(("mimeNumTypes(mime=%p)", mime));
+
   if (!mime)
+  {
+    DEBUG_puts("1mimeNumTypes: Returning 0.");
     return (0);
+  }
   else
+  {
+    DEBUG_printf(("1mimeNumTypes: Returning %d.",
+                  cupsArrayCount(mime->types)));
     return (cupsArrayCount(mime->types));
+  }
+}
+
+
+/*
+ * 'mimeSetErrorCallback()' - Set the callback for error messages.
+ */
+
+void
+mimeSetErrorCallback(
+    mime_t          *mime,             /* I - MIME database */
+    mime_error_cb_t cb,                        /* I - Callback function */
+    void            *ctx)              /* I - Context pointer for callback */
+{
+  if (mime)
+  {
+    mime->error_cb  = cb;
+    mime->error_ctx = ctx;
+  }
 }
 
 
 /*
- * 'add_fcache()' - Add a filter to the filter cache.
+ * 'mime_add_fcache()' - Add a filter to the filter cache.
  */
 
 static const char *                    /* O - Full path to filter or NULL */
-add_fcache(cups_array_t *filtercache,  /* I - Filter cache */
-           const char   *name,         /* I - Filter name */
-          const char   *filterpath)    /* I - Filter path */
+mime_add_fcache(
+    cups_array_t *filtercache,         /* I - Filter cache */
+    const char   *name,                        /* I - Filter name */
+    const char   *filterpath)          /* I - Filter path */
 {
   _mime_fcache_t       key,            /* Search key */
                        *temp;          /* New filter cache */
   char                 path[1024];     /* Full path to filter */
 
 
+  DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", "
+                "filterpath=\"%s\")", filtercache, name, filterpath));
+
   key.name = (char *)name;
   if ((temp = (_mime_fcache_t *)cupsArrayFind(filtercache, &key)) != NULL)
+  {
+    DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
     return (temp->path);
+  }
 
   if ((temp = calloc(1, sizeof(_mime_fcache_t))) == NULL)
+  {
+    DEBUG_puts("3mime_add_fcache: Returning NULL.");
     return (NULL);
+  }
 
   temp->name = strdup(name);
 
@@ -388,16 +567,17 @@ add_fcache(cups_array_t *filtercache,     /* I - Filter cache */
 
   cupsArrayAdd(filtercache, temp);
 
+  DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
   return (temp->path);
 }
 
 
 /*
- * 'compare_fcache()' - Compare two filter cache entries.
+ * 'mime_compare_fcache()' - Compare two filter cache entries.
  */
 
 static int                             /* O - Result of comparison */
-compare_fcache(_mime_fcache_t *a,      /* I - First entry */
+mime_compare_fcache(_mime_fcache_t *a, /* I - First entry */
                _mime_fcache_t *b)      /* I - Second entry */
 {
   return (strcmp(a->name, b->name));
@@ -405,15 +585,18 @@ compare_fcache(_mime_fcache_t *a, /* I - First entry */
 
 
 /*
- * 'delete_fcache()' - Free all memory used by the filter cache.
+ * 'mime_delete_fcache()' - Free all memory used by the filter cache.
  */
 
 static void
-delete_fcache(cups_array_t *filtercache)/* I - Filter cache */
+mime_delete_fcache(
+    cups_array_t *filtercache)         /* I - Filter cache */
 {
   _mime_fcache_t       *current;       /* Current cache entry */
 
 
+  DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache));
+
   for (current = (_mime_fcache_t *)cupsArrayFirst(filtercache);
        current;
        current = (_mime_fcache_t *)cupsArrayNext(filtercache))
@@ -431,15 +614,17 @@ delete_fcache(cups_array_t *filtercache)/* I - Filter cache */
 
 
 /*
- * 'delete_rules()' - Free all memory for the given rule tree.
+ * 'mime_delete_rules()' - Free all memory for the given rule tree.
  */
 
 static void
-delete_rules(mime_magic_t *rules)      /* I - Rules to free */
+mime_delete_rules(mime_magic_t *rules) /* I - Rules to free */
 {
   mime_magic_t *next;                  /* Next rule to free */
 
 
+  DEBUG_printf(("2mime_delete_rules(rules=%p)", rules));
+
  /*
   * Free the rules list, descending recursively to free any child rules.
   */
@@ -449,7 +634,10 @@ delete_rules(mime_magic_t *rules)  /* I - Rules to free */
     next = rules->next;
 
     if (rules->child != NULL)
-      delete_rules(rules->child);
+      mime_delete_rules(rules->child);
+
+    if (rules->op == MIME_MAGIC_REGEX)
+      regfree(&(rules->value.rev));
 
     free(rules);
     rules = next;
@@ -458,14 +646,15 @@ delete_rules(mime_magic_t *rules) /* I - Rules to free */
 
 
 /*
- * 'load_convs()' - Load a xyz.convs file...
+ * 'mime_load_convs()' - Load a xyz.convs file.
  */
 
 static void
-load_convs(mime_t       *mime,         /* I - MIME database */
-           const char   *filename,     /* I - Convs file to load */
-           const char   *filterpath,   /* I - Path for filters */
-          cups_array_t *filtercache)   /* I - Filter program cache */
+mime_load_convs(
+    mime_t       *mime,                        /* I - MIME database */
+    const char   *filename,            /* I - Convs file to load */
+    const char   *filterpath,          /* I - Path for filters */
+    cups_array_t *filtercache)         /* I - Filter program cache */
 {
   cups_file_t  *fp;                    /* Convs file */
   char         line[1024],             /* Input line from file */
@@ -479,12 +668,20 @@ load_convs(mime_t       *mime,            /* I - MIME database */
   int          cost;                   /* Cost of filter */
 
 
+  DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", "
+                "filtercache=%p)", mime, filename, filterpath, filtercache));
+
  /*
   * First try to open the file...
   */
 
   if ((fp = cupsFileOpen(filename, "r")) == NULL)
+  {
+    DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename,
+                  strerror(errno)));
+    _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno));
     return;
+  }
 
  /*
   * Then read each line from the file, skipping any comments in the file...
@@ -524,7 +721,7 @@ load_convs(mime_t       *mime,              /* I - MIME database */
 
     while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
            (temp - super + 1) < MIME_MAX_SUPER)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -536,7 +733,7 @@ load_convs(mime_t       *mime,              /* I - MIME database */
 
     while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
            *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -544,7 +741,11 @@ load_convs(mime_t       *mime,             /* I - MIME database */
       continue;
 
     if ((dsttype = mimeType(mime, super, type)) == NULL)
+    {
+      DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.",
+                    super, type));
       continue;
+    }
 
    /*
     * Then get the cost and filter program...
@@ -574,8 +775,13 @@ load_convs(mime_t       *mime,             /* I - MIME database */
       * Verify that the filter exists and is executable...
       */
 
-      if (!add_fcache(filtercache, filter, filterpath))
+      if (!mime_add_fcache(filtercache, filter, filterpath))
+      {
+        DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter,
+                     filterpath));
+        _mimeError(mime, "Filter \"%s\" not found.", filter);
         continue;
+      }
     }
 
    /*
@@ -588,7 +794,7 @@ load_convs(mime_t       *mime,              /* I - MIME database */
 
     while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
            (temp - super + 1) < MIME_MAX_SUPER)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -600,7 +806,7 @@ load_convs(mime_t       *mime,              /* I - MIME database */
 
     while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
            *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -610,8 +816,8 @@ load_convs(mime_t       *mime,              /* I - MIME database */
       * Force * / * to be "application/octet-stream"...
       */
 
-      strcpy(super, "application");
-      strcpy(type, "octet-stream");
+      strlcpy(super, "application", sizeof(super));
+      strlcpy(type, "octet-stream", sizeof(type));
     }
 
    /*
@@ -631,15 +837,15 @@ load_convs(mime_t       *mime,            /* I - MIME database */
 
 
 /*
- * 'load_types()' - Load a xyz.types file...
+ * 'mime_load_types()' - Load a xyz.types file.
  */
 
 static void
-load_types(mime_t     *mime,           /* I - MIME database */
-           const char *filename)       /* I - Types file to load */
+mime_load_types(mime_t     *mime,      /* I - MIME database */
+                const char *filename)  /* I - Types file to load */
 {
   cups_file_t  *fp;                    /* Types file */
-  int          linelen;                /* Length of line */
+  size_t       linelen;                /* Length of line */
   char         line[32768],            /* Input line from file */
                *lineptr,               /* Current position in line */
                super[MIME_MAX_SUPER],  /* Super-type name */
@@ -648,12 +854,19 @@ load_types(mime_t     *mime,              /* I - MIME database */
   mime_type_t  *typeptr;               /* New MIME type */
 
 
+  DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename));
+
  /*
   * First try to open the file...
   */
 
   if ((fp = cupsFileOpen(filename, "r")) == NULL)
+  {
+    DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename,
+                  strerror(errno)));
+    _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno));
     return;
+  }
 
  /*
   * Then read each line from the file, skipping any comments in the file...
@@ -694,7 +907,7 @@ load_types(mime_t     *mime,                /* I - MIME database */
 
     while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
            (temp - super + 1) < MIME_MAX_SUPER)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -706,7 +919,7 @@ load_types(mime_t     *mime,                /* I - MIME database */
 
     while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
            *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
-      *temp++ = tolower(*lineptr++ & 255);
+      *temp++ = (char)tolower(*lineptr++ & 255);
 
     *temp = '\0';
 
@@ -720,8 +933,3 @@ load_types(mime_t     *mime,                /* I - MIME database */
 
   cupsFileClose(fp);
 }
-
-
-/*
- * End of "$Id: mime.c 5495 2006-05-05 17:58:07Z mike $".
- */