2 * Destination localization support for CUPS.
4 * Copyright 2012-2017 by Apple Inc.
6 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
10 * Include necessary headers...
13 #include "cups-private.h"
20 static void cups_create_localizations(http_t
*http
, cups_dinfo_t
*dinfo
);
24 * 'cupsLocalizeDestMedia()' - Get the localized string for a destination media
27 * The returned string is stored in the destination information and will become
28 * invalid if the destination information is deleted.
30 * @since CUPS 2.0/macOS 10.10@
33 const char * /* O - Localized string */
34 cupsLocalizeDestMedia(
35 http_t
*http
, /* I - Connection to destination */
36 cups_dest_t
*dest
, /* I - Destination */
37 cups_dinfo_t
*dinfo
, /* I - Destination information */
38 unsigned flags
, /* I - Media flags */
39 cups_size_t
*size
) /* I - Media size */
41 cups_lang_t
*lang
; /* Standard localizations */
42 _cups_message_t key
, /* Search key */
43 *match
; /* Matching entry */
44 pwg_media_t
*pwg
; /* PWG media information */
45 cups_array_t
*db
; /* Media database */
46 _cups_media_db_t
*mdb
; /* Media database entry */
47 char name
[1024], /* Size name */
48 temp
[256]; /* Temporary string */
49 const char *lsize
, /* Localized media size */
50 *lsource
, /* Localized media source */
51 *ltype
; /* Localized media type */
54 DEBUG_printf(("cupsLocalizeDestMedia(http=%p, dest=%p, dinfo=%p, flags=%x, size=%p(\"%s\"))", (void *)http
, (void *)dest
, (void *)dinfo
, flags
, (void *)size
, size
? size
->media
: "(null)"));
57 * Range check input...
60 if (!http
|| !dest
|| !dinfo
|| !size
)
62 DEBUG_puts("1cupsLocalizeDestMedia: Returning NULL.");
63 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
68 * See if the localization is cached...
71 if (!dinfo
->localizations
)
72 cups_create_localizations(http
, dinfo
);
74 key
.msg
= size
->media
;
75 if ((match
= (_cups_message_t
*)cupsArrayFind(dinfo
->localizations
, &key
)) != NULL
)
77 DEBUG_printf(("1cupsLocalizeDestMedia: Returning \"%s\".", match
->str
));
82 * If not, get the localized size, source, and type strings...
85 lang
= cupsLangDefault();
87 snprintf(temp
, sizeof(temp
), "media.%s", size
->media
);
88 if ((lsize
= _cupsLangString(lang
, temp
)) != NULL
&& strcmp(lsize
, temp
))
90 DEBUG_printf(("1cupsLocalizeDestMedia: Returning standard localization \"%s\".", lsize
));
94 pwg
= pwgMediaForSize(size
->width
, size
->length
);
97 lsize
= _cupsLangString(lang
, pwg
->ppd
);
103 if ((size
->width
% 635) == 0 && (size
->length
% 635) == 0)
106 * Use inches since the size is a multiple of 1/4 inch.
109 snprintf(temp
, sizeof(temp
), _cupsLangString(lang
, _("%g x %g \"")), size
->width
/ 2540.0, size
->length
/ 2540.0);
114 * Use millimeters since the size is not a multiple of 1/4 inch.
117 snprintf(temp
, sizeof(temp
), _cupsLangString(lang
, _("%d x %d mm")), (size
->width
+ 50) / 100, (size
->length
+ 50) / 100);
123 if (flags
& CUPS_MEDIA_FLAGS_READY
)
124 db
= dinfo
->ready_db
;
126 db
= dinfo
->media_db
;
128 DEBUG_printf(("1cupsLocalizeDestMedia: size->media=\"%s\"", size
->media
));
130 for (mdb
= (_cups_media_db_t
*)cupsArrayFirst(db
); mdb
; mdb
= (_cups_media_db_t
*)cupsArrayNext(db
))
132 if (mdb
->key
&& !strcmp(mdb
->key
, size
->media
))
134 else if (mdb
->size_name
&& !strcmp(mdb
->size_name
, size
->media
))
140 for (mdb
= (_cups_media_db_t
*)cupsArrayFirst(db
); mdb
; mdb
= (_cups_media_db_t
*)cupsArrayNext(db
))
142 if (mdb
->width
== size
->width
&& mdb
->length
== size
->length
&& mdb
->bottom
== size
->bottom
&& mdb
->left
== size
->left
&& mdb
->right
== size
->right
&& mdb
->top
== size
->top
)
149 DEBUG_printf(("1cupsLocalizeDestMedia: MATCH mdb%p [key=\"%s\" size_name=\"%s\" source=\"%s\" type=\"%s\" width=%d length=%d B%d L%d R%d T%d]", (void *)mdb
, mdb
->key
, mdb
->size_name
, mdb
->source
, mdb
->type
, mdb
->width
, mdb
->length
, mdb
->bottom
, mdb
->left
, mdb
->right
, mdb
->top
));
151 lsource
= cupsLocalizeDestValue(http
, dest
, dinfo
, "media-source", mdb
->source
);
152 ltype
= cupsLocalizeDestValue(http
, dest
, dinfo
, "media-type", mdb
->type
);
160 if (!lsource
&& !ltype
)
162 if (size
->bottom
|| size
->left
|| size
->right
|| size
->top
)
163 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (Borderless)")), lsize
);
165 strlcpy(name
, lsize
, sizeof(name
));
169 if (size
->bottom
|| size
->left
|| size
->right
|| size
->top
)
170 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (Borderless, %s)")), lsize
, ltype
);
172 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (%s)")), lsize
, ltype
);
176 if (size
->bottom
|| size
->left
|| size
->right
|| size
->top
)
177 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (Borderless, %s)")), lsize
, lsource
);
179 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (%s)")), lsize
, lsource
);
183 if (size
->bottom
|| size
->left
|| size
->right
|| size
->top
)
184 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (Borderless, %s, %s)")), lsize
, ltype
, lsource
);
186 snprintf(name
, sizeof(name
), _cupsLangString(lang
, _("%s (%s, %s)")), lsize
, ltype
, lsource
);
189 if ((match
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
192 match
->msg
= strdup(size
->media
);
193 match
->str
= strdup(name
);
195 cupsArrayAdd(dinfo
->localizations
, match
);
197 DEBUG_printf(("1cupsLocalizeDestMedia: Returning \"%s\".", match
->str
));
204 * 'cupsLocalizeDestOption()' - Get the localized string for a destination
207 * The returned string is stored in the destination information and will become
208 * invalid if the destination information is deleted.
210 * @since CUPS 1.6/macOS 10.8@
213 const char * /* O - Localized string */
214 cupsLocalizeDestOption(
215 http_t
*http
, /* I - Connection to destination */
216 cups_dest_t
*dest
, /* I - Destination */
217 cups_dinfo_t
*dinfo
, /* I - Destination information */
218 const char *option
) /* I - Option to localize */
220 _cups_message_t key
, /* Search key */
221 *match
; /* Matching entry */
222 const char *localized
; /* Localized string */
225 DEBUG_printf(("cupsLocalizeDestOption(http=%p, dest=%p, dinfo=%p, option=\"%s\")", (void *)http
, (void *)dest
, (void *)dinfo
, option
));
227 if (!http
|| !dest
|| !dinfo
)
230 if (!dinfo
->localizations
)
231 cups_create_localizations(http
, dinfo
);
233 key
.msg
= (char *)option
;
234 if ((match
= (_cups_message_t
*)cupsArrayFind(dinfo
->localizations
, &key
)) != NULL
)
236 else if ((localized
= _cupsLangString(cupsLangDefault(), option
)) != NULL
)
244 * 'cupsLocalizeDestValue()' - Get the localized string for a destination
247 * The returned string is stored in the destination information and will become
248 * invalid if the destination information is deleted.
250 * @since CUPS 1.6/macOS 10.8@
253 const char * /* O - Localized string */
254 cupsLocalizeDestValue(
255 http_t
*http
, /* I - Connection to destination */
256 cups_dest_t
*dest
, /* I - Destination */
257 cups_dinfo_t
*dinfo
, /* I - Destination information */
258 const char *option
, /* I - Option to localize */
259 const char *value
) /* I - Value to localize */
261 _cups_message_t key
, /* Search key */
262 *match
; /* Matching entry */
263 char pair
[256]; /* option.value pair */
264 const char *localized
; /* Localized string */
267 DEBUG_printf(("cupsLocalizeDestValue(http=%p, dest=%p, dinfo=%p, option=\"%s\", value=\"%s\")", (void *)http
, (void *)dest
, (void *)dinfo
, option
, value
));
269 if (!http
|| !dest
|| !dinfo
)
272 if (!strcmp(option
, "media"))
274 pwg_media_t
*media
= pwgMediaForPWG(value
);
277 strlcpy(size
.media
, value
, sizeof(size
.media
));
278 size
.width
= media
? media
->width
: 0;
279 size
.length
= media
? media
->length
: 0;
285 return (cupsLocalizeDestMedia(http
, dest
, dinfo
, CUPS_MEDIA_FLAGS_DEFAULT
, &size
));
288 if (!dinfo
->localizations
)
289 cups_create_localizations(http
, dinfo
);
291 snprintf(pair
, sizeof(pair
), "%s.%s", option
, value
);
293 if ((match
= (_cups_message_t
*)cupsArrayFind(dinfo
->localizations
, &key
)) != NULL
)
295 else if ((localized
= _cupsLangString(cupsLangDefault(), pair
)) != NULL
&& strcmp(localized
, pair
))
303 * 'cups_create_localizations()' - Create the localizations array for a
308 cups_create_localizations(
309 http_t
*http
, /* I - Connection to destination */
310 cups_dinfo_t
*dinfo
) /* I - Destination informations */
312 http_t
*http2
; /* Connection for strings file */
313 http_status_t status
; /* Request status */
314 ipp_attribute_t
*attr
; /* "printer-strings-uri" attribute */
315 char scheme
[32], /* URI scheme */
316 userpass
[256], /* Username/password info */
317 hostname
[256], /* Hostname */
318 resource
[1024], /* Resource */
320 /* Hostname of connection */
321 tempfile
[1024]; /* Temporary filename */
322 int port
; /* Port number */
323 http_encryption_t encryption
; /* Encryption to use */
324 cups_file_t
*temp
; /* Temporary file */
328 * See if there are any localizations...
331 if ((attr
= ippFindAttribute(dinfo
->attrs
, "printer-strings-uri",
332 IPP_TAG_URI
)) == NULL
)
335 * Nope, create an empty message catalog...
338 dinfo
->localizations
= _cupsMessageNew(NULL
);
339 DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) value.");
344 * Pull apart the URI and determine whether we need to try a different
348 if (httpSeparateURI(HTTP_URI_CODING_ALL
, attr
->values
[0].string
.text
,
349 scheme
, sizeof(scheme
), userpass
, sizeof(userpass
),
350 hostname
, sizeof(hostname
), &port
, resource
,
351 sizeof(resource
)) < HTTP_URI_STATUS_OK
)
353 dinfo
->localizations
= _cupsMessageNew(NULL
);
354 DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value \"%s\".", attr
->values
[0].string
.text
));
358 httpGetHostname(http
, http_hostname
, sizeof(http_hostname
));
360 if (!_cups_strcasecmp(http_hostname
, hostname
) &&
361 port
== httpAddrPort(http
->hostaddr
))
364 * Use the same connection...
372 * Connect to the alternate host...
375 if (!strcmp(scheme
, "https"))
376 encryption
= HTTP_ENCRYPTION_ALWAYS
;
378 encryption
= HTTP_ENCRYPTION_IF_REQUESTED
;
380 if ((http2
= httpConnect2(hostname
, port
, NULL
, AF_UNSPEC
, encryption
, 1,
381 30000, NULL
)) == NULL
)
383 DEBUG_printf(("4cups_create_localizations: Unable to connect to "
384 "%s:%d: %s", hostname
, port
, cupsLastErrorString()));
390 * Get a temporary file...
393 if ((temp
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
395 DEBUG_printf(("4cups_create_localizations: Unable to create temporary "
396 "file: %s", cupsLastErrorString()));
402 status
= cupsGetFd(http2
, resource
, cupsFileNumber(temp
));
405 DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource
, httpStatus(status
)));
407 if (status
== HTTP_STATUS_OK
)
410 * Got the file, read it...
413 dinfo
->localizations
= _cupsMessageLoad(tempfile
, _CUPS_MESSAGE_STRINGS
);
416 DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
417 cupsArrayCount(dinfo
->localizations
)));