diff options
Diffstat (limited to 'webservice.c')
-rw-r--r-- | webservice.c | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/webservice.c b/webservice.c deleted file mode 100644 index e713e1282..000000000 --- a/webservice.c +++ /dev/null @@ -1,409 +0,0 @@ -#include <glib/gi18n.h> -#include <libsoup/soup.h> -#include <libxml/tree.h> -#include <libxml/parser.h> -#include "dive.h" -#include "divelist.h" -#include "display-gtk.h" -#include "file.h" - -struct dive_table gps_location_table; -static gboolean merge_locations_into_dives(void); - -enum { - DD_STATUS_OK, - DD_STATUS_ERROR_CONNECT, - DD_STATUS_ERROR_ID, - DD_STATUS_ERROR_PARSE, -}; - -static const gchar *download_dialog_status_text(const gint status) -{ - switch (status) { - case DD_STATUS_ERROR_CONNECT: - return _("Connection Error: "); - case DD_STATUS_ERROR_ID: - return _("Invalid user identifier!"); - case DD_STATUS_ERROR_PARSE: - return _("Cannot parse response!"); - } - return _("Download Success!"); -} - -/* provides a state of the download dialog contents and the downloaded xml */ -struct download_dialog_state { - GtkWidget *uid; - GtkWidget *status; - GtkWidget *apply; - gchar *xmldata; - guint xmldata_len; -}; - -/* this method uses libsoup as a backend. if there are some portability, - * compatibility or speed issues, libcurl is a better choice. */ -gboolean webservice_request_user_xml(const gchar *user_id, - gchar **data, - guint *len, - guint *status_code) -{ - SoupMessage *msg; - SoupSession *session; - gboolean ret = FALSE; - gchar url[256] = {0}; - - session = soup_session_async_new(); - strcat(url, "http://api.hohndel.org/api/dive/get/?login="); - strncat(url, user_id, sizeof(url) - strlen(url) - 1); - msg = soup_message_new("GET", url); - soup_message_headers_append(msg->request_headers, "Accept", "text/xml"); - soup_session_send_message(session, msg); - if SOUP_STATUS_IS_SUCCESSFUL(msg->status_code) { - *len = (guint)msg->response_body->length; - *data = strdup((gchar *)msg->response_body->data); - ret = TRUE; - } else { - *len = 0; - *data = NULL; - } - *status_code = msg->status_code; - soup_session_abort(session); - g_object_unref(G_OBJECT(msg)); - g_object_unref(G_OBJECT(session)); - return ret; -} - -/* requires that there is a <download> or <error> tag under the <root> tag */ -static void download_dialog_traverse_xml(xmlNodePtr node, guint *download_status) -{ - xmlNodePtr cur_node; - for (cur_node = node; cur_node; cur_node = cur_node->next) { - if ((!strcmp((const char *)cur_node->name, (const char *)"download")) && - (!strcmp((const char *)xmlNodeGetContent(cur_node), (const char *)"ok"))) { - *download_status = DD_STATUS_OK; - return; - } else if (!strcmp((const char *)cur_node->name, (const char *)"error")) { - *download_status = DD_STATUS_ERROR_ID; - return; - } - } -} - -static guint download_dialog_parse_response(gchar *xmldata, guint len) -{ - xmlNodePtr root; - xmlDocPtr doc = xmlParseMemory(xmldata, len); - guint status = DD_STATUS_ERROR_PARSE; - - if (!doc) - return DD_STATUS_ERROR_PARSE; - root = xmlDocGetRootElement(doc); - if (!root) { - status = DD_STATUS_ERROR_PARSE; - goto end; - } - if (root->children) - download_dialog_traverse_xml(root->children, &status); - end: - xmlFreeDoc(doc); - return status; -} - -static void download_dialog_connect_cb(GtkWidget *w, gpointer data) -{ - struct download_dialog_state *state = (struct download_dialog_state *)data; - const gchar *uid = gtk_entry_get_text(GTK_ENTRY(state->uid)); - guint len, status_connect, status_xml; - gchar *xmldata; - gboolean ret; - gchar err[256] = {0}; - - gtk_label_set_text(GTK_LABEL(state->status), _("Connecting...")); - gtk_widget_set_sensitive(state->apply, FALSE); - ret = webservice_request_user_xml(uid, &xmldata, &len, &status_connect); - if (ret) { - status_xml = download_dialog_parse_response(xmldata, len); - gtk_label_set_text(GTK_LABEL(state->status), download_dialog_status_text(status_xml)); - if (status_xml != DD_STATUS_OK) - ret = FALSE; - } else { - snprintf(err, sizeof(err), "%s %u!", download_dialog_status_text(DD_STATUS_ERROR_CONNECT), status_connect); - gtk_label_set_text(GTK_LABEL(state->status), err); - } - state->xmldata = xmldata; - state->xmldata_len = len; - gtk_widget_set_sensitive(state->apply, ret); -} - -static void download_dialog_release_xml(struct download_dialog_state *state) -{ - if (state->xmldata) - free((void *)state->xmldata); -} - -static void clear_table(struct dive_table *table) -{ - int i; - for (i = 0; i < table->nr; i++) - free(table->dives[i]); - table->nr = 0; -} - -static void download_dialog_response_cb(GtkDialog *d, gint response, gpointer data) -{ - struct download_dialog_state *state = (struct download_dialog_state *)data; - switch (response) { - case GTK_RESPONSE_HELP: - /* open webservice api page */ - subsurface_launch_for_uri("http://api.hohndel.org/"); - break; - case GTK_RESPONSE_ACCEPT: - /* apply download */ - clear_table(&gps_location_table); - parse_xml_buffer(_("Webservice"), state->xmldata, state->xmldata_len, &gps_location_table, NULL); - /* now merge the data in the gps_location table into the dive_table */ - if (merge_locations_into_dives()) { - mark_divelist_changed(TRUE); -#if USE_GTK_UI - dive_list_update_dives(); -#endif - } - /* store last entered uid in config */ - subsurface_set_conf("webservice_uid", gtk_entry_get_text(GTK_ENTRY(state->uid))); - default: - case GTK_RESPONSE_DELETE_EVENT: - gtk_widget_destroy(GTK_WIDGET(d)); - download_dialog_release_xml(state); - free(state); - } -} - -static gboolean is_automatic_fix(struct dive *gpsfix) -{ - if (gpsfix && gpsfix->location && - (!strcmp(gpsfix->location, "automatic fix") || - !strcmp(gpsfix->location, "Auto-created dive"))) - return TRUE; - return FALSE; -} - -#define SAME_GROUP 6 * 3600 // six hours - -/* returns TRUE if dive_table was changed */ -static gboolean merge_locations_into_dives(void) -{ - int i, nr = 0, changed = 0; - struct dive *gpsfix, *last_named_fix = NULL, *dive; - - sort_table(&gps_location_table); - - for_each_gps_location(i, gpsfix) { - if (is_automatic_fix(gpsfix)) { - dive = find_dive_including(gpsfix->when); - if (dive && !dive_has_gps_location(dive)) { -#if DEBUG_WEBSERVICE - struct tm tm; - utc_mkdate(gpsfix->when, &tm); - printf("found dive named %s @ %04d-%02d-%02d %02d:%02d:%02d\n", - gpsfix->location, - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif - changed++; - copy_gps_location(gpsfix, dive); - } - } else { - if (last_named_fix && dive_within_time_range(last_named_fix, gpsfix->when, SAME_GROUP)) { - nr++; - } else { - nr = 1; - last_named_fix = gpsfix; - } - dive = find_dive_n_near(gpsfix->when, nr, SAME_GROUP); - if (dive) { - if (!dive_has_gps_location(dive)) { - copy_gps_location(gpsfix, dive); - changed++; - } - if (!dive->location) { - dive->location = strdup(gpsfix->location); - changed++; - } - } else { - struct tm tm; - utc_mkdate(gpsfix->when, &tm); -#if DEBUG_WEBSERVICE - printf("didn't find dive matching gps fix named %s @ %04d-%02d-%02d %02d:%02d:%02d\n", - gpsfix->location, - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif - } - } - } - return changed > 0; -} - -void webservice_download_dialog(void) -{ - const guint pad = 6; - /* user entered value should be stored in the config */ - const gchar *current_uid = subsurface_get_conf("webservice_uid"); - GtkWidget *dialog, *vbox, *status, *info, *uid; - GtkWidget *frame_uid, *frame_status, *download, *image, *apply; - struct download_dialog_state *state = calloc(1, sizeof(struct download_dialog_state)); - gboolean has_previous_uid = TRUE; - - if (!current_uid) { - current_uid = ""; - has_previous_uid = FALSE; - } - - dialog = gtk_dialog_new_with_buttons(_("Download From Web Service"), - GTK_WINDOW(main_window), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_APPLY, - GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, - GTK_RESPONSE_REJECT, - GTK_STOCK_HELP, - GTK_RESPONSE_HELP, - NULL); - - apply = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - gtk_widget_set_sensitive(apply, FALSE); - - vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - info = gtk_label_new(_("Enter a user identifier and press 'Download'." - " Once the download is complete you can press 'Apply'" - " if you wish to apply the changes.")); - gtk_label_set_line_wrap(GTK_LABEL(info), TRUE); - gtk_box_pack_start(GTK_BOX(vbox), info, FALSE, TRUE, 0); - gtk_misc_set_padding(GTK_MISC(info), pad, pad); - - frame_uid = gtk_frame_new(_("User Identifier")); - gtk_box_pack_start(GTK_BOX(vbox), frame_uid, FALSE, TRUE, pad); - uid = gtk_entry_new(); - gtk_container_add(GTK_CONTAINER(frame_uid), uid); - gtk_entry_set_max_length(GTK_ENTRY(uid), 30); - gtk_entry_set_text(GTK_ENTRY(uid), current_uid); - - download = gtk_button_new_with_label(_(" Download")); - image = gtk_image_new_from_stock(GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(download), image); - gtk_box_pack_start(GTK_BOX(vbox), download, FALSE, TRUE, pad); - g_signal_connect(download, "clicked", G_CALLBACK(download_dialog_connect_cb), (gpointer)state); - - frame_status = gtk_frame_new(_("Status")); - status = gtk_label_new(_("Idle")); - gtk_box_pack_start(GTK_BOX(vbox), frame_status, FALSE, TRUE, pad); - gtk_container_add(GTK_CONTAINER(frame_status), status); - gtk_misc_set_padding(GTK_MISC(status), pad, pad); - - state->uid = uid; - state->status = status; - state->apply = apply; - - g_signal_connect(dialog, "response", G_CALLBACK(download_dialog_response_cb), (gpointer)state); - gtk_widget_show_all(dialog); - if (has_previous_uid) - free((void *)current_uid); -} - -static gboolean divelogde_dialog(const char **user, const char **pass) -{ - GtkWidget *dialog, *vbox, *info, *frame_user, *frame_pass, *uid, *pwd; - gboolean ret = FALSE; - - *user = subsurface_get_conf("divelogde_user"); - *pass = subsurface_get_conf("divelogde_pass"); - dialog = gtk_dialog_new_with_buttons(_("Upload to divelogs.de"), - GTK_WINDOW(main_window), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_APPLY, - GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, - GTK_RESPONSE_REJECT, - NULL); - vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - info = gtk_label_new(_("Please enter your userid and password for divelogs.de. " - "The selected dives will be added to your account")); - gtk_label_set_line_wrap(GTK_LABEL(info), TRUE); - gtk_box_pack_start(GTK_BOX(vbox), info, FALSE, TRUE, 0); - gtk_misc_set_padding(GTK_MISC(info), 6, 6); - - frame_user = gtk_frame_new(_("User Identifier")); - gtk_box_pack_start(GTK_BOX(vbox), frame_user, FALSE, TRUE, 6); - uid = gtk_entry_new(); - gtk_container_add(GTK_CONTAINER(frame_user), uid); - gtk_entry_set_max_length(GTK_ENTRY(uid), 40); - gtk_entry_set_text(GTK_ENTRY(uid), *user ?: ""); - gtk_entry_set_activates_default(GTK_ENTRY(uid), TRUE); - - frame_pass = gtk_frame_new(_("Password")); - gtk_box_pack_start(GTK_BOX(vbox), frame_pass, FALSE, TRUE, 6); - pwd = gtk_entry_new(); - gtk_container_add(GTK_CONTAINER(frame_pass), pwd); - gtk_entry_set_max_length(GTK_ENTRY(pwd), 40); - gtk_entry_set_text(GTK_ENTRY(pwd), *pass ?: ""); - gtk_entry_set_visibility(GTK_ENTRY(pwd), FALSE); - gtk_entry_set_activates_default(GTK_ENTRY(pwd), TRUE); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - - gtk_widget_show_all(dialog); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - free((void*)*user); - free((void*)*pass); - *user = strdup(gtk_entry_get_text(GTK_ENTRY(uid))); - *pass = strdup(gtk_entry_get_text(GTK_ENTRY(pwd))); - subsurface_set_conf("divelogde_user", *user); - subsurface_set_conf("divelogde_pass", *pass); - ret = TRUE; - } - gtk_widget_destroy(dialog); - return ret; -} - -int divelogde_upload(char *fn, char **error) -{ - SoupMessage *msg; - SoupMultipart *multipart; - SoupSession *session; - SoupBuffer *sbuf; - gboolean ret = FALSE; -#ifdef __MINGW32__ - /* for odd reasons I can't seem to get https connections to work - * with mingw32 when cross-building the Windows binaries... so fall - * back to http for now */ - char url[256] = "http://divelogs.de/DivelogsDirectImport.php"; -#else - char url[256] = "https://divelogs.de/DivelogsDirectImport.php"; -#endif - const char *pass = NULL; - const char *user = NULL; - struct memblock mem; - - if (readfile(fn, &mem) < 0) - return ret; - if (!divelogde_dialog(&user, &pass)) - return TRUE; - sbuf = soup_buffer_new(SOUP_MEMORY_STATIC, mem.buffer, mem.size); - session = soup_session_async_new(); - multipart = soup_multipart_new(SOUP_FORM_MIME_TYPE_MULTIPART); - soup_multipart_append_form_string(multipart, "user", user); - soup_multipart_append_form_string(multipart, "pass", pass); - - soup_multipart_append_form_file(multipart, "userfile", fn, NULL, sbuf); - msg = soup_form_request_new_from_multipart(url, multipart); - soup_message_headers_append(msg->request_headers, "Accept", "text/xml"); - soup_session_send_message(session, msg); - if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) { - *error = strdup(msg->response_body->data); - ret = TRUE; - } else { - *error = strdup(msg->reason_phrase); - } - soup_session_abort(session); - g_object_unref(G_OBJECT(msg)); - g_object_unref(G_OBJECT(session)); - return ret; -} |