diff options
Diffstat (limited to 'src/glade-registration.c')
-rw-r--r-- | src/glade-registration.c | 1100 |
1 files changed, 0 insertions, 1100 deletions
diff --git a/src/glade-registration.c b/src/glade-registration.c deleted file mode 100644 index ec8d5de0..00000000 --- a/src/glade-registration.c +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * Copyright (C) 2014, 2020 Juan Pablo Ugarte. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Authors: - * Juan Pablo Ugarte <juanpablougarte@gmail.com> - */ - -#include "config.h" -#include "glade-registration.h" -#include "glade-window.h" -#include "glade-http.h" -#include "glade-logo.h" -#include <gladeui/glade.h> -#include <glib/gi18n.h> - -#define USER_SURVEY_CONFIG_GROUP "User & Survey" -#define SURVEY_DATA_CONFIG_GROUP "Survey Data" - -struct _GladeRegistrationPrivate -{ - GKeyFile *config; - gchar *user_agent; - - GtkWidget *infobar; - GtkWidget *statusbar; - GtkWidget *net_spinner; - GtkLabel *infobar_label; - GtkLabel *status_label; - GtkWidget *submit_button; - GtkContainer *user_survey_box; - - GladeHTTP *http; - GladeHTTP *sub_http; - GCancellable *cancellable; - GCancellable *sub_cancellable; - - /* HTML Form parsing */ - GHashTable *hidden_inputs; - gboolean form_loaded; - GHashTable *sub_hidden_inputs; - gboolean sub_form_loaded; - - /* Form widgets */ - - GtkWidget *name; - GtkWidget *email; - GtkWidget *country_id; - GtkWidget *city; - GtkWidget *contact_type; - GtkWidget *contact_name; - GtkWidget *contact_website; - GtkWidget *subscribe; - - GtkWidget *experience; - GtkWidget *experience_unit; - GtkWidget *experience_not_programmer; - GtkWidget *lang_c; - GtkWidget *lang_cpp; - GtkWidget *lang_csharp; - GtkWidget *lang_java; - GtkWidget *lang_python; - GtkWidget *lang_javascript; - GtkWidget *lang_vala; - GtkWidget *lang_perl; - GtkWidget *lang_rust; - GtkWidget *lang_other; - GtkWidget *start_using; - GtkWidget *start_using_unit; - GtkWidget *version; - GtkWidget *version_other; - GtkWidget *os; - GtkWidget *os_linux; - GtkWidget *os_bsd; - GtkWidget *os_windows; - GtkWidget *os_osx; - GtkWidget *os_solaris; - GtkWidget *os_other; - GtkWidget *freq; - GtkWidget *user_level; - GtkWidget *soft_free; - GtkWidget *soft_open; - GtkWidget *soft_commercial; - GtkWidget *soft_none; - GtkWidget *field_academic; - GtkWidget *field_accounting; - GtkWidget *field_desktop; - GtkWidget *field_educational; - GtkWidget *field_embedded; - GtkWidget *field_medical; - GtkWidget *field_industrial; - GtkWidget *field_scientific; - GtkWidget *field_other; - GtkWidget *improvement; - GtkWidget *problem; - GtkWidget *problem_other; - GtkWidget *bug; - GtkWidget *bugzilla; - GtkWidget *contributing; - GtkWidget *contributing_whynot; - GtkWidget *comments; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (GladeRegistration, glade_registration, GTK_TYPE_DIALOG) - -enum -{ - PROP_0, - PROP_COMPLETED, - PROP_SKIP_REMINDER -}; - -static void -glade_registration_parse_response_form (GladeRegistration *registration, - const gchar *response, - const gchar *form_action, - GHashTable *data); - -static void -string_append_input_key_value_tuple (GString *string, - const gchar *name, - GtkWidget *input) -{ - if (string->len) - g_string_append_c (string, '&'); - - g_string_append (string, name); - g_string_append_c (string, '='); - - if (GTK_IS_ENTRY (input)) - g_string_append_uri_escaped (string, gtk_entry_get_text (GTK_ENTRY (input)), NULL, FALSE); - else if (GTK_IS_TEXT_VIEW (input)) - { - GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (input)); - GtkTextIter start, end; - gchar *text; - - gtk_text_buffer_get_bounds (buffer, &start, &end); - text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); - g_string_append_uri_escaped (string, text ? text : "", NULL, FALSE); - g_free (text); - } - else if (GTK_IS_COMBO_BOX (input)) - g_string_append_uri_escaped (string, gtk_combo_box_get_active_id (GTK_COMBO_BOX (input)), NULL, FALSE); - else if (GTK_IS_RADIO_BUTTON (input)) - { - GSList *group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (input)); - - for (; group; group = g_slist_next (group)) - { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (group->data))) - g_string_append (string, gtk_widget_get_name (group->data)); - } - } - else if (GTK_IS_TOGGLE_BUTTON (input) && - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (input))) - g_string_append_c (string, 'Y'); -} - -static void -append_hidden_inputs (gpointer key, gpointer value, gpointer user_data) -{ - GString *str = user_data; - g_string_append_printf (str, "&%s=%s", (gchar *)key, (gchar *)value); -} - -static void -glade_registration_show_message (GladeRegistration *registration, - GtkMessageType type, - const gchar *format, - ...) G_GNUC_PRINTF (3, 4); - -static void -glade_registration_show_message (GladeRegistration *registration, - GtkMessageType type, - const gchar *format, - ...) -{ - GladeRegistrationPrivate *priv = registration->priv; - - gtk_info_bar_set_message_type (GTK_INFO_BAR (priv->infobar), type); - - if (format) - { - g_autofree gchar *string = NULL; - va_list args; - - va_start (args, format); - string = g_strdup_vprintf (format, args); - va_end (args); - - gtk_label_set_markup (priv->infobar_label, string); - } - else - gtk_label_set_markup (priv->infobar_label, ""); - - /* Only show the infobar if the dialog is visible */ - if (gtk_widget_is_visible (GTK_WIDGET (registration))) - gtk_widget_show (priv->infobar); -} - -static void -glade_registration_http_post (GladeRegistration *registration, - GladeHTTP *http, - GCancellable *cancellable, - const gchar *url, - GString *content) -{ - const gchar *lang = pango_language_to_string (pango_language_get_default ()); - g_autofree gchar *cookies = glade_http_get_cookies (http); - - glade_http_request_send_async (http, cancellable, - "POST %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: %s\r\n" - "Connection: close\r\n" - "Accept: text/html\r\n" - "Accept-Language: %s\r\n" - "Cookie: %s\r\n" - "Origin: https://%s\r\n" - "Referer: https://%s%s\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %"G_GSIZE_FORMAT"\r\n" - "\r\n%s", - url, /* POST url */ - glade_http_get_host (http), /* Host */ - registration->priv->user_agent, /* User-Agent */ - lang, /* Accept-Language */ - cookies, /* Cookie */ - glade_http_get_host (http), /* Origin */ - glade_http_get_host (http), /* Referer */ - url, /* Referer */ - content->len, /* Content-length */ - content->str); /* content */ -} - -static void -glade_registration_http_get (GladeRegistration *registration, - GladeHTTP *http, - GCancellable *cancellable, - const gchar *url) -{ - glade_http_request_send_async (http, cancellable, - "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: %s\r\n" - "Connection: close\r\n" - "Accept: text/html\r\n" - "Content-Length: 0\r\n" - "\r\n", - url, /* POST url */ - glade_http_get_host (http), /* Host */ - registration->priv->user_agent); /* User-Agent */ -} - -static void -on_http_status (GladeHTTP *http, - GladeHTTPStatus status, - GError *error, - GladeRegistration *registration) -{ - g_autofree gchar *text = NULL; - - switch (status) - { - case GLADE_HTTP_READY: - break; - case GLADE_HTTP_CONNECTING: - text = g_strdup_printf (_("Connecting to %s"), glade_http_get_host (http)); - break; - case GLADE_HTTP_SENDING: - text = g_strdup_printf (_("Sending data to %s"), glade_http_get_host (http)); - break; - case GLADE_HTTP_WAITING: - text = g_strdup_printf (_("Waiting for %s"), glade_http_get_host (http)); - break; - case GLADE_HTTP_RECEIVING: - text = g_strdup_printf (_("Receiving data from %s"), glade_http_get_host (http)); - break; - case GLADE_HTTP_ERROR: - glade_registration_show_message (registration, GTK_MESSAGE_WARNING, - "%s", error->message); - break; - } - - gtk_label_set_text (registration->priv->status_label, text ? text : ""); - gtk_widget_set_visible (registration->priv->net_spinner, text != NULL); - gtk_widget_set_visible (registration->priv->statusbar, text != NULL); -} - -static void -glade_registration_subscribe_email (GladeRegistration *registration) -{ - GladeRegistrationPrivate *priv = registration->priv; - g_autoptr(GString) post = g_string_new (""); - - string_append_input_key_value_tuple (post, "email", priv->email); - string_append_input_key_value_tuple (post, "fullname", priv->name); - - /* Append magic token */ - g_hash_table_foreach (priv->sub_hidden_inputs, append_hidden_inputs, post); - - glade_registration_http_post (registration, priv->sub_http, NULL, - "/mailman/subscribe/glade-users-list", - post); -} - -static void -on_subscribe_http_request_done (GladeHTTP *http, - gint code, - const gchar *response, - GladeRegistration *registration) -{ - GladeRegistrationPrivate *priv = registration->priv; - - switch (code) - { - case 100: - /* Ignore Continue HTTP response */ - break; - case 200: - { - if (!priv->sub_form_loaded) - { - /* Get magic token from html form */ - glade_registration_parse_response_form (registration, - response, - "subscribe/glade-users-list", - priv->sub_hidden_inputs); - priv->sub_form_loaded = TRUE; - - /* Now that we have the magic token we can make the actual POST */ - glade_registration_subscribe_email (registration); - } - else - glade_registration_show_message (registration, GTK_MESSAGE_INFO, "%s", - _("Your subscription to the users list has been received!\nCheck your email!")); - } - break; - default: - { -#define SUBSCRIPTION_FAILED "Sorry, automatic subscription to Glade Users mailing list failed.\n\ -<a href=\"https://mail.gnome.org/mailman/listinfo/glade-users-list\">Open Glade Users Website</a>" - - glade_registration_show_message (registration, GTK_MESSAGE_WARNING, - "%s\nHTTP response %d", - _(SUBSCRIPTION_FAILED), - code); - } - break; - } -} - -static void -glade_registration_clear (GladeRegistrationPrivate *priv) -{ - g_clear_object (&priv->cancellable); - g_clear_object (&priv->sub_cancellable); - - priv->cancellable = g_cancellable_new (); - priv->sub_cancellable = g_cancellable_new (); - - gtk_widget_hide (priv->infobar); - g_hash_table_remove_all (priv->hidden_inputs); - g_hash_table_remove_all (priv->sub_hidden_inputs); - priv->form_loaded = FALSE; - priv->sub_form_loaded = FALSE; -} - -#define ADD_USER_INPUT(p,q,i) string_append_input_key_value_tuple (p, "311811X51X"q, priv->i) -#define ADD_SURVEY_INPUT(p,q,i) string_append_input_key_value_tuple (p, "311811X57X"q, priv->i) - -static void -glade_registration_submit_survey (GladeRegistration *registration) -{ - GladeRegistrationPrivate *priv = registration->priv; - g_autoptr(GString) post; - - post = g_string_new ("move=movesubmit&ajax=off&311811X51X843="); - - /* User Agent */ - g_string_append_uri_escaped (post, priv->user_agent, NULL, FALSE); - - /* User info */ - ADD_USER_INPUT (post, "849", name); - ADD_USER_INPUT (post, "852", email); - ADD_USER_INPUT (post, "1074", country_id); - ADD_USER_INPUT (post, "858", city); - ADD_USER_INPUT (post, "861", contact_type); - ADD_USER_INPUT (post, "864", contact_name); - ADD_USER_INPUT (post, "867", contact_website); - - /* Survey data */ - ADD_SURVEY_INPUT (post, "873", experience); - ADD_SURVEY_INPUT (post, "879", experience_unit); - ADD_SURVEY_INPUT (post, "882", experience_not_programmer); - ADD_SURVEY_INPUT (post, "885c", lang_c); - ADD_SURVEY_INPUT (post, "885cpp", lang_cpp); - ADD_SURVEY_INPUT (post, "885csharp", lang_csharp); - ADD_SURVEY_INPUT (post, "885java", lang_java); - ADD_SURVEY_INPUT (post, "885python", lang_python); - ADD_SURVEY_INPUT (post, "885javascript", lang_javascript); - ADD_SURVEY_INPUT (post, "885vala", lang_vala); - ADD_SURVEY_INPUT (post, "885perl", lang_perl); - ADD_SURVEY_INPUT (post, "885rust", lang_rust); - ADD_SURVEY_INPUT (post, "885other", lang_other); - ADD_SURVEY_INPUT (post, "915", start_using); - ADD_SURVEY_INPUT (post, "918", start_using_unit); - ADD_SURVEY_INPUT (post, "921", version); - ADD_SURVEY_INPUT (post, "924", version_other); - ADD_SURVEY_INPUT (post, "927", os); - - ADD_SURVEY_INPUT (post, "930", os_linux); - ADD_SURVEY_INPUT (post, "933", os_bsd); - ADD_SURVEY_INPUT (post, "936", os_windows); - ADD_SURVEY_INPUT (post, "939", os_osx); - ADD_SURVEY_INPUT (post, "942", os_solaris); - - ADD_SURVEY_INPUT (post, "945", os_other); - - ADD_SURVEY_INPUT (post, "948", freq); - ADD_SURVEY_INPUT (post, "951", user_level); - - ADD_SURVEY_INPUT (post, "954free", soft_free); - ADD_SURVEY_INPUT (post, "954open", soft_open); - ADD_SURVEY_INPUT (post, "954commercial", soft_commercial); - ADD_SURVEY_INPUT (post, "954none", soft_none); - - ADD_SURVEY_INPUT (post, "969academic", field_academic); - ADD_SURVEY_INPUT (post, "969accounting", field_accounting); - ADD_SURVEY_INPUT (post, "969desktop", field_desktop); - ADD_SURVEY_INPUT (post, "969educational", field_educational); - ADD_SURVEY_INPUT (post, "969embedded", field_embedded); - ADD_SURVEY_INPUT (post, "969medical", field_medical); - ADD_SURVEY_INPUT (post, "969industrial", field_industrial); - ADD_SURVEY_INPUT (post, "969scientific", field_scientific); - - ADD_SURVEY_INPUT (post, "1134", field_other); - - ADD_SURVEY_INPUT (post, "999", improvement); - ADD_SURVEY_INPUT (post, "1002", problem); - ADD_SURVEY_INPUT (post, "1140", problem_other); - ADD_SURVEY_INPUT (post, "1005", bug); - - ADD_SURVEY_INPUT (post, "1008", bugzilla); - ADD_SURVEY_INPUT (post, "1011", contributing); - ADD_SURVEY_INPUT (post, "1014", contributing_whynot); - ADD_SURVEY_INPUT (post, "1017", comments); - - /* Append hidden inputs */ - g_hash_table_foreach (priv->hidden_inputs, append_hidden_inputs, post); - - glade_registration_http_post (GLADE_REGISTRATION (registration), - priv->http, - priv->cancellable, - "/index.php/311811", - post); -} - -static void -on_http_request_done (GladeHTTP *http, - gint code, - const gchar *response, - GladeRegistration *registration) -{ - switch (code) - { - case 100: - /* Ignore Continue HTTP response */ - break; - case 200: - { - GladeRegistrationPrivate *priv = registration->priv; - - if (!priv->form_loaded) - { - glade_registration_parse_response_form (registration, - response, - "311811", - priv->hidden_inputs); - priv->form_loaded = TRUE; - - /* Now that we have the magic token we can make the actual POST */ - glade_registration_submit_survey (registration); - return; - } - - if (g_strstr_len (response, -1, "GLADE_USER_REGISTRATION_SURVEY_OK") != NULL) - { - gtk_label_set_text (priv->status_label, ""); - gtk_widget_hide (priv->statusbar); - - g_object_set (registration, "completed", TRUE, NULL); - glade_app_config_save (); - - glade_util_ui_message (GTK_WIDGET (registration), GLADE_UI_INFO, NULL, - "<big>%s</big>", _("Thank you for taking the time to complete the survey, we appreciate it!")); - gtk_widget_hide (GTK_WIDGET (registration)); - } - else - glade_registration_show_message (registration, GTK_MESSAGE_WARNING, - "Internal server error"); - } - break; - default: - glade_registration_show_message (registration, GTK_MESSAGE_WARNING, - "Got HTTP response %d", code); - break; - } -} - -static inline void -survey_data_set_string (GKeyFile *config, const gchar *id, const gchar *value) -{ - if (value) - g_key_file_set_string (config, SURVEY_DATA_CONFIG_GROUP, id, value); -} - -void -glade_registration_save_state_foreach (GtkWidget *widget, gpointer data) -{ - GladeRegistration *registration = GLADE_REGISTRATION (data); - const gchar *id = gtk_buildable_get_name (GTK_BUILDABLE (widget)); - - if (id) - { - GKeyFile *config = registration->priv->config; - - if (GTK_IS_ENTRY (widget)) - survey_data_set_string (config, id, gtk_entry_get_text (GTK_ENTRY (widget))); - else if (GTK_IS_TEXT_VIEW (widget)) - { - GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget)); - GtkTextIter start, end; - g_autofree gchar *text = NULL; - - gtk_text_buffer_get_bounds (buffer, &start, &end); - text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); - survey_data_set_string (config, id, text); - } - else if (GTK_IS_COMBO_BOX (widget)) - survey_data_set_string (config, id, gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget))); - else if (GTK_IS_TOGGLE_BUTTON (widget)) - g_key_file_set_boolean (config, SURVEY_DATA_CONFIG_GROUP, id, - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))); - } - - /* Recurse all containers */ - if (GTK_IS_CONTAINER (widget)) - gtk_container_foreach (GTK_CONTAINER (widget), - glade_registration_save_state_foreach, - data); -} - -void -glade_registration_load_state_foreach (GtkWidget *widget, gpointer data) -{ - GladeRegistration *registration = GLADE_REGISTRATION (data); - const gchar *id = gtk_buildable_get_name (GTK_BUILDABLE (widget)); - - if (id) - { - GKeyFile *config = registration->priv->config; - - if (GTK_IS_SPIN_BUTTON (widget)) - { - gint val = g_key_file_get_integer (config, SURVEY_DATA_CONFIG_GROUP, id, NULL); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), val); - } - else if (GTK_IS_ENTRY (widget)) - { - g_autofree gchar *val = NULL; - val = g_key_file_get_string (config, SURVEY_DATA_CONFIG_GROUP, id, NULL); - gtk_entry_set_text (GTK_ENTRY (widget), val ? val : ""); - } - else if (GTK_IS_TEXT_VIEW (widget)) - { - g_autofree gchar *val = NULL; - - val = g_key_file_get_string (config, SURVEY_DATA_CONFIG_GROUP, id, NULL); - GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget)); - - gtk_text_buffer_set_text (buffer, val ? val : "", -1); - } - else if (GTK_IS_COMBO_BOX (widget)){ - g_autofree gchar *val = NULL; - - val = g_key_file_get_string (config, SURVEY_DATA_CONFIG_GROUP, id, NULL); - gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget), val ? val : ""); - } - else if (GTK_IS_TOGGLE_BUTTON (widget)){ - gboolean val = g_key_file_get_boolean (config, SURVEY_DATA_CONFIG_GROUP, id, NULL); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), val); - } - } - - /* Recurse all containers */ - if (GTK_IS_CONTAINER (widget)) - gtk_container_foreach (GTK_CONTAINER (widget), - glade_registration_load_state_foreach, - data); -} - -static gboolean -entry_is_empty (GtkWidget *entry) -{ - const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry)); - g_autofree gchar *str = NULL; - - if (!text || *text == '\0') - return TRUE; - - str = g_strstrip (g_strdup (text)); - - return (!str || *str == '\0'); -} - -static gboolean -glade_registration_verify (GtkWidget *entry) -{ - GtkStyleContext *ctx = gtk_widget_get_style_context (entry); - - gtk_style_context_remove_class (ctx, "error"); - - if (entry_is_empty (entry)) - { - gtk_style_context_add_class (ctx, "error"); - gtk_widget_grab_focus (entry); - return TRUE; - } - - if (gtk_entry_get_input_purpose (GTK_ENTRY (entry)) == GTK_INPUT_PURPOSE_EMAIL) - { - const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); - g_auto(GStrv) email = NULL; - - /* Check if this looks like an email */ - if (g_strstr_len (text, -1, " ") || - g_strstr_len (text, -1, "\t") || - g_strstr_len (text, -1, "\n") || - !(email = g_strsplit (text, "@", 2)) || - g_strv_length (email) != 2 || - *email[0] == '\0'|| *email[1] == '\0') - { - gtk_style_context_add_class (ctx, "error"); - gtk_widget_grab_focus (entry); - return TRUE; - } - } - - return FALSE; -} - -static void -glade_registration_verify_entry (GtkEntry *entry, GladeRegistration *registration) -{ - glade_registration_verify (GTK_WIDGET (entry)); -} - -static void -on_registration_dialog_response (GtkDialog *dialog, gint response_id) -{ - GladeRegistration *registration = GLADE_REGISTRATION (dialog); - GladeRegistrationPrivate *priv = registration->priv; - - gtk_widget_hide (priv->infobar); - - /* Save state */ - gtk_container_foreach (priv->user_survey_box, - glade_registration_save_state_foreach, - registration); - glade_app_config_save (); - - if (response_id != GTK_RESPONSE_OK) - { - gtk_widget_hide (GTK_WIDGET (dialog)); - glade_registration_clear (priv); - return; - } - - if (glade_registration_verify (priv->name) || - glade_registration_verify (priv->email) || - g_key_file_get_boolean (priv->config, USER_SURVEY_CONFIG_GROUP, "completed", NULL)) - return; - - /* Init state */ - glade_registration_clear (priv); - - - /* Get survey form */ - glade_registration_http_get (registration, - priv->http, - priv->cancellable, - "/index.php/311811"); - - /* Get mailman form */ - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->subscribe))) - glade_registration_http_get (registration, - priv->sub_http, - priv->sub_cancellable, - "/mailman/listinfo/glade-users-list"); -} - -static void -toggle_button_set_visible_on_toggle (GtkToggleButton *button, GtkWidget *widget) -{ - gtk_widget_set_visible (widget, gtk_toggle_button_get_active (button)); -} - -static void -toggle_button_set_sensitive_on_toggle (GtkToggleButton *button, GtkWidget *widget) -{ - gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (button)); -} - -static gboolean -on_viewport_draw (GtkWidget *viewport, cairo_t *cr, GladeRegistration *widget) -{ - GtkStyleContext *context = gtk_widget_get_style_context (viewport); - GtkAllocation alloc; - gdouble scale; - GdkRGBA c; - - gtk_style_context_get_color (context, gtk_style_context_get_state (context), &c); - - gtk_widget_get_allocation (viewport, &alloc); - - scale = MIN (alloc.width/GLADE_LOGO_WIDTH, alloc.height/GLADE_LOGO_HEIGHT) - .1; - - cairo_save (cr); - - cairo_set_source_rgba (cr, c.red, c.green, c.blue, .04); - cairo_scale (cr, scale, scale); - cairo_translate (cr, (alloc.width / scale) - GLADE_LOGO_WIDTH*.95, - (alloc.height / scale) - GLADE_LOGO_HEIGHT); - cairo_append_path (cr, &glade_logo_path); - cairo_fill (cr); - - cairo_restore (cr); - - return FALSE; -} - -static void -glade_registration_update_state (GladeRegistration *registration) -{ - GladeRegistrationPrivate *priv = glade_registration_get_instance_private (registration); - - if (g_key_file_get_boolean (priv->config, USER_SURVEY_CONFIG_GROUP, "completed", NULL)) - { - GtkWidget *headerbar = gtk_dialog_get_header_bar (GTK_DIALOG (registration)); - - gtk_widget_set_sensitive (GTK_WIDGET (priv->user_survey_box), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (priv->submit_button), FALSE); - - if (headerbar) - gtk_header_bar_set_subtitle(GTK_HEADER_BAR (headerbar), - _("Completed and submitted!")); - } -} - -static void -glade_registration_init (GladeRegistration *registration) -{ - GladeRegistrationPrivate *priv = glade_registration_get_instance_private (registration); - - registration->priv = priv; - - priv->config = glade_app_get_config (); - - /* Create user agent */ - priv->user_agent = - g_strdup_printf ("Glade/"PACKAGE_VERSION" (%s; Gtk+ %d.%d.%d; glib %d.%d.%d; %s)", - glade_window_get_gdk_backend (), /* Gdk backend */ - GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION, /* Gtk version */ - glib_major_version, glib_minor_version, glib_micro_version,/* Glib version */ - pango_language_to_string (pango_language_get_default ())); - - priv->hidden_inputs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - priv->sub_hidden_inputs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* HTTPS default port is 443 */ - priv->http = glade_http_new ("surveys.gnome.org", 443, TRUE); - - g_signal_connect_object (priv->http, "request-done", - G_CALLBACK (on_http_request_done), - registration, 0); - g_signal_connect_object (priv->http, "status", - G_CALLBACK (on_http_status), - registration, 0); - - priv->sub_http = glade_http_new ("mail.gnome.org", 443, TRUE); - g_signal_connect_object (priv->sub_http, "request-done", - G_CALLBACK (on_subscribe_http_request_done), - registration, 0); - - gtk_widget_init_template (GTK_WIDGET (registration)); - - /* Generate Glade versions */ - if (GTK_IS_COMBO_BOX_TEXT (priv->version_other)) - { - GtkComboBoxText *combo = GTK_COMBO_BOX_TEXT (priv->version_other); - gchar id[16], text[18]; - gint minor; - - for (minor = 0; minor <= GLADE_MINOR_VERSION; minor+=2) - { - g_snprintf (id, 16, "%d", minor); - g_snprintf (text, 18, "3.%d", minor); - gtk_combo_box_text_prepend (combo, id, text); - - /* Skip non released version 24-34 */ - if (minor == 22) - minor = 34; - } - - gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); - } - - /* Load survey state */ - gtk_container_foreach (priv->user_survey_box, - glade_registration_load_state_foreach, - registration); - - gtk_dialog_set_default_response (GTK_DIALOG (registration), GTK_RESPONSE_OK); - - glade_registration_update_state (registration); -} - -static void -glade_registration_finalize (GObject *object) -{ - GladeRegistrationPrivate *priv = GLADE_REGISTRATION (object)->priv; - - g_clear_pointer (&priv->user_agent, g_free); - g_clear_object (&priv->http); - g_clear_object (&priv->sub_http); - g_clear_object (&priv->cancellable); - g_clear_object (&priv->sub_cancellable); - g_hash_table_destroy (priv->hidden_inputs); - g_hash_table_destroy (priv->sub_hidden_inputs); - - G_OBJECT_CLASS (glade_registration_parent_class)->finalize (object); -} - -static void -glade_registration_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - GladeRegistrationPrivate *priv; - - g_return_if_fail (GLADE_IS_REGISTRATION (object)); - - priv = GLADE_REGISTRATION (object)->priv; - - switch (prop_id) - { - case PROP_SKIP_REMINDER: - g_key_file_set_boolean (priv->config, USER_SURVEY_CONFIG_GROUP, - pspec->name, g_value_get_boolean (value)); - break; - case PROP_COMPLETED: - g_key_file_set_boolean (priv->config, USER_SURVEY_CONFIG_GROUP, - pspec->name, g_value_get_boolean (value)); - glade_registration_update_state (GLADE_REGISTRATION (object)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -glade_registration_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - GladeRegistrationPrivate *priv; - - g_return_if_fail (GLADE_IS_REGISTRATION (object)); - - priv = GLADE_REGISTRATION (object)->priv; - - switch (prop_id) - { - case PROP_SKIP_REMINDER: - case PROP_COMPLETED: - g_value_set_boolean (value, g_key_file_get_boolean (priv->config, USER_SURVEY_CONFIG_GROUP, pspec->name, NULL)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -glade_registration_class_init (GladeRegistrationClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GtkCssProvider *css_provider; - - gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/glade/glade-registration.glade"); - - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, infobar); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, statusbar); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, net_spinner); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, infobar_label); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, status_label); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, submit_button); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, user_survey_box); - - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, name); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, email); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, country_id); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, city); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_type); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_name); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_website); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, subscribe); - - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience_unit); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience_not_programmer); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_c); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_cpp); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_csharp); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_java); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_python); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_javascript); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_vala); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_perl); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_rust); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_other); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, start_using); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, start_using_unit); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, version); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, version_other); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_linux); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_bsd); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_windows); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_osx); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_solaris); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_other); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, freq); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, user_level); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_free); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_open); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_commercial); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_none); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_academic); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_accounting); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_desktop); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_educational); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_embedded); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_medical); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_industrial); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_scientific); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_other); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, improvement); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, problem); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, problem_other); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, bug); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, bugzilla); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contributing); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contributing_whynot); - gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, comments); - - gtk_widget_class_bind_template_callback (widget_class, glade_registration_verify_entry); - gtk_widget_class_bind_template_callback (widget_class, on_registration_dialog_response); - gtk_widget_class_bind_template_callback (widget_class, toggle_button_set_visible_on_toggle); - gtk_widget_class_bind_template_callback (widget_class, toggle_button_set_sensitive_on_toggle); - gtk_widget_class_bind_template_callback (widget_class, on_viewport_draw); - - object_class->finalize = glade_registration_finalize; - object_class->set_property = glade_registration_set_property; - object_class->get_property = glade_registration_get_property; - - g_object_class_install_property (object_class, - PROP_COMPLETED, - g_param_spec_boolean ("completed", - "Completed", - "Registration was completed successfully", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_SKIP_REMINDER, - g_param_spec_boolean ("skip-reminder", - "Skip reminder", - "Skip registration reminder dialog", - FALSE, - G_PARAM_READWRITE)); - - /* Setup Custom CSS */ - css_provider = gtk_css_provider_new (); - gtk_css_provider_load_from_resource (css_provider, "/org/gnome/glade/glade-registration.css"); - - gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), - GTK_STYLE_PROVIDER (css_provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_object_unref (css_provider); -} - -GtkWidget* -glade_registration_new (void) -{ - return GTK_WIDGET (g_object_new (GLADE_TYPE_REGISTRATION, - "use-header-bar", TRUE, - NULL)); -} - -/* HTML Form parsing utils */ -#include <libxml/HTMLparser.h> - -typedef struct { - const gchar *form_action; - GHashTable *inputs; - - gboolean in_form; -} ParseData; - -static void -start_element (ParseData *data, const gchar *name, const gchar **atts) -{ - gboolean is_hidden = FALSE; - const gchar *input_name = NULL, *input_value = NULL; - gint i; - - if (g_strcmp0 (name, "form") == 0) - { - for (i = 0; atts[i]; i++) - if (g_strcmp0 (atts[i], "action") == 0 && - g_strstr_len (atts[i+1], -1, data->form_action)) - data->in_form = TRUE; - - return; - } - - /* Ignore elements outside of the form */ - if (!data->in_form) - return; - - if (g_strcmp0 (name, "input")) - return; - - for (i = 0; atts[i]; i += 2) - { - gint val = i + 1; - - if (!g_strcmp0 (atts[i], "type") && !g_strcmp0 (atts[val], "hidden")) - is_hidden = TRUE; - - if (!g_strcmp0 (atts[i], "name")) - input_name = atts[val]; - - if (!g_strcmp0 (atts[i], "value")) - input_value = atts[val]; - } - - if (is_hidden && input_name && input_value) - g_hash_table_insert (data->inputs, - g_uri_escape_string (input_name, NULL, FALSE), - g_uri_escape_string (input_value, NULL, FALSE)); -} - -static void -end_element (ParseData *data, const gchar *name) -{ - if (g_strcmp0 (name, "form") == 0) - data->in_form = FALSE; -} - -static void -glade_registration_parse_response_form (GladeRegistration *registration, - const gchar *response, - const gchar *form_action, - GHashTable *inputs) -{ - ParseData data = { .form_action = form_action, .inputs = inputs }; - htmlSAXHandler sax = { NULL, }; - - sax.startElement = (startElementSAXFunc) start_element; - sax.endElement = (endElementSAXFunc) end_element; - - /* Parse response and collect hidden inputs in the hash table */ - xmlFreeDoc (htmlSAXParseDoc ((guchar *)response, NULL, &sax, &data)); -} - |