~ubuntu-branches/ubuntu/utopic/gnome-control-center/utopic-proposed

« back to all changes in this revision

Viewing changes to panels/printers/pp-utils.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher, Sebastien Bacher, Robert Ancell, Iain Lane, Edward Donovan, Rico Tzschichholz, Jeremy Bicha, David Henningsson
  • Date: 2012-11-21 19:32:45 UTC
  • mfrom: (1.1.63)
  • Revision ID: package-import@ubuntu.com-20121121193245-mj61nzz1z4fk3z25
Tags: 1:3.6.3-0ubuntu1
[ Sebastien Bacher ]
* New upstream version
* debian/control.in: recommends libcanberra-pulse (lp: #1004973)
* debian/patches/58_ubuntu_icon_views_redesign.patch:
  - drop most of the changes, keep the different grid size though
    to fit on screen with our extra icons
* debian/patches/91_dont_show_in_unity.patch:
  - dropped, show the upstream printer panel and the layout tab
* debian/patches/revert_git_keyboard_gsettings.patch,
  debian/patches/revert_git_stop_using_gconf.patch:
  - dropped the gconf->gsettings reverts

[ Robert Ancell ]
* New upstream release (LP: #1010317)
* debian/control:
  - Bump build-depends on libgnome-desktop-3-dev, libwacom-dev
  - Add build-depends on libclutter-1.0-dev, libclutter-gtk-1.0-dev,
    libpwquality-dev
  - Drop build-depends on libgnomekbd-dev
* debian/patches/60_ubuntu_nav_bar.patch:
  - Disabled for now, doesn't apply
* debian/patches/revert_ua_gsettings.patch:
  - We can use GSettings for universal access now
* debian/patches/00git_online_accounts_gtkgrid.patch:
* debian/patches/00git_online_accounts_layout.part:
* debian/patches/git_wacom_translations.patch:
  - Applied upstream

[ Iain Lane ]
* Add Build-Depends on libxkbfile-dev
* New upstream release.
* Refresh all patches to apply cleanly.

[ Edward Donovan ]
* debian/source_gnome-control-center.py: Fix for Python 3. (LP: #1013171)

[ Rico Tzschichholz ]
* debian/control.in:
  - Build-depend on gtk-doc-tools instead of docbook directly
  - Bump minimum glib-2.0, gnome-desktop3, gnome-settings-daemon
     and gsettings-desktop-schemas

[ Jeremy Bicha ]
* Dropped more patches applied in new version:
  - git_unmute_sound_event.patch
  - git_fix_big_editable_labels.patch
  - 96_sound_nua_panel.patch
* debian/patches/04_new_appearance_settings.patch:
  - Dropped, this is now packaged separately as gnome-control-center-unity
* debian/patches/10_keyboard_layout_on_unity.patch:
  - Don't change the keyboard panel name when not running Unity
* debian/patches/52_ubuntu_language_list_mods.patch:
  - Don't disable adding current language to the list. While this
    fix shows the current language twice, at least it avoids the
    "Ubuntu suddenly in Chinese" bug (LP: #1035219)
* debian/patches/53_use_ubuntu_help.patch:
  - Only show Ubuntu help when running Unity
* debian/patches/58_hide_gdm_notifications.patch:
  - Hide "Show notifications when locked" settings when running Unity
    since it's a GNOME Shell-specific feature
* debian/patches/63_normal_scrollbar_in_a11y.patch:
  - Drop, overlay-scrollbars should handle this instead
* debian/patches/91_dont_show_in_unity.patch:
  - Hide Printers & Region panels in Unity until we're ready to switch
    to them.
* debian/patches/fix-crash-on-user-panel.patch:
  - Dropped, GNOME says it's obsolete
* debian/rules:
  - Build with -z,defs again
  - Explicitly disable ibus support since ibus 1.4 isn't supported in
    this version
* debian/control.in:
  - Drop ubuntu-docs and gnome-user-guide from recommends to suggests
  - Don't recommend indicators; let's leave that to Unity

[ David Henningsson ]
* sound_nua_panel.patch: Rebase to gnome 3.6 

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 3 of the License, or
 
7
 * the Free Software Foundation; either version 2 of the License, or
8
8
 * (at your option) any later version.
9
9
 *
10
10
 * This program is distributed in the hope that it will be useful,
29
29
 
30
30
#include "pp-utils.h"
31
31
 
32
 
#define MECHANISM_BUS "org.opensuse.CupsPkHelper.Mechanism"
33
 
 
34
 
#define SCP_BUS   "org.fedoraproject.Config.Printing"
35
 
#define SCP_PATH  "/org/fedoraproject/Config/Printing"
36
 
#define SCP_IFACE "org.fedoraproject.Config.Printing"
 
32
#define DBUS_TIMEOUT      120000
 
33
#define DBUS_TIMEOUT_LONG 600000
37
34
 
38
35
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
39
36
#define HAVE_CUPS_1_6 1
47
44
#define ippGetStatusCode(ipp) ipp->request.status.status_code
48
45
#define ippGetInteger(attr, element) attr->values[element].integer
49
46
#define ippGetString(attr, element, language) attr->values[element].string.text
 
47
#define ippGetBoolean(attr, element) attr->values[element].boolean
 
48
 
 
49
static int
 
50
ippGetRange (ipp_attribute_t *attr,
 
51
             int element,
 
52
             int *upper)
 
53
{
 
54
  *upper = attr->values[element].range.upper;
 
55
  return (attr->values[element].range.lower);
 
56
}
50
57
 
51
58
static ipp_attribute_t *
52
 
ippFirstAttribute(ipp_t *ipp)
 
59
ippFirstAttribute (ipp_t *ipp)
53
60
{
54
61
  if (!ipp)
55
62
    return (NULL);
57
64
}
58
65
 
59
66
static ipp_attribute_t *
60
 
ippNextAttribute(ipp_t *ipp)
 
67
ippNextAttribute (ipp_t *ipp)
61
68
{
62
69
  if (!ipp || !ipp->current)
63
70
    return (NULL);
93
100
}
94
101
 
95
102
 
96
 
typedef struct
97
 
{
98
 
  gchar *ppd_name;
99
 
  gchar *ppd_device_id;
100
 
  gchar *ppd_product;
101
 
  gchar *ppd_make_and_model;
102
 
 
103
 
  gchar *driver_type;
104
 
 
105
 
  gchar *mfg;
106
 
  gchar *mdl;
107
 
  gint   match_level;
108
 
  gint   preference_value;
109
 
} PPDItem;
110
 
 
111
 
 
112
 
static void
113
 
ppd_item_free (PPDItem *item)
114
 
{
115
 
  if (item)
116
 
    {
117
 
      g_free (item->ppd_name);
118
 
      g_free (item->ppd_device_id);
119
 
      g_free (item->ppd_product);
120
 
      g_free (item->ppd_make_and_model);
121
 
      g_free (item->driver_type);
122
 
      g_free (item->mfg);
123
 
      g_free (item->mdl);
124
 
    }
125
 
}
126
 
 
127
 
static PPDItem *
128
 
ppd_item_copy (PPDItem *item)
129
 
{
130
 
  PPDItem *result = NULL;
131
 
 
132
 
  result = g_new0 (PPDItem, 1);
133
 
  if (item && result)
134
 
    {
135
 
      result->ppd_name = g_strdup (item->ppd_name);
136
 
      result->ppd_device_id = g_strdup (item->ppd_device_id);
137
 
      result->ppd_product = g_strdup (item->ppd_product);
138
 
      result->ppd_make_and_model = g_strdup (item->ppd_make_and_model);
139
 
      result->driver_type = g_strdup (item->driver_type);
140
 
      result->mfg = g_strdup (item->mfg);
141
 
      result->mdl = g_strdup (item->mdl);
142
 
      result->match_level = item->match_level;
143
 
      result->preference_value = item->preference_value;
144
 
    }
145
 
 
146
 
  return result;
147
 
}
148
 
 
149
 
 
150
 
/*
151
 
 * Make deep copy of given const string array.
152
 
 */
153
 
static gchar **
154
 
strvdup (const gchar * const x[])
155
 
{
156
 
  gint i, length = 0;
157
 
  gchar **result;
158
 
 
159
 
  for (length = 0; x && x[length]; length++);
160
 
 
161
 
  length++;
162
 
 
163
 
  result = g_new0 (gchar *, length);
164
 
  for (i = 0; i < length; i++)
165
 
    result[i] = g_strdup (x[i]);
166
 
 
167
 
  return result;
168
 
}
169
 
 
170
103
/*
171
104
 * Normalize given string so that it is lowercase, doesn't
172
105
 * have trailing or leading whitespaces and digits doesn't
228
161
}
229
162
 
230
163
 
231
 
/*
232
 
 * Find out type of the given printer driver.
233
 
 * (see xml/preferreddrivers.xml from system-config-printer)
234
 
 */
235
 
static gchar *
236
 
get_driver_type (gchar *ppd_name,
237
 
                 gchar *ppd_device_id,
238
 
                 gchar *ppd_make_and_model,
239
 
                 gchar *ppd_product,
240
 
                 gint   match_level)
241
 
{
242
 
  gchar *tmp = NULL;
243
 
 
244
 
  if (match_level == PPD_GENERIC_MATCH)
245
 
    {
246
 
      if (ppd_name && g_regex_match_simple ("(foomatic(-db-compressed-ppds)?|ijsgutenprint.*):", ppd_name, 0, 0))
247
 
        {
248
 
          tmp = get_tag_value ("DRV", ppd_device_id);
249
 
          if (tmp && g_regex_match_simple (".*,?R1", tmp, 0, 0))
250
 
            return g_strdup ("generic-foomatic-recommended");
251
 
        }
252
 
    }
253
 
 
254
 
  if (match_level == PPD_GENERIC_MATCH || match_level == PPD_NO_MATCH)
255
 
    {
256
 
      if (ppd_name && g_regex_match_simple ("(foomatic(-db-compressed-ppds)?|ijsgutenprint.*):Generic-ESC_P", ppd_name, 0, 0))
257
 
        return g_strdup ("generic-escp");
258
 
 
259
 
      if (ppd_name && g_regex_match_simple ("drv:///sample.drv/epson(9|24).ppd", ppd_name, 0, 0))
260
 
        return g_strdup ("generic-escp");
261
 
 
262
 
      if (g_strcmp0 (ppd_make_and_model, "Generic PostScript Printer") == 0)
263
 
        return g_strdup ("generic-postscript");
264
 
 
265
 
      if (g_strcmp0 (ppd_make_and_model, "Generic PCL 6 Printer") == 0)
266
 
        return g_strdup ("generic-pcl6");
267
 
 
268
 
      if (g_strcmp0 (ppd_make_and_model, "Generic PCL 5e Printer") == 0)
269
 
        return g_strdup ("generic-pcl5e");
270
 
 
271
 
      if (g_strcmp0 (ppd_make_and_model, "Generic PCL 5 Printer") == 0)
272
 
        return g_strdup ("generic-pcl5");
273
 
 
274
 
      if (g_strcmp0 (ppd_make_and_model, "Generic PCL Laser Printer") == 0)
275
 
        return g_strdup ("generic-pcl");
276
 
 
277
 
      return g_strdup ("generic");
278
 
    }
279
 
 
280
 
 
281
 
  if (ppd_name && g_regex_match_simple ("drv:///sample.drv/", ppd_name, 0, 0))
282
 
    return g_strdup ("cups");
283
 
 
284
 
  if (ppd_product && g_regex_match_simple (".*Ghostscript", ppd_product, 0, 0))
285
 
    return g_strdup ("ghostscript");
286
 
 
287
 
  if (ppd_name && g_regex_match_simple ("gutenprint.*:.*/simple|.*-gutenprint.*\\.sim", ppd_name, 0, 0))
288
 
    return g_strdup ("gutenprint-simplified");
289
 
 
290
 
  if (ppd_name && g_regex_match_simple ("gutenprint.*:|.*-gutenprint", ppd_name, 0, 0))
291
 
    return g_strdup ("gutenprint-expert");
292
 
 
293
 
  if (ppd_make_and_model && g_regex_match_simple (".* Foomatic/hpijs", ppd_make_and_model, 0, 0))
294
 
    {
295
 
      tmp = get_tag_value ("DRV", ppd_device_id);
296
 
      if (tmp && g_regex_match_simple (",?R1", tmp, 0, 0))
297
 
        return g_strdup ("foomatic-recommended-hpijs");
298
 
    }
299
 
 
300
 
  if (ppd_make_and_model && g_regex_match_simple (".* Foomatic/hpijs", ppd_make_and_model, 0, 0))
301
 
    return g_strdup ("foomatic-hpijs");
302
 
 
303
 
  if (ppd_name && g_regex_match_simple ("foomatic(-db-compressed-ppds)?:", ppd_name, 0, 0) &&
304
 
      ppd_make_and_model && g_regex_match_simple (".* Postscript", ppd_make_and_model, 0, 0))
305
 
    {
306
 
      tmp = get_tag_value ("DRV", ppd_device_id);
307
 
      if (tmp && g_regex_match_simple (".*,?R1", tmp, 0, 0))
308
 
        return g_strdup ("foomatic-recommended-postscript");
309
 
    }
310
 
 
311
 
  if (ppd_name && g_regex_match_simple ("foomatic(-db-compressed-ppds)?:.*-Postscript", ppd_name, 0, 0))
312
 
    return g_strdup ("foomatic-postscript");
313
 
 
314
 
  if (ppd_make_and_model && g_regex_match_simple (".* Foomatic/pxlmono", ppd_make_and_model, 0, 0))
315
 
    return g_strdup ("foomatic-pxlmono");
316
 
 
317
 
  if (ppd_name && g_regex_match_simple ("(foomatic(-db-compressed-ppds)?|ijsgutenprint.*):", ppd_name, 0, 0))
318
 
    {
319
 
      tmp = get_tag_value ("DRV", ppd_device_id);
320
 
      if (tmp && g_regex_match_simple (".*,?R1", tmp, 0, 0))
321
 
        return g_strdup ("foomatic-recommended-non-postscript");
322
 
    }
323
 
 
324
 
  if (ppd_name && g_regex_match_simple ("(foomatic(-db-compressed-ppds)?|ijsgutenprint.*):.*-gutenprint", ppd_name, 0, 0))
325
 
    return g_strdup ("foomatic-gutenprint");
326
 
 
327
 
  if (ppd_name && g_regex_match_simple ("(foomatic(-db-compressed-ppds)?|ijsgutenprint.*):", ppd_name, 0, 0))
328
 
    return g_strdup ("foomatic");
329
 
 
330
 
  if (ppd_name && g_regex_match_simple ("drv:///(hp/)?hpcups.drv/|.*-hpcups", ppd_name, 0, 0) &&
331
 
      ppd_make_and_model && g_regex_match_simple (".* plugin", ppd_make_and_model, 0, 0))
332
 
    return g_strdup ("hpcups-plugin");
333
 
 
334
 
  if (ppd_name && g_regex_match_simple ("drv:///(hp/)?hpcups.drv/|.*-hpcups", ppd_name, 0, 0))
335
 
    return g_strdup ("hpcups");
336
 
 
337
 
  if (ppd_name && g_regex_match_simple ("drv:///(hp/)?hpijs.drv/|.*-hpijs", ppd_name, 0, 0) &&
338
 
      ppd_make_and_model && g_regex_match_simple (".* plugin", ppd_make_and_model, 0, 0))
339
 
    return g_strdup ("hpijs-plugin");
340
 
 
341
 
  if (ppd_name && g_regex_match_simple ("drv:///(hp/)?hpijs.drv/|.*-hpijs", ppd_name, 0, 0))
342
 
    return g_strdup ("hpijs");
343
 
 
344
 
  if (ppd_name && g_regex_match_simple (".*splix", ppd_name, 0, 0))
345
 
    return g_strdup ("splix");
346
 
 
347
 
  if (ppd_name && g_regex_match_simple (".*turboprint", ppd_name, 0, 0))
348
 
    return g_strdup ("turboprint");
349
 
 
350
 
  if (ppd_name && g_regex_match_simple (".*/(Ricoh|Lanier|Gestetner|InfoPrint|Infotech|Savin|NRG)/PS/", ppd_name, 0, 0))
351
 
    return g_strdup ("manufacturer-ricoh-postscript");
352
 
 
353
 
  if (ppd_name && g_regex_match_simple (".*/(Ricoh|Lanier|Gestetner|InfoPrint|Infotech|Savin|NRG)/PXL/", ppd_name, 0, 0))
354
 
    return g_strdup ("manufacturer-ricoh-pxl");
355
 
 
356
 
  if (match_level == PPD_EXACT_CMD_MATCH)
357
 
    return g_strdup ("manufacturer-cmd");
358
 
 
359
 
  return g_strdup ("manufacturer");
360
 
}
361
 
 
362
 
 
363
 
/*
364
 
 * Return preference value. The most preferred driver has the lowest value.
365
 
 * If the value is higher or equal to 1000 then try to avoid installation
366
 
 * of this driver. If it is higher or equal to 2000 then don't install
367
 
 * this driver.
368
 
 * (see xml/preferreddrivers.xml from system-config-printer)
369
 
 */
370
 
static gint
371
 
get_driver_preference (PPDItem *item)
372
 
{
373
 
  gchar   *tmp1 = NULL;
374
 
  gchar   *tmp2 = NULL;
375
 
  gint     result = 0;
376
 
 
377
 
  if (item && item->ppd_make_and_model &&
378
 
      g_regex_match_simple ("Brother HL-2030", item->ppd_make_and_model, 0, 0))
379
 
    {
380
 
      tmp1 = get_tag_value ("MFG", item->ppd_device_id);
381
 
      tmp2 = get_tag_value ("MDL", item->ppd_device_id);
382
 
 
383
 
      if (tmp1 && g_regex_match_simple ("Brother", tmp1, 0, 0) &&
384
 
          tmp2 && g_regex_match_simple ("HL-2030", tmp2, 0, 0))
385
 
        {
386
 
          if (item->driver_type && g_regex_match_simple ("gutenprint*", item->driver_type, 0, 0))
387
 
            return result + 2000;
388
 
          else
389
 
            return result;
390
 
        }
391
 
    }
392
 
  result++;
393
 
 
394
 
  if (item && item->ppd_make_and_model &&
395
 
      g_regex_match_simple ("(Ricoh|Lanier|Gestetner|InfoPrint|Infotech|Savin|NRG) ", item->ppd_make_and_model, 0, 0))
396
 
    {
397
 
      tmp1 = get_tag_value ("MFG", item->ppd_device_id);
398
 
 
399
 
      if (tmp1 && g_regex_match_simple ("(Ricoh|Lanier|Gestetner|InfoPrint|Infotech|Savin|NRG)", tmp1, 0, 0) &&
400
 
          ((g_strcmp0 (item->driver_type, "manufacturer-ricoh-postscript") == 0) ||
401
 
           (g_strcmp0 (item->driver_type, "manufacturer-ricoh-pxl") == 0)))
402
 
        return result;
403
 
    }
404
 
  result++;
405
 
 
406
 
  if (item && item->ppd_make_and_model &&
407
 
      g_regex_match_simple ("Xerox 6250DP", item->ppd_make_and_model, 0, 0))
408
 
    {
409
 
      tmp1 = get_tag_value ("MFG", item->ppd_device_id);
410
 
      tmp2 = get_tag_value ("MDL", item->ppd_device_id);
411
 
 
412
 
      if (tmp1 && g_regex_match_simple ("Xerox", tmp1, 0, 0) &&
413
 
          tmp2 && g_regex_match_simple ("6250DP", tmp2, 0, 0))
414
 
        {
415
 
          if (item->driver_type && g_regex_match_simple ("gutenprint*", item->driver_type, 0, 0))
416
 
            return result + 1000;
417
 
          else
418
 
            return result;
419
 
        }
420
 
    }
421
 
  result++;
422
 
 
423
 
  if (item && g_strcmp0 (item->driver_type, "manufacturer-cmd") == 0)
424
 
    return result;
425
 
  result++;
426
 
 
427
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-recommended-hpijs") == 0)
428
 
    return result;
429
 
  result++;
430
 
 
431
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-recommended-non-postscript") == 0)
432
 
    return result;
433
 
  result++;
434
 
 
435
 
  if (item && item->driver_type &&
436
 
      g_regex_match_simple ("manufacturer*", item->driver_type, 0, 0))
437
 
    return result;
438
 
  result++;
439
 
 
440
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-recommended-postscript") == 0)
441
 
    return result;
442
 
  result++;
443
 
 
444
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-postscript") == 0)
445
 
    return result;
446
 
  result++;
447
 
 
448
 
  if (item && g_strcmp0 (item->driver_type, "hpcups") == 0)
449
 
    return result;
450
 
  result++;
451
 
 
452
 
  if (item && g_strcmp0 (item->driver_type, "hpijs") == 0)
453
 
    return result;
454
 
  result++;
455
 
 
456
 
  if (item && item->ppd_make_and_model &&
457
 
      g_regex_match_simple ("(HP|Hewlett-Packard) ", item->ppd_make_and_model, 0, 0))
458
 
    {
459
 
      tmp1 = get_tag_value ("MFG", item->ppd_device_id);
460
 
 
461
 
      if (tmp1 && g_regex_match_simple ("HP|Hewlett-Packard", tmp1, 0, 0) &&
462
 
          g_strcmp0 (item->driver_type, "foomatic-hpijs") == 0)
463
 
        return result;
464
 
    }
465
 
  result++;
466
 
 
467
 
  if (item && g_strcmp0 (item->driver_type, "gutenprint-simplified") == 0)
468
 
    return result;
469
 
  result++;
470
 
 
471
 
  if (item && g_strcmp0 (item->driver_type, "gutenprint-expert") == 0)
472
 
    return result;
473
 
  result++;
474
 
 
475
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-hpijs") == 0)
476
 
    return result;
477
 
  result++;
478
 
 
479
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-gutenprint") == 0)
480
 
    return result;
481
 
  result++;
482
 
 
483
 
  if (item && g_strcmp0 (item->driver_type, "foomatic") == 0)
484
 
    return result;
485
 
  result++;
486
 
 
487
 
  if (item && g_strcmp0 (item->driver_type, "cups") == 0)
488
 
    return result;
489
 
  result++;
490
 
 
491
 
  if (item && g_strcmp0 (item->driver_type, "generic-postscript") == 0)
492
 
    return result;
493
 
  result++;
494
 
 
495
 
  if (item && g_strcmp0 (item->driver_type, "generic-foomatic-recommended") == 0)
496
 
    return result;
497
 
  result++;
498
 
 
499
 
  if (item && g_strcmp0 (item->driver_type, "generic-pcl6") == 0)
500
 
    return result;
501
 
  result++;
502
 
 
503
 
  if (item && g_strcmp0 (item->driver_type, "generic-pcl5c") == 0)
504
 
    return result;
505
 
  result++;
506
 
 
507
 
  if (item && g_strcmp0 (item->driver_type, "generic-pcl5e") == 0)
508
 
    return result;
509
 
  result++;
510
 
 
511
 
  if (item && g_strcmp0 (item->driver_type, "generic-pcl5") == 0)
512
 
    return result;
513
 
  result++;
514
 
 
515
 
  if (item && g_strcmp0 (item->driver_type, "generic-pcl") == 0)
516
 
    return result;
517
 
  result++;
518
 
 
519
 
  if (item && g_strcmp0 (item->driver_type, "foomatic-pxlmono") == 0)
520
 
    return result;
521
 
  result++;
522
 
 
523
 
  if (item && g_strcmp0 (item->driver_type, "generic-escp") == 0)
524
 
    return result;
525
 
  result++;
526
 
 
527
 
  if (item && g_strcmp0 (item->driver_type, "ghostscript") == 0)
528
 
    return result;
529
 
  result++;
530
 
 
531
 
  if (item && g_strcmp0 (item->driver_type, "generic") == 0)
532
 
    return result;
533
 
  result++;
534
 
 
535
 
  if (item && g_strcmp0 (item->driver_type, "hpcups-plugin") == 0)
536
 
    return result;
537
 
  result++;
538
 
 
539
 
  if (item && g_strcmp0 (item->driver_type, "hpijs-plugin") == 0)
540
 
    return result;
541
 
  result++;
542
 
 
543
 
  if (item && g_strcmp0 (item->driver_type, "splix") == 0)
544
 
    return result;
545
 
  result++;
546
 
 
547
 
  if (item && g_strcmp0 (item->driver_type, "turboprint") == 0)
548
 
    return result;
549
 
  result++;
550
 
 
551
 
  return result;
552
 
}
553
 
 
554
 
 
555
 
/*
556
 
 * Compare driver types according to preference order.
557
 
 * The most preferred driver is the lowest one.
558
 
 * (see xml/preferreddrivers.xml from system-config-printer)
559
 
 */
560
 
static gint
561
 
preference_value_cmp (gconstpointer a,
562
 
                      gconstpointer b)
563
 
{
564
 
  PPDItem *c = (PPDItem *) a;
565
 
  PPDItem *d = (PPDItem *) b;
566
 
 
567
 
  if (c == NULL && d == NULL)
568
 
    return 0;
569
 
  else if (c == NULL)
570
 
    return -1;
571
 
  else if (d == NULL)
572
 
    return 1;
573
 
 
574
 
  if (c->preference_value < d->preference_value)
575
 
    return -1;
576
 
  else if (c->preference_value > d->preference_value)
577
 
    return 1;
578
 
  else
579
 
    return 0;
580
 
}
581
 
 
582
 
 
583
 
/* Compare PPDItems a and b according to normalized model name */
584
 
static gint
585
 
item_cmp (gconstpointer a,
586
 
          gconstpointer b)
587
 
{
588
 
  PPDItem *c = (PPDItem *) a;
589
 
  PPDItem *d = (PPDItem *) b;
590
 
  glong   a_number;
591
 
  glong   b_number;
592
 
  gchar  *a_normalized = NULL;
593
 
  gchar  *b_normalized = NULL;
594
 
  gchar **av = NULL;
595
 
  gchar **bv = NULL;
596
 
  gint    a_length = 0;
597
 
  gint    b_length = 0;
598
 
  gint    min_length;
599
 
  gint    result = 0;
600
 
  gint    i;
601
 
 
602
 
  if (c && d)
603
 
    {
604
 
      a_normalized = normalize (c->mdl);
605
 
      b_normalized = normalize (d->mdl);
606
 
 
607
 
      if (a_normalized)
608
 
        av = g_strsplit (a_normalized, " ", 0);
609
 
 
610
 
      if (b_normalized)
611
 
        bv = g_strsplit (b_normalized, " ", 0);
612
 
 
613
 
      if (av)
614
 
        a_length = g_strv_length (av);
615
 
 
616
 
      if (bv)
617
 
        b_length = g_strv_length (bv);
618
 
 
619
 
      min_length = a_length < b_length ? a_length : b_length;
620
 
 
621
 
      for (i = 0; i < min_length; i++)
622
 
        {
623
 
          if (g_ascii_isdigit (av[i][0]) && g_ascii_isdigit (bv[i][0]))
624
 
            {
625
 
              a_number = atol (av[i]);
626
 
              b_number = atol (bv[i]);
627
 
              if (a_number < b_number)
628
 
                {
629
 
                  result = -1;
630
 
                  goto out;
631
 
                }
632
 
              else if (a_number > b_number)
633
 
                {
634
 
                  result = 1;
635
 
                  goto out;
636
 
                }
637
 
            }
638
 
          else if (g_ascii_isdigit (av[i][0]) && !g_ascii_isdigit (bv[i][0]))
639
 
            {
640
 
              result = -1;
641
 
              goto out;
642
 
            }
643
 
          else if (!g_ascii_isdigit (av[i][0]) && g_ascii_isdigit (bv[i][0]))
644
 
            {
645
 
              result = 1;
646
 
              goto out;
647
 
            }
648
 
          else
649
 
            {
650
 
              if (g_strcmp0 (av[i], bv[i]) != 0)
651
 
                {
652
 
                  result = g_strcmp0 (av[i], bv[i]);
653
 
                  goto out;
654
 
                }
655
 
            }
656
 
        }
657
 
 
658
 
      if (a_length < b_length)
659
 
        result = -1;
660
 
      else if (a_length > b_length)
661
 
        result = 1;
662
 
    }
663
 
 
664
 
out:
665
 
  if (av)
666
 
    g_strfreev (av);
667
 
 
668
 
  if (bv)
669
 
    g_strfreev (bv);
670
 
 
671
 
  g_free (a_normalized);
672
 
  g_free (b_normalized);
673
 
 
674
 
  return result;
675
 
}
676
 
 
677
 
 
678
 
static gint
679
 
get_prefix_length (gchar *a, gchar *b)
680
 
{
681
 
  gint a_length;
682
 
  gint b_length;
683
 
  gint min_length;
684
 
  gint i;
685
 
 
686
 
  if (a && b)
687
 
    {
688
 
      a_length = strlen (a);
689
 
      b_length = strlen (b);
690
 
      min_length = a_length < b_length ? a_length : b_length;
691
 
 
692
 
      for (i = 0; i < min_length; i++)
693
 
        {
694
 
          if (a[i] != b[i])
695
 
            return i;
696
 
        }
697
 
      return min_length;
698
 
    }
699
 
 
700
 
  return 0;
701
 
}
702
 
 
703
 
 
704
 
/*
705
 
 * Append best matching ppds from list "ppds" to list "list"
706
 
 * according to model name "model". Return the resulting list.
707
 
 */
708
 
static GList *
709
 
append_best_ppds (GList *list,
710
 
                  GList *ppds,
711
 
                  gchar *model)
712
 
{
713
 
  PPDItem *item;
714
 
  PPDItem *tmp_item;
715
 
  PPDItem *best_item = NULL;
716
 
  gchar   *mdl_normalized;
717
 
  gchar   *mdl;
718
 
  gchar   *tmp;
719
 
  GList   *local_ppds;
720
 
  GList   *actual_item;
721
 
  GList   *candidates = NULL;
722
 
  GList   *tmp_list = NULL;
723
 
  GList   *result = NULL;
724
 
  gint     best_prefix_length = -1;
725
 
  gint     prefix_length;
726
 
 
727
 
  result = list;
728
 
 
729
 
  if (model)
730
 
    {
731
 
      mdl = g_ascii_strdown (model, -1);
732
 
      if (g_str_has_suffix (mdl, " series"))
733
 
        {
734
 
          tmp = g_strndup (mdl, strlen (mdl) - 7);
735
 
          g_free (mdl);
736
 
          mdl = tmp;
737
 
        }
738
 
 
739
 
      mdl_normalized = normalize (mdl);
740
 
 
741
 
      item = g_new0 (PPDItem, 1);
742
 
      item->ppd_device_id = g_strdup_printf ("mdl:%s;", mdl);
743
 
      item->mdl = mdl_normalized;
744
 
 
745
 
      local_ppds = g_list_copy (ppds);
746
 
      local_ppds = g_list_append (local_ppds, item);
747
 
      local_ppds = g_list_sort (local_ppds, item_cmp);
748
 
 
749
 
      actual_item = g_list_find (local_ppds, item);
750
 
      if (actual_item)
751
 
        {
752
 
          if (actual_item->prev)
753
 
            candidates = g_list_append (candidates, actual_item->prev->data);
754
 
          if (actual_item->next)
755
 
            candidates = g_list_append (candidates, actual_item->next->data);
756
 
        }
757
 
 
758
 
      for (tmp_list = candidates; tmp_list; tmp_list = tmp_list->next)
759
 
        {
760
 
          tmp_item = (PPDItem *) tmp_list->data;
761
 
 
762
 
          prefix_length = get_prefix_length (tmp_item->mdl, mdl_normalized);
763
 
          if (prefix_length > best_prefix_length)
764
 
            {
765
 
              best_prefix_length = prefix_length;
766
 
              best_item = tmp_item;
767
 
            }
768
 
        }
769
 
 
770
 
      if (best_item && best_prefix_length > strlen (mdl_normalized) / 2)
771
 
        {
772
 
          if (best_prefix_length == strlen (mdl_normalized))
773
 
            best_item->match_level = PPD_EXACT_MATCH;
774
 
          else
775
 
            best_item->match_level = PPD_CLOSE_MATCH;
776
 
 
777
 
          result = g_list_append (result, ppd_item_copy (best_item));
778
 
        }
779
 
      else
780
 
        {
781
 
          /* TODO the last resort (see _findBestMatchPPDs() in ppds.py) */
782
 
        }
783
 
 
784
 
      g_list_free (candidates);
785
 
      g_list_free (local_ppds);
786
 
 
787
 
      g_free (item->ppd_device_id);
788
 
      g_free (item);
789
 
      g_free (mdl);
790
 
      g_free (mdl_normalized);
791
 
    }
792
 
 
793
 
  return result;
794
 
}
795
 
 
796
 
/*
797
 
 * Return the best matching driver name
798
 
 * for device described by given parameters.
799
 
 */
800
 
PPDName *
801
 
get_ppd_name (gchar *device_id,
802
 
              gchar *device_make_and_model,
803
 
              gchar *device_uri)
804
 
{
805
 
  GDBusConnection *bus;
806
 
  GVariant   *output;
807
 
  GVariant   *array;
808
 
  GVariant   *tuple;
809
 
  PPDName    *result = NULL;
810
 
  GError     *error = NULL;
811
 
  gchar      *name, *match;
812
 
  gint        i, j;
813
 
  static const char * const match_levels[] = {
814
 
             "exact-cmd",
815
 
             "exact",
816
 
             "close",
817
 
             "generic",
818
 
             "none"};
819
 
 
820
 
  bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
821
 
  if (bus)
822
 
    {
823
 
      output = g_dbus_connection_call_sync (bus,
824
 
                                            SCP_BUS,
825
 
                                            SCP_PATH,
826
 
                                            SCP_IFACE,
827
 
                                            "GetBestDrivers",
828
 
                                            g_variant_new ("(sss)",
829
 
                                                           device_id ? device_id : "",
830
 
                                                           device_make_and_model ? device_make_and_model : "",
831
 
                                                           device_uri ? device_uri : ""),
832
 
                                            NULL,
833
 
                                            G_DBUS_CALL_FLAGS_NONE,
834
 
                                            60000,
835
 
                                            NULL,
836
 
                                            &error);
837
 
 
838
 
      if (output && g_variant_n_children (output) >= 1)
839
 
        {
840
 
          array = g_variant_get_child_value (output, 0);
841
 
          if (array)
842
 
            for (j = 0; j < G_N_ELEMENTS (match_levels) && result == NULL; j++)
843
 
              for (i = 0; i < g_variant_n_children (array) && result == NULL; i++)
844
 
                {
845
 
                  tuple = g_variant_get_child_value (array, i);
846
 
                  if (tuple && g_variant_n_children (tuple) == 2)
847
 
                    {
848
 
                      name = g_strdup (g_variant_get_string (
849
 
                                         g_variant_get_child_value (tuple, 0),
850
 
                                         NULL));
851
 
                      match = g_strdup (g_variant_get_string (
852
 
                                          g_variant_get_child_value (tuple, 1),
853
 
                                          NULL));
854
 
 
855
 
                      if (g_strcmp0 (match, match_levels[j]) == 0)
856
 
                        {
857
 
                          result = g_new0 (PPDName, 1);
858
 
                          result->ppd_name = g_strdup (name);
859
 
 
860
 
                          if (g_strcmp0 (match, "exact-cmd") == 0)
861
 
                            result->ppd_match_level = PPD_EXACT_CMD_MATCH;
862
 
                          else if (g_strcmp0 (match, "exact") == 0)
863
 
                            result->ppd_match_level = PPD_EXACT_MATCH;
864
 
                          else if (g_strcmp0 (match, "close") == 0)
865
 
                            result->ppd_match_level = PPD_CLOSE_MATCH;
866
 
                          else if (g_strcmp0 (match, "generic") == 0)
867
 
                            result->ppd_match_level = PPD_GENERIC_MATCH;
868
 
                          else if (g_strcmp0 (match, "none") == 0)
869
 
                            result->ppd_match_level = PPD_NO_MATCH;
870
 
                        }
871
 
 
872
 
                      g_free (match);
873
 
                      g_free (name);
874
 
                    }
875
 
                }
876
 
        }
877
 
 
878
 
      if (output)
879
 
        g_variant_unref (output);
880
 
      g_object_unref (bus);
881
 
    }
882
 
 
883
 
  if (bus == NULL ||
884
 
      (error &&
885
 
       error->domain == G_DBUS_ERROR &&
886
 
       (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
887
 
        error->code == G_DBUS_ERROR_UNKNOWN_METHOD)))
888
 
    {
889
 
      ipp_attribute_t *attr = NULL;
890
 
      const gchar     *hp_equivalents[] = {"hp", "hewlett packard", NULL};
891
 
      const gchar     *kyocera_equivalents[] = {"kyocera", "kyocera mita", NULL};
892
 
      const gchar     *toshiba_equivalents[] = {"toshiba", "toshiba tec corp.", NULL};
893
 
      const gchar     *lexmark_equivalents[] = {"lexmark", "lexmark international", NULL};
894
 
      gboolean         ppd_exact_match_found = FALSE;
895
 
      PPDItem         *item;
896
 
      http_t          *http = NULL;
897
 
      ipp_t           *request = NULL;
898
 
      ipp_t           *response = NULL;
899
 
      GList           *tmp_list;
900
 
      GList           *tmp_list2;
901
 
      GList           *mdls = NULL;
902
 
      GList           *list = NULL;
903
 
      gchar           *mfg_normalized = NULL;
904
 
      gchar           *mdl_normalized = NULL;
905
 
      gchar           *eq_normalized = NULL;
906
 
      gchar           *mfg = NULL;
907
 
      gchar           *mdl = NULL;
908
 
      gchar           *tmp = NULL;
909
 
      gchar           *ppd_device_id;
910
 
      gchar           *ppd_make_and_model;
911
 
      gchar           *ppd_name;
912
 
      gchar           *ppd_product;
913
 
      gchar          **equivalents = NULL;
914
 
      gint             i;
915
 
 
916
 
      g_warning ("You should install system-config-printer which provides \
917
 
DBus method \"GetBestDrivers\". Using fallback solution for now.");
918
 
      g_error_free (error);
919
 
 
920
 
      mfg = get_tag_value (device_id, "mfg");
921
 
      if (!mfg)
922
 
        mfg = get_tag_value (device_id, "manufacturer");
923
 
 
924
 
      mdl = get_tag_value (device_id, "mdl");
925
 
      if (!mdl)
926
 
        mdl = get_tag_value (device_id, "model");
927
 
 
928
 
      mfg_normalized = normalize (mfg);
929
 
      mdl_normalized = normalize (mdl);
930
 
 
931
 
      if (mfg_normalized && mfg)
932
 
        {
933
 
          if (g_str_has_prefix (mfg_normalized, "hewlett") ||
934
 
              g_str_has_prefix (mfg_normalized, "hp"))
935
 
            equivalents = strvdup (hp_equivalents);
936
 
 
937
 
          if (g_str_has_prefix (mfg_normalized, "kyocera"))
938
 
            equivalents = strvdup (kyocera_equivalents);
939
 
 
940
 
          if (g_str_has_prefix (mfg_normalized, "toshiba"))
941
 
            equivalents = strvdup (toshiba_equivalents);
942
 
 
943
 
          if (g_str_has_prefix (mfg_normalized, "lexmark"))
944
 
            equivalents = strvdup (lexmark_equivalents);
945
 
 
946
 
          if (equivalents == NULL)
947
 
            {
948
 
              equivalents = g_new0 (gchar *, 2);
949
 
              equivalents[0] = g_strdup (mfg);
950
 
            }
951
 
        }
952
 
 
953
 
      http = httpConnectEncrypt (cupsServer (),
954
 
                                 ippPort (),
955
 
                                 cupsEncryption ());
956
 
 
957
 
      /* Find usable drivers for given device */
958
 
      if (http)
959
 
        {
960
 
          /* Try exact match according to device-id */
961
 
          if (device_id)
962
 
            {
963
 
              request = ippNewRequest (CUPS_GET_PPDS);
964
 
              ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
965
 
                            "ppd-device-id", NULL, device_id);
966
 
              response = cupsDoRequest (http, request, "/");
967
 
 
968
 
              if (response &&
969
 
                  ippGetStatusCode (response) <= IPP_OK_CONFLICT)
970
 
                {
971
 
                  for (attr = ippFirstAttribute (response); attr != NULL; attr = ippNextAttribute (response))
972
 
                    {
973
 
                      while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
974
 
                        attr = ippNextAttribute (response);
975
 
 
976
 
                      if (attr == NULL)
977
 
                        break;
978
 
 
979
 
                      ppd_device_id = NULL;
980
 
                      ppd_make_and_model = NULL;
981
 
                      ppd_name = NULL;
982
 
                      ppd_product = NULL;
983
 
 
984
 
                      while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
985
 
                        {
986
 
                          if (g_strcmp0 (ippGetName (attr), "ppd-device-id") == 0 &&
987
 
                              ippGetValueTag (attr) == IPP_TAG_TEXT)
988
 
                            ppd_device_id = (gchar *) ippGetString (attr, 0, NULL);
989
 
                          else if (g_strcmp0 (ippGetName (attr), "ppd-make-and-model") == 0 &&
990
 
                                   ippGetValueTag (attr) == IPP_TAG_TEXT)
991
 
                            ppd_make_and_model = ippGetString (attr, 0, NULL);
992
 
                          else if (g_strcmp0 (ippGetName (attr), "ppd-name") == 0 &&
993
 
                                   ippGetValueTag (attr) == IPP_TAG_NAME)
994
 
                            ppd_name = ippGetString (attr, 0, NULL);
995
 
                          else if (g_strcmp0 (ippGetName (attr), "ppd-product") == 0 &&
996
 
                                   ippGetValueTag (attr) == IPP_TAG_TEXT)
997
 
                            ppd_product = ippGetString (attr, 0, NULL);
998
 
 
999
 
                          attr = ippNextAttribute (response);
1000
 
                        }
1001
 
 
1002
 
                      if (ppd_device_id && ppd_name)
1003
 
                        {
1004
 
                          item = g_new0 (PPDItem, 1);
1005
 
                          item->ppd_name = g_strdup (ppd_name);
1006
 
                          item->ppd_device_id = g_strdup (ppd_device_id);
1007
 
                          item->ppd_make_and_model = g_strdup (ppd_make_and_model);
1008
 
                          item->ppd_product = g_strdup (ppd_product);
1009
 
 
1010
 
                          tmp = get_tag_value (ppd_device_id, "mfg");
1011
 
                          if (!tmp)
1012
 
                            tmp = get_tag_value (ppd_device_id, "manufacturer");
1013
 
                          item->mfg = normalize (tmp);
1014
 
                          g_free (tmp);
1015
 
 
1016
 
                          tmp = get_tag_value (ppd_device_id, "mdl");
1017
 
                          if (!tmp)
1018
 
                            tmp = get_tag_value (ppd_device_id, "model");
1019
 
                          item->mdl = normalize (tmp);
1020
 
                          g_free (tmp);
1021
 
 
1022
 
                          item->match_level = PPD_EXACT_CMD_MATCH;
1023
 
                          ppd_exact_match_found = TRUE;
1024
 
                          list = g_list_append (list, item);
1025
 
                        }
1026
 
 
1027
 
                      if (attr == NULL)
1028
 
                        break;
1029
 
                    }
1030
 
                }
1031
 
 
1032
 
              if (response)
1033
 
                ippDelete(response);
1034
 
            }
1035
 
 
1036
 
          /* Try match according to manufacturer and model fields */
1037
 
          if (!ppd_exact_match_found && mfg_normalized && mdl_normalized)
1038
 
            {
1039
 
              request = ippNewRequest (CUPS_GET_PPDS);
1040
 
              response = cupsDoRequest (http, request, "/");
1041
 
 
1042
 
              if (response &&
1043
 
                  ippGetStatusCode (response) <= IPP_OK_CONFLICT)
1044
 
                {
1045
 
                  for (i = 0; equivalents && equivalents[i]; i++)
1046
 
                    {
1047
 
                      eq_normalized = normalize (equivalents[i]);
1048
 
                      for (attr = ippFirstAttribute (response); attr != NULL; attr = ippNextAttribute (response))
1049
 
                        {
1050
 
                          while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
1051
 
                            attr = ippNextAttribute (response);
1052
 
 
1053
 
                          if (attr == NULL)
1054
 
                            break;
1055
 
 
1056
 
                          ppd_device_id = NULL;
1057
 
                          ppd_make_and_model = NULL;
1058
 
                          ppd_name = NULL;
1059
 
                          ppd_product = NULL;
1060
 
 
1061
 
                          while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
1062
 
                            {
1063
 
                              if (g_strcmp0 (ippGetName (attr), "ppd-device-id") == 0 &&
1064
 
                                  ippGetValueTag (attr) == IPP_TAG_TEXT)
1065
 
                                ppd_device_id = ippGetString (attr, 0, NULL);
1066
 
                              else if (g_strcmp0 (ippGetName (attr), "ppd-make-and-model") == 0 &&
1067
 
                                       ippGetValueTag (attr) == IPP_TAG_TEXT)
1068
 
                                ppd_make_and_model = ippGetString (attr, 0, NULL);
1069
 
                              else if (g_strcmp0 (ippGetName (attr), "ppd-name") == 0 &&
1070
 
                                       ippGetValueTag (attr) == IPP_TAG_NAME)
1071
 
                                ppd_name = ippGetString (attr, 0, NULL);
1072
 
                              else if (g_strcmp0 (ippGetName (attr), "ppd-product") == 0 &&
1073
 
                                       ippGetValueTag (attr) == IPP_TAG_TEXT)
1074
 
                                ppd_product = ippGetString (attr, 0, NULL);
1075
 
 
1076
 
                              attr = ippNextAttribute (response);
1077
 
                            }
1078
 
 
1079
 
                          if (ppd_device_id && ppd_name)
1080
 
                            {
1081
 
                              item = g_new0 (PPDItem, 1);
1082
 
                              item->ppd_name = g_strdup (ppd_name);
1083
 
                              item->ppd_device_id = g_strdup (ppd_device_id);
1084
 
                              item->ppd_make_and_model = g_strdup (ppd_make_and_model);
1085
 
                              item->ppd_product = g_strdup (ppd_product);
1086
 
 
1087
 
                              tmp = get_tag_value (ppd_device_id, "mfg");
1088
 
                              if (!tmp)
1089
 
                                tmp = get_tag_value (ppd_device_id, "manufacturer");
1090
 
                              item->mfg = normalize (tmp);
1091
 
                              g_free (tmp);
1092
 
 
1093
 
                              tmp = get_tag_value (ppd_device_id, "mdl");
1094
 
                              if (!tmp)
1095
 
                                tmp = get_tag_value (ppd_device_id, "model");
1096
 
                              item->mdl = normalize (tmp);
1097
 
                              g_free (tmp);
1098
 
 
1099
 
                              if (item->mdl && item->mfg &&
1100
 
                                  g_ascii_strcasecmp (item->mdl, mdl_normalized) == 0 &&
1101
 
                                  g_ascii_strcasecmp (item->mfg, eq_normalized) == 0)
1102
 
                                {
1103
 
                                  item->match_level = PPD_EXACT_MATCH;
1104
 
                                  ppd_exact_match_found = TRUE;
1105
 
                                }
1106
 
 
1107
 
                              if (item->match_level == PPD_EXACT_MATCH)
1108
 
                                list = g_list_append (list, item);
1109
 
                              else if (item->mfg &&
1110
 
                                       g_ascii_strcasecmp (item->mfg, eq_normalized) == 0)
1111
 
                                mdls = g_list_append (mdls, item);
1112
 
                              else
1113
 
                                {
1114
 
                                  ppd_item_free (item);
1115
 
                                  g_free (item);
1116
 
                                }
1117
 
                            }
1118
 
 
1119
 
                          if (attr == NULL)
1120
 
                            break;
1121
 
                        }
1122
 
 
1123
 
                      g_free (eq_normalized);
1124
 
                    }
1125
 
                }
1126
 
 
1127
 
              if (response)
1128
 
                ippDelete(response);
1129
 
            }
1130
 
 
1131
 
          httpClose (http);
1132
 
        }
1133
 
 
1134
 
      if (list == NULL)
1135
 
        list = append_best_ppds (list, mdls, mdl);
1136
 
 
1137
 
      /* Find out driver types for all listed drivers and set their preference values */
1138
 
      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
1139
 
        {
1140
 
          item = (PPDItem *) tmp_list->data;
1141
 
          if (item)
1142
 
            {
1143
 
              item->driver_type = get_driver_type (item->ppd_name,
1144
 
                                                   item->ppd_device_id,
1145
 
                                                   item->ppd_make_and_model,
1146
 
                                                   item->ppd_product,
1147
 
                                                   item->match_level);
1148
 
              item->preference_value = get_driver_preference (item);
1149
 
            }
1150
 
        }
1151
 
 
1152
 
      /* Sort driver list according to preference value */
1153
 
      list = g_list_sort (list, preference_value_cmp);
1154
 
 
1155
 
      /* Split blacklisted drivers to tmp_list */
1156
 
      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
1157
 
        {
1158
 
          item = (PPDItem *) tmp_list->data;
1159
 
          if (item && item->preference_value >= 2000)
1160
 
            break;
1161
 
        }
1162
 
 
1163
 
      /* Free tmp_list */
1164
 
      if (tmp_list)
1165
 
        {
1166
 
          if (tmp_list->prev)
1167
 
            tmp_list->prev->next = NULL;
1168
 
          else
1169
 
            list = NULL;
1170
 
 
1171
 
          tmp_list->prev = NULL;
1172
 
          for (tmp_list2 = tmp_list; tmp_list2; tmp_list2 = tmp_list2->next)
1173
 
            {
1174
 
              item = (PPDItem *) tmp_list2->data;
1175
 
              ppd_item_free (item);
1176
 
              g_free (item);
1177
 
            }
1178
 
 
1179
 
          g_list_free (tmp_list);
1180
 
        }
1181
 
 
1182
 
      /* Free driver list and set the best one */
1183
 
      if (list)
1184
 
        {
1185
 
          item = (PPDItem *) list->data;
1186
 
          if (item)
1187
 
            {
1188
 
              result = g_new0 (PPDName, 1);
1189
 
              result->ppd_name = g_strdup (item->ppd_name);
1190
 
              result->ppd_match_level = item->match_level;
1191
 
              switch (item->match_level)
1192
 
                {
1193
 
                  case PPD_GENERIC_MATCH:
1194
 
                  case PPD_CLOSE_MATCH:
1195
 
                    g_warning ("Found PPD does not match given device exactly!");
1196
 
                    break;
1197
 
                  default:
1198
 
                    break;
1199
 
                }
1200
 
            }
1201
 
 
1202
 
          for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
1203
 
            {
1204
 
              item = (PPDItem *) tmp_list->data;
1205
 
              ppd_item_free (item);
1206
 
              g_free (item);
1207
 
            }
1208
 
 
1209
 
          g_list_free (list);
1210
 
        }
1211
 
 
1212
 
      if (mdls)
1213
 
        {
1214
 
          for (tmp_list = mdls; tmp_list; tmp_list = tmp_list->next)
1215
 
            {
1216
 
              item = (PPDItem *) tmp_list->data;
1217
 
              ppd_item_free (item);
1218
 
              g_free (item);
1219
 
            }
1220
 
          g_list_free (mdls);
1221
 
        }
1222
 
 
1223
 
      g_free (mfg);
1224
 
      g_free (mdl);
1225
 
      g_free (mfg_normalized);
1226
 
      g_free (mdl_normalized);
1227
 
      if (equivalents)
1228
 
        g_strfreev (equivalents);
1229
 
    }
1230
 
 
1231
 
  return result;
1232
 
}
1233
 
 
1234
164
char *
1235
165
get_dest_attr (const char *dest_name,
1236
166
               const char *attr)
1270
200
  return ret;
1271
201
}
1272
202
 
1273
 
ipp_t *
1274
 
execute_maintenance_command (const char *printer_name,
1275
 
                             const char *command,
1276
 
                             const char *title)
1277
 
{
1278
 
  http_t *http;
1279
 
  GError *error = NULL;
1280
 
  ipp_t  *request = NULL;
1281
 
  ipp_t  *response = NULL;
1282
 
  gchar  *file_name = NULL;
1283
 
  char   *uri;
1284
 
  int     fd = -1;
1285
 
 
1286
 
  http = httpConnectEncrypt (cupsServer (),
1287
 
                             ippPort (),
1288
 
                             cupsEncryption ());
1289
 
 
1290
 
  if (!http)
1291
 
    return NULL;
1292
 
 
1293
 
  request = ippNewRequest (IPP_PRINT_JOB);
1294
 
 
1295
 
  uri = g_strdup_printf ("ipp://localhost/printers/%s", printer_name);
1296
 
 
1297
 
  ippAddString (request,
1298
 
                IPP_TAG_OPERATION,
1299
 
                IPP_TAG_URI,
1300
 
                "printer-uri",
1301
 
                NULL,
1302
 
                uri);
1303
 
 
1304
 
  g_free (uri);
1305
 
 
1306
 
  ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
1307
 
                NULL, title);
1308
 
 
1309
 
  ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
1310
 
                NULL, "application/vnd.cups-command");
1311
 
 
1312
 
  fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
1313
 
 
1314
 
  if (fd != -1)
1315
 
    {
1316
 
      FILE *file;
1317
 
 
1318
 
      file = fdopen (fd, "w");
1319
 
      fprintf (file, "#CUPS-COMMAND\n");
1320
 
      fprintf (file, "%s\n", command);
1321
 
      fclose (file);
1322
 
 
1323
 
      response = cupsDoFileRequest (http, request, "/", file_name);
1324
 
      g_unlink (file_name);
1325
 
    }
1326
 
  else
1327
 
    {
1328
 
      g_warning ("%s", error->message);
1329
 
      g_error_free (error);
1330
 
    }
1331
 
 
1332
 
  g_free (file_name);
1333
 
  httpClose (http);
1334
 
 
1335
 
  return response;
1336
 
}
1337
 
 
1338
 
