File: | modules/printbackends/cups/ctkprintbackendcups.c |
Warning: | line 1774, column 3 Value stored to 'state' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* CTK - The GIMP Toolkit |
2 | * ctkprintbackendcups.h: Default implementation of CtkPrintBackend |
3 | * for the Common Unix Print System (CUPS) |
4 | * Copyright (C) 2006, 2007 Red Hat, Inc. |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include <ctype.h> |
22 | #include <unistd.h> |
23 | #include <sys/types.h> |
24 | #include <sys/stat.h> |
25 | #include <stdlib.h> |
26 | #include <time.h> |
27 | |
28 | /* Cups 1.6 deprecates ppdFindAttr(), ppdFindCustomOption(), |
29 | * ppdFirstCustomParam(), and ppdNextCustomParam() among others. This |
30 | * turns off the warning so that it will compile. |
31 | */ |
32 | #define _PPD_DEPRECATED |
33 | |
34 | #include <cups/cups.h> |
35 | #include <cups/language.h> |
36 | #include <cups/http.h> |
37 | #include <cups/ipp.h> |
38 | #include <errno(*__errno_location ()).h> |
39 | #include <cairo.h> |
40 | #include <cairo-pdf.h> |
41 | #include <cairo-ps.h> |
42 | |
43 | #include <glib/gstdio.h> |
44 | #include <glib/gi18n-lib.h> |
45 | #include <gmodule.h> |
46 | |
47 | #include <ctk/ctk.h> |
48 | #include <ctk/ctkprintbackend.h> |
49 | #include <ctk/ctkunixprint.h> |
50 | #include <ctk/ctkprinter-private.h> |
51 | |
52 | #include "ctkprintbackendcups.h" |
53 | #include "ctkprintercups.h" |
54 | |
55 | #include "ctkcupsutils.h" |
56 | #include "ctkcupssecretsutils.h" |
57 | |
58 | #include <ctkprintutils.h> |
59 | |
60 | #ifdef HAVE_COLORD1 |
61 | #include <colord.h> |
62 | #endif |
63 | |
64 | #if ((CUPS_VERSION_MAJOR2 == 2 && CUPS_VERSION_MINOR4 >= 2) || CUPS_VERSION_MAJOR2 > 2) |
65 | #define HAVE_CUPS_2_2 |
66 | #endif |
67 | |
68 | typedef struct _CtkPrintBackendCupsClass CtkPrintBackendCupsClass; |
69 | |
70 | #define CTK_PRINT_BACKEND_CUPS_CLASS(klass)((((CtkPrintBackendCupsClass*) (void *) g_type_check_class_cast ((GTypeClass*) ((klass)), ((ctk_print_backend_cups_get_type ( ))))))) (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_PRINT_BACKEND_CUPS, CtkPrintBackendCupsClass)(((CtkPrintBackendCupsClass*) (void *) g_type_check_class_cast ((GTypeClass*) ((klass)), ((ctk_print_backend_cups_get_type ( ))))))) |
71 | #define CTK_IS_PRINT_BACKEND_CUPS_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass )); GType __t = ((ctk_print_backend_cups_get_type ())); gboolean __r; if (!__class) __r = (0); else if (__class->g_type == __t) __r = (!(0)); else __r = g_type_check_class_is_a (__class , __t); __r; })))) (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_PRINT_BACKEND_CUPS)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass )); GType __t = ((ctk_print_backend_cups_get_type ())); gboolean __r; if (!__class) __r = (0); else if (__class->g_type == __t) __r = (!(0)); else __r = g_type_check_class_is_a (__class , __t); __r; })))) |
72 | #define CTK_PRINT_BACKEND_CUPS_GET_CLASS(obj)((((CtkPrintBackendCupsClass*) (((GTypeInstance*) ((obj)))-> g_class)))) (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_PRINT_BACKEND_CUPS, CtkPrintBackendCupsClass)(((CtkPrintBackendCupsClass*) (((GTypeInstance*) ((obj)))-> g_class)))) |
73 | |
74 | #define _CUPS_MAX_ATTEMPTS10 10 |
75 | #define _CUPS_MAX_CHUNK_SIZE8192 8192 |
76 | |
77 | #define AVAHI_IF_UNSPEC-1 -1 |
78 | #define AVAHI_PROTO_INET0 0 |
79 | #define AVAHI_PROTO_INET61 1 |
80 | #define AVAHI_PROTO_UNSPEC-1 -1 |
81 | |
82 | #define AVAHI_BUS"org.freedesktop.Avahi" "org.freedesktop.Avahi" |
83 | #define AVAHI_SERVER_IFACE"org.freedesktop.Avahi.Server" "org.freedesktop.Avahi.Server" |
84 | #define AVAHI_SERVICE_BROWSER_IFACE"org.freedesktop.Avahi.ServiceBrowser" "org.freedesktop.Avahi.ServiceBrowser" |
85 | #define AVAHI_SERVICE_RESOLVER_IFACE"org.freedesktop.Avahi.ServiceResolver" "org.freedesktop.Avahi.ServiceResolver" |
86 | |
87 | #define PRINTER_NAME_ALLOWED_CHARACTERS"abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" |
88 | /* define this to see warnings about ignored ppd options */ |
89 | #undef PRINT_IGNORED_OPTIONS |
90 | |
91 | #define _CUPS_MAP_ATTR_INT(attr, v, a){if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values [0].integer;} {if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values[0].integer;} |
92 | #define _CUPS_MAP_ATTR_STR(attr, v, a){if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values [0].string.text;} {if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values[0].string.text;} |
93 | |
94 | static GType print_backend_cups_type = 0; |
95 | |
96 | typedef void (* CtkPrintCupsResponseCallbackFunc) (CtkPrintBackend *print_backend, |
97 | CtkCupsResult *result, |
98 | gpointer user_data); |
99 | |
100 | typedef enum |
101 | { |
102 | DISPATCH_SETUP, |
103 | DISPATCH_REQUEST, |
104 | DISPATCH_SEND, |
105 | DISPATCH_CHECK, |
106 | DISPATCH_READ, |
107 | DISPATCH_ERROR |
108 | } CtkPrintCupsDispatchState; |
109 | |
110 | typedef struct |
111 | { |
112 | GSource source; |
113 | |
114 | http_t *http; |
115 | CtkCupsRequest *request; |
116 | CtkCupsPollState poll_state; |
117 | GPollFD *data_poll; |
118 | CtkPrintBackendCups *backend; |
119 | CtkPrintCupsResponseCallbackFunc callback; |
120 | gpointer callback_data; |
121 | |
122 | } CtkPrintCupsDispatchWatch; |
123 | |
124 | struct _CtkPrintBackendCupsClass |
125 | { |
126 | CtkPrintBackendClass parent_class; |
127 | }; |
128 | |
129 | struct _CtkPrintBackendCups |
130 | { |
131 | CtkPrintBackend parent_instance; |
132 | |
133 | char *default_printer; |
134 | |
135 | guint list_printers_poll; |
136 | guint list_printers_pending : 1; |
137 | gint list_printers_attempts; |
138 | guint got_default_printer : 1; |
139 | guint default_printer_poll; |
140 | CtkCupsConnectionTest *cups_connection_test; |
141 | gint reading_ppds; |
142 | |
143 | GList *requests; |
144 | GHashTable *auth; |
145 | gchar *username; |
146 | gboolean authentication_lock; |
147 | #ifdef HAVE_COLORD1 |
148 | CdClient *colord_client; |
149 | #endif |
150 | |
151 | GDBusConnection *dbus_connection; |
152 | char *avahi_default_printer; |
153 | guint avahi_service_browser_subscription_id; |
154 | guint avahi_service_browser_subscription_ids[2]; |
155 | char *avahi_service_browser_paths[2]; |
156 | GCancellable *avahi_cancellable; |
157 | guint unsubscribe_general_subscription_id; |
158 | |
159 | gboolean secrets_service_available; |
160 | guint secrets_service_watch_id; |
161 | GCancellable *secrets_service_cancellable; |
162 | |
163 | GList *temporary_queues_in_construction; |
164 | GList *temporary_queues_removed; |
165 | }; |
166 | |
167 | static GObjectClass *backend_parent_class; |
168 | |
169 | static void ctk_print_backend_cups_class_init (CtkPrintBackendCupsClass *class); |
170 | static void ctk_print_backend_cups_init (CtkPrintBackendCups *impl); |
171 | static void ctk_print_backend_cups_finalize (GObject *object); |
172 | static void ctk_print_backend_cups_dispose (GObject *object); |
173 | static void cups_get_printer_list (CtkPrintBackend *print_backend); |
174 | static void cups_get_default_printer (CtkPrintBackendCups *print_backend); |
175 | static void cups_get_local_default_printer (CtkPrintBackendCups *print_backend); |
176 | static void cups_request_execute (CtkPrintBackendCups *print_backend, |
177 | CtkCupsRequest *request, |
178 | CtkPrintCupsResponseCallbackFunc callback, |
179 | gpointer user_data, |
180 | GDestroyNotify notify); |
181 | static void cups_printer_get_settings_from_options (CtkPrinter *printer, |
182 | CtkPrinterOptionSet *options, |
183 | CtkPrintSettings *settings); |
184 | static gboolean cups_printer_mark_conflicts (CtkPrinter *printer, |
185 | CtkPrinterOptionSet *options); |
186 | static CtkPrinterOptionSet *cups_printer_get_options (CtkPrinter *printer, |
187 | CtkPrintSettings *settings, |
188 | CtkPageSetup *page_setup, |
189 | CtkPrintCapabilities capabilities); |
190 | static void cups_printer_prepare_for_print (CtkPrinter *printer, |
191 | CtkPrintJob *print_job, |
192 | CtkPrintSettings *settings, |
193 | CtkPageSetup *page_setup); |
194 | static GList * cups_printer_list_papers (CtkPrinter *printer); |
195 | static CtkPageSetup * cups_printer_get_default_page_size (CtkPrinter *printer); |
196 | static void cups_printer_request_details (CtkPrinter *printer); |
197 | static gboolean cups_request_default_printer (CtkPrintBackendCups *print_backend); |
198 | static gboolean cups_request_ppd (CtkPrinter *printer); |
199 | static gboolean cups_printer_get_hard_margins (CtkPrinter *printer, |
200 | gdouble *top, |
201 | gdouble *bottom, |
202 | gdouble *left, |
203 | gdouble *right); |
204 | static gboolean cups_printer_get_hard_margins_for_paper_size (CtkPrinter *printer, |
205 | CtkPaperSize *paper_size, |
206 | gdouble *top, |
207 | gdouble *bottom, |
208 | gdouble *left, |
209 | gdouble *right); |
210 | static CtkPrintCapabilities cups_printer_get_capabilities (CtkPrinter *printer); |
211 | static void set_option_from_settings (CtkPrinterOption *option, |
212 | CtkPrintSettings *setting); |
213 | static void cups_begin_polling_info (CtkPrintBackendCups *print_backend, |
214 | CtkPrintJob *job, |
215 | int job_id); |
216 | static gboolean cups_job_info_poll_timeout (gpointer user_data); |
217 | static void ctk_print_backend_cups_print_stream (CtkPrintBackend *backend, |
218 | CtkPrintJob *job, |
219 | GIOChannel *data_io, |
220 | CtkPrintJobCompleteFunc callback, |
221 | gpointer user_data, |
222 | GDestroyNotify dnotify); |
223 | static cairo_surface_t * cups_printer_create_cairo_surface (CtkPrinter *printer, |
224 | CtkPrintSettings *settings, |
225 | gdouble width, |
226 | gdouble height, |
227 | GIOChannel *cache_io); |
228 | |
229 | static void ctk_print_backend_cups_set_password (CtkPrintBackend *backend, |
230 | gchar **auth_info_required, |
231 | gchar **auth_info, |
232 | gboolean store_auth_info); |
233 | |
234 | void overwrite_and_free (gpointer data); |
235 | static gboolean is_address_local (const gchar *address); |
236 | static gboolean request_auth_info (gpointer data); |
237 | static void lookup_auth_info (gpointer data); |
238 | |
239 | static void avahi_request_printer_list (CtkPrintBackendCups *cups_backend); |
240 | |
241 | static void secrets_service_appeared_cb (GDBusConnection *connection, |
242 | const gchar *name, |
243 | const gchar *name_owner, |
244 | gpointer user_data); |
245 | static void secrets_service_vanished_cb (GDBusConnection *connection, |
246 | const gchar *name, |
247 | gpointer user_data); |
248 | |
249 | #ifdef HAVE_CUPS_2_2 |
250 | static void create_temporary_queue (CtkPrintBackendCups *backend, |
251 | const gchar *printer_name, |
252 | const gchar *printer_uri, |
253 | const gchar *device_uri); |
254 | #endif |
255 | |
256 | static void |
257 | ctk_print_backend_cups_register_type (GTypeModule *module) |
258 | { |
259 | const GTypeInfo print_backend_cups_info = |
260 | { |
261 | .class_size = sizeof (CtkPrintBackendCupsClass), |
262 | .class_init = (GClassInitFunc) ctk_print_backend_cups_class_init, |
263 | .instance_size = sizeof (CtkPrintBackendCups), |
264 | .n_preallocs = 0, |
265 | .instance_init = (GInstanceInitFunc) ctk_print_backend_cups_init |
266 | }; |
267 | |
268 | print_backend_cups_type = g_type_module_register_type (module, |
269 | CTK_TYPE_PRINT_BACKEND(ctk_print_backend_get_type ()), |
270 | "CtkPrintBackendCups", |
271 | &print_backend_cups_info, 0); |
272 | } |
273 | |
274 | G_MODULE_EXPORT__attribute__((visibility("default"))) void |
275 | pb_module_init (GTypeModule *module) |
276 | { |
277 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Initializing the CUPS print backend module\n" ); }; } while (0) |
278 | g_print ("CUPS Backend: Initializing the CUPS print backend module\n"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Initializing the CUPS print backend module\n" ); }; } while (0); |
279 | |
280 | ctk_print_backend_cups_register_type (module); |
281 | ctk_printer_cups_register_type (module); |
282 | } |
283 | |
284 | G_MODULE_EXPORT__attribute__((visibility("default"))) void |
285 | pb_module_exit (void) |
286 | { |
287 | |
288 | } |
289 | |
290 | G_MODULE_EXPORT__attribute__((visibility("default"))) CtkPrintBackend * |
291 | pb_module_create (void) |
292 | { |
293 | return ctk_print_backend_cups_new (); |
294 | } |
295 | /* |
296 | * CtkPrintBackendCups |
297 | */ |
298 | GType |
299 | ctk_print_backend_cups_get_type (void) |
300 | { |
301 | return print_backend_cups_type; |
302 | } |
303 | |
304 | /** |
305 | * ctk_print_backend_cups_new: |
306 | * |
307 | * Creates a new #CtkPrintBackendCups object. #CtkPrintBackendCups |
308 | * implements the #CtkPrintBackend interface with direct access to |
309 | * the filesystem using Unix/Linux API calls |
310 | * |
311 | * Returns: the new #CtkPrintBackendCups object |
312 | */ |
313 | CtkPrintBackend * |
314 | ctk_print_backend_cups_new (void) |
315 | { |
316 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating a new CUPS print backend object\n" ); }; } while (0) |
317 | g_print ("CUPS Backend: Creating a new CUPS print backend object\n"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating a new CUPS print backend object\n" ); }; } while (0); |
318 | |
319 | return g_object_new (CTK_TYPE_PRINT_BACKEND_CUPS(ctk_print_backend_cups_get_type ()), NULL((void*)0)); |
320 | } |
321 | |
322 | static void |
323 | ctk_print_backend_cups_class_init (CtkPrintBackendCupsClass *class) |
324 | { |
325 | GObjectClass *gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((class)), (((GType) ((20) << (2)))))))); |
326 | CtkPrintBackendClass *backend_class = CTK_PRINT_BACKEND_CLASS (class)((((CtkPrintBackendClass*) (void *) g_type_check_class_cast ( (GTypeClass*) ((class)), ((ctk_print_backend_get_type ()))))) ); |
327 | |
328 | backend_parent_class = g_type_class_peek_parent (class); |
329 | |
330 | gobject_class->finalize = ctk_print_backend_cups_finalize; |
331 | gobject_class->dispose = ctk_print_backend_cups_dispose; |
332 | |
333 | backend_class->request_printer_list = cups_get_printer_list; |
334 | backend_class->print_stream = ctk_print_backend_cups_print_stream; |
335 | backend_class->printer_request_details = cups_printer_request_details; |
336 | backend_class->printer_create_cairo_surface = cups_printer_create_cairo_surface; |
337 | backend_class->printer_get_options = cups_printer_get_options; |
338 | backend_class->printer_mark_conflicts = cups_printer_mark_conflicts; |
339 | backend_class->printer_get_settings_from_options = cups_printer_get_settings_from_options; |
340 | backend_class->printer_prepare_for_print = cups_printer_prepare_for_print; |
341 | backend_class->printer_list_papers = cups_printer_list_papers; |
342 | backend_class->printer_get_default_page_size = cups_printer_get_default_page_size; |
343 | backend_class->printer_get_hard_margins = cups_printer_get_hard_margins; |
344 | backend_class->printer_get_hard_margins_for_paper_size = cups_printer_get_hard_margins_for_paper_size; |
345 | backend_class->printer_get_capabilities = cups_printer_get_capabilities; |
346 | backend_class->set_password = ctk_print_backend_cups_set_password; |
347 | } |
348 | |
349 | static gboolean |
350 | option_is_ipp_option (CtkPrinterOption *option) |
351 | { |
352 | gpointer data = g_object_get_data (G_OBJECT (option)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((option)), (((GType) ((20) << (2)))))))), "is-ipp-option"); |
353 | |
354 | if (data != NULL((void*)0)) |
355 | return GPOINTER_TO_UINT (data)((guint) (gulong) (data)) != 0; |
356 | else |
357 | return FALSE(0); |
358 | } |
359 | |
360 | static void |
361 | option_set_is_ipp_option (CtkPrinterOption *option, |
362 | gboolean is_ipp_option) |
363 | { |
364 | g_object_set_data (G_OBJECT (option)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((option)), (((GType) ((20) << (2)))))))), |
365 | "is-ipp-option", |
366 | GUINT_TO_POINTER (is_ipp_option ? 1 : 0)((gpointer) (gulong) (is_ipp_option ? 1 : 0))); |
367 | } |
368 | |
369 | static cairo_status_t |
370 | _cairo_write_to_cups (void *closure, |
371 | const unsigned char *data, |
372 | unsigned int length) |
373 | { |
374 | GIOChannel *io = (GIOChannel *)closure; |
375 | gsize written; |
376 | GError *error; |
377 | |
378 | error = NULL((void*)0); |
379 | |
380 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Writing %i byte chunk to temp file\n" , length); }; } while (0) |
381 | g_print ("CUPS Backend: Writing %i byte chunk to temp file\n", length))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Writing %i byte chunk to temp file\n" , length); }; } while (0); |
382 | |
383 | while (length > 0) |
384 | { |
385 | g_io_channel_write_chars (io, (gchar *)data, length, &written, &error); |
386 | |
387 | if (error != NULL((void*)0)) |
388 | { |
389 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Error writing to temp file, %s\n", error ->message); }; } while (0) |
390 | g_print ("CUPS Backend: Error writing to temp file, %s\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Error writing to temp file, %s\n", error ->message); }; } while (0) |
391 | error->message))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Error writing to temp file, %s\n", error ->message); }; } while (0); |
392 | |
393 | g_error_free (error); |
394 | return CAIRO_STATUS_WRITE_ERROR; |
395 | } |
396 | |
397 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Wrote %""lu"" bytes to temp file\n", written); }; } while (0) |
398 | g_print ("CUPS Backend: Wrote %"G_GSIZE_FORMAT" bytes to temp file\n", written))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Wrote %""lu"" bytes to temp file\n", written); }; } while (0); |
399 | |
400 | data += written; |
401 | length -= written; |
402 | } |
403 | |
404 | return CAIRO_STATUS_SUCCESS; |
405 | } |
406 | |
407 | static cairo_surface_t * |
408 | cups_printer_create_cairo_surface (CtkPrinter *printer, |
409 | CtkPrintSettings *settings, |
410 | gdouble width, |
411 | gdouble height, |
412 | GIOChannel *cache_io) |
413 | { |
414 | cairo_surface_t *surface; |
415 | ppd_file_t *ppd_file = NULL((void*)0); |
416 | ppd_attr_t *ppd_attr = NULL((void*)0); |
417 | ppd_attr_t *ppd_attr_res = NULL((void*)0); |
418 | ppd_attr_t *ppd_attr_screen_freq = NULL((void*)0); |
419 | ppd_attr_t *ppd_attr_res_screen_freq = NULL((void*)0); |
420 | gchar *res_string = NULL((void*)0); |
421 | gint level = 2; |
422 | |
423 | if (ctk_printer_accepts_pdf (printer)) |
424 | surface = cairo_pdf_surface_create_for_stream (_cairo_write_to_cups, cache_io, width, height); |
425 | else |
426 | surface = cairo_ps_surface_create_for_stream (_cairo_write_to_cups, cache_io, width, height); |
427 | |
428 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
429 | |
430 | if (ppd_file != NULL((void*)0)) |
431 | { |
432 | ppd_attr = ppdFindAttr (ppd_file, "LanguageLevel", NULL((void*)0)); |
433 | |
434 | if (ppd_attr != NULL((void*)0)) |
435 | level = atoi (ppd_attr->value); |
436 | |
437 | if (ctk_print_settings_get_resolution (settings) == 0) |
438 | { |
439 | ppd_attr_res = ppdFindAttr (ppd_file, "DefaultResolution", NULL((void*)0)); |
440 | |
441 | if (ppd_attr_res != NULL((void*)0)) |
442 | { |
443 | int res, res_x, res_y; |
444 | |
445 | if (sscanf (ppd_attr_res->value, "%dx%ddpi", &res_x, &res_y) == 2) |
446 | { |
447 | if (res_x > 0 && res_y > 0) |
448 | ctk_print_settings_set_resolution_xy (settings, res_x, res_y); |
449 | } |
450 | else if (sscanf (ppd_attr_res->value, "%ddpi", &res) == 1) |
451 | { |
452 | if (res > 0) |
453 | ctk_print_settings_set_resolution (settings, res); |
454 | } |
455 | } |
456 | } |
457 | |
458 | res_string = g_strdup_printf ("%ddpi", |
459 | ctk_print_settings_get_resolution (settings)); |
460 | ppd_attr_res_screen_freq = ppdFindAttr (ppd_file, "ResScreenFreq", res_string); |
461 | g_free (res_string); |
462 | |
463 | if (ppd_attr_res_screen_freq == NULL((void*)0)) |
464 | { |
465 | res_string = g_strdup_printf ("%dx%ddpi", |
466 | ctk_print_settings_get_resolution_x (settings), |
467 | ctk_print_settings_get_resolution_y (settings)); |
468 | ppd_attr_res_screen_freq = ppdFindAttr (ppd_file, "ResScreenFreq", res_string); |
469 | g_free (res_string); |
470 | } |
471 | |
472 | ppd_attr_screen_freq = ppdFindAttr (ppd_file, "ScreenFreq", NULL((void*)0)); |
473 | |
474 | if (ppd_attr_res_screen_freq != NULL((void*)0) && atof (ppd_attr_res_screen_freq->value) > 0.0) |
475 | ctk_print_settings_set_printer_lpi (settings, atof (ppd_attr_res_screen_freq->value)); |
476 | else if (ppd_attr_screen_freq != NULL((void*)0) && atof (ppd_attr_screen_freq->value) > 0.0) |
477 | ctk_print_settings_set_printer_lpi (settings, atof (ppd_attr_screen_freq->value)); |
478 | } |
479 | |
480 | if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_PS) |
481 | { |
482 | if (level == 2) |
483 | cairo_ps_surface_restrict_to_level (surface, CAIRO_PS_LEVEL_2); |
484 | |
485 | if (level == 3) |
486 | cairo_ps_surface_restrict_to_level (surface, CAIRO_PS_LEVEL_3); |
487 | } |
488 | |
489 | cairo_surface_set_fallback_resolution (surface, |
490 | 2.0 * ctk_print_settings_get_printer_lpi (settings), |
491 | 2.0 * ctk_print_settings_get_printer_lpi (settings)); |
492 | |
493 | return surface; |
494 | } |
495 | |
496 | typedef struct { |
497 | CtkPrintJobCompleteFunc callback; |
498 | CtkPrintJob *job; |
499 | gpointer user_data; |
500 | GDestroyNotify dnotify; |
501 | http_t *http; |
502 | } CupsPrintStreamData; |
503 | |
504 | static void |
505 | cups_free_print_stream_data (CupsPrintStreamData *data) |
506 | { |
507 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
508 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
509 | |
510 | if (data->dnotify) |
511 | data->dnotify (data->user_data); |
512 | g_object_unref (data->job); |
513 | if (data->http != NULL((void*)0)) |
514 | httpClose (data->http); |
515 | g_free (data); |
516 | } |
517 | |
518 | static void |
519 | cups_print_cb (CtkPrintBackendCups *print_backend, |
520 | CtkCupsResult *result, |
521 | gpointer user_data) |
522 | { |
523 | GError *error = NULL((void*)0); |
524 | CupsPrintStreamData *ps = user_data; |
525 | |
526 | cdk_threads_enter (); |
527 | |
528 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
529 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
530 | |
531 | if (ctk_cups_result_is_error (result)) |
532 | error = g_error_new_literal (ctk_print_error_quark (), |
533 | CTK_PRINT_ERROR_INTERNAL_ERROR, |
534 | ctk_cups_result_get_error_string (result)); |
535 | |
536 | if (ps->callback) |
537 | ps->callback (ps->job, ps->user_data, error); |
538 | |
539 | if (error == NULL((void*)0)) |
540 | { |
541 | int job_id = 0; |
542 | ipp_attribute_t *attr; /* IPP job-id attribute */ |
543 | ipp_t *response = ctk_cups_result_get_response (result); |
544 | |
545 | if ((attr = ippFindAttribute (response, "job-id", IPP_TAG_INTEGER)) != NULL((void*)0)) |
546 | job_id = ippGetInteger (attr, 0); |
547 | |
548 | if (!ctk_print_job_get_track_print_status (ps->job) || job_id == 0) |
549 | ctk_print_job_set_status (ps->job, CTK_PRINT_STATUS_FINISHED); |
550 | else |
551 | { |
552 | ctk_print_job_set_status (ps->job, CTK_PRINT_STATUS_PENDING); |
553 | cups_begin_polling_info (print_backend, ps->job, job_id); |
554 | } |
555 | } |
556 | else |
557 | ctk_print_job_set_status (ps->job, CTK_PRINT_STATUS_FINISHED_ABORTED); |
558 | |
559 | |
560 | if (error) |
561 | g_error_free (error); |
562 | |
563 | cdk_threads_leave (); |
564 | } |
565 | |
566 | typedef struct { |
567 | CtkCupsRequest *request; |
568 | CtkPageSetup *page_setup; |
569 | CtkPrinterCups *printer; |
570 | } CupsOptionsData; |
571 | |
572 | #define UNSIGNED_FLOAT_REGEX"([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" |
573 | #define SIGNED_FLOAT_REGEX"[+-]?""([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "[+-]?"UNSIGNED_FLOAT_REGEX"([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" |
574 | #define SIGNED_INTEGER_REGEX"[+-]?([0-9]+)" "[+-]?([0-9]+)" |
575 | |
576 | static void |
577 | add_cups_options (const gchar *key, |
578 | const gchar *value, |
579 | gpointer user_data) |
580 | { |
581 | CupsOptionsData *data = (CupsOptionsData *) user_data; |
582 | CtkCupsRequest *request = data->request; |
583 | CtkPrinterCups *printer = data->printer; |
584 | gboolean custom_value = FALSE(0); |
585 | gchar *new_value = NULL((void*)0); |
586 | gint i; |
587 | |
588 | if (!key || !value) |
589 | return; |
590 | |
591 | if (!g_str_has_prefix (key, "cups-")(__builtin_constant_p ("cups-")? __extension__ ({ const char * const __str = (key); const char * const __prefix = ("cups-") ; gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix ))); if (__str_len >= __prefix_len) __result = memcmp (((__str ) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0 ; } __result; }) : (g_str_has_prefix) (key, "cups-") )) |
592 | return; |
593 | |
594 | if (strcmp (value, "ctk-ignore-value") == 0) |
595 | return; |
596 | |
597 | key = key + strlen ("cups-"); |
598 | |
599 | if (printer && printer->ppd_file && !g_str_has_prefix (value, "Custom.")(__builtin_constant_p ("Custom.")? __extension__ ({ const char * const __str = (value); const char * const __prefix = ("Custom." ); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix ))); if (__str_len >= __prefix_len) __result = memcmp (((__str ) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0 ; } __result; }) : (g_str_has_prefix) (value, "Custom.") )) |
600 | { |
601 | ppd_coption_t *coption; |
602 | gboolean found = FALSE(0); |
603 | gboolean custom_values_enabled = FALSE(0); |
604 | |
605 | coption = ppdFindCustomOption (printer->ppd_file, key); |
606 | if (coption && coption->option) |
607 | { |
608 | for (i = 0; i < coption->option->num_choices; i++) |
609 | { |
610 | /* Are custom values enabled ? */ |
611 | if (g_str_equal (coption->option->choices[i].choice, "Custom")(strcmp ((const char *) (coption->option->choices[i].choice ), (const char *) ("Custom")) == 0)) |
612 | custom_values_enabled = TRUE(!(0)); |
613 | |
614 | /* Is the value among available choices ? */ |
615 | if (g_str_equal (coption->option->choices[i].choice, value)(strcmp ((const char *) (coption->option->choices[i].choice ), (const char *) (value)) == 0)) |
616 | found = TRUE(!(0)); |
617 | } |
618 | |
619 | if (custom_values_enabled && !found) |
620 | { |
621 | /* Check syntax of the invalid choice to see whether |
622 | it could be a custom value */ |
623 | if (g_str_equal (key, "PageSize")(strcmp ((const char *) (key), (const char *) ("PageSize")) == 0) || |
624 | g_str_equal (key, "PageRegion")(strcmp ((const char *) (key), (const char *) ("PageRegion")) == 0)) |
625 | { |
626 | /* Handle custom page sizes... */ |
627 | if (g_regex_match_simple ("^" UNSIGNED_FLOAT_REGEX"([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "x" UNSIGNED_FLOAT_REGEX"([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "(cm|mm|m|in|ft|pt)?$", value, G_REGEX_CASELESS, 0)) |
628 | custom_value = TRUE(!(0)); |
629 | else |
630 | { |
631 | if (data->page_setup != NULL((void*)0)) |
632 | { |
633 | custom_value = TRUE(!(0)); |
634 | new_value = |
635 | g_strdup_printf ("Custom.%.2fx%.2fmm", |
636 | ctk_paper_size_get_width (ctk_page_setup_get_paper_size (data->page_setup), CTK_UNIT_MM), |
637 | ctk_paper_size_get_height (ctk_page_setup_get_paper_size (data->page_setup), CTK_UNIT_MM)); |
638 | } |
639 | } |
640 | } |
641 | else |
642 | { |
643 | /* Handle other custom options... */ |
644 | ppd_cparam_t *cparam; |
645 | |
646 | cparam = (ppd_cparam_t *) cupsArrayFirst (coption->params); |
647 | if (cparam != NULL((void*)0)) |
648 | { |
649 | switch (cparam->type) |
650 | { |
651 | case PPD_CUSTOM_CURVE : |
652 | case PPD_CUSTOM_INVCURVE : |
653 | case PPD_CUSTOM_REAL : |
654 | if (g_regex_match_simple ("^" SIGNED_FLOAT_REGEX"[+-]?""([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "$", value, G_REGEX_CASELESS, 0)) |
655 | custom_value = TRUE(!(0)); |
656 | break; |
657 | |
658 | case PPD_CUSTOM_POINTS : |
659 | if (g_regex_match_simple ("^" SIGNED_FLOAT_REGEX"[+-]?""([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?" "(cm|mm|m|in|ft|pt)?$", value, G_REGEX_CASELESS, 0)) |
660 | custom_value = TRUE(!(0)); |
661 | break; |
662 | |
663 | case PPD_CUSTOM_INT : |
664 | if (g_regex_match_simple ("^" SIGNED_INTEGER_REGEX"[+-]?([0-9]+)" "$", value, G_REGEX_CASELESS, 0)) |
665 | custom_value = TRUE(!(0)); |
666 | break; |
667 | |
668 | case PPD_CUSTOM_PASSCODE : |
669 | case PPD_CUSTOM_PASSWORD : |
670 | case PPD_CUSTOM_STRING : |
671 | custom_value = TRUE(!(0)); |
672 | break; |
673 | |
674 | default : |
675 | custom_value = FALSE(0); |
676 | } |
677 | } |
678 | } |
679 | } |
680 | } |
681 | } |
682 | |
683 | /* Add "Custom." prefix to custom values if not already added. */ |
684 | if (custom_value) |
685 | { |
686 | if (new_value == NULL((void*)0)) |
687 | new_value = g_strdup_printf ("Custom.%s", value); |
688 | ctk_cups_request_encode_option (request, key, new_value); |
689 | g_free (new_value); |
690 | } |
691 | else |
692 | ctk_cups_request_encode_option (request, key, value); |
693 | } |
694 | |
695 | static void |
696 | ctk_print_backend_cups_print_stream (CtkPrintBackend *print_backend, |
697 | CtkPrintJob *job, |
698 | GIOChannel *data_io, |
699 | CtkPrintJobCompleteFunc callback, |
700 | gpointer user_data, |
701 | GDestroyNotify dnotify) |
702 | { |
703 | CtkPrinterCups *cups_printer; |
704 | CupsPrintStreamData *ps; |
705 | CupsOptionsData *options_data; |
706 | CtkPageSetup *page_setup; |
707 | CtkCupsRequest *request = NULL((void*)0); |
708 | CtkPrintSettings *settings; |
709 | const gchar *title; |
710 | char printer_absolute_uri[HTTP_MAX_URI1024]; |
711 | http_t *http = NULL((void*)0); |
712 | |
713 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
714 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
715 | |
716 | cups_printer = CTK_PRINTER_CUPS (ctk_print_job_get_printer (job))((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((ctk_print_job_get_printer (job))), ((ctk_printer_cups_get_type ())))))); |
717 | settings = ctk_print_job_get_settings (job); |
718 | |
719 | if (cups_printer->avahi_browsed) |
720 | { |
721 | http = httpConnect2 (cups_printer->hostname, cups_printer->port, |
722 | NULL((void*)0), AF_UNSPEC0, |
723 | HTTP_ENCRYPTION_IF_REQUESTED, |
724 | 1, 30000, |
725 | NULL((void*)0)); |
726 | if (http) |
727 | { |
728 | request = ctk_cups_request_new_with_username (http, |
729 | CTK_CUPS_POST, |
730 | IPP_PRINT_JOBIPP_OP_PRINT_JOB, |
731 | data_io, |
732 | cups_printer->hostname, |
733 | cups_printer->device_uri, |
734 | CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ()))))))->username); |
735 | g_snprintf (printer_absolute_uri, HTTP_MAX_URI1024, "%s", cups_printer->printer_uri); |
736 | } |
737 | else |
738 | { |
739 | GError *error = NULL((void*)0); |
740 | |
741 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error connecting to %s:%d", cups_printer ->hostname, cups_printer->port); }; } while (0) |
742 | g_warning ("CUPS Backend: Error connecting to %s:%d",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error connecting to %s:%d", cups_printer ->hostname, cups_printer->port); }; } while (0) |
743 | cups_printer->hostname,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error connecting to %s:%d", cups_printer ->hostname, cups_printer->port); }; } while (0) |
744 | cups_printer->port))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error connecting to %s:%d", cups_printer ->hostname, cups_printer->port); }; } while (0); |
745 | |
746 | error = g_error_new (ctk_print_error_quark (), |
747 | CTK_CUPS_ERROR_GENERAL, |
748 | "Error connecting to %s", |
749 | cups_printer->hostname); |
750 | |
751 | ctk_print_job_set_status (job, CTK_PRINT_STATUS_FINISHED_ABORTED); |
752 | |
753 | if (callback) |
754 | { |
755 | callback (job, user_data, error); |
756 | } |
757 | |
758 | g_clear_error (&error); |
759 | |
760 | return; |
761 | } |
762 | } |
763 | else |
764 | { |
765 | request = ctk_cups_request_new_with_username (NULL((void*)0), |
766 | CTK_CUPS_POST, |
767 | IPP_PRINT_JOBIPP_OP_PRINT_JOB, |
768 | data_io, |
769 | NULL((void*)0), |
770 | cups_printer->device_uri, |
771 | CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ()))))))->username); |
772 | |
773 | httpAssembleURIf (HTTP_URI_CODING_ALL, |
774 | printer_absolute_uri, |
775 | sizeof (printer_absolute_uri), |
776 | "ipp", |
777 | NULL((void*)0), |
778 | "localhost", |
779 | ippPort (), |
780 | "/printers/%s", |
781 | ctk_printer_get_name (ctk_print_job_get_printer (job))); |
782 | } |
783 | |
784 | ctk_cups_request_set_ipp_version (request, |
785 | cups_printer->ipp_version_major, |
786 | cups_printer->ipp_version_minor); |
787 | |
788 | ctk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, |
789 | IPP_TAG_URI, "printer-uri", |
790 | NULL((void*)0), printer_absolute_uri); |
791 | |
792 | title = ctk_print_job_get_title (job); |
793 | if (title) { |
794 | char *title_truncated = NULL((void*)0); |
795 | size_t title_bytes = strlen (title); |
796 | |
797 | if (title_bytes >= IPP_MAX_NAME256) |
798 | { |
799 | gchar *end; |
800 | |
801 | end = g_utf8_find_prev_char (title, title + IPP_MAX_NAME256 - 1); |
802 | title_truncated = g_utf8_substring (title, |
803 | 0, |
804 | g_utf8_pointer_to_offset (title, end)); |
805 | } |
806 | |
807 | ctk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, |
808 | IPP_TAG_NAME, "job-name", |
809 | NULL((void*)0), |
810 | title_truncated ? title_truncated : title); |
811 | g_free (title_truncated); |
812 | } |
813 | |
814 | g_object_get (job, |
815 | "page-setup", &page_setup, |
816 | NULL((void*)0)); |
817 | |
818 | options_data = g_new0 (CupsOptionsData, 1)((CupsOptionsData *) g_malloc0_n ((1), sizeof (CupsOptionsData ))); |
819 | options_data->request = request; |
820 | options_data->printer = cups_printer; |
821 | options_data->page_setup = page_setup; |
822 | ctk_print_settings_foreach (settings, add_cups_options, options_data); |
823 | g_clear_object (&page_setup)do { _Static_assert (sizeof *((&page_setup)) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ (((&page_setup ))) _pp = ((&page_setup)); __typeof__ (*((&page_setup ))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref ) (_ptr); } while (0); |
824 | g_free (options_data); |
825 | |
826 | ps = g_new0 (CupsPrintStreamData, 1)((CupsPrintStreamData *) g_malloc0_n ((1), sizeof (CupsPrintStreamData ))); |
827 | ps->callback = callback; |
828 | ps->user_data = user_data; |
829 | ps->dnotify = dnotify; |
830 | ps->job = g_object_ref (job)((__typeof__ (job)) (g_object_ref) (job)); |
831 | ps->http = http; |
832 | |
833 | request->need_auth_info = FALSE(0); |
834 | request->auth_info_required = NULL((void*)0); |
835 | |
836 | /* Check if auth_info_required is set and if it should be handled. |
837 | * The cups libraries handle the ticket exchange for "negotiate". */ |
838 | if (cups_printer->auth_info_required != NULL((void*)0) && |
839 | g_strv_length (cups_printer->auth_info_required) == 1 && |
840 | g_strcmp0 (cups_printer->auth_info_required[0], "negotiate") == 0) |
841 | { |
842 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Ignoring auth-info-required \"%s\"\n" , cups_printer->auth_info_required[0]); }; } while (0) |
843 | g_print ("CUPS Backend: Ignoring auth-info-required \"%s\"\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Ignoring auth-info-required \"%s\"\n" , cups_printer->auth_info_required[0]); }; } while (0) |
844 | cups_printer->auth_info_required[0]))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Ignoring auth-info-required \"%s\"\n" , cups_printer->auth_info_required[0]); }; } while (0); |
845 | } |
846 | else if (cups_printer->auth_info_required != NULL((void*)0)) |
847 | { |
848 | request->need_auth_info = TRUE(!(0)); |
849 | request->auth_info_required = g_strdupv (cups_printer->auth_info_required); |
850 | } |
851 | |
852 | cups_request_execute (CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ())))))), |
853 | request, |
854 | (CtkPrintCupsResponseCallbackFunc) cups_print_cb, |
855 | ps, |
856 | (GDestroyNotify)cups_free_print_stream_data); |
857 | } |
858 | |
859 | void overwrite_and_free (gpointer data) |
860 | { |
861 | gchar *password = (gchar *) data; |
862 | |
863 | if (password != NULL((void*)0)) |
864 | { |
865 | memset (password, 0, strlen (password)); |
866 | g_free (password); |
867 | } |
868 | } |
869 | |
870 | static void |
871 | ctk_print_backend_cups_init (CtkPrintBackendCups *backend_cups) |
872 | { |
873 | int i; |
874 | |
875 | backend_cups->list_printers_poll = FALSE(0); |
876 | backend_cups->got_default_printer = FALSE(0); |
877 | backend_cups->list_printers_pending = FALSE(0); |
878 | backend_cups->list_printers_attempts = 0; |
879 | backend_cups->reading_ppds = 0; |
880 | |
881 | backend_cups->requests = NULL((void*)0); |
882 | backend_cups->auth = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, overwrite_and_free); |
883 | backend_cups->authentication_lock = FALSE(0); |
884 | |
885 | backend_cups->default_printer_poll = 0; |
886 | backend_cups->cups_connection_test = NULL((void*)0); |
887 | |
888 | backend_cups->username = NULL((void*)0); |
889 | |
890 | #ifdef HAVE_COLORD1 |
891 | backend_cups->colord_client = cd_client_new (); |
892 | #endif |
893 | |
894 | backend_cups->dbus_connection = NULL((void*)0); |
895 | backend_cups->avahi_default_printer = NULL((void*)0); |
896 | backend_cups->avahi_service_browser_subscription_id = 0; |
897 | for (i = 0; i < 2; i++) |
898 | { |
899 | backend_cups->avahi_service_browser_paths[i] = NULL((void*)0); |
900 | backend_cups->avahi_service_browser_subscription_ids[i] = 0; |
901 | } |
902 | |
903 | cups_get_local_default_printer (backend_cups); |
904 | |
905 | backend_cups->secrets_service_available = FALSE(0); |
906 | backend_cups->secrets_service_cancellable = g_cancellable_new (); |
907 | backend_cups->secrets_service_watch_id = |
908 | ctk_cups_secrets_service_watch (secrets_service_appeared_cb, |
909 | secrets_service_vanished_cb, |
910 | backend_cups); |
911 | |
912 | backend_cups->temporary_queues_in_construction = NULL((void*)0); |
913 | backend_cups->temporary_queues_removed = NULL((void*)0); |
914 | } |
915 | |
916 | static void |
917 | ctk_print_backend_cups_finalize (GObject *object) |
918 | { |
919 | CtkPrintBackendCups *backend_cups; |
920 | |
921 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: finalizing CUPS backend module\n"); } ; } while (0) |
922 | g_print ("CUPS Backend: finalizing CUPS backend module\n"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: finalizing CUPS backend module\n"); } ; } while (0); |
923 | |
924 | backend_cups = CTK_PRINT_BACKEND_CUPS (object)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((object)), ((ctk_print_backend_cups_get_type ())))))); |
925 | |
926 | g_free (backend_cups->default_printer); |
927 | backend_cups->default_printer = NULL((void*)0); |
928 | |
929 | ctk_cups_connection_test_free (backend_cups->cups_connection_test); |
930 | backend_cups->cups_connection_test = NULL((void*)0); |
931 | |
932 | g_hash_table_destroy (backend_cups->auth); |
933 | |
934 | g_free (backend_cups->username); |
935 | |
936 | #ifdef HAVE_COLORD1 |
937 | g_object_unref (backend_cups->colord_client); |
938 | #endif |
939 | |
940 | g_clear_object (&backend_cups->avahi_cancellable)do { _Static_assert (sizeof *((&backend_cups->avahi_cancellable )) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&backend_cups->avahi_cancellable))) _pp = ((&backend_cups ->avahi_cancellable)); __typeof__ (*((&backend_cups-> avahi_cancellable))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr ) (g_object_unref) (_ptr); } while (0); |
941 | g_clear_pointer (&backend_cups->avahi_default_printer, g_free)do { _Static_assert (sizeof *(&backend_cups->avahi_default_printer ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&backend_cups->avahi_default_printer)) _pp = (& backend_cups->avahi_default_printer); __typeof__ (*(&backend_cups ->avahi_default_printer)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
942 | g_clear_object (&backend_cups->dbus_connection)do { _Static_assert (sizeof *((&backend_cups->dbus_connection )) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&backend_cups->dbus_connection))) _pp = ((&backend_cups ->dbus_connection)); __typeof__ (*((&backend_cups-> dbus_connection))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) ( g_object_unref) (_ptr); } while (0); |
943 | |
944 | g_clear_object (&backend_cups->secrets_service_cancellable)do { _Static_assert (sizeof *((&backend_cups->secrets_service_cancellable )) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&backend_cups->secrets_service_cancellable))) _pp = ((&backend_cups->secrets_service_cancellable)); __typeof__ (*((&backend_cups->secrets_service_cancellable))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr) ; } while (0); |
945 | if (backend_cups->secrets_service_watch_id != 0) |
946 | { |
947 | g_bus_unwatch_name (backend_cups->secrets_service_watch_id); |
948 | } |
949 | |
950 | g_list_free_full (backend_cups->temporary_queues_in_construction, g_free); |
951 | backend_cups->temporary_queues_in_construction = NULL((void*)0); |
952 | |
953 | g_list_free_full (backend_cups->temporary_queues_removed, g_free); |
954 | backend_cups->temporary_queues_removed = NULL((void*)0); |
955 | |
956 | backend_parent_class->finalize (object); |
957 | } |
958 | |
959 | static void |
960 | ctk_print_backend_cups_dispose (GObject *object) |
961 | { |
962 | CtkPrintBackendCups *backend_cups; |
963 | int i; |
964 | |
965 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
966 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
967 | |
968 | backend_cups = CTK_PRINT_BACKEND_CUPS (object)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((object)), ((ctk_print_backend_cups_get_type ())))))); |
969 | |
970 | if (backend_cups->list_printers_poll > 0) |
971 | g_source_remove (backend_cups->list_printers_poll); |
972 | backend_cups->list_printers_poll = 0; |
973 | backend_cups->list_printers_attempts = 0; |
974 | |
975 | if (backend_cups->default_printer_poll > 0) |
976 | g_source_remove (backend_cups->default_printer_poll); |
977 | backend_cups->default_printer_poll = 0; |
978 | |
979 | g_cancellable_cancel (backend_cups->avahi_cancellable); |
980 | |
981 | for (i = 0; i < 2; i++) |
982 | { |
983 | if (backend_cups->avahi_service_browser_subscription_ids[i] > 0) |
984 | { |
985 | g_dbus_connection_signal_unsubscribe (backend_cups->dbus_connection, |
986 | backend_cups->avahi_service_browser_subscription_ids[i]); |
987 | backend_cups->avahi_service_browser_subscription_ids[i] = 0; |
988 | } |
989 | |
990 | if (backend_cups->avahi_service_browser_paths[i]) |
991 | { |
992 | g_dbus_connection_call (backend_cups->dbus_connection, |
993 | AVAHI_BUS"org.freedesktop.Avahi", |
994 | backend_cups->avahi_service_browser_paths[i], |
995 | AVAHI_SERVICE_BROWSER_IFACE"org.freedesktop.Avahi.ServiceBrowser", |
996 | "Free", |
997 | NULL((void*)0), |
998 | NULL((void*)0), |
999 | G_DBUS_CALL_FLAGS_NONE, |
1000 | -1, |
1001 | NULL((void*)0), |
1002 | NULL((void*)0), |
1003 | NULL((void*)0)); |
1004 | g_clear_pointer (&backend_cups->avahi_service_browser_paths[i], g_free)do { _Static_assert (sizeof *(&backend_cups->avahi_service_browser_paths [i]) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&backend_cups->avahi_service_browser_paths[i])) _pp = (&backend_cups->avahi_service_browser_paths[i]); __typeof__ (*(&backend_cups->avahi_service_browser_paths[i])) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
1005 | } |
1006 | } |
1007 | |
1008 | if (backend_cups->avahi_service_browser_subscription_id > 0) |
1009 | { |
1010 | g_dbus_connection_signal_unsubscribe (backend_cups->dbus_connection, |
1011 | backend_cups->avahi_service_browser_subscription_id); |
1012 | backend_cups->avahi_service_browser_subscription_id = 0; |
1013 | } |
1014 | |
1015 | if (backend_cups->unsubscribe_general_subscription_id > 0) |
1016 | { |
1017 | g_source_remove (backend_cups->unsubscribe_general_subscription_id); |
1018 | backend_cups->unsubscribe_general_subscription_id = 0; |
1019 | } |
1020 | |
1021 | backend_parent_class->dispose (object); |
1022 | } |
1023 | |
1024 | static gboolean |
1025 | is_address_local (const gchar *address) |
1026 | { |
1027 | if (address[0] == '/' || |
1028 | strcmp (address, "127.0.0.1") == 0 || |
1029 | strcmp (address, "[::1]") == 0) |
1030 | return TRUE(!(0)); |
1031 | else |
1032 | return FALSE(0); |
1033 | } |
1034 | |
1035 | static void |
1036 | ctk_print_backend_cups_set_password (CtkPrintBackend *backend, |
1037 | gchar **auth_info_required, |
1038 | gchar **auth_info, |
1039 | gboolean store_auth_info) |
1040 | { |
1041 | CtkPrintBackendCups *cups_backend = CTK_PRINT_BACKEND_CUPS (backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((backend)), ((ctk_print_backend_cups_get_type ())))))); |
1042 | GList *l; |
1043 | char dispatch_hostname[HTTP_MAX_URI1024]; |
1044 | gchar *username = NULL((void*)0); |
1045 | gchar *hostname = NULL((void*)0); |
1046 | gchar *password = NULL((void*)0); |
1047 | gint length; |
1048 | gint i; |
1049 | |
1050 | length = g_strv_length (auth_info_required); |
1051 | |
1052 | if (auth_info != NULL((void*)0)) |
1053 | for (i = 0; i < length; i++) |
1054 | { |
1055 | if (g_strcmp0 (auth_info_required[i], "username") == 0) |
1056 | username = g_strdup (auth_info[i])g_strdup_inline (auth_info[i]); |
1057 | else if (g_strcmp0 (auth_info_required[i], "hostname") == 0) |
1058 | hostname = g_strdup (auth_info[i])g_strdup_inline (auth_info[i]); |
1059 | else if (g_strcmp0 (auth_info_required[i], "password") == 0) |
1060 | password = g_strdup (auth_info[i])g_strdup_inline (auth_info[i]); |
1061 | } |
1062 | |
1063 | if (hostname != NULL((void*)0) && username != NULL((void*)0) && password != NULL((void*)0)) |
1064 | { |
1065 | gchar *key = g_strconcat (username, "@", hostname, NULL((void*)0)); |
1066 | g_hash_table_insert (cups_backend->auth, key, g_strdup (password)g_strdup_inline (password)); |
1067 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: caching password for %s\n", key); }; } while (0) |
1068 | g_print ("CUPS backend: caching password for %s\n", key))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: caching password for %s\n", key); }; } while (0); |
1069 | } |
1070 | |
1071 | g_free (cups_backend->username); |
1072 | cups_backend->username = g_strdup (username)g_strdup_inline (username); |
1073 | |
1074 | |
1075 | for (l = cups_backend->requests; l; l = l->next) |
1076 | { |
1077 | CtkPrintCupsDispatchWatch *dispatch = l->data; |
1078 | |
1079 | httpGetHostname (dispatch->request->http, dispatch_hostname, sizeof (dispatch_hostname)); |
1080 | if (is_address_local (dispatch_hostname)) |
1081 | strcpy (dispatch_hostname, "localhost"); |
1082 | |
1083 | if (dispatch->request->need_auth_info) |
1084 | { |
1085 | if (auth_info != NULL((void*)0)) |
1086 | { |
1087 | dispatch->request->auth_info = g_new0 (gchar *, length + 1)((gchar * *) g_malloc0_n ((length + 1), sizeof (gchar *))); |
1088 | for (i = 0; i < length; i++) |
1089 | dispatch->request->auth_info[i] = g_strdup (auth_info[i])g_strdup_inline (auth_info[i]); |
1090 | } |
1091 | /* Save the password if the user requested it */ |
1092 | if (password != NULL((void*)0) && store_auth_info) |
1093 | { |
1094 | const gchar *printer_uri = |
1095 | ctk_cups_request_ipp_get_string (dispatch->request, |
1096 | IPP_TAG_URI, |
1097 | "printer-uri"); |
1098 | |
1099 | ctk_cups_secrets_service_store (auth_info, auth_info_required, |
1100 | printer_uri); |
1101 | } |
1102 | dispatch->backend->authentication_lock = FALSE(0); |
1103 | dispatch->request->need_auth_info = FALSE(0); |
1104 | } |
1105 | else if (dispatch->request->password_state == CTK_CUPS_PASSWORD_REQUESTED || auth_info == NULL((void*)0)) |
1106 | { |
1107 | overwrite_and_free (dispatch->request->password); |
1108 | dispatch->request->password = g_strdup (password)g_strdup_inline (password); |
1109 | g_free (dispatch->request->username); |
1110 | dispatch->request->username = g_strdup (username)g_strdup_inline (username); |
1111 | dispatch->request->password_state = CTK_CUPS_PASSWORD_HAS; |
1112 | dispatch->backend->authentication_lock = FALSE(0); |
1113 | } |
1114 | } |
1115 | } |
1116 | |
1117 | static gboolean |
1118 | request_password (gpointer data) |
1119 | { |
1120 | CtkPrintCupsDispatchWatch *dispatch = data; |
1121 | const gchar *username; |
1122 | gchar *password; |
1123 | gchar *prompt = NULL((void*)0); |
1124 | gchar *key = NULL((void*)0); |
1125 | char hostname[HTTP_MAX_URI1024]; |
1126 | gchar **auth_info_required; |
1127 | gchar **auth_info_default; |
1128 | gchar **auth_info_display; |
1129 | gboolean *auth_info_visible; |
1130 | gint length = 3; |
1131 | gint i; |
1132 | |
1133 | if (dispatch->backend->authentication_lock) |
1134 | return G_SOURCE_REMOVE(0); |
1135 | |
1136 | httpGetHostname (dispatch->request->http, hostname, sizeof (hostname)); |
1137 | if (is_address_local (hostname)) |
1138 | strcpy (hostname, "localhost"); |
1139 | |
1140 | if (dispatch->backend->username != NULL((void*)0)) |
1141 | username = dispatch->backend->username; |
1142 | else |
1143 | username = cupsUser (); |
1144 | |
1145 | auth_info_required = g_new0 (gchar*, length + 1)((gchar* *) g_malloc0_n ((length + 1), sizeof (gchar*))); |
1146 | auth_info_required[0] = g_strdup ("hostname")g_strdup_inline ("hostname"); |
1147 | auth_info_required[1] = g_strdup ("username")g_strdup_inline ("username"); |
1148 | auth_info_required[2] = g_strdup ("password")g_strdup_inline ("password"); |
1149 | |
1150 | auth_info_default = g_new0 (gchar*, length + 1)((gchar* *) g_malloc0_n ((length + 1), sizeof (gchar*))); |
1151 | auth_info_default[0] = g_strdup (hostname)g_strdup_inline (hostname); |
1152 | auth_info_default[1] = g_strdup (username)g_strdup_inline (username); |
1153 | |
1154 | auth_info_display = g_new0 (gchar*, length + 1)((gchar* *) g_malloc0_n ((length + 1), sizeof (gchar*))); |
1155 | auth_info_display[1] = g_strdup (_("Username:"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Username:")) ); |
1156 | auth_info_display[2] = g_strdup (_("Password:"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Password:")) ); |
1157 | |
1158 | auth_info_visible = g_new0 (gboolean, length + 1)((gboolean *) g_malloc0_n ((length + 1), sizeof (gboolean))); |
1159 | auth_info_visible[1] = TRUE(!(0)); |
1160 | |
1161 | key = g_strconcat (username, "@", hostname, NULL((void*)0)); |
1162 | password = g_hash_table_lookup (dispatch->backend->auth, key); |
1163 | |
1164 | if (password && dispatch->request->password_state != CTK_CUPS_PASSWORD_NOT_VALID) |
1165 | { |
1166 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: using stored password for %s\n", key ); }; } while (0) |
1167 | g_print ("CUPS backend: using stored password for %s\n", key))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: using stored password for %s\n", key ); }; } while (0); |
1168 | |
1169 | overwrite_and_free (dispatch->request->password); |
1170 | dispatch->request->password = g_strdup (password)g_strdup_inline (password); |
1171 | g_free (dispatch->request->username); |
1172 | dispatch->request->username = g_strdup (username)g_strdup_inline (username); |
1173 | dispatch->request->password_state = CTK_CUPS_PASSWORD_HAS; |
1174 | } |
1175 | else |
1176 | { |
1177 | const char *job_title = ctk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_NAME, "job-name"); |
1178 | const char *printer_uri = ctk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_URI, "printer-uri"); |
1179 | char *printer_name = NULL((void*)0); |
1180 | |
1181 | if (printer_uri != NULL((void*)0) && strrchr (printer_uri, '/') != NULL((void*)0)) |
1182 | printer_name = g_strdup (strrchr (printer_uri, '/') + 1)g_strdup_inline (strrchr (printer_uri, '/') + 1); |
1183 | |
1184 | if (dispatch->request->password_state == CTK_CUPS_PASSWORD_NOT_VALID) |
1185 | g_hash_table_remove (dispatch->backend->auth, key); |
1186 | |
1187 | dispatch->request->password_state = CTK_CUPS_PASSWORD_REQUESTED; |
1188 | |
1189 | dispatch->backend->authentication_lock = TRUE(!(0)); |
1190 | |
1191 | switch (ippGetOperation (dispatch->request->ipp_request)) |
1192 | { |
1193 | case IPP_PRINT_JOBIPP_OP_PRINT_JOB: |
1194 | if (job_title != NULL((void*)0) && printer_name != NULL((void*)0)) |
1195 | prompt = g_strdup_printf ( _("Authentication is required to print document “%s” on printer %s")((char *) g_dgettext ("ctk30", "Authentication is required to print document “%s” on printer %s" )), job_title, printer_name); |
1196 | else |
1197 | prompt = g_strdup_printf ( _("Authentication is required to print a document on %s")((char *) g_dgettext ("ctk30", "Authentication is required to print a document on %s" )), hostname); |
1198 | break; |
1199 | case IPP_GET_JOB_ATTRIBUTESIPP_OP_GET_JOB_ATTRIBUTES: |
1200 | if (job_title != NULL((void*)0)) |
1201 | prompt = g_strdup_printf ( _("Authentication is required to get attributes of job “%s”")((char *) g_dgettext ("ctk30", "Authentication is required to get attributes of job “%s”" )), job_title); |
1202 | else |
1203 | prompt = g_strdup ( _("Authentication is required to get attributes of a job"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Authentication is required to get attributes of a job" ))); |
1204 | break; |
1205 | case IPP_GET_PRINTER_ATTRIBUTESIPP_OP_GET_PRINTER_ATTRIBUTES: |
1206 | if (printer_name != NULL((void*)0)) |
1207 | prompt = g_strdup_printf ( _("Authentication is required to get attributes of printer %s")((char *) g_dgettext ("ctk30", "Authentication is required to get attributes of printer %s" )), printer_name); |
1208 | else |
1209 | prompt = g_strdup ( _("Authentication is required to get attributes of a printer"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Authentication is required to get attributes of a printer" ))); |
1210 | break; |
1211 | case CUPS_GET_DEFAULTIPP_OP_CUPS_GET_DEFAULT: |
1212 | prompt = g_strdup_printf ( _("Authentication is required to get default printer of %s")((char *) g_dgettext ("ctk30", "Authentication is required to get default printer of %s" )), hostname); |
1213 | break; |
1214 | case CUPS_GET_PRINTERSIPP_OP_CUPS_GET_PRINTERS: |
1215 | prompt = g_strdup_printf ( _("Authentication is required to get printers from %s")((char *) g_dgettext ("ctk30", "Authentication is required to get printers from %s" )), hostname); |
1216 | break; |
1217 | default: |
1218 | /* work around gcc warning about 0 not being a value for this enum */ |
1219 | if (ippGetOperation (dispatch->request->ipp_request) == 0) |
1220 | prompt = g_strdup_printf ( _("Authentication is required to get a file from %s")((char *) g_dgettext ("ctk30", "Authentication is required to get a file from %s" )), hostname); |
1221 | else |
1222 | prompt = g_strdup_printf ( _("Authentication is required on %s")((char *) g_dgettext ("ctk30", "Authentication is required on %s" )), hostname); |
1223 | break; |
1224 | } |
1225 | |
1226 | g_free (printer_name); |
1227 | |
1228 | g_signal_emit_by_name (dispatch->backend, "request-password", |
1229 | auth_info_required, auth_info_default, |
1230 | auth_info_display, auth_info_visible, prompt, |
1231 | FALSE(0)); /* Cups password is only cached not stored. */ |
1232 | |
1233 | g_free (prompt); |
1234 | } |
1235 | |
1236 | for (i = 0; i < length; i++) |
1237 | { |
1238 | g_free (auth_info_required[i]); |
1239 | g_free (auth_info_default[i]); |
1240 | g_free (auth_info_display[i]); |
1241 | } |
1242 | |
1243 | g_free (auth_info_required); |
1244 | g_free (auth_info_default); |
1245 | g_free (auth_info_display); |
1246 | g_free (auth_info_visible); |
1247 | g_free (key); |
1248 | |
1249 | return G_SOURCE_REMOVE(0); |
1250 | } |
1251 | |
1252 | static void |
1253 | cups_dispatch_add_poll (GSource *source) |
1254 | { |
1255 | CtkPrintCupsDispatchWatch *dispatch; |
1256 | CtkCupsPollState poll_state; |
1257 | |
1258 | dispatch = (CtkPrintCupsDispatchWatch *) source; |
1259 | |
1260 | poll_state = ctk_cups_request_get_poll_state (dispatch->request); |
1261 | |
1262 | /* Remove the old source if the poll state changed. */ |
1263 | if (poll_state != dispatch->poll_state && dispatch->data_poll != NULL((void*)0)) |
1264 | { |
1265 | g_source_remove_poll (source, dispatch->data_poll); |
1266 | g_free (dispatch->data_poll); |
1267 | dispatch->data_poll = NULL((void*)0); |
1268 | } |
1269 | |
1270 | if (dispatch->request->http != NULL((void*)0)) |
1271 | { |
1272 | if (dispatch->data_poll == NULL((void*)0)) |
1273 | { |
1274 | dispatch->data_poll = g_new0 (GPollFD, 1)((GPollFD *) g_malloc0_n ((1), sizeof (GPollFD))); |
1275 | dispatch->poll_state = poll_state; |
1276 | |
1277 | if (poll_state == CTK_CUPS_HTTP_READ) |
1278 | dispatch->data_poll->events = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI; |
1279 | else if (poll_state == CTK_CUPS_HTTP_WRITE) |
1280 | dispatch->data_poll->events = G_IO_OUT | G_IO_ERR; |
1281 | else |
1282 | dispatch->data_poll->events = 0; |
1283 | |
1284 | dispatch->data_poll->fd = httpGetFd (dispatch->request->http); |
1285 | g_source_add_poll (source, dispatch->data_poll); |
1286 | } |
1287 | } |
1288 | } |
1289 | |
1290 | static gboolean |
1291 | check_auth_info (gpointer user_data) |
1292 | { |
1293 | CtkPrintCupsDispatchWatch *dispatch; |
1294 | dispatch = (CtkPrintCupsDispatchWatch *) user_data; |
1295 | |
1296 | if (!dispatch->request->need_auth_info) |
1297 | { |
1298 | if (dispatch->request->auth_info == NULL((void*)0)) |
1299 | { |
1300 | dispatch->callback (CTK_PRINT_BACKEND (dispatch->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dispatch->backend)), ((ctk_print_backend_get_type ()) ))))), |
1301 | ctk_cups_request_get_result (dispatch->request), |
1302 | dispatch->callback_data); |
1303 | g_source_destroy ((GSource *) dispatch); |
1304 | } |
1305 | else |
1306 | { |
1307 | gint length; |
1308 | gint i; |
1309 | |
1310 | length = g_strv_length (dispatch->request->auth_info_required); |
1311 | |
1312 | ctk_cups_request_ipp_add_strings (dispatch->request, |
1313 | IPP_TAG_JOB, |
1314 | IPP_TAG_TEXT, |
1315 | "auth-info", |
1316 | length, |
1317 | NULL((void*)0), |
1318 | (const char * const *) dispatch->request->auth_info); |
1319 | |
1320 | g_source_attach ((GSource *) dispatch, NULL((void*)0)); |
1321 | g_source_unref ((GSource *) dispatch); |
1322 | |
1323 | for (i = 0; i < length; i++) |
1324 | overwrite_and_free (dispatch->request->auth_info[i]); |
1325 | g_free (dispatch->request->auth_info); |
1326 | dispatch->request->auth_info = NULL((void*)0); |
1327 | } |
1328 | |
1329 | return G_SOURCE_REMOVE(0); |
1330 | } |
1331 | |
1332 | return G_SOURCE_CONTINUE(!(0)); |
1333 | } |
1334 | |
1335 | static void |
1336 | lookup_auth_info_cb (GObject *source_object G_GNUC_UNUSED__attribute__ ((__unused__)), |
1337 | GAsyncResult *res, |
1338 | gpointer user_data) |
1339 | { |
1340 | GTask *task; |
1341 | CtkPrintCupsDispatchWatch *dispatch; |
1342 | gchar **auth_info; |
1343 | GError *error = NULL((void*)0); |
1344 | gint i; |
1345 | |
1346 | task = (GTask *) res; |
1347 | dispatch = user_data; |
1348 | auth_info = g_task_propagate_pointer (task, &error); |
1349 | |
1350 | if (auth_info == NULL((void*)0)) |
1351 | { |
1352 | if (error != NULL((void*)0)) |
1353 | { |
1354 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("Failed to look up auth info: %s\n", error->message ); }; } while (0) |
1355 | g_print ("Failed to look up auth info: %s\n", error->message))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("Failed to look up auth info: %s\n", error->message ); }; } while (0); |
1356 | g_error_free (error); |
1357 | } |
1358 | else |
1359 | { |
1360 | /* Error note should have been shown by the function causing this */ |
1361 | CTK_NOTE (PRINTING, g_print ("Failed to look up auth info.\n"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("Failed to look up auth info.\n"); }; } while (0); |
1362 | } |
1363 | dispatch->backend->authentication_lock = FALSE(0); |
1364 | g_object_unref (task); |
1365 | request_auth_info (dispatch); |
1366 | return; |
1367 | } |
1368 | |
1369 | ctk_print_backend_cups_set_password (CTK_PRINT_BACKEND (dispatch->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dispatch->backend)), ((ctk_print_backend_get_type ()) ))))), |
1370 | dispatch->request->auth_info_required, auth_info, |
1371 | FALSE(0)); |
1372 | for (i = 0; auth_info[i] != NULL((void*)0); i++) |
1373 | { |
1374 | overwrite_and_free (auth_info[i]); |
1375 | auth_info[i] = NULL((void*)0); |
1376 | } |
1377 | g_clear_pointer (auth_info, g_free)do { _Static_assert (sizeof *(auth_info) == sizeof (gpointer) , "Expression evaluates to false"); __typeof__ ((auth_info)) _pp = (auth_info); __typeof__ (*(auth_info)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
1378 | |
1379 | g_object_unref (task); |
1380 | } |
1381 | |
1382 | static void |
1383 | lookup_auth_info (gpointer user_data) |
1384 | { |
1385 | CtkPrintCupsDispatchWatch *dispatch; |
1386 | gsize length, |
1387 | i; |
1388 | gboolean need_secret_auth_info = FALSE(0); |
1389 | |
1390 | dispatch = user_data; |
1391 | |
1392 | if (dispatch->backend->authentication_lock) |
1393 | return; |
1394 | |
1395 | length = g_strv_length (dispatch->request->auth_info_required); |
1396 | |
1397 | for (i = 0; i < length; i++) |
1398 | { |
1399 | if (g_strcmp0 (dispatch->request->auth_info_required[i], "password") == 0) |
1400 | { |
1401 | need_secret_auth_info = TRUE(!(0)); |
1402 | break; |
1403 | } |
1404 | } |
1405 | |
1406 | g_idle_add (check_auth_info, user_data); |
1407 | |
1408 | if (dispatch->backend->secrets_service_available && need_secret_auth_info) |
1409 | { |
1410 | const gchar *printer_uri; |
1411 | |
1412 | dispatch->backend->authentication_lock = TRUE(!(0)); |
1413 | printer_uri = ctk_cups_request_ipp_get_string (dispatch->request, |
1414 | IPP_TAG_URI, |
1415 | "printer-uri"); |
1416 | ctk_cups_secrets_service_query_task (dispatch->backend, |
1417 | dispatch->backend->secrets_service_cancellable, |
1418 | lookup_auth_info_cb, |
1419 | dispatch, |
1420 | printer_uri, |
1421 | dispatch->request->auth_info_required); |
1422 | return; |
1423 | } |
1424 | |
1425 | request_auth_info (user_data); |
1426 | } |
1427 | |
1428 | static gboolean |
1429 | request_auth_info (gpointer user_data) |
1430 | { |
1431 | CtkPrintCupsDispatchWatch *dispatch; |
1432 | const char *job_title; |
1433 | const char *printer_uri; |
1434 | gchar *prompt = NULL((void*)0); |
1435 | char *printer_name = NULL((void*)0); |
1436 | gint length; |
1437 | gint i; |
1438 | gboolean *auth_info_visible = NULL((void*)0); |
1439 | gchar **auth_info_default = NULL((void*)0); |
1440 | gchar **auth_info_display = NULL((void*)0); |
1441 | |
1442 | dispatch = (CtkPrintCupsDispatchWatch *) user_data; |
1443 | |
1444 | if (dispatch->backend->authentication_lock) |
1445 | return FALSE(0); |
1446 | |
1447 | job_title = ctk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_NAME, "job-name"); |
1448 | printer_uri = ctk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_URI, "printer-uri"); |
1449 | length = g_strv_length (dispatch->request->auth_info_required); |
1450 | |
1451 | auth_info_visible = g_new0 (gboolean, length)((gboolean *) g_malloc0_n ((length), sizeof (gboolean))); |
1452 | auth_info_default = g_new0 (gchar *, length + 1)((gchar * *) g_malloc0_n ((length + 1), sizeof (gchar *))); |
1453 | auth_info_display = g_new0 (gchar *, length + 1)((gchar * *) g_malloc0_n ((length + 1), sizeof (gchar *))); |
1454 | |
1455 | for (i = 0; i < length; i++) |
1456 | { |
1457 | if (g_strcmp0 (dispatch->request->auth_info_required[i], "domain") == 0) |
1458 | { |
1459 | auth_info_display[i] = g_strdup (_("Domain:"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Domain:"))); |
1460 | auth_info_default[i] = g_strdup ("WORKGROUP")g_strdup_inline ("WORKGROUP"); |
1461 | auth_info_visible[i] = TRUE(!(0)); |
1462 | } |
1463 | else if (g_strcmp0 (dispatch->request->auth_info_required[i], "username") == 0) |
1464 | { |
1465 | auth_info_display[i] = g_strdup (_("Username:"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Username:")) ); |
1466 | if (dispatch->backend->username != NULL((void*)0)) |
1467 | auth_info_default[i] = g_strdup (dispatch->backend->username)g_strdup_inline (dispatch->backend->username); |
1468 | else |
1469 | auth_info_default[i] = g_strdup (cupsUser ())g_strdup_inline (cupsUser ()); |
1470 | auth_info_visible[i] = TRUE(!(0)); |
1471 | } |
1472 | else if (g_strcmp0 (dispatch->request->auth_info_required[i], "password") == 0) |
1473 | { |
1474 | auth_info_display[i] = g_strdup (_("Password:"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Password:")) ); |
1475 | auth_info_visible[i] = FALSE(0); |
1476 | } |
1477 | } |
1478 | |
1479 | if (printer_uri != NULL((void*)0) && strrchr (printer_uri, '/') != NULL((void*)0)) |
1480 | printer_name = g_strdup (strrchr (printer_uri, '/') + 1)g_strdup_inline (strrchr (printer_uri, '/') + 1); |
1481 | |
1482 | dispatch->backend->authentication_lock = TRUE(!(0)); |
1483 | |
1484 | if (job_title != NULL((void*)0)) |
1485 | { |
1486 | if (printer_name != NULL((void*)0)) |
1487 | prompt = g_strdup_printf ( _("Authentication is required to print document “%s” on printer %s")((char *) g_dgettext ("ctk30", "Authentication is required to print document “%s” on printer %s" )), job_title, printer_name); |
1488 | else |
1489 | prompt = g_strdup_printf ( _("Authentication is required to print document “%s”")((char *) g_dgettext ("ctk30", "Authentication is required to print document “%s”" )), job_title); |
1490 | } |
1491 | else |
1492 | { |
1493 | if (printer_name != NULL((void*)0)) |
1494 | prompt = g_strdup_printf ( _("Authentication is required to print this document on printer %s")((char *) g_dgettext ("ctk30", "Authentication is required to print this document on printer %s" )), printer_name); |
1495 | else |
1496 | prompt = g_strdup ( _("Authentication is required to print this document"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Authentication is required to print this document" ))); |
1497 | } |
1498 | |
1499 | g_signal_emit_by_name (dispatch->backend, "request-password", |
1500 | dispatch->request->auth_info_required, |
1501 | auth_info_default, |
1502 | auth_info_display, |
1503 | auth_info_visible, |
1504 | prompt, |
1505 | dispatch->backend->secrets_service_available); |
1506 | |
1507 | for (i = 0; i < length; i++) |
1508 | { |
1509 | g_free (auth_info_default[i]); |
1510 | g_free (auth_info_display[i]); |
1511 | } |
1512 | |
1513 | g_free (auth_info_default); |
1514 | g_free (auth_info_display); |
1515 | g_free (printer_name); |
1516 | g_free (prompt); |
1517 | |
1518 | return FALSE(0); |
1519 | } |
1520 | |
1521 | static gboolean |
1522 | cups_dispatch_watch_check (GSource *source) |
1523 | { |
1524 | CtkPrintCupsDispatchWatch *dispatch; |
1525 | CtkCupsPollState poll_state; |
1526 | gboolean result; |
1527 | |
1528 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0) |
1529 | g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0); |
1530 | |
1531 | dispatch = (CtkPrintCupsDispatchWatch *) source; |
1532 | |
1533 | poll_state = ctk_cups_request_get_poll_state (dispatch->request); |
1534 | |
1535 | if (poll_state != CTK_CUPS_HTTP_IDLE && !dispatch->request->need_password) |
1536 | if (!(dispatch->data_poll->revents & dispatch->data_poll->events)) |
1537 | return FALSE(0); |
1538 | |
1539 | result = ctk_cups_request_read_write (dispatch->request, FALSE(0)); |
1540 | if (result && dispatch->data_poll != NULL((void*)0)) |
1541 | { |
1542 | g_source_remove_poll (source, dispatch->data_poll); |
1543 | g_free (dispatch->data_poll); |
1544 | dispatch->data_poll = NULL((void*)0); |
1545 | } |
1546 | |
1547 | if (dispatch->request->need_password && dispatch->request->password_state != CTK_CUPS_PASSWORD_REQUESTED) |
1548 | { |
1549 | dispatch->request->need_password = FALSE(0); |
1550 | g_idle_add (request_password, dispatch); |
1551 | result = FALSE(0); |
1552 | } |
1553 | |
1554 | return result; |
1555 | } |
1556 | |
1557 | static gboolean |
1558 | cups_dispatch_watch_prepare (GSource *source, |
1559 | gint *timeout_) |
1560 | { |
1561 | CtkPrintCupsDispatchWatch *dispatch; |
1562 | gboolean result; |
1563 | |
1564 | dispatch = (CtkPrintCupsDispatchWatch *) source; |
1565 | |
1566 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0) |
1567 | g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0); |
1568 | |
1569 | *timeout_ = -1; |
1570 | |
1571 | result = ctk_cups_request_read_write (dispatch->request, TRUE(!(0))); |
1572 | |
1573 | cups_dispatch_add_poll (source); |
1574 | |
1575 | return result; |
1576 | } |
1577 | |
1578 | static gboolean |
1579 | cups_dispatch_watch_dispatch (GSource *source, |
1580 | GSourceFunc callback, |
1581 | gpointer user_data) |
1582 | { |
1583 | CtkPrintCupsDispatchWatch *dispatch; |
1584 | CtkPrintCupsResponseCallbackFunc ep_callback; |
1585 | CtkCupsResult *result; |
1586 | |
1587 | g_assert (callback != NULL)do { if (callback != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "ctkprintbackendcups.c", 1587, ((const char*) (__func__)), "callback != NULL"); } while (0); |
1588 | |
1589 | ep_callback = (CtkPrintCupsResponseCallbackFunc) callback; |
1590 | |
1591 | dispatch = (CtkPrintCupsDispatchWatch *) source; |
1592 | |
1593 | result = ctk_cups_request_get_result (dispatch->request); |
1594 | |
1595 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0) |
1596 | g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0); |
1597 | |
1598 | if (ctk_cups_result_is_error (result)) |
1599 | { |
1600 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
1601 | g_print("Error result: %s (type %i, status %i, code %i)\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
1602 | ctk_cups_result_get_error_string (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
1603 | ctk_cups_result_get_error_type (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
1604 | ctk_cups_result_get_error_status (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
1605 | ctk_cups_result_get_error_code (result)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print("Error result: %s (type %i, status %i, code %i)\n", ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_status (result), ctk_cups_result_get_error_code (result)); }; } while (0); |
1606 | } |
1607 | |
1608 | ep_callback (CTK_PRINT_BACKEND (dispatch->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dispatch->backend)), ((ctk_print_backend_get_type ()) ))))), result, user_data); |
1609 | |
1610 | return FALSE(0); |
1611 | } |
1612 | |
1613 | static void |
1614 | cups_dispatch_watch_finalize (GSource *source) |
1615 | { |
1616 | CtkPrintCupsDispatchWatch *dispatch; |
1617 | CtkCupsResult *result; |
1618 | |
1619 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0) |
1620 | g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p>\n", ((const char *) (__func__)), source); }; } while (0); |
1621 | |
1622 | dispatch = (CtkPrintCupsDispatchWatch *) source; |
1623 | |
1624 | result = ctk_cups_request_get_result (dispatch->request); |
1625 | if (ctk_cups_result_get_error_type (result) == CTK_CUPS_ERROR_AUTH) |
1626 | { |
1627 | const gchar *username; |
1628 | gchar hostname[HTTP_MAX_URI1024]; |
1629 | gchar *key; |
1630 | |
1631 | httpGetHostname (dispatch->request->http, hostname, sizeof (hostname)); |
1632 | if (is_address_local (hostname)) |
1633 | strcpy (hostname, "localhost"); |
1634 | |
1635 | if (dispatch->backend->username != NULL((void*)0)) |
1636 | username = dispatch->backend->username; |
1637 | else |
1638 | username = cupsUser (); |
1639 | |
1640 | key = g_strconcat (username, "@", hostname, NULL((void*)0)); |
1641 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: removing stored password for %s\n", key ); }; } while (0) |
1642 | g_print ("CUPS backend: removing stored password for %s\n", key))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS backend: removing stored password for %s\n", key ); }; } while (0); |
1643 | g_hash_table_remove (dispatch->backend->auth, key); |
1644 | g_free (key); |
1645 | |
1646 | if (dispatch->backend) |
1647 | dispatch->backend->authentication_lock = FALSE(0); |
1648 | } |
1649 | |
1650 | ctk_cups_request_free (dispatch->request); |
1651 | |
1652 | if (dispatch->backend) |
1653 | { |
1654 | /* We need to unref this at idle time, because it might be the |
1655 | * last reference to this module causing the code to be |
1656 | * unloaded (including this particular function!) |
1657 | * Update: Doing this at idle caused a deadlock taking the |
1658 | * mainloop context lock while being in a GSource callout for |
1659 | * multithreaded apps. So, for now we just disable unloading |
1660 | * of print backends. See _ctk_print_backend_create for the |
1661 | * disabling. |
1662 | */ |
1663 | |
1664 | dispatch->backend->requests = g_list_remove (dispatch->backend->requests, dispatch); |
1665 | |
1666 | |
1667 | g_object_unref (dispatch->backend); |
1668 | dispatch->backend = NULL((void*)0); |
1669 | } |
1670 | |
1671 | if (dispatch->data_poll) |
1672 | { |
1673 | g_source_remove_poll (source, dispatch->data_poll); |
1674 | g_free (dispatch->data_poll); |
1675 | dispatch->data_poll = NULL((void*)0); |
1676 | } |
1677 | } |
1678 | |
1679 | static GSourceFuncs _cups_dispatch_watch_funcs = { |
1680 | .prepare = cups_dispatch_watch_prepare, |
1681 | .check = cups_dispatch_watch_check, |
1682 | .dispatch = cups_dispatch_watch_dispatch, |
1683 | .finalize = cups_dispatch_watch_finalize |
1684 | }; |
1685 | |
1686 | |
1687 | static void |
1688 | cups_request_execute (CtkPrintBackendCups *print_backend, |
1689 | CtkCupsRequest *request, |
1690 | CtkPrintCupsResponseCallbackFunc callback, |
1691 | gpointer user_data, |
1692 | GDestroyNotify notify) |
1693 | { |
1694 | CtkPrintCupsDispatchWatch *dispatch; |
1695 | |
1696 | dispatch = (CtkPrintCupsDispatchWatch *) g_source_new (&_cups_dispatch_watch_funcs, |
1697 | sizeof (CtkPrintCupsDispatchWatch)); |
1698 | g_source_set_name (&dispatch->source, "CTK+ CUPS backend"); |
1699 | |
1700 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s'\n" , ((const char*) (__func__)), dispatch, request->server, request ->resource); }; } while (0) |
1701 | g_print ("CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s'\n", G_STRFUNC, dispatch, request->server, request->resource))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s'\n" , ((const char*) (__func__)), dispatch, request->server, request ->resource); }; } while (0); |
1702 | |
1703 | dispatch->request = request; |
1704 | dispatch->backend = g_object_ref (print_backend)((__typeof__ (print_backend)) (g_object_ref) (print_backend)); |
1705 | dispatch->poll_state = CTK_CUPS_HTTP_IDLE; |
1706 | dispatch->data_poll = NULL((void*)0); |
1707 | dispatch->callback = NULL((void*)0); |
1708 | dispatch->callback_data = NULL((void*)0); |
1709 | |
1710 | print_backend->requests = g_list_prepend (print_backend->requests, dispatch); |
1711 | |
1712 | g_source_set_callback ((GSource *) dispatch, (GSourceFunc) callback, user_data, notify); |
1713 | |
1714 | if (request->need_auth_info) |
1715 | { |
1716 | dispatch->callback = callback; |
1717 | dispatch->callback_data = user_data; |
1718 | lookup_auth_info (dispatch); |
1719 | } |
1720 | else |
1721 | { |
1722 | g_source_attach ((GSource *) dispatch, NULL((void*)0)); |
1723 | g_source_unref ((GSource *) dispatch); |
1724 | } |
1725 | } |
1726 | |
1727 | typedef struct { |
1728 | CtkPrintBackendCups *print_backend; |
1729 | CtkPrintJob *job; |
1730 | int job_id; |
1731 | int counter; |
1732 | } CupsJobPollData; |
1733 | |
1734 | static void |
1735 | job_object_died (gpointer user_data, |
1736 | GObject *where_the_object_was G_GNUC_UNUSED__attribute__ ((__unused__))) |
1737 | { |
1738 | CupsJobPollData *data = user_data; |
1739 | data->job = NULL((void*)0); |
1740 | } |
1741 | |
1742 | static void |
1743 | cups_job_poll_data_free (CupsJobPollData *data) |
1744 | { |
1745 | if (data->job) |
1746 | g_object_weak_unref (G_OBJECT (data->job)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->job)), (((GType) ((20) << (2)))))))), job_object_died, data); |
1747 | |
1748 | g_free (data); |
1749 | } |
1750 | |
1751 | static void |
1752 | cups_request_job_info_cb (CtkPrintBackendCups *print_backend G_GNUC_UNUSED__attribute__ ((__unused__)), |
1753 | CtkCupsResult *result, |
1754 | gpointer user_data) |
1755 | { |
1756 | CupsJobPollData *data = user_data; |
1757 | ipp_attribute_t *attr; |
1758 | ipp_t *response; |
1759 | int state; |
1760 | gboolean done; |
1761 | |
1762 | cdk_threads_enter (); |
1763 | |
1764 | if (data->job == NULL((void*)0)) |
1765 | { |
1766 | cups_job_poll_data_free (data); |
1767 | goto done; |
1768 | } |
1769 | |
1770 | data->counter++; |
1771 | |
1772 | response = ctk_cups_result_get_response (result); |
1773 | |
1774 | state = 0; |
Value stored to 'state' is never read | |
1775 | |
1776 | attr = ippFindAttribute (response, "job-state", IPP_TAG_ENUM); |
1777 | state = ippGetInteger (attr, 0); |
1778 | |
1779 | done = FALSE(0); |
1780 | switch (state) |
1781 | { |
1782 | case IPP_JOB_PENDINGIPP_JSTATE_PENDING: |
1783 | case IPP_JOB_HELDIPP_JSTATE_HELD: |
1784 | case IPP_JOB_STOPPEDIPP_JSTATE_STOPPED: |
1785 | ctk_print_job_set_status (data->job, |
1786 | CTK_PRINT_STATUS_PENDING); |
1787 | break; |
1788 | case IPP_JOB_PROCESSINGIPP_JSTATE_PROCESSING: |
1789 | ctk_print_job_set_status (data->job, |
1790 | CTK_PRINT_STATUS_PRINTING); |
1791 | break; |
1792 | default: |
1793 | case IPP_JOB_CANCELLEDIPP_JSTATE_CANCELED: |
1794 | case IPP_JOB_ABORTEDIPP_JSTATE_ABORTED: |
1795 | ctk_print_job_set_status (data->job, |
1796 | CTK_PRINT_STATUS_FINISHED_ABORTED); |
1797 | done = TRUE(!(0)); |
1798 | break; |
1799 | case 0: |
1800 | case IPP_JOB_COMPLETEDIPP_JSTATE_COMPLETED: |
1801 | ctk_print_job_set_status (data->job, |
1802 | CTK_PRINT_STATUS_FINISHED); |
1803 | done = TRUE(!(0)); |
1804 | break; |
1805 | } |
1806 | |
1807 | if (!done && data->job != NULL((void*)0)) |
1808 | { |
1809 | guint32 timeout; |
1810 | guint id; |
1811 | |
1812 | if (data->counter < 5) |
1813 | timeout = 100; |
1814 | else if (data->counter < 10) |
1815 | timeout = 500; |
1816 | else |
1817 | timeout = 1000; |
1818 | |
1819 | id = g_timeout_add (timeout, cups_job_info_poll_timeout, data); |
1820 | g_source_set_name_by_id (id, "[ctk+] cups_job_info_poll_timeout"); |
1821 | } |
1822 | else |
1823 | cups_job_poll_data_free (data); |
1824 | |
1825 | done: |
1826 | cdk_threads_leave (); |
1827 | } |
1828 | |
1829 | static void |
1830 | cups_request_job_info (CupsJobPollData *data) |
1831 | { |
1832 | CtkCupsRequest *request; |
1833 | gchar *job_uri; |
1834 | |
1835 | request = ctk_cups_request_new_with_username (NULL((void*)0), |
1836 | CTK_CUPS_POST, |
1837 | IPP_GET_JOB_ATTRIBUTESIPP_OP_GET_JOB_ATTRIBUTES, |
1838 | NULL((void*)0), |
1839 | NULL((void*)0), |
1840 | NULL((void*)0), |
1841 | data->print_backend->username); |
1842 | |
1843 | job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", data->job_id); |
1844 | ctk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, |
1845 | "job-uri", NULL((void*)0), job_uri); |
1846 | g_free (job_uri); |
1847 | |
1848 | cups_request_execute (data->print_backend, |
1849 | request, |
1850 | (CtkPrintCupsResponseCallbackFunc) cups_request_job_info_cb, |
1851 | data, |
1852 | NULL((void*)0)); |
1853 | } |
1854 | |
1855 | static gboolean |
1856 | cups_job_info_poll_timeout (gpointer user_data) |
1857 | { |
1858 | CupsJobPollData *data = user_data; |
1859 | |
1860 | if (data->job == NULL((void*)0)) |
1861 | cups_job_poll_data_free (data); |
1862 | else |
1863 | cups_request_job_info (data); |
1864 | |
1865 | return G_SOURCE_REMOVE(0); |
1866 | } |
1867 | |
1868 | static void |
1869 | cups_begin_polling_info (CtkPrintBackendCups *print_backend, |
1870 | CtkPrintJob *job, |
1871 | gint job_id) |
1872 | { |
1873 | CupsJobPollData *data; |
1874 | |
1875 | data = g_new0 (CupsJobPollData, 1)((CupsJobPollData *) g_malloc0_n ((1), sizeof (CupsJobPollData ))); |
1876 | |
1877 | data->print_backend = print_backend; |
1878 | data->job = job; |
1879 | data->job_id = job_id; |
1880 | data->counter = 0; |
1881 | |
1882 | g_object_weak_ref (G_OBJECT (job)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((job)), (((GType) ((20) << (2)))))))), job_object_died, data); |
1883 | |
1884 | cups_request_job_info (data); |
1885 | } |
1886 | |
1887 | static void |
1888 | mark_printer_inactive (CtkPrinter *printer, |
1889 | CtkPrintBackend *backend) |
1890 | { |
1891 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
1892 | |
1893 | if (cups_printer->is_temporary) |
1894 | { |
1895 | GList *iter; |
1896 | |
1897 | /* Do not recreate printers which disappeared from Avahi. */ |
1898 | iter = g_list_find_custom (CTK_PRINT_BACKEND_CUPS (backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((backend)), ((ctk_print_backend_cups_get_type ()))))))->temporary_queues_removed, |
1899 | ctk_printer_get_name (printer), (GCompareFunc) g_strcmp0); |
1900 | if (iter == NULL((void*)0)) |
1901 | { |
1902 | /* Recreate temporary queue since they are created for 60 seconds only. */ |
1903 | #ifdef HAVE_CUPS_2_2 |
1904 | create_temporary_queue (CTK_PRINT_BACKEND_CUPS (backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((backend)), ((ctk_print_backend_cups_get_type ())))))), |
1905 | ctk_printer_get_name (printer), |
1906 | cups_printer->printer_uri, |
1907 | cups_printer->temporary_queue_device_uri); |
1908 | #endif |
1909 | } |
1910 | } |
1911 | else |
1912 | { |
1913 | ctk_printer_set_is_active (printer, FALSE(0)); |
1914 | g_signal_emit_by_name (backend, "printer-removed", printer); |
1915 | } |
1916 | } |
1917 | |
1918 | static gint |
1919 | find_printer (CtkPrinter *printer, |
1920 | const gchar *find_name) |
1921 | { |
1922 | const gchar *printer_name; |
1923 | |
1924 | printer_name = ctk_printer_get_name (printer); |
1925 | return g_ascii_strcasecmp (printer_name, find_name); |
1926 | } |
1927 | /* Printer messages we're interested in */ |
1928 | static const char * const printer_messages[] = |
1929 | { |
1930 | "toner-low", |
1931 | "toner-empty", |
1932 | "developer-low", |
1933 | "developer-empty", |
1934 | "marker-supply-low", |
1935 | "marker-supply-empty", |
1936 | "cover-open", |
1937 | "door-open", |
1938 | "media-low", |
1939 | "media-empty", |
1940 | "offline", |
1941 | "other" |
1942 | }; |
1943 | |
1944 | /* Attributes we're interested in for printers */ |
1945 | static const char * const printer_attrs[] = |
1946 | { |
1947 | "printer-name", |
1948 | "printer-uri-supported", |
1949 | "member-uris", |
1950 | "printer-location", |
1951 | "printer-info", |
1952 | "printer-state-message", |
1953 | "printer-state-reasons", |
1954 | "printer-state", |
1955 | "queued-job-count", |
1956 | "printer-is-accepting-jobs", |
1957 | "job-sheets-supported", |
1958 | "job-sheets-default", |
1959 | "printer-type", |
1960 | "auth-info-required", |
1961 | "number-up-default", |
1962 | "ipp-versions-supported", |
1963 | "multiple-document-handling-supported", |
1964 | "copies-supported", |
1965 | "number-up-supported", |
1966 | "device-uri", |
1967 | "printer-is-temporary" |
1968 | }; |
1969 | |
1970 | /* Attributes we're interested in for printers without PPD */ |
1971 | static const char * const printer_attrs_detailed[] = |
1972 | { |
1973 | "printer-name", |
1974 | "printer-uri-supported", |
1975 | "member-uris", |
1976 | "printer-location", |
1977 | "printer-info", |
1978 | "printer-state-message", |
1979 | "printer-state-reasons", |
1980 | "printer-state", |
1981 | "queued-job-count", |
1982 | "printer-is-accepting-jobs", |
1983 | "job-sheets-supported", |
1984 | "job-sheets-default", |
1985 | "printer-type", |
1986 | "auth-info-required", |
1987 | "number-up-default", |
1988 | "ipp-versions-supported", |
1989 | "multiple-document-handling-supported", |
1990 | "copies-supported", |
1991 | "number-up-supported", |
1992 | "media-col-default", |
1993 | "media-col-supported", |
1994 | "media-default", |
1995 | "media-size-supported", |
1996 | "media-supported", |
1997 | "media-left-margin-supported", |
1998 | "media-right-margin-supported", |
1999 | "media-bottom-margin-supported", |
2000 | "media-top-margin-supported", |
2001 | "sides-default", |
2002 | "sides-supported", |
2003 | "output-bin-default", |
2004 | "output-bin-supported", |
2005 | }; |
2006 | |
2007 | typedef enum |
2008 | { |
2009 | CTK_PRINTER_STATE_LEVEL_NONE = 0, |
2010 | CTK_PRINTER_STATE_LEVEL_INFO = 1, |
2011 | CTK_PRINTER_STATE_LEVEL_WARNING = 2, |
2012 | CTK_PRINTER_STATE_LEVEL_ERROR = 3 |
2013 | } PrinterStateLevel; |
2014 | |
2015 | typedef struct |
2016 | { |
2017 | float x_dimension; |
2018 | float y_dimension; |
2019 | } MediaSize; |
2020 | |
2021 | typedef struct |
2022 | { |
2023 | const gchar *printer_name; |
2024 | const gchar *printer_uri; |
2025 | const gchar *member_uris; |
2026 | const gchar *location; |
2027 | const gchar *description; |
2028 | gchar *state_msg; |
2029 | const gchar *reason_msg; |
2030 | PrinterStateLevel reason_level; |
2031 | gint state; |
2032 | gint job_count; |
2033 | gboolean is_paused; |
2034 | gboolean is_accepting_jobs; |
2035 | const gchar *default_cover_before; |
2036 | const gchar *default_cover_after; |
2037 | gboolean default_printer; |
2038 | gboolean got_printer_type; |
2039 | gboolean remote_printer; |
2040 | gboolean avahi_printer; |
2041 | gchar *avahi_resource_path; |
2042 | gchar **auth_info_required; |
2043 | gint default_number_up; |
2044 | guchar ipp_version_major; |
2045 | guchar ipp_version_minor; |
2046 | gboolean supports_copies; |
2047 | gboolean supports_collate; |
2048 | gboolean supports_number_up; |
2049 | gchar *media_default; |
2050 | GList *media_supported; |
2051 | GList *media_size_supported; |
2052 | float media_bottom_margin_default; |
2053 | float media_top_margin_default; |
2054 | float media_left_margin_default; |
2055 | float media_right_margin_default; |
2056 | gboolean media_margin_default_set; |
2057 | gchar *sides_default; |
2058 | GList *sides_supported; |
2059 | char **covers; |
2060 | int number_of_covers; |
2061 | gchar *output_bin_default; |
2062 | GList *output_bin_supported; |
2063 | gchar *original_device_uri; |
2064 | gboolean is_temporary; |
2065 | } PrinterSetupInfo; |
2066 | |
2067 | static void |
2068 | printer_setup_info_free (PrinterSetupInfo *info) |
2069 | { |
2070 | g_free (info->original_device_uri); |
2071 | g_free (info->state_msg); |
2072 | g_strfreev (info->covers); |
2073 | g_slice_free (PrinterSetupInfo, info)do { if (1) g_slice_free1 (sizeof (PrinterSetupInfo), (info)) ; else (void) ((PrinterSetupInfo*) 0 == (info)); } while (0); |
2074 | } |
2075 | |
2076 | static void |
2077 | get_ipp_version (const char *ipp_version_string, |
2078 | guchar *ipp_version_major, |
2079 | guchar *ipp_version_minor) |
2080 | { |
2081 | gchar *endptr; |
2082 | |
2083 | *ipp_version_major = 1; |
2084 | *ipp_version_minor = 1; |
2085 | |
2086 | if (ipp_version_string) |
2087 | { |
2088 | gchar **ipp_version_strv; |
2089 | |
2090 | ipp_version_strv = g_strsplit (ipp_version_string, ".", 0); |
2091 | |
2092 | if (ipp_version_strv) |
2093 | { |
2094 | if (g_strv_length (ipp_version_strv) == 2) |
2095 | { |
2096 | *ipp_version_major = (guchar) g_ascii_strtoull (ipp_version_strv[0], &endptr, 10); |
2097 | if (endptr == ipp_version_strv[0]) |
2098 | *ipp_version_major = 1; |
2099 | |
2100 | *ipp_version_minor = (guchar) g_ascii_strtoull (ipp_version_strv[1], &endptr, 10); |
2101 | if (endptr == ipp_version_strv[1]) |
2102 | *ipp_version_minor = 1; |
2103 | } |
2104 | |
2105 | g_strfreev (ipp_version_strv); |
2106 | } |
2107 | } |
2108 | } |
2109 | |
2110 | static void |
2111 | get_server_ipp_version (guchar *ipp_version_major, |
2112 | guchar *ipp_version_minor) |
2113 | { |
2114 | *ipp_version_major = 1; |
2115 | *ipp_version_minor = 1; |
2116 | |
2117 | if (IPP_VERSION"\002\001" && strlen (IPP_VERSION"\002\001") == 2) |
2118 | { |
2119 | *ipp_version_major = (unsigned char) IPP_VERSION"\002\001"[0]; |
2120 | *ipp_version_minor = (unsigned char) IPP_VERSION"\002\001"[1]; |
2121 | } |
2122 | } |
2123 | |
2124 | static gint |
2125 | ipp_version_cmp (guchar ipp_version_major1, |
2126 | guchar ipp_version_minor1, |
2127 | guchar ipp_version_major2, |
2128 | guchar ipp_version_minor2) |
2129 | { |
2130 | if (ipp_version_major1 == ipp_version_major2 && |
2131 | ipp_version_minor1 == ipp_version_minor2) |
2132 | { |
2133 | return 0; |
2134 | } |
2135 | else if (ipp_version_major1 < ipp_version_major2 || |
2136 | (ipp_version_major1 == ipp_version_major2 && |
2137 | ipp_version_minor1 < ipp_version_minor2)) |
2138 | { |
2139 | return -1; |
2140 | } |
2141 | else |
2142 | { |
2143 | return 1; |
2144 | } |
2145 | } |
2146 | |
2147 | static void |
2148 | cups_printer_handle_attribute (CtkPrintBackendCups *cups_backend G_GNUC_UNUSED__attribute__ ((__unused__)), |
2149 | ipp_attribute_t *attr, |
2150 | PrinterSetupInfo *info) |
2151 | { |
2152 | gint i, j; |
2153 | if (strcmp (ippGetName (attr), "printer-name") == 0 && |
2154 | ippGetValueTag (attr) == IPP_TAG_NAME) |
2155 | info->printer_name = ippGetString (attr, 0, NULL((void*)0)); |
2156 | else if (strcmp (ippGetName (attr), "printer-uri-supported") == 0 && |
2157 | ippGetValueTag (attr) == IPP_TAG_URI) |
2158 | info->printer_uri = ippGetString (attr, 0, NULL((void*)0)); |
2159 | else if (strcmp (ippGetName (attr), "member-uris") == 0 && |
2160 | ippGetValueTag (attr) == IPP_TAG_URI) |
2161 | info->member_uris = ippGetString (attr, 0, NULL((void*)0)); |
2162 | else if (strcmp (ippGetName (attr), "printer-location") == 0) |
2163 | info->location = ippGetString (attr, 0, NULL((void*)0)); |
2164 | else if (strcmp (ippGetName (attr), "printer-info") == 0) |
2165 | info->description = ippGetString (attr, 0, NULL((void*)0)); |
2166 | else if (strcmp (ippGetName (attr), "printer-state-message") == 0) |
2167 | info->state_msg = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
2168 | else if (strcmp (ippGetName (attr), "printer-state-reasons") == 0) |
2169 | /* Store most important reason to reason_msg and set |
2170 | its importance at printer_state_reason_level */ |
2171 | { |
2172 | for (i = 0; i < ippGetCount (attr); i++) |
2173 | { |
2174 | if (strcmp (ippGetString (attr, i, NULL((void*)0)), "none") != 0) |
2175 | { |
2176 | gboolean interested_in = FALSE(0); |
2177 | /* Sets is_paused flag for paused printer. */ |
2178 | if (strcmp (ippGetString (attr, i, NULL((void*)0)), "paused") == 0) |
2179 | { |
2180 | info->is_paused = TRUE(!(0)); |
2181 | } |
2182 | |
2183 | for (j = 0; j < G_N_ELEMENTS (printer_messages)(sizeof (printer_messages) / sizeof ((printer_messages)[0])); j++) |
2184 | if (strncmp (ippGetString (attr, i, NULL((void*)0)), printer_messages[j], |
2185 | strlen (printer_messages[j])) == 0) |
2186 | { |
2187 | interested_in = TRUE(!(0)); |
2188 | break; |
2189 | } |
2190 | |
2191 | if (interested_in) |
2192 | { |
2193 | if (g_str_has_suffix (ippGetString (attr, i, NULL), "-report")(__builtin_constant_p ("-report")? __extension__ ({ const char * const __str = (ippGetString (attr, i, ((void*)0))); const char * const __suffix = ("-report"); gboolean __result = (0); if ( __str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (ippGetString (attr, i, ((void*)0)), "-report") )) |
2194 | { |
2195 | if (info->reason_level <= CTK_PRINTER_STATE_LEVEL_INFO) |
2196 | { |
2197 | info->reason_msg = ippGetString (attr, i, NULL((void*)0)); |
2198 | info->reason_level = CTK_PRINTER_STATE_LEVEL_INFO; |
2199 | } |
2200 | } |
2201 | else if (g_str_has_suffix (ippGetString (attr, i, NULL), "-warning")(__builtin_constant_p ("-warning")? __extension__ ({ const char * const __str = (ippGetString (attr, i, ((void*)0))); const char * const __suffix = ("-warning"); gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = ( g_str_has_suffix) (__str, __suffix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix))); if (__str_len >= __suffix_len ) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix ) + !(__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (ippGetString (attr, i, ((void*)0)), "-warning") )) |
2202 | { |
2203 | if (info->reason_level <= CTK_PRINTER_STATE_LEVEL_WARNING) |
2204 | { |
2205 | info->reason_msg = ippGetString (attr, i, NULL((void*)0)); |
2206 | info->reason_level = CTK_PRINTER_STATE_LEVEL_WARNING; |
2207 | } |
2208 | } |
2209 | else /* It is error in the case of no suffix. */ |
2210 | { |
2211 | info->reason_msg = ippGetString (attr, i, NULL((void*)0)); |
2212 | info->reason_level = CTK_PRINTER_STATE_LEVEL_ERROR; |
2213 | } |
2214 | } |
2215 | } |
2216 | } |
2217 | } |
2218 | else if (strcmp (ippGetName (attr), "printer-state") == 0) |
2219 | info->state = ippGetInteger (attr, 0); |
2220 | else if (strcmp (ippGetName (attr), "queued-job-count") == 0) |
2221 | info->job_count = ippGetInteger (attr, 0); |
2222 | else if (strcmp (ippGetName (attr), "printer-is-accepting-jobs") == 0) |
2223 | { |
2224 | if (ippGetBoolean (attr, 0) == 1) |
2225 | info->is_accepting_jobs = TRUE(!(0)); |
2226 | else |
2227 | info->is_accepting_jobs = FALSE(0); |
2228 | } |
2229 | else if (strcmp (ippGetName (attr), "job-sheets-supported") == 0) |
2230 | { |
2231 | info->number_of_covers = ippGetCount (attr); |
2232 | info->covers = g_new (char *, info->number_of_covers + 1)((char * *) g_malloc_n ((info->number_of_covers + 1), sizeof (char *))); |
2233 | for (i = 0; i < info->number_of_covers; i++) |
2234 | info->covers[i] = g_strdup (ippGetString (attr, i, NULL))g_strdup_inline (ippGetString (attr, i, ((void*)0))); |
2235 | info->covers[info->number_of_covers] = NULL((void*)0); |
2236 | } |
2237 | else if (strcmp (ippGetName (attr), "job-sheets-default") == 0) |
2238 | { |
2239 | if (ippGetCount (attr) == 2) |
2240 | { |
2241 | info->default_cover_before = ippGetString (attr, 0, NULL((void*)0)); |
2242 | info->default_cover_after = ippGetString (attr, 1, NULL((void*)0)); |
2243 | } |
2244 | } |
2245 | else if (strcmp (ippGetName (attr), "printer-type") == 0) |
2246 | { |
2247 | info->got_printer_type = TRUE(!(0)); |
2248 | if (ippGetInteger (attr, 0) & 0x00020000) |
2249 | info->default_printer = TRUE(!(0)); |
2250 | else |
2251 | info->default_printer = FALSE(0); |
2252 | |
2253 | if (ippGetInteger (attr, 0) & 0x00000002) |
2254 | info->remote_printer = TRUE(!(0)); |
2255 | else |
2256 | info->remote_printer = FALSE(0); |
2257 | } |
2258 | else if (strcmp (ippGetName (attr), "auth-info-required") == 0) |
2259 | { |
2260 | if (strcmp (ippGetString (attr, 0, NULL((void*)0)), "none") != 0) |
2261 | { |
2262 | info->auth_info_required = g_new0 (gchar *, ippGetCount (attr) + 1)((gchar * *) g_malloc0_n ((ippGetCount (attr) + 1), sizeof (gchar *))); |
2263 | for (i = 0; i < ippGetCount (attr); i++) |
2264 | info->auth_info_required[i] = g_strdup (ippGetString (attr, i, NULL))g_strdup_inline (ippGetString (attr, i, ((void*)0))); |
2265 | } |
2266 | } |
2267 | else if (strcmp (ippGetName (attr), "number-up-default") == 0) |
2268 | { |
2269 | info->default_number_up = ippGetInteger (attr, 0); |
2270 | } |
2271 | else if (g_strcmp0 (ippGetName (attr), "ipp-versions-supported") == 0) |
2272 | { |
2273 | guchar server_ipp_version_major; |
2274 | guchar server_ipp_version_minor; |
2275 | guchar ipp_version_major; |
2276 | guchar ipp_version_minor; |
2277 | |
2278 | get_server_ipp_version (&server_ipp_version_major, |
2279 | &server_ipp_version_minor); |
2280 | |
2281 | for (i = 0; i < ippGetCount (attr); i++) |
2282 | { |
2283 | get_ipp_version (ippGetString (attr, i, NULL((void*)0)), |
2284 | &ipp_version_major, |
2285 | &ipp_version_minor); |
2286 | |
2287 | if (ipp_version_cmp (ipp_version_major, |
2288 | ipp_version_minor, |
2289 | info->ipp_version_major, |
2290 | info->ipp_version_minor) > 0 && |
2291 | ipp_version_cmp (ipp_version_major, |
2292 | ipp_version_minor, |
2293 | server_ipp_version_major, |
2294 | server_ipp_version_minor) <= 0) |
2295 | { |
2296 | info->ipp_version_major = ipp_version_major; |
2297 | info->ipp_version_minor = ipp_version_minor; |
2298 | } |
2299 | } |
2300 | } |
2301 | else if (g_strcmp0 (ippGetName (attr), "number-up-supported") == 0) |
2302 | { |
2303 | if (ippGetCount (attr) == 6) |
2304 | { |
2305 | info->supports_number_up = TRUE(!(0)); |
2306 | } |
2307 | } |
2308 | else if (g_strcmp0 (ippGetName (attr), "copies-supported") == 0) |
2309 | { |
2310 | int upper = 1; |
2311 | |
2312 | ippGetRange (attr, 0, &upper); |
2313 | if (upper > 1) |
2314 | { |
2315 | info->supports_copies = TRUE(!(0)); |
2316 | } |
2317 | } |
2318 | else if (g_strcmp0 (ippGetName (attr), "multiple-document-handling-supported") == 0) |
2319 | { |
2320 | for (i = 0; i < ippGetCount (attr); i++) |
2321 | { |
2322 | if (g_strcmp0 (ippGetString (attr, i, NULL((void*)0)), "separate-documents-collated-copies") == 0) |
2323 | { |
2324 | info->supports_collate = TRUE(!(0)); |
2325 | } |
2326 | } |
2327 | } |
2328 | else if (g_strcmp0 (ippGetName (attr), "sides-default") == 0) |
2329 | { |
2330 | info->sides_default = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
2331 | } |
2332 | else if (g_strcmp0 (ippGetName (attr), "sides-supported") == 0) |
2333 | { |
2334 | for (i = 0; i < ippGetCount (attr); i++) |
2335 | info->sides_supported = g_list_prepend (info->sides_supported, g_strdup (ippGetString (attr, i, NULL))g_strdup_inline (ippGetString (attr, i, ((void*)0)))); |
2336 | |
2337 | info->sides_supported = g_list_reverse (info->sides_supported); |
2338 | } |
2339 | else if (g_strcmp0 (ippGetName (attr), "media-default") == 0) |
2340 | { |
2341 | if (ippGetValueTag (attr) == IPP_TAG_KEYWORD || |
2342 | ippGetValueTag (attr) == IPP_TAG_NAME) |
2343 | info->media_default = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
2344 | } |
2345 | else if (g_strcmp0 (ippGetName (attr), "media-col-default") == 0) |
2346 | { |
2347 | ipp_attribute_t *iter; |
2348 | gint num_of_margins = 0; |
2349 | |
2350 | for (i = 0; i < ippGetCount (attr); i++) |
2351 | { |
2352 | ipp_t *col; |
2353 | |
2354 | col = ippGetCollection (attr, i); |
2355 | for (iter = ippFirstAttribute (col); iter != NULL((void*)0); iter = ippNextAttribute (col)) |
2356 | { |
2357 | switch (ippGetValueTag (iter)) |
2358 | { |
2359 | case IPP_TAG_INTEGER: |
2360 | if (g_strcmp0 (ippGetName (iter), "media-bottom-margin") == 0) |
2361 | { |
2362 | info->media_bottom_margin_default = ippGetInteger (iter, 0) / 100.0; |
2363 | num_of_margins++; |
2364 | } |
2365 | else if (g_strcmp0 (ippGetName (iter), "media-top-margin") == 0) |
2366 | { |
2367 | info->media_top_margin_default = ippGetInteger (iter, 0) / 100.0; |
2368 | num_of_margins++; |
2369 | } |
2370 | else if (g_strcmp0 (ippGetName (iter), "media-left-margin") == 0) |
2371 | { |
2372 | info->media_left_margin_default = ippGetInteger (iter, 0) / 100.0; |
2373 | num_of_margins++; |
2374 | } |
2375 | else if (g_strcmp0 (ippGetName (iter), "media-right-margin") == 0) |
2376 | { |
2377 | info->media_right_margin_default = ippGetInteger (iter, 0) / 100.0; |
2378 | num_of_margins++; |
2379 | } |
2380 | break; |
2381 | |
2382 | default: |
2383 | break; |
2384 | } |
2385 | } |
2386 | } |
2387 | |
2388 | if (num_of_margins == 4) |
2389 | info->media_margin_default_set = TRUE(!(0)); |
2390 | } |
2391 | else if (g_strcmp0 (ippGetName (attr), "media-supported") == 0) |
2392 | { |
2393 | for (i = 0; i < ippGetCount (attr); i++) |
2394 | info->media_supported = g_list_prepend (info->media_supported, g_strdup (ippGetString (attr, i, NULL))g_strdup_inline (ippGetString (attr, i, ((void*)0)))); |
2395 | |
2396 | info->media_supported = g_list_reverse (info->media_supported); |
2397 | } |
2398 | else if (g_strcmp0 (ippGetName (attr), "media-size-supported") == 0) |
2399 | { |
2400 | ipp_attribute_t *iter; |
2401 | gboolean number_of_dimensions; |
2402 | |
2403 | for (i = 0; i < ippGetCount (attr); i++) |
2404 | { |
2405 | MediaSize *media_size; |
2406 | ipp_t *media_size_collection; |
2407 | |
2408 | media_size_collection = ippGetCollection (attr, i); |
2409 | media_size = g_new0 (MediaSize, 1)((MediaSize *) g_malloc0_n ((1), sizeof (MediaSize))); |
2410 | number_of_dimensions = 0; |
2411 | |
2412 | for (iter = ippFirstAttribute (media_size_collection); |
2413 | iter != NULL((void*)0); |
2414 | iter = ippNextAttribute (media_size_collection)) |
2415 | { |
2416 | if (g_strcmp0 (ippGetName (iter), "x-dimension") == 0 && |
2417 | ippGetValueTag (iter) == IPP_TAG_INTEGER) |
2418 | { |
2419 | media_size->x_dimension = ippGetInteger (iter, 0) / 100.0; |
2420 | number_of_dimensions++; |
2421 | } |
2422 | else if (g_strcmp0 (ippGetName (iter), "y-dimension") == 0 && |
2423 | ippGetValueTag (iter) == IPP_TAG_INTEGER) |
2424 | { |
2425 | media_size->y_dimension = ippGetInteger (iter, 0) / 100.0; |
2426 | number_of_dimensions++; |
2427 | } |
2428 | } |
2429 | |
2430 | if (number_of_dimensions == 2) |
2431 | info->media_size_supported = g_list_prepend (info->media_size_supported, media_size); |
2432 | else |
2433 | g_free (media_size); |
2434 | } |
2435 | |
2436 | info->media_size_supported = g_list_reverse (info->media_size_supported); |
2437 | } |
2438 | else if (g_strcmp0 (ippGetName (attr), "output-bin-default") == 0) |
2439 | { |
2440 | info->output_bin_default = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
2441 | } |
2442 | else if (g_strcmp0 (ippGetName (attr), "output-bin-supported") == 0) |
2443 | { |
2444 | for (i = 0; i < ippGetCount (attr); i++) |
2445 | info->output_bin_supported = g_list_prepend (info->output_bin_supported, g_strdup (ippGetString (attr, i, NULL))g_strdup_inline (ippGetString (attr, i, ((void*)0)))); |
2446 | |
2447 | info->output_bin_supported = g_list_reverse (info->output_bin_supported); |
2448 | } |
2449 | else if (g_strcmp0 (ippGetName (attr), "device-uri") == 0) |
2450 | { |
2451 | info->original_device_uri = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
2452 | } |
2453 | else if (strcmp (ippGetName (attr), "printer-is-temporary") == 0) |
2454 | { |
2455 | if (ippGetBoolean (attr, 0) == 1) |
2456 | info->is_temporary = TRUE(!(0)); |
2457 | else |
2458 | info->is_temporary = FALSE(0); |
2459 | } |
2460 | else |
2461 | { |
2462 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Attribute %s ignored\n", ippGetName ( attr)); }; } while (0) |
2463 | g_print ("CUPS Backend: Attribute %s ignored\n", ippGetName (attr)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Attribute %s ignored\n", ippGetName ( attr)); }; } while (0); |
2464 | } |
2465 | } |
2466 | |
2467 | static CtkPrinter* |
2468 | cups_create_printer (CtkPrintBackendCups *cups_backend, |
2469 | PrinterSetupInfo *info) |
2470 | { |
2471 | CtkPrinterCups *cups_printer; |
2472 | CtkPrinter *printer; |
2473 | CtkPrintBackend *backend = CTK_PRINT_BACKEND (cups_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_backend)), ((ctk_print_backend_get_type ())))))); |
2474 | char uri[HTTP_MAX_URI1024]; /* Printer URI */ |
2475 | char method[HTTP_MAX_URI1024]; /* Method/scheme name */ |
2476 | char username[HTTP_MAX_URI1024]; /* Username:password */ |
2477 | char hostname[HTTP_MAX_URI1024]; /* Hostname */ |
2478 | char resource[HTTP_MAX_URI1024]; /* Resource name */ |
2479 | int port; /* Port number */ |
2480 | char *cups_server; /* CUPS server */ |
2481 | |
2482 | #ifdef HAVE_COLORD1 |
2483 | if (info->avahi_printer) |
2484 | cups_printer = ctk_printer_cups_new (info->printer_name, |
2485 | backend, |
2486 | NULL((void*)0)); |
2487 | else |
2488 | cups_printer = ctk_printer_cups_new (info->printer_name, |
2489 | backend, |
2490 | cups_backend->colord_client); |
2491 | #else |
2492 | cups_printer = ctk_printer_cups_new (info->printer_name, backend, NULL((void*)0)); |
2493 | #endif |
2494 | |
2495 | if (!info->avahi_printer) |
2496 | { |
2497 | cups_printer->device_uri = g_strdup_printf ("/printers/%s", |
2498 | info->printer_name); |
2499 | } |
2500 | |
2501 | /* Check to see if we are looking at a class */ |
2502 | if (info->member_uris) |
2503 | { |
2504 | cups_printer->printer_uri = g_strdup (info->member_uris)g_strdup_inline (info->member_uris); |
2505 | /* TODO if member_uris is a class we need to recursivly find a printer */ |
2506 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found class with printer %s\n", info ->member_uris); }; } while (0) |
2507 | g_print ("CUPS Backend: Found class with printer %s\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found class with printer %s\n", info ->member_uris); }; } while (0) |
2508 | info->member_uris))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found class with printer %s\n", info ->member_uris); }; } while (0); |
2509 | } |
2510 | else |
2511 | { |
2512 | cups_printer->printer_uri = g_strdup (info->printer_uri)g_strdup_inline (info->printer_uri); |
2513 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found printer %s\n", info->printer_uri ); }; } while (0) |
2514 | g_print ("CUPS Backend: Found printer %s\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found printer %s\n", info->printer_uri ); }; } while (0) |
2515 | info->printer_uri))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Found printer %s\n", info->printer_uri ); }; } while (0); |
2516 | } |
2517 | |
2518 | httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri, |
2519 | method, sizeof (method), |
2520 | username, sizeof (username), |
2521 | hostname, sizeof (hostname), |
2522 | &port, |
2523 | resource, sizeof (resource)); |
2524 | |
2525 | if (strncmp (resource, "/printers/", 10) == 0) |
2526 | { |
2527 | cups_printer->ppd_name = g_strdup (resource + 10)g_strdup_inline (resource + 10); |
2528 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n" , cups_printer->ppd_name, info->printer_name); }; } while (0) |
2529 | g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n", cups_printer->ppd_name, info->printer_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n" , cups_printer->ppd_name, info->printer_name); }; } while (0); |
2530 | } |
2531 | |
2532 | gethostname (uri, sizeof (uri)); |
2533 | cups_server = g_strdup (cupsServer())g_strdup_inline (cupsServer()); |
2534 | |
2535 | if (strcasecmp (uri, hostname) == 0) |
2536 | strcpy (hostname, "localhost"); |
2537 | |
2538 | /* if the cups server is local and listening at a unix domain socket |
2539 | * then use the socket connection |
2540 | */ |
2541 | if ((strstr (hostname, "localhost") != NULL((void*)0)) && |
2542 | (cups_server[0] == '/')) |
2543 | strcpy (hostname, cups_server); |
2544 | |
2545 | g_free (cups_server); |
2546 | |
2547 | cups_printer->default_cover_before = g_strdup (info->default_cover_before)g_strdup_inline (info->default_cover_before); |
2548 | cups_printer->default_cover_after = g_strdup (info->default_cover_after)g_strdup_inline (info->default_cover_after); |
2549 | cups_printer->original_device_uri = g_strdup (info->original_device_uri)g_strdup_inline (info->original_device_uri); |
2550 | cups_printer->hostname = g_strdup (hostname)g_strdup_inline (hostname); |
2551 | cups_printer->port = port; |
2552 | |
2553 | if (cups_printer->original_device_uri != NULL((void*)0)) |
2554 | { |
2555 | httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->original_device_uri, |
2556 | method, sizeof (method), |
2557 | username, sizeof (username), |
2558 | hostname, sizeof (hostname), |
2559 | &port, |
2560 | resource, sizeof (resource)); |
2561 | cups_printer->original_hostname = g_strdup (hostname)g_strdup_inline (hostname); |
2562 | cups_printer->original_resource = g_strdup (resource)g_strdup_inline (resource); |
2563 | cups_printer->original_port = port; |
2564 | } |
2565 | |
2566 | if (info->default_number_up > 0) |
2567 | cups_printer->default_number_up = info->default_number_up; |
2568 | |
2569 | cups_printer->auth_info_required = g_strdupv (info->auth_info_required); |
2570 | g_strfreev (info->auth_info_required); |
2571 | |
2572 | printer = CTK_PRINTER (cups_printer)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_printer)), ((ctk_printer_get_type ())))))); |
2573 | |
2574 | if (cups_backend->default_printer != NULL((void*)0) && |
2575 | strcmp (cups_backend->default_printer, ctk_printer_get_name (printer)) == 0) |
2576 | ctk_printer_set_is_default (printer, TRUE(!(0))); |
2577 | |
2578 | cups_printer->avahi_browsed = info->avahi_printer; |
2579 | |
2580 | ctk_print_backend_add_printer (backend, printer); |
2581 | return printer; |
2582 | } |
2583 | |
2584 | static void |
2585 | set_printer_icon_name_from_info (CtkPrinter *printer, |
2586 | PrinterSetupInfo *info) |
2587 | { |
2588 | /* Set printer icon according to importance |
2589 | (none, report, warning, error - report is omitted). */ |
2590 | if (info->reason_level == CTK_PRINTER_STATE_LEVEL_ERROR) |
2591 | ctk_printer_set_icon_name (printer, "printer-error"); |
2592 | else if (info->reason_level == CTK_PRINTER_STATE_LEVEL_WARNING) |
2593 | ctk_printer_set_icon_name (printer, "printer-warning"); |
2594 | else if (ctk_printer_is_paused (printer)) |
2595 | ctk_printer_set_icon_name (printer, "printer-paused"); |
2596 | else |
2597 | ctk_printer_set_icon_name (printer, "printer"); |
2598 | } |
2599 | |
2600 | static gchar * |
2601 | get_reason_msg_desc (guint i, |
2602 | const gchar *printer_name) |
2603 | { |
2604 | gchar *reason_msg_desc; |
2605 | |
2606 | /* The numbers must match the indices in the printer_messages array */ |
2607 | switch (i) |
2608 | { |
2609 | case 0: |
2610 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is low on toner.")((char *) g_dgettext ("ctk30", "Printer “%s” is low on toner." )), |
2611 | printer_name); |
2612 | break; |
2613 | case 1: |
2614 | reason_msg_desc = g_strdup_printf (_("Printer “%s” has no toner left.")((char *) g_dgettext ("ctk30", "Printer “%s” has no toner left." )), |
2615 | printer_name); |
2616 | break; |
2617 | case 2: |
2618 | /* Translators: "Developer" like on photo development context */ |
2619 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is low on developer.")((char *) g_dgettext ("ctk30", "Printer “%s” is low on developer." )), |
2620 | printer_name); |
2621 | break; |
2622 | case 3: |
2623 | /* Translators: "Developer" like on photo development context */ |
2624 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is out of developer.")((char *) g_dgettext ("ctk30", "Printer “%s” is out of developer." )), |
2625 | printer_name); |
2626 | break; |
2627 | case 4: |
2628 | /* Translators: "marker" is one color bin of the printer */ |
2629 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is low on at least one marker supply.")((char *) g_dgettext ("ctk30", "Printer “%s” is low on at least one marker supply." )), |
2630 | printer_name); |
2631 | break; |
2632 | case 5: |
2633 | /* Translators: "marker" is one color bin of the printer */ |
2634 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is out of at least one marker supply.")((char *) g_dgettext ("ctk30", "Printer “%s” is out of at least one marker supply." )), |
2635 | printer_name); |
2636 | break; |
2637 | case 6: |
2638 | reason_msg_desc = g_strdup_printf (_("The cover is open on printer “%s”.")((char *) g_dgettext ("ctk30", "The cover is open on printer “%s”." )), |
2639 | printer_name); |
2640 | break; |
2641 | case 7: |
2642 | reason_msg_desc = g_strdup_printf (_("The door is open on printer “%s”.")((char *) g_dgettext ("ctk30", "The door is open on printer “%s”." )), |
2643 | printer_name); |
2644 | break; |
2645 | case 8: |
2646 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is low on paper.")((char *) g_dgettext ("ctk30", "Printer “%s” is low on paper." )), |
2647 | printer_name); |
2648 | break; |
2649 | case 9: |
2650 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is out of paper.")((char *) g_dgettext ("ctk30", "Printer “%s” is out of paper." )), |
2651 | printer_name); |
2652 | break; |
2653 | case 10: |
2654 | reason_msg_desc = g_strdup_printf (_("Printer “%s” is currently offline.")((char *) g_dgettext ("ctk30", "Printer “%s” is currently offline." )), |
2655 | printer_name); |
2656 | break; |
2657 | case 11: |
2658 | reason_msg_desc = g_strdup_printf (_("There is a problem on printer “%s”.")((char *) g_dgettext ("ctk30", "There is a problem on printer “%s”." )), |
2659 | printer_name); |
2660 | break; |
2661 | default: |
2662 | g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "ctkprintbackendcups.c" , 2662, ((const char*) (__func__)), ((void*)0)); } while (0); |
2663 | } |
2664 | |
2665 | return reason_msg_desc; |
2666 | } |
2667 | |
2668 | static void |
2669 | set_info_state_message (PrinterSetupInfo *info) |
2670 | { |
2671 | gint i; |
2672 | |
2673 | if (info->state_msg == NULL((void*)0) || strlen (info->state_msg) == 0) |
2674 | { |
2675 | gchar *tmp_msg2 = NULL((void*)0); |
2676 | if (info->is_paused && !info->is_accepting_jobs) |
2677 | /* Translators: this is a printer status. */ |
2678 | tmp_msg2 = g_strdup ( _("Paused; Rejecting Jobs"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Paused; Rejecting Jobs" ))); |
2679 | if (info->is_paused && info->is_accepting_jobs) |
2680 | /* Translators: this is a printer status. */ |
2681 | tmp_msg2 = g_strdup ( _("Paused"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Paused"))); |
2682 | if (!info->is_paused && !info->is_accepting_jobs) |
2683 | /* Translators: this is a printer status. */ |
2684 | tmp_msg2 = g_strdup ( _("Rejecting Jobs"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Rejecting Jobs" ))); |
2685 | |
2686 | if (tmp_msg2 != NULL((void*)0)) |
2687 | { |
2688 | g_free (info->state_msg); |
2689 | info->state_msg = tmp_msg2; |
2690 | } |
2691 | } |
2692 | |
2693 | /* Set description of the reason and combine it with printer-state-message. */ |
2694 | if (info->reason_msg) |
2695 | { |
2696 | gchar *reason_msg_desc = NULL((void*)0); |
2697 | gboolean found = FALSE(0); |
2698 | |
2699 | for (i = 0; i < G_N_ELEMENTS (printer_messages)(sizeof (printer_messages) / sizeof ((printer_messages)[0])); i++) |
2700 | { |
2701 | if (strncmp (info->reason_msg, printer_messages[i], |
2702 | strlen (printer_messages[i])) == 0) |
2703 | { |
2704 | reason_msg_desc = get_reason_msg_desc (i, info->printer_name); |
2705 | found = TRUE(!(0)); |
2706 | break; |
2707 | } |
2708 | } |
2709 | |
2710 | if (!found) |
2711 | info->reason_level = CTK_PRINTER_STATE_LEVEL_NONE; |
2712 | |
2713 | if (info->reason_level >= CTK_PRINTER_STATE_LEVEL_WARNING) |
2714 | { |
2715 | if (info->state_msg == NULL((void*)0) || info->state_msg[0] == '\0') |
2716 | { |
2717 | g_free (info->state_msg); |
2718 | info->state_msg = reason_msg_desc; |
2719 | reason_msg_desc = NULL((void*)0); |
2720 | } |
2721 | else |
2722 | { |
2723 | gchar *tmp_msg = NULL((void*)0); |
2724 | /* Translators: this string connects multiple printer states together. */ |
2725 | tmp_msg = g_strjoin ( _("; ")((char *) g_dgettext ("ctk30", "; ")), info->state_msg, |
2726 | reason_msg_desc, NULL((void*)0)); |
2727 | g_free (info->state_msg); |
2728 | info->state_msg = tmp_msg; |
2729 | } |
2730 | } |
2731 | |
2732 | g_free (reason_msg_desc); |
2733 | } |
2734 | } |
2735 | |
2736 | static void |
2737 | set_default_printer (CtkPrintBackendCups *cups_backend, |
2738 | const gchar *default_printer_name) |
2739 | { |
2740 | cups_backend->default_printer = g_strdup (default_printer_name)g_strdup_inline (default_printer_name); |
2741 | cups_backend->got_default_printer = TRUE(!(0)); |
2742 | |
2743 | if (cups_backend->default_printer != NULL((void*)0)) |
2744 | { |
2745 | CtkPrinter *default_printer = NULL((void*)0); |
2746 | default_printer = ctk_print_backend_find_printer (CTK_PRINT_BACKEND (cups_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_backend)), ((ctk_print_backend_get_type ())))))), |
2747 | cups_backend->default_printer); |
2748 | if (default_printer != NULL((void*)0)) |
2749 | { |
2750 | ctk_printer_set_is_default (default_printer, TRUE(!(0))); |
2751 | g_signal_emit_by_name (CTK_PRINT_BACKEND (cups_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_backend)), ((ctk_print_backend_get_type ())))))), |
2752 | "printer-status-changed", default_printer); |
2753 | } |
2754 | } |
2755 | } |
2756 | |
2757 | typedef struct { |
2758 | CtkPrinterCups *printer; |
2759 | http_t *http; |
2760 | } RequestPrinterInfoData; |
2761 | |
2762 | static void |
2763 | request_printer_info_data_free (RequestPrinterInfoData *data) |
2764 | { |
2765 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
2766 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
2767 | httpClose (data->http); |
2768 | g_object_unref (data->printer); |
2769 | g_free (data); |
2770 | } |
2771 | |
2772 | static void |
2773 | cups_request_printer_info_cb (CtkPrintBackendCups *cups_backend, |
2774 | CtkCupsResult *result, |
2775 | gpointer user_data) |
2776 | { |
2777 | RequestPrinterInfoData *data = (RequestPrinterInfoData *) user_data; |
2778 | PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo)((PrinterSetupInfo*) g_slice_alloc0 (sizeof (PrinterSetupInfo ))); |
2779 | CtkPrintBackend *backend = CTK_PRINT_BACKEND (cups_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_backend)), ((ctk_print_backend_get_type ())))))); |
2780 | ipp_attribute_t *attr; |
2781 | CtkPrinter *printer = g_object_ref (CTK_PRINTER (data->printer))((__typeof__ (((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((data->printer)), ((ctk_printer_get_type ())))))))) (g_object_ref) (((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((data->printer)), ((ctk_printer_get_type ())))))))); |
2782 | gboolean status_changed = FALSE(0); |
2783 | ipp_t *response; |
2784 | |
2785 | cdk_threads_enter (); |
2786 | |
2787 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
2788 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
2789 | |
2790 | if (ctk_cups_result_is_error (result)) |
2791 | { |
2792 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer info: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
2793 | g_warning ("CUPS Backend: Error getting printer info: %s %d %d",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer info: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
2794 | ctk_cups_result_get_error_string (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer info: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
2795 | ctk_cups_result_get_error_type (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer info: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
2796 | ctk_cups_result_get_error_code (result)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer info: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0); |
2797 | |
2798 | goto done; |
2799 | } |
2800 | |
2801 | response = ctk_cups_result_get_response (result); |
2802 | attr = ippFirstAttribute (response); |
2803 | while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER) |
2804 | attr = ippNextAttribute (response); |
2805 | |
2806 | if (attr) |
2807 | { |
2808 | while (attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER) |
2809 | { |
2810 | cups_printer_handle_attribute (cups_backend, attr, info); |
2811 | attr = ippNextAttribute (response); |
2812 | } |
2813 | |
2814 | if (info->printer_name && info->printer_uri) |
2815 | { |
2816 | set_info_state_message (info); |
2817 | |
2818 | if (info->got_printer_type && |
2819 | info->default_printer && |
2820 | cups_backend->avahi_default_printer == NULL((void*)0)) |
2821 | cups_backend->avahi_default_printer = g_strdup (info->printer_name)g_strdup_inline (info->printer_name); |
2822 | |
2823 | ctk_printer_set_is_paused (printer, info->is_paused); |
2824 | ctk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs); |
2825 | |
2826 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->remote = info->remote_printer; |
2827 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->state = info->state; |
2828 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->ipp_version_major = info->ipp_version_major; |
2829 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->ipp_version_minor = info->ipp_version_minor; |
2830 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_copies = info->supports_copies; |
2831 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_collate = info->supports_collate; |
2832 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_number_up = info->supports_number_up; |
2833 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->number_of_covers = info->number_of_covers; |
2834 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->covers = g_strdupv (info->covers); |
2835 | status_changed = ctk_printer_set_job_count (printer, info->job_count); |
2836 | status_changed |= ctk_printer_set_location (printer, info->location); |
2837 | status_changed |= ctk_printer_set_description (printer, info->description); |
2838 | status_changed |= ctk_printer_set_state_message (printer, info->state_msg); |
2839 | status_changed |= ctk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs); |
2840 | |
2841 | set_printer_icon_name_from_info (printer, info); |
2842 | |
2843 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_default = info->media_default; |
2844 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_supported = info->media_supported; |
2845 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_size_supported = info->media_size_supported; |
2846 | if (info->media_margin_default_set) |
2847 | { |
2848 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_margin_default_set = TRUE(!(0)); |
2849 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_bottom_margin_default = info->media_bottom_margin_default; |
2850 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_top_margin_default = info->media_top_margin_default; |
2851 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_left_margin_default = info->media_left_margin_default; |
2852 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->media_right_margin_default = info->media_right_margin_default; |
2853 | } |
2854 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->sides_default = info->sides_default; |
2855 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->sides_supported = info->sides_supported; |
2856 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->output_bin_default = info->output_bin_default; |
2857 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->output_bin_supported = info->output_bin_supported; |
2858 | |
2859 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->is_temporary = info->is_temporary; |
2860 | |
2861 | ctk_printer_set_has_details (printer, TRUE(!(0))); |
2862 | g_signal_emit_by_name (printer, "details-acquired", TRUE(!(0))); |
2863 | |
2864 | if (status_changed) |
2865 | g_signal_emit_by_name (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((backend)), ((ctk_print_backend_get_type ())))))), |
2866 | "printer-status-changed", printer); |
2867 | } |
2868 | } |
2869 | |
2870 | done: |
2871 | g_object_unref (printer); |
2872 | |
2873 | if (!cups_backend->got_default_printer && |
2874 | ctk_print_backend_printer_list_is_done (backend) && |
2875 | cups_backend->avahi_default_printer != NULL((void*)0)) |
2876 | { |
2877 | set_default_printer (cups_backend, cups_backend->avahi_default_printer); |
2878 | } |
2879 | |
2880 | printer_setup_info_free (info); |
2881 | |
2882 | cdk_threads_leave (); |
2883 | } |
2884 | |
2885 | static void |
2886 | cups_request_printer_info (CtkPrinterCups *printer) |
2887 | { |
2888 | CtkPrintBackendCups *backend = CTK_PRINT_BACKEND_CUPS (ctk_printer_get_backend (CTK_PRINTER (printer)))((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((ctk_printer_get_backend (((((CtkPrinter* ) (void *) g_type_check_instance_cast ((GTypeInstance*) ((printer )), ((ctk_printer_get_type ()))))))))), ((ctk_print_backend_cups_get_type ())))))); |
2889 | http_t *http; |
2890 | |
2891 | http = httpConnect2 (printer->hostname, printer->port, NULL((void*)0), AF_UNSPEC0, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL((void*)0)); |
2892 | if (http) |
2893 | { |
2894 | RequestPrinterInfoData *data; |
2895 | CtkCupsRequest *request; |
2896 | |
2897 | data = g_new0 (RequestPrinterInfoData, 1)((RequestPrinterInfoData *) g_malloc0_n ((1), sizeof (RequestPrinterInfoData ))); |
2898 | data->http = http; |
2899 | data->printer = g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer)); |
2900 | |
2901 | request = ctk_cups_request_new_with_username (http, |
2902 | CTK_CUPS_POST, |
2903 | IPP_GET_PRINTER_ATTRIBUTESIPP_OP_GET_PRINTER_ATTRIBUTES, |
2904 | NULL((void*)0), |
2905 | NULL((void*)0), |
2906 | NULL((void*)0), |
2907 | backend->username); |
2908 | |
2909 | ctk_cups_request_set_ipp_version (request, 1, 1); |
2910 | |
2911 | ctk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, |
2912 | "printer-uri", NULL((void*)0), printer->printer_uri); |
2913 | |
2914 | ctk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, |
2915 | "requested-attributes", G_N_ELEMENTS (printer_attrs_detailed)(sizeof (printer_attrs_detailed) / sizeof ((printer_attrs_detailed )[0])), |
2916 | NULL((void*)0), printer_attrs_detailed); |
2917 | |
2918 | cups_request_execute (backend, |
2919 | request, |
2920 | (CtkPrintCupsResponseCallbackFunc) cups_request_printer_info_cb, |
2921 | data, |
2922 | (GDestroyNotify) request_printer_info_data_free); |
2923 | } |
2924 | } |
2925 | |
2926 | typedef struct |
2927 | { |
2928 | gchar *printer_uri; |
2929 | gchar *device_uri; |
2930 | gchar *location; |
2931 | gchar *address; |
2932 | gchar *hostname; |
2933 | gint port; |
2934 | gchar *printer_name; |
2935 | gchar *name; |
2936 | gchar *resource_path; |
2937 | gboolean got_printer_type; |
2938 | guint printer_type; |
2939 | gboolean got_printer_state; |
2940 | guint printer_state; |
2941 | gchar *type; |
2942 | gchar *domain; |
2943 | gchar *UUID; |
2944 | CtkPrintBackendCups *backend; |
2945 | } AvahiConnectionTestData; |
2946 | |
2947 | static CtkPrinter * |
2948 | find_printer_by_uuid (CtkPrintBackendCups *backend, |
2949 | const gchar *UUID) |
2950 | { |
2951 | CtkPrinter *result = NULL((void*)0); |
2952 | GList *printers; |
2953 | GList *iter; |
2954 | gchar *printer_uuid; |
2955 | |
2956 | printers = ctk_print_backend_get_printer_list (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((backend)), ((ctk_print_backend_get_type ()))))))); |
2957 | for (iter = printers; iter != NULL((void*)0); iter = iter->next) |
2958 | { |
2959 | CtkPrinterCups *printer; |
2960 | |
2961 | printer = CTK_PRINTER_CUPS (iter->data)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((iter->data)), ((ctk_printer_cups_get_type ())))))); |
2962 | |
2963 | if (printer->original_device_uri != NULL((void*)0)) |
2964 | { |
2965 | printer_uuid = g_strrstr (printer->original_device_uri, "uuid="); |
2966 | if (printer_uuid != NULL((void*)0) && strlen (printer_uuid) >= 41) |
2967 | { |
2968 | printer_uuid += 5; |
2969 | printer_uuid = g_strndup (printer_uuid, 36); |
2970 | |
2971 | if (g_uuid_string_is_valid (printer_uuid)) |
2972 | { |
2973 | if (g_strcmp0 (printer_uuid, UUID) == 0) |
2974 | { |
2975 | result = CTK_PRINTER (printer)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_get_type ())))))); |
2976 | g_free (printer_uuid); |
2977 | break; |
2978 | } |
2979 | } |
2980 | |
2981 | g_free (printer_uuid); |
2982 | } |
2983 | } |
2984 | } |
2985 | |
2986 | g_list_free (printers); |
2987 | |
2988 | return result; |
2989 | } |
2990 | |
2991 | static void |
2992 | cups_create_local_printer_cb (CtkPrintBackendCups *print_backend, |
2993 | CtkCupsResult *result, |
2994 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
2995 | { |
2996 | gchar *printer_name = NULL((void*)0); |
2997 | ipp_t *response; |
2998 | GList *iter; |
2999 | |
3000 | response = ctk_cups_result_get_response (result); |
3001 | |
3002 | if (ippGetStatusCode (response) <= IPP_OK_CONFLICTIPP_STATUS_OK_CONFLICTING) |
3003 | { |
3004 | ipp_attribute_t *attr; |
3005 | |
3006 | if ((attr = ippFindAttribute (response, "printer-uri-supported", IPP_TAG_URI)) != NULL((void*)0)) |
3007 | { |
3008 | printer_name = g_strdup (g_strrstr (ippGetString (attr, 0, NULL), "/") + 1)g_strdup_inline (g_strrstr (ippGetString (attr, 0, ((void*)0) ), "/") + 1); |
3009 | } |
3010 | |
3011 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Created local printer %s\n", printer_name ); }; } while (0) |
3012 | g_print ("CUPS Backend: Created local printer %s\n", printer_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Created local printer %s\n", printer_name ); }; } while (0); |
3013 | } |
3014 | else |
3015 | { |
3016 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating of local printer failed: %d\n" , ippGetStatusCode (response)); }; } while (0) |
3017 | g_print ("CUPS Backend: Creating of local printer failed: %d\n", ippGetStatusCode (response)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating of local printer failed: %d\n" , ippGetStatusCode (response)); }; } while (0); |
3018 | } |
3019 | |
3020 | iter = g_list_find_custom (print_backend->temporary_queues_in_construction, printer_name, (GCompareFunc) g_strcmp0); |
3021 | if (iter != NULL((void*)0)) |
3022 | { |
3023 | g_free (iter->data); |
3024 | print_backend->temporary_queues_in_construction = g_list_delete_link (print_backend->temporary_queues_in_construction, iter); |
3025 | } |
3026 | |
3027 | g_free (printer_name); |
3028 | } |
3029 | |
3030 | /* |
3031 | * Create CUPS temporary queue. |
3032 | */ |
3033 | #ifdef HAVE_CUPS_2_2 |
3034 | static void |
3035 | create_temporary_queue (CtkPrintBackendCups *backend, |
3036 | const gchar *printer_name, |
3037 | const gchar *printer_uri, |
3038 | const gchar *device_uri) |
3039 | { |
3040 | CtkCupsRequest *request; |
3041 | GList *iter; |
3042 | |
3043 | /* There can be several queues with the same name (ipp and ipps versions of the same printer) */ |
3044 | iter = g_list_find_custom (backend->temporary_queues_in_construction, printer_name, (GCompareFunc) g_strcmp0); |
3045 | if (iter != NULL((void*)0)) |
3046 | return; |
3047 | |
3048 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating local printer %s\n", printer_name ); }; } while (0) |
3049 | g_print ("CUPS Backend: Creating local printer %s\n", printer_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Creating local printer %s\n", printer_name ); }; } while (0); |
3050 | |
3051 | backend->temporary_queues_in_construction = g_list_prepend (backend->temporary_queues_in_construction, g_strdup (printer_name)g_strdup_inline (printer_name)); |
3052 | |
3053 | request = ctk_cups_request_new_with_username (NULL((void*)0), |
3054 | CTK_CUPS_POST, |
3055 | IPP_OP_CUPS_CREATE_LOCAL_PRINTER, |
3056 | NULL((void*)0), |
3057 | NULL((void*)0), |
3058 | NULL((void*)0), |
3059 | NULL((void*)0)); |
3060 | |
3061 | ctk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, |
3062 | "printer-uri", NULL((void*)0), printer_uri); |
3063 | ctk_cups_request_ipp_add_string (request, IPP_TAG_PRINTER, IPP_TAG_NAME, |
3064 | "printer-name", NULL((void*)0), printer_name); |
3065 | ctk_cups_request_ipp_add_string (request, IPP_TAG_PRINTER, IPP_TAG_URI, |
3066 | "device-uri", NULL((void*)0), device_uri); |
3067 | |
3068 | cups_request_execute (backend, |
3069 | request, |
3070 | (CtkPrintCupsResponseCallbackFunc) cups_create_local_printer_cb, |
3071 | NULL((void*)0), |
3072 | NULL((void*)0)); |
3073 | } |
3074 | #endif |
3075 | /* |
3076 | * Create new CtkPrinter from informations included in TXT records. |
3077 | */ |
3078 | static void |
3079 | create_cups_printer_from_avahi_data (AvahiConnectionTestData *data) |
3080 | { |
3081 | PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo)((PrinterSetupInfo*) g_slice_alloc0 (sizeof (PrinterSetupInfo ))); |
3082 | CtkPrinter *printer; |
3083 | |
3084 | printer = ctk_print_backend_find_printer (CTK_PRINT_BACKEND (data->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->backend)), ((ctk_print_backend_get_type ()))))) ), data->printer_name); |
3085 | if (printer != NULL((void*)0)) |
3086 | { |
3087 | /* A printer with this name is already present in this backend. It is probably the same printer |
3088 | * on another protocol (IPv4 vs IPv6). |
3089 | */ |
3090 | return; |
3091 | } |
3092 | |
3093 | info->avahi_printer = TRUE(!(0)); |
3094 | info->printer_name = data->printer_name; |
3095 | info->printer_uri = data->printer_uri; |
3096 | info->avahi_resource_path = data->resource_path; |
3097 | info->default_printer = FALSE(0); |
3098 | info->remote_printer = TRUE(!(0)); |
3099 | info->is_accepting_jobs = TRUE(!(0)); |
3100 | |
3101 | if (data->got_printer_state) |
3102 | { |
3103 | info->state = data->printer_state; |
3104 | info->is_paused = info->state == IPP_PRINTER_STOPPEDIPP_PSTATE_STOPPED; |
3105 | } |
3106 | |
3107 | info->got_printer_type = data->got_printer_type; |
3108 | if (data->got_printer_type) |
3109 | { |
3110 | if (data->printer_type & CUPS_PRINTER_DEFAULT) |
3111 | info->default_printer = TRUE(!(0)); |
3112 | else |
3113 | info->default_printer = FALSE(0); |
3114 | |
3115 | if (data->printer_type & CUPS_PRINTER_REMOTE) |
3116 | info->remote_printer = TRUE(!(0)); |
3117 | else |
3118 | info->remote_printer = FALSE(0); |
3119 | |
3120 | if (data->printer_type & CUPS_PRINTER_REJECTING) |
3121 | info->is_accepting_jobs = FALSE(0); |
3122 | else |
3123 | info->is_accepting_jobs = TRUE(!(0)); |
3124 | |
3125 | if (info->default_printer && |
3126 | data->backend->avahi_default_printer == NULL((void*)0)) |
3127 | data->backend->avahi_default_printer = g_strdup (info->printer_name)g_strdup_inline (info->printer_name); |
3128 | } |
3129 | |
3130 | set_info_state_message (info); |
3131 | |
3132 | printer = ctk_print_backend_find_printer (CTK_PRINT_BACKEND (data->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->backend)), ((ctk_print_backend_get_type ()))))) ), data->printer_name); |
3133 | if (printer == NULL((void*)0) && data->UUID != NULL((void*)0)) |
3134 | printer = find_printer_by_uuid (data->backend, data->UUID); |
3135 | |
3136 | if (printer == NULL((void*)0)) |
3137 | { |
3138 | printer = cups_create_printer (data->backend, info); |
3139 | |
3140 | if (data->got_printer_type) |
3141 | { |
3142 | ctk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs); |
3143 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->remote = info->remote_printer; |
3144 | |
3145 | if (info->default_printer && |
3146 | data->backend->avahi_default_printer == NULL((void*)0)) |
3147 | data->backend->avahi_default_printer = g_strdup (info->printer_name)g_strdup_inline (info->printer_name); |
3148 | } |
3149 | |
3150 | if (data->got_printer_state) |
3151 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->state = info->state; |
3152 | |
3153 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_name = g_strdup (data->name)g_strdup_inline (data->name); |
3154 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_type = g_strdup (data->type)g_strdup_inline (data->type); |
3155 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_domain = g_strdup (data->domain)g_strdup_inline (data->domain); |
3156 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->printer_uri = g_strdup (data->printer_uri)g_strdup_inline (data->printer_uri); |
3157 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->temporary_queue_device_uri = g_strdup (data->device_uri)g_strdup_inline (data->device_uri); |
3158 | g_free (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->hostname); |
3159 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->hostname = g_strdup (data->hostname)g_strdup_inline (data->hostname); |
3160 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->port = data->port; |
3161 | ctk_printer_set_location (printer, data->location); |
3162 | ctk_printer_set_state_message (printer, info->state_msg); |
3163 | |
3164 | set_printer_icon_name_from_info (printer, info); |
3165 | |
3166 | if (!ctk_printer_is_active (printer)) |
3167 | ctk_printer_set_is_active (printer, TRUE(!(0))); |
3168 | |
3169 | g_signal_emit_by_name (data->backend, "printer-added", printer); |
3170 | ctk_printer_set_is_new (printer, FALSE(0)); |
3171 | g_signal_emit_by_name (data->backend, "printer-list-changed"); |
3172 | |
3173 | if (!data->backend->got_default_printer && |
3174 | ctk_print_backend_printer_list_is_done (CTK_PRINT_BACKEND (data->backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->backend)), ((ctk_print_backend_get_type ()))))) )) && |
3175 | data->backend->avahi_default_printer != NULL((void*)0)) |
3176 | set_default_printer (data->backend, data->backend->avahi_default_printer); |
3177 | |
3178 | /* The ref is held by CtkPrintBackend, in add_printer() */ |
3179 | g_object_unref (printer); |
3180 | } |
3181 | |
3182 | printer_setup_info_free (info); |
3183 | } |
3184 | |
3185 | static void |
3186 | avahi_connection_test_cb (GObject *source_object, |
3187 | GAsyncResult *res, |
3188 | gpointer user_data) |
3189 | { |
3190 | AvahiConnectionTestData *data = (AvahiConnectionTestData *) user_data; |
3191 | GSocketConnection *connection; |
3192 | GError *error = NULL((void*)0); |
3193 | |
3194 | connection = g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (source_object)((((GSocketClient*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((source_object)), ((g_socket_client_get_type ())))))), |
3195 | res, |
3196 | &error); |
3197 | g_object_unref (source_object); |
3198 | |
3199 | if (connection != NULL((void*)0)) |
3200 | { |
3201 | g_io_stream_close (G_IO_STREAM (connection)((((GIOStream*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((connection)), ((g_io_stream_get_type ())))))), NULL((void*)0), NULL((void*)0)); |
3202 | g_object_unref (connection); |
3203 | |
3204 | create_cups_printer_from_avahi_data (data); |
3205 | } |
3206 | else |
3207 | { |
3208 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Can not connect to %s: %s\n", data ->address, error->message); }; } while (0) |
3209 | g_warning ("CUPS Backend: Can not connect to %s: %s\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Can not connect to %s: %s\n", data ->address, error->message); }; } while (0) |
3210 | data->address,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Can not connect to %s: %s\n", data ->address, error->message); }; } while (0) |
3211 | error->message))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Can not connect to %s: %s\n", data ->address, error->message); }; } while (0); |
3212 | g_error_free (error); |
3213 | } |
3214 | |
3215 | g_free (data->printer_uri); |
3216 | g_free (data->location); |
3217 | g_free (data->address); |
3218 | g_free (data->hostname); |
3219 | g_free (data->printer_name); |
3220 | g_free (data->name); |
3221 | g_free (data->resource_path); |
3222 | g_free (data->type); |
3223 | g_free (data->domain); |
3224 | g_free (data->device_uri); |
3225 | g_free (data); |
3226 | } |
3227 | |
3228 | gboolean |
3229 | avahi_txt_get_key_value_pair (const gchar *entry, |
3230 | gchar **key, |
3231 | gchar **value) |
3232 | { |
3233 | *key = NULL((void*)0); |
3234 | *value = NULL((void*)0); |
3235 | |
3236 | if (entry != NULL((void*)0)) |
3237 | { |
3238 | const gchar *equal_sign; |
3239 | |
3240 | /* See RFC 6763 section 6.3 */ |
3241 | equal_sign = strstr (entry, "="); |
3242 | |
3243 | if (equal_sign != NULL((void*)0)) |
3244 | { |
3245 | *key = g_strndup (entry, equal_sign - entry); |
3246 | *value = g_strdup (equal_sign + 1)g_strdup_inline (equal_sign + 1); |
3247 | |
3248 | return TRUE(!(0)); |
3249 | } |
3250 | } |
3251 | |
3252 | return FALSE(0); |
3253 | } |
3254 | |
3255 | static void |
3256 | avahi_service_resolver_cb (GObject *source_object, |
3257 | GAsyncResult *res, |
3258 | gpointer user_data) |
3259 | { |
3260 | CtkPrintBackendCups *backend; |
3261 | const gchar *name; |
3262 | const gchar *hostname; |
3263 | const gchar *type; |
3264 | const gchar *domain; |
3265 | const gchar *address; |
3266 | GVariant *output; |
3267 | GVariant *txt; |
3268 | guint32 flags; |
3269 | guint16 port; |
3270 | GError *error = NULL((void*)0); |
3271 | gchar **printer_name_strv; |
3272 | gchar *endptr; |
3273 | gchar *key; |
3274 | gchar *value; |
3275 | gsize length; |
3276 | gint interface; |
3277 | gint protocol; |
3278 | gint aprotocol; |
3279 | gint i, j; |
3280 | |
3281 | output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object)((((GDBusConnection*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((source_object)), ((g_dbus_connection_get_type ())))))), |
3282 | res, |
3283 | &error); |
3284 | if (output) |
3285 | { |
3286 | AvahiConnectionTestData *data; |
3287 | |
3288 | backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
3289 | |
3290 | g_variant_get (output, "(ii&s&s&s&si&sq@aayu)", |
3291 | &interface, |
3292 | &protocol, |
3293 | &name, |
3294 | &type, |
3295 | &domain, |
3296 | &hostname, |
3297 | &aprotocol, |
3298 | &address, |
3299 | &port, |
3300 | &txt, |
3301 | &flags); |
3302 | |
3303 | data = g_new0 (AvahiConnectionTestData, 1)((AvahiConnectionTestData *) g_malloc0_n ((1), sizeof (AvahiConnectionTestData ))); |
3304 | |
3305 | for (i = 0; i < g_variant_n_children (txt); i++) |
3306 | { |
3307 | GVariant *child; |
3308 | |
3309 | child = g_variant_get_child_value (txt, i); |
3310 | |
3311 | length = g_variant_get_size (child); |
3312 | if (length > 0) |
3313 | { |
3314 | gchar *tmp; |
3315 | |
3316 | tmp = g_strndup (g_variant_get_data (child), length); |
3317 | g_variant_unref (child); |
3318 | |
3319 | if (!avahi_txt_get_key_value_pair (tmp, &key, &value)) |
3320 | { |
3321 | g_free (tmp); |
3322 | continue; |
3323 | } |
3324 | |
3325 | if (g_strcmp0 (key, "rp") == 0) |
3326 | { |
3327 | data->resource_path = g_strdup (value)g_strdup_inline (value); |
3328 | } |
3329 | else if (g_strcmp0 (key, "note") == 0) |
3330 | { |
3331 | data->location = g_strdup (value)g_strdup_inline (value); |
3332 | } |
3333 | else if (g_strcmp0 (key, "printer-type") == 0) |
3334 | { |
3335 | endptr = NULL((void*)0); |
3336 | data->printer_type = g_ascii_strtoull (value, &endptr, 16); |
3337 | if (data->printer_type != 0 || endptr != value) |
3338 | data->got_printer_type = TRUE(!(0)); |
3339 | } |
3340 | else if (g_strcmp0 (key, "printer-state") == 0) |
3341 | { |
3342 | endptr = NULL((void*)0); |
3343 | data->printer_state = g_ascii_strtoull (value, &endptr, 10); |
3344 | if (data->printer_state != 0 || endptr != value) |
3345 | data->got_printer_state = TRUE(!(0)); |
3346 | } |
3347 | else if (g_strcmp0 (key, "UUID") == 0) |
3348 | { |
3349 | if (*value != '\0') |
3350 | data->UUID = g_strdup (value)g_strdup_inline (value); |
3351 | } |
3352 | |
3353 | g_clear_pointer (&key, g_free)do { _Static_assert (sizeof *(&key) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&key)) _pp = (&key); __typeof__ (*(&key)) _ptr = *_pp; *_pp = ( (void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
3354 | g_clear_pointer (&value, g_free)do { _Static_assert (sizeof *(&value) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ ((&value) ) _pp = (&value); __typeof__ (*(&value)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
3355 | g_free (tmp); |
3356 | } |
3357 | else |
3358 | { |
3359 | g_variant_unref (child); |
3360 | } |
3361 | } |
3362 | |
3363 | if (data->resource_path != NULL((void*)0)) |
3364 | { |
3365 | gchar **printer_name_compressed_strv; |
3366 | gchar *printer_name; |
3367 | GList *iter; |
3368 | |
3369 | /* |
3370 | * Create name of temporary queue from the name of the discovered service. |
3371 | * This emulates the way how CUPS creates the name. |
3372 | */ |
3373 | printer_name = g_strdup_printf ("%s", name); |
3374 | g_strcanon (printer_name, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", '_'); |
3375 | |
3376 | printer_name_strv = g_strsplit_set (printer_name, "_", -1); |
3377 | printer_name_compressed_strv = g_new0 (gchar *, g_strv_length (printer_name_strv) + 1)((gchar * *) g_malloc0_n ((g_strv_length (printer_name_strv) + 1), sizeof (gchar *))); |
3378 | for (i = 0, j = 0; printer_name_strv[i] != NULL((void*)0); i++) |
3379 | { |
3380 | /* |
3381 | * Keep an empty segment at the beginning or end, if any. |
3382 | * This emulates the way cups-browsed in Debian 11 created |
3383 | * printer names (before 1.28.11), for example: |
3384 | * "Some Printer (123456)" -> Some_Printer_123456_ |
3385 | * and hypothetically |
3386 | * "(Really) Working Printer" -> _Really_Working_Printer |
3387 | */ |
3388 | if (printer_name_strv[i][0] != '\0' || i == 0 || printer_name_strv[i + 1] == NULL((void*)0)) |
3389 | { |
3390 | printer_name_compressed_strv[j] = printer_name_strv[i]; |
3391 | j++; |
3392 | } |
3393 | } |
3394 | |
3395 | data->printer_name = g_strjoinv ("_", printer_name_compressed_strv); |
3396 | |
3397 | g_strfreev (printer_name_strv); |
3398 | g_free (printer_name_compressed_strv); |
3399 | g_free (printer_name); |
3400 | |
3401 | iter = g_list_find_custom (backend->temporary_queues_removed, data->printer_name, (GCompareFunc) g_strcmp0); |
3402 | if (iter != NULL((void*)0)) |
3403 | { |
3404 | g_free (iter->data); |
3405 | backend->temporary_queues_removed = g_list_delete_link (backend->temporary_queues_removed, iter); |
3406 | } |
3407 | |
3408 | if (g_strcmp0 (type, "_ipp._tcp") == 0) |
3409 | { |
3410 | data->printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", data->printer_name); |
3411 | data->device_uri = g_strdup_printf ("ipp://%s:%d/%s", hostname, port, data->resource_path); |
3412 | } |
3413 | else |
3414 | { |
3415 | data->printer_uri = g_strdup_printf ("ipps://localhost/printers/%s", data->printer_name); |
3416 | data->device_uri = g_strdup_printf ("ipps://%s:%d/%s", hostname, port, data->resource_path); |
3417 | } |
3418 | |
3419 | data->address = g_strdup (address)g_strdup_inline (address); |
3420 | data->hostname = g_strdup (hostname)g_strdup_inline (hostname); |
3421 | data->port = port; |
3422 | |
3423 | data->name = g_strdup (name)g_strdup_inline (name); |
3424 | data->type = g_strdup (type)g_strdup_inline (type); |
3425 | data->domain = g_strdup (domain)g_strdup_inline (domain); |
3426 | data->backend = backend; |
3427 | |
3428 | /* It can happen that the address is not reachable */ |
3429 | g_socket_client_connect_to_host_async (g_socket_client_new (), |
3430 | address, |
3431 | port, |
3432 | backend->avahi_cancellable, |
3433 | avahi_connection_test_cb, |
3434 | data); |
3435 | } |
3436 | else |
3437 | { |
3438 | g_free (data->printer_name); |
3439 | g_free (data->location); |
3440 | g_free (data); |
3441 | } |
3442 | |
3443 | g_variant_unref (txt); |
3444 | g_variant_unref (output); |
3445 | } |
3446 | else |
3447 | { |
3448 | if (!g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED)) |
3449 | g_warning ("%s", error->message); |
3450 | g_error_free (error); |
3451 | } |
3452 | } |
3453 | |
3454 | static void |
3455 | avahi_service_browser_signal_handler (GDBusConnection *connection G_GNUC_UNUSED__attribute__ ((__unused__)), |
3456 | const gchar *sender_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
3457 | const gchar *object_path G_GNUC_UNUSED__attribute__ ((__unused__)), |
3458 | const gchar *interface_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
3459 | const gchar *signal_name, |
3460 | GVariant *parameters, |
3461 | gpointer user_data) |
3462 | { |
3463 | CtkPrintBackendCups *backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
3464 | gchar *name; |
3465 | gchar *type; |
3466 | gchar *domain; |
3467 | guint flags; |
3468 | gint interface; |
3469 | gint protocol; |
3470 | |
3471 | if (g_strcmp0 (signal_name, "ItemNew") == 0) |
3472 | { |
3473 | g_variant_get (parameters, "(ii&s&s&su)", |
3474 | &interface, |
3475 | &protocol, |
3476 | &name, |
3477 | &type, |
3478 | &domain, |
3479 | &flags); |
3480 | |
3481 | if (g_strcmp0 (type, "_ipp._tcp") == 0 || |
3482 | g_strcmp0 (type, "_ipps._tcp") == 0) |
3483 | { |
3484 | g_dbus_connection_call (backend->dbus_connection, |
3485 | AVAHI_BUS"org.freedesktop.Avahi", |
3486 | "/", |
3487 | AVAHI_SERVER_IFACE"org.freedesktop.Avahi.Server", |
3488 | "ResolveService", |
3489 | g_variant_new ("(iisssiu)", |
3490 | interface, |
3491 | protocol, |
3492 | name, |
3493 | type, |
3494 | domain, |
3495 | AVAHI_PROTO_UNSPEC-1, |
3496 | 0), |
3497 | G_VARIANT_TYPE ("(iissssisqaayu)")(g_variant_type_checked_ (("(iissssisqaayu)"))), |
3498 | G_DBUS_CALL_FLAGS_NONE, |
3499 | -1, |
3500 | backend->avahi_cancellable, |
3501 | avahi_service_resolver_cb, |
3502 | user_data); |
3503 | } |
3504 | } |
3505 | else if (g_strcmp0 (signal_name, "ItemRemove") == 0) |
3506 | { |
3507 | g_variant_get (parameters, "(ii&s&s&su)", |
3508 | &interface, |
3509 | &protocol, |
3510 | &name, |
3511 | &type, |
3512 | &domain, |
3513 | &flags); |
3514 | |
3515 | if (g_strcmp0 (type, "_ipp._tcp") == 0 || |
3516 | g_strcmp0 (type, "_ipps._tcp") == 0) |
3517 | { |
3518 | GList *list; |
3519 | GList *iter; |
3520 | |
3521 | list = ctk_print_backend_get_printer_list (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((backend)), ((ctk_print_backend_get_type ()))))))); |
3522 | for (iter = list; iter; iter = iter->next) |
3523 | { |
3524 | CtkPrinterCups *printer; |
3525 | |
3526 | printer = CTK_PRINTER_CUPS (iter->data)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((iter->data)), ((ctk_printer_cups_get_type ())))))); |
3527 | if (g_strcmp0 (printer->avahi_name, name) == 0 && |
3528 | g_strcmp0 (printer->avahi_type, type) == 0 && |
3529 | g_strcmp0 (printer->avahi_domain, domain) == 0) |
3530 | { |
3531 | if (g_strcmp0 (ctk_printer_get_name (CTK_PRINTER (printer)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_get_type ()))))))), |
3532 | backend->avahi_default_printer) == 0) |
3533 | g_clear_pointer (&backend->avahi_default_printer, g_free)do { _Static_assert (sizeof *(&backend->avahi_default_printer ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&backend->avahi_default_printer)) _pp = (&backend ->avahi_default_printer); __typeof__ (*(&backend->avahi_default_printer )) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
3534 | |
3535 | backend->temporary_queues_removed = g_list_prepend (backend->temporary_queues_removed, |
3536 | g_strdup (ctk_printer_get_name (CTK_PRINTER (printer)))g_strdup_inline (ctk_printer_get_name (((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((printer)), ((ctk_printer_get_type ()))))))))); |
3537 | |
3538 | g_signal_emit_by_name (backend, "printer-removed", printer); |
3539 | ctk_print_backend_remove_printer (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((backend)), ((ctk_print_backend_get_type ())))))), |
3540 | CTK_PRINTER (printer)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_get_type ()))))))); |
3541 | g_signal_emit_by_name (backend, "printer-list-changed"); |
3542 | break; |
3543 | } |
3544 | } |
3545 | |
3546 | g_list_free (list); |
3547 | } |
3548 | } |
3549 | } |
3550 | |
3551 | static gboolean |
3552 | unsubscribe_general_subscription_cb (gpointer user_data) |
3553 | { |
3554 | CtkPrintBackendCups *cups_backend = user_data; |
3555 | |
3556 | g_dbus_connection_signal_unsubscribe (cups_backend->dbus_connection, |
3557 | cups_backend->avahi_service_browser_subscription_id); |
3558 | cups_backend->avahi_service_browser_subscription_id = 0; |
3559 | cups_backend->unsubscribe_general_subscription_id = 0; |
3560 | |
3561 | return G_SOURCE_REMOVE(0); |
3562 | } |
3563 | |
3564 | static void |
3565 | avahi_service_browser_new_cb (GObject *source_object, |
3566 | GAsyncResult *res, |
3567 | gpointer user_data) |
3568 | { |
3569 | CtkPrintBackendCups *cups_backend; |
3570 | GVariant *output; |
3571 | GError *error = NULL((void*)0); |
3572 | gint i; |
3573 | |
3574 | output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object)((((GDBusConnection*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((source_object)), ((g_dbus_connection_get_type ())))))), |
3575 | res, |
3576 | &error); |
3577 | if (output) |
3578 | { |
3579 | cups_backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
3580 | i = cups_backend->avahi_service_browser_paths[0] ? 1 : 0; |
3581 | |
3582 | g_variant_get (output, "(o)", &cups_backend->avahi_service_browser_paths[i]); |
3583 | |
3584 | cups_backend->avahi_service_browser_subscription_ids[i] = |
3585 | g_dbus_connection_signal_subscribe (cups_backend->dbus_connection, |
3586 | NULL((void*)0), |
3587 | AVAHI_SERVICE_BROWSER_IFACE"org.freedesktop.Avahi.ServiceBrowser", |
3588 | NULL((void*)0), |
3589 | cups_backend->avahi_service_browser_paths[i], |
3590 | NULL((void*)0), |
3591 | G_DBUS_SIGNAL_FLAGS_NONE, |
3592 | avahi_service_browser_signal_handler, |
3593 | user_data, |
3594 | NULL((void*)0)); |
3595 | |
3596 | /* |
3597 | * The general subscription for all service browsers is not needed |
3598 | * now because we are already subscribed to service browsers |
3599 | * specific to _ipp._tcp and _ipps._tcp services. |
3600 | */ |
3601 | if (cups_backend->avahi_service_browser_paths[0] && |
3602 | cups_backend->avahi_service_browser_paths[1] && |
3603 | cups_backend->avahi_service_browser_subscription_id > 0) |
3604 | { |
3605 | /* We need to unsubscribe in idle since signals in queue destined for emit |
3606 | * are emitted in idle and check whether the subscriber is still subscribed. |
3607 | */ |
3608 | cups_backend->unsubscribe_general_subscription_id = g_idle_add (unsubscribe_general_subscription_cb, cups_backend); |
3609 | } |
3610 | |
3611 | g_variant_unref (output); |
3612 | } |
3613 | else |
3614 | { |
3615 | /* |
3616 | * The creation of ServiceBrowser fails with G_IO_ERROR_DBUS_ERROR |
3617 | * if Avahi is disabled. |
3618 | */ |
3619 | if (!g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_DBUS_ERROR) && |
3620 | !g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED)) |
3621 | g_warning ("%s", error->message); |
3622 | g_error_free (error); |
3623 | } |
3624 | } |
3625 | |
3626 | static void |
3627 | avahi_create_browsers (GObject *source_object G_GNUC_UNUSED__attribute__ ((__unused__)), |
3628 | GAsyncResult *res, |
3629 | gpointer user_data) |
3630 | { |
3631 | GDBusConnection *dbus_connection; |
3632 | CtkPrintBackendCups *cups_backend; |
3633 | GError *error = NULL((void*)0); |
3634 | |
3635 | dbus_connection = g_bus_get_finish (res, &error); |
3636 | if (!dbus_connection) |
3637 | { |
3638 | if (!g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED)) |
3639 | g_warning ("Couldn't connect to D-Bus system bus, %s", error->message); |
3640 | |
3641 | g_error_free (error); |
3642 | return; |
3643 | } |
3644 | |
3645 | cups_backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
3646 | cups_backend->dbus_connection = dbus_connection; |
3647 | |
3648 | /* |
3649 | * We need to subscribe to signals of service browser before |
3650 | * we actually create it because it starts to emit them right |
3651 | * after its creation. |
3652 | */ |
3653 | cups_backend->avahi_service_browser_subscription_id = |
3654 | g_dbus_connection_signal_subscribe (cups_backend->dbus_connection, |
3655 | NULL((void*)0), |
3656 | AVAHI_SERVICE_BROWSER_IFACE"org.freedesktop.Avahi.ServiceBrowser", |
3657 | NULL((void*)0), |
3658 | NULL((void*)0), |
3659 | NULL((void*)0), |
3660 | G_DBUS_SIGNAL_FLAGS_NONE, |
3661 | avahi_service_browser_signal_handler, |
3662 | cups_backend, |
3663 | NULL((void*)0)); |
3664 | |
3665 | /* |
3666 | * Create service browsers for _ipp._tcp and _ipps._tcp services. |
3667 | */ |
3668 | g_dbus_connection_call (cups_backend->dbus_connection, |
3669 | AVAHI_BUS"org.freedesktop.Avahi", |
3670 | "/", |
3671 | AVAHI_SERVER_IFACE"org.freedesktop.Avahi.Server", |
3672 | "ServiceBrowserNew", |
3673 | g_variant_new ("(iissu)", |
3674 | AVAHI_IF_UNSPEC-1, |
3675 | AVAHI_PROTO_UNSPEC-1, |
3676 | "_ipp._tcp", |
3677 | "", |
3678 | 0), |
3679 | G_VARIANT_TYPE ("(o)")(g_variant_type_checked_ (("(o)"))), |
3680 | G_DBUS_CALL_FLAGS_NONE, |
3681 | -1, |
3682 | cups_backend->avahi_cancellable, |
3683 | avahi_service_browser_new_cb, |
3684 | cups_backend); |
3685 | |
3686 | g_dbus_connection_call (cups_backend->dbus_connection, |
3687 | AVAHI_BUS"org.freedesktop.Avahi", |
3688 | "/", |
3689 | AVAHI_SERVER_IFACE"org.freedesktop.Avahi.Server", |
3690 | "ServiceBrowserNew", |
3691 | g_variant_new ("(iissu)", |
3692 | AVAHI_IF_UNSPEC-1, |
3693 | AVAHI_PROTO_UNSPEC-1, |
3694 | "_ipps._tcp", |
3695 | "", |
3696 | 0), |
3697 | G_VARIANT_TYPE ("(o)")(g_variant_type_checked_ (("(o)"))), |
3698 | G_DBUS_CALL_FLAGS_NONE, |
3699 | -1, |
3700 | cups_backend->avahi_cancellable, |
3701 | avahi_service_browser_new_cb, |
3702 | cups_backend); |
3703 | } |
3704 | |
3705 | static void |
3706 | avahi_request_printer_list (CtkPrintBackendCups *cups_backend) |
3707 | { |
3708 | cups_backend->avahi_cancellable = g_cancellable_new (); |
3709 | g_bus_get (G_BUS_TYPE_SYSTEM, cups_backend->avahi_cancellable, avahi_create_browsers, cups_backend); |
3710 | } |
3711 | |
3712 | static void |
3713 | cups_request_printer_list_cb (CtkPrintBackendCups *cups_backend, |
3714 | CtkCupsResult *result, |
3715 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
3716 | { |
3717 | CtkPrintBackend *backend = CTK_PRINT_BACKEND (cups_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cups_backend)), ((ctk_print_backend_get_type ())))))); |
3718 | ipp_attribute_t *attr; |
3719 | ipp_t *response; |
3720 | gboolean list_has_changed; |
3721 | GList *removed_printer_checklist; |
3722 | gchar *remote_default_printer = NULL((void*)0); |
3723 | GList *iter; |
3724 | |
3725 | cdk_threads_enter (); |
3726 | |
3727 | list_has_changed = FALSE(0); |
3728 | |
3729 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
3730 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
3731 | |
3732 | cups_backend->list_printers_pending = FALSE(0); |
3733 | |
3734 | if (ctk_cups_result_is_error (result)) |
3735 | { |
3736 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer list: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
3737 | g_warning ("CUPS Backend: Error getting printer list: %s %d %d",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer list: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
3738 | ctk_cups_result_get_error_string (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer list: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
3739 | ctk_cups_result_get_error_type (result),do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer list: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0) |
3740 | ctk_cups_result_get_error_code (result)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Error getting printer list: %s %d %d" , ctk_cups_result_get_error_string (result), ctk_cups_result_get_error_type (result), ctk_cups_result_get_error_code (result)); }; } while (0); |
3741 | |
3742 | if (ctk_cups_result_get_error_type (result) == CTK_CUPS_ERROR_AUTH && |
3743 | ctk_cups_result_get_error_code (result) == 1) |
3744 | { |
3745 | /* Canceled by user, stop popping up more password dialogs */ |
3746 | if (cups_backend->list_printers_poll > 0) |
3747 | g_source_remove (cups_backend->list_printers_poll); |
3748 | cups_backend->list_printers_poll = 0; |
3749 | cups_backend->list_printers_attempts = 0; |
3750 | } |
3751 | |
3752 | goto done; |
3753 | } |
3754 | |
3755 | /* Gather the names of the printers in the current queue |
3756 | * so we may check to see if they were removed |
3757 | */ |
3758 | removed_printer_checklist = ctk_print_backend_get_printer_list (backend); |
3759 | |
3760 | response = ctk_cups_result_get_response (result); |
3761 | for (attr = ippFirstAttribute (response); attr != NULL((void*)0); |
3762 | attr = ippNextAttribute (response)) |
3763 | { |
3764 | CtkPrinter *printer; |
3765 | gboolean status_changed = FALSE(0); |
3766 | GList *node; |
3767 | PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo)((PrinterSetupInfo*) g_slice_alloc0 (sizeof (PrinterSetupInfo ))); |
3768 | |
3769 | /* Skip leading attributes until we hit a printer... |
3770 | */ |
3771 | while (attr != NULL((void*)0) && ippGetGroupTag (attr) != IPP_TAG_PRINTER) |
3772 | attr = ippNextAttribute (response); |
3773 | |
3774 | if (attr == NULL((void*)0)) |
3775 | break; |
3776 | |
3777 | while (attr != NULL((void*)0) && ippGetGroupTag (attr) == IPP_TAG_PRINTER) |
3778 | { |
3779 | cups_printer_handle_attribute (cups_backend, attr, info); |
3780 | attr = ippNextAttribute (response); |
3781 | } |
3782 | |
3783 | if (info->printer_name == NULL((void*)0) || |
3784 | (info->printer_uri == NULL((void*)0) && info->member_uris == NULL((void*)0))) |
3785 | { |
3786 | if (attr == NULL((void*)0)) |
3787 | break; |
3788 | else |
3789 | continue; |
3790 | } |
3791 | |
3792 | /* Do not show printer for queue which was removed from Avahi. */ |
3793 | iter = g_list_find_custom (CTK_PRINT_BACKEND_CUPS (backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((backend)), ((ctk_print_backend_cups_get_type ()))))))->temporary_queues_removed, |
3794 | info->printer_name, (GCompareFunc) g_strcmp0); |
3795 | if (iter != NULL((void*)0)) |
3796 | continue; |
3797 | |
3798 | if (info->got_printer_type) |
3799 | { |
3800 | if (info->default_printer && !cups_backend->got_default_printer) |
3801 | { |
3802 | if (!info->remote_printer) |
3803 | { |
3804 | cups_backend->got_default_printer = TRUE(!(0)); |
3805 | cups_backend->default_printer = g_strdup (info->printer_name)g_strdup_inline (info->printer_name); |
3806 | } |
3807 | else |
3808 | { |
3809 | if (remote_default_printer == NULL((void*)0)) |
3810 | remote_default_printer = g_strdup (info->printer_name)g_strdup_inline (info->printer_name); |
3811 | } |
3812 | } |
3813 | } |
3814 | else |
3815 | { |
3816 | if (!cups_backend->got_default_printer) |
3817 | cups_get_default_printer (cups_backend); |
3818 | } |
3819 | |
3820 | /* remove name from checklist if it was found */ |
3821 | node = g_list_find_custom (removed_printer_checklist, |
3822 | info->printer_name, |
3823 | (GCompareFunc) find_printer); |
3824 | removed_printer_checklist = g_list_delete_link (removed_printer_checklist, |
3825 | node); |
3826 | |
3827 | printer = ctk_print_backend_find_printer (backend, info->printer_name); |
3828 | if (!printer) |
3829 | { |
3830 | printer = cups_create_printer (cups_backend, info); |
3831 | list_has_changed = TRUE(!(0)); |
3832 | } |
3833 | else if (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_browsed && info->is_temporary) |
3834 | { |
3835 | /* |
3836 | * A temporary queue was created for a printer found via Avahi. |
3837 | * We modify the placeholder CtkPrinter to point to the temporary queue |
3838 | * instead of removing the placeholder CtkPrinter and creating new CtkPrinter. |
3839 | */ |
3840 | |
3841 | g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer)); |
3842 | |
3843 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_browsed = FALSE(0); |
3844 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->is_temporary = TRUE(!(0)); |
3845 | g_free (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->device_uri); |
3846 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->device_uri = g_strdup_printf ("/printers/%s", |
3847 | info->printer_name); |
3848 | ctk_printer_set_has_details (printer, FALSE(0)); |
3849 | cups_printer_request_details (printer); |
3850 | } |
3851 | else |
3852 | g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer)); |
3853 | |
3854 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->remote = info->remote_printer; |
3855 | |
3856 | ctk_printer_set_is_paused (printer, info->is_paused); |
3857 | ctk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs); |
3858 | |
3859 | if (!ctk_printer_is_active (printer)) |
3860 | { |
3861 | ctk_printer_set_is_active (printer, TRUE(!(0))); |
3862 | ctk_printer_set_is_new (printer, TRUE(!(0))); |
3863 | list_has_changed = TRUE(!(0)); |
3864 | } |
3865 | |
3866 | if (ctk_printer_is_new (printer)) |
3867 | { |
3868 | g_signal_emit_by_name (backend, "printer-added", printer); |
3869 | |
3870 | ctk_printer_set_is_new (printer, FALSE(0)); |
3871 | } |
3872 | |
3873 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->state = info->state; |
3874 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->ipp_version_major = info->ipp_version_major; |
3875 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->ipp_version_minor = info->ipp_version_minor; |
3876 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_copies = info->supports_copies; |
3877 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_collate = info->supports_collate; |
3878 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->supports_number_up = info->supports_number_up; |
3879 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->number_of_covers = info->number_of_covers; |
3880 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->covers = g_strdupv (info->covers); |
3881 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->is_temporary = info->is_temporary; |
3882 | status_changed = ctk_printer_set_job_count (printer, info->job_count); |
3883 | status_changed |= ctk_printer_set_location (printer, info->location); |
3884 | status_changed |= ctk_printer_set_description (printer, |
3885 | info->description); |
3886 | |
3887 | set_info_state_message (info); |
3888 | |
3889 | status_changed |= ctk_printer_set_state_message (printer, info->state_msg); |
3890 | status_changed |= ctk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs); |
3891 | |
3892 | set_printer_icon_name_from_info (printer, info); |
3893 | |
3894 | if (status_changed) |
3895 | g_signal_emit_by_name (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((backend)), ((ctk_print_backend_get_type ())))))), |
3896 | "printer-status-changed", printer); |
3897 | |
3898 | /* The ref is held by CtkPrintBackend, in add_printer() */ |
3899 | g_object_unref (printer); |
3900 | printer_setup_info_free (info); |
3901 | |
3902 | if (attr == NULL((void*)0)) |
3903 | break; |
3904 | } |
3905 | |
3906 | /* look at the removed printers checklist and mark any printer |
3907 | as inactive if it is in the list, emitting a printer_removed signal */ |
3908 | if (removed_printer_checklist != NULL((void*)0)) |
3909 | { |
3910 | for (iter = removed_printer_checklist; iter; iter = iter->next) |
3911 | { |
3912 | if (!CTK_PRINTER_CUPS (iter->data)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((iter->data)), ((ctk_printer_cups_get_type ()))))))->avahi_browsed) |
3913 | { |
3914 | mark_printer_inactive (CTK_PRINTER (iter->data)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((iter->data)), ((ctk_printer_get_type ())))))), backend); |
3915 | list_has_changed = TRUE(!(0)); |
3916 | } |
3917 | } |
3918 | |
3919 | g_list_free (removed_printer_checklist); |
3920 | } |
3921 | |
3922 | done: |
3923 | if (list_has_changed) |
3924 | g_signal_emit_by_name (backend, "printer-list-changed"); |
3925 | |
3926 | ctk_print_backend_set_list_done (backend); |
3927 | |
3928 | if (!cups_backend->got_default_printer && remote_default_printer != NULL((void*)0)) |
3929 | { |
3930 | set_default_printer (cups_backend, remote_default_printer); |
3931 | g_free (remote_default_printer); |
3932 | } |
3933 | |
3934 | if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL((void*)0)) |
3935 | set_default_printer (cups_backend, cups_backend->avahi_default_printer); |
3936 | |
3937 | cdk_threads_leave (); |
3938 | } |
3939 | |
3940 | static void |
3941 | update_backend_status (CtkPrintBackendCups *cups_backend, |
3942 | CtkCupsConnectionState state) |
3943 | { |
3944 | switch (state) |
3945 | { |
3946 | case CTK_CUPS_CONNECTION_NOT_AVAILABLE: |
3947 | g_object_set (cups_backend, "status", CTK_PRINT_BACKEND_STATUS_UNAVAILABLE, NULL((void*)0)); |
3948 | break; |
3949 | case CTK_CUPS_CONNECTION_AVAILABLE: |
3950 | g_object_set (cups_backend, "status", CTK_PRINT_BACKEND_STATUS_OK, NULL((void*)0)); |
3951 | break; |
3952 | default: ; |
3953 | } |
3954 | } |
3955 | |
3956 | static gboolean |
3957 | cups_request_printer_list (CtkPrintBackendCups *cups_backend) |
3958 | { |
3959 | CtkCupsConnectionState state; |
3960 | CtkCupsRequest *request; |
3961 | |
3962 | if (cups_backend->reading_ppds > 0 || cups_backend->list_printers_pending) |
3963 | return TRUE(!(0)); |
3964 | |
3965 | state = ctk_cups_connection_test_get_state (cups_backend->cups_connection_test); |
3966 | update_backend_status (cups_backend, state); |
3967 | |
3968 | if (cups_backend->list_printers_attempts == 60) |
3969 | { |
3970 | cups_backend->list_printers_attempts = -1; |
3971 | if (cups_backend->list_printers_poll > 0) |
3972 | g_source_remove (cups_backend->list_printers_poll); |
3973 | cups_backend->list_printers_poll = cdk_threads_add_timeout (200, |
3974 | (GSourceFunc) cups_request_printer_list, |
3975 | cups_backend); |
3976 | g_source_set_name_by_id (cups_backend->list_printers_poll, "[ctk+] cups_request_printer_list"); |
3977 | } |
3978 | else if (cups_backend->list_printers_attempts != -1) |
3979 | cups_backend->list_printers_attempts++; |
3980 | |
3981 | if (state == CTK_CUPS_CONNECTION_IN_PROGRESS || state == CTK_CUPS_CONNECTION_NOT_AVAILABLE) |
3982 | return TRUE(!(0)); |
3983 | else |
3984 | if (cups_backend->list_printers_attempts > 0) |
3985 | cups_backend->list_printers_attempts = 60; |
3986 | |
3987 | cups_backend->list_printers_pending = TRUE(!(0)); |
3988 | |
3989 | request = ctk_cups_request_new_with_username (NULL((void*)0), |
3990 | CTK_CUPS_POST, |
3991 | CUPS_GET_PRINTERSIPP_OP_CUPS_GET_PRINTERS, |
3992 | NULL((void*)0), |
3993 | NULL((void*)0), |
3994 | NULL((void*)0), |
3995 | cups_backend->username); |
3996 | |
3997 | ctk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, |
3998 | "requested-attributes", G_N_ELEMENTS (printer_attrs)(sizeof (printer_attrs) / sizeof ((printer_attrs)[0])), |
3999 | NULL((void*)0), printer_attrs); |
4000 | |
4001 | cups_request_execute (cups_backend, |
4002 | request, |
4003 | (CtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb, |
4004 | request, |
4005 | NULL((void*)0)); |
4006 | |
4007 | return TRUE(!(0)); |
4008 | } |
4009 | |
4010 | static void |
4011 | cups_get_printer_list (CtkPrintBackend *backend) |
4012 | { |
4013 | CtkPrintBackendCups *cups_backend; |
4014 | |
4015 | cups_backend = CTK_PRINT_BACKEND_CUPS (backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((backend)), ((ctk_print_backend_cups_get_type ())))))); |
4016 | |
4017 | if (cups_backend->cups_connection_test == NULL((void*)0)) |
4018 | cups_backend->cups_connection_test = ctk_cups_connection_test_new (NULL((void*)0), -1); |
4019 | |
4020 | if (cups_backend->list_printers_poll == 0) |
4021 | { |
4022 | if (cups_request_printer_list (cups_backend)) |
4023 | { |
4024 | cups_backend->list_printers_poll = cdk_threads_add_timeout (50, |
4025 | (GSourceFunc) cups_request_printer_list, |
4026 | backend); |
4027 | g_source_set_name_by_id (cups_backend->list_printers_poll, "[ctk+] cups_request_printer_list"); |
4028 | } |
4029 | |
4030 | avahi_request_printer_list (cups_backend); |
4031 | } |
4032 | } |
4033 | |
4034 | typedef struct { |
4035 | CtkPrinterCups *printer; |
4036 | GIOChannel *ppd_io; |
4037 | http_t *http; |
4038 | } GetPPDData; |
4039 | |
4040 | static void |
4041 | get_ppd_data_free (GetPPDData *data) |
4042 | { |
4043 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
4044 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
4045 | httpClose (data->http); |
4046 | g_io_channel_unref (data->ppd_io); |
4047 | g_object_unref (data->printer); |
4048 | g_free (data); |
4049 | } |
4050 | |
4051 | static void |
4052 | cups_request_ppd_cb (CtkPrintBackendCups *print_backend, |
4053 | CtkCupsResult *result, |
4054 | GetPPDData *data) |
4055 | { |
4056 | CtkPrinter *printer; |
4057 | struct stat data_info; |
4058 | |
4059 | cdk_threads_enter (); |
4060 | |
4061 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
4062 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
4063 | |
4064 | printer = CTK_PRINTER (data->printer)((((CtkPrinter*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->printer)), ((ctk_printer_get_type ())))))); |
4065 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->reading_ppd = FALSE(0); |
4066 | print_backend->reading_ppds--; |
4067 | |
4068 | if (!ctk_cups_result_is_error (result)) |
4069 | { |
4070 | /* let ppdOpenFd take over the ownership of the open file */ |
4071 | g_io_channel_seek_position (data->ppd_io, 0, G_SEEK_SET, NULL((void*)0)); |
4072 | data->printer->ppd_file = ppdOpenFd (dup (g_io_channel_unix_get_fd (data->ppd_io))); |
4073 | ppdLocalize (data->printer->ppd_file); |
4074 | ppdMarkDefaults (data->printer->ppd_file); |
4075 | } |
4076 | |
4077 | fstat (g_io_channel_unix_get_fd (data->ppd_io), &data_info); |
4078 | /* |
4079 | * Standalone Avahi printers and raw printers don't have PPD files or have |
4080 | * empty PPD files. Try to get printer details via IPP. |
4081 | * Always do this for Avahi printers. |
4082 | */ |
4083 | if (data_info.st_size == 0 || |
4084 | CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))->avahi_browsed || |
4085 | (ctk_cups_result_is_error (result) && |
4086 | ((ctk_cups_result_get_error_type (result) == CTK_CUPS_ERROR_HTTP) && |
4087 | (ctk_cups_result_get_error_status (result) == HTTP_NOT_FOUNDHTTP_STATUS_NOT_FOUND)))) |
4088 | { |
4089 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
4090 | |
4091 | /* Try to get the PPD from original host if it is not |
4092 | * available on current CUPS server. |
4093 | */ |
4094 | if (!cups_printer->avahi_browsed && |
4095 | (ctk_cups_result_is_error (result) && |
4096 | ((ctk_cups_result_get_error_type (result) == CTK_CUPS_ERROR_HTTP) && |
4097 | (ctk_cups_result_get_error_status (result) == HTTP_NOT_FOUNDHTTP_STATUS_NOT_FOUND))) && |
4098 | cups_printer->remote && |
4099 | !cups_printer->request_original_uri && |
4100 | cups_printer->original_device_uri != NULL((void*)0) && |
4101 | (g_str_has_prefix (cups_printer->original_device_uri, "ipp://")(__builtin_constant_p ("ipp://")? __extension__ ({ const char * const __str = (cups_printer->original_device_uri); const char * const __prefix = ("ipp://"); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len ) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix )), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) ( cups_printer->original_device_uri, "ipp://") ) || |
4102 | g_str_has_prefix (cups_printer->original_device_uri, "ipps://")(__builtin_constant_p ("ipps://")? __extension__ ({ const char * const __str = (cups_printer->original_device_uri); const char * const __prefix = ("ipps://"); gboolean __result = (0) ; if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len ) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix )), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) ( cups_printer->original_device_uri, "ipps://") ))) |
4103 | { |
4104 | cups_printer->request_original_uri = TRUE(!(0)); |
4105 | |
4106 | ctk_cups_connection_test_free (cups_printer->remote_cups_connection_test); |
4107 | g_clear_handle_id (&cups_printer->get_remote_ppd_poll, g_source_remove)do { _Static_assert (sizeof *(&cups_printer->get_remote_ppd_poll ) == sizeof (guint), "Expression evaluates to false"); guint * _tag_ptr = (guint *) (&cups_printer->get_remote_ppd_poll ); guint _handle_id; _handle_id = *_tag_ptr; if (_handle_id > 0) { *_tag_ptr = 0; g_source_remove (_handle_id); } } while ( 0); |
4108 | cups_printer->get_remote_ppd_attempts = 0; |
4109 | |
4110 | cups_printer->remote_cups_connection_test = |
4111 | ctk_cups_connection_test_new (cups_printer->original_hostname, |
4112 | cups_printer->original_port); |
4113 | |
4114 | if (cups_request_ppd (printer)) |
4115 | { |
4116 | cups_printer->get_remote_ppd_poll = g_timeout_add (50, (GSourceFunc) cups_request_ppd, printer); |
4117 | g_source_set_name_by_id (cups_printer->get_remote_ppd_poll, "[ctk] cups_request_ppd"); |
4118 | } |
4119 | } |
4120 | else |
4121 | { |
4122 | if (cups_printer->request_original_uri) |
4123 | cups_printer->request_original_uri = FALSE(0); |
4124 | |
4125 | cups_request_printer_info (cups_printer); |
4126 | } |
4127 | |
4128 | goto done; |
4129 | } |
4130 | |
4131 | ctk_printer_set_has_details (printer, TRUE(!(0))); |
4132 | g_signal_emit_by_name (printer, "details-acquired", TRUE(!(0))); |
4133 | |
4134 | done: |
4135 | cdk_threads_leave (); |
4136 | } |
4137 | |
4138 | static gboolean |
4139 | cups_request_ppd (CtkPrinter *printer) |
4140 | { |
4141 | GError *error; |
4142 | CtkPrintBackend *print_backend; |
4143 | CtkPrinterCups *cups_printer; |
4144 | CtkCupsRequest *request; |
4145 | char *ppd_filename = NULL((void*)0); |
4146 | gchar *resource; |
4147 | http_t *http; |
4148 | GetPPDData *data; |
4149 | int fd; |
4150 | const gchar *hostname; |
4151 | gint port; |
4152 | |
4153 | cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
4154 | |
4155 | error = NULL((void*)0); |
4156 | |
4157 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0) |
4158 | g_print ("CUPS Backend: %s\n", G_STRFUNC))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: %s\n", ((const char*) (__func__))); } ; } while (0); |
4159 | |
4160 | if (cups_printer->remote && !cups_printer->avahi_browsed) |
4161 | { |
4162 | CtkCupsConnectionState state; |
4163 | |
4164 | state = ctk_cups_connection_test_get_state (cups_printer->remote_cups_connection_test); |
4165 | |
4166 | if (state == CTK_CUPS_CONNECTION_IN_PROGRESS) |
4167 | { |
4168 | if (cups_printer->get_remote_ppd_attempts == 60) |
4169 | { |
4170 | cups_printer->get_remote_ppd_attempts = -1; |
4171 | if (cups_printer->get_remote_ppd_poll > 0) |
4172 | g_source_remove (cups_printer->get_remote_ppd_poll); |
4173 | cups_printer->get_remote_ppd_poll = cdk_threads_add_timeout (200, |
4174 | (GSourceFunc) cups_request_ppd, |
4175 | printer); |
4176 | g_source_set_name_by_id (cups_printer->get_remote_ppd_poll, "[ctk+] cups_request_ppd"); |
4177 | } |
4178 | else if (cups_printer->get_remote_ppd_attempts != -1) |
4179 | cups_printer->get_remote_ppd_attempts++; |
4180 | |
4181 | return TRUE(!(0)); |
4182 | } |
4183 | |
4184 | ctk_cups_connection_test_free (cups_printer->remote_cups_connection_test); |
4185 | cups_printer->remote_cups_connection_test = NULL((void*)0); |
4186 | cups_printer->get_remote_ppd_poll = 0; |
4187 | cups_printer->get_remote_ppd_attempts = 0; |
4188 | |
4189 | if (state == CTK_CUPS_CONNECTION_NOT_AVAILABLE) |
4190 | { |
4191 | g_signal_emit_by_name (printer, "details-acquired", FALSE(0)); |
4192 | return FALSE(0); |
4193 | } |
4194 | } |
4195 | |
4196 | if (cups_printer->request_original_uri) |
4197 | { |
4198 | hostname = cups_printer->original_hostname; |
4199 | port = cups_printer->original_port; |
4200 | resource = g_strdup_printf ("%s.ppd", cups_printer->original_resource); |
4201 | } |
4202 | else |
4203 | { |
4204 | if (cups_printer->is_temporary) |
4205 | hostname = cupsServer (); |
4206 | else |
4207 | hostname = cups_printer->hostname; |
4208 | |
4209 | port = cups_printer->port; |
4210 | resource = g_strdup_printf ("/printers/%s.ppd", |
4211 | ctk_printer_cups_get_ppd_name (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))))); |
4212 | } |
4213 | |
4214 | http = httpConnect2 (hostname, port, |
4215 | NULL((void*)0), AF_UNSPEC0, |
4216 | cupsEncryption (), |
4217 | 1, 30000, NULL((void*)0)); |
4218 | |
4219 | data = g_new0 (GetPPDData, 1)((GetPPDData *) g_malloc0_n ((1), sizeof (GetPPDData))); |
4220 | |
4221 | fd = g_file_open_tmp ("ctkprint_ppd_XXXXXX", |
4222 | &ppd_filename, |
4223 | &error); |
4224 | |
4225 | #ifdef G_ENABLE_DEBUG1 |
4226 | /* If we are debugging printing don't delete the tmp files */ |
4227 | if (!(ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) |
4228 | unlink (ppd_filename); |
4229 | #else |
4230 | unlink (ppd_filename); |
4231 | #endif /* G_ENABLE_DEBUG */ |
4232 | |
4233 | if (error != NULL((void*)0)) |
4234 | { |
4235 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Failed to create temp file, %s\n", error->message); }; } while (0) |
4236 | g_warning ("CUPS Backend: Failed to create temp file, %s\n",do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Failed to create temp file, %s\n", error->message); }; } while (0) |
4237 | error->message))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Failed to create temp file, %s\n", error->message); }; } while (0); |
4238 | g_error_free (error); |
4239 | httpClose (http); |
4240 | g_free (ppd_filename); |
4241 | g_free (data); |
4242 | |
4243 | g_signal_emit_by_name (printer, "details-acquired", FALSE(0)); |
4244 | return FALSE(0); |
4245 | } |
4246 | |
4247 | data->http = http; |
4248 | fchmod (fd, S_IRUSR0400 | S_IWUSR0200); |
4249 | data->ppd_io = g_io_channel_unix_new (fd); |
4250 | g_io_channel_set_encoding (data->ppd_io, NULL((void*)0), NULL((void*)0)); |
4251 | g_io_channel_set_close_on_unref (data->ppd_io, TRUE(!(0))); |
4252 | |
4253 | data->printer = (CtkPrinterCups *) g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer)); |
4254 | |
4255 | print_backend = ctk_printer_get_backend (printer); |
4256 | |
4257 | request = ctk_cups_request_new_with_username (data->http, |
4258 | CTK_CUPS_GET, |
4259 | 0, |
4260 | data->ppd_io, |
4261 | hostname, |
4262 | resource, |
4263 | CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ()))))))->username); |
4264 | |
4265 | ctk_cups_request_set_ipp_version (request, |
4266 | cups_printer->ipp_version_major, |
4267 | cups_printer->ipp_version_minor); |
4268 | |
4269 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n" , resource, ppd_filename); }; } while (0) |
4270 | g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n", resource, ppd_filename))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n" , resource, ppd_filename); }; } while (0); |
4271 | |
4272 | |
4273 | cups_printer->reading_ppd = TRUE(!(0)); |
4274 | CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ()))))))->reading_ppds++; |
4275 | |
4276 | cups_request_execute (CTK_PRINT_BACKEND_CUPS (print_backend)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((print_backend)), ((ctk_print_backend_cups_get_type ())))))), |
4277 | request, |
4278 | (CtkPrintCupsResponseCallbackFunc) cups_request_ppd_cb, |
4279 | data, |
4280 | (GDestroyNotify)get_ppd_data_free); |
4281 | |
4282 | g_free (resource); |
4283 | g_free (ppd_filename); |
4284 | |
4285 | return FALSE(0); |
4286 | } |
4287 | |
4288 | /* Ordering matters for default preference */ |
4289 | static const char *lpoptions_locations[] = { |
4290 | "/etc/cups/lpoptions", |
4291 | ".lpoptions", |
4292 | ".cups/lpoptions" |
4293 | }; |
4294 | |
4295 | static void |
4296 | cups_parse_user_default_printer (const char *filename, |
4297 | char **printer_name) |
4298 | { |
4299 | FILE *fp; |
4300 | char line[1024], *lineptr, *defname = NULL((void*)0); |
4301 | |
4302 | if ((fp = g_fopenfopen (filename, "r")) == NULL((void*)0)) |
4303 | return; |
4304 | |
4305 | while (fgets (line, sizeof (line), fp) != NULL((void*)0)) |
4306 | { |
4307 | if (strncasecmp (line, "default", 7) != 0 || !isspace (line[7])((*__ctype_b_loc ())[(int) ((line[7]))] & (unsigned short int) _ISspace)) |
4308 | continue; |
4309 | |
4310 | lineptr = line + 8; |
4311 | while (isspace (*lineptr)((*__ctype_b_loc ())[(int) ((*lineptr))] & (unsigned short int) _ISspace)) |
4312 | lineptr++; |
4313 | |
4314 | if (!*lineptr) |
4315 | continue; |
4316 | |
4317 | defname = lineptr; |
4318 | while (!isspace (*lineptr)((*__ctype_b_loc ())[(int) ((*lineptr))] & (unsigned short int) _ISspace) && *lineptr && *lineptr != '/') |
4319 | lineptr++; |
4320 | |
4321 | *lineptr = '\0'; |
4322 | |
4323 | g_free (*printer_name); |
4324 | |
4325 | *printer_name = g_strdup (defname)g_strdup_inline (defname); |
4326 | } |
4327 | |
4328 | fclose (fp); |
4329 | } |
4330 | |
4331 | static void |
4332 | cups_get_user_default_printer (char **printer_name) |
4333 | { |
4334 | int i; |
4335 | |
4336 | for (i = 0; i < G_N_ELEMENTS (lpoptions_locations)(sizeof (lpoptions_locations) / sizeof ((lpoptions_locations) [0])); i++) |
4337 | { |
4338 | if (g_path_is_absolute (lpoptions_locations[i])) |
4339 | { |
4340 | cups_parse_user_default_printer (lpoptions_locations[i], |
4341 | printer_name); |
4342 | } |
4343 | else |
4344 | { |
4345 | char *filename; |
4346 | |
4347 | filename = g_build_filename (g_get_home_dir (), |
4348 | lpoptions_locations[i], NULL((void*)0)); |
4349 | cups_parse_user_default_printer (filename, printer_name); |
4350 | g_free (filename); |
4351 | } |
4352 | } |
4353 | } |
4354 | |
4355 | static int |
4356 | cups_parse_user_options (const char *filename, |
4357 | const char *printer_name, |
4358 | int num_options, |
4359 | cups_option_t **options) |
4360 | { |
4361 | FILE *fp; |
4362 | gchar line[1024], *lineptr, *name; |
4363 | |
4364 | if ((fp = g_fopenfopen (filename, "r")) == NULL((void*)0)) |
4365 | return num_options; |
4366 | |
4367 | while (fgets (line, sizeof (line), fp) != NULL((void*)0)) |
4368 | { |
4369 | if (strncasecmp (line, "dest", 4) == 0 && isspace (line[4])((*__ctype_b_loc ())[(int) ((line[4]))] & (unsigned short int) _ISspace)) |
4370 | lineptr = line + 4; |
4371 | else if (strncasecmp (line, "default", 7) == 0 && isspace (line[7])((*__ctype_b_loc ())[(int) ((line[7]))] & (unsigned short int) _ISspace)) |
4372 | lineptr = line + 7; |
4373 | else |
4374 | continue; |
4375 | |
4376 | /* Skip leading whitespace */ |
4377 | while (isspace (*lineptr)((*__ctype_b_loc ())[(int) ((*lineptr))] & (unsigned short int) _ISspace)) |
4378 | lineptr++; |
4379 | |
4380 | if (!*lineptr) |
4381 | continue; |
4382 | |
4383 | name = lineptr; |
4384 | while (!isspace (*lineptr)((*__ctype_b_loc ())[(int) ((*lineptr))] & (unsigned short int) _ISspace) && *lineptr) |
4385 | { |
4386 | lineptr++; |
4387 | } |
4388 | |
4389 | if (!*lineptr) |
4390 | continue; |
4391 | |
4392 | *lineptr++ = '\0'; |
4393 | |
4394 | if (strcasecmp (name, printer_name) != 0) |
4395 | continue; |
4396 | |
4397 | /* We found our printer, parse the options */ |
4398 | num_options = cupsParseOptions (lineptr, num_options, options); |
4399 | } |
4400 | |
4401 | fclose (fp); |
4402 | |
4403 | return num_options; |
4404 | } |
4405 | |
4406 | static int |
4407 | cups_get_user_options (const char *printer_name, |
4408 | int num_options, |
4409 | cups_option_t **options) |
4410 | { |
4411 | int i; |
4412 | |
4413 | for (i = 0; i < G_N_ELEMENTS (lpoptions_locations)(sizeof (lpoptions_locations) / sizeof ((lpoptions_locations) [0])); i++) |
4414 | { |
4415 | if (g_path_is_absolute (lpoptions_locations[i])) |
4416 | { |
4417 | num_options = cups_parse_user_options (lpoptions_locations[i], |
4418 | printer_name, |
4419 | num_options, |
4420 | options); |
4421 | } |
4422 | else |
4423 | { |
4424 | char *filename; |
4425 | |
4426 | filename = g_build_filename (g_get_home_dir (), |
4427 | lpoptions_locations[i], NULL((void*)0)); |
4428 | num_options = cups_parse_user_options (filename, printer_name, |
4429 | num_options, options); |
4430 | g_free (filename); |
4431 | } |
4432 | } |
4433 | |
4434 | return num_options; |
4435 | } |
4436 | |
4437 | /* This function requests default printer from a CUPS server in regular intervals. |
4438 | * In the case of unreachable CUPS server the request is repeated later. |
4439 | * The default printer is not requested in the case of previous success. |
4440 | */ |
4441 | static void |
4442 | cups_get_default_printer (CtkPrintBackendCups *backend) |
4443 | { |
4444 | CtkPrintBackendCups *cups_backend; |
4445 | |
4446 | cups_backend = backend; |
4447 | |
4448 | if (cups_backend->cups_connection_test == NULL((void*)0)) |
4449 | cups_backend->cups_connection_test = ctk_cups_connection_test_new (NULL((void*)0), -1); |
4450 | |
4451 | if (cups_backend->default_printer_poll == 0) |
4452 | { |
4453 | if (cups_request_default_printer (cups_backend)) |
4454 | { |
4455 | cups_backend->default_printer_poll = cdk_threads_add_timeout (200, |
4456 | (GSourceFunc) cups_request_default_printer, |
4457 | backend); |
4458 | g_source_set_name_by_id (cups_backend->default_printer_poll, "[ctk+] cups_request_default_printer"); |
4459 | } |
4460 | } |
4461 | } |
4462 | |
4463 | /* This function gets default printer from local settings.*/ |
4464 | static void |
4465 | cups_get_local_default_printer (CtkPrintBackendCups *backend) |
4466 | { |
4467 | const char *str; |
4468 | char *name = NULL((void*)0); |
4469 | |
4470 | if ((str = g_getenv ("LPDEST")) != NULL((void*)0)) |
4471 | { |
4472 | backend->default_printer = g_strdup (str)g_strdup_inline (str); |
4473 | backend->got_default_printer = TRUE(!(0)); |
4474 | return; |
4475 | } |
4476 | else if ((str = g_getenv ("PRINTER")) != NULL((void*)0) && |
4477 | strcmp (str, "lp") != 0) |
4478 | { |
4479 | backend->default_printer = g_strdup (str)g_strdup_inline (str); |
4480 | backend->got_default_printer = TRUE(!(0)); |
4481 | return; |
4482 | } |
4483 | |
4484 | /* Figure out user setting for default printer */ |
4485 | cups_get_user_default_printer (&name); |
4486 | if (name != NULL((void*)0)) |
4487 | { |
4488 | backend->default_printer = name; |
4489 | backend->got_default_printer = TRUE(!(0)); |
4490 | return; |
4491 | } |
4492 | } |
4493 | |
4494 | static void |
4495 | cups_request_default_printer_cb (CtkPrintBackendCups *print_backend, |
4496 | CtkCupsResult *result, |
4497 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
4498 | { |
4499 | ipp_t *response; |
4500 | ipp_attribute_t *attr; |
4501 | |
4502 | cdk_threads_enter (); |
4503 | |
4504 | if (ctk_cups_result_is_error (result)) |
4505 | { |
4506 | if (ctk_cups_result_get_error_type (result) == CTK_CUPS_ERROR_AUTH && |
4507 | ctk_cups_result_get_error_code (result) == 1) |
4508 | { |
4509 | /* Canceled by user, stop popping up more password dialogs */ |
4510 | if (print_backend->list_printers_poll > 0) |
4511 | g_source_remove (print_backend->list_printers_poll); |
4512 | print_backend->list_printers_poll = 0; |
4513 | } |
4514 | |
4515 | return; |
4516 | } |
4517 | |
4518 | response = ctk_cups_result_get_response (result); |
4519 | |
4520 | if ((attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME)) != NULL((void*)0)) |
4521 | print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL))g_strdup_inline (ippGetString (attr, 0, ((void*)0))); |
4522 | |
4523 | print_backend->got_default_printer = TRUE(!(0)); |
4524 | |
4525 | if (print_backend->default_printer != NULL((void*)0)) |
4526 | { |
4527 | CtkPrinter *printer; |
4528 | |
4529 | printer = ctk_print_backend_find_printer (CTK_PRINT_BACKEND (print_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((print_backend)), ((ctk_print_backend_get_type ())))))), |
4530 | print_backend->default_printer); |
4531 | if (printer != NULL((void*)0)) |
4532 | { |
4533 | ctk_printer_set_is_default (printer, TRUE(!(0))); |
4534 | g_signal_emit_by_name (CTK_PRINT_BACKEND (print_backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((print_backend)), ((ctk_print_backend_get_type ())))))), "printer-status-changed", printer); |
4535 | } |
4536 | } |
4537 | |
4538 | /* Make sure to kick off get_printers if we are polling it, |
4539 | * as we could have blocked this reading the default printer |
4540 | */ |
4541 | if (print_backend->list_printers_poll != 0) |
4542 | cups_request_printer_list (print_backend); |
4543 | |
4544 | cdk_threads_leave (); |
4545 | } |
4546 | |
4547 | static gboolean |
4548 | cups_request_default_printer (CtkPrintBackendCups *print_backend) |
4549 | { |
4550 | CtkCupsConnectionState state; |
4551 | CtkCupsRequest *request; |
4552 | |
4553 | state = ctk_cups_connection_test_get_state (print_backend->cups_connection_test); |
4554 | update_backend_status (print_backend, state); |
4555 | |
4556 | if (state == CTK_CUPS_CONNECTION_IN_PROGRESS || state == CTK_CUPS_CONNECTION_NOT_AVAILABLE) |
4557 | return TRUE(!(0)); |
4558 | |
4559 | request = ctk_cups_request_new_with_username (NULL((void*)0), |
4560 | CTK_CUPS_POST, |
4561 | CUPS_GET_DEFAULTIPP_OP_CUPS_GET_DEFAULT, |
4562 | NULL((void*)0), |
4563 | NULL((void*)0), |
4564 | NULL((void*)0), |
4565 | print_backend->username); |
4566 | |
4567 | cups_request_execute (print_backend, |
4568 | request, |
4569 | (CtkPrintCupsResponseCallbackFunc) cups_request_default_printer_cb, |
4570 | g_object_ref (print_backend)((__typeof__ (print_backend)) (g_object_ref) (print_backend)), |
4571 | g_object_unref); |
4572 | |
4573 | return FALSE(0); |
4574 | } |
4575 | |
4576 | static void |
4577 | cups_printer_request_details (CtkPrinter *printer) |
4578 | { |
4579 | CtkPrinterCups *cups_printer; |
4580 | |
4581 | cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
4582 | |
4583 | if (cups_printer->avahi_browsed) |
4584 | { |
4585 | #ifdef HAVE_CUPS_2_2 |
4586 | create_temporary_queue (CTK_PRINT_BACKEND_CUPS (ctk_printer_get_backend (printer))((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((ctk_printer_get_backend (printer))), ((ctk_print_backend_cups_get_type ())))))), |
4587 | ctk_printer_get_name (printer), |
4588 | cups_printer->printer_uri, |
4589 | cups_printer->temporary_queue_device_uri); |
4590 | #endif |
4591 | } |
4592 | else if (!cups_printer->reading_ppd && |
4593 | ctk_printer_cups_get_ppd (cups_printer) == NULL((void*)0)) |
4594 | { |
4595 | if (cups_printer->remote && !cups_printer->avahi_browsed) |
4596 | { |
4597 | if (cups_printer->get_remote_ppd_poll == 0) |
4598 | { |
4599 | cups_printer->remote_cups_connection_test = |
4600 | ctk_cups_connection_test_new (cups_printer->hostname, |
4601 | cups_printer->port); |
4602 | |
4603 | if (cups_request_ppd (printer)) |
4604 | { |
4605 | cups_printer->get_remote_ppd_poll = cdk_threads_add_timeout (50, |
4606 | (GSourceFunc) cups_request_ppd, |
4607 | printer); |
4608 | g_source_set_name_by_id (cups_printer->get_remote_ppd_poll, "[ctk+] cups_request_ppd"); |
4609 | } |
4610 | } |
4611 | } |
4612 | else |
4613 | cups_request_ppd (printer); |
4614 | } |
4615 | } |
4616 | |
4617 | static char * |
4618 | ppd_text_to_utf8 (ppd_file_t *ppd_file, |
4619 | const char *text) |
4620 | { |
4621 | const char *encoding = NULL((void*)0); |
4622 | char *res; |
4623 | |
4624 | if (g_ascii_strcasecmp (ppd_file->lang_encoding, "UTF-8") == 0) |
4625 | { |
4626 | return g_strdup (text)g_strdup_inline (text); |
4627 | } |
4628 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "ISOLatin1") == 0) |
4629 | { |
4630 | encoding = "ISO-8859-1"; |
4631 | } |
4632 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "ISOLatin2") == 0) |
4633 | { |
4634 | encoding = "ISO-8859-2"; |
4635 | } |
4636 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "ISOLatin5") == 0) |
4637 | { |
4638 | encoding = "ISO-8859-5"; |
4639 | } |
4640 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "JIS83-RKSJ") == 0) |
4641 | { |
4642 | encoding = "SHIFT-JIS"; |
4643 | } |
4644 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "MacStandard") == 0) |
4645 | { |
4646 | encoding = "MACINTOSH"; |
4647 | } |
4648 | else if (g_ascii_strcasecmp (ppd_file->lang_encoding, "WindowsANSI") == 0) |
4649 | { |
4650 | encoding = "WINDOWS-1252"; |
4651 | } |
4652 | else |
4653 | { |
4654 | /* Fallback, try iso-8859-1... */ |
4655 | encoding = "ISO-8859-1"; |
4656 | } |
4657 | |
4658 | res = g_convert (text, -1, "UTF-8", encoding, NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
4659 | |
4660 | if (res == NULL((void*)0)) |
4661 | { |
4662 | CTK_NOTE (PRINTING,do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Unable to convert PPD text\n"); }; } while (0) |
4663 | g_warning ("CUPS Backend: Unable to convert PPD text\n"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_PRINTING)) { g_warning ("CUPS Backend: Unable to convert PPD text\n"); }; } while (0); |
4664 | res = g_strdup ("???")g_strdup_inline ("???"); |
4665 | } |
4666 | |
4667 | return res; |
4668 | } |
4669 | |
4670 | /* TODO: Add more translations for common settings here */ |
4671 | |
4672 | static const struct { |
4673 | const char *keyword; |
4674 | const char *translation; |
4675 | } cups_option_translations[] = { |
4676 | { "Duplex", NC_("printing option", "Two Sided")("Two Sided") }, |
4677 | { "MediaType", NC_("printing option", "Paper Type")("Paper Type") }, |
4678 | { "InputSlot", NC_("printing option", "Paper Source")("Paper Source") }, |
4679 | { "OutputBin", NC_("printing option", "Output Tray")("Output Tray") }, |
4680 | { "Resolution", NC_("printing option", "Resolution")("Resolution") }, |
4681 | { "PreFilter", NC_("printing option", "GhostScript pre-filtering")("GhostScript pre-filtering") } |
4682 | }; |
4683 | |
4684 | |
4685 | static const struct { |
4686 | const char *keyword; |
4687 | const char *choice; |
4688 | const char *translation; |
4689 | } cups_choice_translations[] = { |
4690 | { "Duplex", "None", NC_("printing option value", "One Sided")("One Sided") }, |
4691 | /* Translators: this is an option of "Two Sided" */ |
4692 | { "Duplex", "DuplexNoTumble", NC_("printing option value", "Long Edge (Standard)")("Long Edge (Standard)") }, |
4693 | /* Translators: this is an option of "Two Sided" */ |
4694 | { "Duplex", "DuplexTumble", NC_("printing option value", "Short Edge (Flip)")("Short Edge (Flip)") }, |
4695 | /* Translators: this is an option of "Paper Source" */ |
4696 | { "InputSlot", "Auto", NC_("printing option value", "Auto Select")("Auto Select") }, |
4697 | /* Translators: this is an option of "Paper Source" */ |
4698 | { "InputSlot", "AutoSelect", NC_("printing option value", "Auto Select")("Auto Select") }, |
4699 | /* Translators: this is an option of "Paper Source" */ |
4700 | { "InputSlot", "Default", NC_("printing option value", "Printer Default")("Printer Default") }, |
4701 | /* Translators: this is an option of "Paper Source" */ |
4702 | { "InputSlot", "None", NC_("printing option value", "Printer Default")("Printer Default") }, |
4703 | /* Translators: this is an option of "Paper Source" */ |
4704 | { "InputSlot", "PrinterDefault", NC_("printing option value", "Printer Default")("Printer Default") }, |
4705 | /* Translators: this is an option of "Paper Source" */ |
4706 | { "InputSlot", "Unspecified", NC_("printing option value", "Auto Select")("Auto Select") }, |
4707 | /* Translators: this is an option of "Resolution" */ |
4708 | { "Resolution", "default", NC_("printing option value", "Printer Default")("Printer Default") }, |
4709 | /* Translators: this is an option of "GhostScript" */ |
4710 | { "PreFilter", "EmbedFonts", NC_("printing option value", "Embed GhostScript fonts only")("Embed GhostScript fonts only") }, |
4711 | /* Translators: this is an option of "GhostScript" */ |
4712 | { "PreFilter", "Level1", NC_("printing option value", "Convert to PS level 1")("Convert to PS level 1") }, |
4713 | /* Translators: this is an option of "GhostScript" */ |
4714 | { "PreFilter", "Level2", NC_("printing option value", "Convert to PS level 2")("Convert to PS level 2") }, |
4715 | /* Translators: this is an option of "GhostScript" */ |
4716 | { "PreFilter", "No", NC_("printing option value", "No pre-filtering")("No pre-filtering") } |
4717 | }; |
4718 | |
4719 | static const struct { |
4720 | const char *name; |
4721 | const char *translation; |
4722 | } cups_group_translations[] = { |
4723 | /* Translators: "Miscellaneous" is the label for a button, that opens |
4724 | up an extra panel of settings in a print dialog. */ |
4725 | { "Miscellaneous", NC_("printing option group", "Miscellaneous")("Miscellaneous") } |
4726 | }; |
4727 | |
4728 | static const struct { |
4729 | const char *ppd_keyword; |
4730 | const char *name; |
4731 | } ppd_option_names[] = { |
4732 | { "Duplex", "ctk-duplex" }, |
4733 | { "MediaType", "ctk-paper-type" }, |
4734 | { "InputSlot", "ctk-paper-source" }, |
4735 | { "OutputBin", "ctk-output-tray" } |
4736 | }; |
4737 | |
4738 | static const struct { |
4739 | const char *ipp_option_name; |
4740 | const char *ctk_option_name; |
4741 | const char *translation; |
4742 | } ipp_option_translations[] = { |
4743 | { "sides", "ctk-duplex", NC_("printing option", "Two Sided")("Two Sided") }, |
4744 | { "output-bin", "ctk-output-tray", NC_("printing option", "Output Tray")("Output Tray") } |
4745 | }; |
4746 | |
4747 | static const struct { |
4748 | const char *ipp_option_name; |
4749 | const char *ipp_choice; |
4750 | const char *translation; |
4751 | } ipp_choice_translations[] = { |
4752 | { "sides", "one-sided", NC_("sides", "One Sided")("One Sided") }, |
4753 | /* Translators: this is an option of "Two Sided" */ |
4754 | { "sides", "two-sided-long-edge", NC_("sides", "Long Edge (Standard)")("Long Edge (Standard)") }, |
4755 | /* Translators: this is an option of "Two Sided" */ |
4756 | { "sides", "two-sided-short-edge", NC_("sides", "Short Edge (Flip)")("Short Edge (Flip)") }, |
4757 | |
4758 | /* Translators: Top output bin */ |
4759 | { "output-bin", "top", NC_("output-bin", "Top Bin")("Top Bin") }, |
4760 | /* Translators: Middle output bin */ |
4761 | { "output-bin", "middle", NC_("output-bin", "Middle Bin")("Middle Bin") }, |
4762 | /* Translators: Bottom output bin */ |
4763 | { "output-bin", "bottom", NC_("output-bin", "Bottom Bin")("Bottom Bin") }, |
4764 | /* Translators: Side output bin */ |
4765 | { "output-bin", "side", NC_("output-bin", "Side Bin")("Side Bin") }, |
4766 | /* Translators: Left output bin */ |
4767 | { "output-bin", "left", NC_("output-bin", "Left Bin")("Left Bin") }, |
4768 | /* Translators: Right output bin */ |
4769 | { "output-bin", "right", NC_("output-bin", "Right Bin")("Right Bin") }, |
4770 | /* Translators: Center output bin */ |
4771 | { "output-bin", "center", NC_("output-bin", "Center Bin")("Center Bin") }, |
4772 | /* Translators: Rear output bin */ |
4773 | { "output-bin", "rear", NC_("output-bin", "Rear Bin")("Rear Bin") }, |
4774 | /* Translators: Output bin where one sided output is oriented in the face-up position */ |
4775 | { "output-bin", "face-up", NC_("output-bin", "Face Up Bin")("Face Up Bin") }, |
4776 | /* Translators: Output bin where one sided output is oriented in the face-down position */ |
4777 | { "output-bin", "face-down", NC_("output-bin", "Face Down Bin")("Face Down Bin") }, |
4778 | /* Translators: Large capacity output bin */ |
4779 | { "output-bin", "large-capacity", NC_("output-bin", "Large Capacity Bin")("Large Capacity Bin") }, |
4780 | { NULL((void*)0), NULL((void*)0), NULL((void*)0) } |
4781 | }; |
4782 | |
4783 | /* |
4784 | * Handles "format not a string literal" error |
4785 | * https://mail.gnome.org/archives/desktop-devel-list/2016-March/msg00075.html |
4786 | */ |
4787 | static gchar * |
4788 | get_ipp_choice_translation_string (gint index, |
4789 | guint i) |
4790 | { |
4791 | gchar *translation; |
4792 | |
4793 | if (i < G_N_ELEMENTS (ipp_choice_translations)(sizeof (ipp_choice_translations) / sizeof ((ipp_choice_translations )[0]))) |
4794 | translation = g_strdup (_(ipp_choice_translations[i].translation))g_strdup_inline (((char *) g_dgettext ("ctk30", ipp_choice_translations [i].translation))); |
4795 | else |
4796 | { |
4797 | switch (i) |
4798 | { |
4799 | case 14: |
4800 | /* Translators: Output stacker number %d */ |
4801 | translation = g_strdup_printf (C_("output-bin", "Stacker %d")g_dpgettext ("ctk30", "output-bin" "\004" "Stacker %d", strlen ("output-bin") + 1), index); |
4802 | break; |
4803 | case 15: |
4804 | /* Translators: Output mailbox number %d */ |
4805 | translation = g_strdup_printf (C_("output-bin", "Mailbox %d")g_dpgettext ("ctk30", "output-bin" "\004" "Mailbox %d", strlen ("output-bin") + 1), index); |
4806 | break; |
4807 | case 16: |
4808 | /* Translators: Private mailbox */ |
4809 | translation = g_strdup (C_("output-bin", "My Mailbox"))g_strdup_inline (g_dpgettext ("ctk30", "output-bin" "\004" "My Mailbox" , strlen ("output-bin") + 1)); |
4810 | break; |
4811 | case 17: |
4812 | /* Translators: Output tray number %d */ |
4813 | translation = g_strdup_printf (C_("output-bin", "Tray %d")g_dpgettext ("ctk30", "output-bin" "\004" "Tray %d", strlen ( "output-bin") + 1), index); |
4814 | break; |
4815 | default: |
4816 | g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "ctkprintbackendcups.c" , 4816, ((const char*) (__func__)), ((void*)0)); } while (0); |
4817 | } |
4818 | } |
4819 | |
4820 | return translation; |
4821 | } |
4822 | |
4823 | static const struct { |
4824 | const char *lpoption; |
4825 | const char *name; |
4826 | } lpoption_names[] = { |
4827 | { "number-up", "ctk-n-up" }, |
4828 | { "number-up-layout", "ctk-n-up-layout" }, |
4829 | { "job-billing", "ctk-billing-info" }, |
4830 | { "job-priority", "ctk-job-prio" } |
4831 | }; |
4832 | |
4833 | /* keep sorted when changing */ |
4834 | static const char *color_option_whitelist[] = { |
4835 | "BRColorEnhancement", |
4836 | "BRColorMatching", |
4837 | "BRColorMatching", |
4838 | "BRColorMode", |
4839 | "BRGammaValue", |
4840 | "BRImprovedGray", |
4841 | "BlackSubstitution", |
4842 | "ColorModel", |
4843 | "HPCMYKInks", |
4844 | "HPCSGraphics", |
4845 | "HPCSImages", |
4846 | "HPCSText", |
4847 | "HPColorSmart", |
4848 | "RPSBlackMode", |
4849 | "RPSBlackOverPrint", |
4850 | "Rcmyksimulation", |
4851 | }; |
4852 | |
4853 | /* keep sorted when changing */ |
4854 | static const char *color_group_whitelist[] = { |
4855 | "ColorPage", |
4856 | "FPColorWise1", |
4857 | "FPColorWise2", |
4858 | "FPColorWise3", |
4859 | "FPColorWise4", |
4860 | "FPColorWise5", |
4861 | "HPColorOptionsPanel", |
4862 | }; |
4863 | |
4864 | /* keep sorted when changing */ |
4865 | static const char *image_quality_option_whitelist[] = { |
4866 | "BRDocument", |
4867 | "BRHalfTonePattern", |
4868 | "BRNormalPrt", |
4869 | "BRPrintQuality", |
4870 | "BitsPerPixel", |
4871 | "Darkness", |
4872 | "Dithering", |
4873 | "EconoMode", |
4874 | "Economode", |
4875 | "HPEconoMode", |
4876 | "HPEdgeControl", |
4877 | "HPGraphicsHalftone", |
4878 | "HPHalftone", |
4879 | "HPLJDensity", |
4880 | "HPPhotoHalftone", |
4881 | "OutputMode", |
4882 | "REt", |
4883 | "RPSBitsPerPixel", |
4884 | "RPSDitherType", |
4885 | "Resolution", |
4886 | "ScreenLock", |
4887 | "Smoothing", |
4888 | "TonerSaveMode", |
4889 | "UCRGCRForImage", |
4890 | }; |
4891 | |
4892 | /* keep sorted when changing */ |
4893 | static const char *image_quality_group_whitelist[] = { |
4894 | "FPImageQuality1", |
4895 | "FPImageQuality2", |
4896 | "FPImageQuality3", |
4897 | "ImageQualityPage", |
4898 | }; |
4899 | |
4900 | /* keep sorted when changing */ |
4901 | static const char * finishing_option_whitelist[] = { |
4902 | "BindColor", |
4903 | "BindEdge", |
4904 | "BindType", |
4905 | "BindWhen", |
4906 | "Booklet", |
4907 | "FoldType", |
4908 | "FoldWhen", |
4909 | "HPStaplerOptions", |
4910 | "Jog", |
4911 | "Slipsheet", |
4912 | "Sorter", |
4913 | "StapleLocation", |
4914 | "StapleOrientation", |
4915 | "StapleWhen", |
4916 | "StapleX", |
4917 | "StapleY", |
4918 | }; |
4919 | |
4920 | /* keep sorted when changing */ |
4921 | static const char *finishing_group_whitelist[] = { |
4922 | "FPFinishing1", |
4923 | "FPFinishing2", |
4924 | "FPFinishing3", |
4925 | "FPFinishing4", |
4926 | "FinishingPage", |
4927 | "HPFinishingPanel", |
4928 | }; |
4929 | |
4930 | /* keep sorted when changing */ |
4931 | static const char *cups_option_blacklist[] = { |
4932 | "Collate", |
4933 | "Copies", |
4934 | "OutputOrder", |
4935 | "PageRegion", |
4936 | "PageSize", |
4937 | }; |
4938 | |
4939 | static char * |
4940 | get_option_text (ppd_file_t *ppd_file, |
4941 | ppd_option_t *option) |
4942 | { |
4943 | int i; |
4944 | char *utf8; |
4945 | |
4946 | for (i = 0; i < G_N_ELEMENTS (cups_option_translations)(sizeof (cups_option_translations) / sizeof ((cups_option_translations )[0])); i++) |
4947 | { |
4948 | if (strcmp (cups_option_translations[i].keyword, option->keyword) == 0) |
4949 | return g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", cups_option_translations [i].translation)) |
4950 | "printing option",g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", cups_option_translations [i].translation)) |
4951 | cups_option_translations[i].translation))g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", cups_option_translations [i].translation)); |
4952 | } |
4953 | |
4954 | utf8 = ppd_text_to_utf8 (ppd_file, option->text); |
4955 | |
4956 | /* Some ppd files have spaces in the text before the colon */ |
4957 | g_strchomp (utf8); |
4958 | |
4959 | return utf8; |
4960 | } |
4961 | |
4962 | static char * |
4963 | get_choice_text (ppd_file_t *ppd_file, |
4964 | ppd_choice_t *choice) |
4965 | { |
4966 | int i; |
4967 | ppd_option_t *option = choice->option; |
4968 | const char *keyword = option->keyword; |
4969 | |
4970 | for (i = 0; i < G_N_ELEMENTS (cups_choice_translations)(sizeof (cups_choice_translations) / sizeof ((cups_choice_translations )[0])); i++) |
4971 | { |
4972 | if (strcmp (cups_choice_translations[i].keyword, keyword) == 0 && |
4973 | strcmp (cups_choice_translations[i].choice, choice->choice) == 0) |
4974 | return g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "printing option value" , cups_choice_translations[i].translation)) |
4975 | "printing option value",g_strdup_inline (g_dpgettext2 ("ctk30", "printing option value" , cups_choice_translations[i].translation)) |
4976 | cups_choice_translations[i].translation))g_strdup_inline (g_dpgettext2 ("ctk30", "printing option value" , cups_choice_translations[i].translation)); |
4977 | } |
4978 | return ppd_text_to_utf8 (ppd_file, choice->text); |
4979 | } |
4980 | |
4981 | static gboolean |
4982 | group_has_option (ppd_group_t *group, |
4983 | ppd_option_t *option) |
4984 | { |
4985 | int i; |
4986 | |
4987 | if (group == NULL((void*)0)) |
4988 | return FALSE(0); |
4989 | |
4990 | if (group->num_options > 0 && |
4991 | option >= group->options && option < group->options + group->num_options) |
4992 | return TRUE(!(0)); |
4993 | |
4994 | for (i = 0; i < group->num_subgroups; i++) |
4995 | { |
4996 | if (group_has_option (&group->subgroups[i],option)) |
4997 | return TRUE(!(0)); |
4998 | } |
4999 | return FALSE(0); |
5000 | } |
5001 | |
5002 | static void |
5003 | set_option_off (CtkPrinterOption *option) |
5004 | { |
5005 | /* Any of these will do, _set only applies the value |
5006 | * if its allowed of the option */ |
5007 | ctk_printer_option_set (option, "False"); |
5008 | ctk_printer_option_set (option, "Off"); |
5009 | ctk_printer_option_set (option, "None"); |
5010 | } |
5011 | |
5012 | static gboolean |
5013 | value_is_off (const char *value) |
5014 | { |
5015 | return (strcasecmp (value, "None") == 0 || |
5016 | strcasecmp (value, "Off") == 0 || |
5017 | strcasecmp (value, "False") == 0); |
5018 | } |
5019 | |
5020 | static const char * |
5021 | ppd_group_name (ppd_group_t *group) |
5022 | { |
5023 | return group->name; |
5024 | } |
5025 | |
5026 | static int |
5027 | available_choices (ppd_file_t *ppd, |
5028 | ppd_option_t *option, |
5029 | ppd_choice_t ***available, |
5030 | gboolean keep_if_only_one_option) |
5031 | { |
5032 | ppd_option_t *other_option; |
5033 | int i, j; |
5034 | gchar *conflicts; |
5035 | ppd_const_t *constraint; |
5036 | const char *choice, *other_choice; |
5037 | ppd_option_t *option1, *option2; |
5038 | ppd_group_t *installed_options; |
5039 | int num_conflicts; |
5040 | gboolean all_default; |
5041 | int add_auto; |
5042 | |
5043 | if (available) |
5044 | *available = NULL((void*)0); |
5045 | |
5046 | conflicts = g_new0 (char, option->num_choices)((char *) g_malloc0_n ((option->num_choices), sizeof (char ))); |
5047 | |
5048 | installed_options = NULL((void*)0); |
5049 | for (i = 0; i < ppd->num_groups; i++) |
5050 | { |
5051 | const char *name; |
5052 | |
5053 | name = ppd_group_name (&ppd->groups[i]); |
5054 | if (strcmp (name, "InstallableOptions") == 0) |
5055 | { |
5056 | installed_options = &ppd->groups[i]; |
5057 | break; |
5058 | } |
5059 | } |
5060 | |
5061 | for (i = ppd->num_consts, constraint = ppd->consts; i > 0; i--, constraint++) |
5062 | { |
5063 | option1 = ppdFindOption (ppd, constraint->option1); |
5064 | if (option1 == NULL((void*)0)) |
5065 | continue; |
5066 | |
5067 | option2 = ppdFindOption (ppd, constraint->option2); |
5068 | if (option2 == NULL((void*)0)) |
5069 | continue; |
5070 | |
5071 | if (option == option1) |
5072 | { |
5073 | choice = constraint->choice1; |
5074 | other_option = option2; |
5075 | other_choice = constraint->choice2; |
5076 | } |
5077 | else if (option == option2) |
5078 | { |
5079 | choice = constraint->choice2; |
5080 | other_option = option1; |
5081 | other_choice = constraint->choice1; |
5082 | } |
5083 | else |
5084 | continue; |
5085 | |
5086 | /* We only care of conflicts with installed_options and PageSize */ |
5087 | if (!group_has_option (installed_options, other_option) && |
5088 | (strcmp (other_option->keyword, "PageSize") != 0)) |
5089 | continue; |
5090 | |
5091 | if (*other_choice == 0) |
5092 | { |
5093 | /* Conflict only if the installed option is not off */ |
5094 | if (value_is_off (other_option->defchoice)) |
5095 | continue; |
5096 | } |
5097 | /* Conflict if the installed option has the specified default */ |
5098 | else if (strcasecmp (other_choice, other_option->defchoice) != 0) |
5099 | continue; |
5100 | |
5101 | if (*choice == 0) |
5102 | { |
5103 | /* Conflict with all non-off choices */ |
5104 | for (j = 0; j < option->num_choices; j++) |
5105 | { |
5106 | if (!value_is_off (option->choices[j].choice)) |
5107 | conflicts[j] = 1; |
5108 | } |
5109 | } |
5110 | else |
5111 | { |
5112 | for (j = 0; j < option->num_choices; j++) |
5113 | { |
5114 | if (strcasecmp (option->choices[j].choice, choice) == 0) |
5115 | conflicts[j] = 1; |
5116 | } |
5117 | } |
5118 | } |
5119 | |
5120 | num_conflicts = 0; |
5121 | all_default = TRUE(!(0)); |
5122 | for (j = 0; j < option->num_choices; j++) |
5123 | { |
5124 | if (conflicts[j]) |
5125 | num_conflicts++; |
5126 | else if (strcmp (option->choices[j].choice, option->defchoice) != 0) |
5127 | all_default = FALSE(0); |
5128 | } |
5129 | |
5130 | if ((all_default && !keep_if_only_one_option) || |
5131 | (num_conflicts == option->num_choices)) |
5132 | { |
5133 | g_free (conflicts); |
5134 | |
5135 | return 0; |
5136 | } |
5137 | |
5138 | /* Some ppds don't have a "use printer default" option for |
5139 | * InputSlot. This means you always have to select a particular slot, |
5140 | * and you can't auto-pick source based on the paper size. To support |
5141 | * this we always add an auto option if there isn't one already. If |
5142 | * the user chooses the generated option we don't send any InputSlot |
5143 | * value when printing. The way we detect existing auto-cases is based |
5144 | * on feedback from Michael Sweet of cups fame. |
5145 | */ |
5146 | add_auto = 0; |
5147 | if (strcmp (option->keyword, "InputSlot") == 0) |
5148 | { |
5149 | gboolean found_auto = FALSE(0); |
5150 | for (j = 0; j < option->num_choices; j++) |
5151 | { |
5152 | if (!conflicts[j]) |
5153 | { |
5154 | if (strcmp (option->choices[j].choice, "Auto") == 0 || |
5155 | strcmp (option->choices[j].choice, "AutoSelect") == 0 || |
5156 | strcmp (option->choices[j].choice, "Default") == 0 || |
5157 | strcmp (option->choices[j].choice, "None") == 0 || |
5158 | strcmp (option->choices[j].choice, "PrinterDefault") == 0 || |
5159 | strcmp (option->choices[j].choice, "Unspecified") == 0 || |
5160 | option->choices[j].code == NULL((void*)0) || |
5161 | option->choices[j].code[0] == 0) |
5162 | { |
5163 | found_auto = TRUE(!(0)); |
5164 | break; |
5165 | } |
5166 | } |
5167 | } |
5168 | |
5169 | if (!found_auto) |
5170 | add_auto = 1; |
5171 | } |
5172 | |
5173 | if (available) |
5174 | { |
5175 | *available = g_new (ppd_choice_t *, option->num_choices - num_conflicts + add_auto)((ppd_choice_t * *) g_malloc_n ((option->num_choices - num_conflicts + add_auto), sizeof (ppd_choice_t *))); |
5176 | |
5177 | i = 0; |
5178 | for (j = 0; j < option->num_choices; j++) |
5179 | { |
5180 | if (!conflicts[j]) |
5181 | (*available)[i++] = &option->choices[j]; |
5182 | } |
5183 | |
5184 | if (add_auto) |
5185 | (*available)[i++] = NULL((void*)0); |
5186 | } |
5187 | |
5188 | g_free (conflicts); |
5189 | |
5190 | return option->num_choices - num_conflicts + add_auto; |
5191 | } |
5192 | |
5193 | static CtkPrinterOption * |
5194 | create_pickone_option (ppd_file_t *ppd_file, |
5195 | ppd_option_t *ppd_option, |
5196 | const gchar *ctk_name) |
5197 | { |
5198 | CtkPrinterOption *option; |
5199 | ppd_choice_t **available; |
5200 | char *label; |
5201 | int n_choices; |
5202 | int i; |
5203 | ppd_coption_t *coption; |
5204 | |
5205 | g_assert (ppd_option->ui == PPD_UI_PICKONE)do { if (ppd_option->ui == PPD_UI_PICKONE) ; else g_assertion_message_expr (((gchar*) 0), "ctkprintbackendcups.c", 5205, ((const char*) (__func__)), "ppd_option->ui == PPD_UI_PICKONE"); } while (0); |
5206 | |
5207 | option = NULL((void*)0); |
5208 | |
5209 | n_choices = available_choices (ppd_file, ppd_option, &available, g_str_has_prefix (ctk_name, "ctk-")(__builtin_constant_p ("ctk-")? __extension__ ({ const char * const __str = (ctk_name); const char * const __prefix = ("ctk-" ); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix ))); if (__str_len >= __prefix_len) __result = memcmp (((__str ) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0 ; } __result; }) : (g_str_has_prefix) (ctk_name, "ctk-") )); |
5210 | if (n_choices > 0) |
5211 | { |
5212 | |
5213 | /* right now only support one parameter per custom option |
5214 | * if more than one print warning and only offer the default choices |
5215 | */ |
5216 | |
5217 | label = get_option_text (ppd_file, ppd_option); |
5218 | |
5219 | coption = ppdFindCustomOption (ppd_file, ppd_option->keyword); |
5220 | |
5221 | if (coption) |
5222 | { |
5223 | ppd_cparam_t *cparam; |
5224 | |
5225 | cparam = ppdFirstCustomParam (coption); |
5226 | |
5227 | if (ppdNextCustomParam (coption) == NULL((void*)0)) |
5228 | { |
5229 | switch (cparam->type) |
5230 | { |
5231 | case PPD_CUSTOM_INT: |
5232 | option = ctk_printer_option_new (ctk_name, label, |
5233 | CTK_PRINTER_OPTION_TYPE_PICKONE_INT); |
5234 | break; |
5235 | case PPD_CUSTOM_PASSCODE: |
5236 | option = ctk_printer_option_new (ctk_name, label, |
5237 | CTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE); |
5238 | break; |
5239 | case PPD_CUSTOM_PASSWORD: |
5240 | option = ctk_printer_option_new (ctk_name, label, |
5241 | CTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD); |
5242 | break; |
5243 | case PPD_CUSTOM_REAL: |
5244 | option = ctk_printer_option_new (ctk_name, label, |
5245 | CTK_PRINTER_OPTION_TYPE_PICKONE_REAL); |
5246 | break; |
5247 | case PPD_CUSTOM_STRING: |
5248 | option = ctk_printer_option_new (ctk_name, label, |
5249 | CTK_PRINTER_OPTION_TYPE_PICKONE_STRING); |
5250 | break; |
5251 | #ifdef PRINT_IGNORED_OPTIONS |
5252 | case PPD_CUSTOM_POINTS: |
5253 | g_warning ("CUPS Backend: PPD Custom Points Option not supported"); |
5254 | break; |
5255 | case PPD_CUSTOM_CURVE: |
5256 | g_warning ("CUPS Backend: PPD Custom Curve Option not supported"); |
5257 | break; |
5258 | case PPD_CUSTOM_INVCURVE: |
5259 | g_warning ("CUPS Backend: PPD Custom Inverse Curve Option not supported"); |
5260 | break; |
5261 | #endif |
5262 | default: |
5263 | break; |
5264 | } |
5265 | } |
5266 | #ifdef PRINT_IGNORED_OPTIONS |
5267 | else |
5268 | g_warning ("CUPS Backend: Multi-parameter PPD Custom Option not supported"); |
5269 | #endif |
5270 | } |
5271 | |
5272 | if (!option) |
5273 | option = ctk_printer_option_new (ctk_name, label, |
5274 | CTK_PRINTER_OPTION_TYPE_PICKONE); |
5275 | g_free (label); |
5276 | |
5277 | ctk_printer_option_allocate_choices (option, n_choices); |
5278 | for (i = 0; i < n_choices; i++) |
5279 | { |
5280 | if (available[i] == NULL((void*)0)) |
5281 | { |
5282 | /* This was auto-added */ |
5283 | option->choices[i] = g_strdup ("ctk-ignore-value")g_strdup_inline ("ctk-ignore-value"); |
5284 | option->choices_display[i] = g_strdup (_("Printer Default"))g_strdup_inline (((char *) g_dgettext ("ctk30", "Printer Default" ))); |
5285 | } |
5286 | else |
5287 | { |
5288 | option->choices[i] = g_strdup (available[i]->choice)g_strdup_inline (available[i]->choice); |
5289 | option->choices_display[i] = get_choice_text (ppd_file, available[i]); |
5290 | } |
5291 | } |
5292 | |
5293 | if (option->type != CTK_PRINTER_OPTION_TYPE_PICKONE) |
5294 | { |
5295 | if (g_str_has_prefix (ppd_option->defchoice, "Custom.")(__builtin_constant_p ("Custom.")? __extension__ ({ const char * const __str = (ppd_option->defchoice); const char * const __prefix = ("Custom."); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix ) (__str, __prefix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __prefix_len = strlen ((( __prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (ppd_option->defchoice , "Custom.") )) |
5296 | ctk_printer_option_set (option, ppd_option->defchoice + 7); |
5297 | else |
5298 | ctk_printer_option_set (option, ppd_option->defchoice); |
5299 | } |
5300 | else |
5301 | { |
5302 | ctk_printer_option_set (option, ppd_option->defchoice); |
5303 | } |
5304 | } |
5305 | #ifdef PRINT_IGNORED_OPTIONS |
5306 | else |
5307 | g_warning ("CUPS Backend: Ignoring pickone %s\n", ppd_option->text); |
5308 | #endif |
5309 | g_free (available); |
5310 | |
5311 | return option; |
5312 | } |
5313 | |
5314 | static CtkPrinterOption * |
5315 | create_boolean_option (ppd_file_t *ppd_file, |
5316 | ppd_option_t *ppd_option, |
5317 | const gchar *ctk_name) |
5318 | { |
5319 | CtkPrinterOption *option; |
5320 | ppd_choice_t **available; |
5321 | char *label; |
5322 | int n_choices; |
5323 | |
5324 | g_assert (ppd_option->ui == PPD_UI_BOOLEAN)do { if (ppd_option->ui == PPD_UI_BOOLEAN) ; else g_assertion_message_expr (((gchar*) 0), "ctkprintbackendcups.c", 5324, ((const char*) (__func__)), "ppd_option->ui == PPD_UI_BOOLEAN"); } while (0); |
5325 | |
5326 | option = NULL((void*)0); |
5327 | |
5328 | n_choices = available_choices (ppd_file, ppd_option, &available, g_str_has_prefix (ctk_name, "ctk-")(__builtin_constant_p ("ctk-")? __extension__ ({ const char * const __str = (ctk_name); const char * const __prefix = ("ctk-" ); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix ))); if (__str_len >= __prefix_len) __result = memcmp (((__str ) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0 ; } __result; }) : (g_str_has_prefix) (ctk_name, "ctk-") )); |
5329 | if (n_choices == 2) |
5330 | { |
5331 | label = get_option_text (ppd_file, ppd_option); |
5332 | option = ctk_printer_option_new (ctk_name, label, |
5333 | CTK_PRINTER_OPTION_TYPE_BOOLEAN); |
5334 | g_free (label); |
5335 | |
5336 | ctk_printer_option_allocate_choices (option, 2); |
5337 | option->choices[0] = g_strdup ("True")g_strdup_inline ("True"); |
5338 | option->choices_display[0] = g_strdup ("True")g_strdup_inline ("True"); |
5339 | option->choices[1] = g_strdup ("False")g_strdup_inline ("False"); |
5340 | option->choices_display[1] = g_strdup ("False")g_strdup_inline ("False"); |
5341 | |
5342 | ctk_printer_option_set (option, ppd_option->defchoice); |
5343 | } |
5344 | #ifdef PRINT_IGNORED_OPTIONS |
5345 | else |
5346 | g_warning ("CUPS Backend: Ignoring boolean %s\n", ppd_option->text); |
5347 | #endif |
5348 | g_free (available); |
5349 | |
5350 | return option; |
5351 | } |
5352 | |
5353 | static gchar * |
5354 | get_ppd_option_name (const gchar *keyword) |
5355 | { |
5356 | int i; |
5357 | |
5358 | for (i = 0; i < G_N_ELEMENTS (ppd_option_names)(sizeof (ppd_option_names) / sizeof ((ppd_option_names)[0])); i++) |
5359 | if (strcmp (ppd_option_names[i].ppd_keyword, keyword) == 0) |
5360 | return g_strdup (ppd_option_names[i].name)g_strdup_inline (ppd_option_names[i].name); |
5361 | |
5362 | return g_strdup_printf ("cups-%s", keyword); |
5363 | } |
5364 | |
5365 | static gchar * |
5366 | get_lpoption_name (const gchar *lpoption) |
5367 | { |
5368 | int i; |
5369 | |
5370 | for (i = 0; i < G_N_ELEMENTS (ppd_option_names)(sizeof (ppd_option_names) / sizeof ((ppd_option_names)[0])); i++) |
5371 | if (strcmp (ppd_option_names[i].ppd_keyword, lpoption) == 0) |
5372 | return g_strdup (ppd_option_names[i].name)g_strdup_inline (ppd_option_names[i].name); |
5373 | |
5374 | for (i = 0; i < G_N_ELEMENTS (lpoption_names)(sizeof (lpoption_names) / sizeof ((lpoption_names)[0])); i++) |
5375 | if (strcmp (lpoption_names[i].lpoption, lpoption) == 0) |
5376 | return g_strdup (lpoption_names[i].name)g_strdup_inline (lpoption_names[i].name); |
5377 | |
5378 | return g_strdup_printf ("cups-%s", lpoption); |
5379 | } |
5380 | |
5381 | static int |
5382 | strptr_cmp (const void *a, |
5383 | const void *b) |
5384 | { |
5385 | char **aa = (char **)a; |
5386 | char **bb = (char **)b; |
5387 | return strcmp (*aa, *bb); |
5388 | } |
5389 | |
5390 | |
5391 | static gboolean |
5392 | string_in_table (const gchar *str, |
5393 | const gchar *table[], |
5394 | gint table_len) |
5395 | { |
5396 | return bsearch (&str, table, table_len, sizeof (char *), (void *)strptr_cmp) != NULL((void*)0); |
5397 | } |
5398 | |
5399 | #define STRING_IN_TABLE(_str, _table)(string_in_table (_str, _table, (sizeof (_table) / sizeof ((_table )[0])))) (string_in_table (_str, _table, G_N_ELEMENTS (_table)(sizeof (_table) / sizeof ((_table)[0])))) |
5400 | |
5401 | static void |
5402 | handle_option (CtkPrinterOptionSet *set, |
5403 | ppd_file_t *ppd_file, |
5404 | ppd_option_t *ppd_option, |
5405 | ppd_group_t *toplevel_group, |
5406 | CtkPrintSettings *settings) |
5407 | { |
5408 | CtkPrinterOption *option; |
5409 | char *option_name; |
5410 | int i; |
5411 | |
5412 | if (STRING_IN_TABLE (ppd_option->keyword, cups_option_blacklist)(string_in_table (ppd_option->keyword, cups_option_blacklist , (sizeof (cups_option_blacklist) / sizeof ((cups_option_blacklist )[0]))))) |
5413 | return; |
5414 | |
5415 | option_name = get_ppd_option_name (ppd_option->keyword); |
5416 | |
5417 | option = NULL((void*)0); |
5418 | if (ppd_option->ui == PPD_UI_PICKONE) |
5419 | option = create_pickone_option (ppd_file, ppd_option, option_name); |
5420 | else if (ppd_option->ui == PPD_UI_BOOLEAN) |
5421 | option = create_boolean_option (ppd_file, ppd_option, option_name); |
5422 | #ifdef PRINT_IGNORED_OPTIONS |
5423 | else |
5424 | g_warning ("CUPS Backend: Ignoring pickmany setting %s\n", ppd_option->text); |
5425 | #endif |
5426 | |
5427 | if (option) |
5428 | { |
5429 | const char *name; |
5430 | |
5431 | name = ppd_group_name (toplevel_group); |
5432 | if (STRING_IN_TABLE (name, color_group_whitelist)(string_in_table (name, color_group_whitelist, (sizeof (color_group_whitelist ) / sizeof ((color_group_whitelist)[0])))) || |
5433 | STRING_IN_TABLE (ppd_option->keyword, color_option_whitelist)(string_in_table (ppd_option->keyword, color_option_whitelist , (sizeof (color_option_whitelist) / sizeof ((color_option_whitelist )[0]))))) |
5434 | { |
5435 | option->group = g_strdup ("ColorPage")g_strdup_inline ("ColorPage"); |
5436 | } |
5437 | else if (STRING_IN_TABLE (name, image_quality_group_whitelist)(string_in_table (name, image_quality_group_whitelist, (sizeof (image_quality_group_whitelist) / sizeof ((image_quality_group_whitelist )[0])))) || |
5438 | STRING_IN_TABLE (ppd_option->keyword, image_quality_option_whitelist)(string_in_table (ppd_option->keyword, image_quality_option_whitelist , (sizeof (image_quality_option_whitelist) / sizeof ((image_quality_option_whitelist )[0]))))) |
5439 | { |
5440 | option->group = g_strdup ("ImageQualityPage")g_strdup_inline ("ImageQualityPage"); |
5441 | } |
5442 | else if (STRING_IN_TABLE (name, finishing_group_whitelist)(string_in_table (name, finishing_group_whitelist, (sizeof (finishing_group_whitelist ) / sizeof ((finishing_group_whitelist)[0])))) || |
5443 | STRING_IN_TABLE (ppd_option->keyword, finishing_option_whitelist)(string_in_table (ppd_option->keyword, finishing_option_whitelist , (sizeof (finishing_option_whitelist) / sizeof ((finishing_option_whitelist )[0]))))) |
5444 | { |
5445 | option->group = g_strdup ("FinishingPage")g_strdup_inline ("FinishingPage"); |
5446 | } |
5447 | else |
5448 | { |
5449 | for (i = 0; i < G_N_ELEMENTS (cups_group_translations)(sizeof (cups_group_translations) / sizeof ((cups_group_translations )[0])); i++) |
5450 | { |
5451 | if (strcmp (cups_group_translations[i].name, toplevel_group->name) == 0) |
5452 | { |
5453 | option->group = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "printing option group" , cups_group_translations[i].translation)) |
5454 | "printing option group",g_strdup_inline (g_dpgettext2 ("ctk30", "printing option group" , cups_group_translations[i].translation)) |
5455 | cups_group_translations[i].translation))g_strdup_inline (g_dpgettext2 ("ctk30", "printing option group" , cups_group_translations[i].translation)); |
5456 | break; |
5457 | } |
5458 | } |
5459 | |
5460 | if (i == G_N_ELEMENTS (cups_group_translations)(sizeof (cups_group_translations) / sizeof ((cups_group_translations )[0]))) |
5461 | option->group = g_strdup (toplevel_group->text)g_strdup_inline (toplevel_group->text); |
5462 | } |
5463 | |
5464 | set_option_from_settings (option, settings); |
5465 | |
5466 | ctk_printer_option_set_add (set, option); |
5467 | } |
5468 | |
5469 | g_free (option_name); |
5470 | } |
5471 | |
5472 | static void |
5473 | handle_group (CtkPrinterOptionSet *set, |
5474 | ppd_file_t *ppd_file, |
5475 | ppd_group_t *group, |
5476 | ppd_group_t *toplevel_group, |
5477 | CtkPrintSettings *settings) |
5478 | { |
5479 | gint i; |
5480 | const gchar *name; |
5481 | |
5482 | /* Ignore installable options */ |
5483 | name = ppd_group_name (toplevel_group); |
5484 | if (strcmp (name, "InstallableOptions") == 0) |
5485 | return; |
5486 | |
5487 | for (i = 0; i < group->num_options; i++) |
5488 | handle_option (set, ppd_file, &group->options[i], toplevel_group, settings); |
5489 | |
5490 | for (i = 0; i < group->num_subgroups; i++) |
5491 | handle_group (set, ppd_file, &group->subgroups[i], toplevel_group, settings); |
5492 | |
5493 | } |
5494 | |
5495 | #ifdef HAVE_COLORD1 |
5496 | |
5497 | typedef struct { |
5498 | CtkPrintSettings *settings; |
5499 | CtkPrinter *printer; |
5500 | } CtkPrintBackendCupsColordHelper; |
5501 | |
5502 | static void |
5503 | colord_printer_option_set_changed_cb (CtkPrinterOptionSet *set, |
5504 | CtkPrintBackendCupsColordHelper *helper) |
5505 | { |
5506 | ctk_printer_cups_update_settings (CTK_PRINTER_CUPS (helper->printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->printer)), ((ctk_printer_cups_get_type ())))) )), |
5507 | helper->settings, |
5508 | set); |
5509 | } |
5510 | #endif |
5511 | |
5512 | /* |
5513 | * Lookup translation and Ctk+ name of given IPP option name. |
5514 | */ |
5515 | static gboolean |
5516 | get_ipp_option_translation (const gchar *ipp_option_name, |
5517 | gchar **ctk_option_name, |
5518 | gchar **translation) |
5519 | { |
5520 | gint i; |
5521 | |
5522 | *ctk_option_name = NULL((void*)0); |
5523 | *translation = NULL((void*)0); |
5524 | |
5525 | for (i = 0; i < G_N_ELEMENTS (ipp_option_translations)(sizeof (ipp_option_translations) / sizeof ((ipp_option_translations )[0])); i++) |
5526 | { |
5527 | if (g_strcmp0 (ipp_option_translations[i].ipp_option_name, ipp_option_name) == 0) |
5528 | { |
5529 | *ctk_option_name = g_strdup (ipp_option_translations[i].ctk_option_name)g_strdup_inline (ipp_option_translations[i].ctk_option_name); |
5530 | *translation = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", ipp_option_translations [i].translation)) |
5531 | "printing option",g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", ipp_option_translations [i].translation)) |
5532 | ipp_option_translations[i].translation))g_strdup_inline (g_dpgettext2 ("ctk30", "printing option", ipp_option_translations [i].translation)); |
5533 | return TRUE(!(0)); |
5534 | } |
5535 | } |
5536 | |
5537 | return FALSE(0); |
5538 | } |
5539 | |
5540 | /* |
5541 | * Lookup translation of given IPP choice. |
5542 | */ |
5543 | static gchar * |
5544 | get_ipp_choice_translation (const gchar *ipp_option_name, |
5545 | const gchar *ipp_choice) |
5546 | { |
5547 | const gchar *nptr; |
5548 | guint64 index; |
5549 | gchar *translation = NULL((void*)0); |
5550 | gsize ipp_choice_length; |
5551 | gchar *endptr; |
5552 | gint i; |
5553 | |
5554 | for (i = 0; ipp_choice_translations[i].ipp_option_name != NULL((void*)0); i++) |
5555 | { |
5556 | if (g_strcmp0 (ipp_choice_translations[i].ipp_option_name, ipp_option_name) == 0) |
5557 | { |
5558 | ipp_choice_length = strlen (ipp_choice_translations[i].ipp_choice); |
5559 | |
5560 | if (g_strcmp0 (ipp_choice_translations[i].ipp_choice, ipp_choice) == 0) |
5561 | { |
5562 | translation = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", ipp_option_name, ipp_choice_translations [i].translation)) |
5563 | ipp_option_name,g_strdup_inline (g_dpgettext2 ("ctk30", ipp_option_name, ipp_choice_translations [i].translation)) |
5564 | ipp_choice_translations[i].translation))g_strdup_inline (g_dpgettext2 ("ctk30", ipp_option_name, ipp_choice_translations [i].translation)); |
5565 | break; |
5566 | } |
5567 | else if (g_str_has_suffix (ipp_choice_translations[i].ipp_choice, "-N")(__builtin_constant_p ("-N")? __extension__ ({ const char * const __str = (ipp_choice_translations[i].ipp_choice); const char * const __suffix = ("-N"); gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (ipp_choice_translations[i].ipp_choice, "-N") ) && |
5568 | g_ascii_strncasecmp (ipp_choice_translations[i].ipp_choice, |
5569 | ipp_choice, |
5570 | ipp_choice_length - 2) == 0) |
5571 | { |
5572 | /* Find out index of the ipp_choice if it is supported for the choice. */ |
5573 | endptr = NULL((void*)0); |
5574 | nptr = ipp_choice + ipp_choice_length - 1; |
5575 | index = g_ascii_strtoull (nptr, |
5576 | &endptr, |
5577 | 10); |
5578 | |
5579 | if (index != 0 || endptr != nptr) |
5580 | { |
5581 | translation = get_ipp_choice_translation_string (index, i); |
5582 | break; |
5583 | } |
5584 | } |
5585 | } |
5586 | } |
5587 | |
5588 | return translation; |
5589 | } |
5590 | |
5591 | /* |
5592 | * Format an IPP choice to a displayable string. |
5593 | */ |
5594 | static gchar * |
5595 | format_ipp_choice (const gchar *ipp_choice) |
5596 | { |
5597 | gboolean after_space = TRUE(!(0)); |
5598 | gchar *result = NULL((void*)0); |
5599 | gsize i; |
5600 | |
5601 | if (ipp_choice != NULL((void*)0)) |
5602 | { |
5603 | result = g_strdup (ipp_choice)g_strdup_inline (ipp_choice); |
5604 | /* Replace all '-' by spaces. */ |
5605 | result = g_strdelimit (result, "-", ' '); |
5606 | if (g_str_is_ascii (result)) |
5607 | { |
5608 | /* Convert all leading characters to upper case. */ |
5609 | for (i = 0; i < strlen (result); i++) |
5610 | { |
5611 | if (after_space && g_ascii_isalpha (result[i])((g_ascii_table[(guchar) (result[i])] & G_ASCII_ALPHA) != 0)) |
5612 | result[i] = g_ascii_toupper (result[i]); |
5613 | |
5614 | after_space = g_ascii_isspace (result[i])((g_ascii_table[(guchar) (result[i])] & G_ASCII_SPACE) != 0); |
5615 | } |
5616 | } |
5617 | } |
5618 | |
5619 | return result; |
5620 | } |
5621 | |
5622 | /* |
5623 | * Look the IPP option up in given set of options. |
5624 | * Create it if it doesn't exist and set its default value |
5625 | * if available. |
5626 | */ |
5627 | static CtkPrinterOption * |
5628 | setup_ipp_option (gchar *ipp_option_name, |
5629 | gchar *ipp_choice_default, |
5630 | GList *ipp_choices, |
5631 | CtkPrinterOptionSet *set) |
5632 | { |
5633 | CtkPrinterOption *option = NULL((void*)0); |
5634 | gchar *ctk_option_name = NULL((void*)0); |
5635 | gchar *translation = NULL((void*)0); |
5636 | gsize i; |
5637 | |
5638 | get_ipp_option_translation (ipp_option_name, |
5639 | &ctk_option_name, |
5640 | &translation); |
5641 | |
5642 | /* Look the option up in the given set of options. */ |
5643 | if (ctk_option_name != NULL((void*)0)) |
5644 | option = ctk_printer_option_set_lookup (set, ctk_option_name); |
5645 | |
5646 | /* The option was not found, create it from given choices. */ |
5647 | if (option == NULL((void*)0) && |
5648 | ipp_choices != NULL((void*)0)) |
5649 | { |
5650 | GList *iter; |
5651 | gsize length; |
5652 | char **choices = NULL((void*)0); |
5653 | char **choices_display = NULL((void*)0); |
5654 | |
5655 | option = ctk_printer_option_new (ctk_option_name, |
5656 | translation, |
5657 | CTK_PRINTER_OPTION_TYPE_PICKONE); |
5658 | |
5659 | length = g_list_length (ipp_choices); |
5660 | |
5661 | choices = g_new0 (char *, length)((char * *) g_malloc0_n ((length), sizeof (char *))); |
5662 | choices_display = g_new0 (char *, length)((char * *) g_malloc0_n ((length), sizeof (char *))); |
5663 | |
5664 | i = 0; |
5665 | for (iter = ipp_choices; iter != NULL((void*)0); iter = iter->next) |
5666 | { |
5667 | gchar *ipp_choice; |
5668 | |
5669 | ipp_choice = (gchar *) iter->data; |
5670 | |
5671 | choices[i] = g_strdup (ipp_choice)g_strdup_inline (ipp_choice); |
5672 | |
5673 | translation = get_ipp_choice_translation (ipp_option_name, |
5674 | ipp_choice); |
5675 | if (translation != NULL((void*)0)) |
5676 | choices_display[i] = translation; |
5677 | else |
5678 | choices_display[i] = format_ipp_choice (ipp_choice); |
5679 | |
5680 | i++; |
5681 | } |
5682 | |
5683 | if (choices != NULL((void*)0) && |
5684 | choices_display != NULL((void*)0)) |
5685 | { |
5686 | ctk_printer_option_choices_from_array (option, |
5687 | length, |
5688 | choices, |
5689 | choices_display); |
5690 | } |
5691 | |
5692 | option_set_is_ipp_option (option, TRUE(!(0))); |
5693 | |
5694 | ctk_printer_option_set_add (set, option); |
5695 | |
5696 | g_free (choices); |
5697 | g_free (choices_display); |
5698 | } |
5699 | |
5700 | /* The option exists. Set its default value if available. */ |
5701 | if (option != NULL((void*)0) && |
5702 | ipp_choice_default != NULL((void*)0)) |
5703 | { |
5704 | ctk_printer_option_set (option, ipp_choice_default); |
5705 | } |
5706 | |
5707 | return option; |
5708 | } |
5709 | |
5710 | static CtkPrinterOptionSet * |
5711 | cups_printer_get_options (CtkPrinter *printer, |
5712 | CtkPrintSettings *settings, |
5713 | CtkPageSetup *page_setup, |
5714 | CtkPrintCapabilities capabilities G_GNUC_UNUSED__attribute__ ((__unused__))) |
5715 | { |
5716 | CtkPrinterOptionSet *set; |
5717 | CtkPrinterOption *option; |
5718 | ppd_file_t *ppd_file; |
5719 | int i; |
5720 | char *print_at[] = { "now", "at", "on-hold" }; |
5721 | char *n_up[] = {"1", "2", "4", "6", "9", "16" }; |
5722 | char *prio[] = {"100", "80", "50", "30" }; |
5723 | /* Translators: These strings name the possible values of the |
5724 | * job priority option in the print dialog |
5725 | */ |
5726 | char *prio_display[] = {N_("Urgent")("Urgent"), N_("High")("High"), N_("Medium")("Medium"), N_("Low")("Low") }; |
5727 | char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" }; |
5728 | /* Translators: These strings name the possible arrangements of |
5729 | * multiple pages on a sheet when printing |
5730 | */ |
5731 | char *n_up_layout_display[] = { N_("Left to right, top to bottom")("Left to right, top to bottom"), N_("Left to right, bottom to top")("Left to right, bottom to top"), |
5732 | N_("Right to left, top to bottom")("Right to left, top to bottom"), N_("Right to left, bottom to top")("Right to left, bottom to top"), |
5733 | N_("Top to bottom, left to right")("Top to bottom, left to right"), N_("Top to bottom, right to left")("Top to bottom, right to left"), |
5734 | N_("Bottom to top, left to right")("Bottom to top, left to right"), N_("Bottom to top, right to left")("Bottom to top, right to left") }; |
5735 | char *name; |
5736 | int num_opts; |
5737 | cups_option_t *opts = NULL((void*)0); |
5738 | CtkPrintBackendCups *backend; |
5739 | CtkTextDirection text_direction; |
5740 | CtkPrinterCups *cups_printer = NULL((void*)0); |
5741 | #ifdef HAVE_COLORD1 |
5742 | CtkPrintBackendCupsColordHelper *helper; |
5743 | #endif |
5744 | char *default_number_up; |
5745 | |
5746 | set = ctk_printer_option_set_new (); |
5747 | |
5748 | /* Cups specific, non-ppd related settings */ |
5749 | |
5750 | for (i = 0; i < G_N_ELEMENTS(prio_display)(sizeof (prio_display) / sizeof ((prio_display)[0])); i++) |
5751 | prio_display[i] = _(prio_display[i])((char *) g_dgettext ("ctk30", prio_display[i])); |
5752 | |
5753 | /* Translators, this string is used to label the job priority option |
5754 | * in the print dialog |
5755 | */ |
5756 | option = ctk_printer_option_new ("ctk-job-prio", _("Job Priority")((char *) g_dgettext ("ctk30", "Job Priority")), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5757 | ctk_printer_option_choices_from_array (option, G_N_ELEMENTS (prio)(sizeof (prio) / sizeof ((prio)[0])), |
5758 | prio, prio_display); |
5759 | ctk_printer_option_set (option, "50"); |
5760 | set_option_from_settings (option, settings); |
5761 | ctk_printer_option_set_add (set, option); |
5762 | g_object_unref (option); |
5763 | |
5764 | /* Translators, this string is used to label the billing info entry |
5765 | * in the print dialog |
5766 | */ |
5767 | option = ctk_printer_option_new ("ctk-billing-info", _("Billing Info")((char *) g_dgettext ("ctk30", "Billing Info")), CTK_PRINTER_OPTION_TYPE_STRING); |
5768 | ctk_printer_option_set (option, ""); |
5769 | set_option_from_settings (option, settings); |
5770 | ctk_printer_option_set_add (set, option); |
5771 | g_object_unref (option); |
5772 | |
5773 | backend = CTK_PRINT_BACKEND_CUPS (ctk_printer_get_backend (printer))((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((ctk_printer_get_backend (printer))), ((ctk_print_backend_cups_get_type ())))))); |
5774 | cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
5775 | |
5776 | if (backend != NULL((void*)0) && printer != NULL((void*)0)) |
5777 | { |
5778 | char *cover_default[] = { |
5779 | "none", |
5780 | "classified", |
5781 | "confidential", |
5782 | "secret", |
5783 | "standard", |
5784 | "topsecret", |
5785 | "unclassified" |
5786 | }; |
5787 | /* Translators, these strings are names for various 'standard' cover |
5788 | * pages that the printing system may support. |
5789 | */ |
5790 | char *cover_display_default[] = { |
5791 | NC_("cover page", "None")("None"), |
5792 | NC_("cover page", "Classified")("Classified"), |
5793 | NC_("cover page", "Confidential")("Confidential"), |
5794 | NC_("cover page", "Secret")("Secret"), |
5795 | NC_("cover page", "Standard")("Standard"), |
5796 | NC_("cover page", "Top Secret")("Top Secret"), |
5797 | NC_("cover page", "Unclassified")("Unclassified") |
5798 | }; |
5799 | char **cover = NULL((void*)0); |
5800 | char **cover_display = NULL((void*)0); |
5801 | char **cover_display_translated = NULL((void*)0); |
5802 | gint num_of_covers = 0; |
5803 | gpointer value; |
5804 | gint j; |
5805 | |
5806 | /* Translators, this string is used to label the pages-per-sheet option |
5807 | * in the print dialog |
5808 | */ |
5809 | option = ctk_printer_option_new ("ctk-n-up", C_("printer option", "Pages per Sheet")g_dpgettext ("ctk30", "printer option" "\004" "Pages per Sheet" , strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5810 | ctk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up)(sizeof (n_up) / sizeof ((n_up)[0])), n_up, n_up); |
5811 | default_number_up = g_strdup_printf ("%d", cups_printer->default_number_up); |
5812 | ctk_printer_option_set (option, default_number_up); |
5813 | g_free (default_number_up); |
5814 | set_option_from_settings (option, settings); |
5815 | ctk_printer_option_set_add (set, option); |
5816 | g_object_unref (option); |
5817 | |
5818 | if (cups_printer_get_capabilities (printer) & CTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) |
5819 | { |
5820 | for (i = 0; i < G_N_ELEMENTS (n_up_layout_display)(sizeof (n_up_layout_display) / sizeof ((n_up_layout_display) [0])); i++) |
5821 | n_up_layout_display[i] = _(n_up_layout_display[i])((char *) g_dgettext ("ctk30", n_up_layout_display[i])); |
5822 | |
5823 | /* Translators, this string is used to label the option in the print |
5824 | * dialog that controls in what order multiple pages are arranged |
5825 | */ |
5826 | option = ctk_printer_option_new ("ctk-n-up-layout", C_("printer option", "Page Ordering")g_dpgettext ("ctk30", "printer option" "\004" "Page Ordering" , strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5827 | ctk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up_layout)(sizeof (n_up_layout) / sizeof ((n_up_layout)[0])), |
5828 | n_up_layout, n_up_layout_display); |
5829 | |
5830 | text_direction = ctk_widget_get_default_direction (); |
5831 | if (text_direction == CTK_TEXT_DIR_LTR) |
5832 | ctk_printer_option_set (option, "lrtb"); |
5833 | else |
5834 | ctk_printer_option_set (option, "rltb"); |
5835 | |
5836 | set_option_from_settings (option, settings); |
5837 | ctk_printer_option_set_add (set, option); |
5838 | g_object_unref (option); |
5839 | } |
5840 | |
5841 | num_of_covers = cups_printer->number_of_covers; |
5842 | cover = g_new (char *, num_of_covers + 1)((char * *) g_malloc_n ((num_of_covers + 1), sizeof (char *)) ); |
5843 | cover[num_of_covers] = NULL((void*)0); |
5844 | cover_display = g_new (char *, num_of_covers + 1)((char * *) g_malloc_n ((num_of_covers + 1), sizeof (char *)) ); |
5845 | cover_display[num_of_covers] = NULL((void*)0); |
5846 | cover_display_translated = g_new (char *, num_of_covers + 1)((char * *) g_malloc_n ((num_of_covers + 1), sizeof (char *)) ); |
5847 | cover_display_translated[num_of_covers] = NULL((void*)0); |
5848 | |
5849 | for (i = 0; i < num_of_covers; i++) |
5850 | { |
5851 | cover[i] = g_strdup (cups_printer->covers[i])g_strdup_inline (cups_printer->covers[i]); |
5852 | value = NULL((void*)0); |
5853 | for (j = 0; j < G_N_ELEMENTS (cover_default)(sizeof (cover_default) / sizeof ((cover_default)[0])); j++) |
5854 | if (strcmp (cover_default[j], cover[i]) == 0) |
5855 | { |
5856 | value = cover_display_default[j]; |
5857 | break; |
5858 | } |
5859 | cover_display[i] = (value != NULL((void*)0)) ? g_strdup (value)g_strdup_inline (value) : g_strdup (cups_printer->covers[i])g_strdup_inline (cups_printer->covers[i]); |
5860 | } |
5861 | |
5862 | for (i = 0; i < num_of_covers; i++) |
5863 | cover_display_translated[i] = (gchar *)g_dpgettext2 (GETTEXT_PACKAGE"ctk30", "cover page", cover_display[i]); |
5864 | |
5865 | /* Translators, this is the label used for the option in the print |
5866 | * dialog that controls the front cover page. |
5867 | */ |
5868 | option = ctk_printer_option_new ("ctk-cover-before", C_("printer option", "Before")g_dpgettext ("ctk30", "printer option" "\004" "Before", strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5869 | ctk_printer_option_choices_from_array (option, num_of_covers, |
5870 | cover, cover_display_translated); |
5871 | |
5872 | if (cups_printer->default_cover_before != NULL((void*)0)) |
5873 | ctk_printer_option_set (option, cups_printer->default_cover_before); |
5874 | else |
5875 | ctk_printer_option_set (option, "none"); |
5876 | set_option_from_settings (option, settings); |
5877 | ctk_printer_option_set_add (set, option); |
5878 | g_object_unref (option); |
5879 | |
5880 | /* Translators, this is the label used for the option in the print |
5881 | * dialog that controls the back cover page. |
5882 | */ |
5883 | option = ctk_printer_option_new ("ctk-cover-after", C_("printer option", "After")g_dpgettext ("ctk30", "printer option" "\004" "After", strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5884 | ctk_printer_option_choices_from_array (option, num_of_covers, |
5885 | cover, cover_display_translated); |
5886 | if (cups_printer->default_cover_after != NULL((void*)0)) |
5887 | ctk_printer_option_set (option, cups_printer->default_cover_after); |
5888 | else |
5889 | ctk_printer_option_set (option, "none"); |
5890 | set_option_from_settings (option, settings); |
5891 | ctk_printer_option_set_add (set, option); |
5892 | g_object_unref (option); |
5893 | |
5894 | g_strfreev (cover); |
5895 | g_strfreev (cover_display); |
5896 | g_free (cover_display_translated); |
5897 | } |
5898 | |
5899 | /* Translators: this is the name of the option that controls when |
5900 | * a print job is printed. Possible values are 'now', a specified time, |
5901 | * or 'on hold' |
5902 | */ |
5903 | option = ctk_printer_option_new ("ctk-print-time", C_("printer option", "Print at")g_dpgettext ("ctk30", "printer option" "\004" "Print at", strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_PICKONE); |
5904 | ctk_printer_option_choices_from_array (option, G_N_ELEMENTS (print_at)(sizeof (print_at) / sizeof ((print_at)[0])), |
5905 | print_at, print_at); |
5906 | ctk_printer_option_set (option, "now"); |
5907 | set_option_from_settings (option, settings); |
5908 | ctk_printer_option_set_add (set, option); |
5909 | g_object_unref (option); |
5910 | |
5911 | /* Translators: this is the name of the option that allows the user |
5912 | * to specify a time when a print job will be printed. |
5913 | */ |
5914 | option = ctk_printer_option_new ("ctk-print-time-text", C_("printer option", "Print at time")g_dpgettext ("ctk30", "printer option" "\004" "Print at time" , strlen ("printer option") + 1), CTK_PRINTER_OPTION_TYPE_STRING); |
5915 | ctk_printer_option_set (option, ""); |
5916 | set_option_from_settings (option, settings); |
5917 | ctk_printer_option_set_add (set, option); |
5918 | g_object_unref (option); |
5919 | |
5920 | /* Printer (ppd) specific settings */ |
5921 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
5922 | if (ppd_file) |
5923 | { |
5924 | CtkPaperSize *paper_size; |
5925 | ppd_option_t *ppd_option; |
5926 | |
5927 | ppdMarkDefaults (ppd_file); |
5928 | |
5929 | paper_size = ctk_page_setup_get_paper_size (page_setup); |
5930 | |
5931 | ppd_option = ppdFindOption (ppd_file, "PageSize"); |
5932 | if (ppd_option) |
5933 | { |
5934 | const gchar *ppd_name; |
5935 | |
5936 | ppd_name = ctk_paper_size_get_ppd_name (paper_size); |
5937 | |
5938 | if (ppd_name) |
5939 | { |
5940 | strncpy (ppd_option->defchoice, ppd_name, PPD_MAX_NAME41 - 1); |
5941 | ppd_option->defchoice[PPD_MAX_NAME41 - 1] = '\0'; |
5942 | } |
5943 | else |
5944 | { |
5945 | gchar *custom_name; |
5946 | char width[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)]; |
5947 | char height[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)]; |
5948 | |
5949 | g_ascii_formatd (width, sizeof (width), "%.2f", |
5950 | ctk_paper_size_get_width (paper_size, |
5951 | CTK_UNIT_POINTS)); |
5952 | g_ascii_formatd (height, sizeof (height), "%.2f", |
5953 | ctk_paper_size_get_height (paper_size, |
5954 | CTK_UNIT_POINTS)); |
5955 | /* Translators: this format is used to display a custom |
5956 | * paper size. The two placeholders are replaced with |
5957 | * the width and height in points. E.g: "Custom |
5958 | * 230.4x142.9" |
5959 | */ |
5960 | custom_name = g_strdup_printf (_("Custom %s×%s")((char *) g_dgettext ("ctk30", "Custom %s×%s")), width, height); |
5961 | strncpy (ppd_option->defchoice, custom_name, PPD_MAX_NAME41 - 1); |
5962 | ppd_option->defchoice[PPD_MAX_NAME41 - 1] = '\0'; |
5963 | g_free (custom_name); |
5964 | } |
5965 | } |
5966 | |
5967 | for (i = 0; i < ppd_file->num_groups; i++) |
5968 | handle_group (set, ppd_file, &ppd_file->groups[i], &ppd_file->groups[i], settings); |
5969 | } |
5970 | else |
5971 | { |
5972 | /* Try IPP options */ |
5973 | |
5974 | option = setup_ipp_option ("sides", |
5975 | cups_printer->sides_default, |
5976 | cups_printer->sides_supported, |
5977 | set); |
5978 | |
5979 | if (option != NULL((void*)0)) |
5980 | set_option_from_settings (option, settings); |
5981 | |
5982 | option = setup_ipp_option ("output-bin", |
5983 | cups_printer->output_bin_default, |
5984 | cups_printer->output_bin_supported, |
5985 | set); |
5986 | |
5987 | if (option != NULL((void*)0)) |
5988 | set_option_from_settings (option, settings); |
5989 | } |
5990 | |
5991 | /* Now honor the user set defaults for this printer */ |
5992 | num_opts = cups_get_user_options (ctk_printer_get_name (printer), 0, &opts); |
5993 | |
5994 | for (i = 0; i < num_opts; i++) |
5995 | { |
5996 | if (STRING_IN_TABLE (opts[i].name, cups_option_blacklist)(string_in_table (opts[i].name, cups_option_blacklist, (sizeof (cups_option_blacklist) / sizeof ((cups_option_blacklist)[0] ))))) |
5997 | continue; |
5998 | |
5999 | name = get_lpoption_name (opts[i].name); |
6000 | if (strcmp (name, "cups-job-sheets") == 0) |
6001 | { |
6002 | gchar **values; |
6003 | gint num_values; |
6004 | |
6005 | values = g_strsplit (opts[i].value, ",", 2); |
6006 | num_values = g_strv_length (values); |
6007 | |
6008 | option = ctk_printer_option_set_lookup (set, "ctk-cover-before"); |
6009 | if (option && num_values > 0) |
6010 | ctk_printer_option_set (option, g_strstrip (values[0])g_strchomp (g_strchug (values[0]))); |
6011 | |
6012 | option = ctk_printer_option_set_lookup (set, "ctk-cover-after"); |
6013 | if (option && num_values > 1) |
6014 | ctk_printer_option_set (option, g_strstrip (values[1])g_strchomp (g_strchug (values[1]))); |
6015 | |
6016 | g_strfreev (values); |
6017 | } |
6018 | else if (strcmp (name, "cups-job-hold-until") == 0) |
6019 | { |
6020 | CtkPrinterOption *option2 = NULL((void*)0); |
6021 | |
6022 | option = ctk_printer_option_set_lookup (set, "ctk-print-time-text"); |
6023 | if (option && opts[i].value) |
6024 | { |
6025 | option2 = ctk_printer_option_set_lookup (set, "ctk-print-time"); |
6026 | if (option2) |
6027 | { |
6028 | if (strcmp (opts[i].value, "indefinite") == 0) |
6029 | ctk_printer_option_set (option2, "on-hold"); |
6030 | else |
6031 | { |
6032 | ctk_printer_option_set (option2, "at"); |
6033 | ctk_printer_option_set (option, opts[i].value); |
6034 | } |
6035 | } |
6036 | } |
6037 | } |
6038 | else if (strcmp (name, "cups-sides") == 0) |
6039 | { |
6040 | option = ctk_printer_option_set_lookup (set, "ctk-duplex"); |
6041 | if (option && opts[i].value) |
6042 | { |
6043 | if (!option_is_ipp_option (option)) |
6044 | { |
6045 | if (strcmp (opts[i].value, "two-sided-short-edge") == 0) |
6046 | ctk_printer_option_set (option, "DuplexTumble"); |
6047 | else if (strcmp (opts[i].value, "two-sided-long-edge") == 0) |
6048 | ctk_printer_option_set (option, "DuplexNoTumble"); |
6049 | } |
6050 | else |
6051 | { |
6052 | ctk_printer_option_set (option, opts[i].value); |
6053 | } |
6054 | } |
6055 | } |
6056 | else |
6057 | { |
6058 | option = ctk_printer_option_set_lookup (set, name); |
6059 | if (option) |
6060 | ctk_printer_option_set (option, opts[i].value); |
6061 | } |
6062 | g_free (name); |
6063 | } |
6064 | |
6065 | cupsFreeOptions (num_opts, opts); |
6066 | |
6067 | #ifdef HAVE_COLORD1 |
6068 | /* TRANSLATORS: this this the ICC color profile to use for this job */ |
6069 | option = ctk_printer_option_new ("colord-profile", |
6070 | C_("printer option", "Printer Profile")g_dpgettext ("ctk30", "printer option" "\004" "Printer Profile" , strlen ("printer option") + 1), |
6071 | CTK_PRINTER_OPTION_TYPE_INFO); |
6072 | |
6073 | /* assign it to the color page */ |
6074 | option->group = g_strdup ("ColorPage")g_strdup_inline ("ColorPage"); |
6075 | |
6076 | /* TRANSLATORS: this is when color profile information is unavailable */ |
6077 | ctk_printer_option_set (option, C_("printer option value", "Unavailable")g_dpgettext ("ctk30", "printer option value" "\004" "Unavailable" , strlen ("printer option value") + 1)); |
6078 | ctk_printer_option_set_add (set, option); |
6079 | |
6080 | /* watch to see if the user changed the options */ |
6081 | helper = g_new (CtkPrintBackendCupsColordHelper, 1)((CtkPrintBackendCupsColordHelper *) g_malloc_n ((1), sizeof ( CtkPrintBackendCupsColordHelper))); |
6082 | helper->printer = printer; |
6083 | helper->settings = settings; |
6084 | g_signal_connect_data (set, "changed", |
6085 | G_CALLBACK (colord_printer_option_set_changed_cb)((GCallback) (colord_printer_option_set_changed_cb)), |
6086 | helper, |
6087 | (GClosureNotify) g_free, |
6088 | 0); |
6089 | |
6090 | /* initial coldplug */ |
6091 | ctk_printer_cups_update_settings (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))), |
6092 | settings, set); |
6093 | g_object_bind_property (printer, "profile-title", |
6094 | option, "value", |
6095 | G_BINDING_DEFAULT); |
6096 | |
6097 | #endif |
6098 | |
6099 | return set; |
6100 | } |
6101 | |
6102 | |
6103 | static void |
6104 | mark_option_from_set (CtkPrinterOptionSet *set, |
6105 | ppd_file_t *ppd_file, |
6106 | ppd_option_t *ppd_option) |
6107 | { |
6108 | CtkPrinterOption *option; |
6109 | char *name = get_ppd_option_name (ppd_option->keyword); |
6110 | |
6111 | option = ctk_printer_option_set_lookup (set, name); |
6112 | |
6113 | if (option) |
6114 | ppdMarkOption (ppd_file, ppd_option->keyword, option->value); |
6115 | |
6116 | g_free (name); |
6117 | } |
6118 | |
6119 | |
6120 | static void |
6121 | mark_group_from_set (CtkPrinterOptionSet *set, |
6122 | ppd_file_t *ppd_file, |
6123 | ppd_group_t *group) |
6124 | { |
6125 | int i; |
6126 | |
6127 | for (i = 0; i < group->num_options; i++) |
6128 | mark_option_from_set (set, ppd_file, &group->options[i]); |
6129 | |
6130 | for (i = 0; i < group->num_subgroups; i++) |
6131 | mark_group_from_set (set, ppd_file, &group->subgroups[i]); |
6132 | } |
6133 | |
6134 | static void |
6135 | set_conflicts_from_option (CtkPrinterOptionSet *set, |
6136 | ppd_file_t *ppd_file G_GNUC_UNUSED__attribute__ ((__unused__)), |
6137 | ppd_option_t *ppd_option) |
6138 | { |
6139 | CtkPrinterOption *option; |
6140 | char *name; |
6141 | |
6142 | if (ppd_option->conflicted) |
6143 | { |
6144 | name = get_ppd_option_name (ppd_option->keyword); |
6145 | option = ctk_printer_option_set_lookup (set, name); |
6146 | |
6147 | if (option) |
6148 | ctk_printer_option_set_has_conflict (option, TRUE(!(0))); |
6149 | #ifdef PRINT_IGNORED_OPTIONS |
6150 | else |
6151 | g_warning ("CUPS Backend: Ignoring conflict for option %s", ppd_option->keyword); |
6152 | #endif |
6153 | |
6154 | g_free (name); |
6155 | } |
6156 | } |
6157 | |
6158 | static void |
6159 | set_conflicts_from_group (CtkPrinterOptionSet *set, |
6160 | ppd_file_t *ppd_file, |
6161 | ppd_group_t *group) |
6162 | { |
6163 | int i; |
6164 | |
6165 | for (i = 0; i < group->num_options; i++) |
6166 | set_conflicts_from_option (set, ppd_file, &group->options[i]); |
6167 | |
6168 | for (i = 0; i < group->num_subgroups; i++) |
6169 | set_conflicts_from_group (set, ppd_file, &group->subgroups[i]); |
6170 | } |
6171 | |
6172 | static gboolean |
6173 | cups_printer_mark_conflicts (CtkPrinter *printer, |
6174 | CtkPrinterOptionSet *options) |
6175 | { |
6176 | ppd_file_t *ppd_file; |
6177 | int num_conflicts; |
6178 | int i; |
6179 | |
6180 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
6181 | |
6182 | if (ppd_file == NULL((void*)0)) |
6183 | return FALSE(0); |
6184 | |
6185 | ppdMarkDefaults (ppd_file); |
6186 | |
6187 | for (i = 0; i < ppd_file->num_groups; i++) |
6188 | mark_group_from_set (options, ppd_file, &ppd_file->groups[i]); |
6189 | |
6190 | num_conflicts = ppdConflicts (ppd_file); |
6191 | |
6192 | if (num_conflicts > 0) |
6193 | { |
6194 | for (i = 0; i < ppd_file->num_groups; i++) |
6195 | set_conflicts_from_group (options, ppd_file, &ppd_file->groups[i]); |
6196 | } |
6197 | |
6198 | return num_conflicts > 0; |
6199 | } |
6200 | |
6201 | struct OptionData { |
6202 | CtkPrinter *printer; |
6203 | CtkPrinterOptionSet *options; |
6204 | CtkPrintSettings *settings; |
6205 | ppd_file_t *ppd_file; |
6206 | }; |
6207 | |
6208 | typedef struct { |
6209 | const char *cups; |
6210 | const char *standard; |
6211 | } NameMapping; |
6212 | |
6213 | static void |
6214 | map_settings_to_option (CtkPrinterOption *option, |
6215 | const NameMapping table[], |
6216 | gint n_elements, |
6217 | CtkPrintSettings *settings, |
6218 | const gchar *standard_name, |
6219 | const gchar *cups_name, |
6220 | const gchar *ipp_name) |
6221 | { |
6222 | int i; |
6223 | char *name; |
6224 | const char *cups_value; |
6225 | const char *ipp_value; |
6226 | const char *standard_value; |
6227 | |
6228 | /* If the cups-specific setting is set, always use that */ |
6229 | name = g_strdup_printf ("cups-%s", cups_name); |
6230 | cups_value = ctk_print_settings_get (settings, name); |
6231 | g_free (name); |
6232 | |
6233 | if (cups_value != NULL((void*)0)) |
6234 | { |
6235 | ctk_printer_option_set (option, cups_value); |
6236 | return; |
6237 | } |
6238 | |
6239 | /* If the IPP-specific setting is set, use that */ |
6240 | name = g_strdup_printf ("cups-%s", ipp_name); |
6241 | ipp_value = ctk_print_settings_get (settings, name); |
6242 | g_free (name); |
6243 | |
6244 | if (ipp_value != NULL((void*)0)) |
6245 | { |
6246 | ctk_printer_option_set (option, ipp_value); |
6247 | return; |
6248 | } |
6249 | |
6250 | /* Otherwise we try to convert from the general setting */ |
6251 | standard_value = ctk_print_settings_get (settings, standard_name); |
6252 | if (standard_value == NULL((void*)0)) |
6253 | return; |
6254 | |
6255 | for (i = 0; i < n_elements; i++) |
6256 | { |
6257 | if (table[i].cups == NULL((void*)0) && table[i].standard == NULL((void*)0)) |
6258 | { |
6259 | ctk_printer_option_set (option, standard_value); |
6260 | break; |
6261 | } |
6262 | else if (table[i].cups == NULL((void*)0) && |
6263 | strcmp (table[i].standard, standard_value) == 0) |
6264 | { |
6265 | set_option_off (option); |
6266 | break; |
6267 | } |
6268 | else if (strcmp (table[i].standard, standard_value) == 0) |
6269 | { |
6270 | ctk_printer_option_set (option, table[i].cups); |
6271 | break; |
6272 | } |
6273 | } |
6274 | } |
6275 | |
6276 | static void |
6277 | map_option_to_settings (const gchar *value, |
6278 | const NameMapping table[], |
6279 | gint n_elements, |
6280 | CtkPrintSettings *settings, |
6281 | const gchar *standard_name, |
6282 | const gchar *cups_name, |
6283 | const gchar *ipp_name, |
6284 | gboolean is_ipp_option) |
6285 | { |
6286 | int i; |
6287 | char *name; |
6288 | |
6289 | for (i = 0; i < n_elements; i++) |
6290 | { |
6291 | if (table[i].cups == NULL((void*)0) && table[i].standard == NULL((void*)0)) |
6292 | { |
6293 | ctk_print_settings_set (settings, |
6294 | standard_name, |
6295 | value); |
6296 | break; |
6297 | } |
6298 | else if (table[i].cups == NULL((void*)0) && table[i].standard != NULL((void*)0)) |
6299 | { |
6300 | if (value_is_off (value)) |
6301 | { |
6302 | ctk_print_settings_set (settings, |
6303 | standard_name, |
6304 | table[i].standard); |
6305 | break; |
6306 | } |
6307 | } |
6308 | else if (strcmp (table[i].cups, value) == 0) |
6309 | { |
6310 | ctk_print_settings_set (settings, |
6311 | standard_name, |
6312 | table[i].standard); |
6313 | break; |
6314 | } |
6315 | } |
6316 | |
6317 | /* Always set the corresponding cups-specific setting */ |
6318 | if (is_ipp_option) |
6319 | name = g_strdup_printf ("cups-%s", ipp_name); |
6320 | else |
6321 | name = g_strdup_printf ("cups-%s", cups_name); |
6322 | |
6323 | ctk_print_settings_set (settings, name, value); |
6324 | |
6325 | g_free (name); |
6326 | } |
6327 | |
6328 | |
6329 | static const NameMapping paper_source_map[] = { |
6330 | { "Lower", "lower"}, |
6331 | { "Middle", "middle"}, |
6332 | { "Upper", "upper"}, |
6333 | { "Rear", "rear"}, |
6334 | { "Envelope", "envelope"}, |
6335 | { "Cassette", "cassette"}, |
6336 | { "LargeCapacity", "large-capacity"}, |
6337 | { "AnySmallFormat", "small-format"}, |
6338 | { "AnyLargeFormat", "large-format"}, |
6339 | { NULL((void*)0), NULL((void*)0)} |
6340 | }; |
6341 | |
6342 | static const NameMapping output_tray_map[] = { |
6343 | { "Upper", "upper"}, |
6344 | { "Lower", "lower"}, |
6345 | { "Rear", "rear"}, |
6346 | { NULL((void*)0), NULL((void*)0)} |
6347 | }; |
6348 | |
6349 | static const NameMapping duplex_map[] = { |
6350 | { "DuplexTumble", "vertical" }, |
6351 | { "DuplexNoTumble", "horizontal" }, |
6352 | { NULL((void*)0), "simplex" } |
6353 | }; |
6354 | |
6355 | static const NameMapping output_mode_map[] = { |
6356 | { "Standard", "normal" }, |
6357 | { "Normal", "normal" }, |
6358 | { "Draft", "draft" }, |
6359 | { "Fast", "draft" }, |
6360 | }; |
6361 | |
6362 | static const NameMapping media_type_map[] = { |
6363 | { "Transparency", "transparency"}, |
6364 | { "Standard", "stationery"}, |
6365 | { NULL((void*)0), NULL((void*)0)} |
6366 | }; |
6367 | |
6368 | static const NameMapping all_map[] = { |
6369 | { NULL((void*)0), NULL((void*)0)} |
6370 | }; |
6371 | |
6372 | |
6373 | static void |
6374 | set_option_from_settings (CtkPrinterOption *option, |
6375 | CtkPrintSettings *settings) |
6376 | { |
6377 | const char *cups_value; |
6378 | char *value; |
6379 | |
6380 | if (settings == NULL((void*)0)) |
6381 | return; |
6382 | |
6383 | if (strcmp (option->name, "ctk-paper-source") == 0) |
6384 | map_settings_to_option (option, paper_source_map, G_N_ELEMENTS (paper_source_map)(sizeof (paper_source_map) / sizeof ((paper_source_map)[0])), |
6385 | settings, CTK_PRINT_SETTINGS_DEFAULT_SOURCE"default-source", |
6386 | "InputSlot", NULL((void*)0)); |
6387 | else if (strcmp (option->name, "ctk-output-tray") == 0) |
6388 | map_settings_to_option (option, output_tray_map, G_N_ELEMENTS (output_tray_map)(sizeof (output_tray_map) / sizeof ((output_tray_map)[0])), |
6389 | settings, CTK_PRINT_SETTINGS_OUTPUT_BIN"output-bin", |
6390 | "OutputBin", "output-bin"); |
6391 | else if (strcmp (option->name, "ctk-duplex") == 0) |
6392 | map_settings_to_option (option, duplex_map, G_N_ELEMENTS (duplex_map)(sizeof (duplex_map) / sizeof ((duplex_map)[0])), |
6393 | settings, CTK_PRINT_SETTINGS_DUPLEX"duplex", |
6394 | "Duplex", "sides"); |
6395 | else if (strcmp (option->name, "cups-OutputMode") == 0) |
6396 | map_settings_to_option (option, output_mode_map, G_N_ELEMENTS (output_mode_map)(sizeof (output_mode_map) / sizeof ((output_mode_map)[0])), |
6397 | settings, CTK_PRINT_SETTINGS_QUALITY"quality", |
6398 | "OutputMode", NULL((void*)0)); |
6399 | else if (strcmp (option->name, "cups-Resolution") == 0) |
6400 | { |
6401 | cups_value = ctk_print_settings_get (settings, option->name); |
6402 | if (cups_value) |
6403 | ctk_printer_option_set (option, cups_value); |
6404 | else |
6405 | { |
6406 | if (ctk_print_settings_get_int_with_default (settings, CTK_PRINT_SETTINGS_RESOLUTION"resolution", -1) != -1 || |
6407 | ctk_print_settings_get_int_with_default (settings, CTK_PRINT_SETTINGS_RESOLUTION_X"resolution-x", -1) != -1 || |
6408 | ctk_print_settings_get_int_with_default (settings, CTK_PRINT_SETTINGS_RESOLUTION_Y"resolution-y", -1) != -1 || |
6409 | option->value == NULL((void*)0) || option->value[0] == '\0') |
6410 | { |
6411 | int res = ctk_print_settings_get_resolution (settings); |
6412 | int res_x = ctk_print_settings_get_resolution_x (settings); |
6413 | int res_y = ctk_print_settings_get_resolution_y (settings); |
6414 | |
6415 | if (res_x != res_y) |
6416 | { |
6417 | value = g_strdup_printf ("%dx%ddpi", res_x, res_y); |
6418 | ctk_printer_option_set (option, value); |
6419 | g_free (value); |
6420 | } |
6421 | else if (res != 0) |
6422 | { |
6423 | value = g_strdup_printf ("%ddpi", res); |
6424 | ctk_printer_option_set (option, value); |
6425 | g_free (value); |
6426 | } |
6427 | } |
6428 | } |
6429 | } |
6430 | else if (strcmp (option->name, "ctk-paper-type") == 0) |
6431 | map_settings_to_option (option, media_type_map, G_N_ELEMENTS (media_type_map)(sizeof (media_type_map) / sizeof ((media_type_map)[0])), |
6432 | settings, CTK_PRINT_SETTINGS_MEDIA_TYPE"media-type", |
6433 | "MediaType", NULL((void*)0)); |
6434 | else if (strcmp (option->name, "ctk-n-up") == 0) |
6435 | { |
6436 | map_settings_to_option (option, all_map, G_N_ELEMENTS (all_map)(sizeof (all_map) / sizeof ((all_map)[0])), |
6437 | settings, CTK_PRINT_SETTINGS_NUMBER_UP"number-up", |
6438 | "number-up", NULL((void*)0)); |
6439 | } |
6440 | else if (strcmp (option->name, "ctk-n-up-layout") == 0) |
6441 | { |
6442 | map_settings_to_option (option, all_map, G_N_ELEMENTS (all_map)(sizeof (all_map) / sizeof ((all_map)[0])), |
6443 | settings, CTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT"number-up-layout", |
6444 | "number-up-layout", NULL((void*)0)); |
6445 | } |
6446 | else if (strcmp (option->name, "ctk-billing-info") == 0) |
6447 | { |
6448 | cups_value = ctk_print_settings_get (settings, "cups-job-billing"); |
6449 | if (cups_value) |
6450 | ctk_printer_option_set (option, cups_value); |
6451 | } |
6452 | else if (strcmp (option->name, "ctk-job-prio") == 0) |
6453 | { |
6454 | cups_value = ctk_print_settings_get (settings, "cups-job-priority"); |
6455 | if (cups_value) |
6456 | ctk_printer_option_set (option, cups_value); |
6457 | } |
6458 | else if (strcmp (option->name, "ctk-cover-before") == 0) |
6459 | { |
6460 | cups_value = ctk_print_settings_get (settings, "cover-before"); |
6461 | if (cups_value) |
6462 | ctk_printer_option_set (option, cups_value); |
6463 | } |
6464 | else if (strcmp (option->name, "ctk-cover-after") == 0) |
6465 | { |
6466 | cups_value = ctk_print_settings_get (settings, "cover-after"); |
6467 | if (cups_value) |
6468 | ctk_printer_option_set (option, cups_value); |
6469 | } |
6470 | else if (strcmp (option->name, "ctk-print-time") == 0) |
6471 | { |
6472 | cups_value = ctk_print_settings_get (settings, "print-at"); |
6473 | if (cups_value) |
6474 | ctk_printer_option_set (option, cups_value); |
6475 | } |
6476 | else if (strcmp (option->name, "ctk-print-time-text") == 0) |
6477 | { |
6478 | cups_value = ctk_print_settings_get (settings, "print-at-time"); |
6479 | if (cups_value) |
6480 | ctk_printer_option_set (option, cups_value); |
6481 | } |
6482 | else if (g_str_has_prefix (option->name, "cups-")(__builtin_constant_p ("cups-")? __extension__ ({ const char * const __str = (option->name); const char * const __prefix = ("cups-"); gboolean __result = (0); if (__str == ((void*)0 ) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str , __prefix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix ) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (option->name, "cups-") )) |
6483 | { |
6484 | cups_value = ctk_print_settings_get (settings, option->name); |
6485 | if (cups_value) |
6486 | ctk_printer_option_set (option, cups_value); |
6487 | } |
6488 | } |
6489 | |
6490 | static void |
6491 | foreach_option_get_settings (CtkPrinterOption *option, |
6492 | gpointer user_data) |
6493 | { |
6494 | struct OptionData *data = user_data; |
6495 | CtkPrintSettings *settings = data->settings; |
6496 | const char *value; |
6497 | |
6498 | value = option->value; |
6499 | |
6500 | if (strcmp (option->name, "ctk-paper-source") == 0) |
6501 | map_option_to_settings (value, paper_source_map, G_N_ELEMENTS (paper_source_map)(sizeof (paper_source_map) / sizeof ((paper_source_map)[0])), |
6502 | settings, CTK_PRINT_SETTINGS_DEFAULT_SOURCE"default-source", |
6503 | "InputSlot", NULL((void*)0), FALSE(0)); |
6504 | else if (strcmp (option->name, "ctk-output-tray") == 0) |
6505 | map_option_to_settings (value, output_tray_map, G_N_ELEMENTS (output_tray_map)(sizeof (output_tray_map) / sizeof ((output_tray_map)[0])), |
6506 | settings, CTK_PRINT_SETTINGS_OUTPUT_BIN"output-bin", |
6507 | "OutputBin", "output-bin", option_is_ipp_option (option)); |
6508 | else if (strcmp (option->name, "ctk-duplex") == 0) |
6509 | map_option_to_settings (value, duplex_map, G_N_ELEMENTS (duplex_map)(sizeof (duplex_map) / sizeof ((duplex_map)[0])), |
6510 | settings, CTK_PRINT_SETTINGS_DUPLEX"duplex", |
6511 | "Duplex", "sides", option_is_ipp_option (option)); |
6512 | else if (strcmp (option->name, "cups-OutputMode") == 0) |
6513 | map_option_to_settings (value, output_mode_map, G_N_ELEMENTS (output_mode_map)(sizeof (output_mode_map) / sizeof ((output_mode_map)[0])), |
6514 | settings, CTK_PRINT_SETTINGS_QUALITY"quality", |
6515 | "OutputMode", NULL((void*)0), FALSE(0)); |
6516 | else if (strcmp (option->name, "cups-Resolution") == 0) |
6517 | { |
6518 | int res, res_x, res_y; |
6519 | |
6520 | if (sscanf (value, "%dx%ddpi", &res_x, &res_y) == 2) |
6521 | { |
6522 | if (res_x > 0 && res_y > 0) |
6523 | ctk_print_settings_set_resolution_xy (settings, res_x, res_y); |
6524 | } |
6525 | else if (sscanf (value, "%ddpi", &res) == 1) |
6526 | { |
6527 | if (res > 0) |
6528 | ctk_print_settings_set_resolution (settings, res); |
6529 | } |
6530 | |
6531 | ctk_print_settings_set (settings, option->name, value); |
6532 | } |
6533 | else if (strcmp (option->name, "ctk-paper-type") == 0) |
6534 | map_option_to_settings (value, media_type_map, G_N_ELEMENTS (media_type_map)(sizeof (media_type_map) / sizeof ((media_type_map)[0])), |
6535 | settings, CTK_PRINT_SETTINGS_MEDIA_TYPE"media-type", |
6536 | "MediaType", NULL((void*)0), FALSE(0)); |
6537 | else if (strcmp (option->name, "ctk-n-up") == 0) |
6538 | map_option_to_settings (value, all_map, G_N_ELEMENTS (all_map)(sizeof (all_map) / sizeof ((all_map)[0])), |
6539 | settings, CTK_PRINT_SETTINGS_NUMBER_UP"number-up", |
6540 | "number-up", NULL((void*)0), FALSE(0)); |
6541 | else if (strcmp (option->name, "ctk-n-up-layout") == 0) |
6542 | map_option_to_settings (value, all_map, G_N_ELEMENTS (all_map)(sizeof (all_map) / sizeof ((all_map)[0])), |
6543 | settings, CTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT"number-up-layout", |
6544 | "number-up-layout", NULL((void*)0), FALSE(0)); |
6545 | else if (strcmp (option->name, "ctk-billing-info") == 0 && strlen (value) > 0) |
6546 | ctk_print_settings_set (settings, "cups-job-billing", value); |
6547 | else if (strcmp (option->name, "ctk-job-prio") == 0) |
6548 | ctk_print_settings_set (settings, "cups-job-priority", value); |
6549 | else if (strcmp (option->name, "ctk-cover-before") == 0) |
6550 | ctk_print_settings_set (settings, "cover-before", value); |
6551 | else if (strcmp (option->name, "ctk-cover-after") == 0) |
6552 | ctk_print_settings_set (settings, "cover-after", value); |
6553 | else if (strcmp (option->name, "ctk-print-time") == 0) |
6554 | ctk_print_settings_set (settings, "print-at", value); |
6555 | else if (strcmp (option->name, "ctk-print-time-text") == 0) |
6556 | ctk_print_settings_set (settings, "print-at-time", value); |
6557 | else if (g_str_has_prefix (option->name, "cups-")(__builtin_constant_p ("cups-")? __extension__ ({ const char * const __str = (option->name); const char * const __prefix = ("cups-"); gboolean __result = (0); if (__str == ((void*)0 ) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str , __prefix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix ) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (option->name, "cups-") )) |
6558 | ctk_print_settings_set (settings, option->name, value); |
6559 | } |
6560 | |
6561 | static gboolean |
6562 | supports_am_pm (void) |
6563 | { |
6564 | struct tm tmp_tm = { 0 }; |
6565 | char time[8]; |
6566 | int length; |
6567 | |
6568 | length = strftime (time, sizeof (time), "%p", &tmp_tm); |
6569 | |
6570 | return length != 0; |
6571 | } |
6572 | |
6573 | /* Converts local time to UTC time. Local time has to be in one of these |
6574 | * formats: HH:MM:SS, HH:MM, HH:MM:SS {am, pm}, HH:MM {am, pm}, HH {am, pm}, |
6575 | * {am, pm} HH:MM:SS, {am, pm} HH:MM, {am, pm} HH. |
6576 | * Returns a newly allocated string holding UTC time in HH:MM:SS format |
6577 | * or NULL. |
6578 | */ |
6579 | gchar * |
6580 | localtime_to_utctime (const char *local_time) |
6581 | { |
6582 | const char *formats_0[] = {" %I : %M : %S %p ", " %p %I : %M : %S ", |
6583 | " %H : %M : %S ", |
6584 | " %I : %M %p ", " %p %I : %M ", |
6585 | " %H : %M ", |
6586 | " %I %p ", " %p %I "}; |
6587 | const char *formats_1[] = {" %H : %M : %S ", " %H : %M "}; |
6588 | const char *end = NULL((void*)0); |
6589 | struct tm *actual_utc_time; |
6590 | struct tm local_print_time; |
6591 | gchar *utc_time = NULL((void*)0); |
6592 | int i, n; |
6593 | |
6594 | if (local_time == NULL((void*)0) || local_time[0] == '\0') |
6595 | return NULL((void*)0); |
6596 | |
6597 | n = supports_am_pm () ? G_N_ELEMENTS (formats_0)(sizeof (formats_0) / sizeof ((formats_0)[0])) : G_N_ELEMENTS (formats_1)(sizeof (formats_1) / sizeof ((formats_1)[0])); |
6598 | |
6599 | for (i = 0; i < n; i++) |
6600 | { |
6601 | local_print_time.tm_hour = 0; |
6602 | local_print_time.tm_min = 0; |
6603 | local_print_time.tm_sec = 0; |
6604 | |
6605 | if (supports_am_pm ()) |
6606 | end = strptime (local_time, formats_0[i], &local_print_time); |
6607 | else |
6608 | end = strptime (local_time, formats_1[i], &local_print_time); |
6609 | |
6610 | if (end != NULL((void*)0) && end[0] == '\0') |
6611 | break; |
6612 | } |
6613 | |
6614 | if (end != NULL((void*)0) && end[0] == '\0') |
6615 | { |
6616 | struct tm *actual_local_time; |
6617 | struct tm utc_print_time; |
6618 | struct tm diff_time; |
6619 | time_t rawtime; |
6620 | time (&rawtime); |
6621 | |
6622 | actual_utc_time = g_memdup2 (gmtime (&rawtime), sizeof (struct tm)); |
6623 | actual_local_time = g_memdup2 (localtime (&rawtime), sizeof (struct tm)); |
6624 | |
6625 | diff_time.tm_hour = actual_utc_time->tm_hour - actual_local_time->tm_hour; |
6626 | diff_time.tm_min = actual_utc_time->tm_min - actual_local_time->tm_min; |
6627 | diff_time.tm_sec = actual_utc_time->tm_sec - actual_local_time->tm_sec; |
6628 | |
6629 | utc_print_time.tm_hour = ((local_print_time.tm_hour + diff_time.tm_hour) + 24) % 24; |
6630 | utc_print_time.tm_min = ((local_print_time.tm_min + diff_time.tm_min) + 60) % 60; |
6631 | utc_print_time.tm_sec = ((local_print_time.tm_sec + diff_time.tm_sec) + 60) % 60; |
6632 | |
6633 | utc_time = g_strdup_printf ("%02d:%02d:%02d", |
6634 | utc_print_time.tm_hour, |
6635 | utc_print_time.tm_min, |
6636 | utc_print_time.tm_sec); |
6637 | } |
6638 | |
6639 | return utc_time; |
6640 | } |
6641 | |
6642 | static void |
6643 | cups_printer_get_settings_from_options (CtkPrinter *printer, |
6644 | CtkPrinterOptionSet *options, |
6645 | CtkPrintSettings *settings) |
6646 | { |
6647 | struct OptionData data; |
6648 | |
6649 | data.printer = printer; |
6650 | data.options = options; |
6651 | data.settings = settings; |
6652 | data.ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
6653 | |
6654 | ctk_printer_option_set_foreach (options, foreach_option_get_settings, &data); |
6655 | if (data.ppd_file != NULL((void*)0)) |
6656 | { |
6657 | const char *print_at, *print_at_time; |
6658 | CtkPrinterOption *cover_before, *cover_after; |
6659 | |
6660 | cover_before = ctk_printer_option_set_lookup (options, "ctk-cover-before"); |
6661 | cover_after = ctk_printer_option_set_lookup (options, "ctk-cover-after"); |
6662 | if (cover_before && cover_after) |
6663 | { |
6664 | char *value = g_strdup_printf ("%s,%s", cover_before->value, cover_after->value); |
6665 | ctk_print_settings_set (settings, "cups-job-sheets", value); |
6666 | g_free (value); |
6667 | } |
6668 | |
6669 | print_at = ctk_print_settings_get (settings, "print-at"); |
6670 | print_at_time = ctk_print_settings_get (settings, "print-at-time"); |
6671 | |
6672 | if (strcmp (print_at, "at") == 0) |
6673 | { |
6674 | gchar *utc_time = NULL((void*)0); |
6675 | |
6676 | utc_time = localtime_to_utctime (print_at_time); |
6677 | |
6678 | if (utc_time != NULL((void*)0)) |
6679 | { |
6680 | ctk_print_settings_set (settings, "cups-job-hold-until", utc_time); |
6681 | g_free (utc_time); |
6682 | } |
6683 | else |
6684 | ctk_print_settings_set (settings, "cups-job-hold-until", print_at_time); |
6685 | } |
6686 | else if (strcmp (print_at, "on-hold") == 0) |
6687 | ctk_print_settings_set (settings, "cups-job-hold-until", "indefinite"); |
6688 | } |
6689 | } |
6690 | |
6691 | static void |
6692 | cups_printer_prepare_for_print (CtkPrinter *printer, |
6693 | CtkPrintJob *print_job, |
6694 | CtkPrintSettings *settings, |
6695 | CtkPageSetup *page_setup) |
6696 | { |
6697 | CtkPrintPages pages; |
6698 | CtkPageRange *ranges; |
6699 | gint n_ranges; |
6700 | CtkPageSet page_set; |
6701 | CtkPaperSize *paper_size; |
6702 | const char *ppd_paper_name; |
6703 | double scale; |
6704 | CtkPrintCapabilities capabilities; |
6705 | |
6706 | capabilities = cups_printer_get_capabilities (printer); |
6707 | pages = ctk_print_settings_get_print_pages (settings); |
6708 | ctk_print_job_set_pages (print_job, pages); |
6709 | |
6710 | if (pages == CTK_PRINT_PAGES_RANGES) |
6711 | ranges = ctk_print_settings_get_page_ranges (settings, &n_ranges); |
6712 | else |
6713 | { |
6714 | ranges = NULL((void*)0); |
6715 | n_ranges = 0; |
6716 | } |
6717 | |
6718 | ctk_print_job_set_page_ranges (print_job, ranges, n_ranges); |
6719 | |
6720 | if (capabilities & CTK_PRINT_CAPABILITY_COLLATE) |
6721 | { |
6722 | if (ctk_print_settings_get_collate (settings)) |
6723 | ctk_print_settings_set (settings, "cups-Collate", "True"); |
6724 | else |
6725 | ctk_print_settings_set (settings, "cups-Collate", "False"); |
6726 | ctk_print_job_set_collate (print_job, FALSE(0)); |
6727 | } |
6728 | else |
6729 | { |
6730 | ctk_print_job_set_collate (print_job, ctk_print_settings_get_collate (settings)); |
6731 | } |
6732 | |
6733 | if (capabilities & CTK_PRINT_CAPABILITY_REVERSE) |
6734 | { |
6735 | if (ctk_print_settings_get_reverse (settings)) |
6736 | ctk_print_settings_set (settings, "cups-OutputOrder", "Reverse"); |
6737 | ctk_print_job_set_reverse (print_job, FALSE(0)); |
6738 | } |
6739 | else |
6740 | { |
6741 | ctk_print_job_set_reverse (print_job, ctk_print_settings_get_reverse (settings)); |
6742 | } |
6743 | |
6744 | if (capabilities & CTK_PRINT_CAPABILITY_COPIES) |
6745 | { |
6746 | if (ctk_print_settings_get_n_copies (settings) > 1) |
6747 | ctk_print_settings_set_int (settings, "cups-copies", |
6748 | ctk_print_settings_get_n_copies (settings)); |
6749 | ctk_print_job_set_num_copies (print_job, 1); |
6750 | } |
6751 | else |
6752 | { |
6753 | ctk_print_job_set_num_copies (print_job, ctk_print_settings_get_n_copies (settings)); |
6754 | } |
6755 | |
6756 | scale = ctk_print_settings_get_scale (settings); |
6757 | if (scale != 100.0) |
6758 | ctk_print_job_set_scale (print_job, scale / 100.0); |
6759 | |
6760 | page_set = ctk_print_settings_get_page_set (settings); |
6761 | if (page_set == CTK_PAGE_SET_EVEN) |
6762 | ctk_print_settings_set (settings, "cups-page-set", "even"); |
6763 | else if (page_set == CTK_PAGE_SET_ODD) |
6764 | ctk_print_settings_set (settings, "cups-page-set", "odd"); |
6765 | ctk_print_job_set_page_set (print_job, CTK_PAGE_SET_ALL); |
6766 | |
6767 | paper_size = ctk_page_setup_get_paper_size (page_setup); |
6768 | ppd_paper_name = ctk_paper_size_get_ppd_name (paper_size); |
6769 | if (ppd_paper_name != NULL((void*)0)) |
6770 | ctk_print_settings_set (settings, "cups-PageSize", ppd_paper_name); |
6771 | else if (ctk_paper_size_is_ipp (paper_size)) |
6772 | ctk_print_settings_set (settings, "cups-media", ctk_paper_size_get_name (paper_size)); |
6773 | else |
6774 | { |
6775 | char width[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)]; |
6776 | char height[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)]; |
6777 | char *custom_name; |
6778 | |
6779 | g_ascii_formatd (width, sizeof (width), "%.2f", ctk_paper_size_get_width (paper_size, CTK_UNIT_POINTS)); |
6780 | g_ascii_formatd (height, sizeof (height), "%.2f", ctk_paper_size_get_height (paper_size, CTK_UNIT_POINTS)); |
6781 | custom_name = g_strdup_printf (("Custom.%sx%s"), width, height); |
6782 | ctk_print_settings_set (settings, "cups-PageSize", custom_name); |
6783 | g_free (custom_name); |
6784 | } |
6785 | |
6786 | if (ctk_print_settings_get_number_up (settings) > 1) |
6787 | { |
6788 | CtkNumberUpLayout layout = ctk_print_settings_get_number_up_layout (settings); |
6789 | GEnumClass *enum_class; |
6790 | GEnumValue *enum_value; |
6791 | |
6792 | switch (ctk_page_setup_get_orientation (page_setup)) |
6793 | { |
6794 | case CTK_PAGE_ORIENTATION_PORTRAIT: |
6795 | break; |
6796 | case CTK_PAGE_ORIENTATION_LANDSCAPE: |
6797 | if (layout < 4) |
6798 | layout = layout + 2 + 4 * (1 - layout / 2); |
6799 | else |
6800 | layout = layout - 3 - 2 * (layout % 2); |
6801 | break; |
6802 | case CTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: |
6803 | layout = (layout + 3 - 2 * (layout % 2)) % 4 + 4 * (layout / 4); |
6804 | break; |
6805 | case CTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: |
6806 | if (layout < 4) |
6807 | layout = layout + 5 - 2 * (layout % 2); |
6808 | else |
6809 | layout = layout - 6 + 4 * (1 - (layout - 4) / 2); |
6810 | break; |
6811 | } |
6812 | |
6813 | enum_class = g_type_class_ref (CTK_TYPE_NUMBER_UP_LAYOUT(ctk_number_up_layout_get_type ())); |
6814 | enum_value = g_enum_get_value (enum_class, layout); |
6815 | ctk_print_settings_set (settings, "cups-number-up-layout", enum_value->value_nick); |
6816 | g_type_class_unref (enum_class); |
6817 | |
6818 | if (!(capabilities & CTK_PRINT_CAPABILITY_NUMBER_UP)) |
6819 | { |
6820 | ctk_print_job_set_n_up (print_job, ctk_print_settings_get_number_up (settings)); |
6821 | ctk_print_job_set_n_up_layout (print_job, ctk_print_settings_get_number_up_layout (settings)); |
6822 | } |
6823 | } |
6824 | |
6825 | ctk_print_job_set_rotate (print_job, TRUE(!(0))); |
6826 | } |
6827 | |
6828 | static CtkPageSetup * |
6829 | create_page_setup (ppd_file_t *ppd_file, |
6830 | ppd_size_t *size) |
6831 | { |
6832 | char *display_name; |
6833 | CtkPageSetup *page_setup; |
6834 | CtkPaperSize *paper_size; |
6835 | ppd_option_t *option; |
6836 | |
6837 | display_name = NULL((void*)0); |
6838 | option = ppdFindOption (ppd_file, "PageSize"); |
6839 | if (option) |
6840 | { |
6841 | ppd_choice_t *choice; |
6842 | |
6843 | choice = ppdFindChoice (option, size->name); |
6844 | if (choice) |
6845 | display_name = ppd_text_to_utf8 (ppd_file, choice->text); |
6846 | } |
6847 | |
6848 | if (display_name == NULL((void*)0)) |
6849 | display_name = g_strdup (size->name)g_strdup_inline (size->name); |
6850 | |
6851 | page_setup = ctk_page_setup_new (); |
6852 | paper_size = ctk_paper_size_new_from_ppd (size->name, |
6853 | display_name, |
6854 | size->width, |
6855 | size->length); |
6856 | ctk_page_setup_set_paper_size (page_setup, paper_size); |
6857 | ctk_paper_size_free (paper_size); |
6858 | |
6859 | ctk_page_setup_set_top_margin (page_setup, size->length - size->top, CTK_UNIT_POINTS); |
6860 | ctk_page_setup_set_bottom_margin (page_setup, size->bottom, CTK_UNIT_POINTS); |
6861 | ctk_page_setup_set_left_margin (page_setup, size->left, CTK_UNIT_POINTS); |
6862 | ctk_page_setup_set_right_margin (page_setup, size->width - size->right, CTK_UNIT_POINTS); |
6863 | |
6864 | g_free (display_name); |
6865 | |
6866 | return page_setup; |
6867 | } |
6868 | |
6869 | static CtkPageSetup * |
6870 | create_page_setup_from_media (gchar *media, |
6871 | MediaSize *media_size, |
6872 | gboolean media_margin_default_set, |
6873 | gint media_bottom_margin_default, |
6874 | gint media_top_margin_default, |
6875 | gint media_left_margin_default, |
6876 | gint media_right_margin_default) |
6877 | { |
6878 | CtkPageSetup *page_setup; |
6879 | CtkPaperSize *paper_size; |
6880 | |
6881 | page_setup = ctk_page_setup_new (); |
6882 | paper_size = ctk_paper_size_new_from_ipp (media, |
6883 | POINTS_PER_INCH72 * (media_size->x_dimension / MM_PER_INCH25.4), |
6884 | POINTS_PER_INCH72 * (media_size->y_dimension / MM_PER_INCH25.4)); |
6885 | ctk_page_setup_set_paper_size (page_setup, paper_size); |
6886 | ctk_paper_size_free (paper_size); |
6887 | |
6888 | if (media_margin_default_set) |
6889 | { |
6890 | ctk_page_setup_set_bottom_margin (page_setup, media_bottom_margin_default, CTK_UNIT_MM); |
6891 | ctk_page_setup_set_top_margin (page_setup, media_top_margin_default, CTK_UNIT_MM); |
6892 | ctk_page_setup_set_left_margin (page_setup, media_left_margin_default, CTK_UNIT_MM); |
6893 | ctk_page_setup_set_right_margin (page_setup, media_right_margin_default, CTK_UNIT_MM); |
6894 | } |
6895 | |
6896 | return page_setup; |
6897 | } |
6898 | |
6899 | static GList * |
6900 | cups_printer_list_papers (CtkPrinter *printer) |
6901 | { |
6902 | ppd_file_t *ppd_file; |
6903 | CtkPageSetup *page_setup; |
6904 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
6905 | GList *result = NULL((void*)0); |
6906 | |
6907 | ppd_file = ctk_printer_cups_get_ppd (cups_printer); |
6908 | if (ppd_file != NULL((void*)0)) |
6909 | { |
6910 | int i; |
6911 | |
6912 | for (i = 0; i < ppd_file->num_sizes; i++) |
6913 | { |
6914 | ppd_size_t *size; |
6915 | |
6916 | size = &ppd_file->sizes[i]; |
6917 | |
6918 | page_setup = create_page_setup (ppd_file, size); |
6919 | |
6920 | result = g_list_prepend (result, page_setup); |
6921 | } |
6922 | } |
6923 | else if (cups_printer->media_supported != NULL((void*)0) && |
6924 | cups_printer->media_size_supported != NULL((void*)0) && |
6925 | /* |
6926 | * 'media_supported' list can contain names of minimal and maximal sizes |
6927 | * for which we don't create item in 'media_size_supported' list. |
6928 | */ |
6929 | g_list_length (cups_printer->media_supported) >= |
6930 | g_list_length (cups_printer->media_size_supported)) |
6931 | { |
6932 | GList *media_iter; |
6933 | GList *media_size_iter; |
6934 | |
6935 | for (media_iter = cups_printer->media_supported, |
6936 | media_size_iter = cups_printer->media_size_supported; |
6937 | media_size_iter != NULL((void*)0); |
6938 | media_iter = media_iter->next, |
6939 | media_size_iter = media_size_iter->next) |
6940 | { |
6941 | MediaSize *media_size; |
6942 | gchar *media; |
6943 | |
6944 | media = (gchar *) media_iter->data; |
6945 | media_size = (MediaSize *) media_size_iter->data; |
6946 | |
6947 | page_setup = create_page_setup_from_media (media, |
6948 | media_size, |
6949 | cups_printer->media_margin_default_set, |
6950 | cups_printer->media_bottom_margin_default, |
6951 | cups_printer->media_top_margin_default, |
6952 | cups_printer->media_left_margin_default, |
6953 | cups_printer->media_right_margin_default); |
6954 | |
6955 | result = g_list_prepend (result, page_setup); |
6956 | } |
6957 | } |
6958 | |
6959 | result = g_list_reverse (result); |
6960 | |
6961 | return result; |
6962 | } |
6963 | |
6964 | static CtkPageSetup * |
6965 | cups_printer_get_default_page_size (CtkPrinter *printer) |
6966 | { |
6967 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
6968 | CtkPageSetup *result = NULL((void*)0); |
6969 | ppd_file_t *ppd_file; |
6970 | |
6971 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
6972 | |
6973 | if (ppd_file != NULL((void*)0)) |
6974 | { |
6975 | ppd_option_t *option; |
6976 | ppd_size_t *size; |
6977 | |
6978 | option = ppdFindOption (ppd_file, "PageSize"); |
6979 | if (option == NULL((void*)0)) |
6980 | return NULL((void*)0); |
6981 | |
6982 | size = ppdPageSize (ppd_file, option->defchoice); |
6983 | if (size == NULL((void*)0)) |
6984 | return NULL((void*)0); |
6985 | |
6986 | result = create_page_setup (ppd_file, size); |
6987 | } |
6988 | else if (cups_printer->media_default != NULL((void*)0)) |
6989 | { |
6990 | GList *media_iter; |
6991 | GList *media_size_iter; |
6992 | |
6993 | for (media_iter = cups_printer->media_supported, |
6994 | media_size_iter = cups_printer->media_size_supported; |
6995 | media_size_iter != NULL((void*)0); |
6996 | media_iter = media_iter->next, |
6997 | media_size_iter = media_size_iter->next) |
6998 | { |
6999 | MediaSize *media_size; |
7000 | gchar *media; |
7001 | |
7002 | media = (gchar *) media_iter->data; |
7003 | media_size = (MediaSize *) media_size_iter->data; |
7004 | |
7005 | if (g_strcmp0 (cups_printer->media_default, media) == 0) |
7006 | { |
7007 | result = create_page_setup_from_media (media, |
7008 | media_size, |
7009 | cups_printer->media_margin_default_set, |
7010 | cups_printer->media_bottom_margin_default, |
7011 | cups_printer->media_top_margin_default, |
7012 | cups_printer->media_left_margin_default, |
7013 | cups_printer->media_right_margin_default); |
7014 | } |
7015 | } |
7016 | } |
7017 | |
7018 | return result; |
7019 | } |
7020 | |
7021 | static gboolean |
7022 | cups_printer_get_hard_margins (CtkPrinter *printer, |
7023 | gdouble *top, |
7024 | gdouble *bottom, |
7025 | gdouble *left, |
7026 | gdouble *right) |
7027 | { |
7028 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
7029 | ppd_file_t *ppd_file; |
7030 | gboolean result = FALSE(0); |
7031 | |
7032 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
7033 | if (ppd_file != NULL((void*)0)) |
7034 | { |
7035 | *left = ppd_file->custom_margins[0]; |
7036 | *bottom = ppd_file->custom_margins[1]; |
7037 | *right = ppd_file->custom_margins[2]; |
7038 | *top = ppd_file->custom_margins[3]; |
7039 | result = TRUE(!(0)); |
7040 | } |
7041 | else if (cups_printer->media_margin_default_set) |
7042 | { |
7043 | *left = POINTS_PER_INCH72 * cups_printer->media_left_margin_default / MM_PER_INCH25.4; |
7044 | *bottom = POINTS_PER_INCH72 * cups_printer->media_bottom_margin_default / MM_PER_INCH25.4; |
7045 | *right = POINTS_PER_INCH72 * cups_printer->media_right_margin_default / MM_PER_INCH25.4; |
7046 | *top = POINTS_PER_INCH72 * cups_printer->media_top_margin_default / MM_PER_INCH25.4; |
7047 | result = TRUE(!(0)); |
7048 | } |
7049 | |
7050 | return result; |
7051 | } |
7052 | |
7053 | static gboolean |
7054 | cups_printer_get_hard_margins_for_paper_size (CtkPrinter *printer, |
7055 | CtkPaperSize *paper_size, |
7056 | gdouble *top, |
7057 | gdouble *bottom, |
7058 | gdouble *left, |
7059 | gdouble *right) |
7060 | { |
7061 | ppd_file_t *ppd_file; |
7062 | ppd_size_t *size; |
7063 | const gchar *paper_name; |
7064 | int i; |
7065 | |
7066 | ppd_file = ctk_printer_cups_get_ppd (CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ()))))))); |
7067 | if (ppd_file == NULL((void*)0)) |
7068 | return FALSE(0); |
7069 | |
7070 | paper_name = ctk_paper_size_get_ppd_name (paper_size); |
7071 | |
7072 | for (i = 0; i < ppd_file->num_sizes; i++) |
7073 | { |
7074 | size = &ppd_file->sizes[i]; |
7075 | if (g_strcmp0(size->name, paper_name) == 0) |
7076 | { |
7077 | *top = size->length - size->top; |
7078 | *bottom = size->bottom; |
7079 | *left = size->left; |
7080 | *right = size->width - size->right; |
7081 | return TRUE(!(0)); |
7082 | } |
7083 | } |
7084 | |
7085 | /* Custom size */ |
7086 | *left = ppd_file->custom_margins[0]; |
7087 | *bottom = ppd_file->custom_margins[1]; |
7088 | *right = ppd_file->custom_margins[2]; |
7089 | *top = ppd_file->custom_margins[3]; |
7090 | |
7091 | return TRUE(!(0)); |
7092 | } |
7093 | |
7094 | static CtkPrintCapabilities |
7095 | cups_printer_get_capabilities (CtkPrinter *printer) |
7096 | { |
7097 | CtkPrintCapabilities capabilities = 0; |
7098 | CtkPrinterCups *cups_printer = CTK_PRINTER_CUPS (printer)((((CtkPrinterCups*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((printer)), ((ctk_printer_cups_get_type ())))))); |
7099 | |
7100 | if (ctk_printer_cups_get_ppd (cups_printer)) |
7101 | { |
7102 | capabilities = CTK_PRINT_CAPABILITY_REVERSE; |
7103 | } |
7104 | |
7105 | if (cups_printer->supports_copies) |
7106 | { |
7107 | capabilities |= CTK_PRINT_CAPABILITY_COPIES; |
7108 | } |
7109 | |
7110 | if (cups_printer->supports_collate) |
7111 | { |
7112 | capabilities |= CTK_PRINT_CAPABILITY_COLLATE; |
7113 | } |
7114 | |
7115 | if (cups_printer->supports_number_up) |
7116 | { |
7117 | capabilities |= CTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT | |
7118 | CTK_PRINT_CAPABILITY_NUMBER_UP; |
7119 | } |
7120 | |
7121 | return capabilities; |
7122 | } |
7123 | |
7124 | static void |
7125 | secrets_service_appeared_cb (GDBusConnection *connection G_GNUC_UNUSED__attribute__ ((__unused__)), |
7126 | const gchar *name G_GNUC_UNUSED__attribute__ ((__unused__)), |
7127 | const gchar *name_owner G_GNUC_UNUSED__attribute__ ((__unused__)), |
7128 | gpointer user_data) |
7129 | { |
7130 | CtkPrintBackendCups *backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
7131 | |
7132 | backend->secrets_service_available = TRUE(!(0)); |
7133 | } |
7134 | |
7135 | static void |
7136 | secrets_service_vanished_cb (GDBusConnection *connection G_GNUC_UNUSED__attribute__ ((__unused__)), |
7137 | const gchar *name G_GNUC_UNUSED__attribute__ ((__unused__)), |
7138 | gpointer user_data) |
7139 | { |
7140 | CtkPrintBackendCups *backend = CTK_PRINT_BACKEND_CUPS (user_data)((((CtkPrintBackendCups*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((user_data)), ((ctk_print_backend_cups_get_type ())))))); |
7141 | |
7142 | backend->secrets_service_available = FALSE(0); |
7143 | } |