~ubuntu-branches/ubuntu/trusty/unity-control-center/trusty

« back to all changes in this revision

Viewing changes to panels/printers/pp-maintenance-command.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-01-08 16:29:18 UTC
  • Revision ID: package-import@ubuntu.com-20140108162918-g29dd08tr913y2qh
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

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 2012  Red Hat, Inc,
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Author: Marek Kasik <mkasik@redhat.com>
 
20
 */
 
21
 
 
22
#include <glib/gstdio.h>
 
23
 
 
24
#include "pp-maintenance-command.h"
 
25
 
 
26
#include "pp-utils.h"
 
27
 
 
28
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
 
29
#define HAVE_CUPS_1_6 1
 
30
#endif
 
31
 
 
32
#ifndef HAVE_CUPS_1_6
 
33
#define ippGetCount(attr)     attr->num_values
 
34
#define ippGetValueTag(attr)  attr->value_tag
 
35
#define ippGetStatusCode(ipp) ipp->request.status.status_code
 
36
#define ippGetString(attr, element, language) attr->values[element].string.text
 
37
#endif
 
38
 
 
39
struct _PpMaintenanceCommandPrivate
 
40
{
 
41
  gchar *printer_name;
 
42
  gchar *command;
 
43
  gchar *title;
 
44
};
 
45
 
 
46
G_DEFINE_TYPE (PpMaintenanceCommand, pp_maintenance_command, G_TYPE_OBJECT);
 
47
 
 
48
enum {
 
49
  PROP_0 = 0,
 
50
  PROP_PRINTER_NAME,
 
51
  PROP_COMMAND,
 
52
  PROP_TITLE
 
53
};
 
54
 
 
55
static void
 
56
pp_maintenance_command_finalize (GObject *object)
 
57
{
 
58
  PpMaintenanceCommandPrivate *priv;
 
59
 
 
60
  priv = PP_MAINTENANCE_COMMAND (object)->priv;
 
61
 
 
62
  g_clear_pointer (&priv->printer_name, g_free);
 
63
  g_clear_pointer (&priv->command, g_free);
 
64
  g_clear_pointer (&priv->title, g_free);
 
65
 
 
66
  G_OBJECT_CLASS (pp_maintenance_command_parent_class)->finalize (object);
 
67
}
 
68
 
 
69
static void
 
70
pp_maintenance_command_get_property (GObject    *object,
 
71
                                     guint       prop_id,
 
72
                                     GValue     *value,
 
73
                                     GParamSpec *param_spec)
 
74
{
 
75
  PpMaintenanceCommand *self;
 
76
 
 
77
  self = PP_MAINTENANCE_COMMAND (object);
 
78
 
 
79
  switch (prop_id)
 
80
    {
 
81
      case PROP_PRINTER_NAME:
 
82
        g_value_set_string (value, self->priv->printer_name);
 
83
        break;
 
84
      case PROP_COMMAND:
 
85
        g_value_set_string (value, self->priv->command);
 
86
        break;
 
87
      case PROP_TITLE:
 
88
        g_value_set_string (value, self->priv->title);
 
89
        break;
 
90
      default:
 
91
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
 
92
                                           prop_id,
 
93
                                           param_spec);
 
94
      break;
 
95
    }
 
96
}
 
97
 
 
98
static void
 
99
pp_maintenance_command_set_property (GObject      *object,
 
100
                                     guint         prop_id,
 
101
                                     const GValue *value,
 
102
                                     GParamSpec   *param_spec)
 
103
{
 
104
  PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (object);
 
105
 
 
106
  switch (prop_id)
 
107
    {
 
108
      case PROP_PRINTER_NAME:
 
109
        g_free (self->priv->printer_name);
 
110
        self->priv->printer_name = g_value_dup_string (value);
 
111
        break;
 
112
      case PROP_COMMAND:
 
113
        g_free (self->priv->command);
 
114
        self->priv->command = g_value_dup_string (value);
 
115
        break;
 
116
      case PROP_TITLE:
 
117
        g_free (self->priv->title);
 
118
        self->priv->title = g_value_dup_string (value);
 
119
        break;
 
120
      default:
 
121
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
 
122
                                           prop_id,
 
123
                                           param_spec);
 
124
        break;
 
125
    }
 
