pax_global_header00006660000000000000000000000064132137555430014522gustar00rootroot0000000000000052 comment=afb6b119632b455f38a0b6f5c38079663aeb2e7e cpdb-backend-gcp-1.0.0/000077500000000000000000000000001321375554300145645ustar00rootroot00000000000000cpdb-backend-gcp-1.0.0/.gitignore000066400000000000000000000003641321375554300165570ustar00rootroot00000000000000*.o *.pdf gcp .vscode/ .gdb_history gmon.out Makefile.in .gitignore aclocal.m4 Makefile */Makefile depcomp install-sh missing aclocal.* compile autom4* config.log config.status configure data/org.openprinting.Backend.GCP.service src/.deps tmp/ cpdb-backend-gcp-1.0.0/LICENSE.md000066400000000000000000000020641321375554300161720ustar00rootroot00000000000000# MIT LICENSE ## Copyright (c) 2017 Abhijeet Dubey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cpdb-backend-gcp-1.0.0/Makefile.am000066400000000000000000000000561321375554300166210ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign SUBDIRS = src data cpdb-backend-gcp-1.0.0/README.md000066400000000000000000000035651321375554300160540ustar00rootroot00000000000000# Google Cloud Print Common Print Dialog Backend This repository hosts the code for the Google Cloud Print **C**ommon **P**rint **D**ialog **B**ackend. This backend manages and provides information about Google Cloud Print printing destinations to the printing dialog. ## Background The [Common Printing Dialog](https://wiki.ubuntu.com/CommonPrintingDialog) project aims to provide a uniform, GUI toolkit independent printing experience on Linux Desktop Environments. ## Dependencies ### For building the backend - [cpdb-libs](https://github.com/OpenPrinting/cpdb-libs) - GLIB 2.0: `sudo apt install libglib2.0-dev` - REST 0.7: `sudo apt install librest-dev` - JSON-GLIB 1.0: `sudo apt install libjson-glib-dev` - GOA 1.0: `sudo apt install libgoa-1.0-dev` ### For setting up the GNOME online account - GNOME Control Center and GNOME Online Accounts sudo apt install gnome-control-center gnome-online-accounts ## Build and installation $ ./autogen.sh $ ./configure $ make $ sudo make install ## Following the development and updating The current source code you find on the [OpenPrinting GitHub](https://github.com/OpenPrinting/cpdb-backend-gcp). ## Running Set up your GNOME online account for Google access by following the first answer to [this user question](https://askubuntu.com/questions/838956/ubuntu-16-04-set-up-with-google-online-account-but-no-drive-folder-in-nautilus). Then the backend will list your Google Cloud Print printers and your Google Drive in the print dialog as long as you are logged in. For users not setting up their GNOME online account the backend will not show any destination. The backend is auto-activated when a frontend runs; So no need to run it explicitly. ## More info [Abhijeet Dubey's Google Summer of Code 2017 Final Report](https://github.com/dracarys09/gcp-backend/wiki/1.-Google-Summer-of-Code-2017-%7C-Common-Printing-Dialog) cpdb-backend-gcp-1.0.0/autogen.sh000077500000000000000000000000761321375554300165700ustar00rootroot00000000000000#! /bin/sh aclocal \ && automake --add-missing \ && autoconf cpdb-backend-gcp-1.0.0/configure.ac000066400000000000000000000025201321375554300170510ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([cpdb-backend-gcp],[1.0.0],[dubey.abhijeet09@gmail.com],[CPDB - Google Cloud Print Backend], [https://github.com/OpenPrinting/cpdb-backend-gcp]) AM_INIT_AUTOMAKE([-Wall foreign]) AC_CONFIG_SRCDIR([src/gcp.c]) : ${CFLAGS=""} # Check for a C compiler AC_PROG_CC # Checks for backend library PKG_CHECK_MODULES([CPDBBACKEND],[cpdb-libs-backend >= 1]) PKG_CHECK_MODULES([GIO],[gio-2.0]) PKG_CHECK_MODULES([GIOUNIX],[gio-unix-2.0]) PKG_CHECK_MODULES([GLIB],[glib-2.0]) PKG_CHECK_MODULES([GOBJECT],[gobject-2.0]) PKG_CHECK_MODULES([REST],[rest-0.7]) PKG_CHECK_MODULES([JSONGLIB],[json-glib-1.0]) PKG_CHECK_MODULES([GOA],[goa-1.0]) # Checks for header files. AC_CHECK_HEADERS([stdlib.h string.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T # Checks for library functions AC_FUNC_MALLOC # The Dbus service directory DBUS_SERVICES_DIR="/usr/share/dbus-1/services" AC_SUBST(DBUS_SERVICES_DIR) # The info directory which will be read by the frontend INFO_DIR="/usr/share/print-backends" AC_SUBST(INFO_DIR) # The directory for the backend executables CPDB_BACKEND_DIR="$libdir/print-backends" AC_SUBST(CPDB_BACKEND_DIR) AC_OUTPUT([Makefile src/Makefile data/Makefile]) cpdb-backend-gcp-1.0.0/data/000077500000000000000000000000001321375554300154755ustar00rootroot00000000000000cpdb-backend-gcp-1.0.0/data/Makefile.am000066400000000000000000000006141321375554300175320ustar00rootroot00000000000000# Dbus service file servicedir = $(DBUS_SERVICES_DIR) service_in_files = org.openprinting.Backend.GCP.service.in service_DATA = $(service_in_files:.service.in=.service) $(service_DATA): $(service_in_files) Makefile @sed -e "s|\@cpdb_backend_dir\@|$(CPDB_BACKEND_DIR)|" $<> $@ info_backenddir = $(INFO_DIR) info_backend_DATA = org.openprinting.Backend.GCP clean-local: rm -rf $(service_DATA) cpdb-backend-gcp-1.0.0/data/org.openprinting.Backend.GCP000066400000000000000000000000021321375554300226500ustar00rootroot00000000000000/ cpdb-backend-gcp-1.0.0/data/org.openprinting.Backend.GCP.service.in000066400000000000000000000001161321375554300247220ustar00rootroot00000000000000[D-BUS Service] Name=org.openprinting.Backend.GCP Exec=@cpdb_backend_dir@/gcp cpdb-backend-gcp-1.0.0/src/000077500000000000000000000000001321375554300153535ustar00rootroot00000000000000cpdb-backend-gcp-1.0.0/src/Makefile.am000066400000000000000000000011731321375554300174110ustar00rootroot00000000000000backenddir = $(CPDB_BACKEND_DIR) backend_PROGRAMS = gcp gcp_SOURCES = gcp.c gcp_server.c common_helper.c gcp_CPPFLAGS = $(CPDBBACKEND_CFLAGS) gcp_CPPFLAGS += $(GLIB_CFLAGS) gcp_CPPFLAGS += $(GIO_CFLAGS) gcp_CPPFLAGS += $(GIOUNIX_CFLAGS) gcp_CPPFLAGS += $(GOBJECT_CFLAGS) gcp_CPPFLAGS += $(REST_CFLAGS) gcp_CPPFLAGS += $(JSONGLIB_CFLAGS) gcp_CPPFLAGS += $(GOA_CFLAGS) gcp_LDADD = $(CPDBBACKEND_LIBS) gcp_LDADD += -lcups -lpthread -lm -lcrypt gcp_LDADD += $(GLIB_LIBS) gcp_LDADD += $(GIO_LIBS) gcp_LDADD += $(GIOUNIX_LIBS) gcp_LDADD += $(GOBJECT_LIBS) gcp_LDADD += $(REST_LIBS) gcp_LDADD += $(JSONGLIB_LIBS) gcp_LDADD += $(GOA_LIBS) cpdb-backend-gcp-1.0.0/src/client.c000066400000000000000000000104321321375554300167750ustar00rootroot00000000000000#include "common_helper.h" #include int main () { GError *error = NULL; PrintBackend *proxy; GVariant *dict; error = NULL; proxy = print_backend_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, 0, "org.openprinting.Backend.GCP", "/", NULL, &error); error = NULL; g_print ("\n\n*******Get Backend Name*******\n\n"); error = NULL; gchar *backend_name; print_backend_call_get_backend_name_sync (proxy, &backend_name, NULL, &error); g_print ("Backend Name => %s\n", backend_name); g_print ("\n\n*******Testing Submit Print File*******\n\n"); error = NULL; // gchar *test_printer_id = g_strdup ("0ec6dd1e-f113-615c-5283-54ac7c389049"); gchar *test_printer_id = g_strdup ("__google__docs"); gchar *file_path_name = g_strdup ("/home/abhi/Desktop/fee.pdf"); gint num_settings = 0; GVariant *settings; gchar *out_job_id; GVariantBuilder *builder; builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)")); g_variant_builder_add (builder, "(ss)", "setting1_name", "setting1_value"); g_variant_builder_add (builder, "(ss)", "setting2_name", "setting2_value"); settings = g_variant_builder_end (builder); print_backend_call_print_file_sync (proxy, test_printer_id, file_path_name, num_settings, settings, &out_job_id, NULL, &error); g_print ("Out job id => %s\n", out_job_id); g_print ("\n\n*******Activate Backend*******\n\n"); error = NULL; print_backend_call_activate_backend_sync (proxy, NULL, &error); g_print ("\n\n*******List of Print Jobs*******\n\n"); error = NULL; GVariant *print_jobs_dict; gint num_jobs; print_backend_call_get_all_jobs_sync (proxy, FALSE, &num_jobs, &print_jobs_dict, NULL, &error); GVariantIter *iter; g_variant_get(print_jobs_dict, "a(ssssssi)", &iter); int size; char *jobid, *title, *printer, *user, *state, *submit_time; for (int i = 0; i < num_jobs ; i++) { g_variant_iter_loop(iter, "(ssssssi)", &jobid, &title, &printer , &user, &state, &submit_time , &size); g_print ("%s\n",jobid); g_print ("%s\n",title); g_print ("%s\n",printer); g_print ("%s\n",user); g_print ("%s\n",state); g_print ("%s\n",submit_time); g_print ("%d\n",size); } g_variant_iter_free (iter); gchar *job_id = g_malloc (50); gchar *printer_id = g_malloc (50); g_print ("Enter id of the job that you want to cancel:\n"); scanf ("%s", job_id); g_print ("Enter id of the printer:\n"); scanf ("%s", printer_id); g_print ("\n\n*******Test Delete Print Job*******\n\n"); gboolean delete_job_status; print_backend_call_cancel_job_sync (proxy, job_id, printer_id, &delete_job_status, NULL, &error); g_print ("*******Delete Job Status*******\n"); g_print ("%d\n", delete_job_status); g_print ("Enter id of printer to get printer status:\n"); scanf ("%s", printer_id); error = NULL; gchar *printer_status; print_backend_call_get_printer_state_sync (proxy, printer_id, &printer_status, NULL, &error); g_print ("*******Printer Status*******\n"); g_print ("%s => %s\n\n", printer_id, printer_status); g_print ("Enter id of printer to check if printer is accepting jobs:\n"); scanf ("%s", printer_id); error = NULL; gboolean is_accepting_jobs; print_backend_call_is_accepting_jobs_sync (proxy, printer_id, &is_accepting_jobs, NULL, &error); g_print ("*******Is Accepting Jobs*******\n"); g_print ("%s => %d\n\n", printer_id, is_accepting_jobs); g_print ("Enter id of printer to get printer options:\n"); scanf ("%s", printer_id); g_print ("\n\n*******List of Printer Options*******\n\n"); error = NULL; GVariant *vendor_capability_dict; gint num_options; print_backend_call_get_all_options_sync (proxy, printer_id, &num_options, &vendor_capability_dict, NULL, &error); char *str; GVariantIter *array_iter; char *name, *default_val; int num_sup; g_variant_get(vendor_capability_dict, "a(ssia(s))", &iter); for (int i = 0; i < num_options; i++) { g_variant_iter_loop(iter, "(ssia(s))", &name, &default_val, &num_sup, &array_iter); g_print ("%s\n", name); g_print ("%s\n", default_val); g_print ("%d\n", num_sup); for (int j = 0; j < num_sup; j++) { g_variant_iter_loop(array_iter, "(s)", &str); g_print ("value: %s\n", str); } } g_object_unref(proxy); return 0; } cpdb-backend-gcp-1.0.0/src/common_helper.c000066400000000000000000000366541321375554300203640ustar00rootroot00000000000000#include "common_helper.h" gboolean make_api_request (RestProxy *proxy, RestProxyCall **call, const gchar *method, const gchar *function, const gchar *header, const gchar *header_value, ... ) { GError *error = NULL; va_list params; rest_proxy_call_set_method (*call, method); rest_proxy_call_set_function (*call, function); rest_proxy_call_add_header (*call, header, header_value); va_start (params, header_value); rest_proxy_call_add_params_from_valist (*call, params); va_end (params); gboolean res = rest_proxy_call_run (*call, NULL, &error); /* TODO: Error handling in case something goes wrong. */ return res; } JsonObject *json_data_get_root (const gchar *data) { JsonParser *parser = json_parser_new (); JsonNode *root; JsonObject *jobject; GError *error = NULL; json_parser_load_from_data (parser, data, -1, &error); if (error) { g_print ("Unable to parse json: %s\n", error->message); g_error_free (error); g_object_unref (parser); return NULL; } root = json_parser_get_root (parser); g_assert (root != NULL); jobject = json_node_get_object (root); return jobject; } JsonArray *get_array_from_json_object (JsonObject *jobject, const gchar *name) { g_assert (json_object_has_member (jobject, name) == TRUE); JsonArray *jarr = json_object_get_array_member (jobject, name); g_assert (jarr != NULL); return jarr; } GList *get_glist_for_string_member_in_json_array (JsonArray *jarray, const gchar *name) { GList *glist = NULL; guint len = json_array_get_length (jarray); guint index; for (index = 0; indexdata); g_assert (jobject != NULL); g_assert (json_object_has_member (jobject, id) == TRUE); g_assert (json_object_has_member (jobject, name) == TRUE); g_assert (json_object_has_member (jobject, description) == TRUE); const gchar *id_ = json_object_get_string_member (jobject, id); const gchar *name_ = json_object_get_string_member (jobject, name); const gchar *description_ = json_object_get_string_member (jobject, description); printer *printer_struct = g_malloc(sizeof (printer)); printer_struct->id = g_strdup(id_); printer_struct->name = g_strdup(name_); if (g_strcmp0(description_, g_strdup("")) == 0) { printer_struct->description = g_strdup("NA"); } else { printer_struct->description = g_strdup(description_); } printer_struct->location = g_strdup("NA"); printer_struct->make_and_model = g_strdup("NA"); JsonArray *tags_array = get_array_from_json_object (jobject, "tags"); GList *tags_json_nodes = json_array_get_elements (tags_array); int i = 0; while (tags_json_nodes != NULL) { const gchar *str_element = json_array_get_string_element (tags_array, i); gchar *loc_pointer = g_strrstr (str_element, "__cp__printer-location"); if (loc_pointer != NULL) { printer_struct->location = g_strdup(loc_pointer+(strlen("__cp__printer-location")+1)); } loc_pointer = g_strrstr (str_element, "__cp__printer-make-and-model"); if (loc_pointer != NULL) { printer_struct->make_and_model = g_strdup(loc_pointer+(strlen("__cp__printer-make-and-model")+1)); } i++; tags_json_nodes = tags_json_nodes->next; } printer_structs_list = g_list_append (printer_structs_list, (gpointer)printer_struct); jnodes = jnodes->next; } return printer_structs_list; } gboolean get_access_token (gchar **out_access_token, gint *out_expires_in, GError **error) { GoaClient *client = goa_client_new_sync (NULL, error); GList *accounts, *l; GoaOAuth2Based *oauth2; accounts = goa_client_get_accounts (client); for (l = accounts; l != NULL; l = l->next) { GoaObject *object = GOA_OBJECT (l->data); GoaAccount *account = goa_object_peek_account (object); if ((g_strcmp0 (goa_account_get_provider_type (account), "google") == 0) && !goa_account_get_printers_disabled (account)) { oauth2 = goa_object_get_oauth2_based (object); break; } } if (!oauth2) { return FALSE; } *error = NULL; gboolean res = goa_oauth2_based_call_get_access_token_sync (oauth2, out_access_token, out_expires_in, NULL, error); return res; } GList *get_media_size_options (JsonArray *jarray) { GList *media_size_options = NULL; GList *media_size_nodes = json_array_get_elements (jarray); while (media_size_nodes != NULL) { JsonObject *jobject = json_node_get_object (media_size_nodes->data); g_assert (jobject != NULL); g_assert (json_object_has_member (jobject, "height_microns") == TRUE); g_assert (json_object_has_member (jobject, "width_microns") == TRUE); g_assert (json_object_has_member (jobject, "is_continuous_feed") == TRUE); g_assert (json_object_has_member (jobject, "is_default") == TRUE); g_assert (json_object_has_member (jobject, "vendor_id") == TRUE); g_assert (json_object_has_member (jobject, "name") == TRUE); g_assert (json_object_has_member (jobject, "custom_display_name") == TRUE); gint64 height_microns = json_object_get_int_member (jobject, "height_microns"); gint64 width_microns = json_object_get_int_member (jobject, "width_microns"); gboolean is_continuous_feed = json_object_get_boolean_member (jobject, "is_continuous_feed"); gboolean is_default = json_object_get_boolean_member (jobject, "is_default"); const gchar *vendor_id = json_object_get_string_member (jobject, "vendor_id"); const gchar *name = json_object_get_string_member (jobject, "name"); const gchar *custom_display_name = json_object_get_string_member (jobject, "custom_display_name"); media_size *media = g_malloc (sizeof (media_size)); media->height_microns = height_microns; media->width_microns = width_microns; media->is_continuous_feed = is_continuous_feed; media->is_default = is_default; media->vendor_id = g_strdup (vendor_id); media->name = g_strdup (name); media->custom_display_name = g_strdup (custom_display_name); media_size_options = g_list_append (media_size_options, (gpointer) media); media_size_nodes = media_size_nodes->next; } return media_size_options; } GList *get_google_docs_vendor_capability_options (JsonArray *jarray) { GList *vendor_capability_list = NULL; GList *vendor_capability_nodes = json_array_get_elements (jarray); while (vendor_capability_nodes != NULL) { JsonObject *jobject = json_node_get_object (vendor_capability_nodes->data); g_assert (jobject != NULL); g_assert (json_object_has_member (jobject, "id") == TRUE); g_assert (json_object_has_member (jobject, "display_name") == TRUE); g_assert (json_object_has_member (jobject, "type") == TRUE); g_assert (json_object_has_member (jobject, "typed_value_cap") == TRUE); const gchar *display_name = json_object_get_string_member (jobject, "display_name"); JsonNode *typed_value_cap_node = json_object_get_member (jobject, "typed_value_cap"); JsonObject *typed_value_cap_obj = json_node_get_object (typed_value_cap_node); const gchar *value_type = json_object_get_string_member (typed_value_cap_obj, "value_type"); vendor_capability *capabilities = g_malloc (sizeof (vendor_capability)); capabilities->display_name = g_strdup (display_name); capabilities->num_supported = 1; capabilities->options = NULL; const gchar *option_display_name = g_strdup ("Save to Google Drive"); gboolean option_is_default = TRUE; const gchar *value = g_strdup ("Save to Google Drive"); vendor_capability_option *vc_option = g_malloc (sizeof (vendor_capability_option)); vc_option->display_name = g_strdup (option_display_name); vc_option->is_default = option_is_default; vc_option->value = g_strdup (value); capabilities->options = g_list_append (capabilities->options, (gpointer)vc_option); capabilities->default_value = g_strdup("Save to Google Drive"); vendor_capability_list = g_list_append (vendor_capability_list, (gpointer)capabilities); vendor_capability_nodes = vendor_capability_nodes->next; } return vendor_capability_list; } GList *get_vendor_capability_options (JsonArray *jarray) { GList *vendor_capability_list = NULL; GList *vendor_capability_nodes = json_array_get_elements (jarray); while (vendor_capability_nodes != NULL) { JsonObject *jobject = json_node_get_object (vendor_capability_nodes->data); g_assert (jobject != NULL); g_assert (json_object_has_member (jobject, "id") == TRUE); g_assert (json_object_has_member (jobject, "display_name") == TRUE); g_assert (json_object_has_member (jobject, "type") == TRUE); g_assert (json_object_has_member (jobject, "select_cap") == TRUE); const gchar *display_name = json_object_get_string_member (jobject, "display_name"); JsonNode *select_cap_node = json_object_get_member (jobject, "select_cap"); JsonObject *select_cap_obj = json_node_get_object (select_cap_node); JsonArray *options = get_array_from_json_object (select_cap_obj, "option"); vendor_capability *capabilities = g_malloc (sizeof (vendor_capability)); capabilities->display_name = g_strdup (display_name); capabilities->num_supported = 0; capabilities->options = NULL; GList *option_list = json_array_get_elements (options); GList *values = NULL; while (option_list != NULL) { capabilities->num_supported++; JsonObject *option_obj = json_node_get_object (option_list->data); g_assert (option_obj != NULL); g_assert (json_object_has_member (option_obj, "display_name") == TRUE); g_assert (json_object_has_member (option_obj, "is_default") == TRUE); g_assert (json_object_has_member (option_obj, "value") == TRUE); const gchar *option_display_name = json_object_get_string_member (option_obj, "display_name"); gboolean option_is_default = json_object_get_boolean_member (option_obj, "is_default"); const gchar *value = json_object_get_string_member (option_obj, "value"); vendor_capability_option *vc_option = g_malloc (sizeof (vendor_capability_option)); vc_option->display_name = g_strdup (option_display_name); vc_option->is_default = option_is_default; vc_option->value = g_strdup (value); capabilities->options = g_list_append (capabilities->options, (gpointer)vc_option); if(option_is_default) capabilities->default_value = g_strdup(option_display_name); option_list = option_list->next; } vendor_capability_list = g_list_append (vendor_capability_list, (gpointer)capabilities); vendor_capability_nodes = vendor_capability_nodes->next; } return vendor_capability_list; } GList *get_print_jobs_list (JsonArray *jarray) { GList *print_jobs = json_array_get_elements (jarray); GList *print_jobs_list = NULL; while (print_jobs != NULL) { JsonObject *job_obj = json_node_get_object (print_jobs->data); g_assert (job_obj != NULL); g_assert (json_object_has_member (job_obj, "id") == TRUE); g_assert (json_object_has_member (job_obj, "title") == TRUE); g_assert (json_object_has_member (job_obj, "printerName") == TRUE); g_assert (json_object_has_member (job_obj, "ownerId") == TRUE); g_assert (json_object_has_member (job_obj, "status") == TRUE); g_assert (json_object_has_member (job_obj, "createTime") == TRUE); g_assert (json_object_has_member (job_obj, "numberOfPages") == TRUE); const gchar *id = json_object_get_string_member (job_obj, "id"); const gchar *title = json_object_get_string_member (job_obj, "title"); const gchar *printerName = json_object_get_string_member (job_obj, "printerName"); const gchar *ownerId = json_object_get_string_member (job_obj, "ownerId"); const gchar *status = json_object_get_string_member (job_obj, "status"); const gchar *createTime = json_object_get_string_member (job_obj, "createTime"); gint numberOfPages = json_object_get_int_member (job_obj, "numberOfPages"); print_job *print_job_struct = g_malloc (sizeof (print_job)); print_job_struct->id = g_strdup (id); print_job_struct->title = g_strdup (title); print_job_struct->printerName = g_strdup (printerName); print_job_struct->user = g_strdup (ownerId); print_job_struct->status = g_strdup (status); print_job_struct->submitted_at = g_strdup (createTime); print_job_struct->size = numberOfPages; print_jobs_list = g_list_append (print_jobs_list, (gpointer)print_job_struct); print_jobs = print_jobs->next; } return print_jobs_list; } void connect_to_dbus (GDBusConnection *connection, PrintBackend *skeleton, gchar *obj_path) { GError *error = NULL; g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, obj_path, &error); g_assert_no_error(error); } gchar *get_printer_state_from_printers_array (JsonArray *jarray, const gchar *uid) { GList *jnodes = json_array_get_elements (jarray); gchar *printer_state; while (jnodes != NULL) { JsonObject *jobject = json_node_get_object (jnodes->data); g_assert (jobject != NULL); g_assert (json_object_has_member (jobject, "id") == TRUE); g_assert (json_object_has_member (jobject, "connectionStatus") == TRUE); const gchar *id_ = json_object_get_string_member (jobject, "id"); const gchar *connectionStatus = json_object_get_string_member (jobject, "connectionStatus"); if(g_strcmp0 (id_, uid) == 0) { printer_state = g_strdup (connectionStatus); break; } jnodes = jnodes->next; } return printer_state; } gboolean get_print_job_cancellation_status (JsonObject *jobject) { g_assert (json_object_has_member (jobject, "success") == TRUE); gboolean success_status = json_object_get_boolean_member (jobject, "success"); return success_status; } const gchar *get_job_id_for_submitted_job (JsonObject *jobject) { gboolean success_status = json_object_get_boolean_member (jobject, "success"); if (success_status) { JsonNode *job = json_object_get_member (jobject, "job"); JsonObject *job_object = json_node_get_object (job); const gchar *job_id = json_object_get_string_member (job_object, "id"); return job_id; } else { const gchar *job_id = "Error submitting job!"; return job_id; } } cpdb-backend-gcp-1.0.0/src/common_helper.h000066400000000000000000000056461321375554300203660ustar00rootroot00000000000000#ifndef COMMON_HELPER_H #define COMMON_HELPER_H #define GOA_API_IS_SUBJECT_TO_CHANGE #include #include #include #include #include #include #include #define PRINTER_ADDED_ARGS "(sssssbss)" #define PRINTER_ADDED_SIGNAL "PrinterAdded" #define REFRESH_BACKEND_SIGNAL "RefreshBackend" #define PRINTER_REMOVED_SIGNAL "PrinterRemoved" #define STOP_BACKEND_SIGNAL "StopListing" typedef struct media_size{ gint height_microns; gint width_microns; gboolean is_continuous_feed; gboolean is_default; gchar *vendor_id; gchar *name; gchar *custom_display_name; } media_size; typedef struct vendor_capability_option{ gchar *display_name; gboolean is_default; gchar *value; } vendor_capability_option; typedef struct vendor_capability{ gchar *display_name; gchar *default_value; gint num_supported; GList *options; } vendor_capability; typedef struct print_job{ gchar *id; gchar *title; gchar *printerName; gchar *user; gchar *status; gchar *submitted_at; int size; } print_job; typedef struct printer{ gchar *id; gchar *name; gchar *description; gchar *location; gchar *make_and_model; } printer; gboolean make_api_request (RestProxy *proxy, RestProxyCall **call, const gchar *method, const gchar *function, const gchar *header, const gchar *header_value, ... ); JsonObject *json_data_get_root (const gchar *data); JsonArray *get_array_from_json_object (JsonObject *jobject, const gchar *name); GList *get_glist_for_string_member_in_json_array (JsonArray *jarray, const gchar *name); gboolean get_access_token (gchar **out_access_token, gint *out_expires_in, GError **error); GList *get_printer_struct_from_json_array (JsonArray *jarray, const gchar *id, const gchar *name, const gchar *description); GList *get_media_size_options (JsonArray *jarray); GList *get_vendor_capability_options (JsonArray *array); GList *get_google_docs_vendor_capability_options (JsonArray *jarray); GList *get_print_jobs_list (JsonArray *jarray); gchar *get_printer_state_from_printers_array (JsonArray *jarray, const gchar *uid); gboolean get_print_job_cancellation_status (JsonObject *jobject); const gchar *get_job_id_for_submitted_job (JsonObject *jobject); void connect_to_dbus (GDBusConnection *connection, PrintBackend *skeleton, gchar *obj_path); #endif /* COMMON_HELPER_H */ cpdb-backend-gcp-1.0.0/src/gcp.c000066400000000000000000000354261321375554300163020ustar00rootroot00000000000000#include "gcp.h" G_DEFINE_TYPE (GCPObject, gcp_object, G_TYPE_OBJECT) /*****************************************************************************/ const gchar * gcp_object_real_get_printers (GCPObject *self, const gchar *access_token, const gchar *connection_status); const gchar * gcp_object_real_get_printer_options (GCPObject *self, const gchar *uid, const gchar *access_token); const gchar * gcp_object_real_submit_print_job (GCPObject *self, const gchar *uid, const gchar *access_token, const gchar *title, const gchar *file_path_name, const gchar *content_type, const gchar *ticket); const gchar * gcp_object_real_get_print_jobs (GCPObject *self, const gchar *access_token, const gchar *uid, const gchar *owner, const gchar *status, const gchar *sortorder); const gchar * gcp_object_real_cancel_print_job (GCPObject *self, const gchar *access_token, const gchar *job_id); /*****************************************************************************/ GCPObject * gcp_object_new() { return g_object_new (GCP_TYPE_OBJECT, NULL); } static void gcp_object_init (GCPObject *self) { } static void gcp_object_class_init (GCPObjectClass *klass) { GObjectClass *parent_class = G_OBJECT_CLASS (klass); klass->get_printers = gcp_object_real_get_printers; klass->get_printer_options = gcp_object_real_get_printer_options; klass->submit_print_job = gcp_object_real_submit_print_job; klass->get_print_jobs = gcp_object_real_get_print_jobs; klass->cancel_print_job = gcp_object_real_cancel_print_job; } GList * gcp_object_get_printers (GCPObject *self, const gchar *access_token, const gchar *connection_status) { g_return_val_if_fail (GCP_IS_OBJECT (self), NULL); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *printers = klass->get_printers (self, access_token, connection_status); JsonObject *jobject = json_data_get_root (printers); JsonArray *jarray = get_array_from_json_object (jobject, "printers"); GList *printer_struct_list = get_printer_struct_from_json_array (jarray, "id", "displayName", "description"); return printer_struct_list; } GList * gcp_object_get_media_size_options (GCPObject *self, const gchar *uid, const gchar *access_token) { g_return_val_if_fail (GCP_IS_OBJECT (self), NULL); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *printer_options_json = klass->get_printer_options (self, uid, access_token); JsonObject *root = json_data_get_root (printer_options_json); JsonArray *jarray = get_array_from_json_object (root, "printers"); JsonNode *jnode = json_array_get_element (jarray, 0); JsonObject *jobject = json_node_get_object (jnode); JsonNode *capabilities_node = json_object_get_member (jobject, "capabilities"); JsonObject *capabilities_obj = json_node_get_object (capabilities_node); JsonNode *printer_node = json_object_get_member (capabilities_obj, "printer"); JsonObject *printer_options = json_node_get_object (printer_node); JsonNode *media_size_node = json_object_get_member (printer_options, "media_size"); JsonObject *media_size_object = json_node_get_object (media_size_node); JsonArray *media_options_array = get_array_from_json_object (media_size_object, "option"); GList *media_size_options_list = get_media_size_options (media_options_array); return media_size_options_list; } GList * gcp_object_get_vendor_capability_options (GCPObject *self, const gchar *uid, const gchar *access_token) { g_return_val_if_fail (GCP_IS_OBJECT (self), NULL); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *printer_options_json = klass->get_printer_options (self, uid, access_token); JsonObject *root = json_data_get_root (printer_options_json); JsonArray *jarray = get_array_from_json_object (root, "printers"); JsonNode *jnode = json_array_get_element (jarray, 0); JsonObject *jobject = json_node_get_object (jnode); JsonNode *capabilities_node = json_object_get_member (jobject, "capabilities"); JsonObject *capabilities_obj = json_node_get_object (capabilities_node); JsonNode *printer_node = json_object_get_member (capabilities_obj, "printer"); JsonObject *printer_options = json_node_get_object (printer_node); JsonArray *vendor_capability_array = get_array_from_json_object (printer_options, "vendor_capability"); if(g_strcmp0 (uid, "__google__docs") == 0) return get_google_docs_vendor_capability_options (vendor_capability_array); else return get_vendor_capability_options (vendor_capability_array); } const gchar * gcp_object_submit_print_job (GCPObject *self, const gchar *uid, const gchar *access_token, const gchar *title, const gchar *file_path_name, const gchar *content_type, const gchar *ticket) { g_return_val_if_fail (GCP_IS_OBJECT (self), FALSE); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *res = klass->submit_print_job (self, uid, access_token, title, file_path_name, content_type, ticket); JsonObject *root = json_data_get_root (res); const gchar *job_id = get_job_id_for_submitted_job (root); return job_id; } GList * gcp_object_get_print_jobs (GCPObject *self, const gchar *access_token, const gchar *uid, const gchar *owner, const gchar *status, const gchar *sortorder) { g_return_val_if_fail (GCP_IS_OBJECT (self), NULL); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *printer_jobs = klass->get_print_jobs (self, access_token, uid, owner, status, sortorder); JsonObject *root = json_data_get_root (printer_jobs); JsonArray *jarray = get_array_from_json_object (root, "jobs"); GList *jobs_list = get_print_jobs_list (jarray); return jobs_list; } /*****************************************************************************/ const gchar * gcp_object_real_get_printers (GCPObject *self, const gchar *access_token, const gchar *connection_status) { RestProxy *proxy; RestProxyCall *call; const gchar *header = "X-CloudPrint-Proxy"; const gchar *header_value = "Common Printing Dialog"; const gchar *method = "GET"; const gchar *function = "search"; const gchar *param1_name = "access_token"; gboolean res = FALSE; proxy = rest_proxy_new ("https://www.google.com/cloudprint/", FALSE); call = rest_proxy_new_call (proxy); if (connection_status != NULL) res = make_api_request (proxy, &call, method, function, header, header_value, param1_name, access_token, "connection_status", connection_status, NULL); else res = make_api_request (proxy, &call, method, function, header, header_value, param1_name, access_token, NULL); const gchar *printers; if (res) { printers = rest_proxy_call_get_payload (call); } else { printers = g_strdup("API request failed!"); } /* TODO: Error handling in case something goes wrong. */ return printers; } const gchar * gcp_object_real_get_printer_options (GCPObject *self, const gchar *uid, const gchar *access_token) { RestProxy *proxy; RestProxyCall *call; const gchar *header = "X-CloudPrint-Proxy"; const gchar *header_value = "Common Printing Dialog"; const gchar *method = "GET"; const gchar *function = "printer"; const gchar *param1_name = "access_token"; const gchar *param2_name = "printerid"; gboolean res = FALSE; proxy = rest_proxy_new ("https://www.google.com/cloudprint/", FALSE); call = rest_proxy_new_call (proxy); res = make_api_request (proxy, &call, method, function, header, header_value, param1_name, access_token, param2_name, uid, NULL); const gchar *printer_options; if (res) { printer_options = rest_proxy_call_get_payload (call); } else { printer_options = g_strdup("API request failed!"); } /* TODO: Error handling in case something goes wrong. */ return printer_options; } const gchar * gcp_object_real_submit_print_job (GCPObject *self, const gchar *uid, const gchar *access_token, const gchar *title, const gchar *file_path_name, const gchar *content_type, const gchar *ticket) { /* TODO: Make api request to submit a file for printing. */ RestProxy *proxy; RestProxyCall *call; const gchar *header = "Authorization"; const gchar *header_value = "Common Printing Dialog"; const gchar *method = "GET"; const gchar *function = "submit"; const gchar *param_access_token = "access_token"; const gchar *param_printer_id = "printerid"; const gchar *param_title = "title"; const gchar *param_ticket = "ticket"; const gchar *param_content = "content"; const gchar *param_content_type = "contentType"; gboolean res = FALSE; FILE *fp; fp=fopen(file_path_name, "r"); proxy = rest_proxy_new ("https://www.google.com/cloudprint/", FALSE); call = rest_proxy_new_call (proxy); res = make_api_request (proxy, &call, method, function, header, header_value, param_access_token, access_token, param_printer_id, uid, param_title, title, param_ticket, ticket, param_content, fp, param_content_type, content_type, NULL); const gchar *submit_print_job_status; if (res) { submit_print_job_status = rest_proxy_call_get_payload (call); } else { submit_print_job_status = g_strdup("API request failed!"); } /* TODO: Error handling in case something goes wrong. */ return submit_print_job_status; } const gchar * gcp_object_real_get_print_jobs (GCPObject *self, const gchar *access_token, const gchar *uid, const gchar *owner, const gchar *status, const gchar *sortorder) { RestProxy *proxy; RestProxyCall *call; const gchar *header = "X-CloudPrint-Proxy"; const gchar *header_value = "Common Printing Dialog"; const gchar *method = "GET"; const gchar *function = "jobs"; const gchar *param_access_token = "access_token"; const gchar *param_printer_id = "printerid"; const gchar *param_owner = "owner"; const gchar *param_status = "status"; const gchar *param_sortorder = "sortorder"; gboolean res = FALSE; proxy = rest_proxy_new ("https://www.google.com/cloudprint/", FALSE); call = rest_proxy_new_call (proxy); res = make_api_request (proxy, &call, method, function, header, header_value, param_access_token, access_token, param_printer_id, uid, param_owner, owner, param_status, status, param_sortorder, sortorder, NULL); const gchar *printer_jobs; if (res) { printer_jobs = rest_proxy_call_get_payload (call); } else { printer_jobs = g_strdup("API request failed!"); } /* TODO: Error handling in case something goes wrong. */ return printer_jobs; } const gchar * gcp_object_real_cancel_print_job (GCPObject *self, const gchar *access_token, const gchar *job_id) { RestProxy *proxy; RestProxyCall *call; const gchar *header = "Authorization"; const gchar *header_value = "Common Printing Dialog"; const gchar *method = "GET"; const gchar *function = "deletejob"; const gchar *param_access_token = "access_token"; const gchar *param_job_id = "jobid"; gboolean res = FALSE; proxy = rest_proxy_new ("https://www.google.com/cloudprint/", FALSE); call = rest_proxy_new_call (proxy); res = make_api_request (proxy, &call, method, function, header, header_value, param_access_token, access_token, param_job_id, job_id, NULL); const gchar *delete_job_status; if (res) { delete_job_status = rest_proxy_call_get_payload (call); } else { delete_job_status = g_strdup("API request failed!"); } /* TODO: Error handling in case something goes wrong. */ return delete_job_status; } gchar * gcp_object_get_printer_state (GCPObject *self, const gchar *access_token, const gchar *uid) { g_return_val_if_fail (GCP_IS_OBJECT (self), NULL); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *printers = klass->get_printers (self, access_token, "ALL"); JsonObject *jobject = json_data_get_root (printers); JsonArray *jarray = get_array_from_json_object (jobject, "printers"); gchar *printer_state = get_printer_state_from_printers_array (jarray, uid); return printer_state; } gboolean gcp_object_delete_print_job (GCPObject *self, const gchar *access_token, const gchar *job_id) { g_return_val_if_fail (GCP_IS_OBJECT (self), FALSE); GCPObjectClass *klass = GCP_OBJECT_GET_CLASS (self); const gchar *is_cancelled = klass->cancel_print_job (self, access_token, job_id); JsonObject *jobject = json_data_get_root (is_cancelled); gboolean job_cancel_status = get_print_job_cancellation_status (jobject); return job_cancel_status; } cpdb-backend-gcp-1.0.0/src/gcp.h000066400000000000000000000057131321375554300163030ustar00rootroot00000000000000#ifndef __GCP_H__ #define __GCP_H__ #include #include #include "common_helper.h" G_BEGIN_DECLS #define GCP_TYPE_OBJECT gcp_object_get_type() G_DECLARE_DERIVABLE_TYPE (GCPObject, gcp_object, GCP, OBJECT, GObject) struct _GCPObjectClass { GObjectClass parent; const gchar * (*get_printers) (GCPObject *, const gchar *, const gchar *); const gchar * (*get_printer_options) (GCPObject *, const gchar *, const gchar *); const gchar * (*submit_print_job) (GCPObject *, const gchar *, const gchar *, const gchar *, const gchar *, const gchar *, const gchar *); const gchar * (*get_print_jobs) (GCPObject *, const gchar *, const gchar *, const gchar *, const gchar *, const gchar *); const gchar * (*cancel_print_job) (GCPObject *, const gchar *, const gchar *); }; GCPObject * gcp_object_new (); GList * gcp_object_get_printers (GCPObject *self, const gchar *access_token, const gchar *connection_status); GList * gcp_object_get_media_size_options (GCPObject *self, const gchar *uid, const gchar *access_token); GList * gcp_object_get_vendor_capability_options (GCPObject *self, const gchar *uid, const gchar *access_token); const gchar * gcp_object_submit_print_job (GCPObject *self, const gchar *uid, const gchar *access_token, const gchar *title, const gchar *file_path_name, const gchar *content_type, const gchar *ticket); GList * gcp_object_get_print_jobs (GCPObject *self, const gchar *access_token, const gchar *uid, const gchar *owner, const gchar *status, const gchar *sortorder); gchar * gcp_object_get_printer_state (GCPObject *self, const gchar *access_token, const gchar *uid); gboolean gcp_object_delete_print_job (GCPObject *self, const gchar *access_token, const gchar *job_id); G_END_DECLS #endif /* GCP_H */ cpdb-backend-gcp-1.0.0/src/gcp_server.c000066400000000000000000000525351321375554300176700ustar00rootroot00000000000000#include #include #include "gcp_server.h" G_DEFINE_TYPE (ServerObject, server_object, G_TYPE_OBJECT) #define BUS_NAME "org.openprinting.Backend.GCP" #define OBJECT_PATH "/" BackendObj *b; ServerObject * server_object_new() { return g_object_new (SERVER_TYPE_OBJECT, NULL); } static void server_object_init (ServerObject *self) { } static void server_object_class_init (ServerObjectClass *klass) { GObjectClass *parent_class = G_OBJECT_CLASS (klass); acquire_session_bus_name (); } static void acquire_session_bus_name () { g_bus_own_name (G_BUS_TYPE_SESSION, BUS_NAME, 0, // Flags NULL, // bus acquired handler on_name_acquired, // name acquired handler NULL, // name lost handler NULL, // user_data NULL); // user_data_free_func g_print("acquire_session_bus_name"); } static void on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { g_print ("name acquired!\n"); b->dbus_connection = connection; PrintBackend *skeleton; skeleton = print_backend_skeleton_new (); connect_to_signals (skeleton); connect_to_dbus (connection, skeleton, OBJECT_PATH); } void connect_to_signals (PrintBackend *skeleton) { g_print ("connected to signals!\n"); g_signal_connect (skeleton, "handle_get_all_options", G_CALLBACK (on_handle_get_all_options), NULL); g_signal_connect (skeleton, "handle_get_all_jobs", G_CALLBACK (on_handle_get_all_jobs), NULL); g_signal_connect (skeleton, "handle_get_active_jobs_count", G_CALLBACK (on_handle_get_active_jobs_count), NULL); g_signal_connect (skeleton, "handle_get_printer_state", G_CALLBACK (on_handle_get_printer_state), NULL); g_signal_connect (skeleton, "handle_is_accepting_jobs", G_CALLBACK (on_handle_is_accepting_jobs), NULL); g_signal_connect (skeleton, "handle_cancel_job", G_CALLBACK (on_handle_cancel_job), NULL); g_signal_connect (skeleton, "handle_activate_backend", G_CALLBACK (on_handle_activate_backend), NULL); g_signal_connect (skeleton, "handle_get_backend_name", G_CALLBACK (on_handle_get_backend_name), NULL); g_signal_connect (skeleton, "handle_print_file", G_CALLBACK (on_handle_print_file), NULL); g_dbus_connection_signal_subscribe (b->dbus_connection, NULL, //Sender name "org.openprinting.PrintFrontend", //Sender interface REFRESH_BACKEND_SIGNAL, //Signal name NULL, /**match on all object paths**/ NULL, /**match on all arguments**/ 0, //Flags on_refresh_backend, //callback NULL, //user_data NULL); g_dbus_connection_signal_subscribe (b->dbus_connection, NULL, //Sender name "org.openprinting.PrintFrontend", //Sender interface STOP_BACKEND_SIGNAL, //Signal name NULL, /**match on all object paths**/ NULL, /**match on all arguments**/ 0, //Flags on_stop_backend, //callback NULL, //user_data NULL); } static gboolean on_handle_get_all_options (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data) { g_print ("on_handle_get_all_options() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); GList *vendor_capability_options = gcp_object_get_vendor_capability_options (gcp, printer_id, access_token); GVariantBuilder *builder; guint count = g_list_length (vendor_capability_options); GVariant *vendor_capability_dict; builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ssia(s))")); while(vendor_capability_options != NULL) { vendor_capability *vc = vendor_capability_options->data; GList *options = vc->options; GVariantBuilder *str_array_builder; str_array_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); if (vc->num_supported == 0) g_variant_builder_add(str_array_builder, "(s)", "NA"); while (options != NULL) { vendor_capability_option *vc_option = options->data; g_variant_builder_add (str_array_builder, "(s)", vc_option->display_name); options = options->next; } GVariant **t = g_new (GVariant *, 4); t[0] = g_variant_new_string (vc->display_name); t[1] = g_variant_new_string (vc->default_value); t[2] = g_variant_new_int32 (vc->num_supported); t[3] = g_variant_new ("a(s)", str_array_builder); GVariant *tuple_variant = g_variant_new_tuple (t, 4); g_free (t); g_variant_builder_add_value (builder, tuple_variant); vendor_capability_options = vendor_capability_options->next; } vendor_capability_dict = g_variant_new ("a(ssia(s))", builder); print_backend_complete_get_all_options (skeleton, invocation, count, vendor_capability_dict); g_object_unref (gcp); return TRUE; } static gboolean on_handle_print_file (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, const gchar *file_path_name, gint num_settings, GVariant *settings, gpointer user_data) { g_print ("on_handle_print_file() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); const gchar *title = g_strconcat (printer_id, file_path_name, asctime (timeinfo), NULL); g_print ("title => %s\n",title); const gchar *content_type = "text/plain"; /* TODO: Create the actual print ticket from settings GVariant */ gchar *ticket = "{\ \"version\": \"1.0\",\ \"print\": {\ \"vendor_ticket_item\": [],\ \"color\": {\"type\": \"STANDARD_MONOCHROME\"},\ \"copies\": {\"copies\": 1}\ }\ }"; const gchar *job_id = gcp_object_submit_print_job (gcp, printer_id, access_token, title, file_path_name, content_type, ticket); print_backend_complete_print_file (skeleton, invocation, job_id); g_object_unref (gcp); return TRUE; } static gboolean on_handle_get_all_jobs (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gboolean active_only, gpointer user_data) { g_print ("on_handle_get_all_jobs() called\n"); gchar *uid = ""; gchar *owner = ""; gchar *status = ""; gchar *sortorder = ""; GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); GList *print_jobs = gcp_object_get_print_jobs (gcp, access_token, uid, owner, status, sortorder); GVariantBuilder *builder; GVariant *dict; gint num_jobs = 0; builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ssssssi)")); while(print_jobs != NULL) { print_job *job = print_jobs->data; if(active_only & g_strcmp0(job->status, "IN_PROGRESS") == 0) { g_variant_builder_add (builder, "(ssssssi)", job->id, job->title, job->printerName, job->user, job->status, job->submitted_at, job->size); } else { g_variant_builder_add (builder, "(ssssssi)", job->id, job->title, job->printerName, job->user, job->status, job->submitted_at, job->size); } num_jobs++; print_jobs = print_jobs->next; } dict = g_variant_builder_end (builder); print_backend_complete_get_all_jobs (skeleton, invocation, num_jobs, dict); g_object_unref (gcp); return TRUE; } static gboolean on_handle_get_active_jobs_count (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data) { g_print ("on_handle_get_active_jobs_count() called\n"); gchar *uid = ""; gchar *owner = ""; gchar *status = ""; gchar *sortorder = ""; GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); GList *print_jobs = gcp_object_get_print_jobs (gcp, access_token, uid, owner, status, sortorder); gint active_jobs_count = 0; while(print_jobs != NULL) { print_job *job = print_jobs->data; if(g_strcmp0(job->status, "IN_PROGRESS") == 0) active_jobs_count++; print_jobs = print_jobs->next; } print_backend_complete_get_active_jobs_count (skeleton, invocation, active_jobs_count); g_object_unref (gcp); return TRUE; } static gboolean on_handle_get_printer_state (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data) { g_print ("on_handle_get_printer_state() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); gchar *printer_state = gcp_object_get_printer_state (gcp, access_token, printer_id); print_backend_complete_get_printer_state (skeleton, invocation, printer_state); g_object_unref (gcp); return TRUE; } static gboolean on_handle_is_accepting_jobs (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data) { g_print ("on_handle_is_accepting_jobs() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); gboolean is_accepting_jobs = FALSE; gchar *printer_state = gcp_object_get_printer_state (gcp, access_token, printer_id); if(g_strcmp0 (printer_state, "ONLINE") == 0) is_accepting_jobs = TRUE; print_backend_complete_is_accepting_jobs (skeleton, invocation, is_accepting_jobs); g_object_unref (gcp); return TRUE; } static gboolean on_handle_cancel_job (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *job_id, const gchar *printer_id, gpointer user_data) { g_print ("on_handle_is_accepting_jobs() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); gboolean is_cancelled = gcp_object_delete_print_job (gcp, access_token, job_id); print_backend_complete_cancel_job (skeleton, invocation, is_cancelled); g_object_unref (gcp); return TRUE; } void emit_printer_removed_signal (const gchar *dialog_name, printer *printer_struct) { GError *error = NULL; g_dbus_connection_emit_signal(b->dbus_connection, dialog_name, "/", "org.openprinting.PrintBackend", PRINTER_REMOVED_SIGNAL, g_variant_new("(ss)", printer_struct->name, "GCP"), &error); g_assert_no_error(error); } void emit_printer_added_signal (GCPObject *gcp, const gchar *access_token, const gchar *dialog_name, printer *printer_struct) { GError *error = NULL; gboolean is_accepting_jobs = FALSE; gchar *printer_state = gcp_object_get_printer_state (gcp, access_token, printer_struct->id); if(g_strcmp0 (printer_state, "ONLINE") == 0) is_accepting_jobs = TRUE; GVariant *gv = g_variant_new(PRINTER_ADDED_ARGS, printer_struct->id, printer_struct->name, printer_struct->description, printer_struct->location, printer_struct->make_and_model, is_accepting_jobs, printer_state, "GCP"); error = NULL; g_dbus_connection_emit_signal(b->dbus_connection, dialog_name, // destination bus name (dialog_name) or NULL to emit to all "/", "org.openprinting.PrintBackend", PRINTER_ADDED_SIGNAL, gv, &error); } static gboolean on_handle_activate_backend (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gpointer user_data) { g_print ("on_handle_activate_backend() called\n"); GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); GList *printers = gcp_object_get_printers (gcp, access_token, "ALL"); g_assert (printers != NULL); const gchar *dialog_name = g_dbus_method_invocation_get_sender (invocation); g_hash_table_insert (b->dialog_printers, (gpointer)dialog_name, (gpointer)printers); while (printers != NULL) { printer *printer_struct = printers->data; emit_printer_added_signal (gcp, access_token, dialog_name, printer_struct); g_print ("printer added signal emmitted\n"); printers = printers->next; } print_backend_complete_activate_backend (skeleton, invocation); g_object_unref (gcp); return TRUE; } static gboolean on_handle_get_backend_name (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gpointer user_data) { g_print ("on_handle_get_backend_name() called\n"); print_backend_complete_get_backend_name (skeleton, invocation, "GCP"); return TRUE; } gint comp_function (gconstpointer data_a, gconstpointer data_b) { printer *printer_struct_a = (printer *)data_a; printer *printer_struct_b = (printer *)data_b; return g_strcmp0 (printer_struct_a->id, printer_struct_b->id); } void refresh_printer_list(char *dialog_name) { GCPObject *gcp = gcp_object_new (); GError *error = NULL; gchar *access_token = g_malloc (150); gint expires_in; gboolean res = get_access_token (&access_token, &expires_in, &error); g_assert (res == TRUE); GList *printers_new = gcp_object_get_printers (gcp, access_token, "ALL"); g_assert (printers_new != NULL); GList *printers_old = NULL; GList *temp = NULL; // const gchar *dialog_name = g_dbus_method_invocation_get_sender (invocation); printers_old = (GList *)g_hash_table_lookup (b->dialog_printers, (gconstpointer)dialog_name); g_assert (printers_old != NULL); // Look for new printers temp = printers_new; while (temp != NULL) { printer *printer_struct = temp->data; if (g_list_find_custom (printers_old, (gconstpointer)printer_struct, comp_function) == NULL) { // new printer found, emit printer added signal emit_printer_added_signal (gcp, access_token, dialog_name, printer_struct); } temp = temp->next; } // Look for deleted printers temp = printers_old; while (temp != NULL) { printer *printer_struct = temp->data; if (g_list_find_custom (printers_new, (gconstpointer)printer_struct, comp_function) == NULL) { // printer deleted, emit printer removed signal emit_printer_removed_signal (dialog_name, printer_struct); } temp = temp->next; } g_hash_table_replace (b->dialog_printers, (gpointer)dialog_name, (gpointer)printers_new); } static void on_refresh_backend(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer not_used) { gchar *dialog_name = g_strdup (sender_name); g_message ("Refresh backend signal from %s\n", dialog_name); refresh_printer_list (dialog_name); } 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) { gchar *dialog_name = g_strdup (sender_name); g_message("Stop backend signal from %s\n", dialog_name); exit (EXIT_SUCCESS); } BackendObj *get_new_BackendObj() { BackendObj *b_obj = (BackendObj *)(malloc(sizeof(BackendObj))); b_obj->dbus_connection = NULL; b_obj->dialog_printers = g_hash_table_new (g_str_hash, g_str_equal); return b_obj; } int main () { b = get_new_BackendObj(); g_assert (b != NULL); ServerObject *gcp_server = server_object_new (); GMainLoop *loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); return 0; } cpdb-backend-gcp-1.0.0/src/gcp_server.h000066400000000000000000000106141321375554300176650ustar00rootroot00000000000000#ifndef __GCP_SERVER_H__ #define __GCP_SERVER_H__ #include #include #include #include "gcp.h" G_BEGIN_DECLS #define SERVER_TYPE_OBJECT server_object_get_type() G_DECLARE_DERIVABLE_TYPE (ServerObject, server_object, Server, OBJECT, GObject) struct _ServerObjectClass { GObjectClass parent; }; typedef struct _BackendObj { GDBusConnection *dbus_connection; GHashTable *dialog_printers; } BackendObj; ServerObject * server_object_new (); static void acquire_session_bus_name (); static void on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data); static gboolean on_handle_get_all_options (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data); // static gboolean // on_handle_submit_print_job (PrintBackend *skeleton, // GDBusMethodInvocation *invocation, // const gchar *uid, // const gchar *access_token, // const gchar *title, // const gchar *ticket, // gpointer user_data); static gboolean on_handle_get_all_jobs (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gboolean active_only, gpointer user_data); static gboolean on_handle_get_active_jobs_count (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data); static gboolean on_handle_get_printer_state (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data); static gboolean on_handle_is_accepting_jobs (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, gpointer user_data); static gboolean on_handle_cancel_job (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *job_id, const gchar *printer_id, gpointer user_data); static gboolean on_handle_activate_backend (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gpointer user_data); static gboolean on_handle_get_backend_name (PrintBackend *skeleton, GDBusMethodInvocation *invocation, gpointer user_data); static gboolean on_handle_print_file (PrintBackend *skeleton, GDBusMethodInvocation *invocation, const gchar *printer_id, const gchar *file_path_name, gint num_settings, GVariant *settings, gpointer user_data); gint comp_function (gconstpointer data_a, gconstpointer data_b); void refresh_printer_list(char *dialog_name); static void on_refresh_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_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); void connect_to_signals (PrintBackend *skeleton); void emit_printer_added_signal (GCPObject *gcp, const gchar *access_token, const gchar *dialog_name, printer *printer_struct); void emit_printer_removed_signal (const gchar *dialog_name, printer *printer_struct); BackendObj *get_new_BackendObj(); G_END_DECLS #endif /* GCP_SERVER_H */