]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Update _ppdCacheCreateWithPPD to collect localizable strings for the languages
authorMichael R Sweet <msweet@msweet.org>
Tue, 16 Apr 2024 12:29:10 +0000 (08:29 -0400)
committerMichael R Sweet <msweet@msweet.org>
Tue, 16 Apr 2024 12:29:10 +0000 (08:29 -0400)
we are interested in.

Add support for Languages directive in cups-files.conf.

cups/language.c
cups/ppd-cache.c
cups/testcache.c
cups/testppd.c
cups/testpwg.c
scheduler/client.c
scheduler/conf.c
scheduler/conf.h
scheduler/ipp.c
scheduler/printers.c
scheduler/testmime.c

index c596e254926f335de151d28ca4b23890e44e59c9..2a65ea4412616aadf9f0ee09a741f5e551f7a8ae 100644 (file)
@@ -115,6 +115,7 @@ static const char * const lang_encodings[] =
 static cups_lang_t     *cups_cache_lookup(const char *name, cups_encoding_t encoding);
 static int             cups_message_compare(_cups_message_t *m1, _cups_message_t *m2,
                                 void *data);
+static _cups_message_t *cups_message_copy(_cups_message_t *m, void *data);
 static void            cups_message_free(_cups_message_t *m, void *data);
 static void            cups_message_load(cups_lang_t *lang);
 static void            cups_message_puts(cups_file_t *fp, const char *s);
