2008-07-01 22:57:50 +00:00
/* GTK - The GIMP Toolkit
2012-02-19 21:29:11 +00:00
* gtkprintbackendcups . h : Default implementation of GtkPrintBackend
2006-04-21 15:09:32 +00:00
* for the Common Unix Print System ( CUPS )
2007-01-03 20:34:00 +00:00
* Copyright ( C ) 2006 , 2007 Red Hat , Inc .
2006-04-21 15:09:32 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2012-02-27 13:01:10 +00:00
* License along with this library . If not , see < http : //www.gnu.org/licenses/>.
2006-04-21 15:09:32 +00:00
*/
2008-06-22 14:28:52 +00:00
# include "config.h"
2008-03-05 03:45:41 +00:00
# include <ctype.h>
2006-04-21 15:09:32 +00:00
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <stdlib.h>
2009-01-21 15:03:14 +00:00
# include <time.h>
2019-05-06 19:04:17 +00:00
2012-02-18 22:16:27 +00:00
/* Cups 1.6 deprecates ppdFindAttr(), ppdFindCustomOption(),
2020-04-17 22:33:20 +00:00
* ppdFirstCustomParam ( ) , and ppdNextCustomParam ( ) among others .
* The replacement is to use the Job Ticket API , but that requires
* a larger refactoring of this backend .
2012-02-18 22:16:27 +00:00
*/
2006-04-21 15:09:32 +00:00
# include <cups/cups.h>
# include <cups/language.h>
# include <cups/http.h>
# include <cups/ipp.h>
# include <errno.h>
# include <cairo.h>
# include <cairo-pdf.h>
# include <cairo-ps.h>
2008-03-12 11:12:37 +00:00
# include <glib/gstdio.h>
2006-04-21 15:09:32 +00:00
# include <glib/gi18n-lib.h>
# include <gmodule.h>
2008-05-28 12:49:11 +00:00
# include <gtk/gtk.h>
2019-05-26 21:57:23 +00:00
# include <gtk/gtkprintbackendprivate.h>
2008-05-29 09:34:53 +00:00
# include <gtk/gtkunixprint.h>
2019-05-26 20:29:57 +00:00
# include <gtk/gtkprinterprivate.h>
2006-04-21 15:09:32 +00:00
# include "gtkprintbackendcups.h"
# include "gtkprintercups.h"
# include "gtkcupsutils.h"
2014-08-19 15:55:47 +00:00
# include "gtkcupssecretsutils.h"
2006-04-21 15:09:32 +00:00
2014-10-02 11:50:47 +00:00
# include <gtkprintutils.h>
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
# include <colord.h>
# endif
2006-10-03 15:05:05 +00:00
2006-04-21 15:09:32 +00:00
typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass ;
# define GTK_PRINT_BACKEND_CUPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_CUPS, GtkPrintBackendCupsClass))
# define GTK_IS_PRINT_BACKEND_CUPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_CUPS))
# define GTK_PRINT_BACKEND_CUPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_CUPS, GtkPrintBackendCupsClass))
2012-02-19 21:29:11 +00:00
# define _CUPS_MAX_ATTEMPTS 10
2006-04-21 15:09:32 +00:00
# define _CUPS_MAX_CHUNK_SIZE 8192
2013-03-12 16:18:16 +00:00
# define AVAHI_IF_UNSPEC -1
# define AVAHI_PROTO_INET 0
# define AVAHI_PROTO_INET6 1
# define AVAHI_PROTO_UNSPEC -1
# define AVAHI_BUS "org.freedesktop.Avahi"
# define AVAHI_SERVER_IFACE "org.freedesktop.Avahi.Server"
# define AVAHI_SERVICE_BROWSER_IFACE "org.freedesktop.Avahi.ServiceBrowser"
# define AVAHI_SERVICE_RESOLVER_IFACE "org.freedesktop.Avahi.ServiceResolver"
2019-12-12 15:56:37 +00:00
# define PRINTER_NAME_ALLOWED_CHARACTERS "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
2007-04-23 17:06:07 +00:00
/* define this to see warnings about ignored ppd options */
# undef PRINT_IGNORED_OPTIONS
2006-04-21 15:09:32 +00:00
# define _CUPS_MAP_ATTR_INT(attr, v, a) {if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values[0].integer;}
2006-05-10 00:42:23 +00:00
# define _CUPS_MAP_ATTR_STR(attr, v, a) {if (!g_ascii_strcasecmp (attr->name, (a))) v = attr->values[0].string.text;}
2006-04-21 15:09:32 +00:00
2021-02-04 19:18:28 +00:00
# if !GLIB_CHECK_VERSION (2, 67, 3)
# define g_memdup2(mem,size) g_memdup((mem), (size))
# endif
2006-04-21 15:09:32 +00:00
typedef void ( * GtkPrintCupsResponseCallbackFunc ) ( GtkPrintBackend * print_backend ,
2012-02-19 21:29:11 +00:00
GtkCupsResult * result ,
2006-06-21 05:08:43 +00:00
gpointer user_data ) ;
2006-04-21 15:09:32 +00:00
2012-02-19 21:29:11 +00:00
typedef enum
2006-04-21 15:09:32 +00:00
{
DISPATCH_SETUP ,
DISPATCH_REQUEST ,
DISPATCH_SEND ,
DISPATCH_CHECK ,
DISPATCH_READ ,
DISPATCH_ERROR
} GtkPrintCupsDispatchState ;
2012-02-19 21:29:11 +00:00
typedef struct
2006-04-21 15:09:32 +00:00
{
GSource source ;
http_t * http ;
GtkCupsRequest * request ;
2011-08-06 08:37:21 +00:00
GtkCupsPollState poll_state ;
2006-04-21 15:09:32 +00:00
GPollFD * data_poll ;
GtkPrintBackendCups * backend ;
2009-09-24 13:34:56 +00:00
GtkPrintCupsResponseCallbackFunc callback ;
gpointer callback_data ;
2006-04-21 15:09:32 +00:00
} GtkPrintCupsDispatchWatch ;
struct _GtkPrintBackendCupsClass
{
2006-05-04 13:43:32 +00:00
GtkPrintBackendClass parent_class ;
2006-04-21 15:09:32 +00:00
} ;
struct _GtkPrintBackendCups
{
2006-05-04 13:43:32 +00:00
GtkPrintBackend parent_instance ;
2006-04-21 15:09:32 +00:00
char * default_printer ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
guint list_printers_poll ;
guint list_printers_pending : 1 ;
2020-07-24 13:54:49 +00:00
int list_printers_attempts ;
2006-06-21 05:08:43 +00:00
guint got_default_printer : 1 ;
2008-07-31 23:56:17 +00:00
guint default_printer_poll ;
2008-09-17 22:07:10 +00:00
GtkCupsConnectionTest * cups_connection_test ;
2020-07-24 13:54:49 +00:00
int reading_ppds ;
2008-07-15 17:45:18 +00:00
2009-04-21 12:24:32 +00:00
GList * requests ;
GHashTable * auth ;
2020-07-24 18:40:36 +00:00
char * username ;
2009-04-21 12:24:32 +00:00
gboolean authentication_lock ;
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
CdClient * colord_client ;
# endif
2019-05-06 19:04:17 +00:00
2013-03-12 16:18:16 +00:00
GDBusConnection * dbus_connection ;
2019-05-06 19:04:17 +00:00
char * avahi_default_printer ;
guint avahi_service_browser_subscription_id ;
guint avahi_service_browser_subscription_ids [ 2 ] ;
char * avahi_service_browser_paths [ 2 ] ;
GCancellable * avahi_cancellable ;
2021-02-05 17:13:56 +00:00
guint unsubscribe_general_subscription_id ;
2019-05-06 19:04:17 +00:00
2014-08-19 15:55:47 +00:00
gboolean secrets_service_available ;
guint secrets_service_watch_id ;
GCancellable * secrets_service_cancellable ;
2021-02-05 17:13:34 +00:00
GList * temporary_queues_in_construction ;
GList * temporary_queues_removed ;
2006-04-21 15:09:32 +00:00
} ;
static GObjectClass * backend_parent_class ;
static void gtk_print_backend_cups_finalize ( GObject * object ) ;
2006-05-04 13:43:32 +00:00
static void gtk_print_backend_cups_dispose ( GObject * object ) ;
static void cups_get_printer_list ( GtkPrintBackend * print_backend ) ;
2008-07-31 23:56:17 +00:00
static void cups_get_default_printer ( GtkPrintBackendCups * print_backend ) ;
2008-09-17 22:07:10 +00:00
static void cups_get_local_default_printer ( GtkPrintBackendCups * print_backend ) ;
2006-04-21 15:09:32 +00:00
static void cups_request_execute ( GtkPrintBackendCups * print_backend ,
GtkCupsRequest * request ,
GtkPrintCupsResponseCallbackFunc callback ,
gpointer user_data ,
2006-06-21 05:08:43 +00:00
GDestroyNotify notify ) ;
2006-04-21 15:09:32 +00:00
static void cups_printer_get_settings_from_options ( GtkPrinter * printer ,
GtkPrinterOptionSet * options ,
GtkPrintSettings * settings ) ;
static gboolean cups_printer_mark_conflicts ( GtkPrinter * printer ,
GtkPrinterOptionSet * options ) ;
static GtkPrinterOptionSet * cups_printer_get_options ( GtkPrinter * printer ,
GtkPrintSettings * settings ,
2006-06-21 05:56:14 +00:00
GtkPageSetup * page_setup ,
GtkPrintCapabilities capabilities ) ;
2006-04-21 15:09:32 +00:00
static void cups_printer_prepare_for_print ( GtkPrinter * printer ,
GtkPrintJob * print_job ,
GtkPrintSettings * settings ,
GtkPageSetup * page_setup ) ;
static GList * cups_printer_list_papers ( GtkPrinter * printer ) ;
2008-05-21 02:17:30 +00:00
static GtkPageSetup * cups_printer_get_default_page_size ( GtkPrinter * printer ) ;
2006-04-21 15:09:32 +00:00
static void cups_printer_request_details ( GtkPrinter * printer ) ;
2008-07-31 23:56:17 +00:00
static gboolean cups_request_default_printer ( GtkPrintBackendCups * print_backend ) ;
2009-09-23 12:35:26 +00:00
static gboolean cups_request_ppd ( GtkPrinter * printer ) ;
2008-02-06 22:58:47 +00:00
static gboolean cups_printer_get_hard_margins ( GtkPrinter * printer ,
2020-07-24 20:32:16 +00:00
double * top ,
double * bottom ,
double * left ,
double * right ) ;
2018-04-12 09:31:37 +00:00
static gboolean cups_printer_get_hard_margins_for_paper_size ( GtkPrinter * printer ,
GtkPaperSize * paper_size ,
2020-07-24 20:32:16 +00:00
double * top ,
double * bottom ,
double * left ,
double * right ) ;
2006-05-24 10:50:57 +00:00
static GtkPrintCapabilities cups_printer_get_capabilities ( GtkPrinter * printer ) ;
2006-04-21 15:09:32 +00:00
static void set_option_from_settings ( GtkPrinterOption * option ,
GtkPrintSettings * setting ) ;
static void cups_begin_polling_info ( GtkPrintBackendCups * print_backend ,
GtkPrintJob * job ,
int job_id ) ;
static gboolean cups_job_info_poll_timeout ( gpointer user_data ) ;
2006-05-04 13:43:32 +00:00
static void gtk_print_backend_cups_print_stream ( GtkPrintBackend * backend ,
GtkPrintJob * job ,
2006-06-21 18:16:58 +00:00
GIOChannel * data_io ,
2006-05-04 13:43:32 +00:00
GtkPrintJobCompleteFunc callback ,
gpointer user_data ,
2006-06-21 18:16:58 +00:00
GDestroyNotify dnotify ) ;
2006-05-04 13:43:32 +00:00
static cairo_surface_t * cups_printer_create_cairo_surface ( GtkPrinter * printer ,
2006-06-16 05:08:14 +00:00
GtkPrintSettings * settings ,
2020-07-24 20:32:16 +00:00
double width ,
double height ,
2006-06-21 18:16:58 +00:00
GIOChannel * cache_io ) ;
2006-05-04 13:43:32 +00:00
2012-02-19 21:29:11 +00:00
static void gtk_print_backend_cups_set_password ( GtkPrintBackend * backend ,
2020-07-24 18:40:36 +00:00
char * * auth_info_required ,
char * * auth_info ,
2014-08-19 15:55:47 +00:00
gboolean store_auth_info ) ;
2009-04-21 12:24:32 +00:00
2009-09-24 13:34:56 +00:00
void overwrite_and_free ( gpointer data ) ;
2020-07-24 18:40:36 +00:00
static gboolean is_address_local ( const char * address ) ;
2009-09-24 13:34:56 +00:00
static gboolean request_auth_info ( gpointer data ) ;
2014-08-19 15:55:47 +00:00
static void lookup_auth_info ( gpointer data ) ;
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
static void avahi_request_printer_list ( GtkPrintBackendCups * cups_backend ) ;
2014-08-19 15:55:47 +00:00
static void secrets_service_appeared_cb ( GDBusConnection * connection ,
2020-07-24 18:40:36 +00:00
const char * name ,
const char * name_owner ,
2014-08-19 15:55:47 +00:00
gpointer user_data ) ;
static void secrets_service_vanished_cb ( GDBusConnection * connection ,
2020-07-24 18:40:36 +00:00
const char * name ,
2014-08-19 15:55:47 +00:00
gpointer user_data ) ;
2018-02-18 23:00:42 +00:00
G_DEFINE_DYNAMIC_TYPE ( GtkPrintBackendCups , gtk_print_backend_cups , GTK_TYPE_PRINT_BACKEND )
void
g_io_module_load ( GIOModule * module )
2006-04-21 15:09:32 +00:00
{
2018-02-18 23:00:42 +00:00
g_type_module_use ( G_TYPE_MODULE ( module ) ) ;
gtk_print_backend_cups_register_type ( G_TYPE_MODULE ( module ) ) ;
gtk_printer_cups_register_type ( G_TYPE_MODULE ( module ) ) ;
2006-05-05 20:22:27 +00:00
2018-02-18 23:00:42 +00:00
g_io_extension_point_implement ( GTK_PRINT_BACKEND_EXTENSION_POINT_NAME ,
GTK_TYPE_PRINT_BACKEND_CUPS ,
" cups " ,
10 ) ;
2006-04-21 15:09:32 +00:00
}
2018-02-18 23:00:42 +00:00
void
g_io_module_unload ( GIOModule * module )
2006-04-21 15:09:32 +00:00
{
}
2018-02-18 23:00:42 +00:00
char * *
g_io_module_query ( void )
2006-04-21 15:09:32 +00:00
{
2018-02-18 23:00:42 +00:00
char * eps [ ] = {
2020-05-18 11:41:19 +00:00
( char * ) GTK_PRINT_BACKEND_EXTENSION_POINT_NAME ,
2018-02-18 23:00:42 +00:00
NULL
} ;
2006-04-21 15:09:32 +00:00
2018-02-18 23:00:42 +00:00
return g_strdupv ( eps ) ;
2006-04-21 15:09:32 +00:00
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
/*
* GtkPrintBackendCups
*/
/**
* gtk_print_backend_cups_new :
*
* Creates a new # GtkPrintBackendCups object . # GtkPrintBackendCups
* implements the # GtkPrintBackend interface with direct access to
* the filesystem using Unix / Linux API calls
*
2014-02-19 23:49:43 +00:00
* Returns : the new # GtkPrintBackendCups object
2006-06-21 05:08:43 +00:00
*/
2006-04-21 15:09:32 +00:00
GtkPrintBackend *
gtk_print_backend_cups_new ( void )
{
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Creating a new CUPS print backend object \n " ) ) ;
2006-04-21 15:09:32 +00:00
return g_object_new ( GTK_TYPE_PRINT_BACKEND_CUPS , NULL ) ;
}
2021-02-05 17:13:34 +00:00
static void create_temporary_queue ( GtkPrintBackendCups * backend ,
const gchar * printer_name ,
const gchar * printer_uri ,
const gchar * device_uri ) ;
2006-04-21 15:09:32 +00:00
static void
gtk_print_backend_cups_class_init ( GtkPrintBackendCupsClass * class )
{
GObjectClass * gobject_class = G_OBJECT_CLASS ( class ) ;
2006-05-04 13:43:32 +00:00
GtkPrintBackendClass * backend_class = GTK_PRINT_BACKEND_CLASS ( class ) ;
2006-04-21 15:09:32 +00:00
backend_parent_class = g_type_class_peek_parent ( class ) ;
gobject_class - > finalize = gtk_print_backend_cups_finalize ;
2006-05-04 13:43:32 +00:00
gobject_class - > dispose = gtk_print_backend_cups_dispose ;
2012-02-19 21:29:11 +00:00
backend_class - > request_printer_list = cups_get_printer_list ;
2006-05-04 13:43:32 +00:00
backend_class - > print_stream = gtk_print_backend_cups_print_stream ;
backend_class - > printer_request_details = cups_printer_request_details ;
backend_class - > printer_create_cairo_surface = cups_printer_create_cairo_surface ;
backend_class - > printer_get_options = cups_printer_get_options ;
backend_class - > printer_mark_conflicts = cups_printer_mark_conflicts ;
backend_class - > printer_get_settings_from_options = cups_printer_get_settings_from_options ;
backend_class - > printer_prepare_for_print = cups_printer_prepare_for_print ;
backend_class - > printer_list_papers = cups_printer_list_papers ;
2008-05-21 02:17:30 +00:00
backend_class - > printer_get_default_page_size = cups_printer_get_default_page_size ;
2006-05-04 13:43:32 +00:00
backend_class - > printer_get_hard_margins = cups_printer_get_hard_margins ;
2018-04-12 09:31:37 +00:00
backend_class - > printer_get_hard_margins_for_paper_size = cups_printer_get_hard_margins_for_paper_size ;
2006-05-24 10:50:57 +00:00
backend_class - > printer_get_capabilities = cups_printer_get_capabilities ;
2009-04-21 12:24:32 +00:00
backend_class - > set_password = gtk_print_backend_cups_set_password ;
2006-04-21 15:09:32 +00:00
}
2018-02-18 23:00:42 +00:00
static void
gtk_print_backend_cups_class_finalize ( GtkPrintBackendCupsClass * class )
{
}
2014-10-10 11:36:30 +00:00
static gboolean
option_is_ipp_option ( GtkPrinterOption * option )
{
gpointer data = g_object_get_data ( G_OBJECT ( option ) , " is-ipp-option " ) ;
if ( data ! = NULL )
return GPOINTER_TO_UINT ( data ) ! = 0 ;
else
return FALSE ;
}
static void
option_set_is_ipp_option ( GtkPrinterOption * option ,
gboolean is_ipp_option )
{
g_object_set_data ( G_OBJECT ( option ) ,
" is-ipp-option " ,
GUINT_TO_POINTER ( is_ipp_option ? 1 : 0 ) ) ;
}
2006-04-21 15:09:32 +00:00
static cairo_status_t
2006-06-16 18:29:09 +00:00
_cairo_write_to_cups ( void * closure ,
2006-04-21 15:09:32 +00:00
const unsigned char * data ,
unsigned int length )
{
2006-06-21 18:16:58 +00:00
GIOChannel * io = ( GIOChannel * ) closure ;
gsize written ;
GError * error ;
error = NULL ;
GTK_NOTE ( PRINTING ,
2007-04-23 17:06:07 +00:00
g_print ( " CUPS Backend: Writing %i byte chunk to temp file \n " , length ) ) ;
2006-06-21 18:16:58 +00:00
2012-02-19 21:29:11 +00:00
while ( length > 0 )
2006-06-16 18:29:09 +00:00
{
2020-07-24 18:40:36 +00:00
g_io_channel_write_chars ( io , ( char * ) data , length , & written , & error ) ;
2006-06-16 18:29:09 +00:00
2006-06-21 18:16:58 +00:00
if ( error ! = NULL )
2006-06-16 18:29:09 +00:00
{
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
2012-02-19 21:29:11 +00:00
g_print ( " CUPS Backend: Error writing to temp file, %s \n " ,
2007-04-23 17:06:07 +00:00
error - > message ) ) ;
2006-06-21 18:16:58 +00:00
g_error_free ( error ) ;
2006-06-16 18:29:09 +00:00
return CAIRO_STATUS_WRITE_ERROR ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
2010-09-27 18:48:43 +00:00
g_print ( " CUPS Backend: Wrote % " G_GSIZE_FORMAT " bytes to temp file \n " , written ) ) ;
2006-06-21 18:16:58 +00:00
2006-06-16 18:29:09 +00:00
data + = written ;
length - = written ;
}
return CAIRO_STATUS_SUCCESS ;
}
2006-04-21 15:09:32 +00:00
static cairo_surface_t *
2006-06-16 18:29:09 +00:00
cups_printer_create_cairo_surface ( GtkPrinter * printer ,
2006-06-16 05:08:14 +00:00
GtkPrintSettings * settings ,
2020-07-24 20:32:16 +00:00
double width ,
double height ,
2006-06-21 18:16:58 +00:00
GIOChannel * cache_io )
2006-04-21 15:09:32 +00:00
{
2011-01-03 14:34:04 +00:00
cairo_surface_t * surface ;
2008-05-28 01:43:34 +00:00
ppd_file_t * ppd_file = NULL ;
ppd_attr_t * ppd_attr = NULL ;
2008-10-30 16:24:27 +00:00
ppd_attr_t * ppd_attr_res = NULL ;
ppd_attr_t * ppd_attr_screen_freq = NULL ;
ppd_attr_t * ppd_attr_res_screen_freq = NULL ;
2020-07-24 18:40:36 +00:00
char * res_string = NULL ;
2020-07-24 13:54:49 +00:00
int level = 2 ;
2011-01-03 14:34:04 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2011-01-03 14:34:04 +00:00
if ( gtk_printer_accepts_pdf ( printer ) )
2011-01-03 15:16:02 +00:00
surface = cairo_pdf_surface_create_for_stream ( _cairo_write_to_cups , cache_io , width , height ) ;
2011-01-03 14:34:04 +00:00
else
surface = cairo_ps_surface_create_for_stream ( _cairo_write_to_cups , cache_io , width , height ) ;
2006-04-21 15:09:32 +00:00
2008-05-28 01:43:34 +00:00
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
if ( ppd_file ! = NULL )
{
ppd_attr = ppdFindAttr ( ppd_file , " LanguageLevel " , NULL ) ;
if ( ppd_attr ! = NULL )
level = atoi ( ppd_attr - > value ) ;
2008-10-30 16:24:27 +00:00
if ( gtk_print_settings_get_resolution ( settings ) = = 0 )
{
ppd_attr_res = ppdFindAttr ( ppd_file , " DefaultResolution " , NULL ) ;
if ( ppd_attr_res ! = NULL )
{
int res , res_x , res_y ;
if ( sscanf ( ppd_attr_res - > value , " %dx%ddpi " , & res_x , & res_y ) = = 2 )
{
2009-08-30 15:10:47 +00:00
if ( res_x > 0 & & res_y > 0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_resolution_xy ( settings , res_x , res_y ) ;
}
else if ( sscanf ( ppd_attr_res - > value , " %ddpi " , & res ) = = 1 )
{
2009-08-30 15:10:47 +00:00
if ( res > 0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_resolution ( settings , res ) ;
}
}
}
2011-01-03 14:34:04 +00:00
res_string = g_strdup_printf ( " %ddpi " ,
2008-10-30 16:24:27 +00:00
gtk_print_settings_get_resolution ( settings ) ) ;
ppd_attr_res_screen_freq = ppdFindAttr ( ppd_file , " ResScreenFreq " , res_string ) ;
g_free ( res_string ) ;
if ( ppd_attr_res_screen_freq = = NULL )
{
2011-01-03 14:34:04 +00:00
res_string = g_strdup_printf ( " %dx%ddpi " ,
2008-10-30 16:24:27 +00:00
gtk_print_settings_get_resolution_x ( settings ) ,
gtk_print_settings_get_resolution_y ( settings ) ) ;
ppd_attr_res_screen_freq = ppdFindAttr ( ppd_file , " ResScreenFreq " , res_string ) ;
g_free ( res_string ) ;
}
ppd_attr_screen_freq = ppdFindAttr ( ppd_file , " ScreenFreq " , NULL ) ;
2009-08-30 15:10:47 +00:00
if ( ppd_attr_res_screen_freq ! = NULL & & atof ( ppd_attr_res_screen_freq - > value ) > 0.0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_printer_lpi ( settings , atof ( ppd_attr_res_screen_freq - > value ) ) ;
2009-08-30 15:10:47 +00:00
else if ( ppd_attr_screen_freq ! = NULL & & atof ( ppd_attr_screen_freq - > value ) > 0.0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_printer_lpi ( settings , atof ( ppd_attr_screen_freq - > value ) ) ;
2008-05-28 01:43:34 +00:00
}
2011-01-03 14:34:04 +00:00
if ( cairo_surface_get_type ( surface ) = = CAIRO_SURFACE_TYPE_PS )
{
if ( level = = 2 )
cairo_ps_surface_restrict_to_level ( surface , CAIRO_PS_LEVEL_2 ) ;
2008-05-28 01:43:34 +00:00
2011-01-03 14:34:04 +00:00
if ( level = = 3 )
cairo_ps_surface_restrict_to_level ( surface , CAIRO_PS_LEVEL_3 ) ;
}
2008-05-28 01:43:34 +00:00
2008-10-30 16:24:27 +00:00
cairo_surface_set_fallback_resolution ( surface ,
2.0 * gtk_print_settings_get_printer_lpi ( settings ) ,
2.0 * gtk_print_settings_get_printer_lpi ( settings ) ) ;
2006-04-21 15:09:32 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
return surface ;
}
typedef struct {
GtkPrintJobCompleteFunc callback ;
GtkPrintJob * job ;
gpointer user_data ;
GDestroyNotify dnotify ;
2013-12-16 15:44:58 +00:00
http_t * http ;
2006-04-21 15:09:32 +00:00
} CupsPrintStreamData ;
static void
cups_free_print_stream_data ( CupsPrintStreamData * data )
{
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2006-04-21 15:09:32 +00:00
if ( data - > dnotify )
data - > dnotify ( data - > user_data ) ;
g_object_unref ( data - > job ) ;
2013-12-16 15:44:58 +00:00
if ( data - > http ! = NULL )
httpClose ( data - > http ) ;
2006-04-21 15:09:32 +00:00
g_free ( data ) ;
}
static void
cups_print_cb ( GtkPrintBackendCups * print_backend ,
2006-06-16 18:29:09 +00:00
GtkCupsResult * result ,
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
GError * error = NULL ;
CupsPrintStreamData * ps = user_data ;
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
2012-02-19 21:29:11 +00:00
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2006-06-21 18:16:58 +00:00
2006-04-21 15:09:32 +00:00
if ( gtk_cups_result_is_error ( result ) )
error = g_error_new_literal ( gtk_print_error_quark ( ) ,
GTK_PRINT_ERROR_INTERNAL_ERROR ,
gtk_cups_result_get_error_string ( result ) ) ;
if ( ps - > callback )
ps - > callback ( ps - > job , ps - > user_data , error ) ;
if ( error = = NULL )
{
int job_id = 0 ;
ipp_attribute_t * attr ; /* IPP job-id attribute */
ipp_t * response = gtk_cups_result_get_response ( result ) ;
2006-06-21 05:08:43 +00:00
if ( ( attr = ippFindAttribute ( response , " job-id " , IPP_TAG_INTEGER ) ) ! = NULL )
2012-02-18 22:16:27 +00:00
job_id = ippGetInteger ( attr , 0 ) ;
2006-04-21 15:09:32 +00:00
2006-05-15 16:22:38 +00:00
if ( ! gtk_print_job_get_track_print_status ( ps - > job ) | | job_id = = 0 )
gtk_print_job_set_status ( ps - > job , GTK_PRINT_STATUS_FINISHED ) ;
else
{
gtk_print_job_set_status ( ps - > job , GTK_PRINT_STATUS_PENDING ) ;
cups_begin_polling_info ( print_backend , ps - > job , job_id ) ;
}
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else
gtk_print_job_set_status ( ps - > job , GTK_PRINT_STATUS_FINISHED_ABORTED ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( error )
g_error_free ( error ) ;
}
2011-12-24 16:26:32 +00:00
typedef struct {
GtkCupsRequest * request ;
2019-04-04 16:39:18 +00:00
GtkPageSetup * page_setup ;
2012-01-31 11:15:43 +00:00
GtkPrinterCups * printer ;
2011-12-24 16:26:32 +00:00
} CupsOptionsData ;
2019-04-04 16:39:18 +00:00
# define UNSIGNED_FLOAT_REGEX "([0-9]+([.,][0-9]*)?|[.,][0-9]+)([e][+-]?[0-9]+)?"
# define SIGNED_FLOAT_REGEX "[+-]?"UNSIGNED_FLOAT_REGEX
# define SIGNED_INTEGER_REGEX "[+-]?([0-9]+)"
2006-04-21 15:09:32 +00:00
static void
2020-07-24 18:40:36 +00:00
add_cups_options ( const char * key ,
const char * value ,
2006-06-21 05:08:43 +00:00
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
2011-12-24 16:26:32 +00:00
CupsOptionsData * data = ( CupsOptionsData * ) user_data ;
GtkCupsRequest * request = data - > request ;
2012-01-31 11:15:43 +00:00
GtkPrinterCups * printer = data - > printer ;
gboolean custom_value = FALSE ;
2020-07-24 18:40:36 +00:00
char * new_value = NULL ;
2020-07-24 13:54:49 +00:00
int i ;
2012-01-31 11:15:43 +00:00
if ( ! key | | ! value )
return ;
2006-04-21 15:09:32 +00:00
if ( ! g_str_has_prefix ( key , " cups- " ) )
return ;
if ( strcmp ( value , " gtk-ignore-value " ) = = 0 )
return ;
2011-12-24 16:26:32 +00:00
2006-06-21 05:08:43 +00:00
key = key + strlen ( " cups- " ) ;
2006-04-21 15:09:32 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2019-04-04 16:39:18 +00:00
if ( printer & & printer - > ppd_file & & ! g_str_has_prefix ( value , " Custom. " ) )
2012-01-31 11:15:43 +00:00
{
ppd_coption_t * coption ;
gboolean found = FALSE ;
gboolean custom_values_enabled = FALSE ;
coption = ppdFindCustomOption ( printer - > ppd_file , key ) ;
if ( coption & & coption - > option )
{
for ( i = 0 ; i < coption - > option - > num_choices ; i + + )
{
/* Are custom values enabled ? */
if ( g_str_equal ( coption - > option - > choices [ i ] . choice , " Custom " ) )
custom_values_enabled = TRUE ;
/* Is the value among available choices ? */
if ( g_str_equal ( coption - > option - > choices [ i ] . choice , value ) )
found = TRUE ;
}
2011-12-24 16:26:32 +00:00
2012-01-31 11:15:43 +00:00
if ( custom_values_enabled & & ! found )
2019-04-04 16:39:18 +00:00
{
/* Check syntax of the invalid choice to see whether
it could be a custom value */
if ( g_str_equal ( key , " PageSize " ) | |
g_str_equal ( key , " PageRegion " ) )
{
/* Handle custom page sizes... */
if ( g_regex_match_simple ( " ^ " UNSIGNED_FLOAT_REGEX " x " UNSIGNED_FLOAT_REGEX " (cm|mm|m|in|ft|pt)?$ " , value , G_REGEX_CASELESS , 0 ) )
custom_value = TRUE ;
else
{
if ( data - > page_setup ! = NULL )
{
custom_value = TRUE ;
new_value =
g_strdup_printf ( " Custom.%.2fx%.2fmm " ,
gtk_paper_size_get_width ( gtk_page_setup_get_paper_size ( data - > page_setup ) , GTK_UNIT_MM ) ,
gtk_paper_size_get_height ( gtk_page_setup_get_paper_size ( data - > page_setup ) , GTK_UNIT_MM ) ) ;
}
}
}
else
{
/* Handle other custom options... */
ppd_cparam_t * cparam ;
cparam = ( ppd_cparam_t * ) cupsArrayFirst ( coption - > params ) ;
if ( cparam ! = NULL )
{
switch ( cparam - > type )
{
case PPD_CUSTOM_CURVE :
case PPD_CUSTOM_INVCURVE :
case PPD_CUSTOM_REAL :
if ( g_regex_match_simple ( " ^ " SIGNED_FLOAT_REGEX " $ " , value , G_REGEX_CASELESS , 0 ) )
custom_value = TRUE ;
break ;
case PPD_CUSTOM_POINTS :
if ( g_regex_match_simple ( " ^ " SIGNED_FLOAT_REGEX " (cm|mm|m|in|ft|pt)?$ " , value , G_REGEX_CASELESS , 0 ) )
custom_value = TRUE ;
break ;
case PPD_CUSTOM_INT :
if ( g_regex_match_simple ( " ^ " SIGNED_INTEGER_REGEX " $ " , value , G_REGEX_CASELESS , 0 ) )
custom_value = TRUE ;
break ;
case PPD_CUSTOM_PASSCODE :
case PPD_CUSTOM_PASSWORD :
case PPD_CUSTOM_STRING :
custom_value = TRUE ;
break ;
2020-10-24 11:16:40 +00:00
# if (CUPS_VERSION_MAJOR >= 3) || \
( CUPS_VERSION_MAJOR = = 2 & & CUPS_VERSION_MINOR > = 3 ) | | \
( CUPS_VERSION_MAJOR = = 2 & & CUPS_VERSION_MINOR = = 2 & & CUPS_VERSION_PATCH > = 12 )
2020-05-18 09:38:02 +00:00
case PPD_CUSTOM_UNKNOWN :
2020-10-24 11:16:40 +00:00
# endif
2019-04-04 16:39:18 +00:00
default :
custom_value = FALSE ;
}
}
}
}
2012-01-31 11:15:43 +00:00
}
}
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2012-09-18 12:18:15 +00:00
/* Add "Custom." prefix to custom values if not already added. */
2019-04-04 16:39:18 +00:00
if ( custom_value )
2011-12-24 16:26:32 +00:00
{
2019-04-04 16:39:18 +00:00
if ( new_value = = NULL )
new_value = g_strdup_printf ( " Custom.%s " , value ) ;
2011-12-24 16:26:32 +00:00
gtk_cups_request_encode_option ( request , key , new_value ) ;
g_free ( new_value ) ;
}
else
gtk_cups_request_encode_option ( request , key , value ) ;
2006-04-21 15:09:32 +00:00
}
static void
2006-06-16 18:29:09 +00:00
gtk_print_backend_cups_print_stream ( GtkPrintBackend * print_backend ,
GtkPrintJob * job ,
2006-06-21 18:16:58 +00:00
GIOChannel * data_io ,
2006-06-16 18:29:09 +00:00
GtkPrintJobCompleteFunc callback ,
gpointer user_data ,
2006-06-21 18:16:58 +00:00
GDestroyNotify dnotify )
2006-04-21 15:09:32 +00:00
{
GtkPrinterCups * cups_printer ;
CupsPrintStreamData * ps ;
2011-12-24 16:26:32 +00:00
CupsOptionsData * options_data ;
2019-04-04 16:39:18 +00:00
GtkPageSetup * page_setup ;
2013-03-04 13:29:24 +00:00
GtkCupsRequest * request = NULL ;
2006-04-21 15:09:32 +00:00
GtkPrintSettings * settings ;
2020-07-24 18:40:36 +00:00
const char * title ;
2008-06-12 13:03:35 +00:00
char printer_absolute_uri [ HTTP_MAX_URI ] ;
2013-12-16 15:44:58 +00:00
http_t * http = NULL ;
2006-04-21 15:09:32 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
2012-02-19 21:29:11 +00:00
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2006-06-21 18:16:58 +00:00
2006-04-21 15:09:32 +00:00
cups_printer = GTK_PRINTER_CUPS ( gtk_print_job_get_printer ( job ) ) ;
settings = gtk_print_job_get_settings ( job ) ;
2013-03-04 13:29:24 +00:00
if ( cups_printer - > avahi_browsed )
{
2019-04-12 17:00:02 +00:00
http = httpConnect2 ( cups_printer - > hostname , cups_printer - > port ,
NULL , AF_UNSPEC ,
HTTP_ENCRYPTION_IF_REQUESTED ,
1 , 30000 ,
NULL ) ;
2013-03-04 13:29:24 +00:00
if ( http )
{
request = gtk_cups_request_new_with_username ( http ,
GTK_CUPS_POST ,
IPP_PRINT_JOB ,
data_io ,
cups_printer - > hostname ,
cups_printer - > device_uri ,
GTK_PRINT_BACKEND_CUPS ( print_backend ) - > username ) ;
2013-03-06 21:26:21 +00:00
g_snprintf ( printer_absolute_uri , HTTP_MAX_URI , " %s " , cups_printer - > printer_uri ) ;
2013-03-04 13:29:24 +00:00
}
else
{
GError * error = NULL ;
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Error connecting to %s:%d " ,
cups_printer - > hostname ,
cups_printer - > port ) ) ;
error = g_error_new ( gtk_print_error_quark ( ) ,
GTK_CUPS_ERROR_GENERAL ,
" Error connecting to %s " ,
cups_printer - > hostname ) ;
gtk_print_job_set_status ( job , GTK_PRINT_STATUS_FINISHED_ABORTED ) ;
if ( callback )
{
callback ( job , user_data , error ) ;
}
g_clear_error ( & error ) ;
return ;
}
}
else
{
request = gtk_cups_request_new_with_username ( NULL ,
GTK_CUPS_POST ,
IPP_PRINT_JOB ,
data_io ,
NULL ,
cups_printer - > device_uri ,
GTK_PRINT_BACKEND_CUPS ( print_backend ) - > username ) ;
httpAssembleURIf ( HTTP_URI_CODING_ALL ,
printer_absolute_uri ,
sizeof ( printer_absolute_uri ) ,
" ipp " ,
NULL ,
" localhost " ,
ippPort ( ) ,
" /printers/%s " ,
gtk_printer_get_name ( gtk_print_job_get_printer ( job ) ) ) ;
}
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
gtk_cups_request_set_ipp_version ( request ,
cups_printer - > ipp_version_major ,
cups_printer - > ipp_version_minor ) ;
2008-06-12 13:03:35 +00:00
2012-02-19 21:29:11 +00:00
gtk_cups_request_ipp_add_string ( request , IPP_TAG_OPERATION ,
2007-01-03 20:34:00 +00:00
IPP_TAG_URI , " printer-uri " ,
2008-06-12 13:03:35 +00:00
NULL , printer_absolute_uri ) ;
2006-04-21 15:09:32 +00:00
title = gtk_print_job_get_title ( job ) ;
2016-11-08 10:44:44 +00:00
if ( title ) {
char * title_truncated = NULL ;
size_t title_bytes = strlen ( title ) ;
if ( title_bytes > = IPP_MAX_NAME )
{
2020-07-24 18:40:36 +00:00
char * end ;
2016-11-08 10:44:44 +00:00
end = g_utf8_find_prev_char ( title , title + IPP_MAX_NAME - 1 ) ;
title_truncated = g_utf8_substring ( title ,
0 ,
g_utf8_pointer_to_offset ( title , end ) ) ;
}
2012-02-19 21:29:11 +00:00
gtk_cups_request_ipp_add_string ( request , IPP_TAG_OPERATION ,
IPP_TAG_NAME , " job-name " ,
2016-11-08 10:44:44 +00:00
NULL ,
title_truncated ? title_truncated : title ) ;
g_free ( title_truncated ) ;
}
2006-04-21 15:09:32 +00:00
2019-04-04 16:39:18 +00:00
g_object_get ( job ,
" page-setup " , & page_setup ,
NULL ) ;
2011-12-24 16:26:32 +00:00
options_data = g_new0 ( CupsOptionsData , 1 ) ;
options_data - > request = request ;
2012-01-31 11:15:43 +00:00
options_data - > printer = cups_printer ;
2019-04-04 16:39:18 +00:00
options_data - > page_setup = page_setup ;
2011-12-24 16:26:32 +00:00
gtk_print_settings_foreach ( settings , add_cups_options , options_data ) ;
2019-04-04 16:39:18 +00:00
g_clear_object ( & page_setup ) ;
2011-12-24 16:26:32 +00:00
g_free ( options_data ) ;
2006-04-21 15:09:32 +00:00
ps = g_new0 ( CupsPrintStreamData , 1 ) ;
ps - > callback = callback ;
ps - > user_data = user_data ;
ps - > dnotify = dnotify ;
ps - > job = g_object_ref ( job ) ;
2013-12-16 15:44:58 +00:00
ps - > http = http ;
2006-04-21 15:09:32 +00:00
2015-02-05 10:14:01 +00:00
request - > need_auth_info = FALSE ;
request - > auth_info_required = NULL ;
/* Check if auth_info_required is set and if it should be handled.
* The cups libraries handle the ticket exchange for " negotiate " . */
if ( cups_printer - > auth_info_required ! = NULL & &
g_strv_length ( cups_printer - > auth_info_required ) = = 1 & &
g_strcmp0 ( cups_printer - > auth_info_required [ 0 ] , " negotiate " ) = = 0 )
{
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Ignoring auth-info-required \" %s \" \n " ,
cups_printer - > auth_info_required [ 0 ] ) ) ;
}
else if ( cups_printer - > auth_info_required ! = NULL )
{
request - > need_auth_info = TRUE ;
request - > auth_info_required = g_strdupv ( cups_printer - > auth_info_required ) ;
}
2009-09-24 13:34:56 +00:00
2006-04-21 15:09:32 +00:00
cups_request_execute ( GTK_PRINT_BACKEND_CUPS ( print_backend ) ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_print_cb ,
ps ,
2006-06-21 05:08:43 +00:00
( GDestroyNotify ) cups_free_print_stream_data ) ;
2006-04-21 15:09:32 +00:00
}
2009-04-21 12:24:32 +00:00
void overwrite_and_free ( gpointer data )
{
2020-07-24 18:40:36 +00:00
char * password = ( char * ) data ;
2009-04-21 12:24:32 +00:00
if ( password ! = NULL )
{
memset ( password , 0 , strlen ( password ) ) ;
g_free ( password ) ;
}
}
2006-04-21 15:09:32 +00:00
static void
gtk_print_backend_cups_init ( GtkPrintBackendCups * backend_cups )
{
2019-05-06 19:04:17 +00:00
int i ;
2013-03-12 16:18:16 +00:00
2012-02-19 21:29:11 +00:00
backend_cups - > list_printers_poll = FALSE ;
backend_cups - > got_default_printer = FALSE ;
2006-04-21 15:09:32 +00:00
backend_cups - > list_printers_pending = FALSE ;
2009-09-30 16:40:11 +00:00
backend_cups - > list_printers_attempts = 0 ;
2010-05-24 14:39:19 +00:00
backend_cups - > reading_ppds = 0 ;
2006-04-21 15:09:32 +00:00
2009-04-21 12:24:32 +00:00
backend_cups - > requests = NULL ;
backend_cups - > auth = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , overwrite_and_free ) ;
backend_cups - > authentication_lock = FALSE ;
2008-07-31 23:56:17 +00:00
backend_cups - > default_printer_poll = 0 ;
2008-09-17 22:07:10 +00:00
backend_cups - > cups_connection_test = NULL ;
2008-07-31 23:56:17 +00:00
2009-04-21 12:24:32 +00:00
backend_cups - > username = NULL ;
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
backend_cups - > colord_client = cd_client_new ( ) ;
# endif
2013-03-12 16:18:16 +00:00
backend_cups - > dbus_connection = NULL ;
2013-03-04 13:29:24 +00:00
backend_cups - > avahi_default_printer = NULL ;
2013-03-12 16:18:16 +00:00
backend_cups - > avahi_service_browser_subscription_id = 0 ;
for ( i = 0 ; i < 2 ; i + + )
{
backend_cups - > avahi_service_browser_paths [ i ] = NULL ;
backend_cups - > avahi_service_browser_subscription_ids [ i ] = 0 ;
}
2013-03-04 13:29:24 +00:00
2008-09-17 22:07:10 +00:00
cups_get_local_default_printer ( backend_cups ) ;
2014-08-19 15:55:47 +00:00
backend_cups - > secrets_service_available = FALSE ;
backend_cups - > secrets_service_cancellable = g_cancellable_new ( ) ;
backend_cups - > secrets_service_watch_id =
gtk_cups_secrets_service_watch ( secrets_service_appeared_cb ,
secrets_service_vanished_cb ,
backend_cups ) ;
2021-02-05 17:13:34 +00:00
backend_cups - > temporary_queues_in_construction = NULL ;
backend_cups - > temporary_queues_removed = NULL ;
2006-04-21 15:09:32 +00:00
}
static void
gtk_print_backend_cups_finalize ( GObject * object )
{
GtkPrintBackendCups * backend_cups ;
2012-02-19 21:29:11 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: finalizing CUPS backend module \n " ) ) ;
2006-04-21 15:09:32 +00:00
backend_cups = GTK_PRINT_BACKEND_CUPS ( object ) ;
g_free ( backend_cups - > default_printer ) ;
backend_cups - > default_printer = NULL ;
2008-07-15 17:45:18 +00:00
2008-09-17 22:07:10 +00:00
gtk_cups_connection_test_free ( backend_cups - > cups_connection_test ) ;
backend_cups - > cups_connection_test = NULL ;
2009-04-21 12:24:32 +00:00
g_hash_table_destroy ( backend_cups - > auth ) ;
g_free ( backend_cups - > username ) ;
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
g_object_unref ( backend_cups - > colord_client ) ;
# endif
2013-03-25 12:01:23 +00:00
g_clear_object ( & backend_cups - > avahi_cancellable ) ;
g_clear_pointer ( & backend_cups - > avahi_default_printer , g_free ) ;
g_clear_object ( & backend_cups - > dbus_connection ) ;
2014-08-19 15:55:47 +00:00
g_clear_object ( & backend_cups - > secrets_service_cancellable ) ;
if ( backend_cups - > secrets_service_watch_id ! = 0 )
{
g_bus_unwatch_name ( backend_cups - > secrets_service_watch_id ) ;
}
2021-02-05 17:13:34 +00:00
g_list_free_full ( backend_cups - > temporary_queues_in_construction , g_free ) ;
backend_cups - > temporary_queues_in_construction = NULL ;
g_list_free_full ( backend_cups - > temporary_queues_removed , g_free ) ;
backend_cups - > temporary_queues_removed = NULL ;
2013-03-25 12:01:23 +00:00
backend_parent_class - > finalize ( object ) ;
}
static void
gtk_print_backend_cups_dispose ( GObject * object )
{
GtkPrintBackendCups * backend_cups ;
2019-05-06 19:04:17 +00:00
int i ;
2013-03-25 12:01:23 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
backend_cups = GTK_PRINT_BACKEND_CUPS ( object ) ;
if ( backend_cups - > list_printers_poll > 0 )
g_source_remove ( backend_cups - > list_printers_poll ) ;
backend_cups - > list_printers_poll = 0 ;
backend_cups - > list_printers_attempts = 0 ;
if ( backend_cups - > default_printer_poll > 0 )
g_source_remove ( backend_cups - > default_printer_poll ) ;
backend_cups - > default_printer_poll = 0 ;
2013-03-12 16:18:16 +00:00
g_cancellable_cancel ( backend_cups - > avahi_cancellable ) ;
for ( i = 0 ; i < 2 ; i + + )
{
if ( backend_cups - > avahi_service_browser_subscription_ids [ i ] > 0 )
{
g_dbus_connection_signal_unsubscribe ( backend_cups - > dbus_connection ,
backend_cups - > avahi_service_browser_subscription_ids [ i ] ) ;
backend_cups - > avahi_service_browser_subscription_ids [ i ] = 0 ;
}
if ( backend_cups - > avahi_service_browser_paths [ i ] )
{
g_dbus_connection_call ( backend_cups - > dbus_connection ,
AVAHI_BUS ,
backend_cups - > avahi_service_browser_paths [ i ] ,
AVAHI_SERVICE_BROWSER_IFACE ,
" Free " ,
NULL ,
NULL ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
NULL ,
NULL ,
NULL ) ;
g_clear_pointer ( & backend_cups - > avahi_service_browser_paths [ i ] , g_free ) ;
}
}
if ( backend_cups - > avahi_service_browser_subscription_id > 0 )
{
g_dbus_connection_signal_unsubscribe ( backend_cups - > dbus_connection ,
backend_cups - > avahi_service_browser_subscription_id ) ;
backend_cups - > avahi_service_browser_subscription_id = 0 ;
}
2013-03-04 13:29:24 +00:00
2021-02-05 17:13:56 +00:00
if ( backend_cups - > unsubscribe_general_subscription_id > 0 )
{
g_source_remove ( backend_cups - > unsubscribe_general_subscription_id ) ;
backend_cups - > unsubscribe_general_subscription_id = 0 ;
}
2006-05-04 13:43:32 +00:00
backend_parent_class - > dispose ( object ) ;
}
2009-04-21 12:24:32 +00:00
static gboolean
2020-07-24 18:40:36 +00:00
is_address_local ( const char * address )
2009-04-21 12:24:32 +00:00
{
if ( address [ 0 ] = = ' / ' | |
strcmp ( address , " 127.0.0.1 " ) = = 0 | |
strcmp ( address , " [::1] " ) = = 0 )
return TRUE ;
else
return FALSE ;
}
static void
2009-09-24 13:34:56 +00:00
gtk_print_backend_cups_set_password ( GtkPrintBackend * backend ,
2020-07-24 18:40:36 +00:00
char * * auth_info_required ,
char * * auth_info ,
2014-08-19 15:55:47 +00:00
gboolean store_auth_info )
2009-04-21 12:24:32 +00:00
{
GtkPrintBackendCups * cups_backend = GTK_PRINT_BACKEND_CUPS ( backend ) ;
GList * l ;
char dispatch_hostname [ HTTP_MAX_URI ] ;
2020-07-24 18:40:36 +00:00
char * username = NULL ;
char * hostname = NULL ;
char * password = NULL ;
2020-07-24 13:54:49 +00:00
int length ;
int i ;
2009-04-21 12:24:32 +00:00
2009-09-24 13:34:56 +00:00
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 )
{
2020-07-24 18:40:36 +00:00
char * key = g_strconcat ( username , " @ " , hostname , NULL ) ;
2009-09-24 13:34:56 +00:00
g_hash_table_insert ( cups_backend - > auth , key , g_strdup ( password ) ) ;
2010-10-08 14:01:07 +00:00
GTK_NOTE ( PRINTING ,
2014-08-19 15:55:47 +00:00
g_print ( " CUPS backend: caching password for %s \n " , key ) ) ;
2009-09-24 13:34:56 +00:00
}
2009-04-21 12:24:32 +00:00
g_free ( cups_backend - > username ) ;
cups_backend - > username = g_strdup ( username ) ;
for ( l = cups_backend - > requests ; l ; l = l - > next )
{
GtkPrintCupsDispatchWatch * dispatch = l - > data ;
httpGetHostname ( dispatch - > request - > http , dispatch_hostname , sizeof ( dispatch_hostname ) ) ;
if ( is_address_local ( dispatch_hostname ) )
strcpy ( dispatch_hostname , " localhost " ) ;
2009-09-24 13:34:56 +00:00
if ( dispatch - > request - > need_auth_info )
{
if ( auth_info ! = NULL )
{
2020-07-24 18:40:36 +00:00
dispatch - > request - > auth_info = g_new0 ( char * , length + 1 ) ;
2009-09-24 13:34:56 +00:00
for ( i = 0 ; i < length ; i + + )
dispatch - > request - > auth_info [ i ] = g_strdup ( auth_info [ i ] ) ;
}
2014-08-19 15:55:47 +00:00
/* Save the password if the user requested it */
if ( password ! = NULL & & store_auth_info )
{
2020-07-24 18:40:36 +00:00
const char * printer_uri =
2014-08-19 15:55:47 +00:00
gtk_cups_request_ipp_get_string ( dispatch - > request ,
IPP_TAG_URI ,
" printer-uri " ) ;
gtk_cups_secrets_service_store ( auth_info , auth_info_required ,
printer_uri ) ;
}
2009-09-24 13:34:56 +00:00
dispatch - > backend - > authentication_lock = FALSE ;
dispatch - > request - > need_auth_info = FALSE ;
}
else if ( dispatch - > request - > password_state = = GTK_CUPS_PASSWORD_REQUESTED | | auth_info = = NULL )
2009-04-21 12:24:32 +00:00
{
overwrite_and_free ( dispatch - > request - > password ) ;
dispatch - > request - > password = g_strdup ( password ) ;
g_free ( dispatch - > request - > username ) ;
dispatch - > request - > username = g_strdup ( username ) ;
dispatch - > request - > password_state = GTK_CUPS_PASSWORD_HAS ;
dispatch - > backend - > authentication_lock = FALSE ;
}
}
}
static gboolean
request_password ( gpointer data )
{
GtkPrintCupsDispatchWatch * dispatch = data ;
2020-07-24 18:40:36 +00:00
const char * username ;
char * password ;
char * prompt = NULL ;
char * key = NULL ;
2009-04-21 12:24:32 +00:00
char hostname [ HTTP_MAX_URI ] ;
2020-07-24 18:40:36 +00:00
char * * auth_info_required ;
char * * auth_info_default ;
char * * auth_info_display ;
2009-09-24 13:34:56 +00:00
gboolean * auth_info_visible ;
2020-07-24 13:54:49 +00:00
int length = 3 ;
int i ;
2009-04-21 12:24:32 +00:00
if ( dispatch - > backend - > authentication_lock )
2012-01-31 00:12:27 +00:00
return G_SOURCE_REMOVE ;
2009-04-21 12:24:32 +00:00
httpGetHostname ( dispatch - > request - > http , hostname , sizeof ( hostname ) ) ;
if ( is_address_local ( hostname ) )
strcpy ( hostname , " localhost " ) ;
if ( dispatch - > backend - > username ! = NULL )
username = dispatch - > backend - > username ;
else
username = cupsUser ( ) ;
2020-07-24 18:40:36 +00:00
auth_info_required = g_new0 ( char * , length + 1 ) ;
2009-09-24 13:34:56 +00:00
auth_info_required [ 0 ] = g_strdup ( " hostname " ) ;
auth_info_required [ 1 ] = g_strdup ( " username " ) ;
auth_info_required [ 2 ] = g_strdup ( " password " ) ;
2020-07-24 18:40:36 +00:00
auth_info_default = g_new0 ( char * , length + 1 ) ;
2009-09-24 13:34:56 +00:00
auth_info_default [ 0 ] = g_strdup ( hostname ) ;
auth_info_default [ 1 ] = g_strdup ( username ) ;
2020-07-24 18:40:36 +00:00
auth_info_display = g_new0 ( char * , length + 1 ) ;
2009-09-24 13:34:56 +00:00
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 ;
2009-04-21 12:24:32 +00:00
key = g_strconcat ( username , " @ " , hostname , NULL ) ;
password = g_hash_table_lookup ( dispatch - > backend - > auth , key ) ;
if ( password & & dispatch - > request - > password_state ! = GTK_CUPS_PASSWORD_NOT_VALID )
{
GTK_NOTE ( PRINTING ,
g_print ( " CUPS backend: using stored password for %s \n " , key ) ) ;
overwrite_and_free ( dispatch - > request - > password ) ;
dispatch - > request - > password = g_strdup ( password ) ;
g_free ( dispatch - > request - > username ) ;
dispatch - > request - > username = g_strdup ( username ) ;
dispatch - > request - > password_state = GTK_CUPS_PASSWORD_HAS ;
}
else
{
const char * job_title = gtk_cups_request_ipp_get_string ( dispatch - > request , IPP_TAG_NAME , " job-name " ) ;
const char * printer_uri = gtk_cups_request_ipp_get_string ( dispatch - > request , IPP_TAG_URI , " printer-uri " ) ;
char * printer_name = NULL ;
if ( printer_uri ! = NULL & & strrchr ( printer_uri , ' / ' ) ! = NULL )
printer_name = g_strdup ( strrchr ( printer_uri , ' / ' ) + 1 ) ;
if ( dispatch - > request - > password_state = = GTK_CUPS_PASSWORD_NOT_VALID )
g_hash_table_remove ( dispatch - > backend - > auth , key ) ;
dispatch - > request - > password_state = GTK_CUPS_PASSWORD_REQUESTED ;
dispatch - > backend - > authentication_lock = TRUE ;
2020-05-18 09:38:02 +00:00
switch ( ( guint ) ippGetOperation ( dispatch - > request - > ipp_request ) )
2009-04-21 12:24:32 +00:00
{
case IPP_PRINT_JOB :
if ( job_title ! = NULL & & printer_name ! = NULL )
2014-08-22 15:10:39 +00:00
prompt = g_strdup_printf ( _ ( " Authentication is required to print document “%s” on printer %s " ) , job_title , printer_name ) ;
2009-04-21 12:24:32 +00:00
else
prompt = g_strdup_printf ( _ ( " Authentication is required to print a document on %s " ) , hostname ) ;
break ;
case IPP_GET_JOB_ATTRIBUTES :
if ( job_title ! = NULL )
2014-08-22 15:10:39 +00:00
prompt = g_strdup_printf ( _ ( " Authentication is required to get attributes of job “%s” " ) , job_title ) ;
2009-04-21 12:24:32 +00:00
else
prompt = g_strdup ( _ ( " Authentication is required to get attributes of a job " ) ) ;
break ;
case IPP_GET_PRINTER_ATTRIBUTES :
if ( printer_name ! = NULL )
prompt = g_strdup_printf ( _ ( " Authentication is required to get attributes of printer %s " ) , printer_name ) ;
else
prompt = g_strdup ( _ ( " Authentication is required to get attributes of a printer " ) ) ;
break ;
case CUPS_GET_DEFAULT :
prompt = g_strdup_printf ( _ ( " Authentication is required to get default printer of %s " ) , hostname ) ;
break ;
case CUPS_GET_PRINTERS :
prompt = g_strdup_printf ( _ ( " Authentication is required to get printers from %s " ) , hostname ) ;
break ;
default :
2010-10-18 17:08:55 +00:00
/* work around gcc warning about 0 not being a value for this enum */
2012-02-18 22:16:27 +00:00
if ( ippGetOperation ( dispatch - > request - > ipp_request ) = = 0 )
2010-10-18 17:08:55 +00:00
prompt = g_strdup_printf ( _ ( " Authentication is required to get a file from %s " ) , hostname ) ;
else
prompt = g_strdup_printf ( _ ( " Authentication is required on %s " ) , hostname ) ;
2009-04-21 12:24:32 +00:00
break ;
}
g_free ( printer_name ) ;
2012-02-19 21:29:11 +00:00
g_signal_emit_by_name ( dispatch - > backend , " request-password " ,
2014-08-19 15:55:47 +00:00
auth_info_required , auth_info_default ,
auth_info_display , auth_info_visible , prompt ,
FALSE ) ; /* Cups password is only cached not stored. */
2009-04-21 12:24:32 +00:00
g_free ( prompt ) ;
}
2009-09-24 13:34:56 +00:00
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 ) ;
2009-04-21 12:24:32 +00:00
g_free ( key ) ;
2012-01-31 00:12:27 +00:00
return G_SOURCE_REMOVE ;
2009-04-21 12:24:32 +00:00
}
2006-05-04 13:43:32 +00:00
2009-08-30 01:32:01 +00:00
static void
cups_dispatch_add_poll ( GSource * source )
2006-04-21 15:09:32 +00:00
{
GtkPrintCupsDispatchWatch * dispatch ;
GtkCupsPollState poll_state ;
2006-06-21 18:16:58 +00:00
2006-04-21 15:09:32 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) source ;
poll_state = gtk_cups_request_get_poll_state ( dispatch - > request ) ;
2011-08-06 08:37:21 +00:00
/* Remove the old source if the poll state changed. */
if ( poll_state ! = dispatch - > poll_state & & dispatch - > data_poll ! = NULL )
{
g_source_remove_poll ( source , dispatch - > data_poll ) ;
g_free ( dispatch - > data_poll ) ;
dispatch - > data_poll = NULL ;
}
2006-12-27 06:49:49 +00:00
if ( dispatch - > request - > http ! = NULL )
2006-04-21 15:09:32 +00:00
{
2006-12-27 06:49:49 +00:00
if ( dispatch - > data_poll = = NULL )
2009-08-30 01:32:01 +00:00
{
2006-12-27 06:49:49 +00:00
dispatch - > data_poll = g_new0 ( GPollFD , 1 ) ;
2011-08-06 08:37:21 +00:00
dispatch - > poll_state = poll_state ;
2009-08-30 01:32:01 +00:00
2006-12-27 06:49:49 +00:00
if ( poll_state = = GTK_CUPS_HTTP_READ )
dispatch - > data_poll - > events = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI ;
else if ( poll_state = = GTK_CUPS_HTTP_WRITE )
dispatch - > data_poll - > events = G_IO_OUT | G_IO_ERR ;
else
dispatch - > data_poll - > events = 0 ;
2007-01-17 06:10:08 +00:00
2009-08-30 01:32:01 +00:00
dispatch - > data_poll - > fd = httpGetFd ( dispatch - > request - > http ) ;
g_source_add_poll ( source , dispatch - > data_poll ) ;
}
2006-04-21 15:09:32 +00:00
}
2009-08-30 01:32:01 +00:00
}
2009-09-24 13:34:56 +00:00
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
{
2020-07-24 13:54:49 +00:00
int length ;
int i ;
2009-09-24 13:34:56 +00:00
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 ,
2010-07-12 12:40:04 +00:00
( const char * const * ) dispatch - > request - > auth_info ) ;
2009-09-24 13:34:56 +00:00
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 ;
}
2012-01-31 00:12:27 +00:00
return G_SOURCE_REMOVE ;
2009-09-24 13:34:56 +00:00
}
2012-01-31 00:12:27 +00:00
return G_SOURCE_CONTINUE ;
2009-09-24 13:34:56 +00:00
}
2014-08-19 15:55:47 +00:00
static void
lookup_auth_info_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
{
GTask * task ;
GtkPrintCupsDispatchWatch * dispatch ;
2020-07-24 18:40:36 +00:00
char * * auth_info ;
2014-08-19 15:55:47 +00:00
GError * error = NULL ;
2020-07-24 13:54:49 +00:00
int i ;
2014-08-19 15:55:47 +00:00
task = ( GTask * ) res ;
dispatch = user_data ;
auth_info = g_task_propagate_pointer ( task , & error ) ;
if ( auth_info = = NULL )
{
if ( error ! = NULL )
{
GTK_NOTE ( PRINTING ,
g_print ( " Failed to look up auth info: %s \n " , error - > message ) ) ;
g_error_free ( error ) ;
}
else
{
/* Error note should have been shown by the function causing this */
GTK_NOTE ( PRINTING , g_print ( " Failed to look up auth info. \n " ) ) ;
}
dispatch - > backend - > authentication_lock = FALSE ;
g_object_unref ( task ) ;
request_auth_info ( dispatch ) ;
return ;
}
gtk_print_backend_cups_set_password ( GTK_PRINT_BACKEND ( dispatch - > backend ) ,
dispatch - > request - > auth_info_required , auth_info ,
FALSE ) ;
for ( i = 0 ; auth_info [ i ] ! = NULL ; i + + )
{
overwrite_and_free ( auth_info [ i ] ) ;
auth_info [ i ] = NULL ;
}
g_clear_pointer ( auth_info , g_free ) ;
g_object_unref ( task ) ;
}
static void
lookup_auth_info ( gpointer user_data )
{
GtkPrintCupsDispatchWatch * dispatch ;
gsize length ,
i ;
gboolean need_secret_auth_info = FALSE ;
2020-07-24 18:40:36 +00:00
const char * printer_uri ;
2014-08-19 15:55:47 +00:00
dispatch = user_data ;
if ( dispatch - > backend - > authentication_lock )
return ;
length = g_strv_length ( dispatch - > request - > auth_info_required ) ;
for ( i = 0 ; i < length ; i + + )
{
if ( g_strcmp0 ( dispatch - > request - > auth_info_required [ i ] , " password " ) = = 0 )
{
need_secret_auth_info = TRUE ;
break ;
}
}
g_idle_add ( check_auth_info , user_data ) ;
if ( dispatch - > backend - > secrets_service_available & & need_secret_auth_info )
{
dispatch - > backend - > authentication_lock = TRUE ;
printer_uri = gtk_cups_request_ipp_get_string ( dispatch - > request ,
IPP_TAG_URI ,
" printer-uri " ) ;
gtk_cups_secrets_service_query_task ( dispatch - > backend ,
dispatch - > backend - > secrets_service_cancellable ,
lookup_auth_info_cb ,
dispatch ,
printer_uri ,
dispatch - > request - > auth_info_required ) ;
return ;
}
request_auth_info ( user_data ) ;
}
2009-09-24 13:34:56 +00:00
static gboolean
request_auth_info ( gpointer user_data )
{
GtkPrintCupsDispatchWatch * dispatch ;
const char * job_title ;
const char * printer_uri ;
2020-07-24 18:40:36 +00:00
char * prompt = NULL ;
2009-09-24 13:34:56 +00:00
char * printer_name = NULL ;
2020-07-24 13:54:49 +00:00
int length ;
int i ;
2009-09-24 13:34:56 +00:00
gboolean * auth_info_visible = NULL ;
2020-07-24 18:40:36 +00:00
char * * auth_info_default = NULL ;
char * * auth_info_display = NULL ;
2009-09-24 13:34:56 +00:00
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 ) ;
2020-07-24 18:40:36 +00:00
auth_info_default = g_new0 ( char * , length + 1 ) ;
auth_info_display = g_new0 ( char * , length + 1 ) ;
2009-09-24 13:34:56 +00:00
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 )
2014-08-22 15:10:39 +00:00
prompt = g_strdup_printf ( _ ( " Authentication is required to print document “%s” on printer %s " ) , job_title , printer_name ) ;
2009-09-24 13:34:56 +00:00
else
2014-08-22 15:10:39 +00:00
prompt = g_strdup_printf ( _ ( " Authentication is required to print document “%s” " ) , job_title ) ;
2009-09-24 13:34:56 +00:00
}
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 ,
2014-08-19 15:55:47 +00:00
prompt ,
dispatch - > backend - > secrets_service_available ) ;
2009-09-24 13:34:56 +00:00
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 ) ;
return FALSE ;
}
2009-08-30 01:32:01 +00:00
static gboolean
cups_dispatch_watch_check ( GSource * source )
{
GtkPrintCupsDispatchWatch * dispatch ;
GtkCupsPollState poll_state ;
gboolean result ;
GTK_NOTE ( PRINTING ,
2012-02-19 21:29:11 +00:00
g_print ( " CUPS Backend: %s <source %p> \n " , G_STRFUNC , source ) ) ;
2009-08-30 01:32:01 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) source ;
poll_state = gtk_cups_request_get_poll_state ( dispatch - > request ) ;
2009-04-21 12:24:32 +00:00
if ( poll_state ! = GTK_CUPS_HTTP_IDLE & & ! dispatch - > request - > need_password )
2012-02-19 21:29:11 +00:00
if ( ! ( dispatch - > data_poll - > revents & dispatch - > data_poll - > events ) )
2006-04-21 15:09:32 +00:00
return FALSE ;
2012-02-19 21:29:11 +00:00
2011-08-06 08:37:21 +00:00
result = gtk_cups_request_read_write ( dispatch - > request , FALSE ) ;
2006-04-21 15:09:32 +00:00
if ( result & & dispatch - > data_poll ! = NULL )
{
g_source_remove_poll ( source , dispatch - > data_poll ) ;
g_free ( dispatch - > data_poll ) ;
dispatch - > data_poll = NULL ;
}
2009-04-21 12:24:32 +00:00
if ( dispatch - > request - > need_password & & dispatch - > request - > password_state ! = GTK_CUPS_PASSWORD_REQUESTED )
{
dispatch - > request - > need_password = FALSE ;
g_idle_add ( request_password , dispatch ) ;
result = FALSE ;
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
return result ;
}
static gboolean
cups_dispatch_watch_prepare ( GSource * source ,
2020-07-24 13:54:49 +00:00
int * timeout_ )
2006-04-21 15:09:32 +00:00
{
GtkPrintCupsDispatchWatch * dispatch ;
2009-08-30 01:32:01 +00:00
gboolean result ;
2006-04-21 15:09:32 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) source ;
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s <source %p> \n " , G_STRFUNC , source ) ) ;
2006-04-21 15:09:32 +00:00
* timeout_ = - 1 ;
2011-08-06 08:37:21 +00:00
result = gtk_cups_request_read_write ( dispatch - > request , TRUE ) ;
2009-08-30 01:32:01 +00:00
cups_dispatch_add_poll ( source ) ;
return result ;
2006-04-21 15:09:32 +00:00
}
static gboolean
2006-06-16 18:29:09 +00:00
cups_dispatch_watch_dispatch ( GSource * source ,
GSourceFunc callback ,
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
GtkPrintCupsDispatchWatch * dispatch ;
2012-02-19 21:29:11 +00:00
GtkPrintCupsResponseCallbackFunc ep_callback ;
2006-04-21 15:09:32 +00:00
GtkCupsResult * result ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
g_assert ( callback ! = NULL ) ;
ep_callback = ( GtkPrintCupsResponseCallbackFunc ) callback ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) source ;
result = gtk_cups_request_get_result ( dispatch - > request ) ;
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s <source %p> \n " , G_STRFUNC , source ) ) ;
2006-04-21 15:09:32 +00:00
if ( gtk_cups_result_is_error ( result ) )
2007-03-28 15:53:08 +00:00
{
2012-02-19 21:29:11 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " Error result: %s (type %i, status %i, code %i) \n " ,
2007-03-28 15:53:08 +00:00
gtk_cups_result_get_error_string ( result ) ,
gtk_cups_result_get_error_type ( result ) ,
gtk_cups_result_get_error_status ( result ) ,
gtk_cups_result_get_error_code ( result ) ) ) ;
}
2006-04-21 15:09:32 +00:00
ep_callback ( GTK_PRINT_BACKEND ( dispatch - > backend ) , result , user_data ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
return FALSE ;
}
static void
cups_dispatch_watch_finalize ( GSource * source )
{
GtkPrintCupsDispatchWatch * dispatch ;
2009-04-21 12:24:32 +00:00
GtkCupsResult * result ;
2006-04-21 15:09:32 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s <source %p> \n " , G_STRFUNC , source ) ) ;
2006-04-21 15:09:32 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) source ;
2009-04-21 12:24:32 +00:00
result = gtk_cups_request_get_result ( dispatch - > request ) ;
if ( gtk_cups_result_get_error_type ( result ) = = GTK_CUPS_ERROR_AUTH )
{
2020-07-24 18:40:36 +00:00
const char * username ;
char hostname [ HTTP_MAX_URI ] ;
char * key ;
2012-02-19 21:29:11 +00:00
2009-04-21 12:24:32 +00:00
httpGetHostname ( dispatch - > request - > http , hostname , sizeof ( hostname ) ) ;
if ( is_address_local ( hostname ) )
strcpy ( hostname , " localhost " ) ;
if ( dispatch - > backend - > username ! = NULL )
username = dispatch - > backend - > username ;
else
username = cupsUser ( ) ;
key = g_strconcat ( username , " @ " , hostname , NULL ) ;
GTK_NOTE ( PRINTING ,
g_print ( " CUPS backend: removing stored password for %s \n " , key ) ) ;
g_hash_table_remove ( dispatch - > backend - > auth , key ) ;
g_free ( key ) ;
2012-02-19 21:29:11 +00:00
2009-04-21 12:24:32 +00:00
if ( dispatch - > backend )
dispatch - > backend - > authentication_lock = FALSE ;
}
2006-04-21 15:09:32 +00:00
gtk_cups_request_free ( dispatch - > request ) ;
if ( dispatch - > backend )
{
2006-05-04 13:43:32 +00:00
/* We need to unref this at idle time, because it might be the
2006-05-15 15:24:12 +00:00
* last reference to this module causing the code to be
* unloaded ( including this particular function ! )
* Update : Doing this at idle caused a deadlock taking the
* mainloop context lock while being in a GSource callout for
* multithreaded apps . So , for now we just disable unloading
* of print backends . See _gtk_print_backend_create for the
* disabling .
*/
2009-04-21 12:24:32 +00:00
dispatch - > backend - > requests = g_list_remove ( dispatch - > backend - > requests , dispatch ) ;
2012-02-19 21:29:11 +00:00
2006-05-15 15:24:12 +00:00
g_object_unref ( dispatch - > backend ) ;
2006-04-21 15:09:32 +00:00
dispatch - > backend = NULL ;
}
2011-08-06 08:37:21 +00:00
if ( dispatch - > data_poll )
{
g_source_remove_poll ( source , dispatch - > data_poll ) ;
g_free ( dispatch - > data_poll ) ;
dispatch - > data_poll = NULL ;
}
2006-04-21 15:09:32 +00:00
}
static GSourceFuncs _cups_dispatch_watch_funcs = {
cups_dispatch_watch_prepare ,
cups_dispatch_watch_check ,
cups_dispatch_watch_dispatch ,
cups_dispatch_watch_finalize
} ;
static void
2006-06-16 18:29:09 +00:00
cups_request_execute ( GtkPrintBackendCups * print_backend ,
GtkCupsRequest * request ,
GtkPrintCupsResponseCallbackFunc callback ,
gpointer user_data ,
2006-06-21 05:08:43 +00:00
GDestroyNotify notify )
2006-04-21 15:09:32 +00:00
{
GtkPrintCupsDispatchWatch * dispatch ;
2006-05-04 13:43:32 +00:00
2012-02-19 21:29:11 +00:00
dispatch = ( GtkPrintCupsDispatchWatch * ) g_source_new ( & _cups_dispatch_watch_funcs ,
2006-04-21 15:09:32 +00:00
sizeof ( GtkPrintCupsDispatchWatch ) ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name ( & dispatch - > source , " GTK CUPS backend " ) ;
2006-04-21 15:09:32 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s' \n " , G_STRFUNC , dispatch , request - > server , request - > resource ) ) ;
2006-04-21 15:09:32 +00:00
dispatch - > request = request ;
dispatch - > backend = g_object_ref ( print_backend ) ;
2011-08-06 08:37:21 +00:00
dispatch - > poll_state = GTK_CUPS_HTTP_IDLE ;
2006-04-21 15:09:32 +00:00
dispatch - > data_poll = NULL ;
2009-09-24 13:34:56 +00:00
dispatch - > callback = NULL ;
dispatch - > callback_data = NULL ;
2006-04-21 15:09:32 +00:00
2009-04-21 12:24:32 +00:00
print_backend - > requests = g_list_prepend ( print_backend - > requests , dispatch ) ;
2006-04-21 15:09:32 +00:00
g_source_set_callback ( ( GSource * ) dispatch , ( GSourceFunc ) callback , user_data , notify ) ;
2009-09-24 13:34:56 +00:00
if ( request - > need_auth_info )
{
dispatch - > callback = callback ;
dispatch - > callback_data = user_data ;
2014-08-19 15:55:47 +00:00
lookup_auth_info ( dispatch ) ;
2009-09-24 13:34:56 +00:00
}
else
{
g_source_attach ( ( GSource * ) dispatch , NULL ) ;
g_source_unref ( ( GSource * ) dispatch ) ;
}
2006-04-21 15:09:32 +00:00
}
typedef struct {
GtkPrintBackendCups * print_backend ;
GtkPrintJob * job ;
int job_id ;
int counter ;
} CupsJobPollData ;
static void
2006-06-16 18:29:09 +00:00
job_object_died ( gpointer user_data ,
2006-04-21 15:09:32 +00:00
GObject * where_the_object_was )
{
CupsJobPollData * data = user_data ;
data - > job = NULL ;
}
static void
cups_job_poll_data_free ( CupsJobPollData * data )
{
if ( data - > job )
g_object_weak_unref ( G_OBJECT ( data - > job ) , job_object_died , data ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
g_free ( data ) ;
}
static void
cups_request_job_info_cb ( GtkPrintBackendCups * print_backend ,
2020-05-25 21:12:56 +00:00
GtkCupsResult * result ,
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
CupsJobPollData * data = user_data ;
ipp_attribute_t * attr ;
ipp_t * response ;
int state ;
gboolean done ;
if ( data - > job = = NULL )
{
cups_job_poll_data_free ( data ) ;
2018-02-02 15:34:40 +00:00
return ;
2006-04-21 15:09:32 +00:00
}
data - > counter + + ;
2012-02-18 22:16:27 +00:00
2006-04-21 15:09:32 +00:00
response = gtk_cups_result_get_response ( result ) ;
2013-06-05 16:00:54 +00:00
attr = ippFindAttribute ( response , " job-state " , IPP_TAG_ENUM ) ;
2012-02-18 22:16:27 +00:00
state = ippGetInteger ( attr , 0 ) ;
2006-04-21 15:09:32 +00:00
done = FALSE ;
switch ( state )
{
case IPP_JOB_PENDING :
case IPP_JOB_HELD :
case IPP_JOB_STOPPED :
2020-05-25 21:12:56 +00:00
gtk_print_job_set_status ( data - > job , GTK_PRINT_STATUS_PENDING ) ;
2006-04-21 15:09:32 +00:00
break ;
case IPP_JOB_PROCESSING :
2020-05-25 21:12:56 +00:00
gtk_print_job_set_status ( data - > job , GTK_PRINT_STATUS_PRINTING ) ;
2006-04-21 15:09:32 +00:00
break ;
default :
case IPP_JOB_CANCELLED :
case IPP_JOB_ABORTED :
2020-05-25 21:12:56 +00:00
gtk_print_job_set_status ( data - > job , GTK_PRINT_STATUS_FINISHED_ABORTED ) ;
2006-04-21 15:09:32 +00:00
done = TRUE ;
break ;
case 0 :
case IPP_JOB_COMPLETED :
2020-05-25 21:12:56 +00:00
gtk_print_job_set_status ( data - > job , GTK_PRINT_STATUS_FINISHED ) ;
2006-04-21 15:09:32 +00:00
done = TRUE ;
break ;
}
if ( ! done & & data - > job ! = NULL )
{
guint32 timeout ;
2013-10-22 13:43:43 +00:00
guint id ;
2006-04-21 15:09:32 +00:00
if ( data - > counter < 5 )
2020-05-25 21:12:56 +00:00
timeout = 100 ;
2006-04-21 15:09:32 +00:00
else if ( data - > counter < 10 )
2020-05-25 21:12:56 +00:00
timeout = 500 ;
2006-04-21 15:09:32 +00:00
else
2020-05-25 21:12:56 +00:00
timeout = 1000 ;
2012-02-19 21:29:11 +00:00
2013-10-22 13:43:43 +00:00
id = g_timeout_add ( timeout , cups_job_info_poll_timeout , data ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( id , " [gtk] cups_job_info_poll_timeout " ) ;
2006-04-21 15:09:32 +00:00
}
else
2012-02-19 21:29:11 +00:00
cups_job_poll_data_free ( data ) ;
2006-04-21 15:09:32 +00:00
}
static void
cups_request_job_info ( CupsJobPollData * data )
{
GtkCupsRequest * request ;
2020-07-24 18:40:36 +00:00
char * job_uri ;
2006-04-21 15:09:32 +00:00
2009-04-21 12:24:32 +00:00
request = gtk_cups_request_new_with_username ( NULL ,
GTK_CUPS_POST ,
IPP_GET_JOB_ATTRIBUTES ,
NULL ,
NULL ,
NULL ,
data - > print_backend - > username ) ;
2006-04-21 15:09:32 +00:00
2007-01-03 20:34:00 +00:00
job_uri = g_strdup_printf ( " ipp://localhost/jobs/%d " , data - > job_id ) ;
2006-04-21 15:09:32 +00:00
gtk_cups_request_ipp_add_string ( request , IPP_TAG_OPERATION , IPP_TAG_URI ,
2007-01-03 20:34:00 +00:00
" job-uri " , NULL , job_uri ) ;
g_free ( job_uri ) ;
2006-04-21 15:09:32 +00:00
cups_request_execute ( data - > print_backend ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_request_job_info_cb ,
data ,
2006-06-21 05:08:43 +00:00
NULL ) ;
2006-04-21 15:09:32 +00:00
}
static gboolean
cups_job_info_poll_timeout ( gpointer user_data )
{
CupsJobPollData * data = user_data ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( data - > job = = NULL )
cups_job_poll_data_free ( data ) ;
else
cups_request_job_info ( data ) ;
2012-02-19 21:29:11 +00:00
2012-01-31 00:12:27 +00:00
return G_SOURCE_REMOVE ;
2006-04-21 15:09:32 +00:00
}
static void
cups_begin_polling_info ( GtkPrintBackendCups * print_backend ,
2006-06-16 18:29:09 +00:00
GtkPrintJob * job ,
2020-07-24 13:54:49 +00:00
int job_id )
2006-04-21 15:09:32 +00:00
{
CupsJobPollData * data ;
data = g_new0 ( CupsJobPollData , 1 ) ;
data - > print_backend = print_backend ;
data - > job = job ;
data - > job_id = job_id ;
data - > counter = 0 ;
g_object_weak_ref ( G_OBJECT ( job ) , job_object_died , data ) ;
cups_request_job_info ( data ) ;
}
static void
2012-02-19 21:29:11 +00:00
mark_printer_inactive ( GtkPrinter * printer ,
2006-05-04 13:43:32 +00:00
GtkPrintBackend * backend )
2006-04-21 15:09:32 +00:00
{
2021-02-05 17:13:34 +00:00
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
GList * iter ;
if ( cups_printer - > is_temporary )
{
/* Do not recreate printers which disappeared from Avahi. */
iter = g_list_find_custom ( GTK_PRINT_BACKEND_CUPS ( backend ) - > temporary_queues_removed ,
gtk_printer_get_name ( printer ) , ( GCompareFunc ) g_strcmp0 ) ;
if ( iter = = NULL )
{
/* Recreate temporary queue since they are created for 60 seconds only. */
create_temporary_queue ( GTK_PRINT_BACKEND_CUPS ( backend ) ,
gtk_printer_get_name ( printer ) ,
cups_printer - > printer_uri ,
cups_printer - > temporary_queue_device_uri ) ;
}
}
else
{
gtk_printer_set_is_active ( printer , FALSE ) ;
g_signal_emit_by_name ( backend , " printer-removed " , printer ) ;
}
2006-04-21 15:09:32 +00:00
}
2020-07-24 13:54:49 +00:00
static int
2012-02-19 21:29:11 +00:00
find_printer ( GtkPrinter * printer ,
2020-07-24 18:40:36 +00:00
const char * find_name )
2006-04-21 15:09:32 +00:00
{
2020-07-24 18:40:36 +00:00
const char * printer_name ;
2006-04-21 15:09:32 +00:00
2006-05-04 13:43:32 +00:00
printer_name = gtk_printer_get_name ( printer ) ;
return g_ascii_strcasecmp ( printer_name , find_name ) ;
2006-04-21 15:09:32 +00:00
}
2012-02-19 21:14:36 +00:00
/* Printer messages we're interested in */
static const char * const printer_messages [ ] =
{
" toner-low " ,
" toner-empty " ,
" developer-low " ,
" developer-empty " ,
" marker-supply-low " ,
" marker-supply-empty " ,
" cover-open " ,
" door-open " ,
" media-low " ,
" media-empty " ,
" offline " ,
" other "
} ;
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
/* Attributes we're interested in for printers */
static const char * const printer_attrs [ ] =
{
" printer-name " ,
" printer-uri-supported " ,
" member-uris " ,
" printer-location " ,
" printer-info " ,
" printer-state-message " ,
" printer-state-reasons " ,
" printer-state " ,
" queued-job-count " ,
" printer-is-accepting-jobs " ,
" job-sheets-supported " ,
" job-sheets-default " ,
" printer-type " ,
" auth-info-required " ,
" number-up-default " ,
" ipp-versions-supported " ,
" multiple-document-handling-supported " ,
" copies-supported " ,
2017-08-30 15:56:00 +00:00
" number-up-supported " ,
2021-02-05 17:13:34 +00:00
" device-uri " ,
" printer-is-temporary "
2013-03-04 13:29:24 +00:00
} ;
2014-10-02 11:50:47 +00:00
/* Attributes we're interested in for printers without PPD */
static const char * const printer_attrs_detailed [ ] =
{
" printer-name " ,
" printer-uri-supported " ,
" member-uris " ,
" printer-location " ,
" printer-info " ,
" printer-state-message " ,
" printer-state-reasons " ,
" printer-state " ,
" queued-job-count " ,
" printer-is-accepting-jobs " ,
" job-sheets-supported " ,
" job-sheets-default " ,
" printer-type " ,
" auth-info-required " ,
" number-up-default " ,
" ipp-versions-supported " ,
" multiple-document-handling-supported " ,
" copies-supported " ,
2014-10-16 12:55:30 +00:00
" number-up-supported " ,
2014-10-02 11:50:47 +00:00
" media-col-default " ,
" media-col-supported " ,
" media-default " ,
" media-size-supported " ,
" media-supported " ,
" media-left-margin-supported " ,
" media-right-margin-supported " ,
" media-bottom-margin-supported " ,
" media-top-margin-supported " ,
2014-10-10 11:36:30 +00:00
" sides-default " ,
" sides-supported " ,
2015-06-23 11:28:21 +00:00
" output-bin-default " ,
" output-bin-supported " ,
2014-10-02 11:50:47 +00:00
} ;
2012-02-19 21:15:40 +00:00
typedef enum
{
GTK_PRINTER_STATE_LEVEL_NONE = 0 ,
GTK_PRINTER_STATE_LEVEL_INFO = 1 ,
GTK_PRINTER_STATE_LEVEL_WARNING = 2 ,
GTK_PRINTER_STATE_LEVEL_ERROR = 3
} PrinterStateLevel ;
2012-02-19 21:19:11 +00:00
2014-10-02 11:50:47 +00:00
typedef struct
{
float x_dimension ;
float y_dimension ;
} MediaSize ;
2012-02-19 21:19:11 +00:00
typedef struct
{
2020-07-24 18:40:36 +00:00
const char * printer_name ;
const char * printer_uri ;
const char * member_uris ;
const char * location ;
const char * description ;
char * state_msg ;
const char * reason_msg ;
2012-02-19 21:19:11 +00:00
PrinterStateLevel reason_level ;
2020-07-24 13:54:49 +00:00
int state ;
int job_count ;
2012-02-19 21:19:11 +00:00
gboolean is_paused ;
gboolean is_accepting_jobs ;
2020-07-24 18:40:36 +00:00
const char * default_cover_before ;
const char * default_cover_after ;
2012-02-19 21:19:11 +00:00
gboolean default_printer ;
gboolean got_printer_type ;
gboolean remote_printer ;
2013-03-04 13:29:24 +00:00
gboolean avahi_printer ;
2020-07-24 18:40:36 +00:00
char * avahi_resource_path ;
char * * auth_info_required ;
2020-07-24 13:54:49 +00:00
int default_number_up ;
2013-03-04 13:29:24 +00:00
guchar ipp_version_major ;
guchar ipp_version_minor ;
gboolean supports_copies ;
gboolean supports_collate ;
gboolean supports_number_up ;
2020-07-24 18:40:36 +00:00
char * media_default ;
2014-10-02 11:50:47 +00:00
GList * media_supported ;
GList * media_size_supported ;
float media_bottom_margin_default ;
float media_top_margin_default ;
float media_left_margin_default ;
float media_right_margin_default ;
gboolean media_margin_default_set ;
2020-07-24 18:40:36 +00:00
char * sides_default ;
2014-10-10 11:36:30 +00:00
GList * sides_supported ;
2015-02-25 14:54:36 +00:00
char * * covers ;
int number_of_covers ;
2020-07-24 18:40:36 +00:00
char * output_bin_default ;
2015-06-23 11:28:21 +00:00
GList * output_bin_supported ;
2020-07-24 18:40:36 +00:00
char * original_device_uri ;
2021-02-05 17:13:34 +00:00
gboolean is_temporary ;
2012-02-19 21:19:11 +00:00
} PrinterSetupInfo ;
2012-02-19 21:28:42 +00:00
2015-02-25 14:54:36 +00:00
static void
printer_setup_info_free ( PrinterSetupInfo * info )
{
2017-08-30 15:56:00 +00:00
g_free ( info - > original_device_uri ) ;
2015-02-25 14:54:36 +00:00
g_free ( info - > state_msg ) ;
g_strfreev ( info - > covers ) ;
g_slice_free ( PrinterSetupInfo , info ) ;
}
2013-03-04 13:29:24 +00:00
static void
get_ipp_version ( const char * ipp_version_string ,
guchar * ipp_version_major ,
guchar * ipp_version_minor )
{
2020-07-24 18:40:36 +00:00
char * * ipp_version_strv ;
char * endptr ;
2013-03-04 13:29:24 +00:00
* ipp_version_major = 1 ;
* ipp_version_minor = 1 ;
if ( ipp_version_string )
{
ipp_version_strv = g_strsplit ( ipp_version_string , " . " , 0 ) ;
if ( ipp_version_strv )
{
if ( g_strv_length ( ipp_version_strv ) = = 2 )
{
* ipp_version_major = ( guchar ) g_ascii_strtoull ( ipp_version_strv [ 0 ] , & endptr , 10 ) ;
if ( endptr = = ipp_version_strv [ 0 ] )
* ipp_version_major = 1 ;
* ipp_version_minor = ( guchar ) g_ascii_strtoull ( ipp_version_strv [ 1 ] , & endptr , 10 ) ;
if ( endptr = = ipp_version_strv [ 1 ] )
* ipp_version_minor = 1 ;
}
g_strfreev ( ipp_version_strv ) ;
}
}
}
static void
get_server_ipp_version ( guchar * ipp_version_major ,
guchar * ipp_version_minor )
{
* ipp_version_major = 1 ;
* ipp_version_minor = 1 ;
if ( IPP_VERSION & & strlen ( IPP_VERSION ) = = 2 )
{
* ipp_version_major = ( unsigned char ) IPP_VERSION [ 0 ] ;
* ipp_version_minor = ( unsigned char ) IPP_VERSION [ 1 ] ;
}
}
2020-07-24 13:54:49 +00:00
static int
2013-03-04 13:29:24 +00:00
ipp_version_cmp ( guchar ipp_version_major1 ,
guchar ipp_version_minor1 ,
guchar ipp_version_major2 ,
guchar ipp_version_minor2 )
{
if ( ipp_version_major1 = = ipp_version_major2 & &
ipp_version_minor1 = = ipp_version_minor2 )
{
return 0 ;
}
else if ( ipp_version_major1 < ipp_version_major2 | |
( ipp_version_major1 = = ipp_version_major2 & &
ipp_version_minor1 < ipp_version_minor2 ) )
{
return - 1 ;
}
else
{
return 1 ;
}
}
2012-02-19 21:28:42 +00:00
static void
cups_printer_handle_attribute ( GtkPrintBackendCups * cups_backend ,
ipp_attribute_t * attr ,
PrinterSetupInfo * info )
{
2020-07-24 13:54:49 +00:00
int i , j ;
2012-02-19 21:28:42 +00:00
if ( strcmp ( ippGetName ( attr ) , " printer-name " ) = = 0 & &
ippGetValueTag ( attr ) = = IPP_TAG_NAME )
info - > printer_name = ippGetString ( attr , 0 , NULL ) ;
else if ( strcmp ( ippGetName ( attr ) , " printer-uri-supported " ) = = 0 & &
ippGetValueTag ( attr ) = = IPP_TAG_URI )
info - > printer_uri = ippGetString ( attr , 0 , NULL ) ;
else if ( strcmp ( ippGetName ( attr ) , " member-uris " ) = = 0 & &
ippGetValueTag ( attr ) = = IPP_TAG_URI )
info - > member_uris = ippGetString ( attr , 0 , NULL ) ;
else if ( strcmp ( ippGetName ( attr ) , " printer-location " ) = = 0 )
info - > location = ippGetString ( attr , 0 , NULL ) ;
else if ( strcmp ( ippGetName ( attr ) , " printer-info " ) = = 0 )
info - > description = ippGetString ( attr , 0 , NULL ) ;
else if ( strcmp ( ippGetName ( attr ) , " printer-state-message " ) = = 0 )
2012-11-22 18:04:48 +00:00
info - > state_msg = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
2012-02-19 21:28:42 +00:00
else if ( strcmp ( ippGetName ( attr ) , " printer-state-reasons " ) = = 0 )
/* Store most important reason to reason_msg and set
its importance at printer_state_reason_level */
{
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
{
if ( strcmp ( ippGetString ( attr , i , NULL ) , " none " ) ! = 0 )
{
gboolean interested_in = FALSE ;
/* Sets is_paused flag for paused printer. */
if ( strcmp ( ippGetString ( attr , i , NULL ) , " paused " ) = = 0 )
{
info - > is_paused = TRUE ;
}
for ( j = 0 ; j < G_N_ELEMENTS ( printer_messages ) ; j + + )
if ( strncmp ( ippGetString ( attr , i , NULL ) , printer_messages [ j ] ,
strlen ( printer_messages [ j ] ) ) = = 0 )
{
interested_in = TRUE ;
break ;
}
if ( interested_in )
{
if ( g_str_has_suffix ( ippGetString ( attr , i , NULL ) , " -report " ) )
{
if ( info - > reason_level < = GTK_PRINTER_STATE_LEVEL_INFO )
{
info - > reason_msg = ippGetString ( attr , i , NULL ) ;
info - > reason_level = GTK_PRINTER_STATE_LEVEL_INFO ;
}
}
else if ( g_str_has_suffix ( ippGetString ( attr , i , NULL ) , " -warning " ) )
{
if ( info - > reason_level < = GTK_PRINTER_STATE_LEVEL_WARNING )
{
info - > reason_msg = ippGetString ( attr , i , NULL ) ;
info - > reason_level = GTK_PRINTER_STATE_LEVEL_WARNING ;
}
}
else /* It is error in the case of no suffix. */
{
info - > reason_msg = ippGetString ( attr , i , NULL ) ;
info - > reason_level = GTK_PRINTER_STATE_LEVEL_ERROR ;
}
}
}
}
}
else if ( strcmp ( ippGetName ( attr ) , " printer-state " ) = = 0 )
info - > state = ippGetInteger ( attr , 0 ) ;
else if ( strcmp ( ippGetName ( attr ) , " queued-job-count " ) = = 0 )
info - > job_count = ippGetInteger ( attr , 0 ) ;
else if ( strcmp ( ippGetName ( attr ) , " printer-is-accepting-jobs " ) = = 0 )
{
if ( ippGetBoolean ( attr , 0 ) = = 1 )
info - > is_accepting_jobs = TRUE ;
else
info - > is_accepting_jobs = FALSE ;
}
else if ( strcmp ( ippGetName ( attr ) , " job-sheets-supported " ) = = 0 )
{
2015-02-25 14:54:36 +00:00
info - > number_of_covers = ippGetCount ( attr ) ;
info - > covers = g_new ( char * , info - > number_of_covers + 1 ) ;
for ( i = 0 ; i < info - > number_of_covers ; i + + )
info - > covers [ i ] = g_strdup ( ippGetString ( attr , i , NULL ) ) ;
info - > covers [ info - > number_of_covers ] = NULL ;
2012-02-19 21:28:42 +00:00
}
else if ( strcmp ( ippGetName ( attr ) , " job-sheets-default " ) = = 0 )
{
if ( ippGetCount ( attr ) = = 2 )
{
info - > default_cover_before = ippGetString ( attr , 0 , NULL ) ;
info - > default_cover_after = ippGetString ( attr , 1 , NULL ) ;
}
}
else if ( strcmp ( ippGetName ( attr ) , " printer-type " ) = = 0 )
{
info - > got_printer_type = TRUE ;
if ( ippGetInteger ( attr , 0 ) & 0x00020000 )
info - > default_printer = TRUE ;
else
info - > default_printer = FALSE ;
if ( ippGetInteger ( attr , 0 ) & 0x00000002 )
info - > remote_printer = TRUE ;
else
info - > remote_printer = FALSE ;
}
else if ( strcmp ( ippGetName ( attr ) , " auth-info-required " ) = = 0 )
{
if ( strcmp ( ippGetString ( attr , 0 , NULL ) , " none " ) ! = 0 )
{
2020-07-24 18:40:36 +00:00
info - > auth_info_required = g_new0 ( char * , ippGetCount ( attr ) + 1 ) ;
2012-02-19 21:28:42 +00:00
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
info - > auth_info_required [ i ] = g_strdup ( ippGetString ( attr , i , NULL ) ) ;
}
}
2012-08-05 07:56:58 +00:00
else if ( strcmp ( ippGetName ( attr ) , " number-up-default " ) = = 0 )
2012-02-19 21:28:42 +00:00
{
2012-08-05 07:56:58 +00:00
info - > default_number_up = ippGetInteger ( attr , 0 ) ;
2012-02-19 21:28:42 +00:00
}
2013-03-04 13:29:24 +00:00
else if ( g_strcmp0 ( ippGetName ( attr ) , " ipp-versions-supported " ) = = 0 )
{
guchar server_ipp_version_major ;
guchar server_ipp_version_minor ;
guchar ipp_version_major ;
guchar ipp_version_minor ;
get_server_ipp_version ( & server_ipp_version_major ,
& server_ipp_version_minor ) ;
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
{
get_ipp_version ( ippGetString ( attr , i , NULL ) ,
& ipp_version_major ,
& ipp_version_minor ) ;
if ( ipp_version_cmp ( ipp_version_major ,
ipp_version_minor ,
info - > ipp_version_major ,
info - > ipp_version_minor ) > 0 & &
ipp_version_cmp ( ipp_version_major ,
ipp_version_minor ,
server_ipp_version_major ,
server_ipp_version_minor ) < = 0 )
{
info - > ipp_version_major = ipp_version_major ;
info - > ipp_version_minor = ipp_version_minor ;
}
}
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " number-up-supported " ) = = 0 )
{
if ( ippGetCount ( attr ) = = 6 )
{
info - > supports_number_up = TRUE ;
}
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " copies-supported " ) = = 0 )
{
int upper = 1 ;
ippGetRange ( attr , 0 , & upper ) ;
if ( upper > 1 )
{
info - > supports_copies = TRUE ;
}
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " multiple-document-handling-supported " ) = = 0 )
{
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
{
if ( g_strcmp0 ( ippGetString ( attr , i , NULL ) , " separate-documents-collated-copies " ) = = 0 )
{
info - > supports_collate = TRUE ;
}
}
}
2014-10-10 11:36:30 +00:00
else if ( g_strcmp0 ( ippGetName ( attr ) , " sides-default " ) = = 0 )
{
info - > sides_default = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " sides-supported " ) = = 0 )
{
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
info - > sides_supported = g_list_prepend ( info - > sides_supported , g_strdup ( ippGetString ( attr , i , NULL ) ) ) ;
info - > sides_supported = g_list_reverse ( info - > sides_supported ) ;
}
2014-10-02 11:50:47 +00:00
else if ( g_strcmp0 ( ippGetName ( attr ) , " media-default " ) = = 0 )
{
if ( ippGetValueTag ( attr ) = = IPP_TAG_KEYWORD | |
ippGetValueTag ( attr ) = = IPP_TAG_NAME )
info - > media_default = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " media-col-default " ) = = 0 )
{
ipp_attribute_t * iter ;
ipp_t * col ;
2020-07-24 13:54:49 +00:00
int num_of_margins = 0 ;
2014-10-02 11:50:47 +00:00
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
{
col = ippGetCollection ( attr , i ) ;
for ( iter = ippFirstAttribute ( col ) ; iter ! = NULL ; iter = ippNextAttribute ( col ) )
{
2020-05-18 09:38:02 +00:00
switch ( ( guint ) ippGetValueTag ( iter ) )
2014-10-02 11:50:47 +00:00
{
case IPP_TAG_INTEGER :
if ( g_strcmp0 ( ippGetName ( iter ) , " media-bottom-margin " ) = = 0 )
{
info - > media_bottom_margin_default = ippGetInteger ( iter , 0 ) / 100.0 ;
num_of_margins + + ;
}
else if ( g_strcmp0 ( ippGetName ( iter ) , " media-top-margin " ) = = 0 )
{
info - > media_top_margin_default = ippGetInteger ( iter , 0 ) / 100.0 ;
num_of_margins + + ;
}
else if ( g_strcmp0 ( ippGetName ( iter ) , " media-left-margin " ) = = 0 )
{
info - > media_left_margin_default = ippGetInteger ( iter , 0 ) / 100.0 ;
num_of_margins + + ;
}
else if ( g_strcmp0 ( ippGetName ( iter ) , " media-right-margin " ) = = 0 )
{
info - > media_right_margin_default = ippGetInteger ( iter , 0 ) / 100.0 ;
num_of_margins + + ;
}
break ;
default :
break ;
}
}
}
if ( num_of_margins = = 4 )
info - > media_margin_default_set = TRUE ;
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " media-supported " ) = = 0 )
{
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
info - > media_supported = g_list_prepend ( info - > media_supported , g_strdup ( ippGetString ( attr , i , NULL ) ) ) ;
info - > media_supported = g_list_reverse ( info - > media_supported ) ;
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " media-size-supported " ) = = 0 )
{
ipp_attribute_t * iter ;
MediaSize * media_size ;
gboolean number_of_dimensions ;
ipp_t * media_size_collection ;
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
{
media_size_collection = ippGetCollection ( attr , i ) ;
media_size = g_new0 ( MediaSize , 1 ) ;
number_of_dimensions = 0 ;
for ( iter = ippFirstAttribute ( media_size_collection ) ;
iter ! = NULL ;
iter = ippNextAttribute ( media_size_collection ) )
{
if ( g_strcmp0 ( ippGetName ( iter ) , " x-dimension " ) = = 0 & &
ippGetValueTag ( iter ) = = IPP_TAG_INTEGER )
{
media_size - > x_dimension = ippGetInteger ( iter , 0 ) / 100.0 ;
number_of_dimensions + + ;
}
else if ( g_strcmp0 ( ippGetName ( iter ) , " y-dimension " ) = = 0 & &
ippGetValueTag ( iter ) = = IPP_TAG_INTEGER )
{
media_size - > y_dimension = ippGetInteger ( iter , 0 ) / 100.0 ;
number_of_dimensions + + ;
}
}
if ( number_of_dimensions = = 2 )
info - > media_size_supported = g_list_prepend ( info - > media_size_supported , media_size ) ;
else
g_free ( media_size ) ;
}
info - > media_size_supported = g_list_reverse ( info - > media_size_supported ) ;
}
2015-06-23 11:28:21 +00:00
else if ( g_strcmp0 ( ippGetName ( attr ) , " output-bin-default " ) = = 0 )
{
info - > output_bin_default = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
}
else if ( g_strcmp0 ( ippGetName ( attr ) , " output-bin-supported " ) = = 0 )
{
for ( i = 0 ; i < ippGetCount ( attr ) ; i + + )
info - > output_bin_supported = g_list_prepend ( info - > output_bin_supported , g_strdup ( ippGetString ( attr , i , NULL ) ) ) ;
info - > output_bin_supported = g_list_reverse ( info - > output_bin_supported ) ;
}
2017-08-30 15:56:00 +00:00
else if ( g_strcmp0 ( ippGetName ( attr ) , " device-uri " ) = = 0 )
{
info - > original_device_uri = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
}
2021-02-05 17:13:34 +00:00
else if ( strcmp ( ippGetName ( attr ) , " printer-is-temporary " ) = = 0 )
{
if ( ippGetBoolean ( attr , 0 ) = = 1 )
info - > is_temporary = TRUE ;
else
info - > is_temporary = FALSE ;
}
2012-02-19 21:28:42 +00:00
else
{
GTK_NOTE ( PRINTING ,
2018-02-17 03:19:56 +00:00
g_print ( " CUPS Backend: Attribute %s ignored \n " , ippGetName ( attr ) ) ) ;
2012-02-19 21:28:42 +00:00
}
}
2012-02-19 21:29:11 +00:00
static GtkPrinter *
cups_create_printer ( GtkPrintBackendCups * cups_backend ,
PrinterSetupInfo * info )
{
GtkPrinterCups * cups_printer ;
GtkPrinter * printer ;
GtkPrintBackend * backend = GTK_PRINT_BACKEND ( cups_backend ) ;
char uri [ HTTP_MAX_URI ] ; /* Printer URI */
char method [ HTTP_MAX_URI ] ; /* Method/scheme name */
char username [ HTTP_MAX_URI ] ; /* Username:password */
char hostname [ HTTP_MAX_URI ] ; /* Hostname */
char resource [ HTTP_MAX_URI ] ; /* Resource name */
int port ; /* Port number */
char * cups_server ; /* CUPS server */
# ifdef HAVE_COLORD
2013-03-04 13:29:24 +00:00
if ( info - > avahi_printer )
cups_printer = gtk_printer_cups_new ( info - > printer_name ,
backend ,
NULL ) ;
else
cups_printer = gtk_printer_cups_new ( info - > printer_name ,
backend ,
cups_backend - > colord_client ) ;
2012-02-19 21:29:11 +00:00
# else
cups_printer = gtk_printer_cups_new ( info - > printer_name , backend , NULL ) ;
# endif
2021-02-05 17:13:34 +00:00
if ( ! info - > avahi_printer )
2019-12-13 16:52:21 +00:00
{
cups_printer - > device_uri = g_strdup_printf ( " /printers/%s " ,
info - > printer_name ) ;
}
2012-02-19 21:29:11 +00:00
/* Check to see if we are looking at a class */
if ( info - > member_uris )
{
cups_printer - > printer_uri = g_strdup ( info - > member_uris ) ;
2020-06-18 07:47:16 +00:00
/* TODO if member_uris is a class we need to recursively find a printer */
2012-02-19 21:29:11 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Found class with printer %s \n " ,
info - > member_uris ) ) ;
}
else
{
cups_printer - > printer_uri = g_strdup ( info - > printer_uri ) ;
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Found printer %s \n " ,
info - > printer_uri ) ) ;
}
httpSeparateURI ( HTTP_URI_CODING_ALL , cups_printer - > printer_uri ,
method , sizeof ( method ) ,
username , sizeof ( username ) ,
hostname , sizeof ( hostname ) ,
& port ,
resource , sizeof ( resource ) ) ;
if ( strncmp ( resource , " /printers/ " , 10 ) = = 0 )
{
cups_printer - > ppd_name = g_strdup ( resource + 10 ) ;
GTK_NOTE ( PRINTING ,
2012-04-30 11:07:33 +00:00
g_print ( " CUPS Backend: Setting ppd name '%s' for printer/class '%s' \n " , cups_printer - > ppd_name , info - > printer_name ) ) ;
2012-02-19 21:29:11 +00:00
}
gethostname ( uri , sizeof ( uri ) ) ;
cups_server = g_strdup ( cupsServer ( ) ) ;
if ( strcasecmp ( uri , hostname ) = = 0 )
strcpy ( hostname , " localhost " ) ;
/* if the cups server is local and listening at a unix domain socket
* then use the socket connection
*/
if ( ( strstr ( hostname , " localhost " ) ! = NULL ) & &
( cups_server [ 0 ] = = ' / ' ) )
strcpy ( hostname , cups_server ) ;
g_free ( cups_server ) ;
cups_printer - > default_cover_before = g_strdup ( info - > default_cover_before ) ;
cups_printer - > default_cover_after = g_strdup ( info - > default_cover_after ) ;
2017-08-30 15:56:00 +00:00
cups_printer - > original_device_uri = g_strdup ( info - > original_device_uri ) ;
2019-09-19 16:35:23 +00:00
cups_printer - > hostname = g_strdup ( hostname ) ;
cups_printer - > port = port ;
if ( cups_printer - > original_device_uri ! = NULL )
{
httpSeparateURI ( HTTP_URI_CODING_ALL , cups_printer - > original_device_uri ,
method , sizeof ( method ) ,
username , sizeof ( username ) ,
hostname , sizeof ( hostname ) ,
& port ,
resource , sizeof ( resource ) ) ;
cups_printer - > original_hostname = g_strdup ( hostname ) ;
cups_printer - > original_resource = g_strdup ( resource ) ;
cups_printer - > original_port = port ;
}
2012-02-19 21:29:11 +00:00
2013-03-04 13:29:24 +00:00
if ( info - > default_number_up > 0 )
cups_printer - > default_number_up = info - > default_number_up ;
2012-02-19 21:29:11 +00:00
cups_printer - > auth_info_required = g_strdupv ( info - > auth_info_required ) ;
g_strfreev ( info - > auth_info_required ) ;
printer = GTK_PRINTER ( cups_printer ) ;
if ( cups_backend - > default_printer ! = NULL & &
strcmp ( cups_backend - > default_printer , gtk_printer_get_name ( printer ) ) = = 0 )
gtk_printer_set_is_default ( printer , TRUE ) ;
2013-03-04 13:29:24 +00:00
cups_printer - > avahi_browsed = info - > avahi_printer ;
2012-02-19 21:29:11 +00:00
gtk_print_backend_add_printer ( backend , printer ) ;
return printer ;
}
2013-03-04 13:29:24 +00:00
static void
set_printer_icon_name_from_info ( GtkPrinter * printer ,
PrinterSetupInfo * info )
{
/* Set printer icon according to importance
( none , report , warning , error - report is omitted ) . */
if ( info - > reason_level = = GTK_PRINTER_STATE_LEVEL_ERROR )
gtk_printer_set_icon_name ( printer , " printer-error " ) ;
else if ( info - > reason_level = = GTK_PRINTER_STATE_LEVEL_WARNING )
gtk_printer_set_icon_name ( printer , " printer-warning " ) ;
else if ( gtk_printer_is_paused ( printer ) )
gtk_printer_set_icon_name ( printer , " printer-paused " ) ;
else
gtk_printer_set_icon_name ( printer , " printer " ) ;
}
2020-07-24 18:40:36 +00:00
static char *
2016-04-04 14:38:04 +00:00
get_reason_msg_desc ( guint i ,
2020-07-24 18:40:36 +00:00
const char * printer_name )
2016-04-04 14:38:04 +00:00
{
2020-07-24 18:40:36 +00:00
char * reason_msg_desc ;
2016-04-04 14:38:04 +00:00
2016-04-19 11:34:44 +00:00
/* The numbers must match the indices in the printer_messages array */
2016-04-04 14:38:04 +00:00
switch ( i )
{
case 0 :
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is low on toner. " ) ,
printer_name ) ;
break ;
case 1 :
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” has no toner left. " ) ,
printer_name ) ;
break ;
case 2 :
/* Translators: "Developer" like on photo development context */
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is low on developer. " ) ,
printer_name ) ;
break ;
case 3 :
/* Translators: "Developer" like on photo development context */
2016-04-16 17:46:02 +00:00
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is out of developer. " ) ,
2016-04-04 14:38:04 +00:00
printer_name ) ;
break ;
case 4 :
/* Translators: "marker" is one color bin of the printer */
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is low on at least one marker supply. " ) ,
printer_name ) ;
break ;
case 5 :
/* Translators: "marker" is one color bin of the printer */
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is out of at least one marker supply. " ) ,
printer_name ) ;
break ;
case 6 :
reason_msg_desc = g_strdup_printf ( _ ( " The cover is open on printer “%s”. " ) ,
printer_name ) ;
break ;
case 7 :
reason_msg_desc = g_strdup_printf ( _ ( " The door is open on printer “%s”. " ) ,
printer_name ) ;
break ;
case 8 :
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is low on paper. " ) ,
printer_name ) ;
break ;
case 9 :
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is out of paper. " ) ,
printer_name ) ;
break ;
case 10 :
reason_msg_desc = g_strdup_printf ( _ ( " Printer “%s” is currently offline. " ) ,
printer_name ) ;
break ;
case 11 :
reason_msg_desc = g_strdup_printf ( _ ( " There is a problem on printer “%s”. " ) ,
printer_name ) ;
break ;
default :
g_assert_not_reached ( ) ;
}
return reason_msg_desc ;
}
2013-03-04 13:29:24 +00:00
static void
set_info_state_message ( PrinterSetupInfo * info )
{
2020-07-24 13:54:49 +00:00
int i ;
2013-03-04 13:29:24 +00:00
2015-02-27 15:48:40 +00:00
if ( info - > state_msg = = NULL | | strlen ( info - > state_msg ) = = 0 )
2013-03-04 13:29:24 +00:00
{
2020-07-24 18:40:36 +00:00
char * tmp_msg2 = NULL ;
2013-03-04 13:29:24 +00:00
if ( info - > is_paused & & ! info - > is_accepting_jobs )
/* Translators: this is a printer status. */
2013-03-04 11:00:49 +00:00
tmp_msg2 = g_strdup ( _ ( " Paused; Rejecting Jobs " ) ) ;
2013-03-04 13:29:24 +00:00
if ( info - > is_paused & & info - > is_accepting_jobs )
/* Translators: this is a printer status. */
2013-03-04 11:00:49 +00:00
tmp_msg2 = g_strdup ( _ ( " Paused " ) ) ;
2013-03-04 13:29:24 +00:00
if ( ! info - > is_paused & & ! info - > is_accepting_jobs )
/* Translators: this is a printer status. */
2013-03-04 11:00:49 +00:00
tmp_msg2 = g_strdup ( _ ( " Rejecting Jobs " ) ) ;
2013-03-04 13:29:24 +00:00
if ( tmp_msg2 ! = NULL )
{
g_free ( info - > state_msg ) ;
info - > state_msg = tmp_msg2 ;
}
}
/* Set description of the reason and combine it with printer-state-message. */
if ( info - > reason_msg )
{
2020-07-24 18:40:36 +00:00
char * reason_msg_desc = NULL ;
2013-03-04 13:29:24 +00:00
gboolean found = FALSE ;
for ( i = 0 ; i < G_N_ELEMENTS ( printer_messages ) ; i + + )
{
if ( strncmp ( info - > reason_msg , printer_messages [ i ] ,
strlen ( printer_messages [ i ] ) ) = = 0 )
{
2016-04-04 14:38:04 +00:00
reason_msg_desc = get_reason_msg_desc ( i , info - > printer_name ) ;
2013-03-04 13:29:24 +00:00
found = TRUE ;
break ;
}
}
if ( ! found )
info - > reason_level = GTK_PRINTER_STATE_LEVEL_NONE ;
if ( info - > reason_level > = GTK_PRINTER_STATE_LEVEL_WARNING )
{
2013-05-06 11:43:18 +00:00
if ( info - > state_msg = = NULL | | info - > state_msg [ 0 ] = = ' \0 ' )
2013-03-04 13:29:24 +00:00
{
g_free ( info - > state_msg ) ;
info - > state_msg = reason_msg_desc ;
reason_msg_desc = NULL ;
}
else
{
2020-07-24 18:40:36 +00:00
char * tmp_msg = NULL ;
2013-03-04 11:00:49 +00:00
/* Translators: this string connects multiple printer states together. */
tmp_msg = g_strjoin ( _ ( " ; " ) , info - > state_msg ,
2013-03-04 13:29:24 +00:00
reason_msg_desc , NULL ) ;
g_free ( info - > state_msg ) ;
info - > state_msg = tmp_msg ;
}
}
g_free ( reason_msg_desc ) ;
}
}
static void
set_default_printer ( GtkPrintBackendCups * cups_backend ,
2020-07-24 18:40:36 +00:00
const char * default_printer_name )
2013-03-04 13:29:24 +00:00
{
cups_backend - > default_printer = g_strdup ( default_printer_name ) ;
cups_backend - > got_default_printer = TRUE ;
if ( cups_backend - > default_printer ! = NULL )
{
GtkPrinter * default_printer = NULL ;
default_printer = gtk_print_backend_find_printer ( GTK_PRINT_BACKEND ( cups_backend ) ,
cups_backend - > default_printer ) ;
if ( default_printer ! = NULL )
{
gtk_printer_set_is_default ( default_printer , TRUE ) ;
g_signal_emit_by_name ( GTK_PRINT_BACKEND ( cups_backend ) ,
" printer-status-changed " , default_printer ) ;
}
}
}
2019-12-12 15:56:37 +00:00
typedef struct {
GtkPrinterCups * printer ;
http_t * http ;
} RequestPrinterInfoData ;
static void
request_printer_info_data_free ( RequestPrinterInfoData * data )
{
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
httpClose ( data - > http ) ;
g_object_unref ( data - > printer ) ;
g_free ( data ) ;
}
2013-03-04 13:29:24 +00:00
static void
2014-10-02 11:50:47 +00:00
cups_request_printer_info_cb ( GtkPrintBackendCups * cups_backend ,
GtkCupsResult * result ,
gpointer user_data )
2013-03-04 13:29:24 +00:00
{
2019-12-12 15:56:37 +00:00
RequestPrinterInfoData * data = ( RequestPrinterInfoData * ) user_data ;
PrinterSetupInfo * info = g_slice_new0 ( PrinterSetupInfo ) ;
GtkPrintBackend * backend = GTK_PRINT_BACKEND ( cups_backend ) ;
ipp_attribute_t * attr ;
GtkPrinter * printer = g_object_ref ( GTK_PRINTER ( data - > printer ) ) ;
gboolean status_changed = FALSE ;
ipp_t * response ;
2013-03-04 13:29:24 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
if ( gtk_cups_result_is_error ( result ) )
{
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Error getting printer info: %s %d %d " ,
gtk_cups_result_get_error_string ( result ) ,
gtk_cups_result_get_error_type ( result ) ,
gtk_cups_result_get_error_code ( result ) ) ) ;
goto done ;
}
response = gtk_cups_result_get_response ( result ) ;
attr = ippFirstAttribute ( response ) ;
while ( attr & & ippGetGroupTag ( attr ) ! = IPP_TAG_PRINTER )
attr = ippNextAttribute ( response ) ;
if ( attr )
{
while ( attr & & ippGetGroupTag ( attr ) = = IPP_TAG_PRINTER )
{
cups_printer_handle_attribute ( cups_backend , attr , info ) ;
attr = ippNextAttribute ( response ) ;
}
if ( info - > printer_name & & info - > printer_uri )
{
set_info_state_message ( info ) ;
2013-11-21 14:27:33 +00:00
if ( info - > got_printer_type & &
info - > default_printer & &
cups_backend - > avahi_default_printer = = NULL )
cups_backend - > avahi_default_printer = g_strdup ( info - > printer_name ) ;
2013-03-04 13:29:24 +00:00
gtk_printer_set_is_paused ( printer , info - > is_paused ) ;
gtk_printer_set_is_accepting_jobs ( printer , info - > is_accepting_jobs ) ;
GTK_PRINTER_CUPS ( printer ) - > remote = info - > remote_printer ;
GTK_PRINTER_CUPS ( printer ) - > state = info - > state ;
GTK_PRINTER_CUPS ( printer ) - > ipp_version_major = info - > ipp_version_major ;
GTK_PRINTER_CUPS ( printer ) - > ipp_version_minor = info - > ipp_version_minor ;
GTK_PRINTER_CUPS ( printer ) - > supports_copies = info - > supports_copies ;
GTK_PRINTER_CUPS ( printer ) - > supports_collate = info - > supports_collate ;
GTK_PRINTER_CUPS ( printer ) - > supports_number_up = info - > supports_number_up ;
2015-02-25 14:54:36 +00:00
GTK_PRINTER_CUPS ( printer ) - > number_of_covers = info - > number_of_covers ;
GTK_PRINTER_CUPS ( printer ) - > covers = g_strdupv ( info - > covers ) ;
2013-03-04 13:29:24 +00:00
status_changed = gtk_printer_set_job_count ( printer , info - > job_count ) ;
status_changed | = gtk_printer_set_location ( printer , info - > location ) ;
status_changed | = gtk_printer_set_description ( printer , info - > description ) ;
status_changed | = gtk_printer_set_state_message ( printer , info - > state_msg ) ;
status_changed | = gtk_printer_set_is_accepting_jobs ( printer , info - > is_accepting_jobs ) ;
set_printer_icon_name_from_info ( printer , info ) ;
2014-10-02 11:50:47 +00:00
GTK_PRINTER_CUPS ( printer ) - > media_default = info - > media_default ;
GTK_PRINTER_CUPS ( printer ) - > media_supported = info - > media_supported ;
GTK_PRINTER_CUPS ( printer ) - > media_size_supported = info - > media_size_supported ;
if ( info - > media_margin_default_set )
{
GTK_PRINTER_CUPS ( printer ) - > media_margin_default_set = TRUE ;
GTK_PRINTER_CUPS ( printer ) - > media_bottom_margin_default = info - > media_bottom_margin_default ;
GTK_PRINTER_CUPS ( printer ) - > media_top_margin_default = info - > media_top_margin_default ;
GTK_PRINTER_CUPS ( printer ) - > media_left_margin_default = info - > media_left_margin_default ;
GTK_PRINTER_CUPS ( printer ) - > media_right_margin_default = info - > media_right_margin_default ;
}
2014-10-10 11:36:30 +00:00
GTK_PRINTER_CUPS ( printer ) - > sides_default = info - > sides_default ;
GTK_PRINTER_CUPS ( printer ) - > sides_supported = info - > sides_supported ;
2015-06-23 11:28:21 +00:00
GTK_PRINTER_CUPS ( printer ) - > output_bin_default = info - > output_bin_default ;
GTK_PRINTER_CUPS ( printer ) - > output_bin_supported = info - > output_bin_supported ;
2014-10-02 11:50:47 +00:00
2021-02-05 17:13:34 +00:00
GTK_PRINTER_CUPS ( printer ) - > is_temporary = info - > is_temporary ;
2013-11-21 14:27:33 +00:00
gtk_printer_set_has_details ( printer , TRUE ) ;
g_signal_emit_by_name ( printer , " details-acquired " , TRUE ) ;
2013-03-04 13:29:24 +00:00
if ( status_changed )
g_signal_emit_by_name ( GTK_PRINT_BACKEND ( backend ) ,
" printer-status-changed " , printer ) ;
}
}
done :
2019-12-12 15:56:37 +00:00
g_object_unref ( printer ) ;
2013-03-04 13:29:24 +00:00
if ( ! cups_backend - > got_default_printer & &
gtk_print_backend_printer_list_is_done ( backend ) & &
cups_backend - > avahi_default_printer ! = NULL )
{
set_default_printer ( cups_backend , cups_backend - > avahi_default_printer ) ;
}
2015-02-25 14:54:36 +00:00
printer_setup_info_free ( info ) ;
2013-03-04 13:29:24 +00:00
}
static void
2019-12-12 15:56:37 +00:00
cups_request_printer_info ( GtkPrinterCups * printer )
2013-03-04 13:29:24 +00:00
{
2019-12-12 15:56:37 +00:00
RequestPrinterInfoData * data ;
GtkPrintBackendCups * backend = GTK_PRINT_BACKEND_CUPS ( gtk_printer_get_backend ( GTK_PRINTER ( printer ) ) ) ;
GtkCupsRequest * request ;
http_t * http ;
2013-03-04 13:29:24 +00:00
2019-12-12 15:56:37 +00:00
http = httpConnect2 ( printer - > hostname , printer - > port , NULL , AF_UNSPEC , HTTP_ENCRYPTION_IF_REQUESTED , 1 , 30000 , NULL ) ;
2013-03-04 13:29:24 +00:00
if ( http )
{
2019-12-12 15:56:37 +00:00
data = g_new0 ( RequestPrinterInfoData , 1 ) ;
data - > http = http ;
data - > printer = g_object_ref ( printer ) ;
2013-03-04 13:29:24 +00:00
request = gtk_cups_request_new_with_username ( http ,
GTK_CUPS_POST ,
IPP_GET_PRINTER_ATTRIBUTES ,
NULL ,
NULL ,
NULL ,
backend - > username ) ;
gtk_cups_request_set_ipp_version ( request , 1 , 1 ) ;
gtk_cups_request_ipp_add_string ( request , IPP_TAG_OPERATION , IPP_TAG_URI ,
2019-12-12 15:56:37 +00:00
" printer-uri " , NULL , printer - > printer_uri ) ;
2013-03-04 13:29:24 +00:00
gtk_cups_request_ipp_add_strings ( request , IPP_TAG_OPERATION , IPP_TAG_KEYWORD ,
2014-10-02 11:50:47 +00:00
" requested-attributes " , G_N_ELEMENTS ( printer_attrs_detailed ) ,
NULL , printer_attrs_detailed ) ;
2013-03-04 13:29:24 +00:00
cups_request_execute ( backend ,
request ,
2014-10-02 11:50:47 +00:00
( GtkPrintCupsResponseCallbackFunc ) cups_request_printer_info_cb ,
2019-12-12 15:56:37 +00:00
data ,
( GDestroyNotify ) request_printer_info_data_free ) ;
2013-03-04 13:29:24 +00:00
}
}
2013-03-13 13:57:55 +00:00
typedef struct
{
2020-07-24 18:40:36 +00:00
char * printer_uri ;
2021-02-05 17:13:34 +00:00
char * device_uri ;
2020-07-24 18:40:36 +00:00
char * location ;
2021-02-05 17:13:34 +00:00
char * address ;
char * hostname ;
2020-07-24 13:54:49 +00:00
int port ;
2020-07-24 18:40:36 +00:00
char * printer_name ;
char * name ;
char * resource_path ;
2013-11-21 14:27:33 +00:00
gboolean got_printer_type ;
guint printer_type ;
gboolean got_printer_state ;
guint printer_state ;
2020-07-24 18:40:36 +00:00
char * type ;
char * domain ;
char * UUID ;
2013-03-13 13:57:55 +00:00
GtkPrintBackendCups * backend ;
} AvahiConnectionTestData ;
2017-08-30 15:56:00 +00:00
static GtkPrinter *
find_printer_by_uuid ( GtkPrintBackendCups * backend ,
2020-07-24 18:40:36 +00:00
const char * UUID )
2017-08-30 15:56:00 +00:00
{
GtkPrinterCups * printer ;
GtkPrinter * result = NULL ;
GList * printers ;
GList * iter ;
2020-07-24 18:40:36 +00:00
char * printer_uuid ;
2017-08-30 15:56:00 +00:00
printers = gtk_print_backend_get_printer_list ( GTK_PRINT_BACKEND ( backend ) ) ;
for ( iter = printers ; iter ! = NULL ; iter = iter - > next )
{
printer = GTK_PRINTER_CUPS ( iter - > data ) ;
if ( printer - > original_device_uri ! = NULL )
{
printer_uuid = g_strrstr ( printer - > original_device_uri , " uuid= " ) ;
if ( printer_uuid ! = NULL & & strlen ( printer_uuid ) > = 41 )
{
printer_uuid + = 5 ;
printer_uuid = g_strndup ( printer_uuid , 36 ) ;
if ( g_uuid_string_is_valid ( printer_uuid ) )
{
if ( g_strcmp0 ( printer_uuid , UUID ) = = 0 )
{
result = GTK_PRINTER ( printer ) ;
g_free ( printer_uuid ) ;
break ;
}
}
g_free ( printer_uuid ) ;
}
}
}
g_list_free ( printers ) ;
return result ;
}
2021-02-05 17:13:34 +00:00
static void
cups_create_local_printer_cb ( GtkPrintBackendCups * print_backend ,
GtkCupsResult * result ,
gpointer user_data )
{
ipp_attribute_t * attr ;
gchar * printer_name = NULL ;
ipp_t * response ;
GList * iter ;
response = gtk_cups_result_get_response ( result ) ;
if ( ippGetStatusCode ( response ) < = IPP_OK_CONFLICT )
{
if ( ( attr = ippFindAttribute ( response , " printer-uri-supported " , IPP_TAG_URI ) ) ! = NULL )
{
printer_name = g_strdup ( g_strrstr ( ippGetString ( attr , 0 , NULL ) , " / " ) + 1 ) ;
}
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Created local printer %s \n " , printer_name ) ) ;
}
else
{
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Creating of local printer failed: %d \n " , ippGetStatusCode ( response ) ) ) ;
}
iter = g_list_find_custom ( print_backend - > temporary_queues_in_construction , printer_name , ( GCompareFunc ) g_strcmp0 ) ;
if ( iter ! = NULL )
{
g_free ( iter - > data ) ;
print_backend - > temporary_queues_in_construction = g_list_delete_link ( print_backend - > temporary_queues_in_construction , iter ) ;
}
g_free ( printer_name ) ;
}
/*
* Create CUPS temporary queue .
*/
static void
create_temporary_queue ( GtkPrintBackendCups * backend ,
const gchar * printer_name ,
const gchar * printer_uri ,
const gchar * device_uri )
{
GtkCupsRequest * request ;
GList * iter ;
/* There can be several queues with the same name (ipp and ipps versions of the same printer) */
iter = g_list_find_custom ( backend - > temporary_queues_in_construction , printer_name , ( GCompareFunc ) g_strcmp0 ) ;
if ( iter ! = NULL )
return ;
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Creating local printer %s \n " , printer_name ) ) ;
backend - > temporary_queues_in_construction = g_list_prepend ( backend - > temporary_queues_in_construction , g_strdup ( printer_name ) ) ;
request = gtk_cups_request_new_with_username ( NULL ,
GTK_CUPS_POST ,
IPP_OP_CUPS_CREATE_LOCAL_PRINTER ,
NULL ,
NULL ,
NULL ,
NULL ) ;
gtk_cups_request_ipp_add_string ( request , IPP_TAG_OPERATION , IPP_TAG_URI ,
" printer-uri " , NULL , printer_uri ) ;
gtk_cups_request_ipp_add_string ( request , IPP_TAG_PRINTER , IPP_TAG_NAME ,
" printer-name " , NULL , printer_name ) ;
gtk_cups_request_ipp_add_string ( request , IPP_TAG_PRINTER , IPP_TAG_URI ,
" device-uri " , NULL , device_uri ) ;
cups_request_execute ( backend ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_create_local_printer_cb ,
NULL ,
NULL ) ;
}
2013-11-21 14:27:33 +00:00
/*
2020-08-21 12:41:13 +00:00
* Create new GtkPrinter from information included in TXT records .
2013-11-21 14:27:33 +00:00
*/
static void
create_cups_printer_from_avahi_data ( AvahiConnectionTestData * data )
{
PrinterSetupInfo * info = g_slice_new0 ( PrinterSetupInfo ) ;
GtkPrinter * printer ;
2021-02-05 17:13:34 +00:00
printer = gtk_print_backend_find_printer ( GTK_PRINT_BACKEND ( data - > backend ) , data - > printer_name ) ;
if ( printer ! = NULL )
{
/* A printer with this name is already present in this backend. It is probably the same printer
* on another protocol ( IPv4 vs IPv6 ) .
*/
return ;
}
2013-11-21 14:27:33 +00:00
info - > avahi_printer = TRUE ;
info - > printer_name = data - > printer_name ;
info - > printer_uri = data - > printer_uri ;
2019-12-12 15:56:37 +00:00
info - > avahi_resource_path = data - > resource_path ;
2019-01-25 15:41:24 +00:00
info - > default_printer = FALSE ;
info - > remote_printer = TRUE ;
info - > is_accepting_jobs = TRUE ;
2013-11-21 14:27:33 +00:00
if ( data - > got_printer_state )
2015-02-27 15:48:40 +00:00
{
info - > state = data - > printer_state ;
info - > is_paused = info - > state = = IPP_PRINTER_STOPPED ;
}
2013-11-21 14:27:33 +00:00
info - > got_printer_type = data - > got_printer_type ;
if ( data - > got_printer_type )
{
if ( data - > printer_type & CUPS_PRINTER_DEFAULT )
info - > default_printer = TRUE ;
else
info - > default_printer = FALSE ;
if ( data - > printer_type & CUPS_PRINTER_REMOTE )
info - > remote_printer = TRUE ;
else
info - > remote_printer = FALSE ;
if ( data - > printer_type & CUPS_PRINTER_REJECTING )
info - > is_accepting_jobs = FALSE ;
else
info - > is_accepting_jobs = TRUE ;
if ( info - > default_printer & &
data - > backend - > avahi_default_printer = = NULL )
data - > backend - > avahi_default_printer = g_strdup ( info - > printer_name ) ;
}
set_info_state_message ( info ) ;
printer = gtk_print_backend_find_printer ( GTK_PRINT_BACKEND ( data - > backend ) , data - > printer_name ) ;
2017-08-30 15:56:00 +00:00
if ( printer = = NULL & & data - > UUID ! = NULL )
printer = find_printer_by_uuid ( data - > backend , data - > UUID ) ;
2013-11-21 14:27:33 +00:00
if ( printer = = NULL )
{
printer = cups_create_printer ( data - > backend , info ) ;
if ( data - > got_printer_type )
{
gtk_printer_set_is_accepting_jobs ( printer , info - > is_accepting_jobs ) ;
GTK_PRINTER_CUPS ( printer ) - > remote = info - > remote_printer ;
if ( info - > default_printer & &
data - > backend - > avahi_default_printer = = NULL )
data - > backend - > avahi_default_printer = g_strdup ( info - > printer_name ) ;
}
if ( data - > got_printer_state )
GTK_PRINTER_CUPS ( printer ) - > state = info - > state ;
GTK_PRINTER_CUPS ( printer ) - > avahi_name = g_strdup ( data - > name ) ;
GTK_PRINTER_CUPS ( printer ) - > avahi_type = g_strdup ( data - > type ) ;
GTK_PRINTER_CUPS ( printer ) - > avahi_domain = g_strdup ( data - > domain ) ;
2019-12-12 15:56:37 +00:00
GTK_PRINTER_CUPS ( printer ) - > printer_uri = g_strdup ( data - > printer_uri ) ;
2021-02-05 17:13:34 +00:00
GTK_PRINTER_CUPS ( printer ) - > temporary_queue_device_uri = g_strdup ( data - > device_uri ) ;
2013-11-21 14:27:33 +00:00
g_free ( GTK_PRINTER_CUPS ( printer ) - > hostname ) ;
2021-02-05 17:13:34 +00:00
GTK_PRINTER_CUPS ( printer ) - > hostname = g_strdup ( data - > hostname ) ;
2013-11-21 14:27:33 +00:00
GTK_PRINTER_CUPS ( printer ) - > port = data - > port ;
gtk_printer_set_location ( printer , data - > location ) ;
gtk_printer_set_state_message ( printer , info - > state_msg ) ;
set_printer_icon_name_from_info ( printer , info ) ;
if ( ! gtk_printer_is_active ( printer ) )
gtk_printer_set_is_active ( printer , TRUE ) ;
g_signal_emit_by_name ( data - > backend , " printer-added " , printer ) ;
gtk_printer_set_is_new ( printer , FALSE ) ;
g_signal_emit_by_name ( data - > backend , " printer-list-changed " ) ;
if ( ! data - > backend - > got_default_printer & &
gtk_print_backend_printer_list_is_done ( GTK_PRINT_BACKEND ( data - > backend ) ) & &
data - > backend - > avahi_default_printer ! = NULL )
set_default_printer ( data - > backend , data - > backend - > avahi_default_printer ) ;
/* The ref is held by GtkPrintBackend, in add_printer() */
g_object_unref ( printer ) ;
}
2015-02-25 14:54:36 +00:00
printer_setup_info_free ( info ) ;
2013-11-21 14:27:33 +00:00
}
2013-03-13 13:57:55 +00:00
static void
avahi_connection_test_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
{
AvahiConnectionTestData * data = ( AvahiConnectionTestData * ) user_data ;
GSocketConnection * connection ;
2021-02-05 17:13:34 +00:00
GError * error = NULL ;
2013-03-13 13:57:55 +00:00
connection = g_socket_client_connect_to_host_finish ( G_SOCKET_CLIENT ( source_object ) ,
res ,
2021-02-05 17:13:34 +00:00
& error ) ;
2013-03-13 13:57:55 +00:00
g_object_unref ( source_object ) ;
if ( connection ! = NULL )
{
g_io_stream_close ( G_IO_STREAM ( connection ) , NULL , NULL ) ;
g_object_unref ( connection ) ;
2013-11-21 14:27:33 +00:00
create_cups_printer_from_avahi_data ( data ) ;
2013-03-13 13:57:55 +00:00
}
2021-02-05 17:13:34 +00:00
else
{
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Can not connect to %s: %s \n " ,
data - > address ,
error - > message ) ) ;
g_error_free ( error ) ;
}
2013-03-13 13:57:55 +00:00
g_free ( data - > printer_uri ) ;
2013-11-21 14:27:33 +00:00
g_free ( data - > location ) ;
2021-02-05 17:13:34 +00:00
g_free ( data - > address ) ;
g_free ( data - > hostname ) ;
2013-11-21 14:27:33 +00:00
g_free ( data - > printer_name ) ;
2013-03-13 13:57:55 +00:00
g_free ( data - > name ) ;
2019-12-12 15:56:37 +00:00
g_free ( data - > resource_path ) ;
2013-03-13 13:57:55 +00:00
g_free ( data - > type ) ;
g_free ( data - > domain ) ;
2021-02-05 17:13:34 +00:00
g_free ( data - > device_uri ) ;
2013-03-13 13:57:55 +00:00
g_free ( data ) ;
}
2020-05-18 09:38:02 +00:00
static gboolean
2020-07-24 18:40:36 +00:00
avahi_txt_get_key_value_pair ( const char * entry ,
char * * key ,
char * * value )
2013-11-21 14:27:33 +00:00
{
2020-07-24 18:40:36 +00:00
const char * equal_sign ;
2013-11-21 14:27:33 +00:00
* key = NULL ;
* value = NULL ;
if ( entry ! = NULL )
{
/* See RFC 6763 section 6.3 */
equal_sign = strstr ( entry , " = " ) ;
if ( equal_sign ! = NULL )
{
* key = g_strndup ( entry , equal_sign - entry ) ;
* value = g_strdup ( equal_sign + 1 ) ;
return TRUE ;
}
}
return FALSE ;
}
2013-03-04 13:29:24 +00:00
static void
2013-03-12 16:18:16 +00:00
avahi_service_resolver_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
2013-03-04 13:29:24 +00:00
{
2013-03-13 13:57:55 +00:00
AvahiConnectionTestData * data ;
2013-03-25 12:01:23 +00:00
GtkPrintBackendCups * backend ;
2020-07-24 18:40:36 +00:00
const char * name ;
2021-02-05 17:13:34 +00:00
const char * hostname ;
2020-07-24 18:40:36 +00:00
const char * type ;
const char * domain ;
const char * address ;
2013-03-12 16:18:16 +00:00
GVariant * output ;
GVariant * txt ;
GVariant * child ;
guint32 flags ;
guint16 port ;
GError * error = NULL ;
2021-02-05 17:13:34 +00:00
GList * iter ;
2020-07-24 18:40:36 +00:00
char * tmp ;
char * printer_name ;
char * * printer_name_strv ;
char * * printer_name_compressed_strv ;
char * endptr ;
char * key ;
char * value ;
2013-11-22 10:31:25 +00:00
gsize length ;
2020-07-24 13:54:49 +00:00
int interface ;
int protocol ;
int aprotocol ;
int i , j ;
2013-03-12 16:18:16 +00:00
output = g_dbus_connection_call_finish ( G_DBUS_CONNECTION ( source_object ) ,
res ,
& error ) ;
if ( output )
{
2013-03-25 12:01:23 +00:00
backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
2013-03-12 16:18:16 +00:00
g_variant_get ( output , " (ii&s&s&s&si&sq@aayu) " ,
& interface ,
& protocol ,
& name ,
& type ,
& domain ,
2021-02-05 17:13:34 +00:00
& hostname ,
2013-03-12 16:18:16 +00:00
& aprotocol ,
& address ,
& port ,
& txt ,
& flags ) ;
2013-11-21 14:27:33 +00:00
data = g_new0 ( AvahiConnectionTestData , 1 ) ;
2013-03-12 16:18:16 +00:00
for ( i = 0 ; i < g_variant_n_children ( txt ) ; i + + )
{
child = g_variant_get_child_value ( txt , i ) ;
2013-03-04 13:29:24 +00:00
2013-11-22 10:31:25 +00:00
length = g_variant_get_size ( child ) ;
if ( length > 0 )
2013-03-12 16:18:16 +00:00
{
2013-11-22 10:31:25 +00:00
tmp = g_strndup ( g_variant_get_data ( child ) , length ) ;
g_variant_unref ( child ) ;
2013-03-04 13:29:24 +00:00
2013-11-22 10:31:25 +00:00
if ( ! avahi_txt_get_key_value_pair ( tmp , & key , & value ) )
{
g_free ( tmp ) ;
continue ;
}
2013-03-12 15:26:37 +00:00
2013-11-22 10:31:25 +00:00
if ( g_strcmp0 ( key , " rp " ) = = 0 )
{
2019-12-12 15:56:37 +00:00
data - > resource_path = g_strdup ( value ) ;
2013-11-22 10:31:25 +00:00
}
else if ( g_strcmp0 ( key , " note " ) = = 0 )
{
data - > location = g_strdup ( value ) ;
}
else if ( g_strcmp0 ( key , " printer-type " ) = = 0 )
{
endptr = NULL ;
data - > printer_type = g_ascii_strtoull ( value , & endptr , 16 ) ;
if ( data - > printer_type ! = 0 | | endptr ! = value )
data - > got_printer_type = TRUE ;
}
else if ( g_strcmp0 ( key , " printer-state " ) = = 0 )
{
endptr = NULL ;
data - > printer_state = g_ascii_strtoull ( value , & endptr , 10 ) ;
if ( data - > printer_state ! = 0 | | endptr ! = value )
data - > got_printer_state = TRUE ;
}
2017-08-30 15:56:00 +00:00
else if ( g_strcmp0 ( key , " UUID " ) = = 0 )
{
if ( * value ! = ' \0 ' )
data - > UUID = g_strdup ( value ) ;
}
2013-11-22 10:31:25 +00:00
g_clear_pointer ( & key , g_free ) ;
g_clear_pointer ( & value , g_free ) ;
g_free ( tmp ) ;
2013-11-21 14:27:33 +00:00
}
2013-11-22 10:31:25 +00:00
else
2013-11-21 14:27:33 +00:00
{
2013-11-22 10:31:25 +00:00
g_variant_unref ( child ) ;
2013-11-21 14:27:33 +00:00
}
2013-03-12 16:18:16 +00:00
}
2013-03-13 13:57:55 +00:00
2019-12-12 15:56:37 +00:00
if ( data - > resource_path ! = NULL )
2013-03-12 16:18:16 +00:00
{
2021-02-05 17:13:34 +00:00
/*
* Create name of temporary queue from the name of the discovered service .
* This emulates the way how CUPS creates the name .
*/
printer_name = g_strdup_printf ( " %s " , name ) ;
g_strcanon ( printer_name , " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " , ' _ ' ) ;
printer_name_strv = g_strsplit_set ( printer_name , " _ " , - 1 ) ;
printer_name_compressed_strv = g_new0 ( gchar * , g_strv_length ( printer_name_strv ) + 1 ) ;
for ( i = 0 , j = 0 ; printer_name_strv [ i ] ! = NULL ; i + + )
2019-12-12 15:56:37 +00:00
{
2021-02-05 17:13:34 +00:00
if ( printer_name_strv [ i ] [ 0 ] ! = ' \0 ' )
2019-12-12 15:56:37 +00:00
{
2021-02-05 17:13:34 +00:00
printer_name_compressed_strv [ j ] = printer_name_strv [ i ] ;
j + + ;
2019-12-12 15:56:37 +00:00
}
2021-02-05 17:13:34 +00:00
}
data - > printer_name = g_strjoinv ( " _ " , printer_name_compressed_strv ) ;
2019-12-12 15:56:37 +00:00
2021-02-05 17:13:34 +00:00
g_strfreev ( printer_name_strv ) ;
g_free ( printer_name_compressed_strv ) ;
g_free ( printer_name ) ;
iter = g_list_find_custom ( backend - > temporary_queues_removed , data - > printer_name , ( GCompareFunc ) g_strcmp0 ) ;
if ( iter ! = NULL )
{
g_free ( iter - > data ) ;
backend - > temporary_queues_removed = g_list_delete_link ( backend - > temporary_queues_removed , iter ) ;
2019-12-12 15:56:37 +00:00
}
2013-03-12 16:18:16 +00:00
if ( g_strcmp0 ( type , " _ipp._tcp " ) = = 0 )
2021-02-05 17:13:34 +00:00
{
data - > printer_uri = g_strdup_printf ( " ipp://localhost/printers/%s " , data - > printer_name ) ;
data - > device_uri = g_strdup_printf ( " ipp://%s:%d/%s " , hostname , port , data - > resource_path ) ;
}
2013-03-12 16:18:16 +00:00
else
2021-02-05 17:13:34 +00:00
{
data - > printer_uri = g_strdup_printf ( " ipps://localhost/printers/%s " , data - > printer_name ) ;
data - > device_uri = g_strdup_printf ( " ipps://%s:%d/%s " , hostname , port , data - > resource_path ) ;
}
2013-03-12 16:18:16 +00:00
2021-02-05 17:13:34 +00:00
data - > address = g_strdup ( address ) ;
data - > hostname = g_strdup ( hostname ) ;
2013-03-12 16:18:16 +00:00
data - > port = port ;
2013-11-21 14:27:33 +00:00
2013-03-12 16:18:16 +00:00
data - > name = g_strdup ( name ) ;
data - > type = g_strdup ( type ) ;
data - > domain = g_strdup ( domain ) ;
data - > backend = backend ;
/* It can happen that the address is not reachable */
g_socket_client_connect_to_host_async ( g_socket_client_new ( ) ,
address ,
port ,
backend - > avahi_cancellable ,
avahi_connection_test_cb ,
data ) ;
2013-11-21 14:27:33 +00:00
}
else
{
g_free ( data - > printer_name ) ;
g_free ( data - > location ) ;
g_free ( data ) ;
2013-03-12 16:18:16 +00:00
}
2013-03-04 13:29:24 +00:00
2013-11-22 10:31:25 +00:00
g_variant_unref ( txt ) ;
2013-03-12 16:18:16 +00:00
g_variant_unref ( output ) ;
}
else
{
2013-03-25 12:01:23 +00:00
if ( ! g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_CANCELLED ) )
g_warning ( " %s " , error - > message ) ;
2013-03-12 16:18:16 +00:00
g_error_free ( error ) ;
2013-03-04 13:29:24 +00:00
}
}
static void
2013-03-12 16:18:16 +00:00
avahi_service_browser_signal_handler ( GDBusConnection * connection ,
2020-07-24 18:40:36 +00:00
const char * sender_name ,
const char * object_path ,
const char * interface_name ,
const char * signal_name ,
2013-03-12 16:18:16 +00:00
GVariant * parameters ,
gpointer user_data )
2013-03-04 13:29:24 +00:00
{
GtkPrintBackendCups * backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
2020-07-24 18:40:36 +00:00
char * name ;
char * type ;
char * domain ;
2013-03-12 16:18:16 +00:00
guint flags ;
2020-07-24 13:54:49 +00:00
int interface ;
int protocol ;
2013-03-12 16:18:16 +00:00
if ( g_strcmp0 ( signal_name , " ItemNew " ) = = 0 )
{
g_variant_get ( parameters , " (ii&s&s&su) " ,
& interface ,
& protocol ,
& name ,
& type ,
& domain ,
& flags ) ;
if ( g_strcmp0 ( type , " _ipp._tcp " ) = = 0 | |
g_strcmp0 ( type , " _ipps._tcp " ) = = 0 )
{
g_dbus_connection_call ( backend - > dbus_connection ,
AVAHI_BUS ,
" / " ,
AVAHI_SERVER_IFACE ,
" ResolveService " ,
g_variant_new ( " (iisssiu) " ,
interface ,
protocol ,
name ,
type ,
domain ,
AVAHI_PROTO_UNSPEC ,
0 ) ,
G_VARIANT_TYPE ( " (iissssisqaayu) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
backend - > avahi_cancellable ,
avahi_service_resolver_cb ,
user_data ) ;
}
}
else if ( g_strcmp0 ( signal_name , " ItemRemove " ) = = 0 )
{
g_variant_get ( parameters , " (ii&s&s&su) " ,
& interface ,
& protocol ,
& name ,
& type ,
& domain ,
& flags ) ;
2013-03-04 13:29:24 +00:00
2013-03-12 16:18:16 +00:00
if ( g_strcmp0 ( type , " _ipp._tcp " ) = = 0 | |
g_strcmp0 ( type , " _ipps._tcp " ) = = 0 )
{
2013-04-10 01:18:05 +00:00
GtkPrinterCups * printer ;
GList * list ;
GList * iter ;
2013-03-12 16:18:16 +00:00
list = gtk_print_backend_get_printer_list ( GTK_PRINT_BACKEND ( backend ) ) ;
for ( iter = list ; iter ; iter = iter - > next )
{
printer = GTK_PRINTER_CUPS ( iter - > data ) ;
if ( g_strcmp0 ( printer - > avahi_name , name ) = = 0 & &
g_strcmp0 ( printer - > avahi_type , type ) = = 0 & &
g_strcmp0 ( printer - > avahi_domain , domain ) = = 0 )
{
if ( g_strcmp0 ( gtk_printer_get_name ( GTK_PRINTER ( printer ) ) ,
backend - > avahi_default_printer ) = = 0 )
g_clear_pointer ( & backend - > avahi_default_printer , g_free ) ;
2021-02-05 17:13:34 +00:00
backend - > temporary_queues_removed = g_list_prepend ( backend - > temporary_queues_removed ,
g_strdup ( gtk_printer_get_name ( GTK_PRINTER ( printer ) ) ) ) ;
2013-03-12 16:18:16 +00:00
g_signal_emit_by_name ( backend , " printer-removed " , printer ) ;
gtk_print_backend_remove_printer ( GTK_PRINT_BACKEND ( backend ) ,
GTK_PRINTER ( printer ) ) ;
g_signal_emit_by_name ( backend , " printer-list-changed " ) ;
break ;
}
}
2013-03-04 13:29:24 +00:00
2013-04-10 01:18:05 +00:00
g_list_free ( list ) ;
}
2013-03-04 13:29:24 +00:00
}
}
2021-02-05 17:13:56 +00:00
static gboolean
unsubscribe_general_subscription_cb ( gpointer user_data )
{
GtkPrintBackendCups * cups_backend = user_data ;
g_dbus_connection_signal_unsubscribe ( cups_backend - > dbus_connection ,
cups_backend - > avahi_service_browser_subscription_id ) ;
cups_backend - > avahi_service_browser_subscription_id = 0 ;
cups_backend - > unsubscribe_general_subscription_id = 0 ;
return G_SOURCE_REMOVE ;
}
2013-03-04 13:29:24 +00:00
static void
2013-03-12 16:18:16 +00:00
avahi_service_browser_new_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
2013-03-04 13:29:24 +00:00
{
2013-03-25 12:01:23 +00:00
GtkPrintBackendCups * cups_backend ;
2013-03-12 16:18:16 +00:00
GVariant * output ;
GError * error = NULL ;
2020-07-24 13:54:49 +00:00
int i ;
2013-03-04 13:29:24 +00:00
2013-03-12 16:18:16 +00:00
output = g_dbus_connection_call_finish ( G_DBUS_CONNECTION ( source_object ) ,
res ,
& error ) ;
if ( output )
2013-03-04 13:29:24 +00:00
{
2013-03-25 12:01:23 +00:00
cups_backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
2013-03-12 16:18:16 +00:00
i = cups_backend - > avahi_service_browser_paths [ 0 ] ? 1 : 0 ;
2013-03-04 13:29:24 +00:00
2013-03-12 16:18:16 +00:00
g_variant_get ( output , " (o) " , & cups_backend - > avahi_service_browser_paths [ i ] ) ;
2013-03-04 13:29:24 +00:00
2013-03-12 16:18:16 +00:00
cups_backend - > avahi_service_browser_subscription_ids [ i ] =
g_dbus_connection_signal_subscribe ( cups_backend - > dbus_connection ,
NULL ,
AVAHI_SERVICE_BROWSER_IFACE ,
NULL ,
cups_backend - > avahi_service_browser_paths [ i ] ,
NULL ,
G_DBUS_SIGNAL_FLAGS_NONE ,
avahi_service_browser_signal_handler ,
user_data ,
NULL ) ;
/*
* The general subscription for all service browsers is not needed
* now because we are already subscribed to service browsers
* specific to _ipp . _tcp and _ipps . _tcp services .
*/
if ( cups_backend - > avahi_service_browser_paths [ 0 ] & &
cups_backend - > avahi_service_browser_paths [ 1 ] & &
cups_backend - > avahi_service_browser_subscription_id > 0 )
{
2021-02-05 17:13:56 +00:00
/* We need to unsubscribe in idle since signals in queue destined for emit
* are emitted in idle and check whether the subscriber is still subscribed .
*/
cups_backend - > unsubscribe_general_subscription_id = g_idle_add ( unsubscribe_general_subscription_cb , cups_backend ) ;
2013-03-12 16:18:16 +00:00
}
2013-03-04 13:29:24 +00:00
2013-03-12 16:18:16 +00:00
g_variant_unref ( output ) ;
2013-03-04 13:29:24 +00:00
}
else
{
2013-03-12 16:18:16 +00:00
/*
* The creation of ServiceBrowser fails with G_IO_ERROR_DBUS_ERROR
* if Avahi is disabled .
*/
2013-03-25 12:01:23 +00:00
if ( ! g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_DBUS_ERROR ) & &
! g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_CANCELLED ) )
2013-03-12 16:18:16 +00:00
g_warning ( " %s " , error - > message ) ;
g_error_free ( error ) ;
2013-03-04 13:29:24 +00:00
}
}
static void
2013-03-12 16:18:16 +00:00
avahi_create_browsers ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
2013-03-04 13:29:24 +00:00
{
2013-03-25 12:01:23 +00:00
GDBusConnection * dbus_connection ;
GtkPrintBackendCups * cups_backend ;
2013-03-04 13:29:24 +00:00
GError * error = NULL ;
2013-03-25 12:01:23 +00:00
dbus_connection = g_bus_get_finish ( res , & error ) ;
if ( ! dbus_connection )
2013-03-04 13:29:24 +00:00
{
2013-03-25 12:01:23 +00:00
if ( ! g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_CANCELLED ) )
2020-08-02 02:42:25 +00:00
g_message ( " Couldn't connect to D-Bus system bus, avahi printers will not be available: %s " , error - > message ) ;
2013-03-25 12:01:23 +00:00
2013-03-12 16:18:16 +00:00
g_error_free ( error ) ;
return ;
2013-03-04 13:29:24 +00:00
}
2013-03-12 16:18:16 +00:00
2013-03-25 12:01:23 +00:00
cups_backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
cups_backend - > dbus_connection = dbus_connection ;
2013-03-12 16:18:16 +00:00
/*
* We need to subscribe to signals of service browser before
* we actually create it because it starts to emit them right
* after its creation .
*/
cups_backend - > avahi_service_browser_subscription_id =
g_dbus_connection_signal_subscribe ( cups_backend - > dbus_connection ,
NULL ,
AVAHI_SERVICE_BROWSER_IFACE ,
NULL ,
NULL ,
NULL ,
G_DBUS_SIGNAL_FLAGS_NONE ,
avahi_service_browser_signal_handler ,
cups_backend ,
NULL ) ;
/*
* Create service browsers for _ipp . _tcp and _ipps . _tcp services .
*/
g_dbus_connection_call ( cups_backend - > dbus_connection ,
AVAHI_BUS ,
" / " ,
AVAHI_SERVER_IFACE ,
" ServiceBrowserNew " ,
g_variant_new ( " (iissu) " ,
AVAHI_IF_UNSPEC ,
AVAHI_PROTO_UNSPEC ,
" _ipp._tcp " ,
" " ,
0 ) ,
G_VARIANT_TYPE ( " (o) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
cups_backend - > avahi_cancellable ,
avahi_service_browser_new_cb ,
cups_backend ) ;
g_dbus_connection_call ( cups_backend - > dbus_connection ,
AVAHI_BUS ,
" / " ,
AVAHI_SERVER_IFACE ,
" ServiceBrowserNew " ,
g_variant_new ( " (iissu) " ,
AVAHI_IF_UNSPEC ,
AVAHI_PROTO_UNSPEC ,
" _ipps._tcp " ,
" " ,
0 ) ,
G_VARIANT_TYPE ( " (o) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
cups_backend - > avahi_cancellable ,
avahi_service_browser_new_cb ,
cups_backend ) ;
2013-03-04 13:29:24 +00:00
}
static void
avahi_request_printer_list ( GtkPrintBackendCups * cups_backend )
{
2013-03-12 16:18:16 +00:00
cups_backend - > avahi_cancellable = g_cancellable_new ( ) ;
2013-03-25 12:01:23 +00:00
g_bus_get ( G_BUS_TYPE_SYSTEM , cups_backend - > avahi_cancellable , avahi_create_browsers , cups_backend ) ;
2013-03-04 13:29:24 +00:00
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
static void
cups_request_printer_list_cb ( GtkPrintBackendCups * cups_backend ,
2006-06-16 18:29:09 +00:00
GtkCupsResult * result ,
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
2006-06-21 05:08:43 +00:00
GtkPrintBackend * backend = GTK_PRINT_BACKEND ( cups_backend ) ;
2006-04-21 15:09:32 +00:00
ipp_attribute_t * attr ;
ipp_t * response ;
gboolean list_has_changed ;
GList * removed_printer_checklist ;
2020-07-24 18:40:36 +00:00
char * remote_default_printer = NULL ;
2013-03-04 13:29:24 +00:00
GList * iter ;
2006-04-21 15:09:32 +00:00
list_has_changed = FALSE ;
2006-07-06 17:55:32 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2006-04-21 15:09:32 +00:00
cups_backend - > list_printers_pending = FALSE ;
if ( gtk_cups_result_is_error ( result ) )
{
2012-02-19 21:29:11 +00:00
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Error getting printer list: %s %d %d " ,
2009-04-21 12:24:32 +00:00
gtk_cups_result_get_error_string ( result ) ,
gtk_cups_result_get_error_type ( result ) ,
gtk_cups_result_get_error_code ( result ) ) ) ;
if ( gtk_cups_result_get_error_type ( result ) = = GTK_CUPS_ERROR_AUTH & &
gtk_cups_result_get_error_code ( result ) = = 1 )
{
/* Canceled by user, stop popping up more password dialogs */
if ( cups_backend - > list_printers_poll > 0 )
g_source_remove ( cups_backend - > list_printers_poll ) ;
cups_backend - > list_printers_poll = 0 ;
2009-09-30 16:40:11 +00:00
cups_backend - > list_printers_attempts = 0 ;
2009-04-21 12:24:32 +00:00
}
2006-08-31 17:44:07 +00:00
goto done ;
2006-04-21 15:09:32 +00:00
}
2012-02-19 21:29:11 +00:00
2006-06-21 05:08:43 +00:00
/* Gather the names of the printers in the current queue
2012-02-19 21:29:11 +00:00
* so we may check to see if they were removed
2006-06-21 05:08:43 +00:00
*/
removed_printer_checklist = gtk_print_backend_get_printer_list ( backend ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
response = gtk_cups_result_get_response ( result ) ;
2012-02-19 21:48:19 +00:00
for ( attr = ippFirstAttribute ( response ) ; attr ! = NULL ;
attr = ippNextAttribute ( response ) )
{
GtkPrinter * printer ;
gboolean status_changed = FALSE ;
GList * node ;
PrinterSetupInfo * info = g_slice_new0 ( PrinterSetupInfo ) ;
/* Skip leading attributes until we hit a printer...
*/
while ( attr ! = NULL & & ippGetGroupTag ( attr ) ! = IPP_TAG_PRINTER )
attr = ippNextAttribute ( response ) ;
2006-04-21 15:09:32 +00:00
2012-02-19 21:48:19 +00:00
if ( attr = = NULL )
break ;
2012-04-17 15:12:56 +00:00
2012-02-18 22:16:27 +00:00
while ( attr ! = NULL & & ippGetGroupTag ( attr ) = = IPP_TAG_PRINTER )
2019-05-06 19:04:17 +00:00
{
cups_printer_handle_attribute ( cups_backend , attr , info ) ;
attr = ippNextAttribute ( response ) ;
}
2006-04-21 15:09:32 +00:00
2012-02-19 21:19:11 +00:00
if ( info - > printer_name = = NULL | |
( info - > printer_uri = = NULL & & info - > member_uris = = NULL ) )
2019-05-06 19:04:17 +00:00
{
if ( attr = = NULL )
break ;
else
continue ;
}
2008-09-17 22:07:10 +00:00
2021-02-05 17:13:34 +00:00
/* Do not show printer for queue which was removed from Avahi. */
iter = g_list_find_custom ( GTK_PRINT_BACKEND_CUPS ( backend ) - > temporary_queues_removed ,
info - > printer_name , ( GCompareFunc ) g_strcmp0 ) ;
if ( iter ! = NULL )
continue ;
2012-02-19 21:19:11 +00:00
if ( info - > got_printer_type )
2008-09-17 22:07:10 +00:00
{
2012-02-19 21:19:11 +00:00
if ( info - > default_printer & & ! cups_backend - > got_default_printer )
2008-09-17 22:07:10 +00:00
{
2012-02-19 21:19:11 +00:00
if ( ! info - > remote_printer )
2009-08-18 11:22:23 +00:00
{
cups_backend - > got_default_printer = TRUE ;
2012-02-19 21:19:11 +00:00
cups_backend - > default_printer = g_strdup ( info - > printer_name ) ;
2009-08-18 11:22:23 +00:00
}
else
{
if ( remote_default_printer = = NULL )
2012-02-19 21:19:11 +00:00
remote_default_printer = g_strdup ( info - > printer_name ) ;
2009-08-18 11:22:23 +00:00
}
2008-09-17 22:07:10 +00:00
}
}
else
{
if ( ! cups_backend - > got_default_printer )
cups_get_default_printer ( cups_backend ) ;
}
2006-04-21 15:09:32 +00:00
/* remove name from checklist if it was found */
2013-03-02 00:13:30 +00:00
node = g_list_find_custom ( removed_printer_checklist ,
info - > printer_name ,
( GCompareFunc ) find_printer ) ;
removed_printer_checklist = g_list_delete_link ( removed_printer_checklist ,
node ) ;
2012-02-19 21:29:11 +00:00
2012-02-19 21:19:11 +00:00
printer = gtk_print_backend_find_printer ( backend , info - > printer_name ) ;
2006-05-04 13:43:32 +00:00
if ( ! printer )
2012-02-19 21:29:11 +00:00
{
printer = cups_create_printer ( cups_backend , info ) ;
list_has_changed = TRUE ;
}
2021-02-05 17:13:34 +00:00
else if ( GTK_PRINTER_CUPS ( printer ) - > avahi_browsed & & info - > is_temporary )
{
/*
* A temporary queue was created for a printer found via Avahi .
* We modify the placeholder GtkPrinter to point to the temporary queue
* instead of removing the placeholder GtkPrinter and creating new GtkPrinter .
*/
g_object_ref ( printer ) ;
GTK_PRINTER_CUPS ( printer ) - > avahi_browsed = FALSE ;
GTK_PRINTER_CUPS ( printer ) - > is_temporary = TRUE ;
g_free ( GTK_PRINTER_CUPS ( printer ) - > device_uri ) ;
GTK_PRINTER_CUPS ( printer ) - > device_uri = g_strdup_printf ( " /printers/%s " ,
info - > printer_name ) ;
gtk_printer_set_has_details ( printer , FALSE ) ;
cups_printer_request_details ( printer ) ;
}
2006-05-04 13:43:32 +00:00
else
g_object_ref ( printer ) ;
2012-02-19 21:19:11 +00:00
GTK_PRINTER_CUPS ( printer ) - > remote = info - > remote_printer ;
2009-09-23 12:35:26 +00:00
2012-02-19 21:19:11 +00:00
gtk_printer_set_is_paused ( printer , info - > is_paused ) ;
gtk_printer_set_is_accepting_jobs ( printer , info - > is_accepting_jobs ) ;
2008-07-15 17:34:34 +00:00
2006-04-21 15:09:32 +00:00
if ( ! gtk_printer_is_active ( printer ) )
{
gtk_printer_set_is_active ( printer , TRUE ) ;
gtk_printer_set_is_new ( printer , TRUE ) ;
list_has_changed = TRUE ;
}
if ( gtk_printer_is_new ( printer ) )
{
2006-06-21 05:08:43 +00:00
g_signal_emit_by_name ( backend , " printer-added " , printer ) ;
2006-04-21 15:09:32 +00:00
gtk_printer_set_is_new ( printer , FALSE ) ;
}
2012-02-19 21:19:11 +00:00
GTK_PRINTER_CUPS ( printer ) - > state = info - > state ;
2013-03-04 13:29:24 +00:00
GTK_PRINTER_CUPS ( printer ) - > ipp_version_major = info - > ipp_version_major ;
GTK_PRINTER_CUPS ( printer ) - > ipp_version_minor = info - > ipp_version_minor ;
GTK_PRINTER_CUPS ( printer ) - > supports_copies = info - > supports_copies ;
GTK_PRINTER_CUPS ( printer ) - > supports_collate = info - > supports_collate ;
GTK_PRINTER_CUPS ( printer ) - > supports_number_up = info - > supports_number_up ;
2015-02-25 14:54:36 +00:00
GTK_PRINTER_CUPS ( printer ) - > number_of_covers = info - > number_of_covers ;
2020-07-09 04:31:06 +00:00
g_clear_pointer ( & ( GTK_PRINTER_CUPS ( printer ) - > covers ) , g_strfreev ) ;
2015-02-25 14:54:36 +00:00
GTK_PRINTER_CUPS ( printer ) - > covers = g_strdupv ( info - > covers ) ;
2021-02-05 17:13:34 +00:00
GTK_PRINTER_CUPS ( printer ) - > is_temporary = info - > is_temporary ;
2012-02-19 21:19:11 +00:00
status_changed = gtk_printer_set_job_count ( printer , info - > job_count ) ;
status_changed | = gtk_printer_set_location ( printer , info - > location ) ;
status_changed | = gtk_printer_set_description ( printer ,
info - > description ) ;
2008-05-05 23:38:31 +00:00
2013-03-04 13:29:24 +00:00
set_info_state_message ( info ) ;
2008-05-05 23:38:31 +00:00
2012-02-19 21:19:11 +00:00
status_changed | = gtk_printer_set_state_message ( printer , info - > state_msg ) ;
status_changed | = gtk_printer_set_is_accepting_jobs ( printer , info - > is_accepting_jobs ) ;
2007-04-30 17:39:40 +00:00
2013-03-04 13:29:24 +00:00
set_printer_icon_name_from_info ( printer , info ) ;
2008-05-05 23:38:31 +00:00
2007-04-30 17:39:40 +00:00
if ( status_changed )
g_signal_emit_by_name ( GTK_PRINT_BACKEND ( backend ) ,
" printer-status-changed " , printer ) ;
2006-04-21 15:09:32 +00:00
2006-05-04 13:43:32 +00:00
/* The ref is held by GtkPrintBackend, in add_printer() */
g_object_unref ( printer ) ;
2015-02-25 14:54:36 +00:00
printer_setup_info_free ( info ) ;
2012-02-19 21:19:11 +00:00
2006-05-04 13:43:32 +00:00
if ( attr = = NULL )
break ;
}
2006-04-21 15:09:32 +00:00
2006-05-04 13:43:32 +00:00
/* look at the removed printers checklist and mark any printer
as inactive if it is in the list , emitting a printer_removed signal */
if ( removed_printer_checklist ! = NULL )
{
2013-03-04 13:29:24 +00:00
for ( iter = removed_printer_checklist ; iter ; iter = iter - > next )
{
if ( ! GTK_PRINTER_CUPS ( iter - > data ) - > avahi_browsed )
{
mark_printer_inactive ( GTK_PRINTER ( iter - > data ) , backend ) ;
list_has_changed = TRUE ;
}
}
2012-12-04 14:48:08 +00:00
g_list_free ( removed_printer_checklist ) ;
2006-05-04 13:43:32 +00:00
}
2012-02-19 21:29:11 +00:00
2006-08-31 17:44:07 +00:00
done :
2006-05-04 13:43:32 +00:00
if ( list_has_changed )
2006-06-21 05:08:43 +00:00
g_signal_emit_by_name ( backend , " printer-list-changed " ) ;
2012-02-19 21:29:11 +00:00
2006-06-21 05:08:43 +00:00
gtk_print_backend_set_list_done ( backend ) ;
2007-06-12 02:12:32 +00:00
2009-08-18 11:22:23 +00:00
if ( ! cups_backend - > got_default_printer & & remote_default_printer ! = NULL )
{
2013-03-04 13:29:24 +00:00
set_default_printer ( cups_backend , remote_default_printer ) ;
2009-08-18 11:22:23 +00:00
g_free ( remote_default_printer ) ;
2013-03-04 13:29:24 +00:00
}
2009-08-18 11:22:23 +00:00
2013-03-04 13:29:24 +00:00
if ( ! cups_backend - > got_default_printer & & cups_backend - > avahi_default_printer ! = NULL )
2019-05-06 19:04:17 +00:00
set_default_printer ( cups_backend , cups_backend - > avahi_default_printer ) ;
2006-04-21 15:09:32 +00:00
}
2008-09-17 22:07:10 +00:00
static void
update_backend_status ( GtkPrintBackendCups * cups_backend ,
GtkCupsConnectionState state )
{
switch ( state )
{
case GTK_CUPS_CONNECTION_NOT_AVAILABLE :
g_object_set ( cups_backend , " status " , GTK_PRINT_BACKEND_STATUS_UNAVAILABLE , NULL ) ;
break ;
case GTK_CUPS_CONNECTION_AVAILABLE :
g_object_set ( cups_backend , " status " , GTK_PRINT_BACKEND_STATUS_OK , NULL ) ;
break ;
2020-05-18 09:38:02 +00:00
case GTK_CUPS_CONNECTION_IN_PROGRESS :
2008-09-17 22:07:10 +00:00
default : ;
}
}
2006-04-21 15:09:32 +00:00
static gboolean
cups_request_printer_list ( GtkPrintBackendCups * cups_backend )
{
2008-09-17 22:07:10 +00:00
GtkCupsConnectionState state ;
2006-04-21 15:09:32 +00:00
GtkCupsRequest * request ;
2008-09-17 22:07:10 +00:00
2010-05-24 14:39:19 +00:00
if ( cups_backend - > reading_ppds > 0 | | cups_backend - > list_printers_pending )
2008-09-17 22:07:10 +00:00
return TRUE ;
state = gtk_cups_connection_test_get_state ( cups_backend - > cups_connection_test ) ;
update_backend_status ( cups_backend , state ) ;
2009-09-30 16:40:11 +00:00
if ( cups_backend - > list_printers_attempts = = 60 )
{
cups_backend - > list_printers_attempts = - 1 ;
if ( cups_backend - > list_printers_poll > 0 )
g_source_remove ( cups_backend - > list_printers_poll ) ;
2018-02-02 14:51:47 +00:00
cups_backend - > list_printers_poll = g_timeout_add ( 200 , ( GSourceFunc ) cups_request_printer_list , cups_backend ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( cups_backend - > list_printers_poll , " [gtk] cups_request_printer_list " ) ;
2009-09-30 16:40:11 +00:00
}
else if ( cups_backend - > list_printers_attempts ! = - 1 )
cups_backend - > list_printers_attempts + + ;
2008-09-17 22:07:10 +00:00
if ( state = = GTK_CUPS_CONNECTION_IN_PROGRESS | | state = = GTK_CUPS_CONNECTION_NOT_AVAILABLE )
2006-04-21 15:09:32 +00:00
return TRUE ;
2009-09-30 16:40:11 +00:00
else
if ( cups_backend - > list_printers_attempts > 0 )
cups_backend - > list_printers_attempts = 60 ;
2006-04-21 15:09:32 +00:00
cups_backend - > list_printers_pending = TRUE ;
2009-04-21 12:24:32 +00:00
request = gtk_cups_request_new_with_username ( NULL ,
GTK_CUPS_POST ,
CUPS_GET_PRINTERS ,
NULL ,
NULL ,
NULL ,
cups_backend - > username ) ;
2006-04-21 15:09:32 +00:00
2006-05-04 13:43:32 +00:00
gtk_cups_request_ipp_add_strings ( request , IPP_TAG_OPERATION , IPP_TAG_KEYWORD ,
2013-03-04 13:29:24 +00:00
" requested-attributes " , G_N_ELEMENTS ( printer_attrs ) ,
NULL , printer_attrs ) ;
2006-05-04 13:43:32 +00:00
2006-04-21 15:09:32 +00:00
cups_request_execute ( cups_backend ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_request_printer_list_cb ,
request ,
2006-06-21 05:08:43 +00:00
NULL ) ;
2007-01-03 20:34:00 +00:00
2006-04-21 15:09:32 +00:00
return TRUE ;
}
2006-05-04 13:43:32 +00:00
static void
cups_get_printer_list ( GtkPrintBackend * backend )
2006-04-21 15:09:32 +00:00
{
GtkPrintBackendCups * cups_backend ;
2006-05-04 13:43:32 +00:00
cups_backend = GTK_PRINT_BACKEND_CUPS ( backend ) ;
2008-09-17 22:07:10 +00:00
if ( cups_backend - > cups_connection_test = = NULL )
2014-07-11 09:33:30 +00:00
cups_backend - > cups_connection_test = gtk_cups_connection_test_new ( NULL , - 1 ) ;
2008-09-17 22:07:10 +00:00
2006-04-21 15:09:32 +00:00
if ( cups_backend - > list_printers_poll = = 0 )
{
2008-09-17 22:07:10 +00:00
if ( cups_request_printer_list ( cups_backend ) )
2013-10-22 13:43:43 +00:00
{
2018-02-02 14:51:47 +00:00
cups_backend - > list_printers_poll = g_timeout_add ( 50 , ( GSourceFunc ) cups_request_printer_list , backend ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( cups_backend - > list_printers_poll , " [gtk] cups_request_printer_list " ) ;
2013-10-22 13:43:43 +00:00
}
2013-03-04 13:29:24 +00:00
avahi_request_printer_list ( cups_backend ) ;
2006-04-21 15:09:32 +00:00
}
}
typedef struct {
GtkPrinterCups * printer ;
2006-06-21 18:16:58 +00:00
GIOChannel * ppd_io ;
2007-01-04 00:12:04 +00:00
http_t * http ;
2006-04-21 15:09:32 +00:00
} GetPPDData ;
static void
get_ppd_data_free ( GetPPDData * data )
{
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2007-01-04 00:12:04 +00:00
httpClose ( data - > http ) ;
2006-06-21 18:16:58 +00:00
g_io_channel_unref ( data - > ppd_io ) ;
2006-04-21 15:09:32 +00:00
g_object_unref ( data - > printer ) ;
g_free ( data ) ;
}
static void
cups_request_ppd_cb ( GtkPrintBackendCups * print_backend ,
2006-06-16 18:29:09 +00:00
GtkCupsResult * result ,
GetPPDData * data )
2006-04-21 15:09:32 +00:00
{
GtkPrinter * printer ;
2014-10-02 11:50:47 +00:00
struct stat data_info ;
2006-04-21 15:09:32 +00:00
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2006-04-21 15:09:32 +00:00
printer = GTK_PRINTER ( data - > printer ) ;
GTK_PRINTER_CUPS ( printer ) - > reading_ppd = FALSE ;
2010-05-24 14:39:19 +00:00
print_backend - > reading_ppds - - ;
2006-04-21 15:09:32 +00:00
2015-02-20 10:11:01 +00:00
if ( ! gtk_cups_result_is_error ( result ) )
{
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2015-02-20 10:11:01 +00:00
/* let ppdOpenFd take over the ownership of the open file */
g_io_channel_seek_position ( data - > ppd_io , 0 , G_SEEK_SET , NULL ) ;
data - > printer - > ppd_file = ppdOpenFd ( dup ( g_io_channel_unix_get_fd ( data - > ppd_io ) ) ) ;
ppdLocalize ( data - > printer - > ppd_file ) ;
ppdMarkDefaults ( data - > printer - > ppd_file ) ;
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2015-02-20 10:11:01 +00:00
}
2006-04-21 15:09:32 +00:00
2015-02-20 10:11:01 +00:00
fstat ( g_io_channel_unix_get_fd ( data - > ppd_io ) , & data_info ) ;
/*
* Standalone Avahi printers and raw printers don ' t have PPD files or have
* empty PPD files . Try to get printer details via IPP .
* Always do this for Avahi printers .
*/
if ( data_info . st_size = = 0 | |
GTK_PRINTER_CUPS ( printer ) - > avahi_browsed | |
( gtk_cups_result_is_error ( result ) & &
( ( gtk_cups_result_get_error_type ( result ) = = GTK_CUPS_ERROR_HTTP ) & &
( gtk_cups_result_get_error_status ( result ) = = HTTP_NOT_FOUND ) ) ) )
{
2019-09-19 16:35:23 +00:00
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
/* Try to get the PPD from original host if it is not
* available on current CUPS server .
*/
if ( ! cups_printer - > avahi_browsed & &
( gtk_cups_result_is_error ( result ) & &
( ( gtk_cups_result_get_error_type ( result ) = = GTK_CUPS_ERROR_HTTP ) & &
( gtk_cups_result_get_error_status ( result ) = = HTTP_NOT_FOUND ) ) ) & &
cups_printer - > remote & &
! cups_printer - > request_original_uri & &
cups_printer - > original_device_uri ! = NULL & &
( g_str_has_prefix ( cups_printer - > original_device_uri , " ipp:// " ) | |
g_str_has_prefix ( cups_printer - > original_device_uri , " ipps:// " ) ) )
{
cups_printer - > request_original_uri = TRUE ;
gtk_cups_connection_test_free ( cups_printer - > remote_cups_connection_test ) ;
g_clear_handle_id ( & cups_printer - > get_remote_ppd_poll , g_source_remove ) ;
cups_printer - > get_remote_ppd_attempts = 0 ;
cups_printer - > remote_cups_connection_test =
gtk_cups_connection_test_new ( cups_printer - > original_hostname ,
cups_printer - > original_port ) ;
if ( cups_request_ppd ( printer ) )
{
cups_printer - > get_remote_ppd_poll = g_timeout_add ( 50 , ( GSourceFunc ) cups_request_ppd , printer ) ;
g_source_set_name_by_id ( cups_printer - > get_remote_ppd_poll , " [gtk] cups_request_ppd " ) ;
}
}
else
{
if ( cups_printer - > request_original_uri )
cups_printer - > request_original_uri = FALSE ;
2019-12-12 15:56:37 +00:00
cups_request_printer_info ( cups_printer ) ;
2019-09-19 16:35:23 +00:00
}
2015-02-20 10:11:01 +00:00
2018-02-02 15:34:40 +00:00
return ;
2015-02-20 10:11:01 +00:00
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
gtk_printer_set_has_details ( printer , TRUE ) ;
2006-07-06 17:55:32 +00:00
g_signal_emit_by_name ( printer , " details-acquired " , TRUE ) ;
2006-04-21 15:09:32 +00:00
}
2009-09-23 12:35:26 +00:00
static gboolean
2006-06-16 18:29:09 +00:00
cups_request_ppd ( GtkPrinter * printer )
2006-04-21 15:09:32 +00:00
{
GError * error ;
GtkPrintBackend * print_backend ;
GtkPrinterCups * cups_printer ;
GtkCupsRequest * request ;
2014-03-14 14:36:10 +00:00
char * ppd_filename = NULL ;
2020-07-24 18:40:36 +00:00
char * resource ;
2006-04-21 15:09:32 +00:00
http_t * http ;
GetPPDData * data ;
2006-06-21 18:16:58 +00:00
int fd ;
2020-07-24 18:40:36 +00:00
const char * hostname ;
2020-07-24 13:54:49 +00:00
int port ;
2006-06-21 18:16:58 +00:00
2006-04-21 15:09:32 +00:00
cups_printer = GTK_PRINTER_CUPS ( printer ) ;
error = NULL ;
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: %s \n " , G_STRFUNC ) ) ;
2019-05-06 19:04:17 +00:00
if ( cups_printer - > remote & & ! cups_printer - > avahi_browsed )
2009-09-23 12:35:26 +00:00
{
GtkCupsConnectionState state ;
state = gtk_cups_connection_test_get_state ( cups_printer - > remote_cups_connection_test ) ;
if ( state = = GTK_CUPS_CONNECTION_IN_PROGRESS )
2009-09-30 16:40:11 +00:00
{
if ( cups_printer - > get_remote_ppd_attempts = = 60 )
{
cups_printer - > get_remote_ppd_attempts = - 1 ;
if ( cups_printer - > get_remote_ppd_poll > 0 )
g_source_remove ( cups_printer - > get_remote_ppd_poll ) ;
2018-02-02 14:51:47 +00:00
cups_printer - > get_remote_ppd_poll = g_timeout_add ( 200 , ( GSourceFunc ) cups_request_ppd , printer ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( cups_printer - > get_remote_ppd_poll , " [gtk] cups_request_ppd " ) ;
2009-09-30 16:40:11 +00:00
}
else if ( cups_printer - > get_remote_ppd_attempts ! = - 1 )
cups_printer - > get_remote_ppd_attempts + + ;
return TRUE ;
}
2009-09-23 12:35:26 +00:00
gtk_cups_connection_test_free ( cups_printer - > remote_cups_connection_test ) ;
cups_printer - > remote_cups_connection_test = NULL ;
cups_printer - > get_remote_ppd_poll = 0 ;
2009-09-30 16:40:11 +00:00
cups_printer - > get_remote_ppd_attempts = 0 ;
2009-09-23 12:35:26 +00:00
if ( state = = GTK_CUPS_CONNECTION_NOT_AVAILABLE )
{
g_signal_emit_by_name ( printer , " details-acquired " , FALSE ) ;
return FALSE ;
}
}
2019-09-19 16:35:23 +00:00
if ( cups_printer - > request_original_uri )
{
hostname = cups_printer - > original_hostname ;
port = cups_printer - > original_port ;
resource = g_strdup_printf ( " %s.ppd " , cups_printer - > original_resource ) ;
}
else
{
2021-02-05 17:13:34 +00:00
if ( cups_printer - > is_temporary )
hostname = cupsServer ( ) ;
else
hostname = cups_printer - > hostname ;
2019-09-19 16:35:23 +00:00
port = cups_printer - > port ;
resource = g_strdup_printf ( " /printers/%s.ppd " ,
gtk_printer_cups_get_ppd_name ( GTK_PRINTER_CUPS ( printer ) ) ) ;
}
http = httpConnect2 ( hostname , port ,
2019-04-12 17:00:02 +00:00
NULL , AF_UNSPEC ,
cupsEncryption ( ) ,
1 , 30000 , NULL ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
data = g_new0 ( GetPPDData , 1 ) ;
2012-02-19 21:29:11 +00:00
fd = g_file_open_tmp ( " gtkprint_ppd_XXXXXX " ,
& ppd_filename ,
2006-06-21 18:16:58 +00:00
& error ) ;
2012-02-19 21:29:11 +00:00
# ifdef G_ENABLE_DEBUG
2006-06-21 18:16:58 +00:00
/* If we are debugging printing don't delete the tmp files */
2010-09-08 15:17:57 +00:00
if ( ! ( gtk_get_debug_flags ( ) & GTK_DEBUG_PRINTING ) )
2006-06-21 18:16:58 +00:00
unlink ( ppd_filename ) ;
# else
unlink ( ppd_filename ) ;
# endif /* G_ENABLE_DEBUG */
2006-04-21 15:09:32 +00:00
if ( error ! = NULL )
{
2012-02-19 21:29:11 +00:00
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Failed to create temp file, %s \n " ,
2007-04-23 17:06:07 +00:00
error - > message ) ) ;
2006-04-21 15:09:32 +00:00
g_error_free ( error ) ;
httpClose ( http ) ;
2006-06-21 18:16:58 +00:00
g_free ( ppd_filename ) ;
2006-04-21 15:09:32 +00:00
g_free ( data ) ;
2006-07-06 17:55:32 +00:00
g_signal_emit_by_name ( printer , " details-acquired " , FALSE ) ;
2009-09-23 12:35:26 +00:00
return FALSE ;
2006-04-21 15:09:32 +00:00
}
2012-02-19 21:29:11 +00:00
2007-01-04 00:12:04 +00:00
data - > http = http ;
2006-06-21 18:16:58 +00:00
fchmod ( fd , S_IRUSR | S_IWUSR ) ;
data - > ppd_io = g_io_channel_unix_new ( fd ) ;
g_io_channel_set_encoding ( data - > ppd_io , NULL , NULL ) ;
g_io_channel_set_close_on_unref ( data - > ppd_io , TRUE ) ;
2006-04-21 15:09:32 +00:00
2017-12-08 22:48:47 +00:00
data - > printer = ( GtkPrinterCups * ) g_object_ref ( printer ) ;
2006-04-21 15:09:32 +00:00
2009-04-21 12:24:32 +00:00
print_backend = gtk_printer_get_backend ( printer ) ;
request = gtk_cups_request_new_with_username ( data - > http ,
GTK_CUPS_GET ,
0 ,
data - > ppd_io ,
2019-09-19 16:35:23 +00:00
hostname ,
2009-04-21 12:24:32 +00:00
resource ,
GTK_PRINT_BACKEND_CUPS ( print_backend ) - > username ) ;
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
gtk_cups_request_set_ipp_version ( request ,
cups_printer - > ipp_version_major ,
cups_printer - > ipp_version_minor ) ;
2006-06-21 18:16:58 +00:00
GTK_NOTE ( PRINTING ,
g_print ( " CUPS Backend: Requesting resource %s to be written to temp file %s \n " , resource , ppd_filename ) ) ;
2006-04-21 15:09:32 +00:00
cups_printer - > reading_ppd = TRUE ;
2010-05-24 14:39:19 +00:00
GTK_PRINT_BACKEND_CUPS ( print_backend ) - > reading_ppds + + ;
2006-04-21 15:09:32 +00:00
cups_request_execute ( GTK_PRINT_BACKEND_CUPS ( print_backend ) ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_request_ppd_cb ,
data ,
2006-06-21 05:08:43 +00:00
( GDestroyNotify ) get_ppd_data_free ) ;
2009-04-21 12:24:32 +00:00
g_free ( resource ) ;
g_free ( ppd_filename ) ;
2009-09-23 12:35:26 +00:00
return FALSE ;
2006-04-21 15:09:32 +00:00
}
2008-03-05 03:45:41 +00:00
/* Ordering matters for default preference */
static const char * lpoptions_locations [ ] = {
" /etc/cups/lpoptions " ,
2012-02-19 21:29:11 +00:00
" .lpoptions " ,
2008-03-05 03:45:41 +00:00
" .cups/lpoptions "
} ;
static void
cups_parse_user_default_printer ( const char * filename ,
char * * printer_name )
{
FILE * fp ;
char line [ 1024 ] , * lineptr , * defname = NULL ;
2012-02-19 21:29:11 +00:00
2008-03-05 03:45:41 +00:00
if ( ( fp = g_fopen ( filename , " r " ) ) = = NULL )
return ;
while ( fgets ( line , sizeof ( line ) , fp ) ! = NULL )
{
if ( strncasecmp ( line , " default " , 7 ) ! = 0 | | ! isspace ( line [ 7 ] ) )
continue ;
lineptr = line + 8 ;
while ( isspace ( * lineptr ) )
lineptr + + ;
if ( ! * lineptr )
continue ;
defname = lineptr ;
while ( ! isspace ( * lineptr ) & & * lineptr & & * lineptr ! = ' / ' )
lineptr + + ;
* lineptr = ' \0 ' ;
2014-07-14 15:02:13 +00:00
g_free ( * printer_name ) ;
2008-03-05 03:45:41 +00:00
* printer_name = g_strdup ( defname ) ;
}
fclose ( fp ) ;
}
static void
cups_get_user_default_printer ( char * * printer_name )
{
int i ;
for ( i = 0 ; i < G_N_ELEMENTS ( lpoptions_locations ) ; i + + )
{
if ( g_path_is_absolute ( lpoptions_locations [ i ] ) )
{
cups_parse_user_default_printer ( lpoptions_locations [ i ] ,
printer_name ) ;
}
2012-02-19 21:29:11 +00:00
else
2008-03-05 03:45:41 +00:00
{
char * filename ;
2012-02-19 21:29:11 +00:00
filename = g_build_filename ( g_get_home_dir ( ) ,
2008-03-05 03:45:41 +00:00
lpoptions_locations [ i ] , NULL ) ;
cups_parse_user_default_printer ( filename , printer_name ) ;
g_free ( filename ) ;
}
}
}
static int
cups_parse_user_options ( const char * filename ,
const char * printer_name ,
int num_options ,
cups_option_t * * options )
{
FILE * fp ;
2020-07-24 18:40:36 +00:00
char line [ 1024 ] , * lineptr , * name ;
2008-03-05 03:45:41 +00:00
if ( ( fp = g_fopen ( filename , " r " ) ) = = NULL )
return num_options ;
while ( fgets ( line , sizeof ( line ) , fp ) ! = NULL )
{
if ( strncasecmp ( line , " dest " , 4 ) = = 0 & & isspace ( line [ 4 ] ) )
lineptr = line + 4 ;
else if ( strncasecmp ( line , " default " , 7 ) = = 0 & & isspace ( line [ 7 ] ) )
lineptr = line + 7 ;
else
continue ;
/* Skip leading whitespace */
while ( isspace ( * lineptr ) )
lineptr + + ;
if ( ! * lineptr )
continue ;
name = lineptr ;
while ( ! isspace ( * lineptr ) & & * lineptr )
{
lineptr + + ;
}
if ( ! * lineptr )
continue ;
* lineptr + + = ' \0 ' ;
2015-08-13 20:31:28 +00:00
if ( strcasecmp ( name , printer_name ) ! = 0 )
2008-03-05 03:45:41 +00:00
continue ;
/* We found our printer, parse the options */
num_options = cupsParseOptions ( lineptr , num_options , options ) ;
}
fclose ( fp ) ;
return num_options ;
}
static int
cups_get_user_options ( const char * printer_name ,
int num_options ,
cups_option_t * * options )
{
int i ;
2008-03-12 17:52:36 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( lpoptions_locations ) ; i + + )
2008-03-05 03:45:41 +00:00
{
if ( g_path_is_absolute ( lpoptions_locations [ i ] ) )
2012-02-19 21:29:11 +00:00
{
2008-03-05 03:45:41 +00:00
num_options = cups_parse_user_options ( lpoptions_locations [ i ] ,
printer_name ,
num_options ,
options ) ;
}
else
{
char * filename ;
2012-02-19 21:29:11 +00:00
filename = g_build_filename ( g_get_home_dir ( ) ,
2008-03-05 03:45:41 +00:00
lpoptions_locations [ i ] , NULL ) ;
num_options = cups_parse_user_options ( filename , printer_name ,
num_options , options ) ;
g_free ( filename ) ;
}
}
return num_options ;
}
2006-04-21 15:09:32 +00:00
2008-07-31 23:56:17 +00:00
/* This function requests default printer from a CUPS server in regular intervals.
* In the case of unreachable CUPS server the request is repeated later .
* The default printer is not requested in the case of previous success .
*/
static void
cups_get_default_printer ( GtkPrintBackendCups * backend )
{
GtkPrintBackendCups * cups_backend ;
cups_backend = backend ;
2008-09-17 22:07:10 +00:00
if ( cups_backend - > cups_connection_test = = NULL )
2014-07-11 09:33:30 +00:00
cups_backend - > cups_connection_test = gtk_cups_connection_test_new ( NULL , - 1 ) ;
2008-09-17 22:07:10 +00:00
2008-07-31 23:56:17 +00:00
if ( cups_backend - > default_printer_poll = = 0 )
{
if ( cups_request_default_printer ( cups_backend ) )
2013-10-22 13:43:43 +00:00
{
2018-02-02 14:51:47 +00:00
cups_backend - > default_printer_poll = g_timeout_add ( 200 , ( GSourceFunc ) cups_request_default_printer , backend ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( cups_backend - > default_printer_poll , " [gtk] cups_request_default_printer " ) ;
2013-10-22 13:43:43 +00:00
}
2008-09-17 22:07:10 +00:00
}
}
/* This function gets default printer from local settings.*/
static void
cups_get_local_default_printer ( GtkPrintBackendCups * backend )
{
const char * str ;
char * name = NULL ;
if ( ( str = g_getenv ( " LPDEST " ) ) ! = NULL )
{
backend - > default_printer = g_strdup ( str ) ;
backend - > got_default_printer = TRUE ;
return ;
}
else if ( ( str = g_getenv ( " PRINTER " ) ) ! = NULL & &
strcmp ( str , " lp " ) ! = 0 )
{
backend - > default_printer = g_strdup ( str ) ;
backend - > got_default_printer = TRUE ;
return ;
}
2012-02-19 21:29:11 +00:00
/* Figure out user setting for default printer */
2008-09-17 22:07:10 +00:00
cups_get_user_default_printer ( & name ) ;
if ( name ! = NULL )
{
backend - > default_printer = name ;
backend - > got_default_printer = TRUE ;
return ;
2008-07-31 23:56:17 +00:00
}
}
2006-04-21 15:09:32 +00:00
static void
cups_request_default_printer_cb ( GtkPrintBackendCups * print_backend ,
2006-06-16 18:29:09 +00:00
GtkCupsResult * result ,
gpointer user_data )
2006-04-21 15:09:32 +00:00
{
ipp_t * response ;
ipp_attribute_t * attr ;
2008-09-17 22:07:10 +00:00
GtkPrinter * printer ;
2006-04-21 15:09:32 +00:00
2009-04-21 12:24:32 +00:00
if ( gtk_cups_result_is_error ( result ) )
{
if ( gtk_cups_result_get_error_type ( result ) = = GTK_CUPS_ERROR_AUTH & &
gtk_cups_result_get_error_code ( result ) = = 1 )
{
/* Canceled by user, stop popping up more password dialogs */
if ( print_backend - > list_printers_poll > 0 )
g_source_remove ( print_backend - > list_printers_poll ) ;
print_backend - > list_printers_poll = 0 ;
}
return ;
}
2006-04-21 15:09:32 +00:00
response = gtk_cups_result_get_response ( result ) ;
2012-02-19 21:29:11 +00:00
2006-06-21 05:08:43 +00:00
if ( ( attr = ippFindAttribute ( response , " printer-name " , IPP_TAG_NAME ) ) ! = NULL )
2019-05-06 19:04:17 +00:00
print_backend - > default_printer = g_strdup ( ippGetString ( attr , 0 , NULL ) ) ;
2006-04-21 15:09:32 +00:00
print_backend - > got_default_printer = TRUE ;
2008-09-17 22:07:10 +00:00
if ( print_backend - > default_printer ! = NULL )
{
2019-05-06 19:04:17 +00:00
printer = gtk_print_backend_find_printer ( GTK_PRINT_BACKEND ( print_backend ) ,
print_backend - > default_printer ) ;
2008-09-17 22:07:10 +00:00
if ( printer ! = NULL )
{
gtk_printer_set_is_default ( printer , TRUE ) ;
g_signal_emit_by_name ( GTK_PRINT_BACKEND ( print_backend ) , " printer-status-changed " , printer ) ;
}
}
2012-02-19 21:29:11 +00:00
/* Make sure to kick off get_printers if we are polling it,
* as we could have blocked this reading the default printer
2006-06-21 05:08:43 +00:00
*/
2006-04-21 15:09:32 +00:00
if ( print_backend - > list_printers_poll ! = 0 )
cups_request_printer_list ( print_backend ) ;
}
2008-07-31 23:56:17 +00:00
static gboolean
2006-04-21 15:09:32 +00:00
cups_request_default_printer ( GtkPrintBackendCups * print_backend )
{
2008-09-17 22:07:10 +00:00
GtkCupsConnectionState state ;
2006-04-21 15:09:32 +00:00
GtkCupsRequest * request ;
2008-07-31 23:56:17 +00:00
2008-09-17 22:07:10 +00:00
state = gtk_cups_connection_test_get_state ( print_backend - > cups_connection_test ) ;
update_backend_status ( print_backend , state ) ;
2008-07-31 23:56:17 +00:00
2008-09-17 22:07:10 +00:00
if ( state = = GTK_CUPS_CONNECTION_IN_PROGRESS | | state = = GTK_CUPS_CONNECTION_NOT_AVAILABLE )
return TRUE ;
2008-03-05 03:45:41 +00:00
2009-04-21 12:24:32 +00:00
request = gtk_cups_request_new_with_username ( NULL ,
GTK_CUPS_POST ,
CUPS_GET_DEFAULT ,
NULL ,
NULL ,
NULL ,
print_backend - > username ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
cups_request_execute ( print_backend ,
request ,
( GtkPrintCupsResponseCallbackFunc ) cups_request_default_printer_cb ,
g_object_ref ( print_backend ) ,
2006-06-21 05:08:43 +00:00
g_object_unref ) ;
2008-07-31 23:56:17 +00:00
return FALSE ;
2006-04-21 15:09:32 +00:00
}
static void
cups_printer_request_details ( GtkPrinter * printer )
{
GtkPrinterCups * cups_printer ;
cups_printer = GTK_PRINTER_CUPS ( printer ) ;
2021-02-05 17:13:34 +00:00
if ( cups_printer - > avahi_browsed )
{
create_temporary_queue ( GTK_PRINT_BACKEND_CUPS ( gtk_printer_get_backend ( printer ) ) ,
gtk_printer_get_name ( printer ) ,
cups_printer - > printer_uri ,
cups_printer - > temporary_queue_device_uri ) ;
}
else if ( ! cups_printer - > reading_ppd & &
gtk_printer_cups_get_ppd ( cups_printer ) = = NULL )
2009-09-23 12:35:26 +00:00
{
2019-05-06 19:04:17 +00:00
if ( cups_printer - > remote & & ! cups_printer - > avahi_browsed )
2009-09-23 12:35:26 +00:00
{
if ( cups_printer - > get_remote_ppd_poll = = 0 )
{
2014-07-11 09:33:30 +00:00
cups_printer - > remote_cups_connection_test =
gtk_cups_connection_test_new ( cups_printer - > hostname ,
cups_printer - > port ) ;
2009-09-23 12:35:26 +00:00
if ( cups_request_ppd ( printer ) )
2013-10-22 13:43:43 +00:00
{
2018-02-02 14:51:47 +00:00
cups_printer - > get_remote_ppd_poll = g_timeout_add ( 50 , ( GSourceFunc ) cups_request_ppd , printer ) ;
2019-02-05 09:30:33 +00:00
g_source_set_name_by_id ( cups_printer - > get_remote_ppd_poll , " [gtk] cups_request_ppd " ) ;
2013-10-22 13:43:43 +00:00
}
2009-09-23 12:35:26 +00:00
}
}
else
cups_request_ppd ( printer ) ;
}
2006-04-21 15:09:32 +00:00
}
static char *
2012-02-19 21:29:11 +00:00
ppd_text_to_utf8 ( ppd_file_t * ppd_file ,
2006-06-21 05:08:43 +00:00
const char * text )
2006-04-21 15:09:32 +00:00
{
const char * encoding = NULL ;
char * res ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " UTF-8 " ) = = 0 )
{
return g_strdup ( text ) ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " ISOLatin1 " ) = = 0 )
{
encoding = " ISO-8859-1 " ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " ISOLatin2 " ) = = 0 )
{
encoding = " ISO-8859-2 " ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " ISOLatin5 " ) = = 0 )
{
encoding = " ISO-8859-5 " ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " JIS83-RKSJ " ) = = 0 )
{
encoding = " SHIFT-JIS " ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " MacStandard " ) = = 0 )
{
encoding = " MACINTOSH " ;
}
else if ( g_ascii_strcasecmp ( ppd_file - > lang_encoding , " WindowsANSI " ) = = 0 )
{
encoding = " WINDOWS-1252 " ;
}
2012-02-19 21:29:11 +00:00
else
2006-04-21 15:09:32 +00:00
{
/* Fallback, try iso-8859-1... */
encoding = " ISO-8859-1 " ;
}
res = g_convert ( text , - 1 , " UTF-8 " , encoding , NULL , NULL , NULL ) ;
if ( res = = NULL )
{
2007-04-23 17:06:07 +00:00
GTK_NOTE ( PRINTING ,
g_warning ( " CUPS Backend: Unable to convert PPD text \n " ) ) ;
2006-04-21 15:09:32 +00:00
res = g_strdup ( " ??? " ) ;
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
return res ;
}
/* TODO: Add more translations for common settings here */
static const struct {
const char * keyword ;
const char * translation ;
} cups_option_translations [ ] = {
2016-02-16 23:05:32 +00:00
{ " Duplex " , NC_ ( " printing option " , " Two Sided " ) } ,
{ " MediaType " , NC_ ( " printing option " , " Paper Type " ) } ,
{ " InputSlot " , NC_ ( " printing option " , " Paper Source " ) } ,
{ " OutputBin " , NC_ ( " printing option " , " Output Tray " ) } ,
{ " Resolution " , NC_ ( " printing option " , " Resolution " ) } ,
{ " PreFilter " , NC_ ( " printing option " , " GhostScript pre-filtering " ) }
2006-04-21 15:09:32 +00:00
} ;
static const struct {
const char * keyword ;
const char * choice ;
const char * translation ;
} cups_choice_translations [ ] = {
2016-02-16 23:05:32 +00:00
{ " Duplex " , " None " , NC_ ( " printing option value " , " One Sided " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "Two Sided" */
2016-02-16 23:05:32 +00:00
{ " Duplex " , " DuplexNoTumble " , NC_ ( " printing option value " , " Long Edge (Standard) " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "Two Sided" */
2016-02-16 23:05:32 +00:00
{ " Duplex " , " DuplexTumble " , NC_ ( " printing option value " , " Short Edge (Flip) " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " Auto " , NC_ ( " printing option value " , " Auto Select " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " AutoSelect " , NC_ ( " printing option value " , " Auto Select " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " Default " , NC_ ( " printing option value " , " Printer Default " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " None " , NC_ ( " printing option value " , " Printer Default " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " PrinterDefault " , NC_ ( " printing option value " , " Printer Default " ) } ,
2008-08-14 03:12:58 +00:00
/* Translators: this is an option of "Paper Source" */
2016-02-16 23:05:32 +00:00
{ " InputSlot " , " Unspecified " , NC_ ( " printing option value " , " Auto Select " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "Resolution" */
2016-02-16 23:05:32 +00:00
{ " Resolution " , " default " , NC_ ( " printing option value " , " Printer Default " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "GhostScript" */
2016-02-16 23:05:32 +00:00
{ " PreFilter " , " EmbedFonts " , NC_ ( " printing option value " , " Embed GhostScript fonts only " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "GhostScript" */
2016-02-16 23:05:32 +00:00
{ " PreFilter " , " Level1 " , NC_ ( " printing option value " , " Convert to PS level 1 " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "GhostScript" */
2016-02-16 23:05:32 +00:00
{ " PreFilter " , " Level2 " , NC_ ( " printing option value " , " Convert to PS level 2 " ) } ,
2009-02-09 05:39:37 +00:00
/* Translators: this is an option of "GhostScript" */
2016-02-16 23:05:32 +00:00
{ " PreFilter " , " No " , NC_ ( " printing option value " , " No pre-filtering " ) }
2009-02-09 05:39:37 +00:00
} ;
static const struct {
const char * name ;
const char * translation ;
} cups_group_translations [ ] = {
2009-02-10 17:32:47 +00:00
/* Translators: "Miscellaneous" is the label for a button, that opens
up an extra panel of settings in a print dialog . */
2016-02-16 23:05:32 +00:00
{ " Miscellaneous " , NC_ ( " printing option group " , " Miscellaneous " ) }
2006-04-21 15:09:32 +00:00
} ;
static const struct {
const char * ppd_keyword ;
const char * name ;
2010-10-15 10:08:12 +00:00
} ppd_option_names [ ] = {
2016-02-16 23:05:32 +00:00
{ " Duplex " , " gtk-duplex " } ,
{ " MediaType " , " gtk-paper-type " } ,
{ " InputSlot " , " gtk-paper-source " } ,
{ " OutputBin " , " gtk-output-tray " }
2006-04-21 15:09:32 +00:00
} ;
2014-10-10 11:36:30 +00:00
static const struct {
const char * ipp_option_name ;
const char * gtk_option_name ;
const char * translation ;
} ipp_option_translations [ ] = {
2016-02-16 23:05:32 +00:00
{ " sides " , " gtk-duplex " , NC_ ( " printing option " , " Two Sided " ) } ,
{ " output-bin " , " gtk-output-tray " , NC_ ( " printing option " , " Output Tray " ) }
2014-10-10 11:36:30 +00:00
} ;
static const struct {
const char * ipp_option_name ;
const char * ipp_choice ;
const char * translation ;
} ipp_choice_translations [ ] = {
{ " sides " , " one-sided " , NC_ ( " sides " , " One Sided " ) } ,
/* Translators: this is an option of "Two Sided" */
{ " sides " , " two-sided-long-edge " , NC_ ( " sides " , " Long Edge (Standard) " ) } ,
/* Translators: this is an option of "Two Sided" */
{ " sides " , " two-sided-short-edge " , NC_ ( " sides " , " Short Edge (Flip) " ) } ,
2015-06-23 11:28:21 +00:00
/* Translators: Top output bin */
{ " output-bin " , " top " , NC_ ( " output-bin " , " Top Bin " ) } ,
/* Translators: Middle output bin */
{ " output-bin " , " middle " , NC_ ( " output-bin " , " Middle Bin " ) } ,
/* Translators: Bottom output bin */
{ " output-bin " , " bottom " , NC_ ( " output-bin " , " Bottom Bin " ) } ,
/* Translators: Side output bin */
{ " output-bin " , " side " , NC_ ( " output-bin " , " Side Bin " ) } ,
/* Translators: Left output bin */
{ " output-bin " , " left " , NC_ ( " output-bin " , " Left Bin " ) } ,
/* Translators: Right output bin */
{ " output-bin " , " right " , NC_ ( " output-bin " , " Right Bin " ) } ,
/* Translators: Center output bin */
{ " output-bin " , " center " , NC_ ( " output-bin " , " Center Bin " ) } ,
/* Translators: Rear output bin */
{ " output-bin " , " rear " , NC_ ( " output-bin " , " Rear Bin " ) } ,
/* Translators: Output bin where one sided output is oriented in the face-up position */
{ " output-bin " , " face-up " , NC_ ( " output-bin " , " Face Up Bin " ) } ,
/* Translators: Output bin where one sided output is oriented in the face-down position */
{ " output-bin " , " face-down " , NC_ ( " output-bin " , " Face Down Bin " ) } ,
/* Translators: Large capacity output bin */
{ " output-bin " , " large-capacity " , NC_ ( " output-bin " , " Large Capacity Bin " ) } ,
2016-04-12 13:55:19 +00:00
{ NULL , NULL , NULL }
2014-10-10 11:36:30 +00:00
} ;
2016-04-12 13:55:19 +00:00
/*
* Handles " format not a string literal " error
* https : //mail.gnome.org/archives/desktop-devel-list/2016-March/msg00075.html
*/
2020-07-24 18:40:36 +00:00
static char *
2020-07-24 13:54:49 +00:00
get_ipp_choice_translation_string ( int index ,
2016-04-12 13:55:19 +00:00
guint i )
{
2020-07-24 18:40:36 +00:00
char * translation ;
2016-04-12 13:55:19 +00:00
if ( i < G_N_ELEMENTS ( ipp_choice_translations ) )
2016-04-15 10:13:34 +00:00
translation = g_strdup ( _ ( ipp_choice_translations [ i ] . translation ) ) ;
2016-04-12 13:55:19 +00:00
else
{
switch ( i )
{
case 14 :
/* Translators: Output stacker number %d */
2016-04-15 10:13:34 +00:00
translation = g_strdup_printf ( C_ ( " output-bin " , " Stacker %d " ) , index ) ;
2016-04-12 13:55:19 +00:00
break ;
case 15 :
/* Translators: Output mailbox number %d */
2016-04-15 10:13:34 +00:00
translation = g_strdup_printf ( C_ ( " output-bin " , " Mailbox %d " ) , index ) ;
2016-04-12 13:55:19 +00:00
break ;
case 16 :
/* Translators: Private mailbox */
2016-04-15 10:13:34 +00:00
translation = g_strdup ( C_ ( " output-bin " , " My Mailbox " ) ) ;
2016-04-12 13:55:19 +00:00
break ;
case 17 :
/* Translators: Output tray number %d */
2016-04-15 10:13:34 +00:00
translation = g_strdup_printf ( C_ ( " output-bin " , " Tray %d " ) , index ) ;
2016-04-12 13:55:19 +00:00
break ;
default :
g_assert_not_reached ( ) ;
}
}
return translation ;
}
2010-10-15 10:08:12 +00:00
static const struct {
const char * lpoption ;
const char * name ;
} lpoption_names [ ] = {
2016-02-16 23:05:32 +00:00
{ " number-up " , " gtk-n-up " } ,
{ " number-up-layout " , " gtk-n-up-layout " } ,
{ " job-billing " , " gtk-billing-info " } ,
{ " job-priority " , " gtk-job-prio " }
2010-10-15 10:08:12 +00:00
} ;
2006-04-21 15:09:32 +00:00
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * color_option_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" BRColorEnhancement " ,
" BRColorMatching " ,
" BRColorMatching " ,
" BRColorMode " ,
" BRGammaValue " ,
" BRImprovedGray " ,
" BlackSubstitution " ,
" ColorModel " ,
" HPCMYKInks " ,
" HPCSGraphics " ,
" HPCSImages " ,
" HPCSText " ,
" HPColorSmart " ,
" RPSBlackMode " ,
" RPSBlackOverPrint " ,
" Rcmyksimulation " ,
} ;
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * color_group_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" ColorPage " ,
" FPColorWise1 " ,
" FPColorWise2 " ,
" FPColorWise3 " ,
" FPColorWise4 " ,
" FPColorWise5 " ,
" HPColorOptionsPanel " ,
} ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * image_quality_option_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" BRDocument " ,
" BRHalfTonePattern " ,
" BRNormalPrt " ,
" BRPrintQuality " ,
" BitsPerPixel " ,
" Darkness " ,
" Dithering " ,
" EconoMode " ,
" Economode " ,
" HPEconoMode " ,
" HPEdgeControl " ,
" HPGraphicsHalftone " ,
" HPHalftone " ,
" HPLJDensity " ,
" HPPhotoHalftone " ,
" OutputMode " ,
" REt " ,
" RPSBitsPerPixel " ,
" RPSDitherType " ,
" Resolution " ,
" ScreenLock " ,
" Smoothing " ,
" TonerSaveMode " ,
" UCRGCRForImage " ,
} ;
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * image_quality_group_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" FPImageQuality1 " ,
" FPImageQuality2 " ,
" FPImageQuality3 " ,
" ImageQualityPage " ,
} ;
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * finishing_option_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" BindColor " ,
" BindEdge " ,
" BindType " ,
" BindWhen " ,
" Booklet " ,
" FoldType " ,
" FoldWhen " ,
" HPStaplerOptions " ,
" Jog " ,
" Slipsheet " ,
" Sorter " ,
" StapleLocation " ,
" StapleOrientation " ,
" StapleWhen " ,
" StapleX " ,
" StapleY " ,
} ;
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * finishing_group_allow_list [ ] = {
2006-04-21 15:09:32 +00:00
" FPFinishing1 " ,
" FPFinishing2 " ,
" FPFinishing3 " ,
" FPFinishing4 " ,
" FinishingPage " ,
" HPFinishingPanel " ,
} ;
/* keep sorted when changing */
2020-06-18 15:58:43 +00:00
static const char * cups_option_ignore_list [ ] = {
2006-04-21 15:09:32 +00:00
" Collate " ,
2012-02-19 21:29:11 +00:00
" Copies " ,
2006-04-21 15:09:32 +00:00
" OutputOrder " ,
" PageRegion " ,
" PageSize " ,
} ;
static char *
2012-02-19 21:29:11 +00:00
get_option_text ( ppd_file_t * ppd_file ,
2006-06-16 18:29:09 +00:00
ppd_option_t * option )
2006-04-21 15:09:32 +00:00
{
int i ;
char * utf8 ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( cups_option_translations ) ; i + + )
{
if ( strcmp ( cups_option_translations [ i ] . keyword , option - > keyword ) = = 0 )
2016-02-16 23:05:32 +00:00
return g_strdup ( g_dpgettext2 ( GETTEXT_PACKAGE ,
" printing option " ,
cups_option_translations [ i ] . translation ) ) ;
2006-04-21 15:09:32 +00:00
}
utf8 = ppd_text_to_utf8 ( ppd_file , option - > text ) ;
/* Some ppd files have spaces in the text before the colon */
g_strchomp ( utf8 ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
return utf8 ;
}
static char *
2012-02-19 21:29:11 +00:00
get_choice_text ( ppd_file_t * ppd_file ,
2006-06-16 18:29:09 +00:00
ppd_choice_t * choice )
2006-04-21 15:09:32 +00:00
{
int i ;
ppd_option_t * option = choice - > option ;
const char * keyword = option - > keyword ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( cups_choice_translations ) ; i + + )
{
if ( strcmp ( cups_choice_translations [ i ] . keyword , keyword ) = = 0 & &
strcmp ( cups_choice_translations [ i ] . choice , choice - > choice ) = = 0 )
2016-02-16 23:05:32 +00:00
return g_strdup ( g_dpgettext2 ( GETTEXT_PACKAGE ,
" printing option value " ,
cups_choice_translations [ i ] . translation ) ) ;
2006-04-21 15:09:32 +00:00
}
return ppd_text_to_utf8 ( ppd_file , choice - > text ) ;
}
static gboolean
2012-02-19 21:29:11 +00:00
group_has_option ( ppd_group_t * group ,
2006-06-16 18:29:09 +00:00
ppd_option_t * option )
2006-04-21 15:09:32 +00:00
{
int i ;
if ( group = = NULL )
return FALSE ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( group - > num_options > 0 & &
option > = group - > options & & option < group - > options + group - > num_options )
return TRUE ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
for ( i = 0 ; i < group - > num_subgroups ; i + + )
{
if ( group_has_option ( & group - > subgroups [ i ] , option ) )
return TRUE ;
}
return FALSE ;
}
static void
set_option_off ( GtkPrinterOption * option )
{
/* Any of these will do, _set only applies the value
* if its allowed of the option */
gtk_printer_option_set ( option , " False " ) ;
gtk_printer_option_set ( option , " Off " ) ;
gtk_printer_option_set ( option , " None " ) ;
}
static gboolean
value_is_off ( const char * value )
{
return ( strcasecmp ( value , " None " ) = = 0 | |
strcasecmp ( value , " Off " ) = = 0 | |
strcasecmp ( value , " False " ) = = 0 ) ;
}
2015-05-31 01:19:13 +00:00
static const char *
2006-10-03 15:05:05 +00:00
ppd_group_name ( ppd_group_t * group )
{
2012-10-28 21:19:35 +00:00
return group - > name ;
2006-10-03 15:05:05 +00:00
}
2006-04-21 15:09:32 +00:00
static int
2006-06-16 18:29:09 +00:00
available_choices ( ppd_file_t * ppd ,
ppd_option_t * option ,
2006-04-21 15:09:32 +00:00
ppd_choice_t * * * available ,
2006-06-16 18:29:09 +00:00
gboolean keep_if_only_one_option )
2006-04-21 15:09:32 +00:00
{
ppd_option_t * other_option ;
int i , j ;
2020-07-24 18:40:36 +00:00
char * conflicts ;
2006-04-21 15:09:32 +00:00
ppd_const_t * constraint ;
const char * choice , * other_choice ;
ppd_option_t * option1 , * option2 ;
ppd_group_t * installed_options ;
int num_conflicts ;
gboolean all_default ;
int add_auto ;
if ( available )
* available = NULL ;
conflicts = g_new0 ( char , option - > num_choices ) ;
installed_options = NULL ;
for ( i = 0 ; i < ppd - > num_groups ; i + + )
{
2015-05-31 01:19:13 +00:00
const char * name ;
2006-10-03 15:05:05 +00:00
name = ppd_group_name ( & ppd - > groups [ i ] ) ;
if ( strcmp ( name , " InstallableOptions " ) = = 0 )
2006-04-21 15:09:32 +00:00
{
installed_options = & ppd - > groups [ i ] ;
break ;
}
}
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
for ( i = ppd - > num_consts , constraint = ppd - > consts ; i > 0 ; i - - , constraint + + )
{
option1 = ppdFindOption ( ppd , constraint - > option1 ) ;
if ( option1 = = NULL )
continue ;
option2 = ppdFindOption ( ppd , constraint - > option2 ) ;
if ( option2 = = NULL )
continue ;
if ( option = = option1 )
{
choice = constraint - > choice1 ;
other_option = option2 ;
other_choice = constraint - > choice2 ;
}
else if ( option = = option2 )
{
choice = constraint - > choice2 ;
other_option = option1 ;
other_choice = constraint - > choice1 ;
}
else
continue ;
2014-05-26 00:01:24 +00:00
/* We only care of conflicts with installed_options and PageSize */
2006-04-21 15:09:32 +00:00
if ( ! group_has_option ( installed_options , other_option ) & &
( strcmp ( other_option - > keyword , " PageSize " ) ! = 0 ) )
continue ;
if ( * other_choice = = 0 )
{
/* Conflict only if the installed option is not off */
if ( value_is_off ( other_option - > defchoice ) )
continue ;
}
/* Conflict if the installed option has the specified default */
else if ( strcasecmp ( other_choice , other_option - > defchoice ) ! = 0 )
continue ;
if ( * choice = = 0 )
{
/* Conflict with all non-off choices */
for ( j = 0 ; j < option - > num_choices ; j + + )
{
if ( ! value_is_off ( option - > choices [ j ] . choice ) )
conflicts [ j ] = 1 ;
}
}
else
{
for ( j = 0 ; j < option - > num_choices ; j + + )
{
if ( strcasecmp ( option - > choices [ j ] . choice , choice ) = = 0 )
conflicts [ j ] = 1 ;
}
}
}
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
num_conflicts = 0 ;
all_default = TRUE ;
for ( j = 0 ; j < option - > num_choices ; j + + )
{
if ( conflicts [ j ] )
num_conflicts + + ;
else if ( strcmp ( option - > choices [ j ] . choice , option - > defchoice ) ! = 0 )
all_default = FALSE ;
}
2007-01-04 05:09:08 +00:00
if ( ( all_default & & ! keep_if_only_one_option ) | |
( num_conflicts = = option - > num_choices ) )
{
g_free ( conflicts ) ;
2006-04-21 15:09:32 +00:00
2007-01-04 05:09:08 +00:00
return 0 ;
}
2006-04-21 15:09:32 +00:00
/* Some ppds don't have a "use printer default" option for
2006-06-21 05:08:43 +00:00
* InputSlot . This means you always have to select a particular slot ,
* and you can ' t auto - pick source based on the paper size . To support
* this we always add an auto option if there isn ' t one already . If
* the user chooses the generated option we don ' t send any InputSlot
* value when printing . The way we detect existing auto - cases is based
* on feedback from Michael Sweet of cups fame .
*/
2006-04-21 15:09:32 +00:00
add_auto = 0 ;
if ( strcmp ( option - > keyword , " InputSlot " ) = = 0 )
{
gboolean found_auto = FALSE ;
for ( j = 0 ; j < option - > num_choices ; j + + )
{
if ( ! conflicts [ j ] )
{
if ( strcmp ( option - > choices [ j ] . choice , " Auto " ) = = 0 | |
strcmp ( option - > choices [ j ] . choice , " AutoSelect " ) = = 0 | |
strcmp ( option - > choices [ j ] . choice , " Default " ) = = 0 | |
strcmp ( option - > choices [ j ] . choice , " None " ) = = 0 | |
strcmp ( option - > choices [ j ] . choice , " PrinterDefault " ) = = 0 | |
strcmp ( option - > choices [ j ] . choice , " Unspecified " ) = = 0 | |
option - > choices [ j ] . code = = NULL | |
option - > choices [ j ] . code [ 0 ] = = 0 )
{
found_auto = TRUE ;
break ;
}
}
}
if ( ! found_auto )
add_auto = 1 ;
}
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( available )
{
* available = g_new ( ppd_choice_t * , option - > num_choices - num_conflicts + add_auto ) ;
i = 0 ;
for ( j = 0 ; j < option - > num_choices ; j + + )
{
if ( ! conflicts [ j ] )
( * available ) [ i + + ] = & option - > choices [ j ] ;
}
2012-02-19 21:29:11 +00:00
if ( add_auto )
2006-04-21 15:09:32 +00:00
( * available ) [ i + + ] = NULL ;
}
2007-01-04 05:09:08 +00:00
g_free ( conflicts ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
return option - > num_choices - num_conflicts + add_auto ;
}
static GtkPrinterOption *
2006-08-15 16:05:13 +00:00
create_pickone_option ( ppd_file_t * ppd_file ,
ppd_option_t * ppd_option ,
2020-07-24 18:40:36 +00:00
const char * gtk_name )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOption * option ;
ppd_choice_t * * available ;
char * label ;
int n_choices ;
int i ;
2006-08-15 16:05:13 +00:00
ppd_coption_t * coption ;
2006-04-21 15:09:32 +00:00
g_assert ( ppd_option - > ui = = PPD_UI_PICKONE ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
option = NULL ;
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
n_choices = available_choices ( ppd_file , ppd_option , & available , g_str_has_prefix ( gtk_name , " gtk- " ) ) ;
if ( n_choices > 0 )
{
2012-02-19 21:29:11 +00:00
/* right now only support one parameter per custom option
2006-07-18 18:26:51 +00:00
* if more than one print warning and only offer the default choices
*/
2006-08-15 16:05:13 +00:00
label = get_option_text ( ppd_file , ppd_option ) ;
coption = ppdFindCustomOption ( ppd_file , ppd_option - > keyword ) ;
2006-07-18 18:26:51 +00:00
if ( coption )
{
2006-08-15 16:05:13 +00:00
ppd_cparam_t * cparam ;
2006-07-18 18:26:51 +00:00
cparam = ppdFirstCustomParam ( coption ) ;
if ( ppdNextCustomParam ( coption ) = = NULL )
{
2020-05-18 09:38:02 +00:00
switch ( ( guint ) cparam - > type )
2006-07-18 18:26:51 +00:00
{
case PPD_CUSTOM_INT :
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE_INT ) ;
break ;
case PPD_CUSTOM_PASSCODE :
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE ) ;
break ;
case PPD_CUSTOM_PASSWORD :
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ) ;
break ;
case PPD_CUSTOM_REAL :
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE_REAL ) ;
break ;
case PPD_CUSTOM_STRING :
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE_STRING ) ;
break ;
2007-04-23 17:06:07 +00:00
# ifdef PRINT_IGNORED_OPTIONS
2012-02-19 21:29:11 +00:00
case PPD_CUSTOM_POINTS :
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: PPD Custom Points Option not supported " ) ;
2006-07-18 18:26:51 +00:00
break ;
case PPD_CUSTOM_CURVE :
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: PPD Custom Curve Option not supported " ) ;
2006-07-18 18:26:51 +00:00
break ;
2012-02-19 21:29:11 +00:00
case PPD_CUSTOM_INVCURVE :
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: PPD Custom Inverse Curve Option not supported " ) ;
2006-07-18 18:26:51 +00:00
break ;
2007-04-23 17:06:07 +00:00
# endif
2012-02-19 21:29:11 +00:00
default :
2007-04-23 17:06:07 +00:00
break ;
2006-07-18 18:26:51 +00:00
}
}
2007-04-23 17:06:07 +00:00
# ifdef PRINT_IGNORED_OPTIONS
2006-07-18 18:26:51 +00:00
else
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: Multi-parameter PPD Custom Option not supported " ) ;
# endif
2006-07-18 18:26:51 +00:00
}
if ( ! option )
option = gtk_printer_option_new ( gtk_name , label ,
GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2006-04-21 15:09:32 +00:00
g_free ( label ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
gtk_printer_option_allocate_choices ( option , n_choices ) ;
for ( i = 0 ; i < n_choices ; i + + )
{
if ( available [ i ] = = NULL )
{
/* This was auto-added */
option - > choices [ i ] = g_strdup ( " gtk-ignore-value " ) ;
option - > choices_display [ i ] = g_strdup ( _ ( " Printer Default " ) ) ;
}
else
{
option - > choices [ i ] = g_strdup ( available [ i ] - > choice ) ;
option - > choices_display [ i ] = get_choice_text ( ppd_file , available [ i ] ) ;
}
}
2012-01-17 19:33:32 +00:00
if ( option - > type ! = GTK_PRINTER_OPTION_TYPE_PICKONE )
{
if ( g_str_has_prefix ( ppd_option - > defchoice , " Custom. " ) )
gtk_printer_option_set ( option , ppd_option - > defchoice + 7 ) ;
else
gtk_printer_option_set ( option , ppd_option - > defchoice ) ;
}
else
{
gtk_printer_option_set ( option , ppd_option - > defchoice ) ;
}
2006-04-21 15:09:32 +00:00
}
# ifdef PRINT_IGNORED_OPTIONS
else
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: Ignoring pickone %s \n " , ppd_option - > text ) ;
2006-04-21 15:09:32 +00:00
# endif
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
g_free ( available ) ;
return option ;
}
2006-07-18 18:26:51 +00:00
2006-04-21 15:09:32 +00:00
static GtkPrinterOption *
2006-06-16 18:29:09 +00:00
create_boolean_option ( ppd_file_t * ppd_file ,
2006-04-21 15:09:32 +00:00
ppd_option_t * ppd_option ,
2020-07-24 18:40:36 +00:00
const char * gtk_name )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOption * option ;
ppd_choice_t * * available ;
char * label ;
int n_choices ;
g_assert ( ppd_option - > ui = = PPD_UI_BOOLEAN ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
option = NULL ;
n_choices = available_choices ( ppd_file , ppd_option , & available , g_str_has_prefix ( gtk_name , " gtk- " ) ) ;
if ( n_choices = = 2 )
{
label = get_option_text ( ppd_file , ppd_option ) ;
option = gtk_printer_option_new ( gtk_name , label ,
2006-06-21 05:08:43 +00:00
GTK_PRINTER_OPTION_TYPE_BOOLEAN ) ;
2006-04-21 15:09:32 +00:00
g_free ( label ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
gtk_printer_option_allocate_choices ( option , 2 ) ;
option - > choices [ 0 ] = g_strdup ( " True " ) ;
option - > choices_display [ 0 ] = g_strdup ( " True " ) ;
2006-06-21 05:08:43 +00:00
option - > choices [ 1 ] = g_strdup ( " False " ) ;
option - > choices_display [ 1 ] = g_strdup ( " False " ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
gtk_printer_option_set ( option , ppd_option - > defchoice ) ;
}
# ifdef PRINT_IGNORED_OPTIONS
else
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: Ignoring boolean %s \n " , ppd_option - > text ) ;
2006-04-21 15:09:32 +00:00
# endif
g_free ( available ) ;
return option ;
}
2020-07-24 18:40:36 +00:00
static char *
get_ppd_option_name ( const char * keyword )
2006-04-21 15:09:32 +00:00
{
int i ;
2010-10-15 10:08:12 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( ppd_option_names ) ; i + + )
if ( strcmp ( ppd_option_names [ i ] . ppd_keyword , keyword ) = = 0 )
return g_strdup ( ppd_option_names [ i ] . name ) ;
2006-04-21 15:09:32 +00:00
return g_strdup_printf ( " cups-%s " , keyword ) ;
}
2020-07-24 18:40:36 +00:00
static char *
get_lpoption_name ( const char * lpoption )
2010-10-15 10:08:12 +00:00
{
int i ;
for ( i = 0 ; i < G_N_ELEMENTS ( ppd_option_names ) ; i + + )
if ( strcmp ( ppd_option_names [ i ] . ppd_keyword , lpoption ) = = 0 )
return g_strdup ( ppd_option_names [ i ] . name ) ;
for ( i = 0 ; i < G_N_ELEMENTS ( lpoption_names ) ; i + + )
if ( strcmp ( lpoption_names [ i ] . lpoption , lpoption ) = = 0 )
return g_strdup ( lpoption_names [ i ] . name ) ;
return g_strdup_printf ( " cups-%s " , lpoption ) ;
}
2006-04-21 15:09:32 +00:00
static int
2012-02-19 21:29:11 +00:00
strptr_cmp ( const void * a ,
2006-06-16 18:29:09 +00:00
const void * b )
2006-04-21 15:09:32 +00:00
{
char * * aa = ( char * * ) a ;
char * * bb = ( char * * ) b ;
return strcmp ( * aa , * bb ) ;
}
static gboolean
2020-07-24 18:40:36 +00:00
string_in_table ( const char * str ,
const char * table [ ] ,
2020-07-24 13:54:49 +00:00
int table_len )
2006-04-21 15:09:32 +00:00
{
return bsearch ( & str , table , table_len , sizeof ( char * ) , ( void * ) strptr_cmp ) ! = NULL ;
}
# define STRING_IN_TABLE(_str, _table) (string_in_table (_str, _table, G_N_ELEMENTS (_table)))
static void
handle_option ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_option_t * ppd_option ,
ppd_group_t * toplevel_group ,
GtkPrintSettings * settings )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOption * option ;
2015-05-31 01:19:13 +00:00
char * option_name ;
2009-02-09 05:39:37 +00:00
int i ;
2006-07-18 21:47:04 +00:00
2020-06-18 15:58:43 +00:00
if ( STRING_IN_TABLE ( ppd_option - > keyword , cups_option_ignore_list ) )
2006-04-21 15:09:32 +00:00
return ;
2015-05-31 01:19:13 +00:00
option_name = get_ppd_option_name ( ppd_option - > keyword ) ;
2006-07-18 18:26:51 +00:00
2006-04-21 15:09:32 +00:00
option = NULL ;
if ( ppd_option - > ui = = PPD_UI_PICKONE )
2015-05-31 01:19:13 +00:00
option = create_pickone_option ( ppd_file , ppd_option , option_name ) ;
2006-04-21 15:09:32 +00:00
else if ( ppd_option - > ui = = PPD_UI_BOOLEAN )
2015-05-31 01:19:13 +00:00
option = create_boolean_option ( ppd_file , ppd_option , option_name ) ;
2007-04-23 17:06:07 +00:00
# ifdef PRINT_IGNORED_OPTIONS
2006-04-21 15:09:32 +00:00
else
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: Ignoring pickmany setting %s \n " , ppd_option - > text ) ;
2012-02-19 21:29:11 +00:00
# endif
2006-04-21 15:09:32 +00:00
if ( option )
{
2015-05-31 01:19:13 +00:00
const char * name ;
2006-10-03 15:05:05 +00:00
name = ppd_group_name ( toplevel_group ) ;
2020-06-18 15:58:43 +00:00
if ( STRING_IN_TABLE ( name , color_group_allow_list ) | |
STRING_IN_TABLE ( ppd_option - > keyword , color_option_allow_list ) )
2006-04-21 15:09:32 +00:00
{
option - > group = g_strdup ( " ColorPage " ) ;
}
2020-06-18 15:58:43 +00:00
else if ( STRING_IN_TABLE ( name , image_quality_group_allow_list ) | |
STRING_IN_TABLE ( ppd_option - > keyword , image_quality_option_allow_list ) )
2006-04-21 15:09:32 +00:00
{
option - > group = g_strdup ( " ImageQualityPage " ) ;
}
2020-06-18 15:58:43 +00:00
else if ( STRING_IN_TABLE ( name , finishing_group_allow_list ) | |
STRING_IN_TABLE ( ppd_option - > keyword , finishing_option_allow_list ) )
2006-04-21 15:09:32 +00:00
{
option - > group = g_strdup ( " FinishingPage " ) ;
}
else
{
2009-02-09 05:39:37 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( cups_group_translations ) ; i + + )
{
if ( strcmp ( cups_group_translations [ i ] . name , toplevel_group - > name ) = = 0 )
{
2016-02-16 23:05:32 +00:00
option - > group = g_strdup ( g_dpgettext2 ( GETTEXT_PACKAGE ,
" printing option group " ,
cups_group_translations [ i ] . translation ) ) ;
2009-02-09 05:39:37 +00:00
break ;
}
}
if ( i = = G_N_ELEMENTS ( cups_group_translations ) )
option - > group = g_strdup ( toplevel_group - > text ) ;
2006-04-21 15:09:32 +00:00
}
set_option_from_settings ( option , settings ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
gtk_printer_option_set_add ( set , option ) ;
}
2012-02-19 21:29:11 +00:00
2015-05-31 01:19:13 +00:00
g_free ( option_name ) ;
2006-04-21 15:09:32 +00:00
}
static void
handle_group ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_group_t * group ,
ppd_group_t * toplevel_group ,
GtkPrintSettings * settings )
2006-04-21 15:09:32 +00:00
{
2020-07-24 13:54:49 +00:00
int i ;
2020-07-24 18:40:36 +00:00
const char * name ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
/* Ignore installable options */
2006-10-03 15:05:05 +00:00
name = ppd_group_name ( toplevel_group ) ;
if ( strcmp ( name , " InstallableOptions " ) = = 0 )
2006-04-21 15:09:32 +00:00
return ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
for ( i = 0 ; i < group - > num_options ; i + + )
handle_option ( set , ppd_file , & group - > options [ i ] , toplevel_group , settings ) ;
for ( i = 0 ; i < group - > num_subgroups ; i + + )
handle_group ( set , ppd_file , & group - > subgroups [ i ] , toplevel_group , settings ) ;
}
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
typedef struct {
GtkPrintSettings * settings ;
GtkPrinter * printer ;
} GtkPrintBackendCupsColordHelper ;
static void
colord_printer_option_set_changed_cb ( GtkPrinterOptionSet * set ,
GtkPrintBackendCupsColordHelper * helper )
{
gtk_printer_cups_update_settings ( GTK_PRINTER_CUPS ( helper - > printer ) ,
helper - > settings ,
set ) ;
}
# endif
2014-10-10 11:36:30 +00:00
/*
2019-02-05 09:30:33 +00:00
* Lookup translation and GTK name of given IPP option name .
2014-10-10 11:36:30 +00:00
*/
static gboolean
2020-07-24 18:40:36 +00:00
get_ipp_option_translation ( const char * ipp_option_name ,
char * * gtk_option_name ,
char * * translation )
2014-10-10 11:36:30 +00:00
{
2020-07-24 13:54:49 +00:00
int i ;
2014-10-10 11:36:30 +00:00
* gtk_option_name = NULL ;
* translation = NULL ;
for ( i = 0 ; i < G_N_ELEMENTS ( ipp_option_translations ) ; i + + )
{
if ( g_strcmp0 ( ipp_option_translations [ i ] . ipp_option_name , ipp_option_name ) = = 0 )
{
* gtk_option_name = g_strdup ( ipp_option_translations [ i ] . gtk_option_name ) ;
2016-02-16 23:05:32 +00:00
* translation = g_strdup ( g_dpgettext2 ( GETTEXT_PACKAGE ,
" printing option " ,
ipp_option_translations [ i ] . translation ) ) ;
2014-10-10 11:36:30 +00:00
return TRUE ;
}
}
return FALSE ;
}
/*
* Lookup translation of given IPP choice .
*/
2020-07-24 18:40:36 +00:00
static char *
get_ipp_choice_translation ( const char * ipp_option_name ,
const char * ipp_choice )
2014-10-10 11:36:30 +00:00
{
2020-07-24 18:40:36 +00:00
const char * nptr ;
2015-06-23 11:28:21 +00:00
guint64 index ;
2020-07-24 18:40:36 +00:00
char * translation = NULL ;
2015-06-23 11:28:21 +00:00
gsize ipp_choice_length ;
2020-07-24 18:40:36 +00:00
char * endptr ;
2020-07-24 13:54:49 +00:00
int i ;
2014-10-10 11:36:30 +00:00
2016-04-12 13:55:19 +00:00
for ( i = 0 ; ipp_choice_translations [ i ] . ipp_option_name ! = NULL ; i + + )
2014-10-10 11:36:30 +00:00
{
2015-06-23 11:28:21 +00:00
if ( g_strcmp0 ( ipp_choice_translations [ i ] . ipp_option_name , ipp_option_name ) = = 0 )
2014-10-10 11:36:30 +00:00
{
2015-06-23 11:28:21 +00:00
ipp_choice_length = strlen ( ipp_choice_translations [ i ] . ipp_choice ) ;
if ( g_strcmp0 ( ipp_choice_translations [ i ] . ipp_choice , ipp_choice ) = = 0 )
{
translation = g_strdup ( g_dpgettext2 ( GETTEXT_PACKAGE ,
ipp_option_name ,
ipp_choice_translations [ i ] . translation ) ) ;
break ;
}
else if ( g_str_has_suffix ( ipp_choice_translations [ i ] . ipp_choice , " -N " ) & &
g_ascii_strncasecmp ( ipp_choice_translations [ i ] . ipp_choice ,
ipp_choice ,
ipp_choice_length - 2 ) = = 0 )
{
/* Find out index of the ipp_choice if it is supported for the choice. */
endptr = NULL ;
nptr = ipp_choice + ipp_choice_length - 1 ;
index = g_ascii_strtoull ( nptr ,
& endptr ,
10 ) ;
if ( index ! = 0 | | endptr ! = nptr )
{
2016-04-15 10:13:34 +00:00
translation = get_ipp_choice_translation_string ( index , i ) ;
2015-06-23 11:28:21 +00:00
break ;
}
}
2014-10-10 11:36:30 +00:00
}
}
return translation ;
}
2015-06-23 11:28:21 +00:00
/*
* Format an IPP choice to a displayable string .
*/
2020-07-24 18:40:36 +00:00
static char *
format_ipp_choice ( const char * ipp_choice )
2015-06-23 11:28:21 +00:00
{
gboolean after_space = TRUE ;
2020-07-24 18:40:36 +00:00
char * result = NULL ;
2015-06-23 11:28:21 +00:00
gsize i ;
if ( ipp_choice ! = NULL )
{
result = g_strdup ( ipp_choice ) ;
/* Replace all '-' by spaces. */
result = g_strdelimit ( result , " - " , ' ' ) ;
if ( g_str_is_ascii ( result ) )
{
/* Convert all leading characters to upper case. */
for ( i = 0 ; i < strlen ( result ) ; i + + )
{
if ( after_space & & g_ascii_isalpha ( result [ i ] ) )
result [ i ] = g_ascii_toupper ( result [ i ] ) ;
after_space = g_ascii_isspace ( result [ i ] ) ;
}
}
}
return result ;
}
2014-10-10 11:36:30 +00:00
/*
* Look the IPP option up in given set of options .
* Create it if it doesn ' t exist and set its default value
* if available .
*/
static GtkPrinterOption *
2020-05-18 11:41:19 +00:00
setup_ipp_option ( const char * ipp_option_name ,
const char * ipp_choice_default ,
2014-10-10 11:36:30 +00:00
GList * ipp_choices ,
GtkPrinterOptionSet * set )
{
GtkPrinterOption * option = NULL ;
2020-07-24 18:40:36 +00:00
char * gtk_option_name = NULL ;
char * translation = NULL ;
char * ipp_choice ;
2014-10-10 11:36:30 +00:00
gsize i ;
get_ipp_option_translation ( ipp_option_name ,
& gtk_option_name ,
& translation ) ;
/* Look the option up in the given set of options. */
if ( gtk_option_name ! = NULL )
option = gtk_printer_option_set_lookup ( set , gtk_option_name ) ;
/* The option was not found, create it from given choices. */
if ( option = = NULL & &
ipp_choices ! = NULL )
{
GList * iter ;
gsize length ;
char * * choices = NULL ;
char * * choices_display = NULL ;
option = gtk_printer_option_new ( gtk_option_name ,
translation ,
GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
length = g_list_length ( ipp_choices ) ;
choices = g_new0 ( char * , length ) ;
choices_display = g_new0 ( char * , length ) ;
i = 0 ;
for ( iter = ipp_choices ; iter ! = NULL ; iter = iter - > next )
{
2020-07-24 18:40:36 +00:00
ipp_choice = ( char * ) iter - > data ;
2014-10-10 11:36:30 +00:00
choices [ i ] = g_strdup ( ipp_choice ) ;
translation = get_ipp_choice_translation ( ipp_option_name ,
ipp_choice ) ;
if ( translation ! = NULL )
choices_display [ i ] = translation ;
else
2015-06-23 11:28:21 +00:00
choices_display [ i ] = format_ipp_choice ( ipp_choice ) ;
2014-10-10 11:36:30 +00:00
i + + ;
}
if ( choices ! = NULL & &
choices_display ! = NULL )
{
gtk_printer_option_choices_from_array ( option ,
length ,
2020-05-18 11:41:19 +00:00
( const char * * ) choices ,
( const char * * ) choices_display ) ;
2014-10-10 11:36:30 +00:00
}
option_set_is_ipp_option ( option , TRUE ) ;
gtk_printer_option_set_add ( set , option ) ;
2020-05-18 11:41:19 +00:00
g_strfreev ( choices ) ;
g_strfreev ( choices_display ) ;
2014-10-10 11:36:30 +00:00
}
/* The option exists. Set its default value if available. */
if ( option ! = NULL & &
ipp_choice_default ! = NULL )
{
gtk_printer_option_set ( option , ipp_choice_default ) ;
}
return option ;
}
2006-04-21 15:09:32 +00:00
static GtkPrinterOptionSet *
2006-06-21 05:56:14 +00:00
cups_printer_get_options ( GtkPrinter * printer ,
GtkPrintSettings * settings ,
GtkPageSetup * page_setup ,
GtkPrintCapabilities capabilities )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOptionSet * set ;
GtkPrinterOption * option ;
ppd_file_t * ppd_file ;
int i ;
2020-05-18 11:41:19 +00:00
const char * print_at [ ] = { " now " , " at " , " on-hold " } ;
const char * n_up [ ] = { " 1 " , " 2 " , " 4 " , " 6 " , " 9 " , " 16 " } ;
const char * prio [ ] = { " 100 " , " 80 " , " 50 " , " 30 " } ;
2012-02-19 21:29:11 +00:00
/* Translators: These strings name the possible values of the
2008-08-25 21:46:58 +00:00
* job priority option in the print dialog
*/
2020-05-18 11:41:19 +00:00
const char * prio_display [ ] = { N_ ( " Urgent " ) , N_ ( " High " ) , N_ ( " Medium " ) , N_ ( " Low " ) } ;
const char * n_up_layout [ ] = { " lrtb " , " lrbt " , " rltb " , " rlbt " , " tblr " , " tbrl " , " btlr " , " btrl " } ;
2008-08-25 21:46:58 +00:00
/* Translators: These strings name the possible arrangements of
* multiple pages on a sheet when printing
*/
2020-05-18 11:41:19 +00:00
const char * n_up_layout_display [ ] = { N_ ( " Left to right, top to bottom " ) , N_ ( " Left to right, bottom to top " ) ,
N_ ( " Right to left, top to bottom " ) , N_ ( " Right to left, bottom to top " ) ,
N_ ( " Top to bottom, left to right " ) , N_ ( " Top to bottom, right to left " ) ,
N_ ( " Bottom to top, left to right " ) , N_ ( " Bottom to top, right to left " ) } ;
2008-03-05 03:45:41 +00:00
char * name ;
int num_opts ;
cups_option_t * opts = NULL ;
2008-07-15 17:45:18 +00:00
GtkPrintBackendCups * backend ;
2008-08-21 10:25:27 +00:00
GtkTextDirection text_direction ;
2009-08-05 08:34:27 +00:00
GtkPrinterCups * cups_printer = NULL ;
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
GtkPrintBackendCupsColordHelper * helper ;
# endif
2012-04-17 15:12:56 +00:00
char * default_number_up ;
2006-04-21 15:09:32 +00:00
set = gtk_printer_option_set_new ( ) ;
/* Cups specific, non-ppd related settings */
for ( i = 0 ; i < G_N_ELEMENTS ( prio_display ) ; i + + )
prio_display [ i ] = _ ( prio_display [ i ] ) ;
2012-02-19 21:29:11 +00:00
/* Translators, this string is used to label the job priority option
* in the print dialog
2008-08-25 21:46:58 +00:00
*/
2008-08-21 10:25:27 +00:00
option = gtk_printer_option_new ( " gtk-job-prio " , _ ( " Job Priority " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2006-04-21 15:09:32 +00:00
gtk_printer_option_choices_from_array ( option , G_N_ELEMENTS ( prio ) ,
prio , prio_display ) ;
gtk_printer_option_set ( option , " 50 " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
2008-08-25 21:46:58 +00:00
/* Translators, this string is used to label the billing info entry
2012-02-19 21:29:11 +00:00
* in the print dialog
2008-08-25 21:46:58 +00:00
*/
2008-08-21 10:25:27 +00:00
option = gtk_printer_option_new ( " gtk-billing-info " , _ ( " Billing Info " ) , GTK_PRINTER_OPTION_TYPE_STRING ) ;
2006-04-21 15:09:32 +00:00
gtk_printer_option_set ( option , " " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
2008-07-15 17:45:18 +00:00
backend = GTK_PRINT_BACKEND_CUPS ( gtk_printer_get_backend ( printer ) ) ;
2009-08-05 08:34:27 +00:00
cups_printer = GTK_PRINTER_CUPS ( printer ) ;
2008-07-15 17:45:18 +00:00
2009-08-05 08:34:27 +00:00
if ( backend ! = NULL & & printer ! = NULL )
2008-07-15 17:45:18 +00:00
{
2020-05-18 11:41:19 +00:00
const char * cover_default [ ] = {
2016-02-16 23:05:32 +00:00
" none " ,
" classified " ,
" confidential " ,
" secret " ,
" standard " ,
" topsecret " ,
" unclassified "
} ;
2020-05-18 11:41:19 +00:00
const char * cover_display_default [ ] = {
2017-01-28 00:10:12 +00:00
/* Translators, these strings are names for various 'standard' cover
* pages that the printing system may support .
*/
2016-02-16 23:05:32 +00:00
NC_ ( " cover page " , " None " ) ,
NC_ ( " cover page " , " Classified " ) ,
NC_ ( " cover page " , " Confidential " ) ,
NC_ ( " cover page " , " Secret " ) ,
NC_ ( " cover page " , " Standard " ) ,
NC_ ( " cover page " , " Top Secret " ) ,
NC_ ( " cover page " , " Unclassified " )
} ;
2008-07-15 17:45:18 +00:00
char * * cover = NULL ;
char * * cover_display = NULL ;
2008-07-24 12:56:59 +00:00
char * * cover_display_translated = NULL ;
2020-07-24 13:54:49 +00:00
int num_of_covers = 0 ;
2020-05-18 11:41:19 +00:00
gconstpointer value ;
2020-07-24 13:54:49 +00:00
int j ;
2008-07-15 17:45:18 +00:00
2012-02-19 21:29:11 +00:00
/* Translators, this string is used to label the pages-per-sheet option
* in the print dialog
2012-04-17 15:12:56 +00:00
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-n-up " , C_ ( " printer option " , " Pages per Sheet " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
gtk_printer_option_choices_from_array ( option , G_N_ELEMENTS ( n_up ) , n_up , n_up ) ;
2012-04-17 15:12:56 +00:00
default_number_up = g_strdup_printf ( " %d " , cups_printer - > default_number_up ) ;
gtk_printer_option_set ( option , default_number_up ) ;
g_free ( default_number_up ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
if ( cups_printer_get_capabilities ( printer ) & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT )
{
for ( i = 0 ; i < G_N_ELEMENTS ( n_up_layout_display ) ; i + + )
n_up_layout_display [ i ] = _ ( n_up_layout_display [ i ] ) ;
2012-02-19 21:29:11 +00:00
/* Translators, this string is used to label the option in the print
* dialog that controls in what order multiple pages are arranged
2012-04-17 15:12:56 +00:00
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-n-up-layout " , C_ ( " printer option " , " Page Ordering " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2012-04-17 15:12:56 +00:00
gtk_printer_option_choices_from_array ( option , G_N_ELEMENTS ( n_up_layout ) ,
n_up_layout , n_up_layout_display ) ;
text_direction = gtk_widget_get_default_direction ( ) ;
if ( text_direction = = GTK_TEXT_DIR_LTR )
gtk_printer_option_set ( option , " lrtb " ) ;
else
gtk_printer_option_set ( option , " rltb " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
}
2015-02-25 14:54:36 +00:00
num_of_covers = cups_printer - > number_of_covers ;
2008-07-15 17:45:18 +00:00
cover = g_new ( char * , num_of_covers + 1 ) ;
cover [ num_of_covers ] = NULL ;
cover_display = g_new ( char * , num_of_covers + 1 ) ;
cover_display [ num_of_covers ] = NULL ;
2008-07-24 12:56:59 +00:00
cover_display_translated = g_new ( char * , num_of_covers + 1 ) ;
cover_display_translated [ num_of_covers ] = NULL ;
2008-07-15 17:45:18 +00:00
for ( i = 0 ; i < num_of_covers ; i + + )
{
2015-02-25 14:54:36 +00:00
cover [ i ] = g_strdup ( cups_printer - > covers [ i ] ) ;
2008-07-15 17:45:18 +00:00
value = NULL ;
for ( j = 0 ; j < G_N_ELEMENTS ( cover_default ) ; j + + )
if ( strcmp ( cover_default [ j ] , cover [ i ] ) = = 0 )
{
value = cover_display_default [ j ] ;
break ;
}
2015-02-25 14:54:36 +00:00
cover_display [ i ] = ( value ! = NULL ) ? g_strdup ( value ) : g_strdup ( cups_printer - > covers [ i ] ) ;
2008-07-15 17:45:18 +00:00
}
for ( i = 0 ; i < num_of_covers ; i + + )
2020-07-24 18:40:36 +00:00
cover_display_translated [ i ] = ( char * ) g_dpgettext2 ( GETTEXT_PACKAGE , " cover page " , cover_display [ i ] ) ;
2012-02-19 21:29:11 +00:00
/* Translators, this is the label used for the option in the print
2008-08-25 21:46:58 +00:00
* dialog that controls the front cover page .
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-cover-before " , C_ ( " printer option " , " Before " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2008-07-15 17:45:18 +00:00
gtk_printer_option_choices_from_array ( option , num_of_covers ,
2020-05-18 11:41:19 +00:00
( const char * * ) cover , ( const char * * ) cover_display_translated ) ;
2006-04-21 15:09:32 +00:00
2009-08-05 08:34:27 +00:00
if ( cups_printer - > default_cover_before ! = NULL )
gtk_printer_option_set ( option , cups_printer - > default_cover_before ) ;
2008-07-15 17:45:18 +00:00
else
gtk_printer_option_set ( option , " none " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
2012-02-19 21:29:11 +00:00
/* Translators, this is the label used for the option in the print
2008-08-25 21:46:58 +00:00
* dialog that controls the back cover page .
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-cover-after " , C_ ( " printer option " , " After " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2008-07-15 17:45:18 +00:00
gtk_printer_option_choices_from_array ( option , num_of_covers ,
2020-05-18 11:41:19 +00:00
( const char * * ) cover , ( const char * * ) cover_display_translated ) ;
2009-08-05 08:34:27 +00:00
if ( cups_printer - > default_cover_after ! = NULL )
gtk_printer_option_set ( option , cups_printer - > default_cover_after ) ;
2008-07-15 17:45:18 +00:00
else
gtk_printer_option_set ( option , " none " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
g_strfreev ( cover ) ;
g_strfreev ( cover_display ) ;
2008-07-24 12:56:59 +00:00
g_free ( cover_display_translated ) ;
2008-07-15 17:45:18 +00:00
}
2006-04-21 15:09:32 +00:00
2008-08-25 21:46:58 +00:00
/* Translators: this is the name of the option that controls when
* a print job is printed . Possible values are ' now ' , a specified time ,
* or ' on hold '
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-print-time " , C_ ( " printer option " , " Print at " ) , GTK_PRINTER_OPTION_TYPE_PICKONE ) ;
2006-04-21 15:09:32 +00:00
gtk_printer_option_choices_from_array ( option , G_N_ELEMENTS ( print_at ) ,
print_at , print_at ) ;
gtk_printer_option_set ( option , " now " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
2012-02-19 21:29:11 +00:00
2008-08-25 21:46:58 +00:00
/* Translators: this is the name of the option that allows the user
* to specify a time when a print job will be printed .
*/
2016-02-16 23:05:32 +00:00
option = gtk_printer_option_new ( " gtk-print-time-text " , C_ ( " printer option " , " Print at time " ) , GTK_PRINTER_OPTION_TYPE_STRING ) ;
2006-04-21 15:09:32 +00:00
gtk_printer_option_set ( option , " " ) ;
set_option_from_settings ( option , settings ) ;
gtk_printer_option_set_add ( set , option ) ;
g_object_unref ( option ) ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
/* Printer (ppd) specific settings */
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
if ( ppd_file )
{
GtkPaperSize * paper_size ;
2015-05-31 01:19:13 +00:00
ppd_option_t * ppd_option ;
2020-07-24 18:40:36 +00:00
const char * ppd_name ;
2006-06-21 18:16:58 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
ppdMarkDefaults ( ppd_file ) ;
paper_size = gtk_page_setup_get_paper_size ( page_setup ) ;
2015-05-31 01:19:13 +00:00
ppd_option = ppdFindOption ( ppd_file , " PageSize " ) ;
if ( ppd_option )
2014-05-26 00:01:24 +00:00
{
ppd_name = gtk_paper_size_get_ppd_name ( paper_size ) ;
2012-02-19 21:29:11 +00:00
2014-05-26 00:01:24 +00:00
if ( ppd_name )
2018-04-10 13:51:27 +00:00
{
strncpy ( ppd_option - > defchoice , ppd_name , PPD_MAX_NAME - 1 ) ;
ppd_option - > defchoice [ PPD_MAX_NAME - 1 ] = ' \0 ' ;
}
2014-05-26 00:01:24 +00:00
else
{
2020-07-24 18:40:36 +00:00
char * custom_name ;
2014-05-26 00:01:24 +00:00
char width [ G_ASCII_DTOSTR_BUF_SIZE ] ;
char height [ G_ASCII_DTOSTR_BUF_SIZE ] ;
g_ascii_formatd ( width , sizeof ( width ) , " %.2f " ,
gtk_paper_size_get_width ( paper_size ,
GTK_UNIT_POINTS ) ) ;
g_ascii_formatd ( height , sizeof ( height ) , " %.2f " ,
gtk_paper_size_get_height ( paper_size ,
GTK_UNIT_POINTS ) ) ;
/* Translators: this format is used to display a custom
* paper size . The two placeholders are replaced with
* the width and height in points . E . g : " Custom
* 230.4 x142 .9 "
*/
2014-08-22 14:15:44 +00:00
custom_name = g_strdup_printf ( _ ( " Custom %s× %s " ) , width , height ) ;
2018-04-10 13:51:27 +00:00
strncpy ( ppd_option - > defchoice , custom_name , PPD_MAX_NAME - 1 ) ;
ppd_option - > defchoice [ PPD_MAX_NAME - 1 ] = ' \0 ' ;
2014-05-26 00:01:24 +00:00
g_free ( custom_name ) ;
}
}
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
for ( i = 0 ; i < ppd_file - > num_groups ; i + + )
handle_group ( set , ppd_file , & ppd_file - > groups [ i ] , & ppd_file - > groups [ i ] , settings ) ;
}
2014-10-10 11:36:30 +00:00
else
{
/* Try IPP options */
option = setup_ipp_option ( " sides " ,
cups_printer - > sides_default ,
cups_printer - > sides_supported ,
set ) ;
if ( option ! = NULL )
set_option_from_settings ( option , settings ) ;
2015-06-23 11:28:21 +00:00
option = setup_ipp_option ( " output-bin " ,
cups_printer - > output_bin_default ,
cups_printer - > output_bin_supported ,
set ) ;
if ( option ! = NULL )
set_option_from_settings ( option , settings ) ;
2014-10-10 11:36:30 +00:00
}
2006-04-21 15:09:32 +00:00
2008-03-05 03:45:41 +00:00
/* Now honor the user set defaults for this printer */
num_opts = cups_get_user_options ( gtk_printer_get_name ( printer ) , 0 , & opts ) ;
for ( i = 0 ; i < num_opts ; i + + )
{
2020-06-18 15:58:43 +00:00
if ( STRING_IN_TABLE ( opts [ i ] . name , cups_option_ignore_list ) )
2008-03-05 03:45:41 +00:00
continue ;
2010-10-15 10:08:12 +00:00
name = get_lpoption_name ( opts [ i ] . name ) ;
if ( strcmp ( name , " cups-job-sheets " ) = = 0 )
{
2020-07-24 18:40:36 +00:00
char * * values ;
2020-07-24 13:54:49 +00:00
int num_values ;
2012-02-19 21:29:11 +00:00
2010-10-15 10:08:12 +00:00
values = g_strsplit ( opts [ i ] . value , " , " , 2 ) ;
num_values = g_strv_length ( values ) ;
option = gtk_printer_option_set_lookup ( set , " gtk-cover-before " ) ;
if ( option & & num_values > 0 )
gtk_printer_option_set ( option , g_strstrip ( values [ 0 ] ) ) ;
option = gtk_printer_option_set_lookup ( set , " gtk-cover-after " ) ;
if ( option & & num_values > 1 )
gtk_printer_option_set ( option , g_strstrip ( values [ 1 ] ) ) ;
g_strfreev ( values ) ;
}
else if ( strcmp ( name , " cups-job-hold-until " ) = = 0 )
{
GtkPrinterOption * option2 = NULL ;
option = gtk_printer_option_set_lookup ( set , " gtk-print-time-text " ) ;
if ( option & & opts [ i ] . value )
{
option2 = gtk_printer_option_set_lookup ( set , " gtk-print-time " ) ;
if ( option2 )
{
if ( strcmp ( opts [ i ] . value , " indefinite " ) = = 0 )
gtk_printer_option_set ( option2 , " on-hold " ) ;
else
{
gtk_printer_option_set ( option2 , " at " ) ;
gtk_printer_option_set ( option , opts [ i ] . value ) ;
}
}
}
}
else if ( strcmp ( name , " cups-sides " ) = = 0 )
{
option = gtk_printer_option_set_lookup ( set , " gtk-duplex " ) ;
if ( option & & opts [ i ] . value )
{
2014-10-10 11:36:30 +00:00
if ( ! option_is_ipp_option ( option ) )
{
if ( strcmp ( opts [ i ] . value , " two-sided-short-edge " ) = = 0 )
gtk_printer_option_set ( option , " DuplexTumble " ) ;
else if ( strcmp ( opts [ i ] . value , " two-sided-long-edge " ) = = 0 )
gtk_printer_option_set ( option , " DuplexNoTumble " ) ;
}
else
{
gtk_printer_option_set ( option , opts [ i ] . value ) ;
}
2010-10-15 10:08:12 +00:00
}
}
else
{
option = gtk_printer_option_set_lookup ( set , name ) ;
if ( option )
gtk_printer_option_set ( option , opts [ i ] . value ) ;
}
2008-03-05 03:45:41 +00:00
g_free ( name ) ;
}
cupsFreeOptions ( num_opts , opts ) ;
2011-06-03 13:25:54 +00:00
# ifdef HAVE_COLORD
option = gtk_printer_option_new ( " colord-profile " ,
2020-05-28 08:00:03 +00:00
/* TRANSLATORS: this is the ICC color profile to use for this job */
2016-02-16 23:05:32 +00:00
C_ ( " printer option " , " Printer Profile " ) ,
2011-06-03 13:25:54 +00:00
GTK_PRINTER_OPTION_TYPE_INFO ) ;
/* assign it to the color page */
option - > group = g_strdup ( " ColorPage " ) ;
/* TRANSLATORS: this is when color profile information is unavailable */
2016-02-16 23:05:32 +00:00
gtk_printer_option_set ( option , C_ ( " printer option value " , " Unavailable " ) ) ;
2011-06-03 13:25:54 +00:00
gtk_printer_option_set_add ( set , option ) ;
/* watch to see if the user changed the options */
helper = g_new ( GtkPrintBackendCupsColordHelper , 1 ) ;
helper - > printer = printer ;
helper - > settings = settings ;
g_signal_connect_data ( set , " changed " ,
G_CALLBACK ( colord_printer_option_set_changed_cb ) ,
helper ,
( GClosureNotify ) g_free ,
0 ) ;
/* initial coldplug */
gtk_printer_cups_update_settings ( GTK_PRINTER_CUPS ( printer ) ,
settings , set ) ;
g_object_bind_property ( printer , " profile-title " ,
option , " value " ,
G_BINDING_DEFAULT ) ;
# endif
2006-04-21 15:09:32 +00:00
return set ;
}
static void
mark_option_from_set ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_option_t * ppd_option )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOption * option ;
2010-10-15 10:08:12 +00:00
char * name = get_ppd_option_name ( ppd_option - > keyword ) ;
2006-04-21 15:09:32 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
option = gtk_printer_option_set_lookup ( set , name ) ;
if ( option )
ppdMarkOption ( ppd_file , ppd_option - > keyword , option - > value ) ;
2012-02-19 21:29:11 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
g_free ( name ) ;
}
static void
mark_group_from_set ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_group_t * group )
2006-04-21 15:09:32 +00:00
{
int i ;
for ( i = 0 ; i < group - > num_options ; i + + )
mark_option_from_set ( set , ppd_file , & group - > options [ i ] ) ;
for ( i = 0 ; i < group - > num_subgroups ; i + + )
mark_group_from_set ( set , ppd_file , & group - > subgroups [ i ] ) ;
}
static void
set_conflicts_from_option ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_option_t * ppd_option )
2006-04-21 15:09:32 +00:00
{
GtkPrinterOption * option ;
char * name ;
2006-06-21 05:08:43 +00:00
2006-04-21 15:09:32 +00:00
if ( ppd_option - > conflicted )
{
2010-10-15 10:08:12 +00:00
name = get_ppd_option_name ( ppd_option - > keyword ) ;
2006-04-21 15:09:32 +00:00
option = gtk_printer_option_set_lookup ( set , name ) ;
if ( option )
gtk_printer_option_set_has_conflict ( option , TRUE ) ;
2007-04-23 17:06:07 +00:00
# ifdef PRINT_IGNORED_OPTIONS
2006-04-21 15:09:32 +00:00
else
2007-04-23 17:06:07 +00:00
g_warning ( " CUPS Backend: Ignoring conflict for option %s " , ppd_option - > keyword ) ;
# endif
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
g_free ( name ) ;
}
}
static void
set_conflicts_from_group ( GtkPrinterOptionSet * set ,
2006-06-16 18:29:09 +00:00
ppd_file_t * ppd_file ,
ppd_group_t * group )
2006-04-21 15:09:32 +00:00
{
int i ;
for ( i = 0 ; i < group - > num_options ; i + + )
set_conflicts_from_option ( set , ppd_file , & group - > options [ i ] ) ;
for ( i = 0 ; i < group - > num_subgroups ; i + + )
set_conflicts_from_group ( set , ppd_file , & group - > subgroups [ i ] ) ;
}
static gboolean
2006-06-21 05:56:14 +00:00
cups_printer_mark_conflicts ( GtkPrinter * printer ,
GtkPrinterOptionSet * options )
2006-04-21 15:09:32 +00:00
{
ppd_file_t * ppd_file ;
int num_conflicts ;
int i ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
if ( ppd_file = = NULL )
return FALSE ;
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
ppdMarkDefaults ( ppd_file ) ;
for ( i = 0 ; i < ppd_file - > num_groups ; i + + )
mark_group_from_set ( options , ppd_file , & ppd_file - > groups [ i ] ) ;
num_conflicts = ppdConflicts ( ppd_file ) ;
if ( num_conflicts > 0 )
{
for ( i = 0 ; i < ppd_file - > num_groups ; i + + )
set_conflicts_from_group ( options , ppd_file , & ppd_file - > groups [ i ] ) ;
}
2012-02-19 21:29:11 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2006-04-21 15:09:32 +00:00
return num_conflicts > 0 ;
}
struct OptionData {
GtkPrinter * printer ;
GtkPrinterOptionSet * options ;
GtkPrintSettings * settings ;
ppd_file_t * ppd_file ;
} ;
typedef struct {
const char * cups ;
const char * standard ;
} NameMapping ;
static void
2006-06-16 18:29:09 +00:00
map_settings_to_option ( GtkPrinterOption * option ,
const NameMapping table [ ] ,
2020-07-24 13:54:49 +00:00
int n_elements ,
2006-06-16 18:29:09 +00:00
GtkPrintSettings * settings ,
2020-07-24 18:40:36 +00:00
const char * standard_name ,
const char * cups_name ,
const char * ipp_name )
2006-04-21 15:09:32 +00:00
{
int i ;
char * name ;
const char * cups_value ;
2014-10-10 11:36:30 +00:00
const char * ipp_value ;
2006-04-21 15:09:32 +00:00
const char * standard_value ;
/* If the cups-specific setting is set, always use that */
name = g_strdup_printf ( " cups-%s " , cups_name ) ;
cups_value = gtk_print_settings_get ( settings , name ) ;
g_free ( name ) ;
2012-02-19 21:29:11 +00:00
if ( cups_value ! = NULL )
2006-06-21 05:08:43 +00:00
{
gtk_printer_option_set ( option , cups_value ) ;
return ;
}
2006-04-21 15:09:32 +00:00
2014-10-10 11:36:30 +00:00
/* If the IPP-specific setting is set, use that */
name = g_strdup_printf ( " cups-%s " , ipp_name ) ;
ipp_value = gtk_print_settings_get ( settings , name ) ;
g_free ( name ) ;
if ( ipp_value ! = NULL )
{
gtk_printer_option_set ( option , ipp_value ) ;
return ;
}
2006-04-21 15:09:32 +00:00
/* Otherwise we try to convert from the general setting */
standard_value = gtk_print_settings_get ( settings , standard_name ) ;
if ( standard_value = = NULL )
return ;
for ( i = 0 ; i < n_elements ; i + + )
{
if ( table [ i ] . cups = = NULL & & table [ i ] . standard = = NULL )
{
gtk_printer_option_set ( option , standard_value ) ;
break ;
}
else if ( table [ i ] . cups = = NULL & &
strcmp ( table [ i ] . standard , standard_value ) = = 0 )
{
set_option_off ( option ) ;
break ;
}
else if ( strcmp ( table [ i ] . standard , standard_value ) = = 0 )
{
gtk_printer_option_set ( option , table [ i ] . cups ) ;
break ;
}
}
}
static void
2020-07-24 18:40:36 +00:00
map_option_to_settings ( const char * value ,
2006-06-16 18:29:09 +00:00
const NameMapping table [ ] ,
2020-07-24 13:54:49 +00:00
int n_elements ,
2006-06-16 18:29:09 +00:00
GtkPrintSettings * settings ,
2020-07-24 18:40:36 +00:00
const char * standard_name ,
const char * cups_name ,
const char * ipp_name ,
2014-10-10 11:36:30 +00:00
gboolean is_ipp_option )
2006-04-21 15:09:32 +00:00
{
int i ;
char * name ;
for ( i = 0 ; i < n_elements ; i + + )
{
if ( table [ i ] . cups = = NULL & & table [ i ] . standard = = NULL )
{
gtk_print_settings_set ( settings ,
standard_name ,
value ) ;
break ;
}
else if ( table [ i ] . cups = = NULL & & table [ i ] . standard ! = NULL )
{
if ( value_is_off ( value ) )
{
gtk_print_settings_set ( settings ,
standard_name ,
table [ i ] . standard ) ;
break ;
}
}
else if ( strcmp ( table [ i ] . cups , value ) = = 0 )
{
gtk_print_settings_set ( settings ,
standard_name ,
table [ i ] . standard ) ;
break ;
}
}
/* Always set the corresponding cups-specific setting */
2014-10-10 11:36:30 +00:00
if ( is_ipp_option )
name = g_strdup_printf ( " cups-%s " , ipp_name ) ;
else
name = g_strdup_printf ( " cups-%s " , cups_name ) ;
2006-04-21 15:09:32 +00:00
gtk_print_settings_set ( settings , name , value ) ;
2014-10-10 11:36:30 +00:00
2006-04-21 15:09:32 +00:00
g_free ( name ) ;
}
static const NameMapping paper_source_map [ ] = {
{ " Lower " , " lower " } ,
{ " Middle " , " middle " } ,
{ " Upper " , " upper " } ,
{ " Rear " , " rear " } ,
{ " Envelope " , " envelope " } ,
{ " Cassette " , " cassette " } ,
{ " LargeCapacity " , " large-capacity " } ,
{ " AnySmallFormat " , " small-format " } ,
{ " AnyLargeFormat " , " large-format " } ,
{ NULL , NULL }
} ;
static const NameMapping output_tray_map [ ] = {
{ " Upper " , " upper " } ,
{ " Lower " , " lower " } ,
{ " Rear " , " rear " } ,
{ NULL , NULL }
} ;
static const NameMapping duplex_map [ ] = {
{ " DuplexTumble " , " vertical " } ,
{ " DuplexNoTumble " , " horizontal " } ,
{ NULL , " simplex " }
} ;
static const NameMapping output_mode_map [ ] = {
{ " Standard " , " normal " } ,
{ " Normal " , " normal " } ,
{ " Draft " , " draft " } ,
{ " Fast " , " draft " } ,
} ;
static const NameMapping media_type_map [ ] = {
{ " Transparency " , " transparency " } ,
{ " Standard " , " stationery " } ,
{ NULL , NULL }
} ;
static const NameMapping all_map [ ] = {
{ NULL , NULL }
} ;
static void
set_option_from_settings ( GtkPrinterOption * option ,
GtkPrintSettings * settings )
{
const char * cups_value ;
char * value ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
if ( settings = = NULL )
return ;
if ( strcmp ( option - > name , " gtk-paper-source " ) = = 0 )
map_settings_to_option ( option , paper_source_map , G_N_ELEMENTS ( paper_source_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_DEFAULT_SOURCE ,
" InputSlot " , NULL ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-output-tray " ) = = 0 )
map_settings_to_option ( option , output_tray_map , G_N_ELEMENTS ( output_tray_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_OUTPUT_BIN ,
2015-06-23 11:28:21 +00:00
" OutputBin " , " output-bin " ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-duplex " ) = = 0 )
map_settings_to_option ( option , duplex_map , G_N_ELEMENTS ( duplex_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_DUPLEX ,
" Duplex " , " sides " ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " cups-OutputMode " ) = = 0 )
map_settings_to_option ( option , output_mode_map , G_N_ELEMENTS ( output_mode_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_QUALITY ,
" OutputMode " , NULL ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " cups-Resolution " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , option - > name ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
else
{
2010-11-19 09:55:25 +00:00
if ( gtk_print_settings_get_int_with_default ( settings , GTK_PRINT_SETTINGS_RESOLUTION , - 1 ) ! = - 1 | |
gtk_print_settings_get_int_with_default ( settings , GTK_PRINT_SETTINGS_RESOLUTION_X , - 1 ) ! = - 1 | |
gtk_print_settings_get_int_with_default ( settings , GTK_PRINT_SETTINGS_RESOLUTION_Y , - 1 ) ! = - 1 | |
option - > value = = NULL | | option - > value [ 0 ] = = ' \0 ' )
{
int res = gtk_print_settings_get_resolution ( settings ) ;
int res_x = gtk_print_settings_get_resolution_x ( settings ) ;
int res_y = gtk_print_settings_get_resolution_y ( settings ) ;
2008-10-30 16:24:27 +00:00
2010-11-19 09:55:25 +00:00
if ( res_x ! = res_y )
{
value = g_strdup_printf ( " %dx%ddpi " , res_x , res_y ) ;
gtk_printer_option_set ( option , value ) ;
g_free ( value ) ;
}
else if ( res ! = 0 )
{
value = g_strdup_printf ( " %ddpi " , res ) ;
gtk_printer_option_set ( option , value ) ;
g_free ( value ) ;
}
2008-10-30 16:24:27 +00:00
}
2010-11-19 09:55:25 +00:00
}
2006-04-21 15:09:32 +00:00
}
else if ( strcmp ( option - > name , " gtk-paper-type " ) = = 0 )
map_settings_to_option ( option , media_type_map , G_N_ELEMENTS ( media_type_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_MEDIA_TYPE ,
" MediaType " , NULL ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-n-up " ) = = 0 )
{
map_settings_to_option ( option , all_map , G_N_ELEMENTS ( all_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_NUMBER_UP ,
" number-up " , NULL ) ;
2006-04-21 15:09:32 +00:00
}
2008-08-21 10:25:27 +00:00
else if ( strcmp ( option - > name , " gtk-n-up-layout " ) = = 0 )
{
map_settings_to_option ( option , all_map , G_N_ELEMENTS ( all_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT ,
" number-up-layout " , NULL ) ;
2008-08-21 10:25:27 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-billing-info " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " cups-job-billing " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-job-prio " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " cups-job-priority " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-cover-before " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " cover-before " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-cover-after " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " cover-after " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-print-time " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " print-at " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-print-time-text " ) = = 0 )
{
cups_value = gtk_print_settings_get ( settings , " print-at-time " ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
else if ( g_str_has_prefix ( option - > name , " cups- " ) )
{
cups_value = gtk_print_settings_get ( settings , option - > name ) ;
if ( cups_value )
gtk_printer_option_set ( option , cups_value ) ;
2012-02-19 21:29:11 +00:00
}
2006-04-21 15:09:32 +00:00
}
static void
2006-06-16 18:29:09 +00:00
foreach_option_get_settings ( GtkPrinterOption * option ,
2006-04-21 15:09:32 +00:00
gpointer user_data )
{
struct OptionData * data = user_data ;
GtkPrintSettings * settings = data - > settings ;
const char * value ;
value = option - > value ;
if ( strcmp ( option - > name , " gtk-paper-source " ) = = 0 )
map_option_to_settings ( value , paper_source_map , G_N_ELEMENTS ( paper_source_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_DEFAULT_SOURCE ,
" InputSlot " , NULL , FALSE ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-output-tray " ) = = 0 )
map_option_to_settings ( value , output_tray_map , G_N_ELEMENTS ( output_tray_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_OUTPUT_BIN ,
2015-06-23 11:28:21 +00:00
" OutputBin " , " output-bin " , option_is_ipp_option ( option ) ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-duplex " ) = = 0 )
map_option_to_settings ( value , duplex_map , G_N_ELEMENTS ( duplex_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_DUPLEX ,
" Duplex " , " sides " , option_is_ipp_option ( option ) ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " cups-OutputMode " ) = = 0 )
map_option_to_settings ( value , output_mode_map , G_N_ELEMENTS ( output_mode_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_QUALITY ,
" OutputMode " , NULL , FALSE ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " cups-Resolution " ) = = 0 )
{
2008-10-30 16:24:27 +00:00
int res , res_x , res_y ;
if ( sscanf ( value , " %dx%ddpi " , & res_x , & res_y ) = = 2 )
{
2009-08-30 15:10:47 +00:00
if ( res_x > 0 & & res_y > 0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_resolution_xy ( settings , res_x , res_y ) ;
}
else if ( sscanf ( value , " %ddpi " , & res ) = = 1 )
{
2009-08-30 15:10:47 +00:00
if ( res > 0 )
2008-10-30 16:24:27 +00:00
gtk_print_settings_set_resolution ( settings , res ) ;
}
2006-04-21 15:09:32 +00:00
gtk_print_settings_set ( settings , option - > name , value ) ;
}
else if ( strcmp ( option - > name , " gtk-paper-type " ) = = 0 )
map_option_to_settings ( value , media_type_map , G_N_ELEMENTS ( media_type_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_MEDIA_TYPE ,
" MediaType " , NULL , FALSE ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-n-up " ) = = 0 )
map_option_to_settings ( value , all_map , G_N_ELEMENTS ( all_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_NUMBER_UP ,
" number-up " , NULL , FALSE ) ;
2008-08-21 10:25:27 +00:00
else if ( strcmp ( option - > name , " gtk-n-up-layout " ) = = 0 )
map_option_to_settings ( value , all_map , G_N_ELEMENTS ( all_map ) ,
2014-10-10 11:36:30 +00:00
settings , GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT ,
" number-up-layout " , NULL , FALSE ) ;
2006-04-21 15:09:32 +00:00
else if ( strcmp ( option - > name , " gtk-billing-info " ) = = 0 & & strlen ( value ) > 0 )
gtk_print_settings_set ( settings , " cups-job-billing " , value ) ;
else if ( strcmp ( option - > name , " gtk-job-prio " ) = = 0 )
gtk_print_settings_set ( settings , " cups-job-priority " , value ) ;
else if ( strcmp ( option - > name , " gtk-cover-before " ) = = 0 )
gtk_print_settings_set ( settings , " cover-before " , value ) ;
else if ( strcmp ( option - > name , " gtk-cover-after " ) = = 0 )
gtk_print_settings_set ( settings , " cover-after " , value ) ;
else if ( strcmp ( option - > name , " gtk-print-time " ) = = 0 )
gtk_print_settings_set ( settings , " print-at " , value ) ;
else if ( strcmp ( option - > name , " gtk-print-time-text " ) = = 0 )
gtk_print_settings_set ( settings , " print-at-time " , value ) ;
else if ( g_str_has_prefix ( option - > name , " cups- " ) )
gtk_print_settings_set ( settings , option - > name , value ) ;
}
2009-01-21 15:03:14 +00:00
static gboolean
supports_am_pm ( void )
{
struct tm tmp_tm = { 0 } ;
char time [ 8 ] ;
int length ;
length = strftime ( time , sizeof ( time ) , " %p " , & tmp_tm ) ;
return length ! = 0 ;
}
2009-02-12 12:12:30 +00:00
/* Converts local time to UTC time. Local time has to be in one of these
* formats : HH : MM : SS , HH : MM , HH : MM : SS { am , pm } , HH : MM { am , pm } , HH { am , pm } ,
* { am , pm } HH : MM : SS , { am , pm } HH : MM , { am , pm } HH .
2009-01-21 15:03:14 +00:00
* Returns a newly allocated string holding UTC time in HH : MM : SS format
* or NULL .
*/
2020-07-24 18:40:36 +00:00
static char *
2009-01-21 15:03:14 +00:00
localtime_to_utctime ( const char * local_time )
{
2009-02-12 12:12:30 +00:00
const char * formats_0 [ ] = { " %I : %M : %S %p " , " %p %I : %M : %S " ,
" %H : %M : %S " ,
" %I : %M %p " , " %p %I : %M " ,
" %H : %M " ,
" %I %p " , " %p %I " } ;
2009-01-21 15:03:14 +00:00
const char * formats_1 [ ] = { " %H : %M : %S " , " %H : %M " } ;
const char * end = NULL ;
struct tm * actual_local_time ;
struct tm * actual_utc_time ;
struct tm local_print_time ;
struct tm utc_print_time ;
struct tm diff_time ;
2020-07-24 18:40:36 +00:00
char * utc_time = NULL ;
2009-01-21 15:03:14 +00:00
int i , n ;
if ( local_time = = NULL | | local_time [ 0 ] = = ' \0 ' )
return NULL ;
n = supports_am_pm ( ) ? G_N_ELEMENTS ( formats_0 ) : G_N_ELEMENTS ( formats_1 ) ;
for ( i = 0 ; i < n ; i + + )
{
local_print_time . tm_hour = 0 ;
local_print_time . tm_min = 0 ;
local_print_time . tm_sec = 0 ;
if ( supports_am_pm ( ) )
end = strptime ( local_time , formats_0 [ i ] , & local_print_time ) ;
else
end = strptime ( local_time , formats_1 [ i ] , & local_print_time ) ;
if ( end ! = NULL & & end [ 0 ] = = ' \0 ' )
break ;
}
if ( end ! = NULL & & end [ 0 ] = = ' \0 ' )
{
time_t rawtime ;
time ( & rawtime ) ;
2021-02-04 19:18:28 +00:00
actual_utc_time = g_memdup2 ( gmtime ( & rawtime ) , sizeof ( struct tm ) ) ;
actual_local_time = g_memdup2 ( localtime ( & rawtime ) , sizeof ( struct tm ) ) ;
2009-01-21 15:03:14 +00:00
diff_time . tm_hour = actual_utc_time - > tm_hour - actual_local_time - > tm_hour ;
diff_time . tm_min = actual_utc_time - > tm_min - actual_local_time - > tm_min ;
diff_time . tm_sec = actual_utc_time - > tm_sec - actual_local_time - > tm_sec ;
utc_print_time . tm_hour = ( ( local_print_time . tm_hour + diff_time . tm_hour ) + 24 ) % 24 ;
utc_print_time . tm_min = ( ( local_print_time . tm_min + diff_time . tm_min ) + 60 ) % 60 ;
utc_print_time . tm_sec = ( ( local_print_time . tm_sec + diff_time . tm_sec ) + 60 ) % 60 ;
utc_time = g_strdup_printf ( " %02d:%02d:%02d " ,
utc_print_time . tm_hour ,
utc_print_time . tm_min ,
utc_print_time . tm_sec ) ;
}
return utc_time ;
}
2006-04-21 15:09:32 +00:00
static void
2006-06-16 18:29:09 +00:00
cups_printer_get_settings_from_options ( GtkPrinter * printer ,
2006-04-21 15:09:32 +00:00
GtkPrinterOptionSet * options ,
2006-06-16 18:29:09 +00:00
GtkPrintSettings * settings )
2006-04-21 15:09:32 +00:00
{
struct OptionData data ;
const char * print_at , * print_at_time ;
data . printer = printer ;
data . options = options ;
data . settings = settings ;
data . ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
2012-02-19 21:29:11 +00:00
2013-03-04 13:29:24 +00:00
gtk_printer_option_set_foreach ( options , foreach_option_get_settings , & data ) ;
2006-04-21 15:09:32 +00:00
if ( data . ppd_file ! = NULL )
{
GtkPrinterOption * cover_before , * cover_after ;
2012-02-19 21:29:11 +00:00
2006-04-21 15:09:32 +00:00
cover_before = gtk_printer_option_set_lookup ( options , " gtk-cover-before " ) ;
cover_after = gtk_printer_option_set_lookup ( options , " gtk-cover-after " ) ;
if ( cover_before & & cover_after )
{
char * value = g_strdup_printf ( " %s,%s " , cover_before - > value , cover_after - > value ) ;
gtk_print_settings_set ( settings , " cups-job-sheets " , value ) ;
g_free ( value ) ;
}
print_at = gtk_print_settings_get ( settings , " print-at " ) ;
print_at_time = gtk_print_settings_get ( settings , " print-at-time " ) ;
2009-01-21 15:03:14 +00:00
2006-04-21 15:09:32 +00:00
if ( strcmp ( print_at , " at " ) = = 0 )
2009-01-21 15:03:14 +00:00
{
2020-07-24 18:40:36 +00:00
char * utc_time = NULL ;
2012-02-19 21:29:11 +00:00
2009-01-21 15:03:14 +00:00
utc_time = localtime_to_utctime ( print_at_time ) ;
if ( utc_time ! = NULL )
{
gtk_print_settings_set ( settings , " cups-job-hold-until " , utc_time ) ;
g_free ( utc_time ) ;
}
else
gtk_print_settings_set ( settings , " cups-job-hold-until " , print_at_time ) ;
}
2006-04-21 15:09:32 +00:00
else if ( strcmp ( print_at , " on-hold " ) = = 0 )
gtk_print_settings_set ( settings , " cups-job-hold-until " , " indefinite " ) ;
}
}
static void
2006-06-16 18:29:09 +00:00
cups_printer_prepare_for_print ( GtkPrinter * printer ,
GtkPrintJob * print_job ,
2006-04-21 15:09:32 +00:00
GtkPrintSettings * settings ,
2006-06-16 18:29:09 +00:00
GtkPageSetup * page_setup )
2006-04-21 15:09:32 +00:00
{
2010-12-18 22:45:31 +00:00
GtkPrintPages pages ;
GtkPageRange * ranges ;
2020-07-24 13:54:49 +00:00
int n_ranges ;
2006-04-21 15:09:32 +00:00
GtkPageSet page_set ;
GtkPaperSize * paper_size ;
const char * ppd_paper_name ;
double scale ;
2013-03-04 13:29:24 +00:00
GtkPrintCapabilities capabilities ;
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
capabilities = cups_printer_get_capabilities ( printer ) ;
2010-12-18 22:45:31 +00:00
pages = gtk_print_settings_get_print_pages ( settings ) ;
gtk_print_job_set_pages ( print_job , pages ) ;
if ( pages = = GTK_PRINT_PAGES_RANGES )
ranges = gtk_print_settings_get_page_ranges ( settings , & n_ranges ) ;
else
{
ranges = NULL ;
n_ranges = 0 ;
}
gtk_print_job_set_page_ranges ( print_job , ranges , n_ranges ) ;
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
if ( capabilities & GTK_PRINT_CAPABILITY_COLLATE )
{
if ( gtk_print_settings_get_collate ( settings ) )
gtk_print_settings_set ( settings , " cups-Collate " , " True " ) ;
2016-01-06 13:47:48 +00:00
else
gtk_print_settings_set ( settings , " cups-Collate " , " False " ) ;
2013-03-04 13:29:24 +00:00
gtk_print_job_set_collate ( print_job , FALSE ) ;
}
else
{
gtk_print_job_set_collate ( print_job , gtk_print_settings_get_collate ( settings ) ) ;
}
2006-04-21 15:09:32 +00:00
2013-03-04 13:29:24 +00:00
if ( capabilities & GTK_PRINT_CAPABILITY_REVERSE )
{
if ( gtk_print_settings_get_reverse ( settings ) )
gtk_print_settings_set ( settings , " cups-OutputOrder " , " Reverse " ) ;
gtk_print_job_set_reverse ( print_job , FALSE ) ;
}
else
{
gtk_print_job_set_reverse ( print_job , gtk_print_settings_get_reverse ( settings ) ) ;
}
if ( capabilities & GTK_PRINT_CAPABILITY_COPIES )
{
if ( gtk_print_settings_get_n_copies ( settings ) > 1 )
gtk_print_settings_set_int ( settings , " cups-copies " ,
gtk_print_settings_get_n_copies ( settings ) ) ;
gtk_print_job_set_num_copies ( print_job , 1 ) ;
}
else
{
gtk_print_job_set_num_copies ( print_job , gtk_print_settings_get_n_copies ( settings ) ) ;
}
2006-04-21 15:09:32 +00:00
scale = gtk_print_settings_get_scale ( settings ) ;
if ( scale ! = 100.0 )
2010-12-18 22:45:31 +00:00
gtk_print_job_set_scale ( print_job , scale / 100.0 ) ;
2006-04-21 15:09:32 +00:00
page_set = gtk_print_settings_get_page_set ( settings ) ;
if ( page_set = = GTK_PAGE_SET_EVEN )
gtk_print_settings_set ( settings , " cups-page-set " , " even " ) ;
else if ( page_set = = GTK_PAGE_SET_ODD )
gtk_print_settings_set ( settings , " cups-page-set " , " odd " ) ;
2010-12-18 22:45:31 +00:00
gtk_print_job_set_page_set ( print_job , GTK_PAGE_SET_ALL ) ;
2006-04-21 15:09:32 +00:00
paper_size = gtk_page_setup_get_paper_size ( page_setup ) ;
ppd_paper_name = gtk_paper_size_get_ppd_name ( paper_size ) ;
if ( ppd_paper_name ! = NULL )
gtk_print_settings_set ( settings , " cups-PageSize " , ppd_paper_name ) ;
2014-10-02 11:50:47 +00:00
else if ( gtk_paper_size_is_ipp ( paper_size ) )
gtk_print_settings_set ( settings , " cups-media " , gtk_paper_size_get_name ( paper_size ) ) ;
2006-04-21 15:09:32 +00:00
else
{
2008-03-12 01:34:34 +00:00
char width [ G_ASCII_DTOSTR_BUF_SIZE ] ;
char height [ G_ASCII_DTOSTR_BUF_SIZE ] ;
2008-03-12 18:37:39 +00:00
char * custom_name ;
2008-03-12 01:34:34 +00:00
g_ascii_formatd ( width , sizeof ( width ) , " %.2f " , gtk_paper_size_get_width ( paper_size , GTK_UNIT_POINTS ) ) ;
g_ascii_formatd ( height , sizeof ( height ) , " %.2f " , gtk_paper_size_get_height ( paper_size , GTK_UNIT_POINTS ) ) ;
2008-03-12 18:37:39 +00:00
custom_name = g_strdup_printf ( ( " Custom.%sx%s " ) , width , height ) ;
2006-04-21 15:09:32 +00:00
gtk_print_settings_set ( settings , " cups-PageSize " , custom_name ) ;
g_free ( custom_name ) ;
}
2009-06-04 16:49:29 +00:00
if ( gtk_print_settings_get_number_up ( settings ) > 1 )
{
GtkNumberUpLayout layout = gtk_print_settings_get_number_up_layout ( settings ) ;
GEnumClass * enum_class ;
GEnumValue * enum_value ;
switch ( gtk_page_setup_get_orientation ( page_setup ) )
{
case GTK_PAGE_ORIENTATION_LANDSCAPE :
if ( layout < 4 )
2009-10-27 15:53:43 +00:00
layout = layout + 2 + 4 * ( 1 - layout / 2 ) ;
2009-06-04 16:49:29 +00:00
else
2009-10-27 15:53:43 +00:00
layout = layout - 3 - 2 * ( layout % 2 ) ;
2009-06-04 16:49:29 +00:00
break ;
case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT :
layout = ( layout + 3 - 2 * ( layout % 2 ) ) % 4 + 4 * ( layout / 4 ) ;
break ;
case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE :
if ( layout < 4 )
2009-10-27 15:53:43 +00:00
layout = layout + 5 - 2 * ( layout % 2 ) ;
2009-06-04 16:49:29 +00:00
else
2009-10-27 15:53:43 +00:00
layout = layout - 6 + 4 * ( 1 - ( layout - 4 ) / 2 ) ;
2009-06-04 16:49:29 +00:00
break ;
2020-05-18 11:41:19 +00:00
case GTK_PAGE_ORIENTATION_PORTRAIT :
default :
break ;
2009-06-04 16:49:29 +00:00
}
enum_class = g_type_class_ref ( GTK_TYPE_NUMBER_UP_LAYOUT ) ;
enum_value = g_enum_get_value ( enum_class , layout ) ;
gtk_print_settings_set ( settings , " cups-number-up-layout " , enum_value - > value_nick ) ;
g_type_class_unref ( enum_class ) ;
2013-03-04 13:29:24 +00:00
if ( ! ( capabilities & GTK_PRINT_CAPABILITY_NUMBER_UP ) )
{
gtk_print_job_set_n_up ( print_job , gtk_print_settings_get_number_up ( settings ) ) ;
gtk_print_job_set_n_up_layout ( print_job , gtk_print_settings_get_number_up_layout ( settings ) ) ;
}
2009-06-04 16:49:29 +00:00
}
2010-12-18 22:45:31 +00:00
gtk_print_job_set_rotate ( print_job , TRUE ) ;
2006-04-21 15:09:32 +00:00
}
2008-05-21 02:17:30 +00:00
static GtkPageSetup *
create_page_setup ( ppd_file_t * ppd_file ,
ppd_size_t * size )
2020-04-17 22:33:20 +00:00
{
char * display_name ;
GtkPageSetup * page_setup ;
GtkPaperSize * paper_size ;
ppd_option_t * option ;
ppd_choice_t * choice ;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2008-05-21 02:17:30 +00:00
display_name = NULL ;
option = ppdFindOption ( ppd_file , " PageSize " ) ;
if ( option )
{
choice = ppdFindChoice ( option , size - > name ) ;
if ( choice )
display_name = ppd_text_to_utf8 ( ppd_file , choice - > text ) ;
}
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2008-05-21 02:17:30 +00:00
if ( display_name = = NULL )
display_name = g_strdup ( size - > name ) ;
2012-02-19 21:29:11 +00:00
2008-05-21 02:17:30 +00:00
page_setup = gtk_page_setup_new ( ) ;
paper_size = gtk_paper_size_new_from_ppd ( size - > name ,
display_name ,
size - > width ,
size - > length ) ;
gtk_page_setup_set_paper_size ( page_setup , paper_size ) ;
gtk_paper_size_free ( paper_size ) ;
2012-02-19 21:29:11 +00:00
2008-05-21 02:17:30 +00:00
gtk_page_setup_set_top_margin ( page_setup , size - > length - size - > top , GTK_UNIT_POINTS ) ;
gtk_page_setup_set_bottom_margin ( page_setup , size - > bottom , GTK_UNIT_POINTS ) ;
gtk_page_setup_set_left_margin ( page_setup , size - > left , GTK_UNIT_POINTS ) ;
gtk_page_setup_set_right_margin ( page_setup , size - > width - size - > right , GTK_UNIT_POINTS ) ;
2012-02-19 21:29:11 +00:00
2008-05-21 02:17:30 +00:00
g_free ( display_name ) ;
return page_setup ;
}
2014-10-02 11:50:47 +00:00
static GtkPageSetup *
2020-07-24 18:40:36 +00:00
create_page_setup_from_media ( char * media ,
2014-10-02 11:50:47 +00:00
MediaSize * media_size ,
gboolean media_margin_default_set ,
2020-07-24 13:54:49 +00:00
int media_bottom_margin_default ,
int media_top_margin_default ,
int media_left_margin_default ,
int media_right_margin_default )
2014-10-02 11:50:47 +00:00
{
GtkPageSetup * page_setup ;
GtkPaperSize * paper_size ;
page_setup = gtk_page_setup_new ( ) ;
paper_size = gtk_paper_size_new_from_ipp ( media ,
POINTS_PER_INCH * ( media_size - > x_dimension / MM_PER_INCH ) ,
POINTS_PER_INCH * ( media_size - > y_dimension / MM_PER_INCH ) ) ;
gtk_page_setup_set_paper_size ( page_setup , paper_size ) ;
gtk_paper_size_free ( paper_size ) ;
if ( media_margin_default_set )
{
gtk_page_setup_set_bottom_margin ( page_setup , media_bottom_margin_default , GTK_UNIT_MM ) ;
gtk_page_setup_set_top_margin ( page_setup , media_top_margin_default , GTK_UNIT_MM ) ;
gtk_page_setup_set_left_margin ( page_setup , media_left_margin_default , GTK_UNIT_MM ) ;
gtk_page_setup_set_right_margin ( page_setup , media_right_margin_default , GTK_UNIT_MM ) ;
}
return page_setup ;
}
2006-04-21 15:09:32 +00:00
static GList *
cups_printer_list_papers ( GtkPrinter * printer )
{
ppd_file_t * ppd_file ;
ppd_size_t * size ;
GtkPageSetup * page_setup ;
2014-10-02 11:50:47 +00:00
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
GList * result = NULL ;
2006-04-21 15:09:32 +00:00
int i ;
2014-10-02 11:50:47 +00:00
ppd_file = gtk_printer_cups_get_ppd ( cups_printer ) ;
if ( ppd_file ! = NULL )
2006-04-21 15:09:32 +00:00
{
2014-10-02 11:50:47 +00:00
for ( i = 0 ; i < ppd_file - > num_sizes ; i + + )
{
size = & ppd_file - > sizes [ i ] ;
2006-04-21 15:09:32 +00:00
2014-10-02 11:50:47 +00:00
page_setup = create_page_setup ( ppd_file , size ) ;
2006-04-21 15:09:32 +00:00
2014-10-02 11:50:47 +00:00
result = g_list_prepend ( result , page_setup ) ;
}
}
else if ( cups_printer - > media_supported ! = NULL & &
cups_printer - > media_size_supported ! = NULL & &
/*
* ' media_supported ' list can contain names of minimal and maximal sizes
* for which we don ' t create item in ' media_size_supported ' list .
*/
g_list_length ( cups_printer - > media_supported ) > =
g_list_length ( cups_printer - > media_size_supported ) )
{
MediaSize * media_size ;
GList * media_iter ;
GList * media_size_iter ;
2020-07-24 18:40:36 +00:00
char * media ;
2014-10-02 11:50:47 +00:00
for ( media_iter = cups_printer - > media_supported ,
media_size_iter = cups_printer - > media_size_supported ;
media_size_iter ! = NULL ;
media_iter = media_iter - > next ,
media_size_iter = media_size_iter - > next )
{
2020-07-24 18:40:36 +00:00
media = ( char * ) media_iter - > data ;
2014-10-02 11:50:47 +00:00
media_size = ( MediaSize * ) media_size_iter - > data ;
page_setup = create_page_setup_from_media ( media ,
media_size ,
cups_printer - > media_margin_default_set ,
cups_printer - > media_bottom_margin_default ,
cups_printer - > media_top_margin_default ,
cups_printer - > media_left_margin_default ,
cups_printer - > media_right_margin_default ) ;
result = g_list_prepend ( result , page_setup ) ;
}
2006-04-21 15:09:32 +00:00
}
2014-10-02 11:50:47 +00:00
result = g_list_reverse ( result ) ;
return result ;
2006-04-21 15:09:32 +00:00
}
2008-05-21 02:17:30 +00:00
static GtkPageSetup *
cups_printer_get_default_page_size ( GtkPrinter * printer )
{
2014-10-02 11:50:47 +00:00
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
GtkPageSetup * result = NULL ;
ppd_option_t * option ;
ppd_file_t * ppd_file ;
ppd_size_t * size ;
2008-05-21 02:17:30 +00:00
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
2014-10-02 11:50:47 +00:00
if ( ppd_file ! = NULL )
{
2020-04-17 22:33:20 +00:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2014-10-02 11:50:47 +00:00
option = ppdFindOption ( ppd_file , " PageSize " ) ;
if ( option = = NULL )
return NULL ;
2008-05-21 02:17:30 +00:00
2014-10-02 11:50:47 +00:00
size = ppdPageSize ( ppd_file , option - > defchoice ) ;
if ( size = = NULL )
return NULL ;
2012-01-31 11:15:43 +00:00
2020-04-17 22:33:20 +00:00
G_GNUC_END_IGNORE_DEPRECATIONS
2014-10-02 11:50:47 +00:00
result = create_page_setup ( ppd_file , size ) ;
}
else if ( cups_printer - > media_default ! = NULL )
{
MediaSize * media_size ;
GList * media_iter ;
GList * media_size_iter ;
2020-07-24 18:40:36 +00:00
char * media ;
2014-10-02 11:50:47 +00:00
for ( media_iter = cups_printer - > media_supported ,
media_size_iter = cups_printer - > media_size_supported ;
media_size_iter ! = NULL ;
media_iter = media_iter - > next ,
media_size_iter = media_size_iter - > next )
{
2020-07-24 18:40:36 +00:00
media = ( char * ) media_iter - > data ;
2014-10-02 11:50:47 +00:00
media_size = ( MediaSize * ) media_size_iter - > data ;
2008-05-21 02:17:30 +00:00
2014-10-02 11:50:47 +00:00
if ( g_strcmp0 ( cups_printer - > media_default , media ) = = 0 )
{
result = create_page_setup_from_media ( media ,
media_size ,
cups_printer - > media_margin_default_set ,
cups_printer - > media_bottom_margin_default ,
cups_printer - > media_top_margin_default ,
cups_printer - > media_left_margin_default ,
cups_printer - > media_right_margin_default ) ;
}
}
}
return result ;
2008-05-21 02:17:30 +00:00
}
2008-02-06 22:58:47 +00:00
static gboolean
2006-04-21 15:09:32 +00:00
cups_printer_get_hard_margins ( GtkPrinter * printer ,
2020-07-24 20:32:16 +00:00
double * top ,
double * bottom ,
double * left ,
double * right )
2006-04-21 15:09:32 +00:00
{
2014-10-02 11:50:47 +00:00
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
ppd_file_t * ppd_file ;
gboolean result = FALSE ;
2006-04-21 15:09:32 +00:00
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
2014-10-02 11:50:47 +00:00
if ( ppd_file ! = NULL )
{
* left = ppd_file - > custom_margins [ 0 ] ;
* bottom = ppd_file - > custom_margins [ 1 ] ;
* right = ppd_file - > custom_margins [ 2 ] ;
* top = ppd_file - > custom_margins [ 3 ] ;
result = TRUE ;
}
else if ( cups_printer - > media_margin_default_set )
{
2015-02-20 11:22:26 +00:00
* left = POINTS_PER_INCH * cups_printer - > media_left_margin_default / MM_PER_INCH ;
* bottom = POINTS_PER_INCH * cups_printer - > media_bottom_margin_default / MM_PER_INCH ;
* right = POINTS_PER_INCH * cups_printer - > media_right_margin_default / MM_PER_INCH ;
* top = POINTS_PER_INCH * cups_printer - > media_top_margin_default / MM_PER_INCH ;
2014-10-02 11:50:47 +00:00
result = TRUE ;
}
2008-02-06 22:58:47 +00:00
2014-10-02 11:50:47 +00:00
return result ;
2006-04-21 15:09:32 +00:00
}
2006-05-24 10:50:57 +00:00
2018-04-12 09:31:37 +00:00
static gboolean
cups_printer_get_hard_margins_for_paper_size ( GtkPrinter * printer ,
GtkPaperSize * paper_size ,
2020-07-24 20:32:16 +00:00
double * top ,
double * bottom ,
double * left ,
double * right )
2018-04-12 09:31:37 +00:00
{
ppd_file_t * ppd_file ;
ppd_size_t * size ;
2020-07-24 18:40:36 +00:00
const char * paper_name ;
2018-04-12 09:31:37 +00:00
int i ;
ppd_file = gtk_printer_cups_get_ppd ( GTK_PRINTER_CUPS ( printer ) ) ;
if ( ppd_file = = NULL )
return FALSE ;
paper_name = gtk_paper_size_get_ppd_name ( paper_size ) ;
for ( i = 0 ; i < ppd_file - > num_sizes ; i + + )
{
size = & ppd_file - > sizes [ i ] ;
if ( g_strcmp0 ( size - > name , paper_name ) = = 0 )
{
* top = size - > length - size - > top ;
* bottom = size - > bottom ;
* left = size - > left ;
* right = size - > width - size - > right ;
return TRUE ;
}
}
/* Custom size */
* left = ppd_file - > custom_margins [ 0 ] ;
* bottom = ppd_file - > custom_margins [ 1 ] ;
* right = ppd_file - > custom_margins [ 2 ] ;
* top = ppd_file - > custom_margins [ 3 ] ;
return TRUE ;
}
2006-05-24 10:50:57 +00:00
static GtkPrintCapabilities
cups_printer_get_capabilities ( GtkPrinter * printer )
{
2013-03-04 13:29:24 +00:00
GtkPrintCapabilities capabilities = 0 ;
GtkPrinterCups * cups_printer = GTK_PRINTER_CUPS ( printer ) ;
if ( gtk_printer_cups_get_ppd ( cups_printer ) )
{
capabilities = GTK_PRINT_CAPABILITY_REVERSE ;
}
if ( cups_printer - > supports_copies )
{
capabilities | = GTK_PRINT_CAPABILITY_COPIES ;
}
if ( cups_printer - > supports_collate )
{
capabilities | = GTK_PRINT_CAPABILITY_COLLATE ;
}
if ( cups_printer - > supports_number_up )
{
capabilities | = GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT |
GTK_PRINT_CAPABILITY_NUMBER_UP ;
}
return capabilities ;
2006-05-24 10:50:57 +00:00
}
2014-08-19 15:55:47 +00:00
static void
secrets_service_appeared_cb ( GDBusConnection * connection ,
2020-07-24 18:40:36 +00:00
const char * name ,
const char * name_owner ,
2014-08-19 15:55:47 +00:00
gpointer user_data )
{
GtkPrintBackendCups * backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
backend - > secrets_service_available = TRUE ;
}
static void
secrets_service_vanished_cb ( GDBusConnection * connection ,
2020-07-24 18:40:36 +00:00
const char * name ,
2014-08-19 15:55:47 +00:00
gpointer user_data )
{
GtkPrintBackendCups * backend = GTK_PRINT_BACKEND_CUPS ( user_data ) ;
backend - > secrets_service_available = FALSE ;
}