~ubuntu-branches/ubuntu/precise/gnome-control-center/precise-updates

« back to all changes in this revision

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

Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright 2009-2010  Red Hat, Inc,
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include <glib.h>
 
24
#include <glib/gi18n.h>
 
25
#include <glib/gstdio.h>
 
26
#include <gtk/gtk.h>
 
27
#include <cups/cups.h>
 
28
#include <dbus/dbus-glib.h>
 
29
 
 
30
#include "pp-utils.h"
 
31
 
 
32
DBusGProxy *
 
33
get_dbus_proxy (const gchar *name,
 
34
                const gchar *path,
 
35
                const gchar *iface,
 
36
                const gboolean system_bus)
 
37
{
 
38
  DBusGConnection *bus;
 
39
  DBusGProxy      *proxy;
 
40
  GError          *error;
 
41
 
 
42
  error = NULL;
 
43
  if (system_bus)
 
44
    bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 
45
  else
 
46
    bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
47
 
 
48
  if (bus == NULL)
 
49
    {
 
50
      if (system_bus)
 
51
        /* Translators: Program cannot connect to DBus' system bus */
 
52
        g_warning ("Could not connect to system bus: %s", error->message);
 
53
      else
 
54
        /* Translators: Program cannot connect to DBus' session bus */
 
55
        g_warning ("Could not connect to session bus: %s", error->message);
 
56
      g_error_free (error);
 
57
      return NULL;
 
58
    }
 
59
 
 
60
  error = NULL;
 
61
 
 
62
  proxy = dbus_g_proxy_new_for_name (bus, name, path, iface);
 
63
 
 
64
  return proxy;
 
65
}
 
66
 
 
67
gchar *get_tag_value (const gchar *tag_string, const gchar *tag_name)
 
68
{
 
69
  gchar **tag_string_splitted = NULL;
 
70
  gchar  *tag_value = NULL;
 
71
  gint    tag_name_length = strlen (tag_name);
 
72
  gint    i;
 
73
 
 
74
  tag_string_splitted = g_strsplit (tag_string, ";", 0);
 
75
  for (i = 0; i < g_strv_length (tag_string_splitted); i++)
 
76
    if (g_ascii_strncasecmp (tag_string_splitted[i], tag_name, tag_name_length) == 0)
 
77
      if (strlen (tag_string_splitted[i]) > tag_name_length + 1)
 
78
        tag_value = g_strdup (tag_string_splitted[i] + tag_name_length + 1);
 
79
  g_strfreev (tag_string_splitted);
 
80
 
 
81
  return tag_value;
 
82
}
 
83
 
 
84
gchar *
 
85
get_ppd_name (gchar *device_class,
 
86
              gchar *device_id,
 
87
              gchar *device_info,
 
88
              gchar *device_make_and_model,
 
89
              gchar *device_uri,
 
90
              gchar *device_location)
 
91
{
 
92
  http_t *http = NULL;
 
93
  ipp_t  *request = NULL;
 
94
  ipp_t  *response = NULL;
 
95
  gchar  *mfg = NULL;
 
96
  gchar  *mdl = NULL;
 
97
  gchar  *result = NULL;
 
98
 
 
99
  mfg = get_tag_value (device_id, "mfg");
 
100
  mdl = get_tag_value (device_id, "mdl");
 
101
 
 
102
  http = httpConnectEncrypt (cupsServer (),
 
103
                             ippPort (),
 
104
                             cupsEncryption ());
 
105
 
 
106
  if (http)
 
107
    {
 
108
      request = ippNewRequest (CUPS_GET_PPDS);
 
109
      if (device_id)
 
110
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id",
 
111
                     NULL, device_id);
 
112
      else if (mfg)
 
113
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make",
 
114
                     NULL, mfg);
 
115
      response = cupsDoRequest (http, request, "/");
 
116
 
 
117
      if (response)
 