@@ -668,12 +669,11 @@ _cupsMessageLoad(cups_array_t *a, /* I - Existing message array */
                  int          flags)   /* I - Load flags */
 {
   cups_file_t          *fp;            /* Message file */
-  _cups_message_t      *m;             /* Current message */
+  _cups_message_t      m;              /* Current message */
   char                 s[4096],        /* String buffer */
-                       *ptr,           /* Pointer into buffer */
-                       *temp;          /* New string */
-  size_t               length,         /* Length of combined strings */
-                       ptrlen;         /* Length of string */
+                       msg_id[4096],   /* Message ID buffer */
+                       msg_str[4096],  /* Message string buffer */
+                       *ptr;           /* Pointer into buffer */
 
 
   DEBUG_printf("4_cupsMessageLoad(a=%p, filename=\"%s\", flags=%d)", (void *)a, filename, flags);
@@ -724,7 +724,8 @@ _cupsMessageLoad(cups_array_t *a,   /* I - Existing message array */
     *     "multiple lines"
     */
 
-    m = NULL;
+    m.msg = NULL;
+    m.str = NULL;
 
     while (cupsFileGets(fp, s, sizeof(s)) != NULL)
     {
@@ -770,96 +771,36 @@ _cupsMessageLoad(cups_array_t *a, /* I - Existing message array */
        * Add previous message as needed...
        */
 
-       if (m)
-       {
-         if (m->str && (m->str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
-         {
-           cupsArrayAdd(a, m);
-         }
-         else
-         {
-          /*
-           * Translation is empty, don't add it... (STR #4033)
-           */
-
-           free(m->msg);
-           if (m->str)
-             free(m->str);
-           free(m);
-         }
-       }
+       if (m.str && (m.str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
+         cupsArrayAdd(a, &m);
 
        /*
        * Create a new message with the given msgid string...
        */
 
-       if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
-         break;
-
-       if ((m->msg = strdup(ptr)) == NULL)
-       {
-         free(m);
-         m = NULL;
-         break;
-       }
+        cupsCopyString(msg_id, ptr, sizeof(msg_id));
+        m.msg = msg_id;
+        m.str = NULL;
       }
-      else if (s[0] == '\"' && m)
+      else if (s[0] == '\"' && (m.msg || m.str))
       {
        /*
        * Append to current string...
        */
 
-       length = strlen(m->str ? m->str : m->msg);
-       ptrlen = strlen(ptr);
-
-       if ((temp = realloc(m->str ? m->str : m->msg, length + ptrlen + 1)) == NULL)
-       {
-         if (m->str)
-           free(m->str);
-         free(m->msg);
-         free(m);
-         m = NULL;
-         break;
-       }
-
-       if (m->str)
-       {
-        /*
-         * Copy the new portion to the end of the msgstr string - safe
-         * to use memcpy because the buffer is allocated to the correct
-         * size...
-         */
-
-         m->str = temp;
-
-         memcpy(m->str + length, ptr, ptrlen + 1);
-       }
+       if (m.str)
+          cupsConcatString(msg_str, ptr, sizeof(msg_str));
        else
-       {
-        /*
-         * Copy the new portion to the end of the msgid string - safe
-         * to use memcpy because the buffer is allocated to the correct
-         * size...
-         */
-
-         m->msg = temp;
-
-         memcpy(m->msg + length, ptr, ptrlen + 1);
-       }
+          cupsConcatString(msg_id, ptr, sizeof(msg_id));
       }
-      else if (!strncmp(s, "msgstr", 6) && m)
+      else if (!strncmp(s, "msgstr", 6) && m.msg)
       {
        /*
        * Set the string...
        */
 
-       if ((m->str = strdup(ptr)) == NULL)
-       {
-         free(m->msg);
-         free(m);
-         m = NULL;
-          break;
-       }
+        cupsCopyString(msg_str, ptr, sizeof(msg_str));
+        m.str = msg_str;
       }
     }
 
@@ -867,24 +808,8 @@ _cupsMessageLoad(cups_array_t *a,  /* I - Existing message array */
     * Add the last message string to the array as needed...
     */
 
-    if (m)
-    {
-      if (m->str && (m->str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
-      {
-        if (cupsArrayFind(a, m))
-          cups_message_free(m, NULL);
-        else
-         cupsArrayAdd(a, m);
-      }
-      else
-      {
-       /*
-       * Translation is empty, don't add it... (STR #4033)
-       */
-
-        cups_message_free(m, NULL);
-      }
-    }
+    if (m.msg && m.str && (m.str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
+      cupsArrayAdd(a, &m);
   }
 
  /*
@@ -935,10 +860,10 @@ _cupsMessageLookup(cups_array_t *a,       /* I - Message array */
 cups_array_t *                         /* O - Array */
 _cupsMessageNew(void *context)         /* I - User data */
 {
-  return (cupsArrayNew3((cups_array_func_t)cups_message_compare, context,
-                        (cups_ahash_func_t)NULL, 0,
-                       (cups_acopy_func_t)NULL,
-                       (cups_afree_func_t)cups_message_free));
+  return (cupsArrayNew3((cups_array_cb_t)cups_message_compare, context,
+                        (cups_ahash_cb_t)NULL, 0,
+                       (cups_acopy_cb_t)cups_message_copy,
+                       (cups_afree_cb_t)cups_message_free));
 }
 
 
@@ -1046,13 +971,44 @@ cups_message_compare(_cups_message_t *m1, /* I - First message */
 }
 
 
+//
+// 'cups_message_copy()' - Copy a message.
+//
+
+static _cups_message_t *               // O - New message
+cups_message_copy(_cups_message_t *m,  // I - Message
+                  void            *data)// I - Callback data (unused)
+{
+  _cups_message_t      *newm;          // New message
+
+
+  (void)data;
+
+  if ((newm = (_cups_message_t *)malloc(sizeof(_cups_message_t))) != NULL)
+  {
+    newm->msg = strdup(m->msg);
+    newm->str = strdup(m->str);
+
+    if (!newm->msg || !newm->str)
+    {
+      free(newm->msg);
+      free(newm->str);
+      free(newm);
+
+      newm = NULL;
+    }
+  }
+
+  return (newm);
+}
+
 /*
  * 'cups_message_free()' - Free a message.
  */
 
 static void
 cups_message_free(_cups_message_t *m,  /* I - Message */
-                 void            *data)/* Unused */
+                 void            *data)/* I - Callback data (unused) */
 {
   (void)data;
 
@@ -1157,7 +1113,7 @@ cups_read_strings(cups_file_t  *fp,       /* I - .strings file */
                        *bufptr,        /* Pointer into buffer */
                        *msg,           /* Pointer to start of message */
                        *str;           /* Pointer to start of translation string */
-  _cups_message_t      *m;             /* New message */
+  _cups_message_t      m;              /* New message */
 
 
   while (cupsFileGets(fp, buffer, sizeof(buffer)))
@@ -1228,24 +1184,11 @@ cups_read_strings(cups_file_t  *fp,     /* I - .strings file */
     * If we get this far we have a valid pair of strings, add them...
     */
 
-    if ((m = malloc(sizeof(_cups_message_t))) == NULL)
-      break;
-
-    m->msg = strdup(msg);
-    m->str = strdup(str);
+    m.msg = msg;
+    m.str = str;
 
-    if (m->msg && m->str)
-    {
-      if (cupsArrayFind(a, m))
-        cups_message_free(m, NULL);
-      else
-       cupsArrayAdd(a, m);
-    }
-    else
-    {
-      cups_message_free(m, NULL);
-      break;
-    }
+    if (!cupsArrayFind(a, &m))
+      cupsArrayAdd(a, &m);
 
     return (1);
   }
index 0cd49851ff1748b626e81ab1b70f1f7f25dfd1a4..93ea0034cce7d8854bcf098c96f8bbdb3b5b1d76 100644 (file)
  */
 
 static int     cups_connect(http_t **http, const char *url, char *resource, size_t ressize);
-static cups_array_t *cups_get_languages(void);
 static cups_lang_t *cups_get_strings(http_t **http, const char *printer_uri, const char *language);
 static int     cups_get_url(http_t **http, const char *url, const char *suffix, char *name, size_t namesize);
 static const char *ppd_get_string(cups_lang_t *base, cups_lang_t *printer, const char *msgid, char *buffer, size_t bufsize);
+static void    ppd_get_strings(ppd_file_t *ppd, cups_lang_t *langs, const char *option, ppd_choice_t *choice, const char *pwg_msgid);
 static const char *ppd_inputslot_for_keyword(_ppd_cache_t *pc, const char *keyword);
 static void    ppd_put_strings(cups_file_t *fp, cups_lang_t *langs, const char *ppd_option, const char *ppd_choice, const char *pwg_msgid);
 static void    pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value);
@@ -1351,32 +1351,7 @@ _ppdCacheCreateWithPPD(
       */
 
       snprintf(msg_id, sizeof(msg_id), "media-source.%s", pwg_name);
-      msg.msg = msg_id;
-
-      for (lang = langs; lang; lang = lang->next)
-      {
-        // See if the string is already localized...
-        if (cupsArrayFind(lang->strings, &msg))
-          continue;                    // Yes
-
-        // Otherwise add the text...
-        if (!strcmp(lang->language, "en"))
-        {
-          // English
-          msg.str = choice->text;
-       }
-       else
-       {
-         // Other languauge...
-          snprintf(ppd_name, sizeof(ppd_name), "%s.InputSlot", lang->language);
-          if ((ppd_attr = ppdFindAttr(ppd, ppd_name, choice->choice)) != NULL)
-            msg.str = ppd_attr->text;
-         else
-           continue;
-       }
-
-       cupsArrayAdd(lang->strings, &msg);
-      }
+      ppd_get_strings(ppd, langs, "InputSlot", choice, msg_id);
     }
   }
 
@@ -1487,38 +1462,12 @@ _ppdCacheCreateWithPPD(
         }
       }
 
-
      /*
       * Add localized text for PWG keyword to message catalog...
       */
 
       snprintf(msg_id, sizeof(msg_id), "media-type.%s", map->pwg);
-      msg.msg = msg_id;
-
-      for (lang = langs; lang; lang = lang->next)
-      {
-        // See if the string is already localized...
-        if (cupsArrayFind(lang->strings, &msg))
-          continue;                    // Yes
-
-        // Otherwise add the text...
-        if (!strcmp(lang->language, "en"))
-        {
-          // English
-          msg.str = choice->text;
-       }
-       else
-       {
-         // Other languauge...
-          snprintf(ppd_name, sizeof(ppd_name), "%s.MediaType", lang->language);
-          if ((ppd_attr = ppdFindAttr(ppd, ppd_name, choice->choice)) != NULL)
-            msg.str = ppd_attr->text;
-         else
-           continue;
-       }
-
-       cupsArrayAdd(lang->strings, &msg);
-      }
+      ppd_get_strings(ppd, langs, "MediaType", choice, msg_id);
     }
   }
 
@@ -1552,32 +1501,7 @@ _ppdCacheCreateWithPPD(
       */
 
       snprintf(msg_id, sizeof(msg_id), "output-bin.%s", pwg_name);
-      msg.msg = msg_id;
-
-      for (lang = langs; lang; lang = lang->next)
-      {
-        // See if the string is already localized...
-        if (cupsArrayFind(lang->strings, &msg))
-          continue;                    // Yes
-
-        // Otherwise add the text...
-        if (!strcmp(lang->language, "en"))
-        {
-          // English
-          msg.str = choice->text;
-       }
-       else
-       {
-         // Other languauge...
-          snprintf(ppd_name, sizeof(ppd_name), "%s.OutputBin", lang->language);
-          if ((ppd_attr = ppdFindAttr(ppd, ppd_name, choice->choice)) != NULL)
-            msg.str = ppd_attr->text;
-         else
-           continue;
-       }
-
-       cupsArrayAdd(lang->strings, &msg);
-      }
+      ppd_get_strings(ppd, langs, "OutputBin", choice, msg_id);
     }
   }
 
@@ -5358,62 +5282,6 @@ cups_connect(http_t     **http,          /* IO - Current HTTP connection */
 }
 
 
-/*
- * 'cups_get_languages()' - Get the languages to load for PPDs.
- */
-
-static cups_array_t *                  /* O - Array of languages */
-cups_get_languages(void)
-{
-  cups_array_t *languages = NULL;      /* Array of languages */
-  cups_file_t  *fp;                    /* CUPS_SERVERROOT/cups-files.conf file */
-  char         filename[1024];         /* Filename */
-  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
-
-
-  snprintf(filename, sizeof(filename), "%s/cups-files.conf", cg->cups_serverroot);
-
-  if ((fp = cupsFileOpen(filename, "r")) != NULL)
-  {
-   /*
-    * Read the cups-files.conf file, looking for a Languages directive...
-    */
-
-    char       line[1024],             /* Line from file */
-               *value;                 /* Value from line */
-    int                linenum = 0;            /* Current line number */
-
-    while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
-    {
-      if (!_cups_strcasecmp(line, "Languages") && value)
-      {
-        languages = cupsArrayNewStrings(value, ' ');
-        break;
-      }
-    }
-
-    cupsFileClose(fp);
-  }
-
-  if (!languages)
-  {
-   /*
-    * No Languages directive in CUPS_SERVERROOT/cups-files.conf, so use the
-    * current locale...
-    */
-
-    cups_lang_t        *deflang;               /* Default language */
-
-    languages = cupsArrayNewStrings(NULL, ' ');
-    deflang   = cupsLangDefault();
-
-    cupsArrayAdd(languages, deflang->language);
-  }
-
-  return (languages);
-}
-
-
 /*
  * 'cups_get_strings()' - Get the strings for the specified language.
  */
@@ -5601,6 +5469,53 @@ ppd_get_string(cups_lang_t *base,        // I - Base (CUPS) localization
 }
 
 
+//
+// 'ppd_get_strings()' - Get the strings for a given option and choice.
+//
+
+static void
+ppd_get_strings(
+    ppd_file_t   *ppd,                 // I - PPD file
+    cups_lang_t  *langs,               // I - Languages
+    const char   *option,              // I - PPD option keyword
+    ppd_choice_t *choice,              // I - PPD choice
+    const char   *pwg_msgid)           // I - PWG message ID
+{
+  cups_lang_t  *lang;                  // Current language
+  char         ppd_name[PPD_MAX_NAME]; // PPD main keyword
+  ppd_attr_t   *ppd_attr;              // PPD attribute
+  _cups_message_t msg;                 // Message
+
+
+  msg.msg = (char *)pwg_msgid;
+
+  for (lang = langs; lang; lang = lang->next)
+  {
+    // See if the string is already localized...
+    if (cupsArrayFind(lang->strings, &msg))
+      continue;                        // Yes
+
+    // Otherwise add the text...
+    if (!strcmp(lang->language, "en"))
+    {
+      // English
+      msg.str = choice->text;
+    }
+    else
+    {
+      // Other languauge...
+      snprintf(ppd_name, sizeof(ppd_name), "%s.%s", lang->language, option);
+      if ((ppd_attr = ppdFindAttr(ppd, ppd_name, choice->choice)) != NULL)
+       msg.str = ppd_attr->text;
+      else
+       continue;
+    }
+
+    cupsArrayAdd(lang->strings, &msg);
+  }
+}
+
+
 /*
  * 'ppd_put_strings()' - Write localization attributes to a PPD file.
  */
index b68740ba8b8b1ce5bfdde9f1fdd6d0fc75034480..b5ca2e2407d7cb9aa05781f8a220f233d9e51bf6 100644 (file)
@@ -53,7 +53,7 @@ main(int  argc,                               /* I - Number of command-line args */
     return (1);
   }
 
-  if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
+  if ((pc = _ppdCacheCreateWithPPD(NULL, ppd)) == NULL)
   {
     fprintf(stderr, "Unable to create PPD cache from \"%s\".\n", ppdfile);
     return (1);
index 7b0e87e16a46540f3fcc41c8105a5079ba32cec4..61abce61c4c98daba2daf979a2383c69c23c94b2 100644 (file)
@@ -1358,7 +1358,7 @@ main(int  argc,                           /* I - Number of command-line arguments */
               attr->text, attr->value ? attr->value : "");
 
       puts("\nPPD Cache:");
-      if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
+      if ((pc = _ppdCacheCreateWithPPD(NULL, ppd)) == NULL)
         printf("    Unable to create: %s\n", cupsGetErrorString());
       else
       {
index 1561fd0e599da170d49e8e9ca4d5524d56285429..cc235ae4616c378f41d3ff49ee25757674ad370b 100644 (file)
@@ -69,8 +69,8 @@ main(int  argc,                               /* I - Number of command-line args */
   else
     puts("PASS");
 
-  fputs("_ppdCacheCreateWithPPD(ppd): ", stdout);
-  if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
+  fputs("_ppdCacheCreateWithPPD(NULL, ppd): ", stdout);
+  if ((pc = _ppdCacheCreateWithPPD(NULL, ppd)) == NULL)
   {
     puts("FAIL");
     status ++;
index bd38cc74b4d7b7a6a6d4272c6f2fbccb800dddba..8d1c5cc5d9df9cf297b572a0c4a9c94fcacb68f2 100644 (file)
  * information.
  */
 
-/*
- * Include necessary headers...
- */
-
 #define _CUPS_NO_DEPRECATED
 #define _HTTP_NO_PRIVATE
 #include "cupsd.h"
@@ -36,18 +32,13 @@ static int          check_if_modified(cupsd_client_t *con,
                                          struct stat *filestats);
 static int             compare_clients(cupsd_client_t *a, cupsd_client_t *b, void *data);
 static int             cupsd_start_tls(cupsd_client_t *con, http_encryption_t e);
-static char            *get_file(cupsd_client_t *con, struct stat *filestats,
-                        char *filename, size_t len);
+static char            *get_file(cupsd_client_t *con, struct stat *filestats, char *filename, size_t len);
 static http_status_t   install_cupsd_conf(cupsd_client_t *con);
-static int             is_cgi(cupsd_client_t *con, const char *filename,
-                    struct stat *filestats, mime_type_t *type);
+static int             is_cgi(cupsd_client_t *con, const char *filename, struct stat *filestats, mime_type_t *type);
 static int             is_path_absolute(const char *path);
-static int             pipe_command(cupsd_client_t *con, int infile, int *outfile,
-                           char *command, char *options, int root);
+static int             pipe_command(cupsd_client_t *con, int infile, int *outfile, char *command, char *options, int root);
 static int             valid_host(cupsd_client_t *con);
-static int             write_file(cupsd_client_t *con, http_status_t code,
-                         char *filename, char *type,
-                         struct stat *filestats);
+static int             write_file(cupsd_client_t *con, http_status_t code, char *filename, char *type, struct stat *filestats);
 static void            write_pipe(cupsd_client_t *con);
 
 
@@ -2811,28 +2802,12 @@ get_file(cupsd_client_t *con,           /* I  - Client connection */
     return (NULL);
   }
   else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/'))
+  {
     snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5);
+  }
   else if (!strncmp(con->uri, "/strings/", 9) && !strcmp(con->uri + strlen(con->uri) - 8, ".strings"))
   {
-    cupsCopyString(dest, con->uri + 9, sizeof(dest));
-    dest[strlen(dest) - 8] = '\0';
-
-    if ((p = cupsdFindDest(dest)) == NULL)
-    {
-      cupsCopyString(filename, "/", len);
-      cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
-      return (NULL);
-    }
-
-    if (!p->strings)
-    {
-      cupsCopyString(filename, "/", len);
-      cupsdLogClient(con, CUPSD_LOG_INFO, "No strings files for \"%s\".", dest);
-      return (NULL);
-    }
-
-    cupsCopyString(filename, p->strings, len);
-
+    snprintf(filename, len, "%s/strings/%s", ServerRoot, con->uri + 9);
     perm_check = 0;
   }
   else if (con->language)
index 4f45282fbbd631a7af8b192ba4d5f66886bd8bf1..6846f47bc7d3384c92121ac3468785e415c0a572 100644 (file)
@@ -170,6 +170,7 @@ static const unsigned       zeros[4] =
  * Local functions...
  */
 
+static void            add_language(const char *language);
 static http_addrlist_t *get_address(const char *value, int defport);
 static int             get_addr_and_mask(const char *value, unsigned *ip,
                                          unsigned *mask);
@@ -607,6 +608,23 @@ cupsdReadConfiguration(void)
   else
     cupsdSetString(&DefaultLanguage, language->language);
 
+  if (Languages)
+  {
+    // Free old languages...
+    cups_lang_t        *lang,                  // Current language
+               *next;                  // Next language
+
+    for (lang = Languages; lang; lang = next)
+    {
+      next = lang->next;
+
+      cupsArrayDelete(lang->strings);
+      free(lang);
+    }
+
+    Languages = NULL;
+  }
+
   cupsdClearString(&DefaultPaperSize);
   cupsArrayDelete(ReadyPaperSizes);
   ReadyPaperSizes = NULL;
@@ -1053,6 +1071,15 @@ cupsdReadConfiguration(void)
 
   cupsdSetStringf(&DefaultLocale, "%s.UTF-8", DefaultLanguage);
 
+ /*
+  * Make sure we have languages loaded...
+  */
+
+  if (!Languages)
+    add_language(DefaultLanguage);
+
+  add_language("en");
+
  /*
   * Update all relative filenames to include the full path from ServerRoot...
   */
@@ -1699,6 +1726,68 @@ cupsdReadConfiguration(void)
 }
 
 
+//
+// 'cupsdWriteStrings()' - Write out strings files.
+//
+
+void
+cupsdWriteStrings(void)
+{
+  cups_lang_t  *lang;                  // New language
+  char         strings_file[1024];     // Strings file
+
+
+  // Save each language...
+  for (lang = Languages; lang; lang = lang->next)
+  {
+    snprintf(strings_file, sizeof(strings_file), "%s/strings/%s.strings", ServerRoot, lang->language);
+    _cupsMessageSave(strings_file, _CUPS_MESSAGE_STRINGS, lang->strings);
+  }
+}
+
+
+//
+// 'add_language()' - Add a language to the Languages array.
+//
+
+static void
+add_language(const char *language)     // I - Language code
+{
+  cups_lang_t  *lang;                  // New language
+  char         strings_file[1024];     // Strings file
+
+
+  // See if the language was already added...
+  for (lang = Languages; lang; lang = lang->next)
+  {
+    if (!strcmp(lang->language, language))
+      return;
+  }
+
+  // Not already added, so create a new entry and load any existing strings...
+  lang = (cups_lang_t *)calloc(1, sizeof(cups_lang_t));
+  cupsCopyString(lang->language, language, sizeof(lang->language));
+
+  snprintf(strings_file, sizeof(strings_file), "%s/strings/%s.strings", ServerRoot, language);
+  lang->strings = _cupsMessageLoad(NULL, strings_file, _CUPS_MESSAGE_STRINGS);
+
+  // Add the language to the list - English (en) is always first, then the rest
+  // follow...
+  if (Languages && !strcmp(Languages->language, "en"))
+  {
+    // Insert this language after the first one...
+    lang->next      = Languages->next;
+    Languages->next = lang;
+  }
+  else
+  {
+    // Insert this at the front of the list...
+    lang->next = Languages;
+    Languages  = lang;
+  }
+}
+
+
 /*
  * 'get_address()' - Get an address + port number from a line.
  */
@@ -3475,7 +3564,9 @@ read_cups_files_conf(cups_file_t *fp)     /* I - File to read from */
   while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
   {
     if (!_cups_strcasecmp(line, "FatalErrors"))
+    {
       FatalErrors = parse_fatal_errors(value);
+    }
     else if (!_cups_strcasecmp(line, "Group") && value)
     {
      /*
@@ -3502,6 +3593,21 @@ read_cups_files_conf(cups_file_t *fp)    /* I - File to read from */
       }
     }
     else if (!_cups_strcasecmp(line, "LogFileGroup") && value)
+    {
+     /*
+      * List of languages to support...
+      */
+      cups_array_t     *languages;     // Array of language codes
+      const char       *language;      // Current language
+
+      languages = cupsArrayNewStrings(value, ' ');
+
+      for (language = (const char *)cupsArrayGetFirst(languages); language; language = (const char *)cupsArrayGetNext(languages))
+        add_language(language);
+
+      cupsArrayDelete(languages);
+    }
+    else if (!_cups_strcasecmp(line, "LogFileGroup") && value)
     {
      /*
       * Group ID to log as...
index 19b5c1621b8a386ed03a681d6c1629499c0c7b24..e59ee22f404cdb8fcb2890bb5d0183acc1f0cf55 100644 (file)
@@ -287,3 +287,4 @@ extern int  cupsdLogPage(cupsd_job_t *job, const char *page);
 extern int     cupsdLogRequest(cupsd_client_t *con, http_status_t code);
 extern int     cupsdReadConfiguration(void);
 extern int     cupsdWriteErrorLog(int level, const char *message);
+extern void    cupsdWriteStrings(void);
index 798a8044c17e3e1cd70f2c4f251292724b89e796..92a39aee20e6b4b29981131e37c5848c4e306036 100644 (file)
@@ -4986,9 +4986,31 @@ copy_printer_attrs(
   if (!ra || cupsArrayFind(ra, "printer-state-reasons"))
     add_printer_state_reasons(con, printer);
 
+  if (!ra || cupsArrayFind(ra, "printer-strings-languages-supported"))
+  {
+    cups_lang_t                *lang;          // Current language
+    ipp_attribute_t    *attr = NULL;   // Attribute
+
+    for (lang = Languages; lang; lang = lang->next)
+    {
+      if (attr)
+        ippSetString(con->response, &attr, ippGetCount(attr), lang->language);
+      else
+        attr = ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "printer-strings-languages-supported", NULL, lang->language);
+    }
+  }
+
   if (!ra || cupsArrayFind(ra, "printer-strings-uri"))
   {
-    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "https" : "http", NULL, con->clientname, con->clientport, "/strings/%s.strings", printer->name);
+    cups_lang_t                *lang;          // Current language
+
+    for (lang = Languages; lang; lang = lang->next)
+    {
+      if (!strcmp(lang->language, con->language->language))
+        break;
+    }
+
+    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "https" : "http", NULL, con->clientname, con->clientport, "/strings/%s.strings", lang ? lang->language : "en");
     ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-strings-uri", NULL, uri);
     cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-strings-uri=\"%s\"", uri);
   }
index e4384abc63c623484b38744f12d33ece73fc5c94..24353f20b57a305807d77064e7659335b107cb96 100644 (file)
@@ -4029,6 +4029,8 @@ load_ppd(cupsd_printer_t *p)              /* I - Printer */
     if (!p->pc)
       cupsdLogMessage(CUPSD_LOG_WARN, "Unable to create cache of \"%s\": %s", ppd_name, cupsGetErrorString());
 
+    cupsdWriteStrings();
+
     ppdMarkDefaults(ppd);
 
     if (ppd->color_device)
index f4579711a34e0263634194c38ede7caae5d8d00d..60356af3264b0e040734a30d4f20afeb382f7ea4 100644 (file)
@@ -304,7 +304,7 @@ add_ppd_filters(mime_t     *mime,   /* I - MIME database */
                *prefilter;             /* Pre-filter type */
 
 
-  pc = _ppdCacheCreateWithPPD(ppd);
+  pc = _ppdCacheCreateWithPPD(NULL, ppd);
   if (!pc)
     return;