int
1339
 
ccGetAllowedUsers (gchar ***allowed_users, const char *printer_name)
1340
 
{
1341
 
  const char * const   attrs[1] = { "requesting-user-name-allowed" };
1342
 
  http_t              *http;
1343
 
  ipp_t               *request = NULL;
1344
 
  gchar              **users = NULL;
1345
 
  ipp_t               *response;
1346
 
  char                *uri;
1347
 
  int                  num_allowed_users = 0;
1348
 
 
1349
 
  http = httpConnectEncrypt (cupsServer (),
1350
 
                             ippPort (),
1351
 
                             cupsEncryption ());
1352
 
 
1353
 
  if (!http)
1354
 
    {
1355
 
      *allowed_users = NULL;
1356
 
      return 0;
1357
 
    }
1358
 
 
1359
 
  request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
1360
 
 
1361
 
  uri = g_strdup_printf ("ipp://localhost/printers/%s", printer_name);
1362
 
 
1363
 
  ippAddString (request,
1364
 
                IPP_TAG_OPERATION,
1365
 
                IPP_TAG_URI,
1366
 
                "printer-uri",
1367
 
                NULL,
1368
 
                uri);
1369
 
 
1370
 
  g_free (uri);
1371
 
 
1372
 
  ippAddStrings (request,
1373
 
                 IPP_TAG_OPERATION,
1374
 
                 IPP_TAG_KEYWORD,
1375
 
                 "requested-attributes",
1376
 
                 1,
1377
 
                 NULL,
1378
 
                 attrs);
1379
 
 
1380
 
  response = cupsDoRequest (http, request, "/");
1381
 
  if (response)
1382
 
    {
1383
 
      ipp_attribute_t *attr = NULL;
1384
 
      ipp_attribute_t *allowed = NULL;
1385
 
 
1386
 
      for (attr = ippFirstAttribute (response); attr != NULL; attr = ippNextAttribute (response))
1387
 
        {
1388
 
          if (ippGetGroupTag (attr) == IPP_TAG_PRINTER &&
1389
 
              ippGetValueTag (attr) == IPP_TAG_NAME &&
1390
 
              !g_strcmp0 (ippGetName (attr), "requesting-user-name-allowed"))
1391
 
            allowed = attr;
1392
 
        }
1393
 
 
1394
 
      if (allowed && ippGetCount (allowed) > 0)
1395
 
        {
1396
 
          int i;
1397
 
 
1398
 
          num_allowed_users = ippGetCount (allowed);
1399
 
          users = g_new (gchar*, num_allowed_users);
1400
 
 
1401
 
          for (i = 0; i < num_allowed_users; i ++)
1402
 
            users[i] = g_strdup (ippGetString (allowed, i, NULL));
1403
 
        }
1404
 
      ippDelete(response);
1405
 
    }
1406
 
  httpClose (http);
1407
 
 
1408
 
  *allowed_users = users;
1409
 
  return num_allowed_users;
1410
 
}
1411
 
 
1412
203
gchar *
1413
204
get_ppd_attribute (const gchar *ppd_file_name,
1414
205
                   const gchar *attribute_name)