118
        {
 
119
          ipp_attribute_t *attr = NULL;
 
120
          const char      *ppd_device_id;
 
121
          const char      *ppd_make_model;
 
122
          const char      *ppd_make;
 
123
          const char      *ppd_name;
 
124
          gchar           *ppd_mfg;
 
125
          gchar           *ppd_mdl;
 
126
 
 
127
          for (attr = response->attrs; attr != NULL; attr = attr->next)
 
128
            {
 
129
              while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
 
130
                attr = attr->next;
 
131
 
 
132
              if (attr == NULL)
 
133
                break;
 
134
 
 
135
              ppd_device_id  = "NONE";
 
136
              ppd_make_model = NULL;
 
137
              ppd_make       = NULL;
 
138
              ppd_name       = NULL;
 
139
              ppd_mfg        = NULL;
 
140
              ppd_mdl        = NULL;
 
141
 
 
142
              while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
 
143
                {
 
144
                  if (!strcmp(attr->name, "ppd-device-id") &&
 
145
                      attr->value_tag == IPP_TAG_TEXT)
 
146
                    ppd_device_id = attr->values[0].string.text;
 
147
                  else if (!strcmp(attr->name, "ppd-name") &&
 
148
                           attr->value_tag == IPP_TAG_NAME)
 
149
                    ppd_name = attr->values[0].string.text;
 
150
                  else if (!strcmp(attr->name, "ppd-make") &&
 
151
                           attr->value_tag == IPP_TAG_TEXT)
 
152
                    ppd_make = attr->values[0].string.text;
 
153
                  else if (!strcmp(attr->name, "ppd-make-and-model") &&
 
154
                           attr->value_tag == IPP_TAG_TEXT)
 
155
                    ppd_make_model = attr->values[0].string.text;
 
156
 
 
157
                  attr = attr->next;
 
158
                }
 
159
 
 
160
              if (mfg && mdl && !result)
 
161
                {
 
162
                  if (ppd_device_id)
 
163
                    {
 
164
                      ppd_mfg = get_tag_value (ppd_device_id, "mfg");
 
165
 
 
166
                      if (ppd_mfg && g_ascii_strcasecmp (ppd_mfg, mfg) == 0)
 
167
                        {
 
168
                          ppd_mdl = get_tag_value (ppd_device_id, "mdl");
 
169
 
 
170
                          if (ppd_mdl && g_ascii_strcasecmp (ppd_mdl, mdl) == 0)
 
171
                            {
 
172
                              result = g_strdup (ppd_name);
 
173
                              g_free (ppd_mdl);
 
174
                            }
 
175
                          g_free (ppd_mfg);
 
176
                        }
 
177
                    }
 
178
                }
 
179
 
 
180
              if (attr == NULL)
 
181
                break;
 
182
            }
 
183
          ippDelete(response);
 
184
        }
 
185
      httpClose (http);
 
186
    }
 
187
 
 
188
  g_free (mfg);
 
189
  g_free (mdl);
 
190
 
 
191
  return result;
 
192
}
 
193
 
 
194
char *
 
195
get_dest_attr (const char *dest_name,
 
196
               const char *attr)
 
197
{
 
198
  cups_dest_t *dests;
 
199
  int          num_dests;
 
200
  cups_dest_t *dest;
 
201
  const char  *value;
 
202
  char        *ret;
 
203
 
 
204
  if (dest_name == NULL)
 
205
          return NULL;
 
206
 
 
207
  ret = NULL;
 
208
 
 
209
  num_dests = cupsGetDests (&dests);
 
210
  if (num_dests < 1) {
 
211
          g_debug ("Unable to get printer destinations");
 
212
          return NULL;
 
213
  }
 
214
 
 
215
  dest = cupsGetDest (dest_name, NULL, num_dests, dests);
 
216
  if (dest == NULL) {
 
217
          g_debug ("Unable to find a printer named '%s'", dest_name);
 
218
          goto out;
 
219
  }
 
220
 
 
221
  value = cupsGetOption (attr, dest->num_options, dest->options);
 
222
  if (value == NULL) {
 
223
          g_debug ("Unable to get %s for '%s'", attr, dest_name);
 
224
          goto out;
 
225
  }
 
226
  ret = g_strdup (value);
 
227
out:
 
228
  cupsFreeDests (num_dests, dests);
 
229
 
 
230
  return ret;
 
231
}
 
232
 
 
233
ipp_t *
 
234
execute_maintenance_command (const char *printer_name,
 
235
                             const char *command,
 
236
                             const char *title)
 
237
{
 
238
  http_t *http;
 
239
  GError *error = NULL;
 
240
  ipp_t  *request = NULL;
 
241
  ipp_t  *response = NULL;
 
242
  char    uri[HTTP_MAX_URI + 1];
 
243
  int     fd = -1;
 
244
 
 
245
  http = httpConnectEncrypt (cupsServer (),
 
246
                             ippPort (),
 
247
                             cupsEncryption ());
 
248
 
 
249
  if (http)
 
250
    {
 
251
      request = ippNewRequest (IPP_PRINT_JOB);
 
252
 
 
253
      g_snprintf (uri,
 
254
                  sizeof (uri),
 
255
                  "ipp://localhost/printers/%s",
 
256
                  printer_name);
 
257
 
 
258
      ippAddString (request,
 
259
                    IPP_TAG_OPERATION,
 
260
                    IPP_TAG_URI,
 
261
                    "printer-uri",
 
262
                    NULL,
 
263
                    uri);
 
264
 
 
265
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
 
266
                    NULL, title);
 
267
 
 
268
      ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
 
269
                    NULL, "application/vnd.cups-command");
 
