]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Implement the IPP localization API (STR #3925)
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 23 May 2012 20:17:12 +0000 (20:17 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 23 May 2012 20:17:12 +0000 (20:17 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@10506 7a7537e8-13f0-0310-91df-b6672ffda945

cups/dest-localization.c
cups/language-private.h
cups/language.c

index 375386909471ec1015ce35eb337c9485590afbc3..ad709ee82e286ed0390f8f80a5925d348490d240 100644 (file)
  *
  * Contents:
  *
- *   cupsLocalizeDestOption() - Get the localized string for a destination
- *                             option.
- *   cupsLocalizeDestValue()  - Get the localized string for a destination
- *                             option+value pair.
+ *   cupsLocalizeDestOption()   - Get the localized string for a destination
+ *                                option.
+ *   cupsLocalizeDestValue()    - Get the localized string for a destination
+ *                                option+value pair.
+ *   cups_create_localizations() - Create the localizations array for a
+ *                                destination.
+ *   cups_read_strings()        - Read a pair of strings from a .strings file.
+ *   cups_scan_strings()        - Scan a quoted string.
  */
 
 /*
 #include "cups-private.h"
 
 
+/*
+ * Local functions...
+ */
+
+static void    cups_create_localizations(http_t *http, cups_dinfo_t *dinfo);
+static int     cups_read_strings(cups_file_t *fp, char *buffer, size_t bufsize,
+                                 char **id, char **str);
+static char    *cups_scan_strings(char *buffer);
+
+
 /*
  * 'cupsLocalizeDestOption()' - Get the localized string for a destination
  *                              option.
  *
- * The returned string is stored in the localization array and will become
- * invalid if the localization array is deleted.
+ * The returned string is stored in the destination information and will become
+ * invalid if the destination information is deleted.
  *
  * @since CUPS 1.6/OS X 10.8@
  */
@@ -45,7 +59,25 @@ cupsLocalizeDestOption(
     cups_dinfo_t *dinfo,               /* I - Destination information */
     const char   *option)              /* I - Option to localize */
 {
-  return (option);
+  _cups_message_t      key,            /* Search key */
+                       *match;         /* Matching entry */
+
+
+  if (!http || !dest || !dinfo)
+    return (option);
+
+  if (!dinfo->localizations)
+    cups_create_localizations(http, dinfo);
+
+  if (cupsArrayCount(dinfo->localizations) == 0)
+    return (option);
+
+  key.id = (char *)option;
+  if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
+                                                &key)) != NULL)
+    return (match->str);
+  else
+    return (option);
 }
 
 
