File: | modules/printbackends/cups/ctkprintbackendcups.c |
Warning: | line 6608, column 37 Access of 'formats_1' at index 2, while it holds only 2 'const char *' elements |
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; | |||
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 | } |