270
 
 
271
      gchar *file_name = NULL;
 
272
      fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
 
273
 
 
274
      if (fd != -1 && !error)
 
275
        {
 
276
          FILE *file;
 
277
 
 
278
          file = fdopen (fd, "w");
 
279
          fprintf (file, "#CUPS-COMMAND\n");
 
280
          fprintf (file, "%s\n", command);
 
281
          fclose (file);
 
282
 
 
283
          response = cupsDoFileRequest (http, request, "/", file_name);
 
284
          g_unlink (file_name);
 
285
        }
 
286
 
 
287
      g_free (file_name);
 
288
      httpClose (http);
 
289
    }
 
290
 
 
291
  return response;
 
292
}
 
293
 
 
294
int
 
295
ccGetAllowedUsers (gchar ***allowed_users, const char *printer_name)
 
296
{
 
297
  const char * const   attrs[1] = { "requesting-user-name-allowed" };
 
298
  http_t              *http;
 
299
  ipp_t               *request = NULL;
 
300
  gchar              **users = NULL;
 
301
  ipp_t               *response;
 
302
  char                 uri[HTTP_MAX_URI + 1];
 
303
  int                  num_allowed_users = 0;
 
304
 
 
305
  http = httpConnectEncrypt (cupsServer (),
 
306
                             ippPort (),
 
307
                             cupsEncryption ());
 
308
 
 
309
  if (http || !allowed_users)
 
310
    {
 
311
      request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
 
312
 
 
313
      g_snprintf (uri, sizeof (uri), "ipp://localhost/printers/%s", printer_name);
 
314
      ippAddString (request,
 
315
                    IPP_TAG_OPERATION,
 
316
                    IPP_TAG_URI,
 
317
                    "printer-uri",
 
318
                    NULL,
 
319
                    uri);
 
320
      ippAddStrings (request,
 
321
                     IPP_TAG_OPERATION,
 
322
                     IPP_TAG_KEYWORD,
 
323
                     "requested-attributes",
 
324
                     1,
 
325
                     NULL,
 
326
                     attrs);
 
327
 
 
328
      response = cupsDoRequest (http, request, "/");
 
329
      if (response)
 
330
        {
 
331
          ipp_attribute_t *attr = NULL;
 
332
          ipp_attribute_t *allowed = NULL;
 
333
 
 
334
          for (attr = response->attrs; attr != NULL; attr = attr->next)
 
335
            {
 
336
              if (attr->group_tag == IPP_TAG_PRINTER &&
 
337
                  attr->value_tag == IPP_TAG_NAME &&
 
338
                  !g_strcmp0 (attr->name, "requesting-user-name-allowed"))
 
339
                allowed = attr;
 
340
            }
 
341
 
 
342
          if (allowed && allowed->num_values > 0)
 
343
            {
 
344
              int i;
 
345
 
 
346
              num_allowed_users = allowed->num_values;
 
347
              users = g_new (gchar*, num_allowed_users);
 
348
 
 
349
              for (i = 0; i < num_allowed_users; i ++)
 
350
                users[i] = g_strdup (allowed->values[i].string.text);
 
351
            }
 
352
          ippDelete(response);
 
353
        }
 
354
       httpClose (http);
 
355
     }
 
356
 
 
357
  *allowed_users = users;
 
358
  return num_allowed_users;
 
359
}
 
360
 
 
361
gchar *
 
362
get_ppd_attribute (const gchar *ppd_file_name,
 
363
                   const gchar *attribute_name)
 
364
{
 
365
  ppd_file_t *ppd_file = NULL;
 
366
  ppd_attr_t *ppd_attr = NULL;
 
367
  gchar *result = NULL;
 
368
 
 
369
  if (ppd_file_name)
 
370
    {
 
371
      ppd_file = ppdOpenFile (ppd_file_name);
 
372
 
 
373
      if (ppd_file)
 
374
        {
 
375
          ppd_attr = ppdFindAttr (ppd_file, attribute_name, NULL);
 
376
          if (ppd_attr != NULL)
 
377
            result = g_strdup (ppd_attr->value);
 
378
          ppdClose (ppd_file);
 
379
        }
 
380
    }
 
381
 
 
382
  return result;
 
383
}
 
384
 
 
385
/* Cancels subscription of given id */
 
386
void
 
387
cancel_cups_subscription (gint id)
 