@@ -53,8 +85,8 @@ cupsLocalizeDestOption(
  * 'cupsLocalizeDestValue()' - Get the localized string for a destination
  *                             option+value pair.
  *
- * The returned string is stored in the localization array and will become
- * invalid if the localization array is deleted.
+ * The returned string is stored in the destination information and will become
+ * invalid if the destination information is deleted.
  *
  * @since CUPS 1.6/OS X 10.8@
  */
@@ -67,10 +99,288 @@ cupsLocalizeDestValue(
     const char   *option,              /* I - Option to localize */
     const char   *value)               /* I - Value to localize */
 {
-  return (value);
+  _cups_message_t      key,            /* Search key */
+                       *match;         /* Matching entry */
+  char                 pair[256];      /* option.value pair */
+
+
+  if (!http || !dest || !dinfo)
+    return (value);
+
+  if (!dinfo->localizations)
+    cups_create_localizations(http, dinfo);
+
+  if (cupsArrayCount(dinfo->localizations) == 0)
+    return (value);
+
+  snprintf(pair, sizeof(pair), "%s.%s", option, value);
+  key.id = pair;
+  if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
+                                                &key)) != NULL)
+    return (match->str);
+  else
+    return (value);
+}
+
+
+/*
+ * 'cups_create_localizations()' - Create the localizations array for a
+ *                                 destination.
+ */
+
+static void
+cups_create_localizations(
+    http_t       *http,                        /* I - Connection to destination */
+    cups_dinfo_t *dinfo)               /* I - Destination informations */
+{
+  http_t               *http2;         /* Connection for strings file */
+  http_status_t                status;         /* Request status */
+  ipp_attribute_t      *attr;          /* "printer-strings-uri" attribute */
+  char                 scheme[32],     /* URI scheme */
+                       userpass[256],  /* Username/password info */
+                       hostname[256],  /* Hostname */
+                       resource[1024], /* Resource */
+                       http_hostname[256],
+                                       /* Hostname of connection */
+                       tempfile[1024]; /* Temporary filename */
+  int                  port;           /* Port number */
+  http_encryption_t    encryption;     /* Encryption to use */
+  cups_file_t          *temp;          /* Temporary file */
+
+
+ /*
+  * Create an empty message catalog...
+  */
+
+  dinfo->localizations = _cupsMessageNew(NULL);
+
+ /*
+  * See if there are any localizations...
+  */
+
+  if ((attr = ippFindAttribute(dinfo->attrs, "printer-strings-uri",
+                               IPP_TAG_URI)) == NULL)
+  {
+   /*
+    * Nope...
+    */
+
+    DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) "
+               "value.");
+    return;                            /* Nope */
+  }
+
+ /*
+  * Pull apart the URI and determine whether we need to try a different
+  * server...
+  */
+
+  if (httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
+                      scheme, sizeof(scheme), userpass, sizeof(userpass),
+                      hostname, sizeof(hostname), &port, resource,
+                      sizeof(resource)) < HTTP_URI_OK)
+  {
+    DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value "
+                  "\"%s\".", attr->values[0].string.text));
+    return;
+  }
+
+  httpGetHostname(http, http_hostname, sizeof(http_hostname));
+
+  if (!_cups_strcasecmp(http_hostname, hostname) &&
+      port == _httpAddrPort(http->hostaddr))
+  {
+   /*
+    * Use the same connection...
+    */
+
+    http2 = http;
+  }
+  else
+  {
+   /*
+    * Connect to the alternate host...
+    */
+
+    if (!strcmp(scheme, "https"))
+      encryption = HTTP_ENCRYPT_ALWAYS;
+    else
+      encryption = HTTP_ENCRYPT_IF_REQUESTED;
+
+    if ((http2 = httpConnectEncrypt(hostname, port, encryption)) == NULL)
+    {
+      DEBUG_printf(("4cups_create_localizations: Unable to connect to "
+                    "%s:%d: %s", hostname, port, cupsLastErrorString()));
+      return;
+    }
+  }
+
+ /*
+  * Get a temporary file...
+  */
+
+  if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
+  {
+    DEBUG_printf(("4cups_create_localizations: Unable to create temporary "
+                  "file: %s", cupsLastErrorString()));
+    if (http2 != http)
+      httpClose(http2);
+    return;
+  }
+
+  status = cupsGetFd(http2, resource, cupsFileNumber(temp));
+
+  DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource,
+                httpStatus(status)));
+
+  if (status == HTTP_OK)
+  {
+   /*
+    * Got the file, read it...
+    */
+
+    char               buffer[8192],   /* Message buffer */
+                       *id,            /* ID string */
+                       *str;           /* Translated message */
+    _cups_message_t    *m;             /* Current message */
+
+    lseek(cupsFileNumber(temp), 0, SEEK_SET);
+
+    while (cups_read_strings(temp, buffer, sizeof(buffer), &id, &str))
+    {
+      if ((m = malloc(sizeof(_cups_message_t))) == NULL)
+        break;
+
+      m->id  = strdup(id);
+      m->str = strdup(str);
+
+      if (m->id && m->str)
+        cupsArrayAdd(dinfo->localizations, m);
+      else
+      {
+        if (m->id)
+          free(m->id);
+
+        if (m->str)
+          free(m->str);
+
+        free(m);
+        break;
+      }
+    }
+  }
+
+  DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
+                cupsArrayCount(dinfo->localizations)));
+
+ /*
+  * Cleanup...
+  */
+
+  unlink(tempfile);
+  cupsFileClose(temp);
+
+  if (http2 != http)
+    httpClose(http2);
+}
+
+
+/*
+ * 'cups_read_strings()' - Read a pair of strings from a .strings file.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+cups_read_strings(cups_file_t *strings,        /* I - .strings file */
+                  char        *buffer, /* I - Line buffer */
+                  size_t      bufsize, /* I - Size of line buffer */
+                 char        **id,     /* O - Pointer to ID string */
+                 char        **str)    /* O - Pointer to translation string */
+{
+  char *bufptr;                        /* Pointer into buffer */
+
+
+  while (cupsFileGets(strings, buffer, bufsize))
+  {
+    if (buffer[0] != '\"')
+      continue;
+
+    *id    = buffer + 1;
+    bufptr = cups_scan_strings(buffer);
+
+    if (*bufptr != '\"')
+      continue;
+
+    *bufptr++ = '\0';
+
+    while (*bufptr && *bufptr != '\"')
+      bufptr ++;
+
+    if (!*bufptr)
+      continue;
+
+    *str   = bufptr + 1;
+    bufptr = cups_scan_strings(bufptr);
+
+    if (*bufptr != '\"')
+      continue;
+
+    *bufptr = '\0';
+
+    return (1);
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'cups_scan_strings()' - Scan a quoted string.
+ */
+
+static char *                          /* O - End of string */
+cups_scan_strings(char *buffer)                /* I - Start of string */
+{
+  char *bufptr;                        /* Pointer into string */
+
+
+  for (bufptr = buffer + 1; *bufptr && *bufptr != '\"'; bufptr ++)
+  {
+    if (*bufptr == '\\')
+    {
+      if (bufptr[1] >= '0' && bufptr[1] <= '3' &&
+         bufptr[2] >= '0' && bufptr[2] <= '7' &&
+         bufptr[3] >= '0' && bufptr[3] <= '7')
+      {
+       /*
+       * Decode \nnn octal escape...
+       */
+
+       *bufptr = ((((bufptr[1] - '0') << 3) | (bufptr[2] - '0')) << 3) |
+                 (bufptr[3] - '0');
+       _cups_strcpy(bufptr + 1, bufptr + 4);
+      }
+      else
+      {
+       /*
+       * Decode \C escape...
+       */
+
+       _cups_strcpy(bufptr, bufptr + 1);
+       if (*bufptr == 'n')
+         *bufptr = '\n';
+       else if (*bufptr == 'r')
+         *bufptr = '\r';
+       else if (*bufptr == 't')
+         *bufptr = '\t';
+      }
+    }
+  }
+
+  return (bufptr);
 }
 
 
+
 /*
  * End of "$Id$".
  */
index 6a2a886b1320075edf232ea48eabfd917dc4642f..cf5b482b4357c7de2a653bd43cd90243e260129f 100644 (file)
@@ -71,6 +71,7 @@ extern const char     *_cupsLangString(cups_lang_t *lang,
 extern void            _cupsMessageFree(cups_array_t *a);
 extern cups_array_t    *_cupsMessageLoad(const char *filename, int unquote);
 extern const char      *_cupsMessageLookup(cups_array_t *a, const char *m);
+extern cups_array_t    *_cupsMessageNew(void *context);
 extern void            _cupsSetLocale(char *argv[]);
 
 
index c536e5aa7d315ba1183bb3399766bba67b7b49e5..58b31e082e8e127fcd73ee3e2e35689c10770f67 100644 (file)
  * Contents:
  *
  *   _cupsAppleLanguage()   - Get the Apple language identifier associated with
- *                            a locale ID.
+ *                           a locale ID.
  *   _cupsEncodingName()    - Return the character encoding name string for the
- *                            given encoding enumeration.
- *   cupsLangDefault()      - Return the default language.
- *   cupsLangEncoding()     - Return the character encoding (us-ascii, etc.) for
- *                            the given language.
- *   cupsLangFlush()        - Flush all language data out of the cache.
- *   cupsLangFree()         - Free language data.
- *   cupsLangGet()          - Get a language.
- *   _cupsLangString()      - Get a message string.
+ *                           given encoding enumeration.
+ *   cupsLangDefault()     - Return the default language.
+ *   cupsLangEncoding()     - Return the character encoding (us-ascii, etc.)
+ *                           for the given language.
+ *   cupsLangFlush()       - Flush all language data out of the cache.
+ *   cupsLangFree()        - Free language data.
+ *   cupsLangGet()         - Get a language.
+ *   _cupsLangString()     - Get a message string.
  *   _cupsMessageFree()     - Free a messages array.
  *   _cupsMessageLoad()     - Load a .po file into a messages array.
  *   _cupsMessageLookup()   - Lookup a message string.
+ *   _cupsMessageNew()     - Make a new message catalog array.
  *   appleLangDefault()     - Get the default locale string.
  *   appleMessageLoad()     - Load a message catalog from a localizable bundle.
  *   cups_cache_lookup()    - Lookup a language in the cache...
  *   cups_message_compare() - Compare two messages.
  *   cups_message_free()    - Free a message.
  *   cups_message_load()    - Load the message catalog for a language.
- *   cups_unquote()         - Unquote characters in strings...
+ *   cups_unquote()        - Unquote characters in strings...
  */
 
 /*
@@ -854,10 +855,7 @@ _cupsMessageLoad(const char *filename,     /* I - Message catalog to load */
   * Create an array to hold the messages...
   */
 
-  if ((a = cupsArrayNew3((cups_array_func_t)cups_message_compare, NULL,
-                         (cups_ahash_func_t)NULL, 0,
-                        (cups_acopy_func_t)NULL,
-                        (cups_afree_func_t)cups_message_free)) == NULL)
+  if ((a = _cupsMessageNew(NULL)) == NULL)
   {
     DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!");
     return (NULL);
@@ -1140,6 +1138,20 @@ _cupsMessageLookup(cups_array_t *a,      /* I - Message array */
 }
 
 
+/*
+ * '_cupsMessageNew()' - Make a new message catalog 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));
+}
+
+
 #ifdef __APPLE__
 /*
  * 'appleLangDefault()' - Get the default locale string.
@@ -1374,10 +1386,7 @@ appleMessageLoad(const char *locale)     /* I - Locale ID */
   * plist as the user data.
   */
 
-  return (cupsArrayNew3((cups_array_func_t)cups_message_compare, (void *)plist,
-                        (cups_ahash_func_t)NULL, 0,
-                       (cups_acopy_func_t)NULL,
-                       (cups_afree_func_t)cups_message_free));
+  return (_cupsMessageNew((void *)plist));
 }
 #  endif /* CUPS_BUNDLEDIR */
 #endif /* __APPLE__ */