1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright 2009-2010 Red Hat, Inc,
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.
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.
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.
24
#include <glib/gi18n.h>
25
#include <glib/gstdio.h>
27
#include <cups/cups.h>
28
#include <dbus/dbus-glib.h>
33
get_dbus_proxy (const gchar *name,
36
const gboolean system_bus)
44
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
46
bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
51
/* Translators: Program cannot connect to DBus' system bus */
52
g_warning ("Could not connect to system bus: %s", error->message);
54
/* Translators: Program cannot connect to DBus' session bus */
55
g_warning ("Could not connect to session bus: %s", error->message);
62
proxy = dbus_g_proxy_new_for_name (bus, name, path, iface);
67
gchar *get_tag_value (const gchar *tag_string, const gchar *tag_name)
69
gchar **tag_string_splitted = NULL;
70
gchar *tag_value = NULL;
71
gint tag_name_length = strlen (tag_name);
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);
85
get_ppd_name (gchar *device_class,
88
gchar *device_make_and_model,
90
gchar *device_location)
93
ipp_t *request = NULL;
94
ipp_t *response = NULL;
99
mfg = get_tag_value (device_id, "mfg");
100
mdl = get_tag_value (device_id, "mdl");
102
http = httpConnectEncrypt (cupsServer (),
108
request = ippNewRequest (CUPS_GET_PPDS);
110
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id",
113
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make",
115
response = cupsDoRequest (http, request, "/");
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;
127
for (attr = response->attrs; attr != NULL; attr = attr->next)
129
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
135
ppd_device_id = "NONE";
136
ppd_make_model = NULL;
142
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
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;
160
if (mfg && mdl && !result)
164
ppd_mfg = get_tag_value (ppd_device_id, "mfg");
166
if (ppd_mfg && g_ascii_strcasecmp (ppd_mfg, mfg) == 0)
168
ppd_mdl = get_tag_value (ppd_device_id, "mdl");
170
if (ppd_mdl && g_ascii_strcasecmp (ppd_mdl, mdl) == 0)
172
result = g_strdup (ppd_name);
195
get_dest_attr (const char *dest_name,
204
if (dest_name == NULL)
209
num_dests = cupsGetDests (&dests);
211
g_debug ("Unable to get printer destinations");
215
dest = cupsGetDest (dest_name, NULL, num_dests, dests);
217
g_debug ("Unable to find a printer named '%s'", dest_name);
221
value = cupsGetOption (attr, dest->num_options, dest->options);
223
g_debug ("Unable to get %s for '%s'", attr, dest_name);
226
ret = g_strdup (value);
228
cupsFreeDests (num_dests, dests);
234
execute_maintenance_command (const char *printer_name,
239
GError *error = NULL;
240
ipp_t *request = NULL;
241
ipp_t *response = NULL;
242
char uri[HTTP_MAX_URI + 1];
245
http = httpConnectEncrypt (cupsServer (),
251
request = ippNewRequest (IPP_PRINT_JOB);
255
"ipp://localhost/printers/%s",
258
ippAddString (request,
265
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
268
ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
269
NULL, "application/vnd.cups-command");
271
gchar *file_name = NULL;
272
fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
274
if (fd != -1 && !error)
278
file = fdopen (fd, "w");
279
fprintf (file, "#CUPS-COMMAND\n");
280
fprintf (file, "%s\n", command);
283
response = cupsDoFileRequest (http, request, "/", file_name);
284
g_unlink (file_name);
295
ccGetAllowedUsers (gchar ***allowed_users, const char *printer_name)
297
const char * const attrs[1] = { "requesting-user-name-allowed" };
299
ipp_t *request = NULL;
300
gchar **users = NULL;
302
char uri[HTTP_MAX_URI + 1];
303
int num_allowed_users = 0;
305
http = httpConnectEncrypt (cupsServer (),
309
if (http || !allowed_users)
311
request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
313
g_snprintf (uri, sizeof (uri), "ipp://localhost/printers/%s", printer_name);
314
ippAddString (request,
320
ippAddStrings (request,
323
"requested-attributes",
328
response = cupsDoRequest (http, request, "/");
331
ipp_attribute_t *attr = NULL;
332
ipp_attribute_t *allowed = NULL;
334
for (attr = response->attrs; attr != NULL; attr = attr->next)
336
if (attr->group_tag == IPP_TAG_PRINTER &&
337
attr->value_tag == IPP_TAG_NAME &&
338
!g_strcmp0 (attr->name, "requesting-user-name-allowed"))
342
if (allowed && allowed->num_values > 0)
346
num_allowed_users = allowed->num_values;
347
users = g_new (gchar*, num_allowed_users);
349
for (i = 0; i < num_allowed_users; i ++)
350
users[i] = g_strdup (allowed->values[i].string.text);
357
*allowed_users = users;
358
return num_allowed_users;
362
get_ppd_attribute (const gchar *ppd_file_name,
363
const gchar *attribute_name)
365
ppd_file_t *ppd_file = NULL;
366
ppd_attr_t *ppd_attr = NULL;
367
gchar *result = NULL;
371
ppd_file = ppdOpenFile (ppd_file_name);
375
ppd_attr = ppdFindAttr (ppd_file, attribute_name, NULL);
376
if (ppd_attr != NULL)
377
result = g_strdup (ppd_attr->value);
385
/* Cancels subscription of given id */
387
cancel_cups_subscription (gint id)
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, "/"));
407
/* Returns id of renewed subscription or new id */
409
renew_cups_subscription (gint id,
410
const char * const *events,
414
ipp_attribute_t *attr = NULL;
417
ipp_t *response = NULL;
420
if ((http = httpConnectEncrypt (cupsServer (), ippPort (),
421
cupsEncryption ())) == NULL) {
422
g_debug ("Connection to CUPS server \'%s\' failed.", cupsServer ());
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");
442
if (attr->values[0].integer == lease_duration)
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, "/");
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");
469
result = attr->values[0].integer;
474
ippDelete (response);
482
/* Set default destination in ~/.cups/lpoptions.
483
* Unset default destination if "dest" is NULL.
486
set_local_default_printer (gchar *printer_name)
488
cups_dest_t *dests = NULL;
492
num_dests = cupsGetDests (&dests);
494
for (i = 0; i < num_dests; i ++)
496
if (printer_name && g_strcmp0 (dests[i].name, printer_name) == 0)
497
dests[i].is_default = 1;
499
dests[i].is_default = 0;
502
cupsSetDests (num_dests, dests);