• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Localized printf/puts functions for CUPS.
3  *
4  * Copyright © 2020-2024 by OpenPrinting.
5  * Copyright 2007-2014 by Apple Inc.
6  * Copyright 2002-2007 by Easy Software Products.
7  *
8  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
9  */
10 
11 /*
12  * Include necessary headers...
13  */
14 
15 #include "cups-private.h"
16 #include "debug-internal.h"
17 
18 
19 /*
20  * '_cupsLangPrintError()' - Print a message followed by a standard error.
21  */
22 
23 void
_cupsLangPrintError(const char * prefix,const char * message)24 _cupsLangPrintError(const char *prefix,	/* I - Non-localized message prefix */
25                     const char *message)/* I - Message */
26 {
27   ssize_t	bytes;			/* Number of bytes formatted */
28   int		last_errno;		/* Last error */
29   char		buffer[2048],		/* Message buffer */
30 		*bufptr,		/* Pointer into buffer */
31 		output[8192];		/* Output buffer */
32   _cups_globals_t *cg;			/* Global data */
33 
34 
35  /*
36   * Range check...
37   */
38 
39   if (!message)
40     return;
41 
42  /*
43   * Save the errno value...
44   */
45 
46   last_errno = errno;
47 
48  /*
49   * Get the message catalog...
50   */
51 
52   cg = _cupsGlobals();
53 
54   if (!cg->lang_default)
55     cg->lang_default = cupsLangDefault();
56 
57  /*
58   * Format the message...
59   */
60 
61   if (prefix)
62   {
63     snprintf(buffer, sizeof(buffer), "%s:", prefix);
64     bufptr = buffer + strlen(buffer);
65   }
66   else
67     bufptr = buffer;
68 
69   snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer),
70 	   /* TRANSLATORS: Message is "subject: error" */
71 	   _cupsLangString(cg->lang_default, _("%s: %s")),
72 	   _cupsLangString(cg->lang_default, message), strerror(last_errno));
73   strlcat(buffer, "\n", sizeof(buffer));
74 
75  /*
76   * Convert and write to stderr...
77   */
78 
79   bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
80                             cg->lang_default->encoding);
81 
82   if (bytes > 0)
83     fwrite(output, 1, (size_t)bytes, stderr);
84 }
85 
86 
87 /*
88  * '_cupsLangPrintFilter()' - Print a formatted filter message string to a file.
89  */
90 
91 int					/* O - Number of bytes written */
_cupsLangPrintFilter(FILE * fp,const char * prefix,const char * message,...)92 _cupsLangPrintFilter(
93     FILE       *fp,			/* I - File to write to */
94     const char *prefix,			/* I - Non-localized message prefix */
95     const char *message,		/* I - Message string to use */
96     ...)				/* I - Additional arguments as needed */
97 {
98   ssize_t	bytes;			/* Number of bytes formatted */
99   char		temp[2048],		/* Temporary format buffer */
100 		buffer[2048],		/* Message buffer */
101 		output[8192];		/* Output buffer */
102   va_list 	ap;			/* Pointer to additional arguments */
103   _cups_globals_t *cg;			/* Global data */
104 
105 
106  /*
107   * Range check...
108   */
109 
110   if (!fp || !message)
111     return (-1);
112 
113   cg = _cupsGlobals();
114 
115   if (!cg->lang_default)
116     cg->lang_default = cupsLangDefault();
117 
118  /*
119   * Format the string...
120   */
121 
122   va_start(ap, message);
123   snprintf(temp, sizeof(temp), "%s: %s\n", prefix,
124 	   _cupsLangString(cg->lang_default, message));
125   vsnprintf(buffer, sizeof(buffer), temp, ap);
126   va_end(ap);
127 
128  /*
129   * Transcode to the destination charset...
130   */
131 
132   bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
133                             cg->lang_default->encoding);
134 
135  /*
136   * Write the string and return the number of bytes written...
137   */
138 
139   if (bytes > 0)
140     return ((int)fwrite(output, 1, (size_t)bytes, fp));
141   else
142     return ((int)bytes);
143 }
144 
145 
146 /*
147  * '_cupsLangPrintf()' - Print a formatted message string to a file.
148  */
149 
150 int					/* O - Number of bytes written */
_cupsLangPrintf(FILE * fp,const char * message,...)151 _cupsLangPrintf(FILE       *fp,		/* I - File to write to */
152 		const char *message,	/* I - Message string to use */
153 	        ...)			/* I - Additional arguments as needed */
154 {
155   ssize_t	bytes;			/* Number of bytes formatted */
156   char		buffer[2048],		/* Message buffer */
157 		output[8192];		/* Output buffer */
158   va_list 	ap;			/* Pointer to additional arguments */
159   _cups_globals_t *cg;			/* Global data */
160 
161 
162  /*
163   * Range check...
164   */
165 
166   if (!fp || !message)
167     return (-1);
168 
169   cg = _cupsGlobals();
170 
171   if (!cg->lang_default)
172     cg->lang_default = cupsLangDefault();
173 
174  /*
175   * Format the string...
176   */
177 
178   va_start(ap, message);
179   vsnprintf(buffer, sizeof(buffer) - 1,
180 	    _cupsLangString(cg->lang_default, message), ap);
181   va_end(ap);
182 
183   strlcat(buffer, "\n", sizeof(buffer));
184 
185  /*
186   * Transcode to the destination charset...
187   */
188 
189   bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
190                             cg->lang_default->encoding);
191 
192  /*
193   * Write the string and return the number of bytes written...
194   */
195 
196   if (bytes > 0)
197     return ((int)fwrite(output, 1, (size_t)bytes, fp));
198   else
199     return ((int)bytes);
200 }
201 
202 
203 /*
204  * '_cupsLangPuts()' - Print a static message string to a file.
205  */
206 
207 int					/* O - Number of bytes written */
_cupsLangPuts(FILE * fp,const char * message)208 _cupsLangPuts(FILE       *fp,		/* I - File to write to */
209               const char *message)	/* I - Message string to use */
210 {
211   ssize_t	bytes;			/* Number of bytes formatted */
212   char		output[8192];		/* Message buffer */
213   _cups_globals_t *cg;			/* Global data */
214 
215 
216  /*
217   * Range check...
218   */
219 
220   if (!fp || !message)
221     return (-1);
222 
223   cg = _cupsGlobals();
224 
225   if (!cg->lang_default)
226     cg->lang_default = cupsLangDefault();
227 
228  /*
229   * Transcode to the destination charset...
230   */
231 
232   bytes = cupsUTF8ToCharset(output,
233 			    (cups_utf8_t *)_cupsLangString(cg->lang_default,
234 							   message),
235 			    sizeof(output) - 4, cg->lang_default->encoding);
236   bytes += cupsUTF8ToCharset(output + bytes, (cups_utf8_t *)"\n", (int)(sizeof(output) - (size_t)bytes), cg->lang_default->encoding);
237 
238  /*
239   * Write the string and return the number of bytes written...
240   */
241 
242   if (bytes > 0)
243     return ((int)fwrite(output, 1, (size_t)bytes, fp));
244   else
245     return ((int)bytes);
246 }
247 
248 
249 /*
250  * '_cupsSetLocale()' - Set the current locale and transcode the command-line.
251  */
252 
253 void
_cupsSetLocale(char * argv[])254 _cupsSetLocale(char *argv[])		/* IO - Command-line arguments */
255 {
256   int		i;			/* Looping var */
257   char		buffer[8192];		/* Command-line argument buffer */
258   _cups_globals_t *cg;			/* Global data */
259 #ifdef LC_TIME
260   const char	*lc_time;		/* Current LC_TIME value */
261   char		new_lc_time[255],	/* New LC_TIME value */
262 		*charset;		/* Pointer to character set */
263 #endif /* LC_TIME */
264 
265 
266  /*
267   * Set the locale so that times, etc. are displayed properly.
268   *
269   * Unfortunately, while we need the localized time value, we *don't*
270   * want to use the localized charset for the time value, so we need
271   * to set LC_TIME to the locale name with .UTF-8 on the end (if
272   * the locale includes a character set specifier...)
273   */
274 
275   setlocale(LC_ALL, "");
276 
277 #ifdef LC_TIME
278   if ((lc_time = setlocale(LC_TIME, NULL)) == NULL)
279     lc_time = setlocale(LC_ALL, NULL);
280 
281   if (lc_time)
282   {
283     strlcpy(new_lc_time, lc_time, sizeof(new_lc_time));
284     if ((charset = strchr(new_lc_time, '.')) == NULL)
285       charset = new_lc_time + strlen(new_lc_time);
286 
287     strlcpy(charset, ".UTF-8", sizeof(new_lc_time) - (size_t)(charset - new_lc_time));
288   }
289   else
290     strlcpy(new_lc_time, "C", sizeof(new_lc_time));
291 
292   setlocale(LC_TIME, new_lc_time);
293 #endif /* LC_TIME */
294 
295  /*
296   * Initialize the default language info...
297   */
298 
299   cg = _cupsGlobals();
300 
301   if (!cg->lang_default)
302     cg->lang_default = cupsLangDefault();
303 
304  /*
305   * Transcode the command-line arguments from the locale charset to
306   * UTF-8...
307   */
308 
309   if (cg->lang_default->encoding != CUPS_US_ASCII &&
310       cg->lang_default->encoding != CUPS_UTF8)
311   {
312     for (i = 1; argv[i]; i ++)
313     {
314      /*
315       * Try converting from the locale charset to UTF-8...
316       */
317 
318       if (cupsCharsetToUTF8((cups_utf8_t *)buffer, argv[i], sizeof(buffer),
319                             cg->lang_default->encoding) < 0)
320         continue;
321 
322      /*
323       * Save the new string if it differs from the original...
324       */
325 
326       if (strcmp(buffer, argv[i]))
327         argv[i] = strdup(buffer);
328     }
329   }
330 }
331