126
}
 
127
 
 
128
static void
 
129
pp_maintenance_command_class_init (PpMaintenanceCommandClass *klass)
 
130
{
 
131
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
132
 
 
133
  g_type_class_add_private (klass, sizeof (PpMaintenanceCommandPrivate));
 
134
 
 
135
  gobject_class->set_property = pp_maintenance_command_set_property;
 
136
  gobject_class->get_property = pp_maintenance_command_get_property;
 
137
  gobject_class->finalize = pp_maintenance_command_finalize;
 
138
 
 
139
  g_object_class_install_property (gobject_class, PROP_PRINTER_NAME,
 
140
    g_param_spec_string ("printer-name",
 
141
                         "Printer name",
 
142
                         "Name of the printer",
 
143
                         NULL,
 
144
                         G_PARAM_READWRITE));
 
145
 
 
146
  g_object_class_install_property (gobject_class, PROP_COMMAND,
 
147
    g_param_spec_string ("command",
 
148
                         "Maintenance command",
 
149
                         "Command to execute",
 
150
                         NULL,
 
151
                         G_PARAM_READWRITE));
 
152
 
 
153
  g_object_class_install_property (gobject_class, PROP_TITLE,
 
154
    g_param_spec_string ("title",
 
155
                         "Command title",
 
156
                         "Title of the job by which the command will be executed",
 
157
                         NULL,
 
158
                         G_PARAM_READWRITE));
 
159
}
 
160
 
 
161
static void
 
162
pp_maintenance_command_init (PpMaintenanceCommand *command)
 
163
{
 
164
  command->priv = G_TYPE_INSTANCE_GET_PRIVATE (command,
 
165
                                               PP_TYPE_MAINTENANCE_COMMAND,
 
166
                                               PpMaintenanceCommandPrivate);
 
167
}
 
168
 
 
169
PpMaintenanceCommand *
 
170
pp_maintenance_command_new (const gchar *printer_name,
 
171
                            const gchar *command,
 
172
                            const gchar *title)
 
173
{
 
174
  return g_object_new (PP_TYPE_MAINTENANCE_COMMAND,
 
175
                       "printer-name", printer_name,
 
176
                       "command", command,
 
177
                       "title", title,
 
178
                       NULL);
 
179
}
 
180
 
 
181
static void
 
182
_pp_maintenance_command_execute_thread (GSimpleAsyncResult *res,
 
183
                                        GObject            *object,
 
184
                                        GCancellable       *cancellable)
 
185
{
 
186
  PpMaintenanceCommand        *command = (PpMaintenanceCommand *) object;
 
187
  PpMaintenanceCommandPrivate *priv = command->priv;
 
188
  static const char           *attrs[] = {"printer-commands"};
 
189
  ipp_attribute_t             *attr = NULL;
 
190
  gboolean                     success = FALSE;
 
191
  GError                      *error = NULL;
 
192
  ipp_t                       *request;
 
193
  ipp_t                       *response = NULL;
 
194
  gchar                       *printer_uri;
 
195
  gchar                       *printer_commands = NULL;
 
196
  gchar                       *printer_commands_lowercase = NULL;
 
197
  gchar                       *command_lowercase;
 
198
  gchar                       *file_name = NULL;
 
199
  int                          fd = -1;
 
200
 
 
201
  printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
 
202
                                 priv->printer_name);
 
203
 
 
204
  request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
 
205
  ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
206
                "printer-uri", NULL, printer_uri);
 
207
  ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
 
208
                 "requested-attributes", 1, NULL, attrs);
 
209
  response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
 
210
 
 
211
  if (response)
 