388
{
 
389
  http_t *http;
 
390
  ipp_t  *request;
 
391
 
 
392
  if (id >= 0 &&
 
393
      ((http = httpConnectEncrypt (cupsServer (), ippPort (),
 
394
                                  cupsEncryption ())) != NULL)) {
 
395
    request = ippNewRequest (IPP_CANCEL_SUBSCRIPTION);
 
396
    ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
397
                 "printer-uri", NULL, "/");
 
398
    ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 
399
                 "requesting-user-name", NULL, cupsUser ());
 
400
    ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
 
401
                  "notify-subscription-id", id);
 
402
    ippDelete (cupsDoRequest (http, request, "/"));
 
403
    httpClose (http);
 
404
  }
 
405
}
 
406
 
 
407
/* Returns id of renewed subscription or new id */
 
408
gint
 
409
renew_cups_subscription (gint id,
 
410
                         const char * const *events,
 
411
                         gint num_events,
 
412
                         gint lease_duration)
 
413
{
 
414
  ipp_attribute_t              *attr = NULL;
 
415
  http_t                       *http;
 
416
  ipp_t                        *request;
 
417
  ipp_t                        *response = NULL;
 
418
  gint                          result = -1;
 
419
 
 
420
  if ((http = httpConnectEncrypt (cupsServer (), ippPort (),
 
421
                                  cupsEncryption ())) == NULL) {
 
422
    g_debug ("Connection to CUPS server \'%s\' failed.", cupsServer ());
 
423
  }
 
424
  else {
 
425
    if (id >= 0) {
 
426
      request = ippNewRequest (IPP_RENEW_SUBSCRIPTION);
 
427
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
428
                   "printer-uri", NULL, "/");
 
429
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 
430
                   "requesting-user-name", NULL, cupsUser ());
 
431
      ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
 
432
                    "notify-subscription-id", id);
 
433
      ippAddInteger (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
 
434
                    "notify-lease-duration", lease_duration);
 
435
      response = cupsDoRequest (http, request, "/");
 
436
      if (response != NULL &&
 
437
          response->request.status.status_code <= IPP_OK_CONFLICT) {
 
438
        if ((attr = ippFindAttribute (response, "notify-lease-duration",
 
439
                                      IPP_TAG_INTEGER)) == NULL)
 
440
          g_debug ("No notify-lease-duration in response!\n");
 
441
        else
 
442
          if (attr->values[0].integer == lease_duration)
 
443
            result = id;
 
444
      }
 
445
    }
 
446
 
 
447
    if (result < 0) {
 
448
      request = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION);
 
449
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
450
                    "printer-uri", NULL, "/");
 
451
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 
452
                    "requesting-user-name", NULL, cupsUser ());
 
453
      ippAddStrings (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
 
454
                     "notify-events", num_events, NULL, events);
 
455
      ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
 
456
                    "notify-pull-method", NULL, "ippget");
 
457
      ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
 
458
                    "notify-recipient-uri", NULL, "dbus://");
 
459
      ippAddInteger (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
 
460
                     "notify-lease-duration", lease_duration);
 
461
      response = cupsDoRequest (http, request, "/");
 
462
 
 
463
      if (response != NULL &&
 
464
          response->request.status.status_code <= IPP_OK_CONFLICT) {
 
465
        if ((attr = ippFindAttribute (response, "notify-subscription-id",
 
466
                                      IPP_TAG_INTEGER)) == NULL)
 
467
          g_debug ("No notify-subscription-id in response!\n");
 
468
        else
 
469
          result = attr->values[0].integer;
 
470
      }
 
471
    }
 
472
 
 
473
    if (response)
 
474
      ippDelete (response);
 
475
 
 
476
    httpClose (http);
 
477
  }
 
478
 
 
479
  return result;
 
480
}
 
481
 
 
482
/*  Set default destination in ~/.cups/lpoptions.
 
483
 *  Unset default destination if "dest" is NULL.
 
484
 */
 
485
void
 
486
set_local_default_printer (gchar *printer_name)
 
487
{
 
488
  cups_dest_t *dests = NULL;
 
489
  int          num_dests = 0;
 
490
  int          i;
 
491
 
 
492
  num_dests = cupsGetDests (&dests);
 
493
 
 
494
  for (i = 0; i < num_dests; i ++)
 
495
    {
 
496
      if (printer_name && g_strcmp0 (dests[i].name, printer_name) == 0)
 
497
        dests[i].is_default = 1;
 
498
      else
 
499
        dests[i].is_default = 0;
 
500
    }
 
501
 
 
502
  cupsSetDests (num_dests, dests);
 
503
}