From db3ff14114eae9f62c1c32480e4ff9690e146dd6 Mon Sep 17 00:00:00 2001 From: Biswadeep Purkayastha <98874428+metabiswadeep@users.noreply.github.com> Date: Thu, 30 May 2024 23:31:51 +0530 Subject: [PATCH] Let frontend not be a D-Bus service, remove tryPPD(), bug fixes (#29) - Let the frontend not be a D-Bus service, only the backends Controlling of filtering the backend's list of printers to hide remote printers and/or temporary queues was done by the frontend being a D-Bus service sending signals and not the backends which are D-Bus services by themselves just having methods for that. Having both frontends and backends being D-Bus services makes the interface unnecessarily complicated, especially for distro-independent/ sandboxed packaging, like snapping. No we use backend methods for that and have done away with the frontends being a D-Bus service. - Removed tryPPD(), a useless, PPD-related function This function logs the options in the PPD of the CUPS queue but does nothing else. PPDs will also go away in CUPS 3.x, so we want the CUPS backend not depend on PPDs or PPD-supporting functions/libraries. - send_printer_state_changed_signal(): Send correct signal Send CPDB_SIGNAL_PRINTER_STATE_CHANGED, not CPDB_SIGNAL_PRINTER_REMOVED. Thanks to Tim Shimmin from Papercut for discovering this. - Let "dialog_name" always be "const char *", to eliminate warnings. - Unified logging. Always use log...() functions. Co-authored-by: Till Kamppeter --- src/backend_helper.c | 322 +++++++++++++++++++++++++++++---------- src/backend_helper.h | 22 +-- src/print_backend_cups.c | 286 +++++++++++++++++----------------- src/run-tests.sh | 2 +- 4 files changed, 392 insertions(+), 240 deletions(-) diff --git a/src/backend_helper.c b/src/backend_helper.c index ec48a63..765e3a4 100644 --- a/src/backend_helper.c +++ b/src/backend_helper.c @@ -4,7 +4,11 @@ #include #include #include +#include +#include +#include +#define MAX_ADDRESSES 10 #define _CUPS_NO_DEPRECATED 1 static http_t *system_conn = NULL; @@ -81,7 +85,7 @@ void connect_to_dbus(BackendObj *b, char *obj_path) &error); if (error) { - MSG_LOG("Error connecting CUPS Backend to D-Bus.\n", ERR); + logerror("Error connecting CUPS Backend to D-Bus.\n"); } } @@ -354,7 +358,7 @@ gboolean dialog_contains_printer(BackendObj *b, const char *dialog_name, const c { char *msg = malloc(sizeof(char) * (strlen(dialog_name) + 50)); sprintf(msg, "Can't retrieve printers for dialog %s.\n", dialog_name); - MSG_LOG(msg, ERR); + logerror(msg); free(msg); return FALSE; } @@ -371,7 +375,7 @@ PrinterCUPS *add_printer_to_dialog(BackendObj *b, const char *dialog_name, const { char *msg = malloc(sizeof(char) * (strlen(dialog_name) + 50)); sprintf(msg, "Invalid dialog name %s.\n", dialog_name); - MSG_LOG(msg, ERR); + logerror(msg); free(msg); return NULL; } @@ -388,7 +392,7 @@ void remove_printer_from_dialog(BackendObj *b, const char *dialog_name, const ch { char *msg = malloc(sizeof(char) * (strlen(printer_name) + 50)); sprintf(msg, "Unable to remove printer %s.\n", printer_name); - MSG_LOG(msg, WARN); + logwarn(msg); free(msg); return; } @@ -400,8 +404,8 @@ void send_printer_added_signal(BackendObj *b, const char *dialog_name, cups_dest if (dest == NULL) { - MSG_LOG("Failed to send printer added signal.\n", ERR); - exit(EXIT_FAILURE); + logerror("Failed to send printer added signal.\n"); + return; } char *printer_name = cpdbGetStringCopy(dest->name); GVariant *gv = g_variant_new(CPDB_PRINTER_ADDED_ARGS, @@ -446,7 +450,7 @@ void send_printer_state_changed_signal(BackendObj *b, const char *dialog_name, c dialog_name, b->obj_path, "org.openprinting.PrintBackend", - CPDB_SIGNAL_PRINTER_REMOVED, + CPDB_SIGNAL_PRINTER_STATE_CHANGED, g_variant_new("(ssbs)", printer_name, printer_state, printer_is_accepting_jobs, "CUPS"), &error); @@ -460,7 +464,7 @@ void notify_removed_printers(BackendObj *b, const char *dialog_name, GHashTable GHashTable *prev = d->printers; GList *prevlist = g_hash_table_get_keys(prev); - printf("Notifying removed printers.\n"); + logdebug("Notifying removed printers.\n"); gpointer printer_name = NULL; while (prevlist) { @@ -482,7 +486,7 @@ void notify_added_printers(BackendObj *b, const char *dialog_name, GHashTable *n if (!d) return; GHashTable *prev = d->printers; - printf("Notifying added printers.\n"); + logdebug("Notifying added printers.\n"); gpointer printer_name; gpointer value; cups_dest_t *dest = NULL; @@ -499,17 +503,17 @@ void notify_added_printers(BackendObj *b, const char *dialog_name, GHashTable *n } } -gboolean get_hide_remote(BackendObj *b, char *dialog_name) +gboolean get_hide_remote(BackendObj *b, const char *dialog_name) { Dialog *d = (Dialog *)g_hash_table_lookup(b->dialogs, dialog_name); return d->hide_remote; } -gboolean get_hide_temp(BackendObj *b, char *dialog_name) +gboolean get_hide_temp(BackendObj *b, const char *dialog_name) { Dialog *d = (Dialog *)g_hash_table_lookup(b->dialogs, dialog_name); return d->hide_temp; } -void refresh_printer_list(BackendObj *b, char *dialog_name) +void refresh_printer_list(BackendObj *b, const char *dialog_name) { GHashTable *new_printers; new_printers = cups_get_printers(get_hide_temp(b, dialog_name), get_hide_remote(b, dialog_name)); @@ -521,7 +525,7 @@ GHashTable *get_dialog_printers(BackendObj *b, const char *dialog_name) Dialog *d = (Dialog *)g_hash_table_lookup(b->dialogs, dialog_name); if (d == NULL) { - MSG_LOG("Invalid dialog name.\n", ERR); + logerror("Invalid dialog name.\n"); return NULL; } return d->printers; @@ -533,8 +537,8 @@ PrinterCUPS *get_printer_by_name(BackendObj *b, const char *dialog_name, const c PrinterCUPS *p = (g_hash_table_lookup(printers, printer_name)); if (p == NULL) { - printf("Printer '%s' does not exist for the dialog %s.\n", printer_name, dialog_name); - exit(EXIT_FAILURE); + logerror("Printer '%s' does not exist for the dialog %s.\n", printer_name, dialog_name); + return NULL; } return p; } @@ -545,7 +549,8 @@ cups_dest_t *get_dest_by_name(BackendObj *b, const char *dialog_name, const char PrinterCUPS *p = (g_hash_table_lookup(printers, printer_name)); if (p == NULL) { - printf("Printer '%s' does not exist for the dialog %s.\n", printer_name, dialog_name); + logerror("Printer '%s' does not exist for the dialog %s.\n", printer_name, dialog_name); + return NULL; } return p->dest; } @@ -560,7 +565,7 @@ PrinterCUPS *get_new_PrinterCUPS(const cups_dest_t *dest) cupsCopyDest((cups_dest_t *)dest, 0, &dest_copy); if (dest_copy == NULL) { - MSG_LOG("Error creating PrinterCUPS", WARN); + logerror("Error creating PrinterCUPS"); return NULL; } p->dest = dest_copy; @@ -574,7 +579,7 @@ PrinterCUPS *get_new_PrinterCUPS(const cups_dest_t *dest) void free_PrinterCUPS(PrinterCUPS *p) { - printf("Freeing printerCUPS \n"); + logdebug("Freeing printerCUPS \n"); cupsFreeDests(1, p->dest); if (p->dinfo) { @@ -706,9 +711,9 @@ void print_option(const Option *opt) int i; for (i = 0; i < opt->num_supported; i++) { - printf(" %s\n", opt->supported_values[i]); + logdebug(" %s\n", opt->supported_values[i]); } - printf("****DEFAULT: %s\n", opt->default_value); + logdebug("****DEFAULT: %s\n", opt->default_value); } void free_options(int count, Option *opts) { @@ -737,7 +742,7 @@ void unpack_option_array(GVariant *var, int num_options, Option **options) g_variant_get(var, "a(ssia(s))", &iter); for (i = 0; i < num_options; i++) { - //printf("i = %d\n", i); + //logdebug("i = %d\n", i); g_variant_iter_loop(iter, "(ssia(s))", &name, &default_val, &num_sup, &array_iter); @@ -1151,7 +1156,7 @@ int get_all_media(PrinterCUPS *p, Media **medias) if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST) { /* request failed */ - printf("Request failed: %s\n", cupsLastErrorString()); + logerror("Request failed: %s\n", cupsLastErrorString()); return 0; } @@ -1384,7 +1389,7 @@ const char *get_printer_state(PrinterCUPS *p) if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST) { /* request failed */ - printf("Request failed: %s\n", cupsLastErrorString()); + logerror("Request failed: %s\n", cupsLastErrorString()); return "NA"; } @@ -1393,7 +1398,7 @@ const char *get_printer_state(PrinterCUPS *p) IPP_TAG_ENUM)) != NULL) { - printf("printer-state=%d\n", ippGetInteger(attr, 0)); + logdebug("printer-state=%d\n", ippGetInteger(attr, 0)); str = map->state[ippGetInteger(attr, 0)]; } return str; @@ -1415,7 +1420,7 @@ void print_socket(PrinterCUPS *p, int num_settings, GVariant *settings, char *jo for (i = 0; i < num_settings; i++) { g_variant_iter_loop(iter, "(ss)", &option_name, &option_value); - printf(" %s : %s\n", option_name, option_value); + logdebug(" %s : %s\n", option_name, option_value); /** * to do: @@ -1431,7 +1436,7 @@ void print_socket(PrinterCUPS *p, int num_settings, GVariant *settings, char *jo &job_id, title, num_options, options); cupsStartDestDocument(p->http, p->dest, p->dinfo, job_id, NULL, CUPS_FORMAT_AUTO, - num_options, options, 1); + 0, NULL, 1); int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (socket_fd == -1) { @@ -1512,7 +1517,7 @@ void *print_data_thread(void *data) { // Send data to CUPS using cupsWriteRequestData http_status_t http_status = cupsWriteRequestData(thread_data->printer->http, buffer, bytesRead); if (http_status != HTTP_STATUS_CONTINUE) { - printf("Error writing print data to server.\n"); + logerror("Error writing print data to server.\n"); break; } } @@ -1520,9 +1525,9 @@ void *print_data_thread(void *data) { // Cleanup and free resources close(thread_data->socket_fd); if (cupsFinishDestDocument(thread_data->printer->http, thread_data->printer->dest, thread_data->printer->dinfo) == IPP_STATUS_OK) - printf("Document send succeeded.\n"); + logdebug("Document send succeeded.\n"); else - printf("Document send failed: %s\n", cupsLastErrorString()); + logerror("Document send failed: %s\n", cupsLastErrorString()); cupsFreeOptions(thread_data->num_options, thread_data->options); g_free(thread_data); g_free(buffer); @@ -1543,45 +1548,18 @@ void printAllJobs(PrinterCUPS *p) static void list_group(ppd_file_t *ppd, /* I - PPD file */ ppd_group_t *group) /* I - Group to show */ { - printf("List group %s\n", group->name); + logdebug("List group %s\n", group->name); /** Now iterate through the options in the particular group*/ - printf("It has %d options.\n", group->num_options); - printf("Listing all of them ..\n"); + logdebug("It has %d options.\n", group->num_options); + logdebug("Listing all of them ..\n"); int i; for (i = 0; i < group->num_options; i++) { - printf(" Option %d : %s\n", i, group->options[i].keyword); + logdebug(" Option %d : %s\n", i, group->options[i].keyword); } } -void tryPPD(PrinterCUPS *p) -{ - const char *filename; /* PPD filename */ - ppd_file_t *ppd; /* PPD data */ - ppd_group_t *group; /* Current group */ - if ((filename = cupsGetPPD(p->dest->name)) == NULL) - { - printf("Error getting ppd file.\n"); - return; - } - g_message("Got ppd file %s\n", filename); - if ((ppd = ppdOpenFile(filename)) == NULL) - { - printf("Error opening ppd file.\n"); - return; - } - printf("Opened ppd file.\n"); - ppdMarkDefaults(ppd); - cupsMarkOptions(ppd, p->dest->num_options, p->dest->options); - group = ppd->groups; - for (int i = ppd->num_groups; i > 0; i--) - { - /**iterate through all the groups in the ppd file */ - list_group(ppd, group); - group++; - } -} /**********Dialog related funtions ****************/ Dialog *get_new_Dialog() { @@ -1598,7 +1576,7 @@ Dialog *get_new_Dialog() void free_Dialog(Dialog *d) { - printf("freeing dialog..\n"); + logdebug("freeing dialog..\n"); g_hash_table_destroy(d->printers); free(d); } @@ -1671,14 +1649,25 @@ int add_printer_to_ht_no_temp(void *user_data, unsigned flags, cups_dest_t *dest return 1; } +int add_printer_to_ht_no_remote(void *user_data, unsigned flags, cups_dest_t *dest) +{ + if (cups_is_remote(dest)) + return 1; + GHashTable *h = (GHashTable *)user_data; + char *printername = cpdbGetStringCopy(dest->name); + cups_dest_t *dest_copy = NULL; + cupsCopyDest(dest, 0, &dest_copy); + g_hash_table_insert(h, printername, dest_copy); + return 1; +} + GHashTable *cups_get_printers(gboolean notemp, gboolean noremote) { cups_dest_cb_t cb = add_printer_to_ht; unsigned type = 0, mask = 0; if (noremote) { - type = CUPS_PRINTER_LOCAL; - mask = CUPS_PRINTER_REMOTE; + cb = add_printer_to_ht_no_remote; } if (notemp) { @@ -1687,7 +1676,7 @@ GHashTable *cups_get_printers(gboolean notemp, gboolean noremote) GHashTable *printers_ht = g_hash_table_new(g_str_hash, g_str_equal); cupsEnumDests(CUPS_DEST_FLAGS_NONE, - 1000, //timeout + 3000, //timeout NULL, //cancel type, //TYPE mask, //MASK @@ -1698,7 +1687,7 @@ GHashTable *cups_get_printers(gboolean notemp, gboolean noremote) } GHashTable *cups_get_all_printers() { - printf("all printers\n"); + logdebug("all printers\n"); // to do : fix GHashTable *printers_ht = g_hash_table_new(g_str_hash, g_str_equal); cupsEnumDests(CUPS_DEST_FLAGS_NONE, @@ -1713,7 +1702,7 @@ GHashTable *cups_get_all_printers() } GHashTable *cups_get_local_printers() { - printf("local printers\n"); + logdebug("local printers\n"); //to do: fix GHashTable *printers_ht = g_hash_table_new(g_str_hash, g_str_equal); cupsEnumDests(CUPS_DEST_FLAGS_NONE, @@ -1750,6 +1739,182 @@ gboolean cups_is_temporary(cups_dest_t *dest) return TRUE; } +char *extractHostFromURI(const char *uri) { + const char *host_start, *host_end; + char *host = NULL; + + // Find the start of the host part + host_start = strstr(uri, "://"); + if (host_start != NULL) { + host_start += 3; // Move past "://" + } else { + return NULL; + } + + // Find the end of the host part + const char *slash_pos = strchr(host_start, '/'); + const char *colon_pos = strchr(host_start, ':'); + + if (slash_pos == NULL && colon_pos == NULL) { + host_end = host_start + strlen(host_start); // If no "/" or ":", host extends to end of string + } else if (slash_pos == NULL) { + host_end = colon_pos; + } else if (colon_pos == NULL) { + host_end = slash_pos; + } else { + host_end = (slash_pos < colon_pos) ? slash_pos : colon_pos; + } + + // Allocate memory for the host part + host = (char *)malloc(host_end - host_start + 1); + if (host != NULL) { + // Copy the host part + strncpy(host, host_start, host_end - host_start); + host[host_end - host_start] = '\0'; // Null-terminate the string + } + + fprintf(stderr, "XXX12: URI: %s Host: %s\n", uri, host); + + return host; +} + +gboolean checkRemote(const char *uri) { + //GET LOCALHOST ADDRESSES + char hostname[1024]; + + // Get the hostname of the local machine + if (gethostname(hostname, sizeof(hostname)) == -1) { + perror("gethostname"); + return 1; + } + + strcat(hostname, ".local"); + + // Get the network IP addresses associated with the hostname + struct addrinfo hints, *res, *p; + int status; + int num_addresses = 0; + AddressList addresses[MAX_ADDRESSES]; + + // Get the IPv4 addresses associated with the hostname + { + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // IPv4 + hints.ai_socktype = SOCK_STREAM; + + if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return 1; + } + + // Iterate over the linked list of addrinfo structures + for (p = res; p != NULL && num_addresses < MAX_ADDRESSES; p = p->ai_next) { + inet_ntop(p->ai_family, &((struct sockaddr_in *)p->ai_addr)->sin_addr, addresses[num_addresses].ipstr, sizeof(addresses[num_addresses].ipstr)); + addresses[num_addresses].family = p->ai_family; + num_addresses++; + } + + freeaddrinfo(res); // Free the linked list + } + + // Get the IPv6 addresses associated with the hostname + { + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; // IPv6 + hints.ai_socktype = SOCK_STREAM; + + if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return 1; + } + + // Iterate over the linked list of addrinfo structures + for (p = res; p != NULL && num_addresses < MAX_ADDRESSES; p = p->ai_next) { + inet_ntop(p->ai_family, &((struct sockaddr_in6 *)p->ai_addr)->sin6_addr, addresses[num_addresses].ipstr, sizeof(addresses[num_addresses].ipstr)); + addresses[num_addresses].family = p->ai_family; + num_addresses++; + } + + freeaddrinfo(res); // Free the linked list + } + + // COMPARE LOCAL IP ADDRESSES WITH THAT OF THE URI + struct addrinfo *uri_res; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + const char* new_uri = extractHostFromURI(uri); + + if ((status = getaddrinfo(new_uri, NULL, &hints, &uri_res)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return 1; + } + + + for (p = uri_res; p != NULL; p = p->ai_next) { + void *addr; + char ipstr[INET6_ADDRSTRLEN]; + + // Get the pointer to the address itself, + // different fields in IPv4 and IPv6: + if (p->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + } else { // IPv6 + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + } + + // Convert the IP to a string + inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr)); + + // Check if this IP address matches any of the addresses associated with the local hostname + for (int i = 0; i < num_addresses; i++) { + if (p->ai_family == addresses[i].family && strcmp(ipstr, addresses[i].ipstr) == 0) { + return FALSE; + } + } + } + + freeaddrinfo(uri_res); // Free the linked list + return TRUE; +} + +gboolean cups_is_remote(cups_dest_t *dest) +{ + g_assert_nonnull(dest); + const char *device_uri = cupsGetOption("device-uri", dest->num_options, dest->options); + + const char *uri = cfResolveURI(device_uri); + + fprintf(stderr, "XXX10: deviceURI: %s \n", device_uri); + fprintf(stderr, "XXX11: cfURI: %s \n", uri); + + // Check for "localhost" + if (strstr(uri, "localhost") != NULL) { + return FALSE; + } + + // Check for "::1" + if (strstr(uri, "::1") != NULL) { + return FALSE; + } + + // Check for IPv4 IP addresses starting with "127" + if (strncmp(uri, "127.", 4) == 0) { + return FALSE; + } + + // Check if the URI starts with "usb://" or "parallel://" + if (strncmp(uri, "usb://", 6) == 0 || strncmp(uri, "parallel://", 11) == 0) { + return FALSE; + } + + return checkRemote(uri); +} + char *extract_ipp_attribute(ipp_attribute_t *attr, int index, const char *option_name) { /** first deal with the totally unique cases **/ @@ -1817,13 +1982,13 @@ char *extract_orientation_from_ipp(ipp_attribute_t *attr, int index) void print_job(cups_job_t *j) { - printf("title : %s\n", j->title); - printf("dest : %s\n", j->dest); - printf("job-id : %d\n", j->id); - printf("user : %s\n", j->user); + logdebug("title : %s\n", j->title); + logdebug("dest : %s\n", j->dest); + logdebug("job-id : %d\n", j->id); + logdebug("user : %s\n", j->user); char *state = translate_job_state(j->state); - printf("state : %s\n", state); + logdebug("state : %s\n", state); } char *get_option_translation(PrinterCUPS *p, @@ -1850,7 +2015,7 @@ char *get_option_translation(PrinterCUPS *p, if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST) { /* request failed */ - printf("Request failed: %s\n", cupsLastErrorString()); + logerror("Request failed: %s\n", cupsLastErrorString()); return cpdbGetStringCopy(option_name); } @@ -1896,7 +2061,7 @@ char *get_choice_translation(PrinterCUPS *p, if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST) { /* request failed */ - printf("Request failed: %s\n", cupsLastErrorString()); + logerror("Request failed: %s\n", cupsLastErrorString()); return cpdbGetStringCopy(choice_name); } @@ -2002,7 +2167,7 @@ char *translate_job_state(ipp_jstate_t state) GVariant *pack_cups_job(cups_job_t job) { - printf("%s\n", job.dest); + logdebug("%s\n", job.dest); GVariant **t = g_new0(GVariant *, 7); char jobid[20]; snprintf(jobid, sizeof(jobid), "%d", job.id); @@ -2018,15 +2183,6 @@ GVariant *pack_cups_job(cups_job_t job) return tuple_variant; } -void MSG_LOG(const char *msg, int msg_level) -{ - if (MSG_LOG_LEVEL >= msg_level) - { - printf("%s\n", msg); - fflush(stdout); - } -} - void free_string(char *str) { if (str) diff --git a/src/backend_helper.h b/src/backend_helper.h index d8eb594..e5b5b6c 100644 --- a/src/backend_helper.h +++ b/src/backend_helper.h @@ -102,14 +102,6 @@ typedef struct _Media int (*margins)[4]; /** int margins[num_margins][4]; left(0), right(1), top(2), bottom(3) **/ } Media; -/* -typedef struct _PrintResult -{ - gchar *jobid; - gchar *socket; -} PrintResult; -*/ - typedef struct _PrintDataThreadData { PrinterCUPS *printer; int num_options; @@ -118,6 +110,11 @@ typedef struct _PrintDataThreadData { struct sockaddr_un server_addr; } PrintDataThreadData; +typedef struct _AddressList { + char ipstr[INET6_ADDRSTRLEN]; + int family; +} AddressList; + /********Backend related functions*******************/ /** Get a new BackendObj **/ @@ -154,7 +151,7 @@ void set_dialog_cancel(BackendObj *, const char *dialog_name); //make cancel = void reset_dialog_cancel(BackendObj *, const char *dialog_name); //make cancel = 1 /** Returns whether remote CUPS printers are hidden for this dialog **/ -gboolean get_hide_remote(BackendObj *b, char *dialog_name); +gboolean get_hide_remote(BackendObj *b, const char *dialog_name); /** Hides remote CUPS printers for the dialog **/ void set_hide_remote_printers(BackendObj *, const char *dialog_name); @@ -163,7 +160,7 @@ void set_hide_remote_printers(BackendObj *, const char *dialog_name); void unset_hide_remote_printers(BackendObj *, const char *dialog_name); /** Returns whether temporary CUPS Queues(discovered, but not set up) are hidden for this dialog **/ -gboolean get_hide_temp(BackendObj *b, char *dialog_name); +gboolean get_hide_temp(BackendObj *b, const char *dialog_name); /** Hides temporary CUPS queues for the dialog **/ void set_hide_temp_printers(BackendObj *, const char *dialog_name); @@ -205,7 +202,7 @@ void send_printer_removed_signal(BackendObj *b, const char *dialog_name, const c void notify_removed_printers(BackendObj *b, const char *dialog_name, GHashTable *new_table); void notify_added_printers(BackendObj *b, const char *dialog_name, GHashTable *new_table); void replace_printers(BackendObj *b, const char *dialog_name, GHashTable *new_table); -void refresh_printer_list(BackendObj *b, char *dialog_name); +void refresh_printer_list(BackendObj *b, const char *dialog_name); GHashTable *get_dialog_printers(BackendObj *b, const char *dialog_name); cups_dest_t *get_dest_by_name(BackendObj *b, const char *dialog_name, const char *printer_name); PrinterCUPS *get_printer_by_name(BackendObj *b, const char *dialog_name, const char *printer_name); @@ -239,6 +236,8 @@ static void *print_data_thread(void *data); void print_socket(PrinterCUPS *p, int num_settings, GVariant *settings, char *job_id_str, char *socket_path, const char *title); +gboolean checkRemote(const char *uri); +char *extractHostFromURI(const char *uri); /** * Get translation of choice name for a given locale */ @@ -279,6 +278,7 @@ GHashTable *cups_get_all_printers(); GHashTable *cups_get_local_printers(); char *cups_retrieve_string(cups_dest_t *dest, const char *option_name); gboolean cups_is_temporary(cups_dest_t *dest); +gboolean cups_is_remote(cups_dest_t *dest); GHashTable *cups_get_printers(gboolean notemp, gboolean noremote); char *extract_ipp_attribute(ipp_attribute_t *, int index, const char *option_name); char *extract_res_from_ipp(ipp_attribute_t *, int index); diff --git a/src/print_backend_cups.c b/src/print_backend_cups.c index 7066b57..8331d2b 100644 --- a/src/print_backend_cups.c +++ b/src/print_backend_cups.c @@ -32,7 +32,7 @@ void update_printer_lists() g_hash_table_iter_init(&iter, b->dialogs); while (g_hash_table_iter_next(&iter, &key, &value)) { - char *dialog_name = key; + const char *dialog_name = key; refresh_printer_list(b, dialog_name); } } @@ -47,7 +47,7 @@ on_printer_state_changed (CupsNotifier *object, gboolean printer_is_accepting_jobs, gpointer user_data) { - loginfo("Printer state change on printer %s: %s\n", printer, text); + logdebug("Printer state change on printer %s: %s\n", printer, text); GHashTableIter iter; gpointer key, value; @@ -73,7 +73,7 @@ on_printer_added (CupsNotifier *object, gboolean printer_is_accepting_jobs, gpointer user_data) { - loginfo("Printer added: %s\n", text); + logdebug("Printer added: %s\n", text); update_printer_lists(); } @@ -87,7 +87,7 @@ on_printer_deleted (CupsNotifier *object, gboolean printer_is_accepting_jobs, gpointer user_data) { - loginfo("Printer deleted: %s\n", text); + logdebug("Printer deleted: %s\n", text); update_printer_lists(); } @@ -166,7 +166,7 @@ on_name_acquired(GDBusConnection *connection, connect_to_dbus(b, CPDB_BACKEND_OBJ_PATH); } -static gboolean on_handle_get_printer_list(PrintBackend *interface, +static gboolean on_handle_get_all_printers(PrintBackend *interface, GDBusMethodInvocation *invocation, gpointer user_data) { @@ -189,7 +189,7 @@ static gboolean on_handle_get_printer_list(PrintBackend *interface, if (num_printers == 0) { printers = g_variant_new_array(G_VARIANT_TYPE ("(v)"), NULL, 0); - print_backend_complete_get_printer_list(interface, invocation, 0, printers); + print_backend_complete_get_all_printers(interface, invocation, 0, printers); return TRUE; } @@ -199,7 +199,7 @@ static gboolean on_handle_get_printer_list(PrintBackend *interface, { name = key; dest = value; - loginfo("Found printer : %s\n", name); + logdebug("Found printer : %s\n", name); info = cups_retrieve_string(dest, "printer-info"); location = cups_retrieve_string(dest, "printer-location"); make = cups_retrieve_string(dest, "printer-make-and-model"); @@ -218,7 +218,63 @@ static gboolean on_handle_get_printer_list(PrintBackend *interface, g_hash_table_destroy(table); printers = g_variant_builder_end(&builder); - print_backend_complete_get_printer_list(interface, invocation, num_printers, printers); + print_backend_complete_get_all_printers(interface, invocation, num_printers, printers); + return TRUE; +} + +static gboolean on_handle_get_filtered_printer_list(PrintBackend *interface, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + int num_printers; + GHashTableIter iter; + gpointer key, value; + GVariantBuilder builder; + GVariant *printer, *printers; + + cups_dest_t *dest; + gboolean accepting_jobs; + const char *state; + char *name, *info, *location, *make; + + const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); + GHashTable *table = cups_get_printers(get_hide_temp(b, dialog_name), get_hide_remote(b, dialog_name)); + + add_frontend(b, dialog_name); + num_printers = g_hash_table_size(table); + if (num_printers == 0) + { + printers = g_variant_new_array(G_VARIANT_TYPE ("(v)"), NULL, 0); + print_backend_complete_get_filtered_printer_list(interface, invocation, 0, printers); + return TRUE; + } + + g_hash_table_iter_init(&iter, table); + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + while (g_hash_table_iter_next(&iter, &key, &value)) + { + name = key; + dest = value; + logdebug("Found printer : %s\n", name); + info = cups_retrieve_string(dest, "printer-info"); + location = cups_retrieve_string(dest, "printer-location"); + make = cups_retrieve_string(dest, "printer-make-and-model"); + accepting_jobs = cups_is_accepting_jobs(dest); + state = cups_printer_state(dest); + add_printer_to_dialog(b, dialog_name, dest); + printer = g_variant_new(CPDB_PRINTER_ARGS, dest->name, dest->name, info, + location, make, accepting_jobs, state, BACKEND_NAME); + g_variant_builder_add(&builder, "(v)", printer); + free(key); + cupsFreeDests(1, value); + free(info); + free(location); + free(make); + } + g_hash_table_destroy(table); + printers = g_variant_builder_end(&builder); + + print_backend_complete_get_filtered_printer_list(interface, invocation, num_printers, printers); return TRUE; } @@ -242,7 +298,7 @@ static gboolean on_handle_get_all_translations(PrintBackend *interface, gpointer list_printers(gpointer _dialog_name) { - char *dialog_name = (char *)_dialog_name; + const char *dialog_name = (const char *)_dialog_name; g_message("New thread for dialog at %s\n", dialog_name); int *cancel = get_dialog_cancel(b, dialog_name); @@ -261,7 +317,7 @@ gpointer list_printers(gpointer _dialog_name) int send_printer_added(void *_dialog_name, unsigned flags, cups_dest_t *dest) { - char *dialog_name = (char *)_dialog_name; + const char *dialog_name = (const char *)_dialog_name; char *printer_name = dest->name; if (dialog_contains_printer(b, dialog_name, printer_name)) @@ -280,100 +336,74 @@ int send_printer_added(void *_dialog_name, unsigned flags, cups_dest_t *dest) return 1; //continue enumeration } -static void on_stop_backend(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer not_used) +static void on_handle_do_listing(PrintBackend *interface, + GDBusMethodInvocation *invocation, + gboolean is_listed, + gpointer not_used) { - g_message("Stop backend signal from %s\n", sender_name); - /** - * Ignore this signal if the dialog's keep_alive variable is set - */ - Dialog *d = find_dialog(b, sender_name); - if (d && d->keep_alive) - return; - set_dialog_cancel(b, sender_name); - remove_frontend(b, sender_name); - if (no_frontends(b)) - { - g_message("No frontends connected .. exiting backend.\n"); - exit(EXIT_SUCCESS); - } -} + if(!is_listed){ + const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); + Dialog *d = find_dialog(b, dialog_name); + if (d && d->keep_alive) + return; -static void on_hide_remote_printers(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer not_used) -{ - char *dialog_name = cpdbGetStringCopy(sender_name); - g_message("%s signal from %s\n", CPDB_SIGNAL_HIDE_REMOTE, dialog_name); - if (!get_hide_remote(b, dialog_name)) - { set_dialog_cancel(b, dialog_name); - set_hide_remote_printers(b, dialog_name); - refresh_printer_list(b, dialog_name); + remove_frontend(b, dialog_name); + if (no_frontends(b)) + { + g_message("No frontends connected .. exiting backend.\n"); + exit(EXIT_SUCCESS); + } } } -static void on_unhide_remote_printers(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer not_used) +static void on_handle_show_remote_printers(PrintBackend *interface, + GDBusMethodInvocation *invocation, + gboolean is_visible, + gpointer not_used) { - char *dialog_name = cpdbGetStringCopy(sender_name); - g_message("%s signal from %s\n", CPDB_SIGNAL_UNHIDE_REMOTE, dialog_name); - if (get_hide_remote(b, dialog_name)) - { - set_dialog_cancel(b, dialog_name); - unset_hide_remote_printers(b, dialog_name); - refresh_printer_list(b, dialog_name); + const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); + if (!is_visible){ + if (!get_hide_remote(b, dialog_name)) + { + set_dialog_cancel(b, dialog_name); + set_hide_remote_printers(b, dialog_name); + refresh_printer_list(b, dialog_name); + } } -} - -static void on_hide_temp_printers(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer not_used) -{ - char *dialog_name = cpdbGetStringCopy(sender_name); - g_message("%s signal from %s\n", CPDB_SIGNAL_HIDE_TEMP, dialog_name); - if (!get_hide_temp(b, dialog_name)) - { - set_dialog_cancel(b, dialog_name); - set_hide_temp_printers(b, dialog_name); - refresh_printer_list(b, dialog_name); + else if (is_visible){ + if (get_hide_remote(b, dialog_name)) + { + set_dialog_cancel(b, dialog_name); + unset_hide_remote_printers(b, dialog_name); + refresh_printer_list(b, dialog_name); + } } } -static void on_unhide_temp_printers(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, + +static void on_handle_show_temporary_printers(PrintBackend *interface, + GDBusMethodInvocation *invocation, + gboolean is_visible, gpointer not_used) { - char *dialog_name = cpdbGetStringCopy(sender_name); - g_message("%s signal from %s\n", CPDB_SIGNAL_UNHIDE_TEMP, dialog_name); - if (get_hide_temp(b, dialog_name)) - { - set_dialog_cancel(b, dialog_name); - unset_hide_temp_printers(b, dialog_name); - refresh_printer_list(b, dialog_name); + const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); + if (!is_visible){ + if (!get_hide_temp(b, dialog_name)) + { + set_dialog_cancel(b, dialog_name); + set_hide_temp_printers(b, dialog_name); + refresh_printer_list(b, dialog_name); + } + } + else if (is_visible){ + if (get_hide_temp(b, dialog_name)) + { + set_dialog_cancel(b, dialog_name); + unset_hide_temp_printers(b, dialog_name); + refresh_printer_list(b, dialog_name); + } } } @@ -397,7 +427,7 @@ static gboolean on_handle_get_printer_state(PrintBackend *interface, const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); /// potential risk PrinterCUPS *p = get_printer_by_name(b, dialog_name, printer_name); const char *state = get_printer_state(p); - printf("%s is %s\n", printer_name, state); + logdebug("%s is %s\n", printer_name, state); print_backend_complete_get_printer_state(interface, invocation, state); return TRUE; } @@ -457,7 +487,6 @@ static gboolean on_handle_ping(PrintBackend *interface, const char *dialog_name = g_dbus_method_invocation_get_sender(invocation); /// potential risk PrinterCUPS *p = get_printer_by_name(b, dialog_name, printer_name); print_backend_complete_ping(interface, invocation); - tryPPD(p); return TRUE; } @@ -528,7 +557,7 @@ static gboolean on_handle_get_default_printer(PrintBackend *interface, gpointer user_data) { char *def = get_default_printer(b); - printf("%s\n", def); + logdebug("%s\n", def); print_backend_complete_get_default_printer(interface, invocation, def); return TRUE; } @@ -563,8 +592,12 @@ void connect_to_signals() { PrintBackend *skeleton = b->skeleton; g_signal_connect(skeleton, //instance - "handle-get-printer-list", //signal name - G_CALLBACK(on_handle_get_printer_list), //callback + "handle-get-filtered-printer-list", //signal name + G_CALLBACK(on_handle_get_filtered_printer_list), //callback + NULL); + g_signal_connect(skeleton, //instance + "handle-get-all-printers", //signal name + G_CALLBACK(on_handle_get_all_printers), //callback NULL); g_signal_connect(skeleton, //instance "handle-get-all-options", //signal name @@ -586,6 +619,18 @@ void connect_to_signals() "handle-get-printer-state", //signal name G_CALLBACK(on_handle_get_printer_state), //callback NULL); + g_signal_connect(skeleton, //instance + "handle-do-listing", //signal name + G_CALLBACK(on_handle_do_listing), //callback + NULL); + g_signal_connect(skeleton, //instance + "handle-show-remote-printers", //signal name + G_CALLBACK(on_handle_show_remote_printers), //callback + NULL); + g_signal_connect(skeleton, //instance + "handle-show-temporary-printers", //signal name + G_CALLBACK(on_handle_show_temporary_printers), //callback + NULL); g_signal_connect(skeleton, //instance "handle-is-accepting-jobs", //signal name G_CALLBACK(on_handle_is_accepting_jobs), //callback @@ -614,54 +659,5 @@ void connect_to_signals() "handle-get-all-translations", G_CALLBACK(on_handle_get_all_translations), NULL); - g_dbus_connection_signal_subscribe(b->dbus_connection, - NULL, //Sender name - "org.openprinting.PrintFrontend", //Sender interface - CPDB_SIGNAL_STOP_BACKEND, //Signal name - NULL, /**match on all object paths**/ - NULL, /**match on all arguments**/ - 0, //Flags - on_stop_backend, //callback - NULL, //user_data - NULL); - g_dbus_connection_signal_subscribe(b->dbus_connection, - NULL, //Sender name - "org.openprinting.PrintFrontend", //Sender interface - CPDB_SIGNAL_HIDE_REMOTE, //Signal name - NULL, /**match on all object paths**/ - NULL, /**match on all arguments**/ - 0, //Flags - on_hide_remote_printers, //callback - NULL, //user_data - NULL); - g_dbus_connection_signal_subscribe(b->dbus_connection, - NULL, //Sender name - "org.openprinting.PrintFrontend", //Sender interface - CPDB_SIGNAL_UNHIDE_REMOTE, //Signal name - NULL, /**match on all object paths**/ - NULL, /**match on all arguments**/ - 0, //Flags - on_unhide_remote_printers, //callback - NULL, //user_data - NULL); - g_dbus_connection_signal_subscribe(b->dbus_connection, - NULL, //Sender name - "org.openprinting.PrintFrontend", //Sender interface - CPDB_SIGNAL_HIDE_TEMP, //Signal name - NULL, /**match on all object paths**/ - NULL, /**match on all arguments**/ - 0, //Flags - on_hide_temp_printers, //callback - NULL, //user_data - NULL); - g_dbus_connection_signal_subscribe(b->dbus_connection, - NULL, //Sender name - "org.openprinting.PrintFrontend", //Sender interface - CPDB_SIGNAL_UNHIDE_TEMP, //Signal name - NULL, /**match on all object paths**/ - NULL, /**match on all arguments**/ - 0, //Flags - on_unhide_temp_printers, //callback - NULL, //user_data - NULL); + } diff --git a/src/run-tests.sh b/src/run-tests.sh index 08ba6ba..226e0ab 100755 --- a/src/run-tests.sh +++ b/src/run-tests.sh @@ -653,4 +653,4 @@ echo "SUCCESS: All tests were successful." echo "" RES=0 -exit 0 +exit $RES