212
    {
 
213
      if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
 
214
        {
 
215
          attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
 
216
          if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
 
217
            {
 
218
              if (ippGetValueTag (attr) == IPP_TAG_KEYWORD)
 
219
                {
 
220
                  printer_commands = g_strdup (ippGetString (attr, 0, NULL));
 
221
                }
 
222
            }
 
223
          else
 
224
            {
 
225
              success = TRUE;
 
226
            }
 
227
        }
 
228
 
 
229
      ippDelete (response);
 
230
    }
 
231
 
 
232
  if (printer_commands)
 
233
    {
 
234
      command_lowercase = g_ascii_strdown (priv->command, -1);
 
235
      printer_commands_lowercase = g_ascii_strdown (printer_commands, -1);
 
236
 
 
237
      if (g_strrstr (printer_commands_lowercase, command_lowercase))
 
238
        {
 
239
          request = ippNewRequest (IPP_PRINT_JOB);
 
240
 
 
241
          ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
 
242
                        "printer-uri", NULL, printer_uri);
 
243
          ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 
244
                        "job-name", NULL, priv->title);
 
245
          ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
 
246
                        "document-format", NULL, "application/vnd.cups-command");
 
247
 
 
248
          fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
 
249
 
 
250
          if (fd != -1)
 
251
            {
 
252
              FILE *file;
 
253
 
 
254
              file = fdopen (fd, "w");
 
255
              fprintf (file, "#CUPS-COMMAND\n");
 
256
              fprintf (file, "%s\n", priv->command);
 
257
              fclose (file);
 
258
 
 
259
              response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name);
 
260
              g_unlink (file_name);
 
261
 
 
262
              if (response)
 
263
                {
 
264
                  if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
 
265
                    {
 
266
                      success = TRUE;
 
267
                    }
 
268
 
 
269
                  ippDelete (response);
 
270
                }
 
271
            }
 
272
 
 
273
          g_free (file_name);
 
274
        }
 
275
      else
 
276
        {
 
277
          success = TRUE;
 
278
        }
 
279
 
 
280
      g_free (command_lowercase);
 
281
      g_free (printer_commands_lowercase);
 
282
      g_free (printer_commands);
 
283
    }
 
284
 
 
285
  g_free (printer_uri);
 
286
 
 
287
  if (!success)
 
288
    {
 
289
      g_simple_async_result_set_error (res,
 
290
                                       G_IO_ERROR,
 
291
                                       G_IO_ERROR_FAILED,
 
292
                                       "Execution of maintenance command failed.");
 
293
    }
 
294
 
 
295
  g_simple_async_result_set_op_res_gboolean (res, success);
 
296
}
 
297
 
 
298
void
 
299
pp_maintenance_command_execute_async (PpMaintenanceCommand *command,
 
300
                                      GCancellable         *cancellable,
 
301
                                      GAsyncReadyCallback   callback,
 
302
                                      gpointer              user_data)
 
303
{
 
304
  GSimpleAsyncResult *res;
 
305
 
 
306
  res = g_simple_async_result_new (G_OBJECT (command), callback, user_data, pp_maintenance_command_execute_async);
 
307
 
 
308
  g_simple_async_result_set_check_cancellable (res, cancellable);
 
309
  g_simple_async_result_run_in_thread (res, _pp_maintenance_command_execute_thread, 0, cancellable);
 
310
 
 
311
  g_object_unref (res);
 
312
}
 
313
 
 
314
gboolean
 
315
pp_maintenance_command_execute_finish (PpMaintenanceCommand  *command,
 
316
                                       GAsyncResult          *res,
 
317
                                       GError               **error)
 
318
{
 
319
  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
 
320
 
 
321
  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == pp_maintenance_command_execute_async);
 
322
 
 
323
  if (g_simple_async_result_propagate_error (simple, error))
 
324
    {
 
325
      return FALSE;
 
326
    }
 
327
 
 
328
  return g_simple_async_result_get_op_res_gboolean (simple);
 
329
}