1568
359
  cups_job_t       *jobs = NULL;
1569
360
  GDBusConnection  *bus;
1570
361
  const char       *printer_location = NULL;
1571
 
  const char       *ppd_filename = NULL;
1572
362
  const char       *printer_info = NULL;
1573
363
  const char       *printer_uri = NULL;
1574
364
  const char       *device_uri = NULL;
1580
370
  gboolean          printer_shared = FALSE;
1581
371
  GError           *error = NULL;
1582
372
  http_t           *http;
 
373
  gchar            *ppd_link;
 
374
  gchar            *ppd_filename = NULL;
1583
375
  gchar           **sheets = NULL;
1584
376
  gchar           **users_allowed = NULL;
1585
377
  gchar           **users_denied = NULL;
1735
527
        }
1736
528
    }
1737
529
 
1738
 
  ppd_filename = cupsGetPPD (old_name);
 
530
  ppd_link = g_strdup (cupsGetPPD (old_name));
 
531
  if (ppd_link)
 
532
    {
 
533
      ppd_filename = g_file_read_link (ppd_link, NULL);
 
534
 
 
535
      if (!ppd_filename)
 
536
        ppd_filename = g_strdup (ppd_link);
 
537
    }
 
538
 
1739
539
 
1740
540
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
1741
541
  if (!bus)
1791
591
        }
1792
592
    }
1793
593
 
1794
 
  if (ppd_filename)
1795
 
    g_unlink (ppd_filename);
 
594
  if (ppd_link)
 
595
    {
 
596
      g_unlink (ppd_link);
 
597
      g_free (ppd_link);
 
598
      g_free (ppd_filename);
 
599
    }
1796
600
 
1797
601
  num_dests = cupsGetDests (&dests);
1798
602
  dest = cupsGetDest (new_name, NULL, num_dests, dests);
