4 * Destination localization support for CUPS.
6 * Copyright 2012-2014 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * Include necessary headers...
21 #include "cups-private.h"
28 static void cups_create_localizations(http_t
*http
, cups_dinfo_t
*dinfo
);
29 static int cups_read_strings(cups_file_t
*fp
, char *buffer
, size_t bufsize
,
30 char **id
, char **str
);
31 static char *cups_scan_strings(char *buffer
);
35 * 'cupsLocalizeDestOption()' - Get the localized string for a destination
38 * The returned string is stored in the destination information and will become
39 * invalid if the destination information is deleted.
41 * @since CUPS 1.6/OS X 10.8@
44 const char * /* O - Localized string */
45 cupsLocalizeDestOption(
46 http_t
*http
, /* I - Connection to destination */
47 cups_dest_t
*dest
, /* I - Destination */
48 cups_dinfo_t
*dinfo
, /* I - Destination information */
49 const char *option
) /* I - Option to localize */
51 _cups_message_t key
, /* Search key */
52 *match
; /* Matching entry */
55 if (!http
|| !dest
|| !dinfo
)
58 if (!dinfo
->localizations
)
59 cups_create_localizations(http
, dinfo
);
61 if (cupsArrayCount(dinfo
->localizations
) == 0)
64 key
.id
= (char *)option
;
65 if ((match
= (_cups_message_t
*)cupsArrayFind(dinfo
->localizations
,
74 * 'cupsLocalizeDestValue()' - Get the localized string for a destination
77 * The returned string is stored in the destination information and will become
78 * invalid if the destination information is deleted.
80 * @since CUPS 1.6/OS X 10.8@
83 const char * /* O - Localized string */
84 cupsLocalizeDestValue(
85 http_t
*http
, /* I - Connection to destination */
86 cups_dest_t
*dest
, /* I - Destination */
87 cups_dinfo_t
*dinfo
, /* I - Destination information */
88 const char *option
, /* I - Option to localize */
89 const char *value
) /* I - Value to localize */
91 _cups_message_t key
, /* Search key */
92 *match
; /* Matching entry */
93 char pair
[256]; /* option.value pair */
96 if (!http
|| !dest
|| !dinfo
)
99 if (!dinfo
->localizations
)
100 cups_create_localizations(http
, dinfo
);
102 if (cupsArrayCount(dinfo
->localizations
) == 0)
105 snprintf(pair
, sizeof(pair
), "%s.%s", option
, value
);
107 if ((match
= (_cups_message_t
*)cupsArrayFind(dinfo
->localizations
,
116 * 'cups_create_localizations()' - Create the localizations array for a
121 cups_create_localizations(
122 http_t
*http
, /* I - Connection to destination */
123 cups_dinfo_t
*dinfo
) /* I - Destination informations */
125 http_t
*http2
; /* Connection for strings file */
126 http_status_t status
; /* Request status */
127 ipp_attribute_t
*attr
; /* "printer-strings-uri" attribute */
128 char scheme
[32], /* URI scheme */
129 userpass
[256], /* Username/password info */
130 hostname
[256], /* Hostname */
131 resource
[1024], /* Resource */
133 /* Hostname of connection */
134 tempfile
[1024]; /* Temporary filename */
135 int port
; /* Port number */
136 http_encryption_t encryption
; /* Encryption to use */
137 cups_file_t
*temp
; /* Temporary file */
141 * Create an empty message catalog...
144 dinfo
->localizations
= _cupsMessageNew(NULL
);
147 * See if there are any localizations...
150 if ((attr
= ippFindAttribute(dinfo
->attrs
, "printer-strings-uri",
151 IPP_TAG_URI
)) == NULL
)
157 DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) "
163 * Pull apart the URI and determine whether we need to try a different
167 if (httpSeparateURI(HTTP_URI_CODING_ALL
, attr
->values
[0].string
.text
,
168 scheme
, sizeof(scheme
), userpass
, sizeof(userpass
),
169 hostname
, sizeof(hostname
), &port
, resource
,
170 sizeof(resource
)) < HTTP_URI_STATUS_OK
)
172 DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value "
173 "\"%s\".", attr
->values
[0].string
.text
));
177 httpGetHostname(http
, http_hostname
, sizeof(http_hostname
));
179 if (!_cups_strcasecmp(http_hostname
, hostname
) &&
180 port
== httpAddrPort(http
->hostaddr
))
183 * Use the same connection...
191 * Connect to the alternate host...
194 if (!strcmp(scheme
, "https"))
195 encryption
= HTTP_ENCRYPTION_ALWAYS
;
197 encryption
= HTTP_ENCRYPTION_IF_REQUESTED
;
199 if ((http2
= httpConnect2(hostname
, port
, NULL
, AF_UNSPEC
, encryption
, 1,
200 30000, NULL
)) == NULL
)
202 DEBUG_printf(("4cups_create_localizations: Unable to connect to "
203 "%s:%d: %s", hostname
, port
, cupsLastErrorString()));
209 * Get a temporary file...
212 if ((temp
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
214 DEBUG_printf(("4cups_create_localizations: Unable to create temporary "
215 "file: %s", cupsLastErrorString()));
221 status
= cupsGetFd(http2
, resource
, cupsFileNumber(temp
));
223 DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource
,
224 httpStatus(status
)));
226 if (status
== HTTP_STATUS_OK
)
229 * Got the file, read it...
232 char buffer
[8192], /* Message buffer */
234 *str
; /* Translated message */
235 _cups_message_t
*m
; /* Current message */
237 lseek(cupsFileNumber(temp
), 0, SEEK_SET
);
239 while (cups_read_strings(temp
, buffer
, sizeof(buffer
), &id
, &str
))
241 if ((m
= malloc(sizeof(_cups_message_t
))) == NULL
)
245 m
->str
= strdup(str
);
248 cupsArrayAdd(dinfo
->localizations
, m
);
263 DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
264 cupsArrayCount(dinfo
->localizations
)));
279 * 'cups_read_strings()' - Read a pair of strings from a .strings file.
282 static int /* O - 1 on success, 0 on failure */
283 cups_read_strings(cups_file_t
*strings
, /* I - .strings file */
284 char *buffer
, /* I - Line buffer */
285 size_t bufsize
, /* I - Size of line buffer */
286 char **id
, /* O - Pointer to ID string */
287 char **str
) /* O - Pointer to translation string */
289 char *bufptr
; /* Pointer into buffer */
292 while (cupsFileGets(strings
, buffer
, bufsize
))
294 if (buffer
[0] != '\"')
298 bufptr
= cups_scan_strings(buffer
);
305 while (*bufptr
&& *bufptr
!= '\"')
312 bufptr
= cups_scan_strings(bufptr
);
327 * 'cups_scan_strings()' - Scan a quoted string.
330 static char * /* O - End of string */
331 cups_scan_strings(char *buffer
) /* I - Start of string */
333 char *bufptr
; /* Pointer into string */
336 for (bufptr
= buffer
+ 1; *bufptr
&& *bufptr
!= '\"'; bufptr
++)
340 if (bufptr
[1] >= '0' && bufptr
[1] <= '3' &&
341 bufptr
[2] >= '0' && bufptr
[2] <= '7' &&
342 bufptr
[3] >= '0' && bufptr
[3] <= '7')
345 * Decode \nnn octal escape...
348 *bufptr
= (char)(((((bufptr
[1] - '0') << 3) | (bufptr
[2] - '0')) << 3) | (bufptr
[3] - '0'));
349 _cups_strcpy(bufptr
+ 1, bufptr
+ 4);
354 * Decode \C escape...
357 _cups_strcpy(bufptr
, bufptr
+ 1);
360 else if (*bufptr
== 'r')
362 else if (*bufptr
== 't')