printers: Added new async API to check availability of maintenance commands

This cleans the code up a bit so that we can extract part of the logic
from _pp_maintenance_command_execute_thread() before getting into fixing
the problem in the logic checking whether a CUPS command is available.

Besides, it will be useful to have this logic extracted as it will be used
later on from pp-printer-entry.c to know whether the "Clean" command is
available, in order to show a menu item "Clean Print Heads" (bug 764620).

https://bugzilla.gnome.org/show_bug.cgi?id=766861
This commit is contained in:
Mario Sanchez Prada 2016-04-28 18:58:20 +01:00
parent cbdc356247
commit 4b91972f2c
2 changed files with 157 additions and 95 deletions

View file

@ -177,6 +177,9 @@ pp_maintenance_command_new (const gchar *printer_name,
NULL);
}
static gboolean _pp_maintenance_command_is_supported (const gchar *printer_name,
const gchar *command);
static void
_pp_maintenance_command_execute_thread (GSimpleAsyncResult *res,
GObject *object,
@ -184,105 +187,62 @@ _pp_maintenance_command_execute_thread (GSimpleAsyncResult *res,
{
PpMaintenanceCommand *command = (PpMaintenanceCommand *) object;
PpMaintenanceCommandPrivate *priv = command->priv;
static const char *attrs[] = {"printer-commands"};
ipp_attribute_t *attr = NULL;
gboolean success = FALSE;
GError *error = NULL;
ipp_t *request;
ipp_t *response = NULL;
gchar *printer_uri;
gchar *printer_commands = NULL;
gchar *printer_commands_lowercase = NULL;
gchar *command_lowercase;
gchar *file_name = NULL;
int fd = -1;
printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
priv->printer_name);
request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", 1, NULL, attrs);
response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
if (response)
if (_pp_maintenance_command_is_supported (priv->printer_name, priv->command))
{
if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
ipp_t *request;
ipp_t *response = NULL;
gchar *printer_uri;
gchar *file_name = NULL;
int fd = -1;
printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
priv->printer_name);
request = ippNewRequest (IPP_PRINT_JOB);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"job-name", NULL, priv->title);
ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
"document-format", NULL, "application/vnd.cups-command");
fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
if (fd != -1)
{
attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
FILE *file;
file = fdopen (fd, "w");
fprintf (file, "#CUPS-COMMAND\n");
fprintf (file, "%s\n", priv->command);
fclose (file);
response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name);
g_unlink (file_name);
if (response != NULL)
{
if (ippGetValueTag (attr) == IPP_TAG_KEYWORD)
if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
{
printer_commands = g_strdup (ippGetString (attr, 0, NULL));
success = TRUE;
}
}
else
{
success = TRUE;
ippDelete (response);
}
}
ippDelete (response);
g_free (file_name);
g_free (printer_uri);
}
if (printer_commands)
else
{
command_lowercase = g_ascii_strdown (priv->command, -1);
printer_commands_lowercase = g_ascii_strdown (printer_commands, -1);
if (g_strrstr (printer_commands_lowercase, command_lowercase))
{
request = ippNewRequest (IPP_PRINT_JOB);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"job-name", NULL, priv->title);
ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
"document-format", NULL, "application/vnd.cups-command");
fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
if (fd != -1)
{
FILE *file;
file = fdopen (fd, "w");
fprintf (file, "#CUPS-COMMAND\n");
fprintf (file, "%s\n", priv->command);
fclose (file);
response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name);
g_unlink (file_name);
if (response)
{
if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
{
success = TRUE;
}
ippDelete (response);
}
}
g_free (file_name);
}
else
{
success = TRUE;
}
g_free (command_lowercase);
g_free (printer_commands_lowercase);
g_free (printer_commands);
success = TRUE;
}
g_free (printer_uri);
if (!success)
{
g_simple_async_result_set_error (res,
@ -326,3 +286,98 @@ pp_maintenance_command_execute_finish (PpMaintenanceCommand *command,
return g_simple_async_result_get_op_res_gboolean (simple);
}
static gboolean
_pp_maintenance_command_is_supported (const gchar *printer_name,
const gchar *command)
{
ipp_attribute_t *attr = NULL;
gboolean is_supported = FALSE;
ipp_t *request;
ipp_t *response = NULL;
gchar *printer_uri;
gchar *printer_commands = NULL;
gchar *printer_commands_lowercase = NULL;
gchar *command_lowercase;
printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
printer_name);
request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", NULL, "printer-commands");
response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
if (response != NULL)
{
if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
{
attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
if (attr != NULL && ippGetCount (attr) > 0 &&
ippGetValueTag (attr) != IPP_TAG_NOVALUE &&
(ippGetValueTag (attr) == IPP_TAG_KEYWORD))
{
printer_commands = g_strdup (ippGetString (attr, 0, NULL));
}
}
ippDelete (response);
}
if (printer_commands != NULL)
{
command_lowercase = g_ascii_strdown (command, -1);
printer_commands_lowercase = g_ascii_strdown (printer_commands, -1);
if (g_strcmp0 (printer_commands_lowercase, command_lowercase) == 0)
is_supported = TRUE;
g_free (command_lowercase);
g_free (printer_commands_lowercase);
g_free (printer_commands);
}
g_free (printer_uri);
return is_supported;
}
static void
_pp_maintenance_command_is_supported_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
PpMaintenanceCommand *command = PP_MAINTENANCE_COMMAND (source_object);
PpMaintenanceCommandPrivate *priv = command->priv;
gboolean success = FALSE;
success = _pp_maintenance_command_is_supported (priv->printer_name, priv->command);
g_task_return_boolean (task, success);
}
void
pp_maintenance_command_is_supported_async (PpMaintenanceCommand *command,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
task = g_task_new (command, cancellable, callback, user_data);
g_task_set_check_cancellable (task, TRUE);
g_task_run_in_thread (task, _pp_maintenance_command_is_supported_thread);
g_object_unref (task);
}
gboolean
pp_maintenance_command_is_supported_finish (PpMaintenanceCommand *command,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, command), FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}

View file

@ -48,21 +48,28 @@ struct _PpMaintenanceCommandClass
GObjectClass parent_class;
};
GType pp_maintenance_command_get_type (void) G_GNUC_CONST;
GType pp_maintenance_command_get_type (void) G_GNUC_CONST;
PpMaintenanceCommand *pp_maintenance_command_new (const gchar *printer_name,
const gchar *command,
const gchar *title);
PpMaintenanceCommand *pp_maintenance_command_new (const gchar *printer_name,
const gchar *command,
const gchar *title);
void pp_maintenance_command_execute_async (PpMaintenanceCommand *command,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void pp_maintenance_command_execute_async (PpMaintenanceCommand *command,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean pp_maintenance_command_execute_finish (PpMaintenanceCommand *command,
GAsyncResult *result,
GError **error);
gboolean pp_maintenance_command_execute_finish (PpMaintenanceCommand *command,
GAsyncResult *result,
GError **error);
void pp_maintenance_command_is_supported_async (PpMaintenanceCommand *command,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean pp_maintenance_command_is_supported_finish (PpMaintenanceCommand *command,
GAsyncResult *result,
GError **error);
G_END_DECLS
#endif /* __PP_MAINTENANCE_COMMAND_H__ */