2526
1330
}
2527
1331
 
2528
1332
/* Returns default media size for current locale */
2529
 
static const gchar *
 
1333
const gchar *
2530
1334
get_paper_size_from_locale ()
2531
1335
{
2532
1336
  if (g_str_equal (gtk_paper_size_get_default (), GTK_PAPER_NAME_LETTER))
2591
1395
      g_error_free (error);
2592
1396
    }
2593
1397
}
 
1398
 
 
1399
 
 
1400
typedef struct
 
1401
{
 
1402
  gchar        *printer_name;
 
1403
  gchar       **attributes_names;
 
1404
  GHashTable   *result;
 
1405
  GIACallback   callback;
 
1406
  gpointer      user_data;
 
1407
  GMainContext *context;
 
1408
} GIAData;
 
1409
 
 
1410
static gboolean
 
1411
get_ipp_attributes_idle_cb (gpointer user_data)
 
1412
{
 
1413
  GIAData *data = (GIAData *) user_data;
 
1414
 
 
1415
  data->callback (data->result, data->user_data);
 
1416
 
 
1417
  return FALSE;
 
1418
}
 
1419
 
 
1420
static void
 
1421
get_ipp_attributes_data_free (gpointer user_data)
 
1422
{
 
1423
  GIAData *data = (GIAData *) user_data;
 
1424
 
 
1425
  if (data->context)
 
1426
    g_main_context_unref (data->context);
 
1427
  g_free (data->printer_name);
 
1428
  if (data->attributes_names)
 
1429
    g_strfreev (data->attributes_names);
 
1430
  g_free (data);
 
1431
}
 
1432
 
 
1433
static void
 
1434
get_ipp_attributes_cb (gpointer user_data)
 
1435
{
 
1436
  GIAData *data = (GIAData *) user_data;
 
1437
  GSource *idle_source;
 
1438
 
 
1439
  idle_source = g_idle_source_new ();
 
1440
  g_source_set_callback (idle_source,
 
1441
                         get_ipp_attributes_idle_cb,
 
1442
                         data,
 
1443
                         get_ipp_attributes_data_free);
 
1444
  g_source_attach (idle_source, data->context);
 
1445
  g_source_unref (idle_source);
 
1446
}
 
1447
 
 
1448
static void
 
1449
ipp_attribute_free2 (gpointer attr)
 
1450
{
 
1451
  IPPAttribute *attribute = (IPPAttribute *) attr;
 
1452
  ipp_attribute_free (attribute);
 
1453
}
 
1454
 
 
1455
static gpointer
 
1456
get_ipp_attributes_func (gpointer user_data)
 
1457
{
 
1458
  ipp_attribute_t  *attr = NULL;
 
1459
  GIAData          *data = (GIAData *) user_data;
 
1460
  ipp_t            *request;
 
1461
  ipp_t            *response = NULL;
 
1462
  gchar            *printer_uri;
 
1463
  char            **requested_attrs = NULL;
 
1464
  gint              i, j, length = 0;
 
1465
 
 
1466
  printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", data->printer_name);
 
1467
 
 
1468
  if (data->attributes_names)
 
1469
    {
 
1470
      length = g_strv_length (data->attributes_names);
 
1471
 
 
1472
      requested_attrs = g_new0 (char *, length);
 
1473
      for (i = 0; data->attributes_names[i]; i++)
 
1474
        requested_attrs[i] = g_strdup (data->attributes_names[i]);
 
1475
 
 
1476
      request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
 
1477
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
1478
                    "printer-uri", NULL, printer_uri);
 
1479
      ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
 
1480
                     "requested-attributes", length, NULL, (const char **) requested_attrs);
 
1481
      response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
 
1482
    }
 
1483
 
 
1484
  if (response)
 
1485
    {
 
1486
      if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
 
1487
        {
 
1488
          for (j = 0; j < length; j++)
 
1489
            {
 
1490
              attr = ippFindAttribute (response, requested_attrs[j], IPP_TAG_ZERO);
 
1491
              if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
 
1492
                {
 
1493
                  IPPAttribute *attribute;
 
1494
 
 
1495
                  attribute = g_new0 (IPPAttribute, 1);
 
1496
                  attribute->attribute_name = g_strdup (requested_attrs[j]);
 
1497
                  attribute->attribute_values = g_new0 (IPPAttributeValue, ippGetCount (attr));
 
1498
                  attribute->num_of_values = ippGetCount (attr);
 
1499
 
 
1500
                  if (ippGetValueTag (attr) == IPP_TAG_INTEGER ||
 
1501
                      ippGetValueTag (attr) == IPP_TAG_ENUM)
 
1502
                    {
 
1503
                      attribute->attribute_type = IPP_ATTRIBUTE_TYPE_INTEGER;
 
1504
 
 
1505
                      for (i = 0; i < ippGetCount (attr); i++)
 
1506
                        attribute->attribute_values[i].integer_value = ippGetInteger (attr, i);
 
1507
                    }
 
1508
                  else if (ippGetValueTag (attr) == IPP_TAG_NAME ||
 
1509
                           ippGetValueTag (attr) == IPP_TAG_STRING ||
 
1510
                           ippGetValueTag (attr) == IPP_TAG_TEXT ||
 
1511
                           ippGetValueTag (attr) == IPP_TAG_URI ||
 
1512
                           ippGetValueTag (attr) == IPP_TAG_KEYWORD ||
 
1513
                           ippGetValueTag (attr) == IPP_TAG_URISCHEME)
 
1514
                    {
 
1515
                      attribute->attribute_type = IPP_ATTRIBUTE_TYPE_STRING;
 
1516
 
 
1517
                      for (i = 0; i < ippGetCount (attr); i++)
 
1518
                        attribute->attribute_values[i].string_value = g_strdup (ippGetString (attr, i, NULL));
 
1519
                    }
 
1520
                  else if (ippGetValueTag (attr) == IPP_TAG_RANGE)
 
1521
                    {
 
1522
                      attribute->attribute_type = IPP_ATTRIBUTE_TYPE_RANGE;
 
1523
 
 
1524
                      for (i = 0; i < ippGetCount (attr); i++)
 
1525
                        {
 
1526
                          attribute->attribute_values[i].lower_range =
 
1527
                            ippGetRange (attr, i, &(attribute->attribute_values[i].upper_range));
 
1528
                        }
 
1529
                    }
 
1530
                  else if (ippGetValueTag (attr) == IPP_TAG_BOOLEAN)
 
1531
                    {
 
1532
                      attribute->attribute_type = IPP_ATTRIBUTE_TYPE_BOOLEAN;
 
1533
 
 
1534
                      for (i = 0; i < ippGetCount (attr); i++)
 
1535
                        attribute->attribute_values[i].boolean_value = ippGetBoolean (attr, i);
 
1536
                    }
 
1537
 
 
1538
                  if (!data->result)
 
1539
                    data->result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, ipp_attribute_free2);
 
1540
 
 
1541
                  g_hash_table_insert (data->result, g_strdup (requested_attrs[j]), attribute);
 
1542
                }
 
1543
            }
 
1544
        }
 
1545
 
 
1546
      ippDelete (response);
 
1547
    }
 
1548
 
 
1549
 
 
1550
  for (i = 0; i < length; i++)
 
1551
    g_free (requested_attrs[i]);
 
1552
  g_free (requested_attrs);
 
1553
 
 
1554
  g_free (printer_uri);
 
1555
 
 
1556
  get_ipp_attributes_cb (data);
 
1557
 
 
1558
  return NULL;
 
1559
}
 
1560
 
 
1561
void
 
1562
get_ipp_attributes_async (const gchar  *printer_name,
 
1563
                          gchar       **attributes_names,
 
1564
                          GIACallback   callback,
 
1565
                          gpointer      user_data)
 
1566
{
 
1567
  GIAData *data;
 
1568
  GThread *thread;
 
1569
  GError  *error = NULL;
 
1570
 
 
1571
  data = g_new0 (GIAData, 1);
 
1572
  data->printer_name = g_strdup (printer_name);
 
1573
  data->attributes_names = g_strdupv (attributes_names);
 
1574
  data->callback = callback;
 
1575
  data->user_data = user_data;
 
1576
  data->context = g_main_context_ref_thread_default ();
 
1577
 
 
1578
  thread = g_thread_try_new ("get-ipp-attributes",
 
1579
                             get_ipp_attributes_func,
 
1580
                             data,
 
1581
                             &error);
 
1582
 
 
1583
  if (!thread)
 
1584
    {
 
1585
      g_warning ("%s", error->message);
 
1586
      callback (NULL, user_data);
 
1587
 
 
1588
      g_error_free (error);
 
1589
      get_ipp_attributes_data_free (data);
 
1590
    }
 
1591
  else
 
1592
    {
 
1593
      g_thread_unref (thread);
 
1594
    }
 
1595
}
 
1596
 
 
1597
IPPAttribute *
 
1598
ipp_attribute_copy (IPPAttribute *attr)
 
1599
{
 
1600
  IPPAttribute *result = NULL;
 
1601
  gint          i;
 
1602
 
 
1603
  if (attr)
 
1604
    {
 
1605
      result = g_new0 (IPPAttribute, 1);
 
1606
 
 
1607
      *result = *attr;
 
1608
      result->attribute_name = g_strdup (attr->attribute_name);
 
1609
      result->attribute_values = g_new0 (IPPAttributeValue, attr->num_of_values);
 
1610
      for (i = 0; i < attr->num_of_values; i++)
 
1611
        {
 
1612
          result->attribute_values[i] = attr->attribute_values[i];
 
1613
          if (attr->attribute_values[i].string_value)
 
1614
            result->attribute_values[i].string_value = g_strdup (attr->attribute_values[i].string_value);
 
1615
        }
 
1616
    }
 
1617
 
 
1618
  return result;
 
1619
}
 
1620
 
 
1621
void
 
1622
ipp_attribute_free (IPPAttribute *attr)
 
1623
{
 
1624
  gint i;
 
1625
 
 
1626
  if (attr)
 
1627
    {
 
1628
      for (i = 0; i < attr->num_of_values; i++)
 
1629
        g_free (attr->attribute_values[i].string_value);
 
1630
 
 
1631
      g_free (attr->attribute_values);
 
1632
      g_free (attr->attribute_name);
 
1633
      g_free (attr);
 
1634
    }
 
1635
}
 
1636
 
 
1637
 
 
1638
 
 
1639
typedef struct
 
1640
{
 
1641
  gchar        *printer_name;
 
1642
  gchar        *ppd_copy;
 
1643
  GCancellable *cancellable;
 
1644
  PSPCallback   callback;
 
1645
  gpointer      user_data;
 
1646
} PSPData;
 
1647
 
 
1648
static void
 
1649
printer_set_ppd_async_dbus_cb (GObject      *source_object,
 
1650
                               GAsyncResult *res,
 
1651
                               gpointer      user_data)
 
1652
{
 
1653
  GVariant *output;
 
1654
  gboolean  result = FALSE;
 
1655
  PSPData  *data = (PSPData *) user_data;
 
1656
  GError   *error = NULL;
 
1657
 
 
1658
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
1659
                                          res,
 
1660
                                          &error);
 
1661
  g_object_unref (source_object);
 
1662
 
 
1663
  if (output)
 
1664
    {
 
1665
      const gchar *ret_error;
 
1666
 
 
1667
      g_variant_get (output, "(&s)", &ret_error);
 
1668
      if (ret_error[0] != '\0')
 
1669
        g_warning ("%s", ret_error);
 
1670
      else
 
1671
        result = TRUE;
 
1672
 
 
1673
      g_variant_unref (output);
 
1674
    }
 
1675
  else
 
1676
    {
 
1677
      if (error->code != G_IO_ERROR_CANCELLED)
 
1678
        g_warning ("%s", error->message);
 
1679
      g_error_free (error);
 
1680
    }
 
1681
 
 
1682
  /* Don't call callback if cancelled */
 
1683
  if (!data->cancellable ||
 
1684
      !g_cancellable_is_cancelled (data->cancellable))
 
1685
    data->callback (g_strdup (data->printer_name),
 
1686
                    result,
 
1687
                    data->user_data);
 
1688
 
 
1689
  if (data->cancellable)
 
1690
    g_object_unref (data->cancellable);
 
1691
 
 
1692
  if (data->ppd_copy)
 
1693
    {
 
1694
      g_unlink (data->ppd_copy);
 
1695
      g_free (data->ppd_copy);
 
1696
    }
 
1697
 
 
1698
  g_free (data->printer_name);
 
1699
  g_free (data);
 
1700
}
 
1701
 
 
1702
/*
 
1703
 * Set ppd for given printer.
 
1704
 * Don't use this for classes, just for printers.
 
1705
 */
 
1706
void
 
1707
printer_set_ppd_async (const gchar  *printer_name,
 
1708
                       const gchar  *ppd_name,
 
1709
                       GCancellable *cancellable,
 
1710
                       PSPCallback   callback,
 
1711
                       gpointer      user_data)
 
1712
{
 
1713
  GDBusConnection *bus;
 
1714
  PSPData         *data;
 
1715
  GError          *error = NULL;
 
1716
 
 
1717
  data = g_new0 (PSPData, 1);
 
1718
  if (cancellable)
 
1719
    data->cancellable = g_object_ref (cancellable);
 
1720
  data->callback = callback;
 
1721
  data->user_data = user_data;
 
1722
  data->printer_name = g_strdup (printer_name);
 
1723
 
 
1724
  if (printer_name == NULL ||
 
1725
      printer_name[0] == '\0')
 
1726
    {
 
1727
      goto out;
 
1728
    }
 
1729
 
 
1730
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
1731
  if (!bus)
 
1732
    {
 
1733
      g_warning ("Failed to get system bus: %s", error->message);
 
1734
      g_error_free (error);
 
1735
      goto out;
 
1736
    }
 
1737
 
 
1738
  g_dbus_connection_call (bus,
 
1739
                          MECHANISM_BUS,
 
1740
                          "/",
 
1741
                          MECHANISM_BUS,
 
1742
                          "PrinterAdd",
 
1743
                          g_variant_new ("(sssss)",
 
1744
                                         printer_name,
 
1745
                                         "",
 
1746
                                         ppd_name,
 
1747
                                         "",
 
1748
                                         ""),
 
1749
                          G_VARIANT_TYPE ("(s)"),
 
1750
                          G_DBUS_CALL_FLAGS_NONE,
 
1751
                          -1,
 
1752
                          data->cancellable,
 
1753
                          printer_set_ppd_async_dbus_cb,
 
1754
                          data);
 
1755
 
 
1756
  return;
 
1757
 
 
1758
out:
 
1759
  callback (g_strdup (printer_name), FALSE, user_data);
 
1760
 
 
1761
  if (data->cancellable)
 
1762
    g_object_unref (data->cancellable);
 
1763
  g_free (data->printer_name);
 
1764
  g_free (data);
 
1765
}
 
1766
 
 
1767
static void
 
1768
printer_set_ppd_file_async_scb (GObject      *source_object,
 
1769
                                GAsyncResult *res,
 
1770
                                gpointer      user_data)
 
1771
{
 
1772
  GDBusConnection *bus;
 
1773
  gboolean         success;
 
1774
  PSPData         *data = (PSPData *) user_data;
 
1775
  GError          *error = NULL;
 
1776
 
 
1777
  success = g_file_copy_finish (G_FILE (source_object),
 
1778
                                res,
 
1779
                                &error);
 
1780
  g_object_unref (source_object);
 
1781
 
 
1782
  if (!success)
 
1783
    {
 
1784
      g_warning ("%s", error->message);
 
1785
      g_error_free (error);
 
1786
      goto out;
 
1787
    }
 
1788
 
 
1789
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
1790
  if (!bus)
 
1791
    {
 
1792
      g_warning ("Failed to get system bus: %s", error->message);
 
1793
      g_error_free (error);
 
1794
      goto out;
 
1795
    }
 
1796
 
 
1797
  g_dbus_connection_call (bus,
 
1798
                          MECHANISM_BUS,
 
1799
                          "/",
 
1800
                          MECHANISM_BUS,
 
1801
                          "PrinterAddWithPpdFile",
 
1802
                          g_variant_new ("(sssss)",
 
1803
                                         data->printer_name,
 
1804
                                         "",
 
1805
                                         data->ppd_copy,
 
1806
                                         "",
 
1807
                                         ""),
 
1808
                          G_VARIANT_TYPE ("(s)"),
 
1809
                          G_DBUS_CALL_FLAGS_NONE,
 
1810
                          -1,
 
1811
                          data->cancellable,
 
1812
                          printer_set_ppd_async_dbus_cb,
 
1813
                          data);
 
1814
 
 
1815
  return;
 
1816
 
 
1817
out:
 
1818
  data->callback (g_strdup (data->printer_name), FALSE, data->user_data);
 
1819
 
 
1820
  if (data->cancellable)
 
1821
    g_object_unref (data->cancellable);
 
1822
  g_free (data->printer_name);
 
1823
  g_free (data->ppd_copy);
 
1824
  g_free (data);
 
1825
}
 
1826
 
 
1827
/*
 
1828
 * Set ppd for given printer.
 
1829
 * Don't use this for classes, just for printers.
 
1830
 */
 
1831
void
 
1832
printer_set_ppd_file_async (const gchar  *printer_name,
 
1833
                            const gchar  *ppd_filename,
 
1834
                            GCancellable *cancellable,
 
1835
                            PSPCallback   callback,
 
1836
                            gpointer      user_data)
 
1837
{
 
1838
  GFileIOStream *stream;
 
1839
  PSPData       *data;
 
1840
  GFile         *source_ppd_file;
 
1841
  GFile         *destination_ppd_file;
 
1842
 
 
1843
  data = g_new0 (PSPData, 1);
 
1844
  if (cancellable)
 
1845
    data->cancellable = g_object_ref (cancellable);
 
1846
  data->callback = callback;
 
1847
  data->user_data = user_data;
 
1848
  data->printer_name = g_strdup (printer_name);
 
1849
 
 
1850
  if (printer_name == NULL ||
 
1851
      printer_name[0] == '\0')
 
1852
    {
 
1853
      goto out;
 
1854
    }
 
1855
 
 
1856
  /*
 
1857
   * We need to copy the PPD to temp directory at first.
 
1858
   * This is needed because of SELinux.
 
1859
   */
 
1860
  source_ppd_file = g_file_new_for_path (ppd_filename);
 
1861
  destination_ppd_file = g_file_new_tmp ("g-c-c-XXXXXX.ppd", &stream, NULL);
 
1862
  g_object_unref (stream);
 
1863
  data->ppd_copy = g_strdup (g_file_get_path (destination_ppd_file));
 
1864
 
 
1865
  g_file_copy_async (source_ppd_file,
 
1866
                     destination_ppd_file,
 
1867
                     G_FILE_COPY_OVERWRITE,
 
1868
                     G_PRIORITY_DEFAULT,
 
1869
                     cancellable,
 
1870
                     NULL,
 
1871
                     NULL,
 
1872
                     printer_set_ppd_file_async_scb,
 
1873
                     data);
 
1874
 
 
1875
  g_object_unref (destination_ppd_file);
 
1876
 
 
1877
  return;
 
1878
 
 
1879
out:
 
1880
  callback (g_strdup (printer_name), FALSE, user_data);
 
1881
 
 
1882
  if (data->cancellable)
 
1883
    g_object_unref (data->cancellable);
 
1884
  g_free (data->printer_name);
 
1885
  g_free (data);
 
1886
}
 
1887
 
 
1888
 
 
1889
 
 
1890
typedef void (*GPACallback) (gchar    **attribute_values,
 
1891
                             gpointer   user_data);
 
1892
 
 
1893
typedef struct
 
