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