cups/dest-localization.c: Move .strings file loader to language.c.
cups/language-private.h: Add load options for _cupsMessageLoad.
cups/language.c: Move .strings file loader to this file.
cups/ppd-cache.c: Save printer-strings-uri value and load the strings file for m
edia-type
cups/ppd-private.h: Bump cache version and add strings_uri.
locale/checkpo.c: Use _cupsMessageLoad for .strings files.
- Added label markup to checkbox and radio button controls in the web interface
templates (Issue #5161)
- Fixed group validation on OpenBSD (Issue #5166)
+- IPP Everywhere PPDs now include localizations of printer-specific media types,
+ when available (Issue #5168)
/*
* Destination localization support for CUPS.
*
- * Copyright 2012-2014 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
*/
*/
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);
/*
if (!dinfo->localizations)
cups_create_localizations(http, dinfo);
- key.id = size->media;
+ key.msg = size->media;
if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations, &key)) != NULL)
{
DEBUG_printf(("1cupsLocalizeDestMedia: Returning \"%s\".", match->str));
if ((match = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
return (NULL);
- match->id = strdup(size->media);
+ match->msg = strdup(size->media);
match->str = strdup(name);
cupsArrayAdd(dinfo->localizations, match);
if (!dinfo->localizations)
cups_create_localizations(http, dinfo);
- key.id = (char *)option;
- if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
- &key)) != NULL)
+ key.msg = (char *)option;
+ if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations, &key)) != NULL)
return (match->str);
else if ((localized = _cupsLangString(cupsLangDefault(), option)) != NULL)
return (localized);
cups_create_localizations(http, dinfo);
snprintf(pair, sizeof(pair), "%s.%s", option, value);
- key.id = pair;
- if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
- &key)) != NULL)
+ key.msg = pair;
+ if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations, &key)) != NULL)
return (match->str);
else if ((localized = _cupsLangString(cupsLangDefault(), pair)) != NULL && strcmp(localized, pair))
return (localized);
cups_file_t *temp; /* Temporary file */
- /*
- * Create an empty message catalog...
- */
-
- dinfo->localizations = _cupsMessageNew(NULL);
-
/*
* See if there are any localizations...
*/
IPP_TAG_URI)) == NULL)
{
/*
- * Nope...
+ * Nope, create an empty message catalog...
*/
- DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) "
- "value.");
- return; /* Nope */
+ dinfo->localizations = _cupsMessageNew(NULL);
+ DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) value.");
+ return;
}
/*
hostname, sizeof(hostname), &port, resource,
sizeof(resource)) < HTTP_URI_STATUS_OK)
{
- DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value "
- "\"%s\".", attr->values[0].string.text));
+ dinfo->localizations = _cupsMessageNew(NULL);
+ DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value \"%s\".", attr->values[0].string.text));
return;
}
}
status = cupsGetFd(http2, resource, cupsFileNumber(temp));
+ cupsFileClose(temp);
- DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource,
- httpStatus(status)));
+ DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource, httpStatus(status)));
if (status == HTTP_STATUS_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;
- }
- }
+ dinfo->localizations = _cupsMessageLoad(tempfile, _CUPS_MESSAGE_STRINGS);
}
DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
*/
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 = (char)(((((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);
-}
# define _(x) x
+/*
+ * Constants...
+ */
+
+# define _CUPS_MESSAGE_UNQUOTE 1 /* Unescape \foo in strings? */
+# define _CUPS_MESSAGE_STRINGS 2 /* Message file is in Apple .strings format */
+
+
/*
* Types...
*/
typedef struct _cups_message_s /**** Message catalog entry ****/
{
- char *id, /* Original string */
+ char *msg, /* Original string */
*str; /* Localized string */
} _cups_message_t;
extern const char *_cupsLangString(cups_lang_t *lang,
const char *message);
extern void _cupsMessageFree(cups_array_t *a);
-extern cups_array_t *_cupsMessageLoad(const char *filename, int unquote);
+extern cups_array_t *_cupsMessageLoad(const char *filename, int flags);
extern const char *_cupsMessageLookup(cups_array_t *a, const char *m);
extern cups_array_t *_cupsMessageNew(void *context);
extern void _cupsSetLocale(char *argv[]);
# define CF_RETURNS_RETAINED
# endif /* __has_feature(attribute_cf_returns_retained) */
# endif /* !CF_RETURNED_RETAINED */
-static cups_array_t *appleMessageLoad(const char *locale)
- CF_RETURNS_RETAINED;
+static cups_array_t *appleMessageLoad(const char *locale) CF_RETURNS_RETAINED;
# endif /* CUPS_BUNDLEDIR */
#endif /* __APPLE__ */
-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);
+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);
static void cups_message_free(_cups_message_t *m);
static void cups_message_load(cups_lang_t *lang);
+static int cups_read_strings(cups_file_t *fp, int flags, cups_array_t *a);
static void cups_unquote(char *d, const char *s);
/*
- * '_cupsMessageLoad()' - Load a .po file into a messages array.
+ * '_cupsMessageLoad()' - Load a .po or .strings file into a messages array.
*/
cups_array_t * /* O - New message array */
_cupsMessageLoad(const char *filename, /* I - Message catalog to load */
- int unquote) /* I - Unescape \foo in strings? */
+ int flags) /* I - Load flags */
{
cups_file_t *fp; /* Message file */
cups_array_t *a; /* Message array */
return (a);
}
- /*
- * Read messages from the catalog file until EOF...
- *
- * The format is the GNU gettext .po format, which is fairly simple:
- *
- * msgid "some text"
- * msgstr "localized text"
- *
- * The ID and localized text can span multiple lines using the form:
- *
- * msgid ""
- * "some long text"
- * msgstr ""
- * "localized text spanning "
- * "multiple lines"
- */
-
- m = NULL;
-
- while (cupsFileGets(fp, s, sizeof(s)) != NULL)
+ if (flags & _CUPS_MESSAGE_STRINGS)
+ {
+ while (cups_read_strings(fp, flags, a));
+ }
+ else
{
/*
- * Skip blank and comment lines...
- */
-
- if (s[0] == '#' || !s[0])
- continue;
-
- /*
- * Strip the trailing quote...
+ * Read messages from the catalog file until EOF...
+ *
+ * The format is the GNU gettext .po format, which is fairly simple:
+ *
+ * msgid "some text"
+ * msgstr "localized text"
+ *
+ * The ID and localized text can span multiple lines using the form:
+ *
+ * msgid ""
+ * "some long text"
+ * msgstr ""
+ * "localized text spanning "
+ * "multiple lines"
*/
- if ((ptr = strrchr(s, '\"')) == NULL)
- continue;
-
- *ptr = '\0';
-
- /*
- * Find start of value...
- */
+ m = NULL;
- if ((ptr = strchr(s, '\"')) == NULL)
- continue;
+ while (cupsFileGets(fp, s, sizeof(s)) != NULL)
+ {
+ /*
+ * Skip blank and comment lines...
+ */
- ptr ++;
+ if (s[0] == '#' || !s[0])
+ continue;
- /*
- * Unquote the text...
- */
+ /*
+ * Strip the trailing quote...
+ */
- if (unquote)
- cups_unquote(ptr, ptr);
+ if ((ptr = strrchr(s, '\"')) == NULL)
+ continue;
- /*
- * Create or add to a message...
- */
+ *ptr = '\0';
- if (!strncmp(s, "msgid", 5))
- {
/*
- * Add previous message as needed...
+ * Find start of value...
*/
- if (m)
- {
- if (m->str && m->str[0])
- {
- cupsArrayAdd(a, m);
- }
- else
- {
- /*
- * Translation is empty, don't add it... (STR #4033)
- */
-
- free(m->id);
- if (m->str)
- free(m->str);
- free(m);
- }
- }
+ if ((ptr = strchr(s, '\"')) == NULL)
+ continue;
+
+ ptr ++;
/*
- * Create a new message with the given msgid string...
+ * Unquote the text...
*/
- if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
- {
- cupsFileClose(fp);
- return (a);
- }
+ if (flags & _CUPS_MESSAGE_UNQUOTE)
+ cups_unquote(ptr, ptr);
- if ((m->id = strdup(ptr)) == NULL)
- {
- free(m);
- cupsFileClose(fp);
- return (a);
- }
- }
- else if (s[0] == '\"' && m)
- {
/*
- * Append to current string...
+ * Create or add to a message...
*/
- length = strlen(m->str ? m->str : m->id);
- ptrlen = strlen(ptr);
-
- if ((temp = realloc(m->str ? m->str : m->id, length + ptrlen + 1)) == NULL)
+ if (!strncmp(s, "msgid", 5))
{
- if (m->str)
- free(m->str);
- free(m->id);
- free(m);
+ /*
+ * Add previous message as needed...
+ */
- cupsFileClose(fp);
- return (a);
- }
+ if (m)
+ {
+ if (m->str && m->str[0])
+ {
+ 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)
- {
/*
- * Copy the new portion to the end of the msgstr string - safe
- * to use memcpy because the buffer is allocated to the correct
- * size...
+ * Create a new message with the given msgid string...
*/
- m->str = temp;
+ if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
+ break;
- memcpy(m->str + length, ptr, ptrlen + 1);
+ if ((m->msg = strdup(ptr)) == NULL)
+ {
+ free(m);
+ m = NULL;
+ break;
+ }
}
- else
+ else if (s[0] == '\"' && m)
{
/*
- * Copy the new portion to the end of the msgid string - safe
- * to use memcpy because the buffer is allocated to the correct
- * size...
+ * Append to current string...
*/
- m->id = temp;
+ length = strlen(m->str ? m->str : m->msg);
+ ptrlen = strlen(ptr);
- memcpy(m->id + length, ptr, ptrlen + 1);
- }
- }
- else if (!strncmp(s, "msgstr", 6) && m)
- {
- /*
- * Set the string...
- */
+ 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 = strdup(ptr)) == NULL)
+ 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);
+ }
+ 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);
+ }
+ }
+ else if (!strncmp(s, "msgstr", 6) && m)
{
- free(m->id);
- free(m);
+ /*
+ * Set the string...
+ */
- cupsFileClose(fp);
- return (a);
+ if ((m->str = strdup(ptr)) == NULL)
+ {
+ free(m->msg);
+ free(m);
+ m = NULL;
+ break;
+ }
}
}
- }
- /*
- * Add the last message string to the array as needed...
- */
+ /*
+ * Add the last message string to the array as needed...
+ */
- if (m)
- {
- if (m->str && m->str[0])
+ if (m)
{
- cupsArrayAdd(a, m);
- }
- else
- {
- /*
- * Translation is empty, don't add it... (STR #4033)
- */
+ if (m->str && m->str[0])
+ {
+ cupsArrayAdd(a, m);
+ }
+ else
+ {
+ /*
+ * Translation is empty, don't add it... (STR #4033)
+ */
- free(m->id);
- if (m->str)
- free(m->str);
- free(m);
+ free(m->msg);
+ if (m->str)
+ free(m->str);
+ free(m);
+ }
}
}
cupsFileClose(fp);
- DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...",
- cupsArrayCount(a)));
+ DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...", cupsArrayCount(a)));
return (a);
}
* then return the message that was passed to us...
*/
- key.id = (char *)m;
- match = (_cups_message_t *)cupsArrayFind(a, &key);
+ key.msg = (char *)m;
+ match = (_cups_message_t *)cupsArrayFind(a, &key);
#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
if (!match && cupsArrayUserData(a))
CFStringRef cfm, /* Message as a CF string */
cfstr; /* Localized text as a CF string */
- dict = (CFDictionaryRef)cupsArrayUserData(a);
- cfm = CFStringCreateWithCString(kCFAllocatorDefault, m,
- kCFStringEncodingUTF8);
- match = calloc(1, sizeof(_cups_message_t));
- match->id = strdup(m);
- cfstr = cfm ? CFDictionaryGetValue(dict, cfm) : NULL;
+ dict = (CFDictionaryRef)cupsArrayUserData(a);
+ cfm = CFStringCreateWithCString(kCFAllocatorDefault, m, kCFStringEncodingUTF8);
+ match = calloc(1, sizeof(_cups_message_t));
+ match->msg = strdup(m);
+ cfstr = cfm ? CFDictionaryGetValue(dict, cfm) : NULL;
if (cfstr)
{
CFStringGetCString(cfstr, buffer, sizeof(buffer), kCFStringEncodingUTF8);
match->str = strdup(buffer);
- DEBUG_printf(("1_cupsMessageLookup: Found \"%s\" as \"%s\"...",
- m, buffer));
+ DEBUG_printf(("1_cupsMessageLookup: Found \"%s\" as \"%s\"...", m, buffer));
}
else
{
_cups_message_t *m1, /* I - First message */
_cups_message_t *m2) /* I - Second message */
{
- return (strcmp(m1->id, m2->id));
+ return (strcmp(m1->msg, m2->msg));
}
static void
cups_message_free(_cups_message_t *m) /* I - Message */
{
- if (m->id)
- free(m->id);
+ if (m->msg)
+ free(m->msg);
if (m->str)
free(m->str);
* Read the strings from the file...
*/
- lang->strings = _cupsMessageLoad(filename, 1);
+ lang->strings = _cupsMessageLoad(filename, _CUPS_MESSAGE_UNQUOTE);
#endif /* __APPLE__ && CUPS_BUNDLEDIR */
}
+/*
+ * '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 *fp, /* I - .strings file */
+ int flags, /* I - CUPS_MESSAGE_xxx flags */
+ cups_array_t *a) /* I - Message catalog array */
+{
+ char buffer[8192], /* Line buffer */
+ *bufptr, /* Pointer into buffer */
+ *msg, /* Pointer to start of message */
+ *str; /* Pointer to start of translation string */
+ _cups_message_t *m; /* New message */
+
+
+ while (cupsFileGets(fp, buffer, sizeof(buffer)))
+ {
+ /*
+ * Skip any line (comments, blanks, etc.) that isn't:
+ *
+ * "message" = "translation";
+ */
+
+ for (bufptr = buffer; *bufptr && isspace(*bufptr & 255); bufptr ++);
+
+ if (*bufptr != '\"')
+ continue;
+
+ /*
+ * Find the end of the message...
+ */
+
+ bufptr ++;
+ for (msg = bufptr; *bufptr && *bufptr != '\"'; bufptr ++)
+ if (*bufptr == '\\' && bufptr[1])
+ bufptr ++;
+
+ if (!*bufptr)
+ continue;
+
+ *bufptr++ = '\0';
+
+ if (flags & _CUPS_MESSAGE_UNQUOTE)
+ cups_unquote(msg, msg);
+
+ /*
+ * Find the start of the translation...
+ */
+
+ while (*bufptr && isspace(*bufptr & 255))
+ bufptr ++;
+
+ if (*bufptr != '=')
+ continue;
+
+ bufptr ++;
+ while (*bufptr && isspace(*bufptr & 255))
+ bufptr ++;
+
+ if (*bufptr != '\"')
+ continue;
+
+ /*
+ * Find the end of the translation...
+ */
+
+ bufptr ++;
+ for (str = bufptr; *bufptr && *bufptr != '\"'; bufptr ++)
+ if (*bufptr == '\\' && bufptr[1])
+ bufptr ++;
+
+ if (!*bufptr)
+ continue;
+
+ *bufptr++ = '\0';
+
+ if (flags & _CUPS_MESSAGE_UNQUOTE)
+ cups_unquote(str, str);
+
+ /*
+ * 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);
+
+ if (m->msg && m->str)
+ {
+ cupsArrayAdd(a, m);
+ }
+ else
+ {
+ if (m->msg)
+ free(m->msg);
+
+ if (m->str)
+ free(m->str);
+
+ free(m);
+ break;
+ }
+
+ return (1);
+ }
+
+ /*
+ * No more strings...
+ */
+
+ return (0);
+}
+
+
/*
* 'cups_unquote()' - Unquote characters in strings...
*/
* Local functions...
*/
+static int cups_get_url(http_t **http, const char *url, char *name, size_t namesize);
static void pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value);
static int pwg_compare_finishings(_pwg_finishings_t *a,
_pwg_finishings_t *b);
else
pc->mandatory = _cupsArrayNewStrings(value, ' ');
}
+ else if (!_cups_strcasecmp(line, "StringsURI"))
+ pc->strings_uri = _cupsStrAlloc(value);
else if (!_cups_strcasecmp(line, "SupportFile"))
{
if (!pc->support_files)
if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
+ /*
+ * Strings (remote) file...
+ */
+
+ if ((ppd_attr = ppdFindAttr(ppd, "cupsStringsURI", NULL)) != NULL)
+ pc->strings_uri = _cupsStrAlloc(ppd_attr->value);
+
/*
* Support files...
*/
value = (char *)cupsArrayNext(pc->mandatory))
cupsFilePutConf(fp, "Mandatory", value);
+ /*
+ * (Remote) strings file...
+ */
+
+ if (pc->strings_uri)
+ cupsFilePutConf(fp, "StringsURI", pc->strings_uri);
+
/*
* Support files...
*/
/* Array of resolution indices */
cups_lang_t *lang = cupsLangDefault();
/* Localization info */
+ cups_array_t *strings = NULL;/* Printer strings file */
struct lconv *loc = localeconv();
/* Locale data */
static const char * const finishings[][2] =
cupsFilePrintf(fp, "*cupsVersion: %d.%d\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR);
cupsFilePuts(fp, "*cupsSNMPSupplies: False\n");
- cupsFilePuts(fp, "*cupsLanguages: \"en\"\n");
+ cupsFilePrintf(fp, "*cupsLanguages: \"%s\"\n", lang->language);
+
+ if ((attr = ippFindAttribute(response, "printer-more-info", IPP_TAG_URI)) != NULL)
+ cupsFilePrintf(fp, "*APSupplies: \"%s\"\n", ippGetString(attr, 0, NULL));
+
+ if ((attr = ippFindAttribute(response, "printer-charge-info-uri", IPP_TAG_URI)) != NULL)
+ cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL));
+
+ if ((attr = ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI)) != NULL)
+ {
+ http_t *http = NULL; /* Connection to printer */
+ char stringsfile[1024]; /* Temporary strings file */
+
+ if (cups_get_url(&http, ippGetString(attr, 0, NULL), stringsfile, sizeof(stringsfile)))
+ {
+ cupsFilePrintf(fp, "*cupsStringsURI: \"%s\"\n", ippGetString(attr, 0, NULL));
+
+ strings = _cupsMessageLoad(stringsfile, _CUPS_MESSAGE_STRINGS | _CUPS_MESSAGE_UNQUOTE);
+
+ unlink(stringsfile);
+ }
+
+ if (http)
+ httpClose(http);
+ }
/*
* Filters...
if (j < (int)(sizeof(media_types) / sizeof(media_types[0])))
cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, _cupsLangString(lang, media_types[j][1]), ppdname);
else
- cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, keyword, ppdname);
+ {
+ char msg[256]; /* Message key */
+ const char *str; /* Localized string */
+
+ snprintf(msg, sizeof(msg), "media-type.%s", keyword);
+ if ((str = _cupsMessageLookup(strings, msg)) == msg)
+ str = keyword;
+
+ cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, str, ppdname);
+ }
}
cupsFilePuts(fp, "*CloseUI: *MediaType\n");
}
}
+/*
+ * 'cups_get_url()' - Get a copy of the file at the given URL.
+ */
+
+static int /* O - 1 on success, 0 on failure */
+cups_get_url(http_t **http, /* IO - Current HTTP connection */
+ const char *url, /* I - URL to get */
+ char *name, /* I - Temporary filename */
+ size_t namesize) /* I - Size of temporary filename buffer */
+{
+ char scheme[32], /* URL scheme */
+ userpass[256], /* URL username:password */
+ host[256], /* URL host */
+ curhost[256], /* Current host */
+ resource[256]; /* URL resource */
+ int port; /* URL port */
+ http_encryption_t encryption; /* Type of encryption to use */
+ http_status_t status; /* Status of GET request */
+ int fd; /* Temporary file */
+
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, url, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ return (0);
+
+ if (port == 443 || !strcmp(scheme, "https"))
+ encryption = HTTP_ENCRYPTION_ALWAYS;
+ else
+ encryption = HTTP_ENCRYPTION_IF_REQUESTED;
+
+ if (!*http || strcasecmp(host, httpGetHostname(*http, curhost, sizeof(curhost))) || httpAddrPort(httpGetAddress(*http)) != port)
+ {
+ httpClose(*http);
+ *http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 5000, NULL);
+ }
+
+ if (!*http)
+ return (0);
+
+ if ((fd = cupsTempFd(name, (int)namesize)) < 0)
+ return (0);
+
+ status = cupsGetFd(*http, resource, fd);
+
+ close(fd);
+
+ if (status != HTTP_STATUS_OK)
+ {
+ unlink(name);
+ *name = '\0';
+ return (0);
+ }
+
+ return (1);
+}
+
+
/*
* 'pwg_add_finishing()' - Add a finishings value.
*/
* Copyright 2007-2017 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.
*/
#ifndef _CUPS_PPD_PRIVATE_H_
* Constants...
*/
-# define _PPD_CACHE_VERSION 8 /* Version number in cache file */
+# define _PPD_CACHE_VERSION 9 /* Version number in cache file */
/*
char *password; /* cupsJobPassword value */
cups_array_t *mandatory; /* cupsMandatory value */
char *charge_info_uri; /* cupsChargeInfoURI value */
+ char *strings_uri; /* cupsStringsURI value */
cups_array_t *support_files; /* Support files - ICC profiles, etc. */
};
static char *abbreviate(const char *s, char *buf, int bufsize);
static cups_array_t *collect_formats(const char *id);
-static cups_array_t *cups_load_strings(const char *filename);
-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);
static void free_formats(cups_array_t *fmts);
*/
if (strstr(argv[i], ".strings"))
- po = cups_load_strings(argv[i]);
+ po = _cupsMessageLoad(argv[i], _CUPS_MESSAGE_STRINGS | _CUPS_MESSAGE_UNQUOTE);
else
- po = _cupsMessageLoad(argv[i], 1);
+ po = _cupsMessageLoad(argv[i], _CUPS_MESSAGE_UNQUOTE);
if (!po)
{
* Make sure filter message prefixes are not translated...
*/
- if (!strncmp(msg->id, "ALERT:", 6) || !strncmp(msg->id, "CRIT:", 5) ||
- !strncmp(msg->id, "DEBUG:", 6) || !strncmp(msg->id, "DEBUG2:", 7) ||
- !strncmp(msg->id, "EMERG:", 6) || !strncmp(msg->id, "ERROR:", 6) ||
- !strncmp(msg->id, "INFO:", 5) || !strncmp(msg->id, "NOTICE:", 7) ||
- !strncmp(msg->id, "WARNING:", 8))
+ if (!strncmp(msg->msg, "ALERT:", 6) || !strncmp(msg->msg, "CRIT:", 5) ||
+ !strncmp(msg->msg, "DEBUG:", 6) || !strncmp(msg->msg, "DEBUG2:", 7) ||
+ !strncmp(msg->msg, "EMERG:", 6) || !strncmp(msg->msg, "ERROR:", 6) ||
+ !strncmp(msg->msg, "INFO:", 5) || !strncmp(msg->msg, "NOTICE:", 7) ||
+ !strncmp(msg->msg, "WARNING:", 8))
{
if (pass)
{
}
printf(" Bad prefix on filter message \"%s\"\n",
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
}
- idfmt = msg->id + strlen(msg->id) - 1;
- if (idfmt >= msg->id && *idfmt == '\n')
+ idfmt = msg->msg + strlen(msg->msg) - 1;
+ if (idfmt >= msg->msg && *idfmt == '\n')
{
if (pass)
{
}
printf(" Trailing newline in message \"%s\"\n",
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
}
- for (; idfmt >= msg->id; idfmt --)
+ for (; idfmt >= msg->msg; idfmt --)
if (!isspace(*idfmt & 255))
break;
- if (idfmt >= msg->id && *idfmt == '!')
+ if (idfmt >= msg->msg && *idfmt == '!')
{
if (pass)
{
}
printf(" Exclamation in message \"%s\"\n",
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
}
- if ((idfmt - 2) >= msg->id && !strncmp(idfmt - 2, "...", 3))
+ if ((idfmt - 2) >= msg->msg && !strncmp(idfmt - 2, "...", 3))
{
if (pass)
{
}
printf(" Ellipsis in message \"%s\"\n",
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
}
untranslated ++;
continue;
}
- else if (strchr(msg->id, '%'))
+ else if (strchr(msg->msg, '%'))
{
- idfmts = collect_formats(msg->id);
+ idfmts = collect_formats(msg->msg);
strfmts = collect_formats(msg->str);
fmtidx = 0;
printf(" Bad translation string \"%s\"\n for \"%s\"\n",
abbreviate(msg->str, strbuf, sizeof(strbuf)),
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
fputs(" Translation formats:", stdout);
for (strfmt = (char *)cupsArrayFirst(strfmts);
strfmt;
printf(" Bad escape \\%c in filter message \"%s\"\n"
" for \"%s\"\n", strfmt[1],
abbreviate(msg->str, strbuf, sizeof(strbuf)),
- abbreviate(msg->id, idbuf, sizeof(idbuf)));
+ abbreviate(msg->msg, idbuf, sizeof(idbuf)));
break;
}
}
}
-/*
- * 'cups_load_strings()' - Load a .strings file into a _cups_msg_t array.
- */
-
-static cups_array_t * /* O - CUPS array of _cups_msg_t values */
-cups_load_strings(const char *filename) /* I - File to load */
-{
- cups_file_t *fp; /* .strings file */
- cups_array_t *po; /* Localization array */
- _cups_message_t *m; /* Localization message */
- char buffer[8192], /* Message buffer */
- *id, /* ID string */
- *str; /* Translated message */
-
-
- if ((fp = cupsFileOpen(filename, "r")) == NULL)
- return (NULL);
-
- po = _cupsMessageNew(NULL);
-
- while (cups_read_strings(fp, 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(po, m);
- else
- {
- if (m->id)
- free(m->id);
-
- if (m->str)
- free(m->str);
-
- free(m);
-
- cupsArrayDelete(po);
- po = NULL;
- break;
- }
- }
-
- cupsFileClose(fp);
-
- return (po);
-}
-
-
-/*
- * '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 = (char)(((((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);
-}
-
-
/*
* 'free_formats()' - Free all of the format strings.
*/