1894
{
 
1895
  gchar         *attribute_name;
 
1896
  gchar        **ppds_names;
 
1897
  gchar        **result;
 
1898
  GPACallback    callback;
 
1899
  gpointer       user_data;
 
1900
  GMainContext  *context;
 
1901
} GPAData;
 
1902
 
 
1903
static gboolean
 
1904
get_ppds_attribute_idle_cb (gpointer user_data)
 
1905
{
 
1906
  GPAData *data = (GPAData *) user_data;
 
1907
 
 
1908
  data->callback (data->result, data->user_data);
 
1909
 
 
1910
  return FALSE;
 
1911
}
 
1912
 
 
1913
static void
 
1914
get_ppds_attribute_data_free (gpointer user_data)
 
1915
{
 
1916
  GPAData *data = (GPAData *) user_data;
 
1917
 
 
1918
  if (data->context)
 
1919
    g_main_context_unref (data->context);
 
1920
  g_free (data->attribute_name);
 
1921
  g_strfreev (data->ppds_names);
 
1922
  g_free (data);
 
1923
}
 
1924
 
 
1925
static void
 
1926
get_ppds_attribute_cb (gpointer user_data)
 
1927
{
 
1928
  GPAData *data = (GPAData *) user_data;
 
1929
  GSource *idle_source;
 
1930
 
 
1931
  idle_source = g_idle_source_new ();
 
1932
  g_source_set_callback (idle_source,
 
1933
                         get_ppds_attribute_idle_cb,
 
1934
                         data,
 
1935
                         get_ppds_attribute_data_free);
 
1936
  g_source_attach (idle_source, data->context);
 
1937
  g_source_unref (idle_source);
 
1938
}
 
1939
 
 
1940
static gpointer
 
1941
get_ppds_attribute_func (gpointer user_data)
 
1942
{
 
1943
  ppd_file_t  *ppd_file;
 
1944
  ppd_attr_t  *ppd_attr;
 
1945
  GPAData     *data = (GPAData *) user_data;
 
1946
  gchar       *ppd_filename;
 
1947
  gint         i;
 
1948
 
 
1949
  data->result = g_new0 (gchar *, g_strv_length (data->ppds_names) + 1);
 
1950
  for (i = 0; data->ppds_names[i]; i++)
 
1951
    {
 
1952
      ppd_filename = g_strdup (cupsGetServerPPD (CUPS_HTTP_DEFAULT, data->ppds_names[i]));
 
1953
      if (ppd_filename)
 
1954
        {
 
1955
          ppd_file = ppdOpenFile (ppd_filename);
 
1956
          if (ppd_file)
 
1957
            {
 
1958
              ppd_attr = ppdFindAttr (ppd_file, data->attribute_name, NULL);
 
1959
              if (ppd_attr != NULL)
 
1960
                data->result[i] = g_strdup (ppd_attr->value);
 
1961
 
 
1962
              ppdClose (ppd_file);
 
1963
            }
 
1964
 
 
1965
          g_unlink (ppd_filename);
 
1966
          g_free (ppd_filename);
 
1967
        }
 
1968
    }
 
1969
 
 
1970
  get_ppds_attribute_cb (data);
 
1971
 
 
1972
  return NULL;
 
1973
}
 
1974
 
 
1975
/*
 
1976
 * Get values of requested PPD attribute for given PPDs.
 
1977
 */
 
1978
static void
 
1979
get_ppds_attribute_async (gchar       **ppds_names,
 
1980
                          gchar        *attribute_name,
 
1981
                          GPACallback   callback,
 
1982
                          gpointer      user_data)
 
1983
{
 
1984
  GPAData *data;
 
1985
  GThread *thread;
 
1986
  GError  *error = NULL;
 
1987
 
 
1988
  if (!ppds_names || !attribute_name)
 
1989
    {
 
1990
      callback (NULL, user_data);
 
1991
      return;
 
1992
    }
 
1993
 
 
1994
  data = g_new0 (GPAData, 1);
 
1995
  data->ppds_names = g_strdupv (ppds_names);
 
1996
  data->attribute_name = g_strdup (attribute_name);
 
1997
  data->callback = callback;
 
1998
  data->user_data = user_data;
 
1999
  data->context = g_main_context_ref_thread_default ();
 
2000
 
 
2001
  thread = g_thread_try_new ("get-ppds-attribute",
 
2002
                             get_ppds_attribute_func,
 
2003
                             data,
 
2004
                             &error);
 
2005
 
 
2006
  if (!thread)
 
2007
    {
 
2008
      g_warning ("%s", error->message);
 
2009
      callback (NULL, user_data);
 
2010
 
 
2011
      g_error_free (error);
 
2012
      get_ppds_attribute_data_free (data);
 
2013
    }
 
2014
  else
 
2015
    {
 
2016
      g_thread_unref (thread);
 
2017
    }
 
2018
}
 
2019
 
 
2020
 
 
2021
 
 
2022
typedef void (*GDACallback) (gchar    *device_id,
 
2023
                             gchar    *device_make_and_model,
 
2024
                             gchar    *device_uri,
 
2025
                             gpointer  user_data);
 
2026
 
 
2027
typedef struct
 
2028
{
 
2029
  gchar        *printer_name;
 
2030
  gchar        *device_uri;
 
2031
  GCancellable *cancellable;
 
2032
  GList        *backend_list;
 
2033
  GDACallback   callback;
 
2034
  gpointer      user_data;
 
2035
} GDAData;
 
2036
 
 
2037
typedef struct
 
2038
{
 
2039
  gchar         *printer_name;
 
2040
  gint           count;
 
2041
  PPDName      **result;
 
2042
  GCancellable  *cancellable;
 
2043
  GPNCallback    callback;
 
2044
  gpointer       user_data;
 
2045
} GPNData;
 
2046
 
 
2047
static void
 
2048
get_ppd_names_async_cb (gchar    **attribute_values,
 
2049
                        gpointer   user_data)
 
2050
{
 
2051
  GPNData *data = (GPNData *) user_data;
 
2052
  gint     i;
 
2053
 
 
2054
  if (g_cancellable_is_cancelled (data->cancellable))
 
2055
    {
 
2056
      g_strfreev (attribute_values);
 
2057
 
 
2058
      for (i = 0; data->result[i]; i++)
 
2059
        {
 
2060
          g_free (data->result[i]->ppd_name);
 
2061
          g_free (data->result[i]);
 
2062
        }
 
2063
 
 
2064
      g_free (data->result);
 
2065
      data->result = NULL;
 
2066
 
 
2067
      goto out;
 
2068
    }
 
2069
 
 
2070
  if (attribute_values)
 
2071
    {
 
2072
      for (i = 0; attribute_values[i]; i++)
 
2073
        data->result[i]->ppd_display_name = attribute_values[i];
 
2074
 
 
2075
      g_free (attribute_values);
 
2076
    }
 
2077
 
 
2078
out:
 
2079
  data->callback (data->result,
 
2080
                  data->printer_name,
 
2081
                  g_cancellable_is_cancelled (data->cancellable),
 
2082
                  data->user_data);
 
2083
 
 
2084
  if (data->cancellable)
 
2085
    g_object_unref (data->cancellable);
 
2086
  g_free (data->printer_name);
 
2087
  g_free (data);
 
2088
}
 
2089
 
 
2090
static void
 
2091
get_ppd_names_async_dbus_scb (GObject      *source_object,
 
2092
                              GAsyncResult *res,
 
2093
                              gpointer      user_data)
 
2094
{
 
2095
  GVariant  *output;
 
2096
  PPDName   *ppd_item;
 
2097
  PPDName  **result = NULL;
 
2098
  GPNData   *data = (GPNData *) user_data;
 
2099
  GError    *error = NULL;
 
2100
  GList     *driver_list = NULL;
 
2101
  GList     *iter;
 
2102
  gint       i, j, n = 0;
 
2103
  static const char * const match_levels[] = {
 
2104
             "exact-cmd",
 
2105
             "exact",
 
2106
             "close",
 
2107
             "generic",
 
2108
             "none"};
 
2109
 
 
2110
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
2111
                                          res,
 
2112
                                          &error);
 
2113
  g_object_unref (source_object);
 
2114
 
 
2115
  if (output)
 
2116
    {
 
2117
      GVariant *array;
 
2118
 
 
2119
      g_variant_get (output, "(@a(ss))",
 
2120
                     &array);
 
2121
 
 
2122
      if (array)
 
2123
        {
 
2124
          GVariantIter *iter;
 
2125
          GVariant     *item;
 
2126
          gchar        *driver;
 
2127
          gchar        *match;
 
2128
 
 
2129
          for (j = 0; j < G_N_ELEMENTS (match_levels) && n < data->count; j++)
 
2130
            {
 
2131
              g_variant_get (array,
 
2132
                             "a(ss)",
 
2133
                             &iter);
 
2134
 
 
2135
              while ((item = g_variant_iter_next_value (iter)))
 
2136
                {
 
2137
                  g_variant_get (item,
 
2138
                                 "(ss)",
 
2139
                                 &driver,
 
2140
                                 &match);
 
2141
 
 
2142
                  if (g_str_equal (match, match_levels[j]) && n < data->count)
 
2143
                    {
 
2144
                      ppd_item = g_new0 (PPDName, 1);
 
2145
                      ppd_item->ppd_name = g_strdup (driver);
 
2146
 
 
2147
                      if (g_strcmp0 (match, "exact-cmd") == 0)
 
2148
                        ppd_item->ppd_match_level = PPD_EXACT_CMD_MATCH;
 
2149
                      else if (g_strcmp0 (match, "exact") == 0)
 
2150
                        ppd_item->ppd_match_level = PPD_EXACT_MATCH;
 
2151
                      else if (g_strcmp0 (match, "close") == 0)
 
2152
                        ppd_item->ppd_match_level = PPD_CLOSE_MATCH;
 
2153
                      else if (g_strcmp0 (match, "generic") == 0)
 
2154
                        ppd_item->ppd_match_level = PPD_GENERIC_MATCH;
 
2155
                      else if (g_strcmp0 (match, "none") == 0)
 
2156
                        ppd_item->ppd_match_level = PPD_NO_MATCH;
 
2157
 
 
2158
                      driver_list = g_list_append (driver_list, ppd_item);
 
2159
 
 
2160
                      n++;
 
2161
                    }
 
2162
 
 
2163
                  g_free (driver);
 
2164
                  g_free (match);
 
2165
                  g_variant_unref (item);
 
2166
                }
 
2167
            }
 
2168
 
 
2169
          g_variant_unref (array);
 
2170
        }
 
2171
 
 
2172
      g_variant_unref (output);
 
2173
    }
 
2174
  else
 
2175
    {
 
2176
      if (error->code != G_IO_ERROR_CANCELLED)
 
2177
        g_warning ("%s", error->message);
 
2178
      g_error_free (error);
 
2179
    }
 
2180
 
 
2181
  if (n > 0)
 
2182
    {
 
2183
      result = g_new0 (PPDName *, n + 1);
 
2184
      i = 0;
 
2185
      for (iter = driver_list; iter; iter = iter->next)
 
2186
        {
 
2187
          result[i] = iter->data;
 
2188
          i++;
 
2189
        }
 
2190
    }
 
2191
 
 
2192
  if (result)
 
2193
    {
 
2194
      gchar **ppds_names;
 
2195
 
 
2196
      data->result = result;
 
2197
 
 
2198
      ppds_names = g_new0 (gchar *, n + 1);
 
2199
      for (i = 0; i < n; i++)
 
2200
        ppds_names[i] = g_strdup (result[i]->ppd_name);
 
2201
 
 
2202
      get_ppds_attribute_async (ppds_names,
 
2203
                                "NickName",
 
2204
                                get_ppd_names_async_cb,
 
2205
                                data);
 
2206
 
 
2207
      g_strfreev (ppds_names);
 
2208
    }
 
2209
  else
 
2210
    {
 
2211
      data->callback (NULL,
 
2212
                      data->printer_name,
 
2213
                      g_cancellable_is_cancelled (data->cancellable),
 
2214
                      data->user_data);
 
2215
 
 
2216
      if (data->cancellable)
 
2217
        g_object_unref (data->cancellable);
 
2218
      g_free (data->printer_name);
 
2219
      g_free (data);
 
2220
    }
 
2221
}
 
2222
 
 
2223
static void
 
2224
get_device_attributes_cb (gchar    *device_id,
 
2225
                          gchar    *device_make_and_model,
 
2226
                          gchar    *device_uri,
 
2227
                          gpointer  user_data)
 
2228
{
 
2229
  GDBusConnection *bus;
 
2230
  GError          *error = NULL;
 
2231
  GPNData         *data = (GPNData *) user_data;
 
2232
 
 
2233
  if (g_cancellable_is_cancelled (data->cancellable))
 
2234
    goto out;
 
2235
 
 
2236
  if (!device_id || !device_make_and_model || !device_uri)
 
2237
    goto out;
 
2238
 
 
2239
  bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 
2240
  if (!bus)
 
2241
    {
 
2242
      g_warning ("Failed to get system bus: %s", error->message);
 
2243
      g_error_free (error);
 
2244
      goto out;
 
2245
    }
 
2246
 
 
2247
  g_dbus_connection_call (bus,
 
2248
                          SCP_BUS,
 
2249
                          SCP_PATH,
 
2250
                          SCP_IFACE,
 
2251
                          "GetBestDrivers",
 
2252
                          g_variant_new ("(sss)",
 
2253
                                         device_id,
 
2254
                                         device_make_and_model,
 
2255
                                         device_uri),
 
2256
                          G_VARIANT_TYPE ("(a(ss))"),
 
2257
                          G_DBUS_CALL_FLAGS_NONE,
 
2258
                          DBUS_TIMEOUT_LONG,
 
2259
                          data->cancellable,
 
2260
                          get_ppd_names_async_dbus_scb,
 
2261
                          data);
 
2262
 
 
2263
  return;
 
2264
 
 
2265
out:
 
2266
  data->callback (NULL,
 
2267
                  data->printer_name,
 
2268
                  g_cancellable_is_cancelled (data->cancellable),
 
2269
                  data->user_data);
 
2270
 
 
2271
  if (data->cancellable)
 
2272
    g_object_unref (data->cancellable);
 
2273
  g_free (data->printer_name);
 
2274
  g_free (data);
 
2275
}
 
2276
 
 
2277
static void
 
2278
get_device_attributes_async_dbus_cb (GObject      *source_object,
 
2279
                                     GAsyncResult *res,
 
2280
                                     gpointer      user_data)
 
2281
 
 
2282
{
 
2283
  GVariant *output;
 
2284
  GDAData  *data = (GDAData *) user_data;
 
2285
  GError   *error = NULL;
 
2286
  GList    *tmp;
 
2287
  gchar    *device_id = NULL;
 
2288
  gchar    *device_make_and_model = NULL;
 
2289
 
 
2290
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
2291
                                          res,
 
2292
                                          &error);
 
2293
  g_object_unref (source_object);
 
2294
 
 
2295
  if (output)
 
2296
    {
 
2297
      const gchar *ret_error;
 
2298
      GVariant    *devices_variant = NULL;
 
2299
 
 
2300
      g_variant_get (output, "(&s@a{ss})",
 
2301
                     &ret_error,
 
2302
                     &devices_variant);
 
2303
 
 
2304
      if (ret_error[0] != '\0')
 
2305
        {
 
2306
          g_warning ("%s", ret_error);
 
2307
        }
 
2308
 
 
2309
      if (devices_variant)
 
2310
        {
 
2311
          GVariantIter *iter;
 
2312
          GVariant     *item;
 
2313
          gint          index = -1;
 
2314
 
 
2315
          if (data->device_uri)
 
2316
            {
 
2317
              gchar *key;
 
2318
              gchar *value;
 
2319
              gchar *number;
 
2320
              gchar *endptr;
 
2321
              gchar *suffix;
 
2322
 
 
2323
              g_variant_get (devices_variant,
 
2324
                             "a{ss}",
 
2325
                             &iter);
 
2326
 
 
2327
              while ((item = g_variant_iter_next_value (iter)))
 
2328
                {
 
2329
                  g_variant_get (item,
 
2330
                                 "{ss}",
 
2331
                                 &key,
 
2332
                                 &value);
 
2333
 
 
2334
                  if (g_str_equal (value, data->device_uri))
 
2335
                    {
 
2336
                      number = g_strrstr (key, ":");
 
2337
                      if (number != NULL)
 
2338
                        {
 
2339
                          number++;
 
2340
                          index = g_ascii_strtoll (number, &endptr, 10);
 
2341
                          if (index == 0 && endptr == (number))
 
2342
                            index = -1;
 
2343
                        }
 
2344
                    }
 
2345
 
 
2346
                  g_free (key);
 
2347
                  g_free (value);
 
2348
                  g_variant_unref (item);
 
2349
                }
 
2350
 
 
2351
              suffix = g_strdup_printf (":%d", index);
 
2352
 
 
2353
              g_variant_get (devices_variant,
 
2354
                             "a{ss}",
 
2355
                             &iter);
 
2356
 
 
2357
              while ((item = g_variant_iter_next_value (iter)))
 
2358
                {
 
2359
                  gchar *key;
 
2360
                  gchar *value;
 
2361
 
 
2362
                  g_variant_get (item,
 
2363
                                 "{ss}",
 
2364
                                 &key,
 
2365
                                 &value);
 
2366
 
 
2367
                  if (g_str_has_suffix (key, suffix))
 
2368
                    {
 
2369
                      if (g_str_has_prefix (key, "device-id"))
 
2370
                        {
 
2371
                          device_id = g_strdup (value);
 
2372
                        }
 
2373
 
 
2374
                      if (g_str_has_prefix (key, "device-make-and-model"))
 
2375
                        {
 
2376
                          device_make_and_model = g_strdup (value);
 
2377
                        }
 
2378
                    }
 
2379
 
 
2380
                  g_free (key);
 
2381
                  g_free (value);
 
2382
                  g_variant_unref (item);
 
2383
                }
 
2384
 
 
2385
              g_free (suffix);
 
2386
            }
 
2387
 
 
2388
          g_variant_unref (devices_variant);
 
2389
        }
 
2390
 
 
2391
      g_variant_unref (output);
 
2392
    }
 
2393
  else
 
2394
    {
 
2395
      if (error->code != G_IO_ERROR_CANCELLED)
 
2396
        g_warning ("%s", error->message);
 
2397
      g_error_free (error);
 
2398
    }
 
2399
 
 
2400
  if (!device_id || !device_make_and_model)
 
2401
    {
 
2402
      GVariantBuilder include_scheme_builder;
 
2403
 
 
2404
      g_free (device_id);
 
2405
      g_free (device_make_and_model);
 
2406
 
 
2407
      device_id = NULL;
 
2408
      device_make_and_model = NULL;
 
2409
 
 
2410
      if (data->backend_list && !g_cancellable_is_cancelled (data->cancellable))
 
2411
        {
 
2412
          g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
 
2413
          g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
 
2414
 
 
2415
          tmp = data->backend_list;
 
2416
          data->backend_list = g_list_remove_link (data->backend_list, tmp);
 
2417
          g_list_free_full (tmp, g_free);
 
2418
 
 
2419
          g_dbus_connection_call (G_DBUS_CONNECTION (g_object_ref (source_object)),
 
2420
                                  MECHANISM_BUS,
 
2421
                                  "/",
 
2422
                                  MECHANISM_BUS,
 
2423
                                  "DevicesGet",
 
2424
                                  g_variant_new ("(iiasas)",
 
2425
                                                 0,
 
2426
                                                 0,
 
2427
                                                 &include_scheme_builder,
 
2428
                                                 NULL),
 
2429
                                  G_VARIANT_TYPE ("(sa{ss})"),
 
2430
                                  G_DBUS_CALL_FLAGS_NONE,
 
2431
                                  DBUS_TIMEOUT,
 
2432
                                  data->cancellable,
 
2433
                                  get_device_attributes_async_dbus_cb,
 
2434
                                  user_data);
 
2435
          return;
 
2436
        }
 
2437
    }
 
