| 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 | } |