GCC Code Coverage Report


Directory: ./
File: panels/printers/pp-new-printer.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 516 0.0%
Functions: 0 32 0.0%
Branches: 0 275 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright 2012 Red Hat, Inc,
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Marek Kasik <mkasik@redhat.com>
19 */
20
21 #include "pp-new-printer.h"
22
23 #include <glib/gstdio.h>
24 #include <glib/gi18n.h>
25
26 #include "pp-utils.h"
27 #include "pp-maintenance-command.h"
28
29 #define PACKAGE_KIT_BUS "org.freedesktop.PackageKit"
30 #define PACKAGE_KIT_PATH "/org/freedesktop/PackageKit"
31 #define PACKAGE_KIT_MODIFY_IFACE "org.freedesktop.PackageKit.Modify"
32 #define PACKAGE_KIT_QUERY_IFACE "org.freedesktop.PackageKit.Query"
33
34 #define DBUS_TIMEOUT 120000
35 #define DBUS_TIMEOUT_LONG 600000
36
37 #if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
38 #define HAVE_CUPS_1_6 1
39 #endif
40
41 #ifndef HAVE_CUPS_1_6
42 #define ippGetState(ipp) ipp->state
43 #endif
44
45 struct _PpNewPrinter
46 {
47 GObject parent_instance;
48
49 gchar *name;
50 gchar *original_name;
51 gchar *device_uri;
52 gchar *device_id;
53 gchar *ppd_name;
54 gchar *ppd_file_name;
55 gchar *info;
56 gchar *location;
57 gchar *make_and_model;
58 gchar *host_name;
59 gint host_port;
60 gboolean is_network_device;
61 guint window_id;
62 gboolean unlink_ppd_file;
63
64 GTask *task;
65 GCancellable *cancellable;
66 };
67
68 G_DEFINE_TYPE (PpNewPrinter, pp_new_printer, G_TYPE_OBJECT);
69
70 enum {
71 PROP_0 = 0,
72 PROP_NAME,
73 PROP_ORIGINAL_NAME,
74 PROP_DEVICE_URI,
75 PROP_DEVICE_ID,
76 PROP_PPD_NAME,
77 PROP_PPD_FILE_NAME,
78 PROP_INFO,
79 PROP_LOCATION,
80 PROP_MAKE_AND_MODEL,
81 PROP_HOST_NAME,
82 PROP_HOST_PORT,
83 PROP_IS_NETWORK_DEVICE,
84 PROP_WINDOW_ID
85 };
86
87 static void
88 pp_new_printer_finalize (GObject *object)
89 {
90 PpNewPrinter *self = PP_NEW_PRINTER (object);
91
92 if (self->unlink_ppd_file && self->ppd_file_name)
93 g_unlink (self->ppd_file_name);
94
95 g_clear_pointer (&self->name, g_free);
96 g_clear_pointer (&self->original_name, g_free);
97 g_clear_pointer (&self->device_uri, g_free);
98 g_clear_pointer (&self->device_id, g_free);
99 g_clear_pointer (&self->ppd_name, g_free);
100 g_clear_pointer (&self->ppd_file_name, g_free);
101 g_clear_pointer (&self->info, g_free);
102 g_clear_pointer (&self->location, g_free);
103 g_clear_pointer (&self->make_and_model, g_free);
104 g_clear_pointer (&self->host_name, g_free);
105 g_clear_object (&self->task);
106 g_clear_object (&self->cancellable);
107
108 G_OBJECT_CLASS (pp_new_printer_parent_class)->finalize (object);
109 }
110
111 static void
112 pp_new_printer_get_property (GObject *object,
113 guint prop_id,
114 GValue *value,
115 GParamSpec *param_spec)
116 {
117 PpNewPrinter *self = PP_NEW_PRINTER (object);
118
119 switch (prop_id)
120 {
121 case PROP_NAME:
122 g_value_set_string (value, self->name);
123 break;
124 case PROP_ORIGINAL_NAME:
125 g_value_set_string (value, self->original_name);
126 break;
127 case PROP_DEVICE_URI:
128 g_value_set_string (value, self->device_uri);
129 break;
130 case PROP_DEVICE_ID:
131 g_value_set_string (value, self->device_id);
132 break;
133 case PROP_PPD_NAME:
134 g_value_set_string (value, self->ppd_name);
135 break;
136 case PROP_PPD_FILE_NAME:
137 g_value_set_string (value, self->ppd_file_name);
138 break;
139 case PROP_INFO:
140 g_value_set_string (value, self->info);
141 break;
142 case PROP_LOCATION:
143 g_value_set_string (value, self->location);
144 break;
145 case PROP_MAKE_AND_MODEL:
146 g_value_set_string (value, self->make_and_model);
147 break;
148 case PROP_HOST_NAME:
149 g_value_set_string (value, self->host_name);
150 break;
151 case PROP_HOST_PORT:
152 g_value_set_int (value, self->host_port);
153 break;
154 case PROP_IS_NETWORK_DEVICE:
155 g_value_set_boolean (value, self->is_network_device);
156 break;
157 case PROP_WINDOW_ID:
158 g_value_set_uint (value, self->window_id);
159 break;
160 default:
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
162 prop_id,
163 param_spec);
164 break;
165 }
166 }
167
168 static void
169 pp_new_printer_set_property (GObject *object,
170 guint prop_id,
171 const GValue *value,
172 GParamSpec *param_spec)
173 {
174 PpNewPrinter *self = PP_NEW_PRINTER (object);
175
176 switch (prop_id)
177 {
178 case PROP_NAME:
179 g_free (self->name);
180 self->name = g_value_dup_string (value);
181 break;
182 case PROP_ORIGINAL_NAME:
183 g_free (self->original_name);
184 self->original_name = g_value_dup_string (value);
185 break;
186 case PROP_DEVICE_URI:
187 g_free (self->device_uri);
188 self->device_uri = g_value_dup_string (value);
189 break;
190 case PROP_DEVICE_ID:
191 g_free (self->device_id);
192 self->device_id = g_value_dup_string (value);
193 break;
194 case PROP_PPD_NAME:
195 g_free (self->ppd_name);
196 self->ppd_name = g_value_dup_string (value);
197 break;
198 case PROP_PPD_FILE_NAME:
199 g_free (self->ppd_file_name);
200 self->ppd_file_name = g_value_dup_string (value);
201 break;
202 case PROP_INFO:
203 g_free (self->info);
204 self->info = g_value_dup_string (value);
205 break;
206 case PROP_LOCATION:
207 g_free (self->location);
208 self->location = g_value_dup_string (value);
209 break;
210 case PROP_MAKE_AND_MODEL:
211 g_free (self->make_and_model);
212 self->make_and_model = g_value_dup_string (value);
213 break;
214 case PROP_HOST_NAME:
215 g_free (self->host_name);
216 self->host_name = g_value_dup_string (value);
217 break;
218 case PROP_HOST_PORT:
219 self->host_port = g_value_get_int (value);
220 break;
221 case PROP_IS_NETWORK_DEVICE:
222 self->is_network_device = g_value_get_boolean (value);
223 break;
224 case PROP_WINDOW_ID:
225 self->window_id = g_value_get_uint (value);
226 break;
227 default:
228 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
229 prop_id,
230 param_spec);
231 break;
232 }
233 }
234
235 static void
236 pp_new_printer_class_init (PpNewPrinterClass *klass)
237 {
238 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
239
240 gobject_class->set_property = pp_new_printer_set_property;
241 gobject_class->get_property = pp_new_printer_get_property;
242
243 gobject_class->finalize = pp_new_printer_finalize;
244
245 g_object_class_install_property (gobject_class, PROP_NAME,
246 g_param_spec_string ("name",
247 "Name",
248 "The new printer's name",
249 NULL,
250 G_PARAM_READWRITE));
251
252 g_object_class_install_property (gobject_class, PROP_ORIGINAL_NAME,
253 g_param_spec_string ("original-name",
254 "Original name",
255 "Original name of the new printer",
256 NULL,
257 G_PARAM_READWRITE));
258
259 g_object_class_install_property (gobject_class, PROP_DEVICE_URI,
260 g_param_spec_string ("device-uri",
261 "Device URI",
262 "The new printer's device URI",
263 NULL,
264 G_PARAM_READWRITE));
265
266 g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
267 g_param_spec_string ("device-id",
268 "DeviceID",
269 "The new printer's DeviceID",
270 NULL,
271 G_PARAM_READWRITE));
272
273 g_object_class_install_property (gobject_class, PROP_PPD_NAME,
274 g_param_spec_string ("ppd-name",
275 "PPD name",
276 "Name of PPD for the new printer",
277 NULL,
278 G_PARAM_READWRITE));
279
280 g_object_class_install_property (gobject_class, PROP_PPD_FILE_NAME,
281 g_param_spec_string ("ppd-file-name",
282 "PPD file name",
283 "PPD file for the new printer",
284 NULL,
285 G_PARAM_READWRITE));
286
287 g_object_class_install_property (gobject_class, PROP_INFO,
288 g_param_spec_string ("info",
289 "Printer info",
290 "The new printer's info",
291 NULL,
292 G_PARAM_READWRITE));
293
294 g_object_class_install_property (gobject_class, PROP_LOCATION,
295 g_param_spec_string ("location",
296 "Printer location",
297 "The new printer's location",
298 NULL,
299 G_PARAM_READWRITE));
300
301 g_object_class_install_property (gobject_class, PROP_MAKE_AND_MODEL,
302 g_param_spec_string ("make-and-model",
303 "Printer make and model",
304 "The new printer's make and model",
305 NULL,
306 G_PARAM_READWRITE));
307
308 g_object_class_install_property (gobject_class, PROP_HOST_NAME,
309 g_param_spec_string ("host-name",
310 "Hostname",
311 "The new printer's hostname",
312 NULL,
313 G_PARAM_READWRITE));
314
315 g_object_class_install_property (gobject_class, PROP_HOST_PORT,
316 g_param_spec_int ("host-port",
317 "Host port",
318 "The port of the host",
319 0, G_MAXINT32, 631,
320 G_PARAM_READWRITE));
321
322 g_object_class_install_property (gobject_class, PROP_IS_NETWORK_DEVICE,
323 g_param_spec_boolean ("is-network-device",
324 "Network device",
325 "Whether the new printer is a network device",
326 FALSE,
327 G_PARAM_READWRITE));
328
329 g_object_class_install_property (gobject_class, PROP_WINDOW_ID,
330 g_param_spec_uint ("window-id",
331 "WindowID",
332 "Window ID of parent window",
333 0, G_MAXUINT, 0,
334 G_PARAM_READWRITE));
335 }
336
337 static void
338 pp_new_printer_init (PpNewPrinter *self)
339 {
340 }
341
342 PpNewPrinter *
343 pp_new_printer_new ()
344 {
345 return g_object_new (PP_TYPE_NEW_PRINTER, NULL);
346 }
347
348 static void printer_configure_async (PpNewPrinter *self);
349
350 static void
351 _pp_new_printer_add_async_cb (gboolean success,
352 PpNewPrinter *self)
353 {
354 if (!success)
355 {
356 g_task_return_new_error (self->task,
357 G_IO_ERROR,
358 G_IO_ERROR_FAILED,
359 "Installation of the new printer failed.");
360 return;
361 }
362
363 g_task_return_boolean (self->task, success);
364 }
365
366 static void
367 printer_add_real_async_cb (cups_dest_t *destination,
368 gpointer user_data)
369 {
370 PpNewPrinter *self = user_data;
371 gboolean success = FALSE;
372
373 if (destination)
374 {
375 success = TRUE;
376 cupsFreeDests (1, destination);
377 }
378
379 if (success)
380 {
381 printer_configure_async (self);
382 }
383 else
384 {
385 _pp_new_printer_add_async_cb (FALSE, self);
386 }
387 }
388
389 static void
390 printer_add_real_async_dbus_cb (GObject *source_object,
391 GAsyncResult *res,
392 gpointer user_data)
393 {
394 PpNewPrinter *self = user_data;
395 g_autoptr(GVariant) output = NULL;
396 g_autoptr(GError) error = NULL;
397
398 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
399 res,
400 &error);
401
402 if (output)
403 {
404 const gchar *ret_error;
405
406 g_variant_get (output, "(&s)", &ret_error);
407 if (ret_error[0] != '\0')
408 {
409 g_warning ("cups-pk-helper: addition of printer %s failed: %s", self->name, ret_error);
410 }
411 }
412 else
413 {
414 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
415 g_warning ("%s", error->message);
416 }
417
418 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
419 {
420 get_named_dest_async (self->name,
421 printer_add_real_async_cb,
422 self);
423 }
424 }
425
426 static void
427 printer_add_real_async (PpNewPrinter *self)
428 {
429 g_autoptr(GDBusConnection) bus = NULL;
430 g_autoptr(GError) error = NULL;
431
432 if (!self->ppd_name && !self->ppd_file_name)
433 {
434 _pp_new_printer_add_async_cb (FALSE, self);
435 return;
436 }
437
438 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
439 if (!bus)
440 {
441 g_warning ("Failed to get system bus: %s", error->message);
442 _pp_new_printer_add_async_cb (FALSE, self);
443 return;
444 }
445
446 g_dbus_connection_call (bus,
447 MECHANISM_BUS,
448 "/",
449 MECHANISM_BUS,
450 self->ppd_name ? "PrinterAdd" : "PrinterAddWithPpdFile",
451 g_variant_new ("(sssss)",
452 self->name,
453 self->device_uri,
454 self->ppd_name ? self->ppd_name : self->ppd_file_name,
455 self->info ? self->info : "",
456 self->location ? self->location : ""),
457 G_VARIANT_TYPE ("(s)"),
458 G_DBUS_CALL_FLAGS_NONE,
459 DBUS_TIMEOUT,
460 NULL,
461 printer_add_real_async_dbus_cb,
462 self);
463 }
464
465 static PPDName *
466 get_ppd_item_from_output (GVariant *output)
467 {
468 g_autoptr(GVariant) array = NULL;
469 gint j;
470 static const char * const match_levels[] = {
471 "exact-cmd",
472 "exact",
473 "close",
474 "generic",
475 "none"};
476
477 if (output == NULL)
478 return NULL;
479
480 g_variant_get (output, "(@a(ss))", &array);
481 for (j = 0; j < G_N_ELEMENTS (match_levels); j++)
482 {
483 g_autoptr(GVariantIter) iter = NULL;
484 const gchar *driver, *match;
485
486 g_variant_get (array, "a(ss)", &iter);
487 while (g_variant_iter_next (iter, "(&s&s)", &driver, &match))
488 {
489 PPDName *ppd_item;
490
491 if (!g_str_equal (match, match_levels[j]))
492 continue;
493
494 ppd_item = g_new0 (PPDName, 1);
495 ppd_item->ppd_name = g_strdup (driver);
496
497 if (g_strcmp0 (match, "exact-cmd") == 0)
498 ppd_item->ppd_match_level = PPD_EXACT_CMD_MATCH;
499 else if (g_strcmp0 (match, "exact") == 0)
500 ppd_item->ppd_match_level = PPD_EXACT_MATCH;
501 else if (g_strcmp0 (match, "close") == 0)
502 ppd_item->ppd_match_level = PPD_CLOSE_MATCH;
503 else if (g_strcmp0 (match, "generic") == 0)
504 ppd_item->ppd_match_level = PPD_GENERIC_MATCH;
505 else if (g_strcmp0 (match, "none") == 0)
506 ppd_item->ppd_match_level = PPD_NO_MATCH;
507
508 return ppd_item;
509 }
510 }
511
512 return NULL;
513 }
514
515
516 static void
517 printer_add_async_scb3 (GObject *source_object,
518 GAsyncResult *res,
519 gpointer user_data)
520 {
521 PpNewPrinter *self = user_data;
522 g_autoptr(GVariant) output = NULL;
523 PPDName *ppd_item = NULL;
524 g_autoptr(GError) error = NULL;
525
526 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
527 res,
528 &error);
529
530 if (output)
531 {
532 ppd_item = get_ppd_item_from_output (output);
533 }
534 else
535 {
536 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
537 g_warning ("%s", error->message);
538 }
539
540 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
541 ppd_item && ppd_item->ppd_name)
542 {
543 self->ppd_name = g_strdup (ppd_item->ppd_name);
544 printer_add_real_async (self);
545 }
546 else
547 {
548 _pp_new_printer_add_async_cb (FALSE, self);
549 }
550
551 if (ppd_item)
552 {
553 g_free (ppd_item->ppd_name);
554 g_free (ppd_item);
555 }
556 }
557
558 static void
559 install_printer_drivers_cb (GObject *source_object,
560 GAsyncResult *res,
561 gpointer user_data)
562 {
563 PpNewPrinter *self = user_data;
564 g_autoptr(GVariant) output = NULL;
565 g_autoptr(GError) error = NULL;
566
567 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
568 res,
569 &error);
570
571 if (output == NULL)
572 {
573 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
574 g_warning ("%s", error->message);
575 }
576
577 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
578 {
579 g_autoptr(GDBusConnection) bus = NULL;
580 g_autoptr(GError) bus_error = NULL;
581
582 /* Try whether CUPS has a driver for the new printer */
583 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &bus_error);
584 if (bus)
585 {
586 g_dbus_connection_call (bus,
587 SCP_BUS,
588 SCP_PATH,
589 SCP_IFACE,
590 "GetBestDrivers",
591 g_variant_new ("(sss)",
592 self->device_id,
593 self->make_and_model ? self->make_and_model : "",
594 self->device_uri ? self->device_uri : ""),
595 G_VARIANT_TYPE ("(a(ss))"),
596 G_DBUS_CALL_FLAGS_NONE,
597 DBUS_TIMEOUT_LONG,
598 self->cancellable,
599 printer_add_async_scb3,
600 self);
601 }
602 else
603 {
604 g_warning ("Failed to get system bus: %s", bus_error->message);
605 _pp_new_printer_add_async_cb (FALSE, self);
606 }
607 }
608 }
609
610 static void
611 printer_add_async_scb (GObject *source_object,
612 GAsyncResult *res,
613 gpointer user_data)
614 {
615 PpNewPrinter *self = user_data;
616 g_autoptr(GDBusConnection) bus = NULL;
617 GVariantBuilder array_builder;
618 g_autoptr(GVariant) output = NULL;
619 gboolean cancelled = FALSE;
620 PPDName *ppd_item = NULL;
621 g_autoptr(GError) error = NULL;
622
623 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
624 res,
625 &error);
626
627 if (output)
628 {
629 ppd_item = get_ppd_item_from_output (output);
630 }
631 else
632 {
633 cancelled = g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
634
635 if (!cancelled)
636 g_warning ("%s", error->message);
637 }
638
639 if (!cancelled)
640 {
641 if (ppd_item == NULL || ppd_item->ppd_match_level < PPD_EXACT_MATCH)
642 {
643 g_autoptr(GError) bus_error = NULL;
644
645 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &bus_error);
646 if (bus)
647 {
648 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
649 g_variant_builder_add (&array_builder, "s", self->device_id);
650
651 g_dbus_connection_call (bus,
652 PACKAGE_KIT_BUS,
653 PACKAGE_KIT_PATH,
654 PACKAGE_KIT_MODIFY_IFACE,
655 "InstallPrinterDrivers",
656 g_variant_new ("(uass)",
657 self->window_id,
658 &array_builder,
659 "hide-finished"),
660 G_VARIANT_TYPE ("()"),
661 G_DBUS_CALL_FLAGS_NONE,
662 DBUS_TIMEOUT_LONG,
663 NULL,
664 install_printer_drivers_cb,
665 self);
666 }
667 else
668 {
669 g_warning ("Failed to get session bus: %s", bus_error->message);
670 _pp_new_printer_add_async_cb (FALSE, self);
671 }
672 }
673 else if (ppd_item && ppd_item->ppd_name)
674 {
675 self->ppd_name = g_strdup (ppd_item->ppd_name);
676 printer_add_real_async (self);
677 }
678 else
679 {
680 _pp_new_printer_add_async_cb (FALSE, self);
681 }
682 }
683
684 if (ppd_item)
685 {
686 g_free (ppd_item->ppd_name);
687 g_free (ppd_item);
688 }
689 }
690
691 static void
692 printer_add_async_scb4 (const gchar *ppd_filename,
693 gpointer user_data)
694 {
695 PpNewPrinter *self = user_data;
696
697 self->ppd_file_name = g_strdup (ppd_filename);
698 if (self->ppd_file_name)
699 {
700 self->unlink_ppd_file = TRUE;
701 printer_add_real_async (self);
702 }
703 else
704 {
705 _pp_new_printer_add_async_cb (FALSE, self);
706 }
707 }
708
709 static GList *
710 glist_uniq (GList *list)
711 {
712 GList *result = NULL;
713 GList *iter = NULL;
714 GList *tmp = NULL;
715
716 for (iter = list; iter; iter = iter->next)
717 {
718 if (tmp == NULL ||
719 g_strcmp0 ((gchar *) tmp->data, (gchar *) iter->data) != 0)
720 {
721 tmp = iter;
722 result = g_list_append (result, g_strdup (iter->data));
723 }
724 }
725
726 g_list_free_full (list, g_free);
727
728 return result;
729 }
730
731 typedef struct
732 {
733 PpNewPrinter *new_printer;
734 GCancellable *cancellable;
735 gboolean set_accept_jobs_finished;
736 gboolean set_enabled_finished;
737 gboolean autoconfigure_finished;
738 gboolean set_media_size_finished;
739 gboolean install_missing_executables_finished;
740 } PCData;
741
742 static void
743 printer_configure_async_finish (PCData *data)
744 {
745 PpNewPrinter *self = data->new_printer;
746
747 if (data->set_accept_jobs_finished &&
748 data->set_enabled_finished &&
749 (data->autoconfigure_finished || self->is_network_device) &&
750 data->set_media_size_finished &&
751 data->install_missing_executables_finished)
752 {
753 _pp_new_printer_add_async_cb (TRUE, data->new_printer);
754
755 g_clear_object (&data->cancellable);
756 g_free (data);
757 }
758 }
759
760 static void
761 pao_cb (gboolean success,
762 gpointer user_data)
763 {
764 PCData *data = (PCData *) user_data;
765
766 data->set_media_size_finished = TRUE;
767 printer_configure_async_finish (data);
768 }
769
770 static void
771 printer_set_accepting_jobs_cb (GObject *source_object,
772 GAsyncResult *res,
773 gpointer user_data)
774 {
775 g_autoptr(GVariant) output = NULL;
776 PCData *data = (PCData *) user_data;
777 g_autoptr(GError) error = NULL;
778
779 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
780 res,
781 &error);
782
783 if (output == NULL)
784 {
785 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
786 g_warning ("%s", error->message);
787 }
788
789 data->set_accept_jobs_finished = TRUE;
790 printer_configure_async_finish (data);
791 }
792
793 static void
794 printer_set_enabled_cb (GObject *source_object,
795 GAsyncResult *res,
796 gpointer user_data)
797 {
798 g_autoptr(GVariant) output = NULL;
799 PCData *data = (PCData *) user_data;
800 g_autoptr(GError) error = NULL;
801
802 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
803 res,
804 &error);
805
806 if (output == NULL)
807 {
808 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
809 g_warning ("%s", error->message);
810 }
811
812 data->set_enabled_finished = TRUE;
813 printer_configure_async_finish (data);
814 }
815
816 typedef struct
817 {
818 GList *executables;
819 GList *packages;
820 guint window_id;
821 gchar *ppd_file_name;
822 GCancellable *cancellable;
823 gpointer user_data;
824 } IMEData;
825
826 static void
827 install_missing_executables_cb (IMEData *data)
828 {
829 PCData *pc_data = (PCData *) data->user_data;
830
831 pc_data->install_missing_executables_finished = TRUE;
832 printer_configure_async_finish (pc_data);
833
834 if (data->ppd_file_name)
835 {
836 g_unlink (data->ppd_file_name);
837 g_clear_pointer (&data->ppd_file_name, g_free);
838 }
839
840 if (data->executables)
841 {
842 g_list_free_full (data->executables, g_free);
843 data->executables = NULL;
844 }
845
846 if (data->packages)
847 {
848 g_list_free_full (data->packages, g_free);
849 data->packages = NULL;
850 }
851
852 if (data->cancellable)
853 g_clear_object (&data->cancellable);
854
855 g_free (data);
856 }
857
858 static void
859 install_package_names_cb (GObject *source_object,
860 GAsyncResult *res,
861 gpointer user_data)
862 {
863 g_autoptr(GVariant) output = NULL;
864 IMEData *data = (IMEData *) user_data;
865 g_autoptr(GError) error = NULL;
866
867 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
868 res,
869 &error);
870
871 if (output == NULL)
872 {
873 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
874 g_warning ("%s", error->message);
875 }
876
877 install_missing_executables_cb (data);
878 }
879
880
881 static void
882 search_files_cb (GObject *source_object,
883 GAsyncResult *res,
884 gpointer user_data)
885 {
886 g_autoptr(GVariant) output = NULL;
887 IMEData *data = (IMEData *) user_data;
888 g_autoptr(GError) error = NULL;
889 GList *item;
890
891 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
892 res,
893 &error);
894 if (output)
895 {
896 gboolean installed;
897 gchar *package;
898
899 g_variant_get (output,
900 "(bs)",
901 &installed,
902 &package);
903
904 if (!installed)
905 data->packages = g_list_append (data->packages, g_strdup (package));
906 }
907 else
908 {
909 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
910 g_warning ("%s", error->message);
911 }
912
913 if (data->executables)
914 {
915 item = data->executables;
916 g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
917 PACKAGE_KIT_BUS,
918 PACKAGE_KIT_PATH,
919 PACKAGE_KIT_QUERY_IFACE,
920 "SearchFile",
921 g_variant_new ("(ss)",
922 (gchar *) item->data,
923 ""),
924 G_VARIANT_TYPE ("(bs)"),
925 G_DBUS_CALL_FLAGS_NONE,
926 DBUS_TIMEOUT_LONG,
927 data->cancellable,
928 search_files_cb,
929 data);
930
931 data->executables = g_list_remove_link (data->executables, item);
932 g_list_free_full (item, g_free);
933 }
934 else
935 {
936 GVariantBuilder array_builder;
937 GList *pkg_iter;
938
939 data->packages = g_list_sort (data->packages, (GCompareFunc) g_strcmp0);
940 data->packages = glist_uniq (data->packages);
941
942 if (data->packages)
943 {
944 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
945
946 for (pkg_iter = data->packages; pkg_iter; pkg_iter = pkg_iter->next)
947 g_variant_builder_add (&array_builder,
948 "s",
949 (gchar *) pkg_iter->data);
950
951 g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
952 PACKAGE_KIT_BUS,
953 PACKAGE_KIT_PATH,
954 PACKAGE_KIT_MODIFY_IFACE,
955 "InstallPackageNames",
956 g_variant_new ("(uass)",
957 data->window_id,
958 &array_builder,
959 "hide-finished"),
960 NULL,
961 G_DBUS_CALL_FLAGS_NONE,
962 DBUS_TIMEOUT_LONG,
963 data->cancellable,
964 install_package_names_cb,
965 data);
966
967 g_list_free_full (data->packages, g_free);
968 data->packages = NULL;
969 }
970 else
971 {
972 install_missing_executables_cb (data);
973 }
974 }
975 }
976
977 static void
978 get_missing_executables_cb (GObject *source_object,
979 GAsyncResult *res,
980 gpointer user_data)
981 {
982 g_autoptr(GVariant) output = NULL;
983 IMEData *data = (IMEData *) user_data;
984 g_autoptr(GError) error = NULL;
985 GList *executables = NULL;
986 GList *item;
987
988 if (data->ppd_file_name)
989 {
990 g_unlink (data->ppd_file_name);
991 g_clear_pointer (&data->ppd_file_name, g_free);
992 }
993
994 output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
995 res,
996 &error);
997
998 if (output)
999 {
1000 g_autoptr(GVariant) array = NULL;
1001 g_autoptr(GVariantIter) iter = NULL;
1002 const gchar *executable;
1003
1004 g_variant_get (output, "(@as)", &array);
1005
1006 g_variant_get (array, "as", &iter);
1007 while (g_variant_iter_next (iter, "&s", &executable))
1008 executables = g_list_append (executables, g_strdup (executable));
1009 }
1010 else if (error->domain == G_DBUS_ERROR &&
1011 (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1012 error->code == G_DBUS_ERROR_UNKNOWN_METHOD))
1013 {
1014 g_warning ("Install system-config-printer which provides \
1015 DBus method \"MissingExecutables\" to find missing executables and filters.");
1016 }
1017 else
1018 {
1019 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1020 g_warning ("%s", error->message);
1021 }
1022
1023 executables = g_list_sort (executables, (GCompareFunc) g_strcmp0);
1024 executables = glist_uniq (executables);
1025
1026 if (executables)
1027 {
1028 data->executables = executables;
1029
1030 item = data->executables;
1031 g_dbus_connection_call (g_object_ref (G_DBUS_CONNECTION (source_object)),
1032 PACKAGE_KIT_BUS,
1033 PACKAGE_KIT_PATH,
1034 PACKAGE_KIT_QUERY_IFACE,
1035 "SearchFile",
1036 g_variant_new ("(ss)",
1037 (gchar *) item->data,
1038 ""),
1039 G_VARIANT_TYPE ("(bs)"),
1040 G_DBUS_CALL_FLAGS_NONE,
1041 DBUS_TIMEOUT_LONG,
1042 data->cancellable,
1043 search_files_cb,
1044 data);
1045
1046 data->executables = g_list_remove_link (data->executables, item);
1047 g_list_free_full (item, g_free);
1048 }
1049 else
1050 {
1051 install_missing_executables_cb (data);
1052 }
1053 }
1054
1055 static void
1056 printer_get_ppd_cb (const gchar *ppd_filename,
1057 gpointer user_data)
1058 {
1059 g_autoptr(GDBusConnection) bus = NULL;
1060 IMEData *data = (IMEData *) user_data;
1061 g_autoptr(GError) error = NULL;
1062
1063 data->ppd_file_name = g_strdup (ppd_filename);
1064 if (data->ppd_file_name)
1065 {
1066 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1067 if (!bus)
1068 {
1069 g_warning ("%s", error->message);
1070 }
1071 else
1072 {
1073 g_dbus_connection_call (bus,
1074 SCP_BUS,
1075 SCP_PATH,
1076 SCP_IFACE,
1077 "MissingExecutables",
1078 g_variant_new ("(s)", data->ppd_file_name),
1079 G_VARIANT_TYPE ("(as)"),
1080 G_DBUS_CALL_FLAGS_NONE,
1081 DBUS_TIMEOUT,
1082 data->cancellable,
1083 get_missing_executables_cb,
1084 data);
1085 return;
1086 }
1087 }
1088
1089 install_missing_executables_cb (data);
1090 }
1091
1092 static void
1093 pp_maintenance_command_execute_cb (GObject *source_object,
1094 GAsyncResult *res,
1095 gpointer user_data)
1096 {
1097 g_autoptr(GError) error = NULL;
1098 PCData *data;
1099 gboolean result;
1100
1101 result = pp_maintenance_command_execute_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error);
1102
1103 if (result)
1104 {
1105 data = (PCData *) user_data;
1106
1107 data->autoconfigure_finished = TRUE;
1108 printer_configure_async_finish (data);
1109 }
1110 else
1111 {
1112 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1113 {
1114 data = (PCData *) user_data;
1115
1116 g_warning ("%s", error->message);
1117
1118 data->autoconfigure_finished = TRUE;
1119 printer_configure_async_finish (data);
1120 }
1121 }
1122 }
1123
1124 static void
1125 printer_configure_async (PpNewPrinter *self)
1126 {
1127 g_autoptr(GDBusConnection) bus = NULL;
1128 PCData *data;
1129 IMEData *ime_data;
1130 gchar **values;
1131 g_autoptr(GError) error = NULL;
1132
1133 data = g_new0 (PCData, 1);
1134 data->new_printer = self;
1135 data->set_accept_jobs_finished = FALSE;
1136 data->set_enabled_finished = FALSE;
1137 data->autoconfigure_finished = FALSE;
1138 data->set_media_size_finished = FALSE;
1139 data->install_missing_executables_finished = FALSE;
1140
1141 /* Enable printer and make it accept jobs */
1142 if (self->name)
1143 {
1144 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
1145 if (bus)
1146 {
1147 g_dbus_connection_call (bus,
1148 MECHANISM_BUS,
1149 "/",
1150 MECHANISM_BUS,
1151 "PrinterSetAcceptJobs",
1152 g_variant_new ("(sbs)",
1153 self->name,
1154 TRUE,
1155 ""),
1156 G_VARIANT_TYPE ("(s)"),
1157 G_DBUS_CALL_FLAGS_NONE,
1158 -1,
1159 NULL,
1160 printer_set_accepting_jobs_cb,
1161 data);
1162
1163 g_dbus_connection_call (g_object_ref (bus),
1164 MECHANISM_BUS,
1165 "/",
1166 MECHANISM_BUS,
1167 "PrinterSetEnabled",
1168 g_variant_new ("(sb)",
1169 self->name,
1170 TRUE),
1171 G_VARIANT_TYPE ("(s)"),
1172 G_DBUS_CALL_FLAGS_NONE,
1173 -1,
1174 NULL,
1175 printer_set_enabled_cb,
1176 data);
1177 }
1178 else
1179 {
1180 g_warning ("Failed to get system bus: %s", error->message);
1181 data->set_accept_jobs_finished = TRUE;
1182 data->set_enabled_finished = TRUE;
1183 }
1184 }
1185 else
1186 {
1187 data->set_accept_jobs_finished = TRUE;
1188 data->set_enabled_finished = TRUE;
1189 }
1190
1191 /* Run autoconfiguration of printer */
1192 if (!self->is_network_device)
1193 {
1194 g_autoptr(PpMaintenanceCommand) command = NULL;
1195
1196 command = pp_maintenance_command_new (self->name,
1197 "autoconfigure",
1198 NULL,
1199 /* Translators: Name of job which makes printer to autoconfigure itself */
1200 _("Automatic configuration"));
1201
1202 pp_maintenance_command_execute_async (command,
1203 NULL,
1204 pp_maintenance_command_execute_cb,
1205 data);
1206 }
1207
1208 /* Set media size for printer */
1209 values = g_new0 (gchar *, 2);
1210 values[0] = g_strdup (get_page_size_from_locale ());
1211
1212 printer_add_option_async (self->name, "PageSize", values, FALSE, NULL, pao_cb, data);
1213
1214 g_strfreev (values);
1215
1216 /* Install missing executables for printer */
1217 ime_data = g_new0 (IMEData, 1);
1218 ime_data->window_id = self->window_id;
1219 if (data->cancellable)
1220 ime_data->cancellable = g_object_ref (data->cancellable);
1221 ime_data->user_data = data;
1222
1223 printer_get_ppd_async (self->name,
1224 NULL,
1225 0,
1226 printer_get_ppd_cb,
1227 ime_data);
1228 }
1229
1230 void
1231 pp_new_printer_add_async (PpNewPrinter *self,
1232 GCancellable *cancellable,
1233 GAsyncReadyCallback callback,
1234 gpointer user_data)
1235 {
1236 g_autoptr(GTask) task = NULL;
1237
1238 self->task = g_task_new (self, cancellable, callback, user_data);
1239 self->cancellable = g_object_ref (cancellable);
1240
1241 if (self->ppd_name || self->ppd_file_name)
1242 {
1243 /* We have everything we need */
1244 printer_add_real_async (self);
1245 }
1246 else if (self->device_id)
1247 {
1248 g_autoptr(GDBusConnection) bus = NULL;
1249 g_autoptr(GError) error = NULL;
1250
1251 /* Try whether CUPS has a driver for the new printer */
1252 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1253 if (bus)
1254 {
1255 g_dbus_connection_call (bus,
1256 SCP_BUS,
1257 SCP_PATH,
1258 SCP_IFACE,
1259 "GetBestDrivers",
1260 g_variant_new ("(sss)",
1261 self->device_id,
1262 self->make_and_model ? self->make_and_model : "",
1263 self->device_uri ? self->device_uri : ""),
1264 G_VARIANT_TYPE ("(a(ss))"),
1265 G_DBUS_CALL_FLAGS_NONE,
1266 DBUS_TIMEOUT_LONG,
1267 cancellable,
1268 printer_add_async_scb,
1269 self);
1270 }
1271 else
1272 {
1273 g_warning ("Failed to get system bus: %s", error->message);
1274 _pp_new_printer_add_async_cb (FALSE, self);
1275 }
1276 }
1277 else if (self->original_name && self->host_name)
1278 {
1279 /* Try to get PPD from remote CUPS */
1280 printer_get_ppd_async (self->original_name,
1281 self->host_name,
1282 self->host_port,
1283 printer_add_async_scb4,
1284 self);
1285 }
1286 else
1287 {
1288 _pp_new_printer_add_async_cb (FALSE, self);
1289 }
1290 }
1291
1292 gboolean
1293 pp_new_printer_add_finish (PpNewPrinter *self,
1294 GAsyncResult *res,
1295 GError **error)
1296 {
1297 g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
1298 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1299 return g_task_propagate_boolean (G_TASK (res), error);
1300 }
1301