2438
 
 
2439
  g_object_unref (source_object);
 
2440
 
 
2441
  if (data->backend_list)
 
2442
    {
 
2443
      g_list_free_full (data->backend_list, g_free);
 
2444
      data->backend_list = NULL;
 
2445
    }
 
2446
 
 
2447
  data->callback (device_id,
 
2448
                  device_make_and_model,
 
2449
                  data->device_uri,
 
2450
                  data->user_data);
 
2451
 
 
2452
  if (data->cancellable)
 
2453
    g_object_unref (data->cancellable);
 
2454
  g_free (data->device_uri);
 
2455
  g_free (data->printer_name);
 
2456
  g_free (data);
 
2457
}
 
2458
 
 
2459
static void
 
2460
get_device_attributes_async_scb (GHashTable *result,
 
2461
                                 gpointer    user_data)
 
2462
{
 
2463
  GDBusConnection *bus;
 
2464
  GVariantBuilder  include_scheme_builder;
 
2465
  IPPAttribute    *attr;
 
2466
  GDAData         *data = (GDAData *) user_data;
 
2467
  GError          *error = NULL;
 
2468
  GList           *tmp;
 
2469
  gint             i;
 
2470
  const gchar     *backends[] =
 
2471
    {"hpfax", "ncp", "beh", "bluetooth", "snmp",
 
2472
     "dnssd", "hp", "ipp", "lpd", "parallel",
 
2473
     "serial", "socket", "usb", NULL};
 
2474
 
 
2475
  if (result)
 
2476
    {
 
2477
      attr = g_hash_table_lookup (result, "device-uri");
 
2478
      if (attr && attr->attribute_type == IPP_ATTRIBUTE_TYPE_STRING &&
 
2479
          attr->num_of_values > 0)
 
2480
      data->device_uri = g_strdup (attr->attribute_values[0].string_value);
 
2481
      g_hash_table_unref (result);
 
2482
    }
 
2483
 
 
2484
  if (g_cancellable_is_cancelled (data->cancellable))
 
2485
    goto out;
 
2486
 
 
2487
  if (!data->device_uri)
 
2488
    goto out;
 
2489
 
 
2490
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
2491
  if (!bus)
 
2492
    {
 
2493
      g_warning ("Failed to get system bus: %s", error->message);
 
2494
      g_error_free (error);
 
2495
      goto out;
 
2496
    }
 
2497
 
 
2498
  for (i = 0; backends[i]; i++)
 
2499
    data->backend_list = g_list_prepend (data->backend_list, g_strdup (backends[i]));
 
2500
 
 
2501
  g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
 
2502
  g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
 
2503
 
 
2504
  tmp = data->backend_list;
 
2505
  data->backend_list = g_list_remove_link (data->backend_list, tmp);
 
2506
  g_list_free_full (tmp, g_free);
 
2507
 
 
2508
  g_dbus_connection_call (g_object_ref (bus),
 
2509
                          MECHANISM_BUS,
 
2510
                          "/",
 
2511
                          MECHANISM_BUS,
 
2512
                          "DevicesGet",
 
2513
                          g_variant_new ("(iiasas)",
 
2514
                                         0,
 
2515
                                         0,
 
2516
                                         &include_scheme_builder,
 
2517
                                         NULL),
 
2518
                          G_VARIANT_TYPE ("(sa{ss})"),
 
2519
                          G_DBUS_CALL_FLAGS_NONE,
 
2520
                          DBUS_TIMEOUT,
 
2521
                          data->cancellable,
 
2522
                          get_device_attributes_async_dbus_cb,
 
2523
                          data);
 
2524
 
 
2525
  return;
 
2526
 
 
2527
out:
 
2528
  data->callback (NULL, NULL, NULL, data->user_data);
 
2529
 
 
2530
  if (data->cancellable)
 
2531
    g_object_unref (data->cancellable);
 
2532
  g_free (data->device_uri);
 
2533
  g_free (data->printer_name);
 
2534
  g_free (data);
 
2535
}
 
2536
 
 
2537
/*
 
2538
 * Get device-id, device-make-and-model and device-uri for given printer.
 
2539
 */
 
2540
static void
 
2541
get_device_attributes_async (const gchar  *printer_name,
 
2542
                             GCancellable *cancellable,
 
2543
                             GDACallback   callback,
 
2544
                             gpointer      user_data)
 
2545
{
 
2546
  GDAData  *data;
 
2547
  gchar   **attributes;
 
2548
 
 
2549
  if (!printer_name)
 
2550
   {
 
2551
     callback (NULL, NULL, NULL, user_data);
 
2552
     return;
 
2553
   }
 
2554
 
 
2555
  data = g_new0 (GDAData, 1);
 
2556
  data->printer_name = g_strdup (printer_name);
 
2557
  if (cancellable)
 
2558
    data->cancellable = g_object_ref (cancellable);
 
2559
  data->callback = callback;
 
2560
  data->user_data = user_data;
 
2561
 
 
2562
  attributes = g_new0 (gchar *, 2);
 
2563
  attributes[0] = g_strdup ("device-uri");
 
2564
 
 
2565
  get_ipp_attributes_async (printer_name,
 
2566
                            attributes,
 
2567
                            get_device_attributes_async_scb,
 
2568
                            data);
 
2569
 
 
2570
  g_strfreev (attributes);
 
2571
}
 
2572
 
 
2573
/*
 
2574
 * Return "count" best matching driver names for given printer.
 
2575
 */
 
2576
void
 
2577
get_ppd_names_async (gchar        *printer_name,
 
2578
                     gint          count,
 
2579
                     GCancellable *cancellable,
 
2580
                     GPNCallback   callback,
 
2581
                     gpointer      user_data)
 
2582
{
 
2583
  GPNData *data;
 
2584
 
 
2585
  if (!printer_name)
 
2586
    {
 
2587
      callback (NULL, NULL, TRUE, user_data);
 
2588
      return;
 
2589
    }
 
2590
 
 
2591
  data = g_new0 (GPNData, 1);
 
2592
  data->printer_name = g_strdup (printer_name);
 
2593
  data->count = count;
 
2594
  if (cancellable)
 
2595
    data->cancellable = g_object_ref (cancellable);
 
2596
  data->callback = callback;
 
2597
  data->user_data = user_data;
 
2598
 
 
2599
  /*
 
2600
   * We have to find out device-id for this printer at first.
 
2601
   */
 
2602
  get_device_attributes_async (printer_name,
 
2603
                               cancellable,
 
2604
                               get_device_attributes_cb,
 
2605
                               data);
 
2606
}
 
2607
 
 
2608
typedef struct
 
2609
{
 
2610
  PPDList      *result;
 
2611
  GCancellable *cancellable;
 
2612
  GAPCallback   callback;
 
2613
  gpointer      user_data;
 
2614
  GMainContext *context;
 
2615
} GAPData;
 
2616
 
 
2617
static gboolean
 
2618
get_all_ppds_idle_cb (gpointer user_data)
 
2619
{
 
2620
  GAPData *data = (GAPData *) user_data;
 
2621
 
 
2622
  /* Don't call callback if cancelled */
 
2623
  if (data->cancellable &&
 
2624
      g_cancellable_is_cancelled (data->cancellable))
 
2625
    {
 
2626
      ppd_list_free (data->result);
 
2627
      data->result = NULL;
 
2628
    }
 
2629
  else
 
2630
    {
 
2631
      data->callback (data->result, data->user_data);
 
2632
    }
 
2633
 
 
2634
  return FALSE;
 
2635
}
 
2636
 
 
2637
static void
 
2638
get_all_ppds_data_free (gpointer user_data)
 
2639
{
 
2640
  GAPData *data = (GAPData *) user_data;
 
2641
 
 
2642
  if (data->context)
 
2643
    g_main_context_unref (data->context);
 
2644
  if (data->cancellable)
 
2645
    g_object_unref (data->cancellable);
 
2646
  g_free (data);
 
2647
}
 
2648
 
 
2649
static void
 
2650
get_all_ppds_cb (gpointer user_data)
 
2651
{
 
2652
  GAPData *data = (GAPData *) user_data;
 
2653
  GSource *idle_source;
 
2654
 
 
2655
  idle_source = g_idle_source_new ();
 
2656
  g_source_set_callback (idle_source,
 
2657
                         get_all_ppds_idle_cb,
 
2658
                         data,
 
2659
                         get_all_ppds_data_free);
 
2660
  g_source_attach (idle_source, data->context);
 
2661
  g_source_unref (idle_source);
 
2662
}
 
2663
 
 
2664
static const struct {
 
2665
  const char *normalized_name;
 
2666
  const char *display_name;
 
2667
} manufacturers_names[] = {
 
2668
  { "alps", "Alps" },
 
2669
  { "anitech", "Anitech" },
 
2670
  { "apple", "Apple" },
 
2671
  { "apollo", "Apollo" },
 
2672
  { "brother", "Brother" },
 
2673
  { "canon", "Canon" },
 
2674
  { "citizen", "Citizen" },
 
2675
  { "citoh", "Citoh" },
 
2676
  { "compaq", "Compaq" },
 
2677
  { "dec", "DEC" },
 
2678
  { "dell", "Dell" },
 
2679
  { "dnp", "DNP" },
 
2680
  { "dymo", "Dymo" },
 
2681
  { "epson", "Epson" },
 
2682
  { "fujifilm", "Fujifilm" },
 
2683
  { "fujitsu", "Fujitsu" },
 
2684
  { "gelsprinter", "Ricoh" },
 
2685
  { "generic", "Generic" },
 
2686
  { "genicom", "Genicom" },
 
2687
  { "gestetner", "Gestetner" },
 
2688
  { "hewlett packard", "Hewlett-Packard" },
 
2689
  { "heidelberg", "Heidelberg" },
 
2690
  { "hitachi", "Hitachi" },
 
2691
  { "hp", "Hewlett-Packard" },
 
2692
  { "ibm", "IBM" },
 
2693
  { "imagen", "Imagen" },
 
2694
  { "imagistics", "Imagistics" },
 
2695
  { "infoprint", "InfoPrint" },
 
2696
  { "infotec", "Infotec" },
 
2697
  { "intellitech", "Intellitech" },
 
2698
  { "kodak", "Kodak" },
 
2699
  { "konica minolta", "Minolta" },
 
2700
  { "kyocera", "Kyocera" },
 
2701
  { "kyocera mita", "Kyocera" },
 
2702
  { "lanier", "Lanier" },
 
2703
  { "lexmark international", "Lexmark" },
 
2704
  { "lexmark", "Lexmark" },
 
2705
  { "minolta", "Minolta" },
 
2706
  { "minolta qms", "Minolta" },
 
2707
  { "mitsubishi", "Mitsubishi" },
 
2708
  { "nec", "NEC" },
 
2709
  { "nrg", "NRG" },
 
2710
  { "oce", "Oce" },
 
2711
  { "oki", "Oki" },
 
2712
  { "oki data corp", "Oki" },
 
2713
  { "olivetti", "Olivetti" },
 
2714
  { "olympus", "Olympus" },
 
2715
  { "panasonic", "Panasonic" },
 
2716
  { "pcpi", "PCPI" },
 
2717
  { "pentax", "Pentax" },
 
2718
  { "qms", "QMS" },
 
2719
  { "raven", "Raven" },
 
2720
  { "raw", "Raw" },
 
2721
  { "ricoh", "Ricoh" },
 
2722
  { "samsung", "Samsung" },
 
2723
  { "savin", "Savin" },
 
2724
  { "seiko", "Seiko" },
 
2725
  { "sharp", "Sharp" },
 
2726
  { "shinko", "Shinko" },
 
2727
  { "sipix", "SiPix" },
 
2728
  { "sony", "Sony" },
 
2729
  { "star", "Star" },
 
2730
  { "tally", "Tally" },
 
2731
  { "tektronix", "Tektronix" },
 
2732
  { "texas instruments", "Texas Instruments" },
 
2733
  { "toshiba", "Toshiba" },
 
2734
  { "toshiba tec corp.", "Toshiba" },
 
2735
  { "xante", "Xante" },
 
2736
  { "xerox", "Xerox" },
 
2737
  { "zebra", "Zebra" },
 
2738
};
 
2739
 
 
2740
static gpointer
 
2741
get_all_ppds_func (gpointer user_data)
 
2742
{
 
2743
  ipp_attribute_t *attr;
 
2744
  GHashTable      *ppds_hash = NULL;
 
2745
  GHashTable      *manufacturers_hash = NULL;
 
2746
  GAPData         *data = (GAPData *) user_data;
 
2747
  PPDName         *item;
 
2748
  ipp_t           *request;
 
2749
  ipp_t           *response;
 
2750
  GList           *list;
 
2751
  const gchar     *ppd_make_and_model;
 
2752
  const gchar     *ppd_device_id;
 
2753
  const gchar     *ppd_name;
 
2754
  const gchar     *ppd_product;
 
2755
  const gchar     *ppd_make;
 
2756
  gchar           *mfg;
 
2757
  gchar           *mfg_normalized;
 
2758
  gchar           *mdl;
 
2759
  gchar           *manufacturer_display_name;
 
2760
  gint             i, j;
 
2761
 
 
2762
  request = ippNewRequest (CUPS_GET_PPDS);
 
2763
  response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
 
2764
 
 
2765
  if (response &&
 
2766
      ippGetStatusCode (response) <= IPP_OK_CONFLICT)
 
2767
    {
 
2768
      /*
 
2769
       * This hash contains names of manufacturers as keys and
 
2770
       * values are GLists of PPD names.
 
2771
       */
 
2772
      ppds_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
2773
 
 
2774
      /*
 
2775
       * This hash contains all possible names of manufacturers as keys
 
2776
       * and values are just first occurences of their equivalents.
 
2777
       * This is for mapping of e.g. "Hewlett Packard" and "HP" to the same name
 
2778
       * (the one which comes first).
 
2779
       */
 
2780
      manufacturers_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
2781
 
 
2782
      for (i = 0; i < G_N_ELEMENTS (manufacturers_names); i++)
 
2783
        {
 
2784
          g_hash_table_insert (manufacturers_hash,
 
2785
                               g_strdup (manufacturers_names[i].normalized_name),
 
2786
                               g_strdup (manufacturers_names[i].display_name));
 
2787
        }
 
2788
 
 
2789
      for (attr = ippFirstAttribute (response); attr != NULL; attr = ippNextAttribute (response))
 
2790
        {
 
2791
          while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
 
2792
            attr = ippNextAttribute (response);
 
2793
 
 
2794
          if (attr == NULL)
 
2795
            break;
 
2796
 
 
2797
          ppd_device_id = NULL;
 
2798
          ppd_make_and_model = NULL;
 
2799
          ppd_name = NULL;
 
2800
          ppd_product = NULL;
 
2801
          ppd_make = NULL;
 
2802
          mfg = NULL;
 
2803
          mfg_normalized = NULL;
 
2804
          mdl = NULL;
 
2805
 
 
2806
          while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
 
2807
            {
 
2808
              if (g_strcmp0 (ippGetName (attr), "ppd-device-id") == 0 &&
 
2809
                  ippGetValueTag (attr) == IPP_TAG_TEXT)
 
2810
                ppd_device_id = ippGetString (attr, 0, NULL);
 
2811
              else if (g_strcmp0 (ippGetName (attr), "ppd-make-and-model") == 0 &&
 
2812
                       ippGetValueTag (attr) == IPP_TAG_TEXT)
 
2813
                ppd_make_and_model = ippGetString (attr, 0, NULL);
 
2814
              else if (g_strcmp0 (ippGetName (attr), "ppd-name") == 0 &&
 
2815
                       ippGetValueTag (attr) == IPP_TAG_NAME)
 
2816
                ppd_name = ippGetString (attr, 0, NULL);
 
2817
              else if (g_strcmp0 (ippGetName (attr), "ppd-product") == 0 &&
 
2818
                       ippGetValueTag (attr) == IPP_TAG_TEXT)
 
2819
                ppd_product = ippGetString (attr, 0, NULL);
 
2820
              else if (g_strcmp0 (ippGetName (attr), "ppd-make") == 0 &&
 
2821
                       ippGetValueTag (attr) == IPP_TAG_TEXT)
 
2822
                ppd_make = ippGetString (attr, 0, NULL);
 
2823
 
 
2824
              attr = ippNextAttribute (response);
 
2825
            }
 
2826
 
 
2827
          /* Get manufacturer's name */
 
2828
          if (ppd_device_id && ppd_device_id[0] != '\0')
 
2829
            {
 
2830
              mfg = get_tag_value (ppd_device_id, "mfg");
 
2831
              if (!mfg)
 
2832
                mfg = get_tag_value (ppd_device_id, "manufacturer");
 
2833
              mfg_normalized = normalize (mfg);
 
2834
            }
 
2835
 
 
2836
          if (!mfg &&
 
2837
              ppd_make &&
 
2838
              ppd_make[0] != '\0')
 
2839
            {
 
2840
              mfg = g_strdup (ppd_make);
 
2841
              mfg_normalized = normalize (ppd_make);
 
2842
            }
 
2843
 
 
2844
          /* Get model */
 
2845
          if (ppd_make_and_model &&
 
2846
              ppd_make_and_model[0] != '\0')
 
2847
            {
 
2848
              mdl = g_strdup (ppd_make_and_model);
 
2849
            }
 
2850
 
 
2851
          if (!mdl &&
 
2852
              ppd_product &&
 
2853
              ppd_product[0] != '\0')
 
2854
            {
 
2855
              mdl = g_strdup (ppd_product);
 
2856
            }
 
2857
 
 
2858
          if (!mdl &&
 
2859
              ppd_device_id &&
 
2860
              ppd_device_id[0] != '\0')
 
2861
            {
 
2862
              mdl = get_tag_value (ppd_device_id, "mdl");
 
2863
              if (!mdl)
 
2864
                mdl = get_tag_value (ppd_device_id, "model");
 
2865
            }
 
2866
 
 
2867
          if (ppd_name && ppd_name[0] != '\0' &&
 
2868
              mdl && mdl[0] != '\0' &&
 
2869
              mfg && mfg[0] != '\0')
 
2870
            {
 
2871
              manufacturer_display_name = g_hash_table_lookup (manufacturers_hash, mfg_normalized);
 
2872
              if (!manufacturer_display_name)
 
2873
                {
 
2874
                  g_hash_table_insert (manufacturers_hash, g_strdup (mfg_normalized), g_strdup (mfg));
 
2875
                }
 
2876
              else
 
2877
                {
 
2878
                  g_free (mfg_normalized);
 
2879
                  mfg_normalized = normalize (manufacturer_display_name);
 
2880
                }
 
2881
 
 
2882
              item = g_new0 (PPDName, 1);
 
2883
              item->ppd_name = g_strdup (ppd_name);
 
2884
              item->ppd_display_name = g_strdup (mdl);
 
2885
              item->ppd_match_level = -1;
 
2886
 
 
2887
              list = g_hash_table_lookup (ppds_hash, mfg_normalized);
 
2888
              if (list)
 
2889
                {
 
2890
                  list = g_list_append (list, item);
 
2891
                }
 
2892
              else
 
2893
                {
 
2894
                  list = g_list_append (list, item);
 
2895
                  g_hash_table_insert (ppds_hash, g_strdup (mfg_normalized), list);
 
2896
                }
 
2897
            }
 
2898
 
 
2899
          g_free (mdl);
 
2900
          g_free (mfg);
 
2901
          g_free (mfg_normalized);
 
2902
 
 
2903
          if (attr == NULL)
 
2904
            break;
 
2905
        }
 
2906
    }
 
2907
 
 
2908
  if (response)
 
2909
    ippDelete(response);
 
2910
 
 
2911
  if (ppds_hash &&
 
2912
      manufacturers_hash)
 
2913
    {
 
2914
      GHashTableIter  iter;
 
2915
      gpointer        key;
 
2916
      gpointer        value;
 
2917
      GList          *ppd_item;
 
2918
      GList          *sort_list = NULL;
 
2919
      GList          *list_iter;
 
2920
      gchar          *name;
 
2921
 
 
2922
      data->result = g_new0 (PPDList, 1);
 
2923
      data->result->num_of_manufacturers = g_hash_table_size (ppds_hash);
 
2924
      data->result->manufacturers = g_new0 (PPDManufacturerItem *, data->result->num_of_manufacturers);
 
2925
 
 
2926
      g_hash_table_iter_init (&iter, ppds_hash);
 
2927
      while (g_hash_table_iter_next (&iter, &key, &value))
 
2928
        {
 
2929
          sort_list = g_list_append (sort_list, g_strdup (key));
 
2930
        }
 
2931
 
 
2932
      /* Sort list of manufacturers */
 
2933
      sort_list = g_list_sort (sort_list, (GCompareFunc) g_strcmp0);
 
2934
 
 
2935
      /*
 
2936
       * Fill resulting list of lists (list of manufacturers where
 
2937
       * each item contains list of PPD names)
 
2938
       */
 
2939
      i = 0;
 
2940
      for (list_iter = sort_list; list_iter; list_iter = list_iter->next)
 
2941
        {
 
2942
          name = (gchar *) list_iter->data;
 
2943
          value = g_hash_table_lookup (ppds_hash, name);
 
2944
 
 
2945
          data->result->manufacturers[i] = g_new0 (PPDManufacturerItem, 1);
 
2946
          data->result->manufacturers[i]->manufacturer_name = g_strdup (name);
 
2947
          data->result->manufacturers[i]->manufacturer_display_name = g_strdup (g_hash_table_lookup (manufacturers_hash, name));
 
2948
          data->result->manufacturers[i]->num_of_ppds = g_list_length ((GList *) value);
 
2949
          data->result->manufacturers[i]->ppds = g_new0 (PPDName *, data->result->manufacturers[i]->num_of_ppds);
 
2950
 
 
2951
          for (ppd_item = (GList *) value, j = 0; ppd_item; ppd_item = ppd_item->next, j++)
 
2952
            {
 
2953
              data->result->manufacturers[i]->ppds[j] = ppd_item->data;
 
2954
            }
 
2955
 
 
2956
          g_list_free ((GList *) value);
 
2957
 
 
2958
          i++;
 
2959
        }
 
2960
 
 
2961
      g_list_free_full (sort_list, g_free);
 
2962
      g_hash_table_destroy (ppds_hash);
 
2963
      g_hash_table_destroy (manufacturers_hash);
 
2964
    }
 
2965
 
 
2966
  get_all_ppds_cb (data);
 
2967
 
 
2968
  return NULL;
 
2969
}
 
