Commit a3e07662 authored by Marek Kašík's avatar Marek Kašík

Add support for 'auth-info' attribute to the CUPS backend

Check for 'auth-info-required' attribute from printer attributes to
find out whether an authentization of user is needed.
Change password dialog of print backend to be able to require informations
requested thru 'auth-info-required' (#566522).
parent 9439a7ee
......@@ -111,3 +111,4 @@ VOID:UINT,STRING,UINT
VOID:UINT,UINT
VOID:VOID
OBJECT:OBJECT,INT,INT
VOID:POINTER,POINTER,POINTER,POINTER,STRING
......@@ -50,9 +50,8 @@ struct _GtkPrintBackendPrivate
guint printer_list_requested : 1;
guint printer_list_done : 1;
GtkPrintBackendStatus status;
char *hostname;
char *username;
char *password;
char **auth_info_required;
char **auth_info;
};
enum {
......@@ -359,8 +358,10 @@ static GList * fallback_printer_list_papers (GtkPrinter
static GtkPageSetup * fallback_printer_get_default_page_size (GtkPrinter *printer);
static GtkPrintCapabilities fallback_printer_get_capabilities (GtkPrinter *printer);
static void request_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
gpointer auth_info_required,
gpointer auth_info_default,
gpointer auth_info_display,
gpointer auth_info_visible,
const gchar *prompt);
static void
......@@ -441,8 +442,8 @@ gtk_print_backend_class_init (GtkPrintBackendClass *class)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
NULL, NULL,
_gtk_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
_gtk_marshal_VOID__POINTER_POINTER_POINTER_POINTER_STRING,
G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING);
}
static void
......@@ -455,9 +456,8 @@ gtk_print_backend_init (GtkPrintBackend *backend)
priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
priv->hostname = NULL;
priv->username = NULL;
priv->password = NULL;
priv->auth_info_required = NULL;
priv->auth_info = NULL;
}
static void
......@@ -662,40 +662,29 @@ gtk_print_backend_print_stream (GtkPrintBackend *backend,
}
void
gtk_print_backend_set_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *password)
gtk_print_backend_set_password (GtkPrintBackend *backend,
gchar **auth_info_required,
gchar **auth_info)
{
g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, hostname, username, password);
GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, auth_info_required, auth_info);
}
static void
store_password (GtkEntry *entry,
GtkPrintBackend *backend)
store_entry (GtkEntry *entry,
gpointer user_data)
{
GtkPrintBackendPrivate *priv = backend->priv;
gchar **data = (gchar **) user_data;
if (priv->password != NULL)
if (*data != NULL)
{
memset (priv->password, 0, strlen (priv->password));
g_free (priv->password);
memset (*data, 0, strlen (*data));
g_free (*data);
}
priv->password = g_strdup (gtk_entry_get_text (entry));
}
static void
store_username (GtkEntry *entry,
GtkPrintBackend *backend)
{
GtkPrintBackendPrivate *priv = backend->priv;
g_free (priv->username);
priv->username = g_strdup (gtk_entry_get_text (entry));
*data = g_strdup (gtk_entry_get_text (entry));
}
static void
......@@ -704,21 +693,24 @@ password_dialog_response (GtkWidget *dialog,
GtkPrintBackend *backend)
{
GtkPrintBackendPrivate *priv = backend->priv;
gint i;
if (response_id == GTK_RESPONSE_OK)
gtk_print_backend_set_password (backend, priv->hostname, priv->username, priv->password);
gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info);
else
gtk_print_backend_set_password (backend, priv->hostname, priv->username, NULL);
gtk_print_backend_set_password (backend, priv->auth_info_required, NULL);
if (priv->password != NULL)
{
memset (priv->password, 0, strlen (priv->password));
g_free (priv->password);
priv->password = NULL;
}
for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
if (priv->auth_info[i] != NULL)
{
memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
g_free (priv->auth_info[i]);
priv->auth_info[i] = NULL;
}
g_free (priv->auth_info);
priv->auth_info = NULL;
g_free (priv->username);
priv->username = NULL;
g_strfreev (priv->auth_info_required);
gtk_widget_destroy (dialog);
......@@ -726,16 +718,27 @@ password_dialog_response (GtkWidget *dialog,
}
static void
request_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *prompt)
request_password (GtkPrintBackend *backend,
gpointer auth_info_required,
gpointer auth_info_default,
gpointer auth_info_display,
gpointer auth_info_visible,
const gchar *prompt)
{
GtkPrintBackendPrivate *priv = backend->priv;
GtkWidget *dialog, *username_box, *password_box, *main_box, *label, *icon, *vbox,
*password_prompt, *username_prompt,
*password_entry, *username_entry;
GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry;
GtkWidget *focus = NULL;
gchar *markup;
gint length;
gint i;
gchar **ai_required = (gchar **) auth_info_required;
gchar **ai_default = (gchar **) auth_info_default;
gchar **ai_display = (gchar **) auth_info_display;
gboolean *ai_visible = (gboolean *) auth_info_visible;
priv->auth_info_required = g_strdupv (ai_required);
length = g_strv_length (ai_required);
priv->auth_info = g_new0 (gchar *, length);
dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
......@@ -766,27 +769,6 @@ request_password (GtkPrintBackend *backend,
g_free (markup);
/* Right - 2. */
username_box = gtk_hbox_new (TRUE, 0);
username_prompt = gtk_label_new (_("Username:"));
gtk_misc_set_alignment (GTK_MISC (username_prompt), 0.0, 0.5);
username_entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (username_entry), username);
/* Right - 3. */
password_box = gtk_hbox_new (TRUE, 0);
password_prompt = gtk_label_new (_("Password:"));
gtk_misc_set_alignment (GTK_MISC (password_prompt), 0.0, 0.5);
password_entry = gtk_entry_new ();
gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE);
gtk_entry_set_activates_default (GTK_ENTRY (password_entry), TRUE);
/* Packing */
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_box, TRUE, FALSE, 0);
......@@ -794,26 +776,42 @@ request_password (GtkPrintBackend *backend,
gtk_box_pack_start (GTK_BOX (main_box), vbox, FALSE, FALSE, 6);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
gtk_box_pack_start (GTK_BOX (vbox), username_box, FALSE, TRUE, 6);
gtk_box_pack_start (GTK_BOX (vbox), password_box, FALSE, TRUE, 6);
/* Right - 2. */
for (i = 0; i < length; i++)
{
priv->auth_info[i] = g_strdup (ai_default[i]);
if (ai_display[i] != NULL)
{
box = gtk_hbox_new (TRUE, 0);
label = gtk_label_new (ai_display[i]);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_box_pack_start (GTK_BOX (username_box), username_prompt, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (username_box), username_entry, TRUE, TRUE, 0);
entry = gtk_entry_new ();
focus = entry;
gtk_box_pack_start (GTK_BOX (password_box), password_prompt, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (password_box), password_entry, TRUE, TRUE, 0);
if (ai_default[i] != NULL)
gtk_entry_set_text (GTK_ENTRY (entry), ai_default[i]);
gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_widget_grab_focus (password_entry);
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 6);
priv->hostname = g_strdup (hostname);
priv->username = g_strdup (username);
gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
g_signal_connect (password_entry, "changed",
G_CALLBACK (store_password), backend);
g_signal_connect (entry, "changed",
G_CALLBACK (store_entry), &(priv->auth_info[i]));
}
}
g_signal_connect (username_entry, "changed",
G_CALLBACK (store_username), backend);
if (focus != NULL)
{
gtk_widget_grab_focus (focus);
focus = NULL;
}
g_object_ref (backend);
g_signal_connect (G_OBJECT (dialog), "response",
......
......@@ -121,15 +121,16 @@ struct _GtkPrintBackendClass
void (*printer_status_changed) (GtkPrintBackend *backend,
GtkPrinter *printer);
void (*request_password) (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
gpointer auth_info_required,
gpointer auth_info_default,
gpointer auth_info_display,
gpointer auth_info_visible,
const gchar *prompt);
/* not a signal */
void (*set_password) (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *password);
gchar **auth_info_required,
gchar **auth_info);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
......@@ -153,9 +154,8 @@ void gtk_print_backend_print_stream (GtkPrintBackend *pri
GList * gtk_print_backend_load_modules (void);
void gtk_print_backend_destroy (GtkPrintBackend *print_backend);
void gtk_print_backend_set_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *password);
gchar **auth_info_required,
gchar **auth_info);
/* Backend-only functions for GtkPrintBackend */
......
......@@ -187,6 +187,10 @@ gtk_cups_request_new_with_username (http_t *connection,
"requesting-user-name",
NULL, cupsUser ());
request->auth_info_required = NULL;
request->auth_info = NULL;
request->need_auth_info = FALSE;
cupsLangFree (language);
return request;
......@@ -241,6 +245,7 @@ gtk_cups_request_free (GtkCupsRequest *request)
}
g_free (request->username);
g_strfreev (request->auth_info_required);
gtk_cups_result_free (request->result);
......
......@@ -99,6 +99,9 @@ struct _GtkCupsRequest
gint own_http : 1;
gint need_password : 1;
gint need_auth_info : 1;
gchar **auth_info_required;
gchar **auth_info;
GtkCupsPasswordState password_state;
};
......
......@@ -94,6 +94,8 @@ typedef struct
GtkCupsRequest *request;
GPollFD *data_poll;
GtkPrintBackendCups *backend;
GtkPrintCupsResponseCallbackFunc callback;
gpointer callback_data;
} GtkPrintCupsDispatchWatch;
......@@ -179,13 +181,13 @@ static cairo_surface_t * cups_printer_create_cairo_surface (GtkPrinter
gdouble height,
GIOChannel *cache_io);
static void gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *password);
static void gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
gchar **auth_info_required,
gchar **auth_info);
void overwrite_and_free (gpointer data);
static gboolean is_address_local (const gchar *address);
void overwrite_and_free (gpointer data);
static gboolean is_address_local (const gchar *address);
static gboolean request_auth_info (gpointer data);
static void
gtk_print_backend_cups_register_type (GTypeModule *module)
......@@ -557,6 +559,9 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
ps->dnotify = dnotify;
ps->job = g_object_ref (job);
request->need_auth_info = cups_printer->auth_info_required != NULL;
request->auth_info_required = g_strdupv (cups_printer->auth_info_required);
cups_request_execute (GTK_PRINT_BACKEND_CUPS (print_backend),
request,
(GtkPrintCupsResponseCallbackFunc) cups_print_cb,
......@@ -656,18 +661,38 @@ is_address_local (const gchar *address)
}
static void
gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
const gchar *hostname,
const gchar *username,
const gchar *password)
gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
gchar **auth_info_required,
gchar **auth_info)
{
GtkPrintBackendCups *cups_backend = GTK_PRINT_BACKEND_CUPS (backend);
GList *l;
char dispatch_hostname[HTTP_MAX_URI];
gchar *key;
gchar *username = NULL;
gchar *hostname = NULL;
gchar *password = NULL;
gint length;
gint i;
key = g_strconcat (username, "@", hostname, NULL);
g_hash_table_insert (cups_backend->auth, key, g_strdup (password));
length = g_strv_length (auth_info_required);
if (auth_info != NULL)
for (i = 0; i < length; i++)
{
if (g_strcmp0 (auth_info_required[i], "username") == 0)
username = g_strdup (auth_info[i]);
else if (g_strcmp0 (auth_info_required[i], "hostname") == 0)
hostname = g_strdup (auth_info[i]);
else if (g_strcmp0 (auth_info_required[i], "password") == 0)
password = g_strdup (auth_info[i]);
}
if (hostname != NULL && username != NULL && password != NULL)
{
key = g_strconcat (username, "@", hostname, NULL);
g_hash_table_insert (cups_backend->auth, key, g_strdup (password));
}
g_free (cups_backend->username);
cups_backend->username = g_strdup (username);
......@@ -683,7 +708,18 @@ gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
if (is_address_local (dispatch_hostname))
strcpy (dispatch_hostname, "localhost");
if (strcmp (hostname, dispatch_hostname) == 0)
if (dispatch->request->need_auth_info)
{
if (auth_info != NULL)
{
dispatch->request->auth_info = g_new0 (gchar *, length + 1);
for (i = 0; i < length; i++)
dispatch->request->auth_info[i] = g_strdup (auth_info[i]);
}
dispatch->backend->authentication_lock = FALSE;
dispatch->request->need_auth_info = FALSE;
}
else if (dispatch->request->password_state == GTK_CUPS_PASSWORD_REQUESTED || auth_info == NULL)
{
overwrite_and_free (dispatch->request->password);
dispatch->request->password = g_strdup (password);
......@@ -704,6 +740,12 @@ request_password (gpointer data)
gchar *prompt = NULL;
gchar *key = NULL;
char hostname[HTTP_MAX_URI];
gchar **auth_info_required;
gchar **auth_info_default;
gchar **auth_info_display;
gboolean *auth_info_visible;
gint length = 3;
gint i;
if (dispatch->backend->authentication_lock)
return FALSE;
......@@ -717,6 +759,22 @@ request_password (gpointer data)
else
username = cupsUser ();
auth_info_required = g_new0 (gchar*, length + 1);
auth_info_required[0] = g_strdup ("hostname");
auth_info_required[1] = g_strdup ("username");
auth_info_required[2] = g_strdup ("password");
auth_info_default = g_new0 (gchar*, length + 1);
auth_info_default[0] = g_strdup (hostname);
auth_info_default[1] = g_strdup (username);
auth_info_display = g_new0 (gchar*, length + 1);
auth_info_display[1] = g_strdup (_("Username:"));
auth_info_display[2] = g_strdup (_("Password:"));
auth_info_visible = g_new0 (gboolean, length + 1);
auth_info_visible[1] = TRUE;
key = g_strconcat (username, "@", hostname, NULL);
password = g_hash_table_lookup (dispatch->backend->auth, key);
......@@ -784,11 +842,22 @@ request_password (gpointer data)
g_free (printer_name);
g_signal_emit_by_name (dispatch->backend, "request-password",
hostname, username, prompt);
auth_info_required, auth_info_default, auth_info_display, auth_info_visible, prompt);
g_free (prompt);
}
for (i = 0; i < length; i++)
{
g_free (auth_info_required[i]);
g_free (auth_info_default[i]);
g_free (auth_info_display[i]);
}
g_free (auth_info_required);
g_free (auth_info_default);
g_free (auth_info_display);
g_free (auth_info_visible);
g_free (key);
return FALSE;
......@@ -827,6 +896,145 @@ cups_dispatch_add_poll (GSource *source)
}
}
static gboolean
check_auth_info (gpointer user_data)
{
GtkPrintCupsDispatchWatch *dispatch;
dispatch = (GtkPrintCupsDispatchWatch *) user_data;
if (!dispatch->request->need_auth_info)
{
if (dispatch->request->auth_info == NULL)
{
dispatch->callback (GTK_PRINT_BACKEND (dispatch->backend),
gtk_cups_request_get_result (dispatch->request),
dispatch->callback_data);
g_source_destroy ((GSource *) dispatch);
}
else
{
gint length;
gint i;
length = g_strv_length (dispatch->request->auth_info_required);
gtk_cups_request_ipp_add_strings (dispatch->request,
IPP_TAG_JOB,
IPP_TAG_TEXT,
"auth-info",
length,
NULL,
dispatch->request->auth_info);
g_source_attach ((GSource *) dispatch, NULL);
g_source_unref ((GSource *) dispatch);
for (i = 0; i < length; i++)
overwrite_and_free (dispatch->request->auth_info[i]);
g_free (dispatch->request->auth_info);
dispatch->request->auth_info = NULL;
}
return FALSE;
}
return TRUE;
}
static gboolean
request_auth_info (gpointer user_data)
{
GtkPrintCupsDispatchWatch *dispatch;
const char *job_title;
const char *printer_uri;
gchar *prompt = NULL;
char *printer_name = NULL;
gint length;
gint i;
gboolean *auth_info_visible = NULL;
gchar **auth_info_default = NULL;
gchar **auth_info_display = NULL;
dispatch = (GtkPrintCupsDispatchWatch *) user_data;
if (dispatch->backend->authentication_lock)
return FALSE;
job_title = gtk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_NAME, "job-name");
printer_uri = gtk_cups_request_ipp_get_string (dispatch->request, IPP_TAG_URI, "printer-uri");
length = g_strv_length (dispatch->request->auth_info_required);
auth_info_visible = g_new0 (gboolean, length);
auth_info_default = g_new0 (gchar *, length + 1);
auth_info_display = g_new0 (gchar *, length + 1);
for (i = 0; i < length; i++)
{
if (g_strcmp0 (dispatch->request->auth_info_required[i], "domain") == 0)
{
auth_info_display[i] = g_strdup (_("Domain:"));
auth_info_default[i] = g_strdup ("WORKGROUP");
auth_info_visible[i] = TRUE;
}
else if (g_strcmp0 (dispatch->request->auth_info_required[i], "username") == 0)
{
auth_info_display[i] = g_strdup (_("Username:"));
if (dispatch->backend->username != NULL)
auth_info_default[i] = g_strdup (dispatch->backend->username);
else
auth_info_default[i] = g_strdup (cupsUser ());
auth_info_visible[i] = TRUE;
}
else if (g_strcmp0 (dispatch->request->auth_info_required[i], "password") == 0)
{
auth_info_display[i] = g_strdup (_("Password:"));
auth_info_visible[i] = FALSE;
}
}
if (printer_uri != NULL && strrchr (printer_uri, '/') != NULL)
printer_name = g_strdup (strrchr (printer_uri, '/') + 1);
dispatch->backend->authentication_lock = TRUE;
if (job_title != NULL)
{
if (printer_name != NULL)
prompt = g_strdup_printf ( _("Authentication is required to print document '%s' on printer %s"), job_title, printer_name);
else
prompt = g_strdup_printf ( _("Authentication is required to print document '%s'"), job_title);
}
else
{
if (printer_name != NULL)
prompt = g_strdup_printf ( _("Authentication is required to print this document on printer %s"), printer_name);
else
prompt = g_strdup ( _("Authentication is required to print this document"));
}
g_signal_emit_by_name (dispatch->backend, "request-password",
dispatch->request->auth_info_required,
auth_info_default,
auth_info_display,
auth_info_visible,
prompt);
for (i = 0; i < length; i++)
{
g_free (auth_info_default[i]);
g_free (auth_info_display[i]);
}
g_free (auth_info_default);
g_free (auth_info_display);
g_free (printer_name);
g_free (prompt);
g_idle_add (check_auth_info, user_data);
return FALSE;
}
static gboolean
cups_dispatch_watch_check (GSource *source)
{
......@@ -1008,13 +1216,24 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
dispatch->request = request;
dispatch->backend = g_object_ref (print_backend);
dispatch->data_poll = NULL;
dispatch->callback = NULL;
dispatch->callback_data = NULL;
print_backend->requests = g_list_prepend (print_backend->requests, dispatch);
g_source_set_callback ((GSource *) dispatch, (GSourceFunc) callback, user_data, notify);
g_source_attach ((GSource *) dispatch, NULL);
g_source_unref ((GSource *) dispatch);
if (request->need_auth_info)
{
dispatch->callback = callback;
dispatch->callback_data = user_data;
request_auth_info (dispatch);
}
else
{
g_source_attach ((GSource *) dispatch, NULL);
g_source_unref ((GSource *) dispatch);
}
}
#if 0
......@@ -1435,6 +1654,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
gchar *default_cover_before = NULL;
gchar *default_cover_after = NULL;
gboolean remote_printer = FALSE;
gchar **auth_info_required = NULL;
/* Skip leading attributes until we hit a printer...
*/
......@@ -1553,6 +1773,15 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
else
remote_printer = FALSE;
}
else if (strcmp (attr->name, "auth-info-required") == 0)
{
if (strcmp (attr->values[0].string.text, "none") != 0)
{
auth_info_required = g_new0 (gchar *, attr->num_values + 1);
for (i = 0; i < attr->num_values; i++)
auth_info_required[i] = g_strdup (attr->values[i].string.text);
}
}
else
{
GTK_NOTE (PRINTING,
......@@ -1674,6 +1903,9 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
cups_printer->hostname = g_strdup (hostname);
cups_printer->port = port;
cups_printer->auth_info_required = g_strdupv (auth_info_required);
g_strfreev (auth_info_required);
printer = GTK_PRINTER (cups_printer);
if (cups_backend->default_printer != NULL &&
......@@ -1868,7 +2100,8 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
"printer-is-accepting-jobs",
"job-sheets-supported",
"job-sheets-default",
"printer-type"
"printer-type",
"auth-info-required"
};
if (cups_backend->list_printers_pending)
......
......@@ -80,6 +80,7 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
printer->remote = FALSE;
printer->get_remote_ppd_poll = 0;
printer->remote_cups_connection_test = NULL;
printer->auth_info_required = NULL;
}
static void
......@@ -97,6 +98,7 @@ gtk_printer_cups_finalize (GObject *object)
g_free (printer->ppd_name);
g_free (printer->default_cover_before);
g_free (printer->default_cover_after);
g_strfreev (printer->auth_info_required);