/* * FIXME: make this bullet proof wrt uri scheme. */ static char * url (GSList const *args, void *user_data) { char *resolved_path; char *ret; #ifdef CCSS_WITH_SOUP char *given_path; SoupURI *uri; g_return_val_if_fail (args, NULL); given_path = g_strdup_printf ("file:///%s", (char const *) args->data); uri = soup_uri_new (given_path); g_free (given_path), given_path = NULL; resolved_path = gtk_rc_find_pixmap_in_path (gtk_settings_get_default (), NULL, uri->path); soup_uri_set_path (uri, resolved_path); g_free (resolved_path), resolved_path = NULL; ret = soup_uri_to_string (uri, false); soup_uri_free (uri), uri = NULL; #else char const *given_path; g_return_val_if_fail (args, NULL); given_path = (char const *) args->data; resolved_path = gtk_rc_find_pixmap_in_path (gtk_settings_get_default (), NULL, given_path); ret = g_strdup_printf ("file:///%s", resolved_path); g_free (resolved_path), resolved_path = NULL; #endif return ret; }
/** * self: The SeahorseSource to use as server for the uri * path: The path to add to the SOUP uri * * Returns: A #SoupUri with server, port and paths */ static SoupURI* get_http_server_uri (SeahorseHKPSource *self, const char *path) { g_autoptr(SoupURI) uri = NULL; g_autofree gchar *server = NULL; gchar *port; g_object_get (self, "key-server", &server, NULL); g_return_val_if_fail (server != NULL, NULL); uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); /* If it already has a port then use that */ port = strchr (server, ':'); if (port) { *port++ = '\0'; soup_uri_set_port (uri, atoi (port)); } else { /* default HKP port */ soup_uri_set_port (uri, 11371); } soup_uri_set_host (uri, server); soup_uri_set_path (uri, path); return g_steal_pointer (&uri); }
static SoupURI * suburi_new (SoupURI *base, const char *first, ...) { va_list args; GPtrArray *arg_array; const char *arg; char *subpath; SoupURI *ret; arg_array = g_ptr_array_new (); g_ptr_array_add (arg_array, (char*)soup_uri_get_path (base)); g_ptr_array_add (arg_array, (char*)first); va_start (args, first); while ((arg = va_arg (args, const char *)) != NULL) g_ptr_array_add (arg_array, (char*)arg); g_ptr_array_add (arg_array, NULL); subpath = g_build_filenamev ((char**)arg_array->pdata); g_ptr_array_unref (arg_array); ret = soup_uri_copy (base); soup_uri_set_path (ret, subpath); g_free (subpath); va_end (args); return ret; }
static GSocketAddressEnumerator * soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable) { SoupAddress *addr = SOUP_ADDRESS (connectable); SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); GSocketAddressEnumerator *proxy_enum; SoupURI *uri; char *uri_string; /* We cheerily assume "http" here because you shouldn't be * using SoupAddress any more if you're not doing HTTP anyway. */ uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, priv->protocol ? priv->protocol : "http"); soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr)); soup_uri_set_port (uri, priv->port); soup_uri_set_path (uri, ""); uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE); proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, "uri", uri_string, NULL); g_free (uri_string); soup_uri_free (uri); return proxy_enum; }
/* Server handlers for "*" work but are separate from handlers for * all other URIs. #590751 */ static void do_star_test (void) { SoupSession *session; SoupMessage *msg; SoupURI *star_uri; const char *handled_by; debug_printf (1, "\nOPTIONS *\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); star_uri = soup_uri_copy (base_uri); soup_uri_set_path (star_uri, "*"); debug_printf (1, " Testing with no handler\n"); msg = soup_message_new_from_uri ("OPTIONS", star_uri); soup_session_send_message (session, msg); if (msg->status_code != SOUP_STATUS_NOT_FOUND) { debug_printf (1, " Unexpected response: %d %s\n", msg->status_code, msg->reason_phrase); errors++; } handled_by = soup_message_headers_get_one (msg->response_headers, "X-Handled-By"); if (handled_by) { /* Should have been rejected by SoupServer directly */ debug_printf (1, " Message reached handler '%s'\n", handled_by); errors++; } g_object_unref (msg); soup_server_add_handler (server, "*", server_star_callback, NULL, NULL); debug_printf (1, " Testing with handler\n"); msg = soup_message_new_from_uri ("OPTIONS", star_uri); soup_session_send_message (session, msg); if (msg->status_code != SOUP_STATUS_OK) { debug_printf (1, " Unexpected response: %d %s\n", msg->status_code, msg->reason_phrase); errors++; } handled_by = soup_message_headers_get_one (msg->response_headers, "X-Handled-By"); if (!handled_by) { debug_printf (1, " Message did not reach handler!\n"); errors++; } else if (strcmp (handled_by, "star_callback") != 0) { debug_printf (1, " Message reached incorrect handler '%s'\n", handled_by); errors++; } g_object_unref (msg); soup_test_session_abort_unref (session); soup_uri_free (star_uri); }
static SoupURI * get_uri_to_sig (SoupURI *uri) { g_autofree gchar *sig_path = NULL; SoupURI *sig_uri = soup_uri_copy (uri); sig_path = g_strconcat (soup_uri_get_path (uri), ".sig", NULL); soup_uri_set_path (sig_uri, sig_path); return sig_uri; }
static void do_auth_close_test (void) { SoupServer *server; SoupAuthDomain *basic_auth_domain; SoupURI *uri; AuthCloseData acd; server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); uri = soup_test_server_get_uri (server, "http", NULL); soup_uri_set_path (uri, "/close"); basic_auth_domain = soup_auth_domain_basic_new ( SOUP_AUTH_DOMAIN_REALM, "auth-test", SOUP_AUTH_DOMAIN_ADD_PATH, "/", SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback, NULL); soup_server_add_auth_domain (server, basic_auth_domain); g_object_unref (basic_auth_domain); g_signal_connect (server, "request-started", G_CALLBACK (auth_close_request_started), NULL); acd.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (acd.session, "authenticate", G_CALLBACK (auth_close_authenticate), &acd); acd.msg = soup_message_new_from_uri ("GET", uri); soup_uri_free (uri); soup_session_send_message (acd.session, acd.msg); soup_test_assert_message_status (acd.msg, SOUP_STATUS_OK); g_object_unref (acd.msg); soup_test_session_abort_unref (acd.session); soup_test_server_quit_unref (server); }
static void do_proxy_redirect_test (void) { SoupSession *session; SoupURI *proxy_uri, *req_uri, *new_uri; SoupMessage *msg; debug_printf (1, "\nTesting redirection through proxy\n"); proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_PROXY_URI, proxy_uri, NULL); soup_uri_free (proxy_uri); req_uri = soup_uri_new (HTTPS_SERVER); soup_uri_set_path (req_uri, "/redirected"); msg = soup_message_new_from_uri (SOUP_METHOD_GET, req_uri); soup_message_headers_append (msg->request_headers, "Connection", "close"); soup_session_send_message (session, msg); new_uri = soup_message_get_uri (msg); if (!strcmp (req_uri->path, new_uri->path)) { debug_printf (1, " message was not redirected!\n"); errors++; } soup_uri_free (req_uri); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { debug_printf (1, " unexpected status %d %s!\n", msg->status_code, msg->reason_phrase); errors++; } g_object_unref (msg); soup_test_session_abort_unref (session); }
const gchar * soupcut_server_build_uri(SoupServer *server, const gchar *path) { SoupAddress *address; SoupURI *uri; const gchar *uri_string; g_object_get(server, SOUP_SERVER_INTERFACE, &address, NULL); uri = soup_uri_new(NULL); soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTP); soup_uri_set_host(uri, "localhost"); soup_uri_set_port(uri, soup_address_get_port(address)); soup_uri_set_path(uri, path); uri_string = cut_take_string(soup_uri_to_string(uri, FALSE)); soup_uri_free(uri); return uri_string; }
static void network_set_soup_session_proxy (SoupSession *session, ProxyDetectMode mode, const gchar *host, guint port, const gchar *user, const gchar *password) { SoupURI *uri = NULL; switch (mode) { case PROXY_DETECT_MODE_AUTO: /* Sets proxy-resolver to the default resolver, this unsets proxy-uri. */ g_object_set (G_OBJECT (session), SOUP_SESSION_PROXY_RESOLVER, g_proxy_resolver_get_default (), NULL); break; case PROXY_DETECT_MODE_NONE: /* Sets proxy-resolver to NULL, this unsets proxy-uri. */ g_object_set (G_OBJECT (session), SOUP_SESSION_PROXY_RESOLVER, NULL, NULL); break; case PROXY_DETECT_MODE_MANUAL: uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); soup_uri_set_host (uri, host); soup_uri_set_port (uri, port); soup_uri_set_user (uri, user); soup_uri_set_password (uri, password); soup_uri_set_path (uri, "/"); if (SOUP_URI_IS_VALID (uri)) { /* Sets proxy-uri, this unsets proxy-resolver. */ g_object_set (G_OBJECT (session), SOUP_SESSION_PROXY_URI, uri, NULL); } soup_uri_free (uri); break; } }
SoupMessageQueueItem * soup_session_make_connect_message (SoupSession *session, SoupAddress *server_addr) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupURI *uri; SoupMessage *msg; uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS); soup_uri_set_host (uri, soup_address_get_name (server_addr)); soup_uri_set_port (uri, soup_address_get_port (server_addr)); soup_uri_set_path (uri, ""); msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); soup_uri_free (uri); /* Call the base implementation of soup_session_queue_message * directly, to add msg to the SoupMessageQueue and cause all * the right signals to be emitted. */ queue_message (session, msg, tunnel_connected, NULL); return soup_message_queue_lookup (priv->queue, msg); }
gboolean ostree_repo_pull (OstreeRepo *self, const char *remote_name, char **refs_to_fetch, OstreeRepoPullFlags flags, OstreeAsyncProgress *progress, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GHashTableIter hash_iter; gpointer key, value; gboolean tls_permissive = FALSE; OstreeFetcherConfigFlags fetcher_flags = 0; gs_free char *remote_key = NULL; gs_free char *path = NULL; gs_free char *baseurl = NULL; gs_free char *summary_data = NULL; gs_unref_hashtable GHashTable *requested_refs_to_fetch = NULL; gs_unref_hashtable GHashTable *updated_refs = NULL; gs_unref_hashtable GHashTable *commits_to_fetch = NULL; gs_free char *remote_mode_str = NULL; GSource *queue_src = NULL; OtPullData pull_data_real = { 0, }; OtPullData *pull_data = &pull_data_real; SoupURI *summary_uri = NULL; GKeyFile *config = NULL; GKeyFile *remote_config = NULL; char **configured_branches = NULL; guint64 bytes_transferred; guint64 start_time; guint64 end_time; pull_data->async_error = error; pull_data->main_context = g_main_context_ref_thread_default (); pull_data->loop = g_main_loop_new (pull_data->main_context, FALSE); pull_data->flags = flags; pull_data->repo = self; pull_data->progress = progress; pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, (GDestroyNotify)g_variant_unref, NULL); pull_data->requested_content = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); pull_data->requested_metadata = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); start_time = g_get_monotonic_time (); pull_data->remote_name = g_strdup (remote_name); config = ostree_repo_get_config (self); remote_key = g_strdup_printf ("remote \"%s\"", pull_data->remote_name); if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error)) goto out; pull_data->base_uri = soup_uri_new (baseurl); #ifdef HAVE_GPGME if (!ot_keyfile_get_boolean_with_default (config, remote_key, "gpg-verify", TRUE, &pull_data->gpg_verify, error)) goto out; #else pull_data->gpg_verify = FALSE; #endif if (!ot_keyfile_get_boolean_with_default (config, remote_key, "tls-permissive", FALSE, &tls_permissive, error)) goto out; if (tls_permissive) fetcher_flags |= OSTREE_FETCHER_FLAGS_TLS_PERMISSIVE; pull_data->fetcher = ostree_fetcher_new (pull_data->repo->tmp_dir, fetcher_flags); if (!pull_data->base_uri) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to parse url '%s'", baseurl); goto out; } if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error)) goto out; if (!ot_keyfile_get_value_with_default (remote_config, "core", "mode", "bare", &remote_mode_str, error)) goto out; if (!ostree_repo_mode_from_string (remote_mode_str, &pull_data->remote_mode, error)) goto out; if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE_Z2) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't pull from archives with mode \"%s\"", remote_mode_str); goto out; } requested_refs_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); updated_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); commits_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); if (refs_to_fetch != NULL) { char **strviter; for (strviter = refs_to_fetch; *strviter; strviter++) { const char *branch = *strviter; char *contents; if (ostree_validate_checksum_string (branch, NULL)) { char *key = g_strdup (branch); g_hash_table_insert (commits_to_fetch, key, key); } else { if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error)) goto out; /* Transfer ownership of contents */ g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents); } } } else { GError *temp_error = NULL; gboolean fetch_all_refs; configured_branches = g_key_file_get_string_list (config, remote_key, "branches", NULL, &temp_error); if (configured_branches == NULL && temp_error != NULL) { if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { g_clear_error (&temp_error); fetch_all_refs = TRUE; } else { g_propagate_error (error, temp_error); goto out; } } else fetch_all_refs = FALSE; if (fetch_all_refs) { summary_uri = soup_uri_copy (pull_data->base_uri); path = g_build_filename (soup_uri_get_path (summary_uri), "refs", "summary", NULL); soup_uri_set_path (summary_uri, path); if (!fetch_uri_contents_utf8_sync (pull_data, summary_uri, &summary_data, cancellable, error)) goto out; if (!parse_ref_summary (summary_data, &requested_refs_to_fetch, error)) goto out; } else { char **branches_iter = configured_branches; if (!(branches_iter && *branches_iter)) g_print ("No configured branches for remote %s\n", pull_data->remote_name); for (;branches_iter && *branches_iter; branches_iter++) { const char *branch = *branches_iter; char *contents; if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error)) goto out; /* Transfer ownership of contents */ g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents); } } } if (!ostree_repo_prepare_transaction (pull_data->repo, &pull_data->transaction_resuming, cancellable, error)) goto out; pull_data->metadata_objects_to_fetch = ot_waitable_queue_new (); pull_data->metadata_objects_to_scan = ot_waitable_queue_new (); pull_data->metadata_thread = g_thread_new ("metadatascan", metadata_thread_main, pull_data); g_hash_table_iter_init (&hash_iter, commits_to_fetch); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { const char *commit = value; ot_waitable_queue_push (pull_data->metadata_objects_to_scan, pull_worker_message_new (PULL_MSG_SCAN, ostree_object_name_serialize (commit, OSTREE_OBJECT_TYPE_COMMIT))); } g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { const char *ref = key; const char *sha256 = value; ot_waitable_queue_push (pull_data->metadata_objects_to_scan, pull_worker_message_new (PULL_MSG_SCAN, ostree_object_name_serialize (sha256, OSTREE_OBJECT_TYPE_COMMIT))); g_hash_table_insert (updated_refs, g_strdup (ref), g_strdup (sha256)); } { queue_src = ot_waitable_queue_create_source (pull_data->metadata_objects_to_fetch); g_source_set_callback (queue_src, (GSourceFunc)on_metadata_objects_to_fetch_ready, pull_data, NULL); g_source_attach (queue_src, pull_data->main_context); g_source_unref (queue_src); } /* Prime the message queue */ pull_data->idle_serial++; ot_waitable_queue_push (pull_data->metadata_objects_to_scan, pull_worker_message_new (PULL_MSG_MAIN_IDLE, GUINT_TO_POINTER (pull_data->idle_serial))); /* Now await work completion */ if (!run_mainloop_monitor_fetcher (pull_data)) goto out; g_hash_table_iter_init (&hash_iter, updated_refs); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { const char *ref = key; const char *checksum = value; gs_free char *remote_ref = NULL; gs_free char *original_rev = NULL; remote_ref = g_strdup_printf ("%s/%s", pull_data->remote_name, ref); if (!ostree_repo_resolve_rev (pull_data->repo, remote_ref, TRUE, &original_rev, error)) goto out; if (original_rev && strcmp (checksum, original_rev) == 0) { g_print ("remote %s is unchanged from %s\n", remote_ref, original_rev); } else { ostree_repo_transaction_set_ref (pull_data->repo, pull_data->remote_name, ref, checksum); g_print ("remote %s is now %s\n", remote_ref, checksum); } } if (!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error)) goto out; end_time = g_get_monotonic_time (); bytes_transferred = ostree_fetcher_bytes_transferred (pull_data->fetcher); if (bytes_transferred > 0) { guint shift; if (bytes_transferred < 1024) shift = 1; else shift = 1024; g_print ("%u metadata, %u content objects fetched; %" G_GUINT64_FORMAT " %s transferred in %u seconds\n", pull_data->n_fetched_metadata, pull_data->n_fetched_content, (guint64)(bytes_transferred / shift), shift == 1 ? "B" : "KiB", (guint) ((end_time - start_time) / G_USEC_PER_SEC)); } ret = TRUE; out: if (pull_data->main_context) g_main_context_unref (pull_data->main_context); if (pull_data->loop) g_main_loop_unref (pull_data->loop); g_strfreev (configured_branches); g_clear_object (&pull_data->fetcher); g_free (pull_data->remote_name); if (pull_data->base_uri) soup_uri_free (pull_data->base_uri); if (queue_src) g_source_destroy (queue_src); if (pull_data->metadata_thread) { ot_waitable_queue_push (pull_data->metadata_objects_to_scan, pull_worker_message_new (PULL_MSG_QUIT, NULL)); g_thread_join (pull_data->metadata_thread); } g_clear_pointer (&pull_data->metadata_objects_to_scan, (GDestroyNotify) ot_waitable_queue_unref); g_clear_pointer (&pull_data->metadata_objects_to_fetch, (GDestroyNotify) ot_waitable_queue_unref); g_clear_pointer (&pull_data->scanned_metadata, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_metadata, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref); if (summary_uri) soup_uri_free (summary_uri); return ret; }
static void do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags) { SoupURI *uri = base_uri; PutTestData ptd; SoupMessage *msg; const char *client_md5, *server_md5; GChecksum *check; int i, length; debug_printf (1, "PUT"); if (flags & HACKY_STREAMING) debug_printf (1, " w/ hacky streaming"); else if (flags & PROPER_STREAMING) debug_printf (1, " w/ proper streaming"); if (flags & RESTART) { debug_printf (1, " and restart"); uri = soup_uri_copy (base_uri); soup_uri_set_path (uri, "/redirect"); } debug_printf (1, "\n"); ptd.session = session; setup_request_body (&ptd); ptd.streaming = flags & (HACKY_STREAMING | PROPER_STREAMING); check = g_checksum_new (G_CHECKSUM_MD5); length = 0; for (i = 0; i < 3; i++) { g_checksum_update (check, (guchar *)ptd.chunks[i]->data, ptd.chunks[i]->length); length += ptd.chunks[i]->length; } client_md5 = g_checksum_get_string (check); msg = soup_message_new_from_uri ("PUT", uri); soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED); soup_message_body_set_accumulate (msg->request_body, FALSE); soup_message_set_chunk_allocator (msg, error_chunk_allocator, NULL, NULL); if (flags & HACKY_STREAMING) { g_signal_connect (msg, "wrote_chunk", G_CALLBACK (write_next_chunk_streaming_hack), &ptd); if (flags & RESTART) { g_signal_connect (msg, "restarted", G_CALLBACK (restarted_streaming_hack), &ptd); } } else { g_signal_connect (msg, "wrote_chunk", G_CALLBACK (write_next_chunk), &ptd); } if (flags & PROPER_STREAMING) { soup_message_set_flags (msg, SOUP_MESSAGE_CAN_REBUILD); if (flags & RESTART) { g_signal_connect (msg, "restarted", G_CALLBACK (restarted_streaming), &ptd); } } g_signal_connect (msg, "wrote_headers", G_CALLBACK (write_next_chunk), &ptd); g_signal_connect (msg, "wrote_body_data", G_CALLBACK (wrote_body_data), &ptd); soup_session_send_message (session, msg); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { debug_printf (1, " message failed: %d %s\n", msg->status_code, msg->reason_phrase); errors++; } if (msg->request_body->data) { debug_printf (1, " msg->request_body set!\n"); errors++; } if (msg->request_body->length != length || length != ptd.nwrote) { debug_printf (1, " sent length mismatch: %d vs %d vs %d\n", (int)msg->request_body->length, length, ptd.nwrote); errors++; } server_md5 = soup_message_headers_get_one (msg->response_headers, "Content-MD5"); if (!server_md5 || strcmp (client_md5, server_md5) != 0) { debug_printf (1, " client/server data mismatch: %s vs %s\n", client_md5, server_md5 ? server_md5 : "(null)"); errors++; } g_object_unref (msg); g_checksum_free (check); if (uri != base_uri) soup_uri_free (uri); }
static guint upload_contact (EBookBackendWebdav *webdav, EContact *contact, gchar **reason, GCancellable *cancellable) { ESource *source; ESourceWebdav *webdav_extension; SoupMessage *message; gchar *uri; gchar *etag; const gchar *new_etag, *redir_uri; gchar *request; guint status; gboolean avoid_ifmatch; const gchar *extension_name; source = e_backend_get_source (E_BACKEND (webdav)); extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND; webdav_extension = e_source_get_extension (source, extension_name); source = e_backend_get_source (E_BACKEND (webdav)); uri = e_contact_get (contact, E_CONTACT_UID); if (uri == NULL) { g_warning ("can't upload contact without UID"); return 400; } message = soup_message_new (SOUP_METHOD_PUT, uri); soup_message_headers_append (message->request_headers, "User-Agent", USERAGENT); soup_message_headers_append (message->request_headers, "Connection", "close"); avoid_ifmatch = e_source_webdav_get_avoid_ifmatch (webdav_extension); /* some servers (like apache < 2.2.8) don't handle If-Match, correctly so * we can leave it out */ if (!avoid_ifmatch) { /* only override if etag is still the same on the server */ etag = e_contact_get (contact, E_CONTACT_REV); if (etag == NULL) { soup_message_headers_append ( message->request_headers, "If-None-Match", "*"); } else if (etag[0] == 'W' && etag[1] == '/') { g_warning ("we only have a weak ETag, don't use If-Match synchronisation"); } else { soup_message_headers_append ( message->request_headers, "If-Match", etag); g_free (etag); } } request = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); soup_message_set_request ( message, "text/vcard", SOUP_MEMORY_TEMPORARY, request, strlen (request)); status = send_and_handle_ssl (webdav, message, cancellable); new_etag = soup_message_headers_get_list (message->response_headers, "ETag"); redir_uri = soup_message_headers_get_list (message->response_headers, "Location"); /* set UID and REV fields */ e_contact_set (contact, E_CONTACT_REV, (gconstpointer) new_etag); if (redir_uri && *redir_uri) { if (!strstr (redir_uri, "://")) { /* it's a relative URI */ SoupURI *suri = soup_uri_new (uri); gchar *full_uri; soup_uri_set_path (suri, redir_uri); full_uri = soup_uri_to_string (suri, TRUE); e_contact_set (contact, E_CONTACT_UID, full_uri); g_free (full_uri); soup_uri_free (suri); } else { e_contact_set (contact, E_CONTACT_UID, redir_uri); } } else { e_contact_set (contact, E_CONTACT_UID, uri); } if (reason) { *reason = g_strdup (message->reason_phrase && *message->reason_phrase ? message->reason_phrase : (soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : _("Unknown error"))); } g_object_unref (message); g_free (request); g_free (uri); return status; }
static void got_headers (SoupMessage *req, SoupClientContext *client) { SoupServer *server = client->server; SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server); SoupURI *uri; SoupDate *date; char *date_string; SoupAuthDomain *domain; GSList *iter; gboolean rejected = FALSE; char *auth_user; if (!priv->raw_paths) { char *decoded_path; uri = soup_message_get_uri (req); decoded_path = soup_uri_decode (uri->path); soup_uri_set_path (uri, decoded_path); g_free (decoded_path); } /* Add required response headers */ date = soup_date_new_from_now (0); date_string = soup_date_to_string (date, SOUP_DATE_HTTP); soup_message_headers_replace (req->response_headers, "Date", date_string); g_free (date_string); soup_date_free (date); /* Now handle authentication. (We do this here so that if * the request uses "Expect: 100-continue", we can reject it * immediately rather than waiting for the request body to * be sent. */ for (iter = priv->auth_domains; iter; iter = iter->next) { domain = iter->data; if (soup_auth_domain_covers (domain, req)) { auth_user = soup_auth_domain_accepts (domain, req); if (auth_user) { client->auth_domain = g_object_ref (domain); client->auth_user = auth_user; return; } rejected = TRUE; } } /* If no auth domain rejected it, then it's ok. */ if (!rejected) return; for (iter = priv->auth_domains; iter; iter = iter->next) { domain = iter->data; if (soup_auth_domain_covers (domain, req)) soup_auth_domain_challenge (domain, req); } }
static guint parse_request_headers (SoupMessage *msg, char *headers, guint headers_len, SoupEncoding *encoding, gpointer sock) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); char *req_method, *req_path, *url; SoupHTTPVersion version; const char *req_host; guint status; SoupURI *uri; status = soup_headers_parse_request (headers, headers_len, msg->request_headers, &req_method, &req_path, &version); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) return status; g_object_set (G_OBJECT (msg), SOUP_MESSAGE_METHOD, req_method, SOUP_MESSAGE_HTTP_VERSION, version, NULL); g_free (req_method); /* Handle request body encoding */ *encoding = soup_message_headers_get_encoding (msg->request_headers); if (*encoding == SOUP_ENCODING_UNRECOGNIZED) { if (soup_message_headers_get_list (msg->request_headers, "Transfer-Encoding")) return SOUP_STATUS_NOT_IMPLEMENTED; else return SOUP_STATUS_BAD_REQUEST; } /* Generate correct context for request */ req_host = soup_message_headers_get_one (msg->request_headers, "Host"); if (req_host && strchr (req_host, '/')) { g_free (req_path); return SOUP_STATUS_BAD_REQUEST; } if (!strcmp (req_path, "*") && req_host) { /* Eg, "OPTIONS * HTTP/1.1" */ url = g_strdup_printf ("%s://%s", soup_socket_is_ssl (sock) ? "https" : "http", req_host); uri = soup_uri_new (url); if (uri) soup_uri_set_path (uri, "*"); g_free (url); } else if (*req_path != '/') { /* Must be an absolute URI */ uri = soup_uri_new (req_path); } else if (req_host) { url = g_strdup_printf ("%s://%s%s", soup_socket_is_ssl (sock) ? "https" : "http", req_host, req_path); uri = soup_uri_new (url); g_free (url); } else if (priv->http_version == SOUP_HTTP_1_0) { /* No Host header, no AbsoluteUri */ SoupAddress *addr = soup_socket_get_local_address (sock); uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, soup_socket_is_ssl (sock) ? SOUP_URI_SCHEME_HTTPS : SOUP_URI_SCHEME_HTTP); soup_uri_set_host (uri, soup_address_get_physical (addr)); soup_uri_set_port (uri, soup_address_get_port (addr)); soup_uri_set_path (uri, req_path); } else uri = NULL; g_free (req_path); if (!SOUP_URI_VALID_FOR_HTTP (uri)) { /* certainly not "a valid host on the server" (RFC2616 5.2.3) * SOUP_URI_VALID_FOR_HTTP also guards against uri == NULL */ if (uri) soup_uri_free (uri); return SOUP_STATUS_BAD_REQUEST; } soup_message_set_uri (msg, uri); soup_uri_free (uri); return SOUP_STATUS_OK; }
static SoupURI * fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error) { FwupdRemotePrivate *priv = GET_PRIVATE (self); SoupURI *uri; g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL); g_return_val_if_fail (url != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); /* create URI, substituting if required */ if (priv->firmware_base_uri != NULL) { g_autoptr(SoupURI) uri_tmp = NULL; g_autofree gchar *basename = NULL; g_autofree gchar *url2 = NULL; uri_tmp = soup_uri_new (url); if (uri_tmp == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to parse URI '%s'", url); return NULL; } basename = g_path_get_basename (soup_uri_get_path (uri_tmp)); url2 = g_build_filename (priv->firmware_base_uri, basename, NULL); uri = soup_uri_new (url2); if (uri == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to parse URI '%s'", url2); return NULL; } /* use the base URI of the metadata to build the full path */ } else if (g_strstr_len (url, -1, "/") == NULL) { g_autofree gchar *basename = NULL; g_autofree gchar *path = NULL; uri = soup_uri_new (priv->metadata_uri); if (uri == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to parse metadata URI '%s'", url); return NULL; } basename = g_path_get_dirname (soup_uri_get_path (uri)); path = g_build_filename (basename, url, NULL); soup_uri_set_path (uri, path); /* a normal URI */ } else { uri = soup_uri_new (url); if (uri == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to parse URI '%s'", url); return NULL; } } /* set the username and password */ if (priv->username != NULL) soup_uri_set_user (uri, priv->username); if (priv->password != NULL) soup_uri_set_password (uri, priv->password); return uri; }
static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) { SoupURI *uri = soup_message_get_uri (msg); const char *server_protocol = data; soup_message_headers_append (msg->response_headers, "X-Handled-By", "server_callback"); if (!strcmp (path, "*")) { debug_printf (1, " default server_callback got request for '*'!\n"); errors++; soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); return; } if (!strcmp (path, "/redirect")) { soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/"); return; } if (!strcmp (path, "/alias-redirect")) { SoupURI *redirect_uri; char *redirect_string; const char *redirect_protocol; redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol"); redirect_uri = soup_uri_copy (uri); soup_uri_set_scheme (redirect_uri, "foo"); if (!g_strcmp0 (redirect_protocol, "https")) soup_uri_set_port (redirect_uri, ssl_base_uri->port); else soup_uri_set_port (redirect_uri, base_uri->port); soup_uri_set_path (redirect_uri, "/alias-redirected"); redirect_string = soup_uri_to_string (redirect_uri, FALSE); soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string); g_free (redirect_string); soup_uri_free (redirect_uri); return; } else if (!strcmp (path, "/alias-redirected")) { soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_headers_append (msg->response_headers, "X-Redirected-Protocol", server_protocol); return; } if (!strcmp (path, "/slow")) { soup_server_pause_message (server, msg); g_object_set_data (G_OBJECT (msg), "server", server); soup_add_timeout (soup_server_get_async_context (server), 1000, timeout_finish_message, msg); } soup_message_set_status (msg, SOUP_STATUS_OK); if (!strcmp (uri->host, "foo")) { soup_message_set_response (msg, "text/plain", SOUP_MEMORY_STATIC, "foo-index", 9); return; } else { soup_message_set_response (msg, "text/plain", SOUP_MEMORY_STATIC, "index", 5); return; } }
static void do_soup_uri_null_tests (void) { SoupURI *uri, *uri2; char *uri_string; debug_printf (1, "\nsoup_uri_new (NULL)\n"); uri = soup_uri_new (NULL); if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) { debug_printf (1, " ERROR: soup_uri_new(NULL) returns valid URI?\n"); errors++; } /* This implicitly also verifies that none of these methods g_warn */ if (soup_uri_get_scheme (uri) || soup_uri_get_user (uri) || soup_uri_get_password (uri) || soup_uri_get_host (uri) || soup_uri_get_port (uri) || soup_uri_get_path (uri) || soup_uri_get_query (uri) || soup_uri_get_fragment (uri)) { debug_printf (1, " ERROR: soup_uri_new(NULL) returns non-empty URI?\n"); errors++; } expect_warning = TRUE; uri2 = soup_uri_new_with_base (uri, "/path"); if (uri2 || expect_warning) { debug_printf (1, " ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n"); errors++; expect_warning = FALSE; } expect_warning = TRUE; uri_string = soup_uri_to_string (uri, FALSE); if (expect_warning) { debug_printf (1, " ERROR: soup_uri_to_string didn't fail on NULL URI?\n"); errors++; expect_warning = FALSE; } else if (*uri_string) { debug_printf (1, " ERROR: soup_uri_to_string on NULL URI returned '%s'\n", uri_string); errors++; } g_free (uri_string); soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) { debug_printf (1, " ERROR: setting scheme on NULL URI makes it valid?\n"); errors++; } expect_warning = TRUE; uri_string = soup_uri_to_string (uri, FALSE); if (expect_warning) { debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n"); errors++; expect_warning = FALSE; } else if (strcmp (uri_string, "http:") != 0) { debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n", uri_string); errors++; } g_free (uri_string); soup_uri_set_host (uri, "localhost"); if (SOUP_URI_IS_VALID (uri)) { debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid?\n"); errors++; } if (SOUP_URI_VALID_FOR_HTTP (uri)) { debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid for http?\n"); errors++; } expect_warning = TRUE; uri_string = soup_uri_to_string (uri, FALSE); if (expect_warning) { debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n"); errors++; expect_warning = FALSE; } else if (strcmp (uri_string, "http://localhost/") != 0) { debug_printf (1, " ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n", uri_string); errors++; } g_free (uri_string); expect_warning = TRUE; uri2 = soup_uri_new_with_base (uri, "/path"); if (expect_warning) { debug_printf (1, " ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n"); errors++; expect_warning = FALSE; } else if (!uri2) { debug_printf (1, " ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n"); errors++; } if (uri2) { uri_string = soup_uri_to_string (uri2, FALSE); if (!uri_string) { debug_printf (1, " ERROR: soup_uri_to_string failed on uri2?\n"); errors++; } else if (strcmp (uri_string, "http://localhost/path") != 0) { debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n", uri_string); errors++; } g_free (uri_string); soup_uri_free (uri2); } expect_warning = TRUE; soup_uri_set_path (uri, NULL); if (expect_warning) { debug_printf (1, " ERROR: setting path to NULL doesn't warn\n"); errors++; expect_warning = FALSE; } if (!uri->path || *uri->path) { debug_printf (1, " ERROR: setting path to NULL != \"\"\n"); errors++; soup_uri_set_path (uri, ""); } uri_string = soup_uri_to_string (uri, FALSE); if (!uri_string) { debug_printf (1, " ERROR: soup_uri_to_string failed on complete URI?\n"); errors++; } else if (strcmp (uri_string, "http://localhost/") != 0) { debug_printf (1, " ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n", uri_string); errors++; } g_free (uri_string); if (!SOUP_URI_IS_VALID (uri)) { debug_printf (1, " ERROR: setting scheme+path on NULL URI doesn't make it valid?\n"); errors++; } if (!SOUP_URI_VALID_FOR_HTTP (uri)) { debug_printf (1, " ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n"); errors++; } soup_uri_free (uri); }
/* Open database containing policies for cookie domains. * Create database and setup table structure if it does not exist yet. */ static void _cookie_permission_manager_open_database(CookiePermissionManager *self) { CookiePermissionManagerPrivate *priv=self->priv; const gchar *configDir; gchar *error=NULL; gint success; sqlite3_stmt *statement=NULL; /* Close any open database */ if(priv->database) { g_free(priv->databaseFilename); priv->databaseFilename=NULL; sqlite3_close(priv->database); priv->database=NULL; g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE]); g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]); } /* Build path to database file */ configDir=midori_extension_get_config_dir(priv->extension); if(!configDir) return; if(katze_mkdir_with_parents(configDir, 0700)) { g_warning(_("Could not create configuration folder for extension: %s"), g_strerror(errno)); _cookie_permission_manager_error(self, _("Could not create configuration folder for extension.")); return; } /* Open database */ priv->databaseFilename=g_build_filename(configDir, COOKIE_PERMISSION_DATABASE, NULL); success=sqlite3_open(priv->databaseFilename, &priv->database); if(success!=SQLITE_OK) { g_warning(_("Could not open database of extenstion: %s"), sqlite3_errmsg(priv->database)); g_free(priv->databaseFilename); priv->databaseFilename=NULL; if(priv->database) sqlite3_close(priv->database); priv->database=NULL; _cookie_permission_manager_error(self, _("Could not open database of extension.")); return; } /* Create table structure if it does not exist */ success=sqlite3_exec(priv->database, "CREATE TABLE IF NOT EXISTS " "policies(domain text, value integer);", NULL, NULL, &error); if(success==SQLITE_OK) { success=sqlite3_exec(priv->database, "CREATE UNIQUE INDEX IF NOT EXISTS " "domain ON policies (domain);", NULL, NULL, &error); } if(success==SQLITE_OK) { success=sqlite3_exec(priv->database, "PRAGMA journal_mode=TRUNCATE;", NULL, NULL, &error); } if(success!=SQLITE_OK || error) { _cookie_permission_manager_error(self, _("Could not set up database structure of extension.")); if(error) { g_critical(_("Failed to execute database statement: %s"), error); sqlite3_free(error); } g_free(priv->databaseFilename); priv->databaseFilename=NULL; sqlite3_close(priv->database); priv->database=NULL; return; } // Delete all cookies allowed only in one session success=sqlite3_prepare_v2(priv->database, "SELECT domain FROM policies WHERE value=? ORDER BY domain DESC;", -1, &statement, NULL); if(statement && success==SQLITE_OK) success=sqlite3_bind_int(statement, 1, COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION); if(statement && success==SQLITE_OK) { while(sqlite3_step(statement)==SQLITE_ROW) { gchar *domain=(gchar*)sqlite3_column_text(statement, 0); GSList *cookies, *cookie; #ifdef HAVE_LIBSOUP_2_40_0 SoupURI *uri; uri=soup_uri_new(NULL); soup_uri_set_host(uri, domain); soup_uri_set_path(uri, "/"); cookies=soup_cookie_jar_get_cookie_list(priv->cookieJar, uri, TRUE); for(cookie=cookies; cookie; cookie=cookie->next) { soup_cookie_jar_delete_cookie(priv->cookieJar, (SoupCookie*)cookie->data); } soup_cookies_free(cookies); soup_uri_free(uri); #else cookies=soup_cookie_jar_all_cookies(priv->cookieJar); for(cookie=cookies; cookie; cookie=cookie->next) { if(soup_cookie_domain_matches((SoupCookie*)cookie->data, domain)) { soup_cookie_jar_delete_cookie(priv->cookieJar, (SoupCookie*)cookie->data); } } soup_cookies_free(cookies); #endif } } else g_warning(_("SQL fails: %s"), sqlite3_errmsg(priv->database)); sqlite3_finalize(statement); g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE]); g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]); }
static void _do_token_query(GSignondOauthPlugin *self, GSignondSessionData *session_data, GHashTable* params, GError** error) { gboolean force_request_body_auth; if (gsignond_dictionary_get_boolean(session_data, "ForceClientAuthViaRequestBody", &force_request_body_auth) && force_request_body_auth) { const gchar* client_id = gsignond_dictionary_get_string(session_data, "ClientId"); const gchar* client_secret = gsignond_dictionary_get_string(session_data, "ClientSecret"); if (client_id != NULL && client_secret != NULL) { g_hash_table_insert(params, "client_id", (gchar*)client_id); g_hash_table_insert(params, "client_secret", (gchar*)client_secret); } } const gchar* host = gsignond_dictionary_get_string(session_data, "TokenHost"); if (host == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "TokenHost not set"); return; } gsignond_oauth_plugin_check_host(host, gsignond_session_data_get_allowed_realms (session_data), error); if (*error != NULL) return; const gchar* token_path = gsignond_dictionary_get_string(session_data, "TokenPath"); if (token_path == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "TokenPath not set"); return; } const gchar* token_query_str = gsignond_dictionary_get_string(session_data, "TokenQuery"); SoupURI* open_url = soup_uri_new(NULL); soup_uri_set_scheme(open_url, SOUP_URI_SCHEME_HTTPS); soup_uri_set_host(open_url, host); soup_uri_set_path(open_url, token_path); guint port; if (gsignond_dictionary_get_uint32(session_data, "TokenPort", &port) != FALSE) soup_uri_set_port(open_url, port); if (token_query_str != NULL) { soup_uri_set_query(open_url, token_query_str); } SoupMessage *msg = soup_message_new_from_uri ("POST", open_url); soup_uri_free(open_url); gchar* formdata = soup_form_encode_hash(params); soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, formdata, strlen (formdata)); soup_session_queue_message (self->soup_session, msg, _http_token_callback, self); }
static void _request_new_token(GSignondOauthPlugin *self, GSignondSessionData *session_data, GError** error) { const gchar* response_type = gsignond_dictionary_get_string(session_data, "ResponseType"); const gchar* grant_type = gsignond_dictionary_get_string(session_data, "GrantType"); if (response_type != NULL && (g_strcmp0(response_type, "code") == 0 || g_strcmp0(response_type, "token") == 0)) { const gchar* host = gsignond_dictionary_get_string(session_data, "AuthHost"); if (host == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "AuthHost not set"); return; } gsignond_oauth_plugin_check_host(host, gsignond_session_data_get_allowed_realms (session_data), error); if (*error != NULL) return; const gchar* auth_path = gsignond_dictionary_get_string(session_data, "AuthPath"); if (auth_path == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "AuthPath not set"); return; } const gchar* client_id = gsignond_dictionary_get_string(session_data, "ClientId"); if (client_id == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "ClientId not set"); return; } SoupURI* open_url = soup_uri_new(NULL); soup_uri_set_scheme(open_url, SOUP_URI_SCHEME_HTTPS); soup_uri_set_host(open_url, host); soup_uri_set_path(open_url, auth_path); guint port; if (gsignond_dictionary_get_uint32(session_data, "AuthPort", &port) != FALSE) soup_uri_set_port(open_url, port); GHashTable* query = g_hash_table_new((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal); const gchar* auth_query_str = gsignond_dictionary_get_string(session_data, "AuthQuery"); GHashTable *auth_query = NULL; if (auth_query_str != NULL) { auth_query = soup_form_decode(auth_query_str); if (auth_query) // insert all key/values in AuthQuery into final query // according to RFC6749 section 3.1 g_hash_table_foreach(auth_query, _insert_key_value, query); } g_hash_table_insert(query, "response_type", (gchar*)response_type); g_hash_table_insert(query, "client_id", (gchar*)client_id); const gchar* redirect_uri = gsignond_dictionary_get_string(session_data, "RedirectUri"); if (redirect_uri != NULL) { g_hash_table_insert(query, "redirect_uri", (gchar*)redirect_uri); } const gchar* scope_str = gsignond_dictionary_get_string(session_data, "Scope"); if (scope_str != NULL) { g_hash_table_insert(query, "scope", (gchar*)scope_str); } gchar* state = gsignond_oauth_plugin_generate_random_data(20); g_hash_table_insert(query, "state", state); gsignond_dictionary_set_string(self->oauth2_request, "_Oauth2State", state); const gchar* username = gsignond_session_data_get_username(session_data); const gchar* secret = gsignond_session_data_get_secret(session_data); // login_hint is a google extension specified here: // https://developers.google.com/accounts/docs/OAuth2InstalledApp#formingtheurl gboolean use_login_hint = FALSE; if (gsignond_dictionary_get_boolean(session_data, "UseLoginHint", &use_login_hint) && use_login_hint && username != NULL) g_hash_table_insert(query, "login_hint", (gchar*)username); // display is a facebook extension specified here: // https://developers.facebook.com/docs/reference/dialogs/oauth/ const gchar* display = gsignond_dictionary_get_string(session_data, "UseDisplay"); if (display != NULL) { g_hash_table_insert(query, "display", (gchar*)display); } soup_uri_set_query_from_form(open_url, query); g_free(state); g_hash_table_unref(query); if (auth_query) g_hash_table_unref(auth_query); char* open_url_str = soup_uri_to_string(open_url, FALSE); soup_uri_free(open_url); GSignondSignonuiData* ui_request = gsignond_dictionary_new(); gsignond_signonui_data_set_open_url(ui_request, open_url_str); free(open_url_str); if (redirect_uri != NULL) gsignond_signonui_data_set_final_url(ui_request, redirect_uri); /* add username and password, for fields initialization (the * decision on whether to actually use them is up to the signon UI */ if (username != NULL) gsignond_signonui_data_set_username(ui_request, username); if (secret != NULL) gsignond_signonui_data_set_password(ui_request, secret); gsignond_plugin_user_action_required(GSIGNOND_PLUGIN(self), ui_request); gsignond_dictionary_unref(ui_request); } else if (grant_type != NULL && (g_strcmp0(grant_type, "password") == 0)) { const gchar* username = gsignond_session_data_get_username(session_data); const gchar* secret = gsignond_session_data_get_secret(session_data); if (username == NULL || secret == NULL) { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "username or password not set"); return; } GHashTable* params = g_hash_table_new((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal); g_hash_table_insert(params, "grant_type", "password"); g_hash_table_insert(params, "username", (gchar*)username); g_hash_table_insert(params, "password", (gchar*)secret); _set_scope(params, session_data); _do_token_query(self, session_data, params, error); g_hash_table_unref(params); } else if (grant_type != NULL && (g_strcmp0(grant_type, "client_credentials") == 0)) { GHashTable* params = g_hash_table_new((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal); g_hash_table_insert(params, "grant_type", "client_credentials"); _set_scope(params, session_data); _do_token_query(self, session_data, params, error); g_hash_table_unref(params); } else { *error = g_error_new(GSIGNOND_ERROR, GSIGNOND_ERROR_MISSING_DATA, "Unknown ResponseType or GrantType"); } }
int main (int argc, char **argv) { SoupServer *server; SoupURI *server_uri; int ret; test_init (argc, argv, no_test_entry); server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT); soup_server_add_handler (server, "/xmlrpc-server.php", server_callback, NULL, NULL); server_uri = soup_test_server_get_uri (server, "http", NULL); soup_uri_set_path (server_uri, "/xmlrpc-server.php"); uri = soup_uri_to_string (server_uri, FALSE); if (run_tests) { char *out, **tests, *path; char *list_argv[4]; GError *error = NULL; int i; list_argv[0] = NULL; list_argv[1] = "-S"; list_argv[2] = "-l"; list_argv[3] = NULL; if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) { g_printerr ("'xmlrpc-test -l' failed: %s\n", error->message); g_error_free (error); return 1; } tests = g_strsplit (out, "\n", -1); g_free (out); for (i = 0; tests[i] && *tests[i]; i++) { g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc/")); path = g_strdup_printf ("/xmlrpc-server/%s", tests[i] + strlen ("/xmlrpc/")); g_test_add_data_func (path, tests[i], do_one_xmlrpc_test); g_free (path); } ret = g_test_run (); g_strfreev (tests); } else { GMainLoop *loop; g_print ("Listening on port %d\n", soup_server_get_port (server)); loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); g_main_loop_unref (loop); ret = 0; } soup_test_server_quit_unref (server); soup_uri_free (server_uri); g_free (uri); if (run_tests) test_cleanup (); return ret; }
static gboolean cal_backend_http_load (ECalBackendHttp *backend, const gchar *uri, gchar **out_certificate_pem, GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { ECalBackendHttpPrivate *priv = backend->priv; ETimezoneCache *timezone_cache; SoupMessage *soup_message; SoupSession *soup_session; icalcomponent *icalcomp, *subcomp; icalcomponent_kind kind; const gchar *newuri; SoupURI *uri_parsed; GHashTable *old_cache; GSList *comps_in_cache; ESource *source; guint status_code; gulong cancel_id = 0; struct { SoupSession *soup_session; SoupMessage *soup_message; } cancel_data; timezone_cache = E_TIMEZONE_CACHE (backend); soup_session = backend->priv->soup_session; soup_message = cal_backend_http_new_message (backend, uri); if (soup_message == NULL) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Malformed URI: %s"), uri); return FALSE; } if (G_IS_CANCELLABLE (cancellable)) { cancel_data.soup_session = soup_session; cancel_data.soup_message = soup_message; cancel_id = g_cancellable_connect ( cancellable, G_CALLBACK (cal_backend_http_cancelled), &cancel_data, (GDestroyNotify) NULL); } source = e_backend_get_source (E_BACKEND (backend)); e_soup_ssl_trust_connect (soup_message, source); e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING); status_code = soup_session_send_message (soup_session, soup_message); if (G_IS_CANCELLABLE (cancellable)) g_cancellable_disconnect (cancellable, cancel_id); if (status_code == SOUP_STATUS_NOT_MODIFIED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); /* attempts with ETag can result in 304 status code */ g_object_unref (soup_message); priv->opened = TRUE; return TRUE; } /* Handle redirection ourselves */ if (SOUP_STATUS_IS_REDIRECTION (status_code)) { gboolean success; newuri = soup_message_headers_get_list ( soup_message->response_headers, "Location"); d (g_message ("Redirected from %s to %s\n", async_context->uri, newuri)); if (newuri != NULL) { gchar *redirected_uri; if (newuri[0]=='/') { g_warning ("Hey! Relative URI returned! Working around...\n"); uri_parsed = soup_uri_new (uri); soup_uri_set_path (uri_parsed, newuri); soup_uri_set_query (uri_parsed, NULL); /* g_free (newuri); */ newuri = soup_uri_to_string (uri_parsed, FALSE); g_message ("Translated URI: %s\n", newuri); soup_uri_free (uri_parsed); } redirected_uri = webcal_to_http_method (newuri, FALSE); success = cal_backend_http_load ( backend, redirected_uri, out_certificate_pem, out_certificate_errors, cancellable, error); g_free (redirected_uri); } else { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_BAD_REQUEST, _("Redirected to Invalid URI")); success = FALSE; } if (success) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); return success; } /* check status code */ if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) { /* because evolution knows only G_IO_ERROR_CANCELLED */ if (status_code == SOUP_STATUS_CANCELLED) g_set_error ( error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "%s", soup_message->reason_phrase); else g_set_error ( error, SOUP_HTTP_ERROR, status_code, "%s", soup_message->reason_phrase); if (status_code == SOUP_STATUS_SSL_FAILED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_SSL_FAILED); cal_backend_http_extract_ssl_failed_data (soup_message, out_certificate_pem, out_certificate_errors); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); empty_cache (backend); return FALSE; } e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); if (priv->store) { const gchar *etag; etag = soup_message_headers_get_one ( soup_message->response_headers, "ETag"); if (etag != NULL && *etag == '\0') etag = NULL; e_cal_backend_store_put_key_value (priv->store, "ETag", etag); } /* get the calendar from the response */ icalcomp = icalparser_parse_string (soup_message->response_body->data); if (!icalcomp) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Bad file format.")); g_object_unref (soup_message); empty_cache (backend); return FALSE; } if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Not a calendar.")); icalcomponent_free (icalcomp); g_object_unref (soup_message); empty_cache (backend); return FALSE; } g_object_unref (soup_message); soup_message = NULL; /* Update cache */ old_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); comps_in_cache = e_cal_backend_store_get_components (priv->store); while (comps_in_cache != NULL) { const gchar *uid; ECalComponent *comp = comps_in_cache->data; e_cal_component_get_uid (comp, &uid); g_hash_table_insert (old_cache, g_strdup (uid), e_cal_component_get_as_string (comp)); comps_in_cache = g_slist_remove (comps_in_cache, comps_in_cache->data); g_object_unref (comp); } kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend)); subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); e_cal_backend_store_freeze_changes (priv->store); while (subcomp) { ECalComponent *comp; icalcomponent_kind subcomp_kind; icalproperty *prop = NULL; subcomp_kind = icalcomponent_isa (subcomp); prop = icalcomponent_get_first_property (subcomp, ICAL_UID_PROPERTY); if (!prop && subcomp_kind == kind) { gchar *new_uid = e_cal_component_gen_uid (); icalcomponent_set_uid (subcomp, new_uid); g_free (new_uid); } if (subcomp_kind == kind) { comp = e_cal_component_new (); if (e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp))) { const gchar *uid; gpointer orig_key, orig_value; e_cal_component_get_uid (comp, &uid); if (!put_component_to_store (backend, comp)) { g_hash_table_remove (old_cache, uid); } else if (g_hash_table_lookup_extended (old_cache, uid, &orig_key, &orig_value)) { ECalComponent *orig_comp = e_cal_component_new_from_string (orig_value); e_cal_backend_notify_component_modified (E_CAL_BACKEND (backend), orig_comp, comp); g_hash_table_remove (old_cache, uid); if (orig_comp) g_object_unref (orig_comp); } else { e_cal_backend_notify_component_created (E_CAL_BACKEND (backend), comp); } } g_object_unref (comp); } else if (subcomp_kind == ICAL_VTIMEZONE_COMPONENT) { icaltimezone *zone; zone = icaltimezone_new (); icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp)); e_timezone_cache_add_timezone (timezone_cache, zone); icaltimezone_free (zone, 1); } subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT); } e_cal_backend_store_thaw_changes (priv->store); /* notify the removals */ g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, backend); g_hash_table_destroy (old_cache); /* free memory */ icalcomponent_free (icalcomp); priv->opened = TRUE; return TRUE; }
static void do_request_test (SoupSession *session, SoupURI *base_uri, int test) { SoupURI *uri = base_uri; PutTestData ptd; SoupMessage *msg; const char *client_md5, *server_md5; GChecksum *check; int i, length; gboolean streaming = FALSE; switch (test) { case 0: debug_printf (1, "PUT\n"); break; case 1: debug_printf (1, "PUT w/ streaming\n"); streaming = TRUE; break; case 2: debug_printf (1, "PUT w/ streaming and restart\n"); streaming = TRUE; uri = soup_uri_copy (base_uri); soup_uri_set_path (uri, "/redirect"); break; } ptd.session = session; make_put_chunk (&ptd.chunks[0], "one\r\n"); make_put_chunk (&ptd.chunks[1], "two\r\n"); make_put_chunk (&ptd.chunks[2], "three\r\n"); ptd.next = ptd.nwrote = ptd.nfreed = 0; ptd.streaming = streaming; check = g_checksum_new (G_CHECKSUM_MD5); length = 0; for (i = 0; i < 3; i++) { g_checksum_update (check, (guchar *)ptd.chunks[i]->data, ptd.chunks[i]->length); length += ptd.chunks[i]->length; } client_md5 = g_checksum_get_string (check); msg = soup_message_new_from_uri ("PUT", uri); soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED); soup_message_body_set_accumulate (msg->request_body, FALSE); soup_message_set_chunk_allocator (msg, error_chunk_allocator, NULL, NULL); if (streaming) { g_signal_connect (msg, "wrote_chunk", G_CALLBACK (write_next_chunk_streaming_hack), &ptd); g_signal_connect (msg, "restarted", G_CALLBACK (restarted_streaming_hack), &ptd); } else { g_signal_connect (msg, "wrote_chunk", G_CALLBACK (write_next_chunk), &ptd); } g_signal_connect (msg, "wrote_headers", G_CALLBACK (write_next_chunk), &ptd); g_signal_connect (msg, "wrote_body_data", G_CALLBACK (wrote_body_data), &ptd); soup_session_send_message (session, msg); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { debug_printf (1, " message failed: %d %s\n", msg->status_code, msg->reason_phrase); errors++; } if (msg->request_body->data) { debug_printf (1, " msg->request_body set!\n"); errors++; } if (msg->request_body->length != length || length != ptd.nwrote) { debug_printf (1, " sent length mismatch: %d vs %d vs %d\n", (int)msg->request_body->length, length, ptd.nwrote); errors++; } server_md5 = soup_message_headers_get_one (msg->response_headers, "Content-MD5"); if (!server_md5 || strcmp (client_md5, server_md5) != 0) { debug_printf (1, " client/server data mismatch: %s vs %s\n", client_md5, server_md5 ? server_md5 : "(null)"); errors++; } g_object_unref (msg); g_checksum_free (check); if (uri != base_uri) soup_uri_free (uri); }
static gboolean do_one_attempt (gpointer user_data) { GError *local_error = NULL; MinCloudAgentApp *self = user_data; gs_free char *uri_str = NULL; gs_unref_object SoupRequest *request = NULL; gs_unref_object GInputStream *instream = NULL; gs_unref_object GFileOutputStream *outstream = NULL; gs_unref_object GFile *authorized_keys_path = NULL; gs_unref_object SoupMessage *msg = NULL; SoupURI *uri = NULL; const int max_request_failures = 5; const char *state_description = NULL; /* Skip over already completed states */ again: switch (self->state) { case MCA_STATE_USER_DATA: if (g_file_query_exists (self->userdata_done_stamp, NULL)) { self->state++; goto again; } break; case MCA_STATE_OPENSSH_KEY: if (g_file_query_exists (self->authorized_keys_path, NULL)) { self->state++; goto again; } break; case MCA_STATE_DONE: goto out; } uri = soup_uri_new (NULL); soup_uri_set_scheme (uri, "http"); { gs_free char *addr_str = g_inet_address_to_string (self->addr); soup_uri_set_host (uri, addr_str); } soup_uri_set_port (uri, g_inet_socket_address_get_port (self->addr_port)); switch (self->state) { case MCA_STATE_USER_DATA: soup_uri_set_path (uri, "/2009-04-04/user-data"); state_description = "user-data"; break; case MCA_STATE_OPENSSH_KEY: soup_uri_set_path (uri, "/2009-04-04/meta-data/public-keys/0/openssh-key"); state_description = "openssh-key"; break; case MCA_STATE_DONE: g_assert_not_reached (); } uri_str = soup_uri_to_string (uri, FALSE); g_print ("Requesting '%s'...\n", uri_str); request = soup_session_request_uri (self->session, uri, &local_error); soup_uri_free (uri); if (!request) goto out; instream = soup_request_send (request, NULL, &local_error); if (!instream) goto out; msg = soup_request_http_get_message ((SoupRequestHTTP*) request); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { switch (msg->status_code) { case 404: case 410: { gs_log_structured_print_id_v (MCA_NOT_FOUND_ID, "No %s found", state_description); g_clear_error (&local_error); /* Note fallthrough to out, where we'll advance to the next state */ goto out; } default: /* Don't actually set the error, we will just continue to * the next phase. */ gs_log_structured_print_id_v (MCA_TIMEOUT_ID, "Error fetching %s: %u %s", uri_str, msg->status_code, soup_status_get_phrase (msg->status_code)); goto out; } } switch (self->state) { case MCA_STATE_USER_DATA: if (!handle_userdata_script (self, instream, self->cancellable, &local_error)) goto out; break; case MCA_STATE_OPENSSH_KEY: if (!handle_install_authorized_keys (self, instream, self->cancellable, &local_error)) goto out; break; default: g_assert_not_reached (); } g_assert (self->state != MCA_STATE_DONE); self->state++; self->request_failure_count = 0; out: if (local_error) { self->request_failure_count++; if (self->request_failure_count >= max_request_failures) { g_error_free (local_error); gs_log_structured_print_id_v (MCA_TIMEOUT_ID, "Reached maximum failed attempts (%u) to fetch metadata", self->request_failure_count); self->do_one_attempt_id = 0; self->running = FALSE; } else { gs_log_structured_print_id_v (MCA_REQUEST_FAILED_ID, "Request failed (count: %u): %s", self->request_failure_count, local_error->message); g_error_free (local_error); self->do_one_attempt_id = g_timeout_add_seconds (self->request_failure_count, do_one_attempt, self); } } else { /* If we advanced in state, schedule the next callback in an * idle so we're consistently scheduled out of an idle. */ if (self->state != MCA_STATE_DONE) self->do_one_attempt_id = g_idle_add (do_one_attempt, self); else { self->do_one_attempt_id = 0; self->running = FALSE; } } return FALSE; }