2970
 
 
2971
/*
 
2972
 * Get names of all installed PPDs sorted by manufacturers names.
 
2973
 */
 
2974
void
 
2975
get_all_ppds_async (GCancellable *cancellable,
 
2976
                    GAPCallback   callback,
 
2977
                    gpointer      user_data)
 
2978
{
 
2979
  GAPData *data;
 
2980
  GThread *thread;
 
2981
  GError  *error = NULL;
 
2982
 
 
2983
  data = g_new0 (GAPData, 1);
 
2984
  if (cancellable)
 
2985
    data->cancellable = g_object_ref (cancellable);
 
2986
  data->callback = callback;
 
2987
  data->user_data = user_data;
 
2988
  data->context = g_main_context_ref_thread_default ();
 
2989
 
 
2990
  thread = g_thread_try_new ("get-all-ppds",
 
2991
                             get_all_ppds_func,
 
2992
                             data,
 
2993
                             &error);
 
2994
 
 
2995
  if (!thread)
 
2996
    {
 
2997
      g_warning ("%s", error->message);
 
2998
      callback (NULL, user_data);
 
2999
 
 
3000
      g_error_free (error);
 
3001
      get_all_ppds_data_free (data);
 
3002
    }
 
3003
  else
 
3004
    {
 
3005
      g_thread_unref (thread);
 
3006
    }
 
3007
}
 
3008
 
 
3009
PPDList *
 
3010
ppd_list_copy (PPDList *list)
 
3011
{
 
3012
  PPDList *result = NULL;
 
3013
  gint     i, j;
 
3014
 
 
3015
  if (list)
 
3016
    {
 
3017
      result = g_new0 (PPDList, 1);
 
3018
      result->num_of_manufacturers = list->num_of_manufacturers;
 
3019
      result->manufacturers = g_new0 (PPDManufacturerItem *, list->num_of_manufacturers);
 
3020
 
 
3021
      for (i = 0; i < result->num_of_manufacturers; i++)
 
3022
        {
 
3023
          result->manufacturers[i] = g_new0 (PPDManufacturerItem, 1);
 
3024
          result->manufacturers[i]->num_of_ppds = list->manufacturers[i]->num_of_ppds;
 
3025
          result->manufacturers[i]->ppds = g_new0 (PPDName *, result->manufacturers[i]->num_of_ppds);
 
3026
 
 
3027
          result->manufacturers[i]->manufacturer_display_name =
 
3028
            g_strdup (list->manufacturers[i]->manufacturer_display_name);
 
3029
 
 
3030
          result->manufacturers[i]->manufacturer_name =
 
3031
            g_strdup (list->manufacturers[i]->manufacturer_name);
 
3032
 
 
3033
          for (j = 0; j < result->manufacturers[i]->num_of_ppds; j++)
 
3034
            {
 
3035
              result->manufacturers[i]->ppds[j] = g_new0 (PPDName, 1);
 
3036
 
 
3037
              result->manufacturers[i]->ppds[j]->ppd_display_name =
 
3038
                g_strdup (list->manufacturers[i]->ppds[j]->ppd_display_name);
 
3039
 
 
3040
              result->manufacturers[i]->ppds[j]->ppd_name =
 
3041
                g_strdup (list->manufacturers[i]->ppds[j]->ppd_name);
 
3042
 
 
3043
              result->manufacturers[i]->ppds[j]->ppd_match_level =
 
3044
                list->manufacturers[i]->ppds[j]->ppd_match_level;
 
3045
            }
 
3046
        }
 
3047
    }
 
3048
 
 
3049
  return result;
 
3050
}
 
3051
 
 
3052
void
 
3053
ppd_list_free (PPDList *list)
 
3054
{
 
3055
  gint i, j;
 
3056
 
 
3057
  if (list)
 
3058
    {
 
3059
      for (i = 0; i < list->num_of_manufacturers; i++)
 
3060
        {
 
3061
          for (j = 0; j < list->manufacturers[i]->num_of_ppds; j++)
 
3062
            {
 
3063
              g_free (list->manufacturers[i]->ppds[j]->ppd_name);
 
3064
              g_free (list->manufacturers[i]->ppds[j]->ppd_display_name);
 
3065
              g_free (list->manufacturers[i]->ppds[j]);
 
3066
            }
 
3067
 
 
3068
          g_free (list->manufacturers[i]->manufacturer_name);
 
3069
          g_free (list->manufacturers[i]->manufacturer_display_name);
 
3070
          g_free (list->manufacturers[i]->ppds);
 
3071
          g_free (list->manufacturers[i]);
 
3072
        }
 
3073
 
 
3074
      g_free (list->manufacturers);
 
3075
      g_free (list);
 
3076
    }
 
3077
}
 
3078
 
 
3079
gchar *
 
3080
get_standard_manufacturers_name (gchar *name)
 
3081
{
 
3082
  gchar *normalized_name;
 
3083
  gchar *result = NULL;
 
3084
  gint   i;
 
3085
 
 
3086
  if (name)
 
3087
    {
 
3088
      normalized_name = normalize (name);
 
3089
 
 
3090
      for (i = 0; i < G_N_ELEMENTS (manufacturers_names); i++)
 
3091
        {
 
3092
          if (g_strcmp0 (manufacturers_names[i].normalized_name, normalized_name) == 0)
 
3093
            {
 
3094
              result = g_strdup (manufacturers_names[i].display_name);
 
3095
              break;
 
3096
            }
 
3097
        }
 
3098
 
 
3099
      g_free (normalized_name);
 
3100
    }
 
3101
 
 
3102
  return result;
 
3103
}
 
3104
 
 
3105
typedef struct
 
3106
{
 
3107
  gchar        *printer_name;
 
3108
  gchar        *host_name;
 
3109
  gint          port;
 
3110
  gchar        *result;
 
3111
  PGPCallback   callback;
 
3112
  gpointer      user_data;
 
3113
  GMainContext *context;
 
3114
} PGPData;
 
3115
 
 
3116
static gboolean
 
3117
printer_get_ppd_idle_cb (gpointer user_data)
 
3118
{
 
3119
  PGPData *data = (PGPData *) user_data;
 
3120
 
 
3121
  data->callback (data->result, data->user_data);
 
3122
 
 
3123
  return FALSE;
 
3124
}
 
3125
 
 
3126
static void
 
3127
printer_get_ppd_data_free (gpointer user_data)
 
3128
{
 
3129
  PGPData *data = (PGPData *) user_data;
 
3130
 
 
3131
  if (data->context)
 
3132
    g_main_context_unref (data->context);
 
3133
  g_free (data->result);
 
3134
  g_free (data->printer_name);
 
3135
  g_free (data->host_name);
 
3136
  g_free (data);
 
3137
}
 
3138
 
 
3139
static void
 
3140
printer_get_ppd_cb (gpointer user_data)
 
3141
{
 
3142
  PGPData *data = (PGPData *) user_data;
 
3143
  GSource *idle_source;
 
3144
 
 
3145
  idle_source = g_idle_source_new ();
 
3146
  g_source_set_callback (idle_source,
 
3147
                         printer_get_ppd_idle_cb,
 
3148
                         data,
 
3149
                         printer_get_ppd_data_free);
 
3150
  g_source_attach (idle_source, data->context);
 
3151
  g_source_unref (idle_source);
 
3152
}
 
3153
 
 
3154
static gpointer
 
3155
printer_get_ppd_func (gpointer user_data)
 
3156
{
 
3157
  PGPData *data = (PGPData *) user_data;
 
3158
 
 
3159
  if (data->host_name)
 
3160
    {
 
3161
      http_t *http;
 
3162
 
 
3163
      http = httpConnect (data->host_name, data->port);
 
3164
      if (http)
 
3165
        {
 
3166
          data->result = g_strdup (cupsGetPPD2 (http, data->printer_name));
 
3167
          httpClose (http);
 
3168
        }
 
3169
    }
 
3170
  else
 
3171
    {
 
3172
      data->result = g_strdup (cupsGetPPD (data->printer_name));
 
3173
    }
 
3174
 
 
3175
  printer_get_ppd_cb (data);
 
3176
 
 
3177
  return NULL;
 
3178
}
 
3179
 
 
3180
void
 
3181
printer_get_ppd_async (const gchar *printer_name,
 
3182
                       const gchar *host_name,
 
3183
                       gint         port,
 
3184
                       PGPCallback  callback,
 
3185
                       gpointer     user_data)
 
3186
{
 
3187
  PGPData *data;
 
3188
  GThread *thread;
 
3189
  GError  *error = NULL;
 
3190
 
 
3191
  data = g_new0 (PGPData, 1);
 
3192
  data->printer_name = g_strdup (printer_name);
 
3193
  data->host_name = g_strdup (host_name);
 
3194
  data->port = port;
 
3195
  data->callback = callback;
 
3196
  data->user_data = user_data;
 
3197
  data->context = g_main_context_ref_thread_default ();
 
3198
 
 
3199
  thread = g_thread_try_new ("printer-get-ppd",
 
3200
                             printer_get_ppd_func,
 
3201
                             data,
 
3202
                             &error);
 
3203
 
 
3204
  if (!thread)
 
3205
    {
 
3206
      g_warning ("%s", error->message);
 
3207
      callback (NULL, user_data);
 
3208
 
 
3209
      g_error_free (error);
 
3210
      printer_get_ppd_data_free (data);
 
3211
    }
 
3212
  else
 
3213
    {
 
3214
      g_thread_unref (thread);
 
3215
    }
 
3216
}
 
3217
 
 
3218
typedef struct
 
3219
{
 
3220
  gchar        *printer_name;
 
3221
  cups_dest_t  *result;
 
3222
  GNDCallback   callback;
 
3223
  gpointer      user_data;
 
3224
  GMainContext *context;
 
3225
} GNDData;
 
3226
 
 
3227
static gboolean
 
3228
get_named_dest_idle_cb (gpointer user_data)
 
3229
{
 
3230
  GNDData *data = (GNDData *) user_data;
 
3231
 
 
3232
  data->callback (data->result, data->user_data);
 
3233
 
 
3234
  return FALSE;
 
3235
}
 
3236
 
 
3237
static void
 
3238
get_named_dest_data_free (gpointer user_data)
 
3239
{
 
3240
  GNDData *data = (GNDData *) user_data;
 
3241
 
 
3242
  if (data->context)
 
3243
    g_main_context_unref (data->context);
 
3244
  g_free (data->printer_name);
 
3245
  g_free (data);
 
3246
}
 
3247
 
 
3248
static void
 
3249
get_named_dest_cb (gpointer user_data)
 
3250
{
 
3251
  GNDData *data = (GNDData *) user_data;
 
3252
  GSource *idle_source;
 
3253
 
 
3254
  idle_source = g_idle_source_new ();
 
3255
  g_source_set_callback (idle_source,
 
3256
                         get_named_dest_idle_cb,
 
3257
                         data,
 
3258
                         get_named_dest_data_free);
 
3259
  g_source_attach (idle_source, data->context);
 
3260
  g_source_unref (idle_source);
 
3261
}
 
3262
 
 
3263
static gpointer
 
3264
get_named_dest_func (gpointer user_data)
 
3265
{
 
3266
  GNDData *data = (GNDData *) user_data;
 
3267
 
 
3268
  data->result = cupsGetNamedDest (CUPS_HTTP_DEFAULT, data->printer_name, NULL);
 
3269
 
 
3270
  get_named_dest_cb (data);
 
3271
 
 
3272
  return NULL;
 
3273
}
 
3274
 
 
3275
void
 
3276
get_named_dest_async (const gchar *printer_name,
 
3277
                      GNDCallback  callback,
 
3278
                      gpointer     user_data)
 
3279
{
 
3280
  GNDData *data;
 
3281
  GThread *thread;
 
3282
  GError  *error = NULL;
 
3283
 
 
3284
  data = g_new0 (GNDData, 1);
 
3285
  data->printer_name = g_strdup (printer_name);
 
3286
  data->callback = callback;
 
3287
  data->user_data = user_data;
 
3288
  data->context = g_main_context_ref_thread_default ();
 
3289
 
 
3290
  thread = g_thread_try_new ("get-named-dest",
 
3291
                             get_named_dest_func,
 
3292
                             data,
 
3293
                             &error);
 
3294
 
 
3295
  if (!thread)
 
3296
    {
 
3297
      g_warning ("%s", error->message);
 
3298
      callback (NULL, user_data);
 
3299
 
 
3300
      g_error_free (error);
 
3301
      get_named_dest_data_free (data);
 
3302
    }
 
3303
  else
 
3304
    {
 
3305
      g_thread_unref (thread);
 
3306
    }
 
3307
}
 
3308
 
 
3309
typedef struct
 
3310
{
 
3311
  GCancellable *cancellable;
 
3312
  PAOCallback   callback;
 
3313
  gpointer      user_data;
 
3314
} PAOData;
 
3315
 
 
3316
static void
 
3317
printer_add_option_async_dbus_cb (GObject      *source_object,
 
3318
                                  GAsyncResult *res,
 
3319
                                  gpointer      user_data)
 
3320
{
 
3321
  GVariant *output;
 
3322
  gboolean  success = FALSE;
 
3323
  PAOData  *data = (PAOData *) user_data;
 
3324
  GError   *error = NULL;
 
3325
 
 
3326
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
3327
                                          res,
 
3328
                                          &error);
 
3329
  g_object_unref (source_object);
 
3330
 
 
3331
  if (output)
 
3332
    {
 
3333
      const gchar *ret_error;
 
3334
 
 
3335
      g_variant_get (output, "(&s)", &ret_error);
 
3336
      if (ret_error[0] != '\0')
 
3337
        g_warning ("%s", ret_error);
 
3338
      else
 
3339
        success = TRUE;
 
3340
 
 
3341
      g_variant_unref (output);
 
3342
    }
 
3343
  else
 
3344
    {
 
3345
      if (error->code != G_IO_ERROR_CANCELLED)
 
3346
        g_warning ("%s", error->message);
 
3347
      g_error_free (error);
 
3348
    }
 
3349
 
 
3350
  data->callback (success, data->user_data);
 
3351
 
 
3352
  if (data->cancellable)
 
3353
    g_object_unref (data->cancellable);
 
3354
  g_free (data);
 
3355
}
 
3356
 
 
3357
void
 
3358
printer_add_option_async (const gchar   *printer_name,
 
3359
                          const gchar   *option_name,
 
3360
                          gchar        **values,
 
3361
                          gboolean       set_default,
 
3362
                          GCancellable  *cancellable,
 
3363
                          PAOCallback    callback,
 
3364
                          gpointer       user_data)
 
3365
{
 
3366
  GVariantBuilder  array_builder;
 
3367
  GDBusConnection *bus;
 
3368
  PAOData         *data;
 
3369
  GError          *error = NULL;
 
3370
  gint             i;
 
3371
 
 
3372
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
3373
  if (!bus)
 
3374
   {
 
3375
     g_warning ("Failed to get system bus: %s", error->message);
 
3376
     g_error_free (error);
 
3377
     callback (FALSE, user_data);
 
3378
     return;
 
3379
   }
 
3380
 
 
3381
  g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
 
3382
  if (values)
 
3383
    {
 
3384
      for (i = 0; values[i]; i++)
 
3385
        g_variant_builder_add (&array_builder, "s", values[i]);
 
3386
    }
 
3387
 
 
3388
  data = g_new0 (PAOData, 1);
 
3389
  data->cancellable = cancellable;
 
3390
  data->callback = callback;
 
3391
  data->user_data = user_data;
 
3392
 
 
3393
  g_dbus_connection_call (bus,
 
3394
                          MECHANISM_BUS,
 
3395
                          "/",
 
3396
                          MECHANISM_BUS,
 
3397
                          set_default ? "PrinterAddOptionDefault" :
 
3398
                                        "PrinterAddOption",
 
3399
                          g_variant_new ("(ssas)",
 
3400
                                         printer_name,
 
3401
                                         option_name,
 
3402
                                         &array_builder),
 
3403
                          G_VARIANT_TYPE ("(s)"),
 
3404
                          G_DBUS_CALL_FLAGS_NONE,
 
3405
                          DBUS_TIMEOUT,
 
3406
                          cancellable,
 
3407
                          printer_add_option_async_dbus_cb,
 
3408
                          data);
 
3409
}
 
3410
 
 
3411
typedef struct
 
3412
{
 
3413
  GCancellable *cancellable;
 
3414
  GCDCallback   callback;
 
3415
  gpointer      user_data;
 
3416
  GList        *backend_list;
 
3417
} GCDData;
 
3418
 
 
3419
static gint
 
3420
get_suffix_index (gchar *string)
 
3421
{
 
3422
  gchar *number;
 
3423
  gchar *endptr;
 
3424
  gint   index = -1;
 
3425
 
 
3426
  number = g_strrstr (string, ":");
 
3427
  if (number)
 
3428
    {
 
3429
      number++;
 
3430
      index = g_ascii_strtoll (number, &endptr, 10);
 
3431
      if (index == 0 && endptr == number)
 
3432
        index = -1;
 
3433
    }
 
3434
 
 
3435
  return index;
 
3436
}
 
3437
 
 
3438
static void
 
3439
get_cups_devices_async_dbus_cb (GObject      *source_object,
 
3440
                                GAsyncResult *res,
 
3441
                                gpointer      user_data)
 
3442
 
 
3443
{
 
3444
  PpPrintDevice **devices = NULL;
 
3445
  GVariant       *output;
 
3446
  GCDData        *data = (GCDData *) user_data;
 
3447
  GError         *error = NULL;
 
3448
  GList          *result = NULL;
 
3449
  gint            num_of_devices = 0;
 
3450
 
 
3451
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
3452
                                          res,
 
3453
                                          &error);
 
3454
 
 
3455
  if (output)
 
3456
    {
 
3457
      const gchar *ret_error;
 
3458
      GVariant    *devices_variant = NULL;
 
3459
 
 
3460
      g_variant_get (output, "(&s@a{ss})",
 
3461
                     &ret_error,
 
3462
                     &devices_variant);
 
3463
 
 
3464
      if (ret_error[0] != '\0')
 
3465
        {
 
3466
          g_warning ("%s", ret_error);
 
3467
        }
 
3468
 
 
3469
      if (devices_variant)
 
3470
        {
 
3471
          GVariantIter *iter;
 
3472
          GVariant     *item;
 
3473
          gchar        *key;
 
3474
          gchar        *value;
 
3475
          gint          index = -1, max_index = -1, i;
 
3476
 
 
3477
          g_variant_get (devices_variant, "a{ss}", &iter);
 
3478
          while ((item = g_variant_iter_next_value (iter)))
 
3479
            {
 
3480
              g_variant_get (item, "{ss}", &key, &value);
 
3481
 
 
3482
              index = get_suffix_index (key);
 
3483
              if (index > max_index)
 
3484
                max_index = index;
 
3485
 
 
3486
              g_free (key);
 
3487
              g_free (value);
 
3488
              g_variant_unref (item);
 
3489
            }
 
3490
 
 
3491
          if (max_index >= 0)
 
3492
            {
 
3493
              num_of_devices = max_index + 1;
 
3494
              devices = g_new0 (PpPrintDevice *, num_of_devices);
 
3495
 
 
3496
              g_variant_get (devices_variant, "a{ss}", &iter);
 
3497
              while ((item = g_variant_iter_next_value (iter)))
 
3498
                {
 
3499
                  g_variant_get (item, "{ss}", &key, &value);
 
3500
 
 
3501
                  index = get_suffix_index (key);
 
3502
                  if (index >= 0)
 
3503
                    {
 
3504
                      if (!devices[index])
 
3505
                        devices[index] = g_new0 (PpPrintDevice, 1);
 
3506
 
 
3507
                      if (g_str_has_prefix (key, "device-class"))
 
3508
                        devices[index]->device_class = g_strdup (value);
 
3509
                      else if (g_str_has_prefix (key, "device-id"))
 
3510
                        devices[index]->device_id = g_strdup (value);
 
3511
                      else if (g_str_has_prefix (key, "device-info"))
 
3512
                        devices[index]->device_info = g_strdup (value);
 
3513
                      else if (g_str_has_prefix (key, "device-make-and-model"))
 
3514
                        {
 
3515
                          devices[index]->device_make_and_model = g_strdup (value);
 
3516
                          devices[index]->device_name = g_strdup (value);
 
3517
                        }
 
3518
                      else if (g_str_has_prefix (key, "device-uri"))
 
3519
                        devices[index]->device_uri = g_strdup (value);
 
3520
                      else if (g_str_has_prefix (key, "device-location"))
 
3521
                        devices[index]->device_location = g_strdup (value);
 
3522
 
 
3523
                      devices[index]->acquisition_method = ACQUISITION_METHOD_DEFAULT_CUPS_SERVER;
 
3524
                    }
 
3525
 
 
3526
                  g_free (key);
 
3527
                  g_free (value);
 
3528
                  g_variant_unref (item);
 
3529
                }
 
3530
 
 
3531
              for (i = 0; i < num_of_devices; i++)
 
3532
                result = g_list_append (result, devices[i]);
 
3533
 
 
3534
              g_free (devices);
 
3535
            }
 
3536
 
 
3537
          g_variant_unref (devices_variant);
 
3538
        }
 
3539
 
 
3540
      g_variant_unref (output);
 
3541
    }
 
3542
  else
 
3543
    {
 
3544
      if (error->domain != G_IO_ERROR ||
 
3545
          error->code != G_IO_ERROR_CANCELLED)
 
3546
        g_warning ("%s", error->message);
 
3547
      g_error_free (error);
 
3548
 
 
3549
      data->callback (result,
 
3550
                      TRUE,
 
3551
                      g_cancellable_is_cancelled (data->cancellable),
 
3552
                      data->user_data);
 
3553
 
 
3554
      g_list_free_full (data->backend_list, g_free);
 
3555
      data->backend_list = NULL;
 
3556
      g_object_unref (source_object);
 
3557
      if (data->cancellable)
 
3558
        g_object_unref (data->cancellable);
 
3559
      g_free (data);
 
3560
 
 
3561
      return;
 
3562
    }
 
3563
 
 
3564
  if (data->backend_list)
 
3565
    {
 
3566
      if (!g_cancellable_is_cancelled (data->cancellable))
 
3567
        {
 
3568
          GVariantBuilder include_scheme_builder;
 
3569
 
 
3570
          data->callback (result,
 
3571
                          FALSE,
 
3572
                          FALSE,
 
3573
                          data->user_data);
 
3574
 
 
3575
          g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
 
3576
          g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
 
3577
 
 
3578
          g_free (data->backend_list->data);
 
3579
          data->backend_list = g_list_remove_link (data->backend_list, data->backend_list);
 
3580
 
 
3581
          g_dbus_connection_call (G_DBUS_CONNECTION (g_object_ref (source_object)),
 
3582
                                  MECHANISM_BUS,
 
3583
                                  "/",
 
3584
                                  MECHANISM_BUS,
 
3585
                                  "DevicesGet",
 
3586
                                  g_variant_new ("(iiasas)",
 
3587
                                                 0,
 
3588
                                                 0,
 
3589
                                                 &include_scheme_builder,
 
3590
                                                 NULL),
 
3591
                                  G_VARIANT_TYPE ("(sa{ss})"),
 
3592
                                  G_DBUS_CALL_FLAGS_NONE,
 
3593
                                  DBUS_TIMEOUT,
 
3594
                                  data->cancellable,
 
3595
                                  get_cups_devices_async_dbus_cb,
 
3596
                                  user_data);
 
3597
          return;
 
3598
        }
 
3599
      else
 
3600
        {
 
3601
          data->callback (result,
 
3602
                          TRUE,
 
3603
                          TRUE,
 
3604
                          data->user_data);
 
3605
 
 
3606
          g_list_free_full (data->backend_list, g_free);
 
3607
          data->backend_list = NULL;
 
3608
        }
 
3609
    }
 
3610
  else
 
3611
    {
 
3612
      data->callback (result,
 
3613
                      TRUE,
 
3614
                      g_cancellable_is_cancelled (data->cancellable),
 
3615
                      data->user_data);
 
3616
    }
 
3617
 
 
3618
  g_object_unref (source_object);
 
3619
  if (data->cancellable)
 
3620
    g_object_unref (data->cancellable);
 
3621
  g_free (data);
 
3622
}
 
3623
 
 
3624
void
 
3625
get_cups_devices_async (GCancellable *cancellable,
 
3626
                        GCDCallback   callback,
 
3627
                        gpointer      user_data)
 
3628
{
 
3629
  GDBusConnection *bus;
 
3630
  GVariantBuilder  include_scheme_builder;
 
3631
  GCDData         *data;
 
3632
  GError          *error = NULL;
 
3633
  gint             i;
 
3634
  const gchar     *backends[] =
 
3635
    {"hpfax", "ncp", "beh", "bluetooth", "snmp",
 
3636
     "dnssd", "hp", "ipp", "lpd", "parallel",
 
3637
     "serial", "socket", "usb", NULL};
 
3638
 
 
3639
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
3640
  if (!bus)
 
3641
   {
 
3642
     g_warning ("Failed to get system bus: %s", error->message);
 
3643
     g_error_free (error);
 
3644
     callback (NULL, TRUE, FALSE, user_data);
 
3645
     return;
 
3646
   }
 
3647
 
 
3648
  data = g_new0 (GCDData, 1);
 
3649
  if (cancellable)
 
3650
    data->cancellable = g_object_ref (cancellable);
 
3651
  data->callback = callback;
 
3652
  data->user_data = user_data;
 
3653
  for (i = 0; backends[i]; i++)
 
3654
    data->backend_list = g_list_prepend (data->backend_list, g_strdup (backends[i]));
 
3655
 
 
3656
  g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
 
3657
  g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
 
3658
 
 
3659
  g_free (data->backend_list->data);
 
3660
  data->backend_list = g_list_remove_link (data->backend_list, data->backend_list);
 
3661
 
 
3662
  g_dbus_connection_call (bus,
 
3663
                          MECHANISM_BUS,
 
3664
                          "/",
 
3665
                          MECHANISM_BUS,
 
3666
                          "DevicesGet",
 
3667
                          g_variant_new ("(iiasas)",
 
3668
                                         0,
 
3669
                                         0,
 
3670
                                         &include_scheme_builder,
 
3671
                                         NULL),
 
3672
                          G_VARIANT_TYPE ("(sa{ss})"),
 
3673
                          G_DBUS_CALL_FLAGS_NONE,
 
3674
                          DBUS_TIMEOUT,
 
3675
                          cancellable,
 
3676
                          get_cups_devices_async_dbus_cb,
 
3677
                          data);
 
3678
}
 
3679
 
 
3680
void
 
3681
pp_print_device_free (PpPrintDevice *device)
 
3682
{
 
3683
  if (device)
 
3684
    {
 
3685
      g_free (device->device_class);
 
3686
      g_free (device->device_id);
 
3687
      g_free (device->device_info);
 
3688
      g_free (device->device_make_and_model);
 
3689
      g_free (device->device_uri);
 
3690
      g_free (device->device_location);
 
3691
      g_free (device->device_name);
 
3692
      g_free (device->device_ppd);
 
3693
      g_free (device);
 
3694
    }
 
3695
}
 
3696
 
 
3697
typedef struct
 
3698
{
 
3699
  gchar        *printer_name;
 
3700
  gboolean      my_jobs;
 
3701
  gint          which_jobs;
 
3702
  cups_job_t   *jobs;
 
3703
  gint          num_of_jobs;
 
3704
  CGJCallback   callback;
 
3705
  gpointer      user_data;
 
3706
  GMainContext *context;
 
3707
} CGJData;
 
3708
 
 
3709
static gboolean
 
3710
cups_get_jobs_idle_cb (gpointer user_data)
 
3711
{
 
3712
  CGJData *data = (CGJData *) user_data;
 
3713
 
 
3714
  data->callback (data->jobs,
 
3715
                  data->num_of_jobs,
 
3716
                  data->user_data);
 
3717
 
 
3718
  return FALSE;
 
3719
}
 
3720
 
 
3721
static void
 
3722
cups_get_jobs_data_free (gpointer user_data)
 
3723
{
 
3724
  CGJData *data = (CGJData *) user_data;
 
3725
 
 
3726
  if (data->context)
 
3727
    g_main_context_unref (data->context);
 
3728
  g_free (data->printer_name);
 
3729
  g_free (data);
 
3730
}
 
3731
 
 
3732
static void
 
3733
cups_get_jobs_cb (gpointer user_data)
 
3734
{
 
3735
  CGJData *data = (CGJData *) user_data;
 
3736
  GSource *idle_source;
 
3737
 
 
3738
  idle_source = g_idle_source_new ();
 
3739
  g_source_set_callback (idle_source,
 
3740
                         cups_get_jobs_idle_cb,
 
3741
                         data,
 
3742
                         cups_get_jobs_data_free);
 
3743
  g_source_attach (idle_source, data->context);
 
3744
  g_source_unref (idle_source);
 
3745
}
 
3746
 
 
3747
static gpointer
 
3748
cups_get_jobs_func (gpointer user_data)
 
3749
{
 
3750
  CGJData *data = (CGJData *) user_data;
 
3751
 
 
3752
  data->num_of_jobs = cupsGetJobs (&data->jobs,
 
3753
                                   data->printer_name,
 
3754
                                   data->my_jobs ? 1 : 0,
 
3755
                                   data->which_jobs);
 
3756
 
 
3757
  cups_get_jobs_cb (data);
 
3758
 
 
3759
  return NULL;
 
3760
}
 
3761
 
 
3762
void
 
3763
cups_get_jobs_async (const gchar *printer_name,
 
3764
                     gboolean     my_jobs,
 
3765
                     gint         which_jobs,
 
3766
                     CGJCallback  callback,
 
3767
                     gpointer     user_data)
 
3768
{
 
3769
  CGJData *data;
 
3770
  GThread *thread;
 
3771
  GError  *error = NULL;
 
3772
 
 
3773
  data = g_new0 (CGJData, 1);
 
3774
  data->printer_name = g_strdup (printer_name);
 
3775
  data->my_jobs = my_jobs;
 
3776
  data->which_jobs = which_jobs;
 
3777
  data->callback = callback;
 
3778
  data->user_data = user_data;
 
3779
  data->context = g_main_context_ref_thread_default ();
 
3780
 
 
3781
  thread = g_thread_try_new ("cups-get-jobs",
 
3782
                             cups_get_jobs_func,
 
3783
                             data,
 
3784
                             &error);
 
3785
 
 
3786
  if (!thread)
 
3787
    {
 
3788
      g_warning ("%s", error->message);
 
3789
      callback (NULL, 0, user_data);
 
3790
 
 
3791
      g_error_free (error);
 
3792
      cups_get_jobs_data_free (data);
 
3793
    }
 
3794
  else
 
3795
    {
 
3796
      g_thread_unref (thread);
 
3797
    }
 
3798
}
 
3799
 
 
3800
typedef struct
 
3801
{
 
3802
  GCancellable *cancellable;
 
3803
  JCPCallback   callback;
 
3804
  gpointer      user_data;
 
3805
} JCPData;
 
3806
 
 
3807
static void
 
3808
job_cancel_purge_async_dbus_cb (GObject      *source_object,
 
3809
                                GAsyncResult *res,
 
3810
                                gpointer      user_data)
 
3811
{
 
3812
  GVariant *output;
 
3813
  JCPData  *data = (JCPData *) user_data;
 
3814
  GError   *error = NULL;
 
3815
 
 
3816
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
3817
                                          res,
 
3818
                                          &error);
 
3819
  g_object_unref (source_object);
 
3820
 
 
3821
  if (output)
 
3822
    {
 
3823
      g_variant_unref (output);
 
3824
    }
 
3825
  else
 
3826
    {
 
3827
      if (!g_cancellable_is_cancelled (data->cancellable))
 
3828
        g_warning ("%s", error->message);
 
3829
      g_error_free (error);
 
3830
    }
 
3831
 
 
3832
  data->callback (data->user_data);
 
3833
 
 
3834
  if (data->cancellable)
 
3835
    g_object_unref (data->cancellable);
 
3836
  g_free (data);
 
3837
}
 
3838
 
 
3839
void
 
3840
job_cancel_purge_async (gint          job_id,
 
3841
                        gboolean      job_purge,
 
3842
                        GCancellable *cancellable,
 
3843
                        JCPCallback   callback,
 
3844
                        gpointer      user_data)
 
3845
{
 
3846
  GDBusConnection *bus;
 
3847
  JCPData         *data;
 
3848
  GError          *error = NULL;
 
3849
 
 
3850
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
3851
  if (!bus)
 
3852
    {
 
3853
      g_warning ("Failed to get session bus: %s", error->message);
 
3854
      g_error_free (error);
 
3855
      callback (user_data);
 
3856
      return;
 
3857
    }
 
3858
 
 
3859
  data = g_new0 (JCPData, 1);
 
3860
  if (cancellable)
 
3861
    data->cancellable = g_object_ref (cancellable);
 
3862
  data->callback = callback;
 
3863
  data->user_data = user_data;
 
3864
 
 
3865
  g_dbus_connection_call (bus,
 
3866
                          MECHANISM_BUS,
 
3867
                          "/",
 
3868
                          MECHANISM_BUS,
 
3869
                          "JobCancelPurge",
 
3870
                          g_variant_new ("(ib)",
 
3871
                                         job_id,
 
3872
                                         job_purge),
 
3873
                          G_VARIANT_TYPE ("(s)"),
 
3874
                          G_DBUS_CALL_FLAGS_NONE,
 
3875
                          -1,
 
3876
                          NULL,
 
3877
                          job_cancel_purge_async_dbus_cb,
 
3878
                          data);
 
3879
}
 
3880
 
 
3881
typedef struct
 
3882
{
 
3883
  GCancellable *cancellable;
 
3884
  JSHUCallback  callback;
 
3885
  gpointer      user_data;
 
3886
} JSHUData;
 
3887
 
 
3888
static void
 
3889
job_set_hold_until_async_dbus_cb (GObject      *source_object,
 
3890
                                  GAsyncResult *res,
 
3891
                                  gpointer      user_data)
 
3892
{
 
3893
  GVariant *output;
 
3894
  JSHUData *data = (JSHUData *) user_data;
 
3895
  GError   *error = NULL;
 
3896
 
 
3897
  output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
 
3898
                                          res,
 
3899
                                          &error);
 
3900
  g_object_unref (source_object);
 
3901
 
 
3902
  if (output)
 
3903
    {
 
3904
      g_variant_unref (output);
 
3905
    }
 
3906
  else
 
3907
    {
 
3908
      if (!g_cancellable_is_cancelled (data->cancellable))
 
3909
        g_warning ("%s", error->message);
 
3910
      g_error_free (error);
 
3911
    }
 
3912
 
 
3913
  data->callback (data->user_data);
 
3914
 
 
3915
  if (data->cancellable)
 
3916
    g_object_unref (data->cancellable);
 
3917
  g_free (data);
 
3918
}
 
3919
 
 
3920
void
 
3921
job_set_hold_until_async (gint          job_id,
 
3922
                          const gchar  *job_hold_until,
 
3923
                          GCancellable *cancellable,
 
3924
                          JSHUCallback  callback,
 
3925
                          gpointer      user_data)
 
3926
{
 
3927
  GDBusConnection *bus;
 
3928
  JSHUData        *data;
 
3929
  GError          *error = NULL;
 
3930
 
 
3931
  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
3932
  if (!bus)
 
3933
    {
 
3934
      g_warning ("Failed to get session bus: %s", error->message);
 
3935
      g_error_free (error);
 
3936
      callback (user_data);
 
3937
      return;
 
3938
    }
 
3939
 
 
3940
  data = g_new0 (JSHUData, 1);
 
3941
  if (cancellable)
 
3942
    data->cancellable = g_object_ref (cancellable);
 
3943
  data->callback = callback;
 
3944
  data->user_data = user_data;
 
3945
 
 
3946
  g_dbus_connection_call (bus,
 
3947
                          MECHANISM_BUS,
 
3948
                          "/",
 
3949
                          MECHANISM_BUS,
 
3950
                          "JobSetHoldUntil",
 
3951
                          g_variant_new ("(is)",
 
3952
                                         job_id,
 
3953
                                         job_hold_until),
 
3954
                          G_VARIANT_TYPE ("(s)"),
 
3955
                          G_DBUS_CALL_FLAGS_NONE,
 
3956
                          -1,
 
3957
                          NULL,
 
3958
                          job_set_hold_until_async_dbus_cb,
 
3959
                          data);
 
3960
}