summaryrefslogtreecommitdiff
path: root/daemon/gvfsbackendhttp.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/gvfsbackendhttp.c')
-rw-r--r--daemon/gvfsbackendhttp.c250
1 files changed, 132 insertions, 118 deletions
diff --git a/daemon/gvfsbackendhttp.c b/daemon/gvfsbackendhttp.c
index 1120d2f0..0f01d213 100644
--- a/daemon/gvfsbackendhttp.c
+++ b/daemon/gvfsbackendhttp.c
@@ -1,6 +1,7 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2021 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -51,7 +52,7 @@
#include "gvfsdaemonprotocol.h"
#include "gvfsdaemonutils.h"
-static SoupSession *the_session;
+static SoupSession *the_session = NULL;
G_DEFINE_TYPE (GVfsBackendHttp, g_vfs_backend_http, G_VFS_TYPE_BACKEND)
@@ -63,7 +64,7 @@ g_vfs_backend_http_finalize (GObject *object)
backend = G_VFS_BACKEND_HTTP (object);
if (backend->mount_base)
- soup_uri_free (backend->mount_base);
+ g_uri_unref (backend->mount_base);
g_object_unref (backend->session);
@@ -77,18 +78,89 @@ g_vfs_backend_http_init (GVfsBackendHttp *backend)
{
g_vfs_backend_set_user_visible (G_VFS_BACKEND (backend), FALSE);
- backend->session = g_object_ref (the_session);
+ /* attempt to use libsoup's default values */
+ backend->session = g_object_ref (http_try_init_session (-1, -1));
}
/* ************************************************************************* */
/* public utility functions */
-SoupURI *
+GUri *
http_backend_get_mount_base (GVfsBackend *backend)
{
return G_VFS_BACKEND_HTTP (backend)->mount_base;
}
+#define DEBUG_MAX_BODY_SIZE (100 * 1024 * 1024)
+
+/* initializes the session singleton; if max_conns is lower than 0, the
+ * libsoup defaults are used for max-conns and max-conns-per-host, this
+ * is called in the instance constructor, so if they are to be overridden,
+ * all one has to do is make sure to call it with the desired values before
+ * any instance is created (most likely in the class constructor of the
+ * derived class, see dav backend)
+ */
+SoupSession *
+http_try_init_session (gint max_conns, gint max_conns_per_host)
+{
+ const char *debug;
+ SoupSessionFeature *cookie_jar;
+
+ if (the_session)
+ return the_session;
+
+ /* Initialize the SoupSession, common to all backend instances */
+ if (max_conns < 0)
+ the_session = soup_session_new_with_options ("user-agent",
+ "gvfs/" VERSION, NULL);
+ else
+ the_session = soup_session_new_with_options ("user-agent",
+ "gvfs/" VERSION,
+ "max-conns",
+ max_conns,
+ "max-conns-per-host",
+ max_conns_per_host,
+ NULL);
+
+ /* Cookie handling - stored temporarlly in memory, mostly useful for
+ * authentication in WebDAV. */
+ cookie_jar = g_object_new (SOUP_TYPE_COOKIE_JAR, NULL);
+ soup_session_add_feature (the_session, cookie_jar);
+ g_object_unref (cookie_jar);
+
+ /* Send Accept-Language header (see bug 166795) */
+ soup_session_set_accept_language_auto (the_session, TRUE);
+
+ /* Prevent connection timeouts during long operations like COPY. */
+ soup_session_set_timeout (the_session, 0);
+
+ /* Logging */
+ debug = g_getenv ("GVFS_HTTP_DEBUG");
+ if (debug)
+ {
+ SoupLogger *logger;
+ SoupLoggerLogLevel level;
+
+ if (g_ascii_strcasecmp (debug, "all") == 0 ||
+ g_ascii_strcasecmp (debug, "body") == 0)
+ level = SOUP_LOGGER_LOG_BODY;
+ else if (g_ascii_strcasecmp (debug, "header") == 0)
+ level = SOUP_LOGGER_LOG_HEADERS;
+ else
+ level = SOUP_LOGGER_LOG_MINIMAL;
+
+ logger = soup_logger_new (level);
+ g_object_set (G_OBJECT (logger),
+ "max-body-size",
+ DEBUG_MAX_BODY_SIZE,
+ NULL);
+ soup_session_add_feature (the_session, SOUP_SESSION_FEATURE (logger));
+ g_object_unref (logger);
+ }
+
+ return the_session;
+}
+
char *
http_path_get_basename (const char *path)
{
@@ -138,7 +210,7 @@ http_uri_get_basename (const char *uri_str)
basename = http_path_get_basename (uri_str);
- decoded = soup_uri_decode (basename);
+ decoded = g_uri_unescape_string (basename, NULL);
g_free (basename);
return decoded;
@@ -149,13 +221,6 @@ http_error_code_from_status (guint status)
{
switch (status) {
- case SOUP_STATUS_CANT_RESOLVE:
- case SOUP_STATUS_CANT_RESOLVE_PROXY:
- return G_IO_ERROR_HOST_NOT_FOUND;
-
- case SOUP_STATUS_CANCELLED:
- return G_IO_ERROR_CANCELLED;
-
case SOUP_STATUS_UNAUTHORIZED:
case SOUP_STATUS_PAYMENT_REQUIRED:
case SOUP_STATUS_FORBIDDEN:
@@ -184,45 +249,27 @@ http_error_code_from_status (guint status)
void
http_job_failed (GVfsJob *job, SoupMessage *msg)
{
- switch (msg->status_code) {
+ switch (soup_message_get_status(msg)) {
case SOUP_STATUS_NOT_FOUND:
g_vfs_job_failed_literal (job, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- msg->reason_phrase);
+ soup_message_get_reason_phrase(msg));
break;
case SOUP_STATUS_UNAUTHORIZED:
case SOUP_STATUS_PAYMENT_REQUIRED:
case SOUP_STATUS_FORBIDDEN:
g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("HTTP Client Error: %s"), msg->reason_phrase);
+ _("HTTP Client Error: %s"),
+ soup_message_get_reason_phrase(msg));
break;
default:
g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("HTTP Error: %s"), msg->reason_phrase);
+ _("HTTP Error: %s"),
+ soup_message_get_reason_phrase(msg));
}
}
-guint
-http_backend_send_message (GVfsBackend *backend,
- SoupMessage *msg)
-{
- GVfsBackendHttp *op_backend = G_VFS_BACKEND_HTTP (backend);
-
- return soup_session_send_message (op_backend->session, msg);
-}
-
-void
-http_backend_queue_message (GVfsBackend *backend,
- SoupMessage *msg,
- SoupSessionCallback callback,
- gpointer user_data)
-{
- GVfsBackendHttp *op_backend = G_VFS_BACKEND_HTTP (backend);
-
- soup_session_queue_message (op_backend->session, msg,
- callback, user_data);
-}
/* ************************************************************************* */
/* virtual functions overrides */
@@ -235,8 +282,8 @@ try_mount (GVfsBackend *backend,
{
GVfsBackendHttp *op_backend;
const char *uri_str;
- char *path;
- SoupURI *uri;
+ const char *path;
+ GUri *uri;
GMountSpec *real_mount_spec;
op_backend = G_VFS_BACKEND_HTTP (backend);
@@ -245,7 +292,7 @@ try_mount (GVfsBackend *backend,
uri_str = g_mount_spec_get (mount_spec, "uri");
if (uri_str)
- uri = soup_uri_new (uri_str);
+ uri = g_uri_parse (uri_str, SOUP_HTTP_URI_FLAGS, NULL);
g_debug ("+ try_mount: %s\n", uri_str ? uri_str : "(null)");
@@ -260,12 +307,11 @@ try_mount (GVfsBackend *backend,
real_mount_spec = g_mount_spec_new ("http");
g_mount_spec_set (real_mount_spec, "uri", uri_str);
- if (uri->path != NULL)
+ path = g_uri_get_path (uri);
+ if (path[0])
{
- path = g_uri_unescape_string (uri->path, "/");
g_free (real_mount_spec->mount_prefix);
real_mount_spec->mount_prefix = g_mount_spec_canonicalize_path (path);
- g_free (path);
}
g_vfs_backend_set_mount_spec (backend, real_mount_spec);
@@ -309,7 +355,7 @@ open_for_read_ready (GObject *source_object,
}
msg = g_vfs_http_input_stream_get_message (stream);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg)))
{
http_job_failed (G_VFS_JOB (job), msg);
g_object_unref (msg);
@@ -330,7 +376,7 @@ try_open_for_read (GVfsBackend *backend,
GVfsJobOpenForRead *job,
const char *filename)
{
- SoupURI *uri;
+ GUri *uri;
uri = http_backend_get_mount_base (backend);
http_backend_open_for_read (backend, G_VFS_JOB (job), uri);
@@ -341,7 +387,7 @@ try_open_for_read (GVfsBackend *backend,
void
http_backend_open_for_read (GVfsBackend *backend,
GVfsJob *job,
- SoupURI *uri)
+ GUri *uri)
{
GVfsBackendHttp *op_backend;
GInputStream *stream;
@@ -507,7 +553,7 @@ file_info_from_message (SoupMessage *msg,
/* prefer the filename from the Content-Disposition (rfc2183) header
if one if present. See bug 551298. */
- if (soup_message_headers_get_content_disposition (msg->response_headers,
+ if (soup_message_headers_get_content_disposition (soup_message_get_response_headers (msg),
NULL, &params))
{
const char *name = g_hash_table_lookup (params, "filename");
@@ -520,10 +566,10 @@ file_info_from_message (SoupMessage *msg,
if (basename == NULL)
{
- const SoupURI *uri;
+ GUri *uri;
uri = soup_message_get_uri (msg);
- basename = http_uri_get_basename (uri->path);
+ basename = http_uri_get_basename (g_uri_get_path (uri));
}
g_debug ("basename:%s\n", basename);
@@ -540,12 +586,12 @@ file_info_from_message (SoupMessage *msg,
g_free (basename);
g_free (ed_name);
- if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_CONTENT_LENGTH)
+ if (soup_message_headers_get_encoding (soup_message_get_response_headers (msg)) == SOUP_ENCODING_CONTENT_LENGTH)
{
goffset start, end, length;
gboolean ret;
- ret = soup_message_headers_get_content_range (msg->response_headers,
+ ret = soup_message_headers_get_content_range (soup_message_get_response_headers (msg),
&start, &end, &length);
if (ret && length != -1)
{
@@ -553,14 +599,14 @@ file_info_from_message (SoupMessage *msg,
}
else if (!ret)
{
- length = soup_message_headers_get_content_length (msg->response_headers);
+ length = soup_message_headers_get_content_length (soup_message_get_response_headers (msg));
g_file_info_set_size (info, length);
}
}
g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
- text = soup_message_headers_get_content_type (msg->response_headers, NULL);
+ text = soup_message_headers_get_content_type (soup_message_get_response_headers (msg), NULL);
if (text)
{
GIcon *icon;
@@ -578,23 +624,25 @@ file_info_from_message (SoupMessage *msg,
}
- text = soup_message_headers_get_one (msg->response_headers,
+ text = soup_message_headers_get_one (soup_message_get_response_headers (msg),
"Last-Modified");
if (text)
{
- SoupDate *sd;
+ GDateTime *gd;
- sd = soup_date_new_from_string(text);
- if (sd)
+ gd = soup_date_time_new_from_http_string (text);
+ if (gd)
{
- g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, soup_date_to_time_t (sd));
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ g_date_time_to_unix (gd));
g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
- soup_date_free (sd);
+ g_date_time_unref (gd);
}
}
- text = soup_message_headers_get_one (msg->response_headers,
+ text = soup_message_headers_get_one (soup_message_get_response_headers (msg),
"ETag");
if (text)
{
@@ -605,19 +653,25 @@ file_info_from_message (SoupMessage *msg,
}
static void
-query_info_ready (SoupSession *session,
- SoupMessage *msg,
- gpointer user_data)
+query_info_ready (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GFileAttributeMatcher *matcher;
- GVfsJobQueryInfo *job;
- GFileInfo *info;
-
- job = G_VFS_JOB_QUERY_INFO (user_data);
- info = job->file_info;
- matcher = job->attribute_matcher;
+ GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data);
+ GFileAttributeMatcher *matcher = job->attribute_matcher;
+ GFileInfo *info = job->file_info;
+ GInputStream *res;
+ GError *error = NULL;
+ SoupMessage *msg = G_VFS_JOB (job)->backend_data;
+
+ res = soup_session_send_finish (SOUP_SESSION (object), result, &error);
+ if (!res)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
- if (! SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg)))
{
http_job_failed (G_VFS_JOB (job), msg);
return;
@@ -625,10 +679,11 @@ query_info_ready (SoupSession *session,
file_info_from_message (msg, info, matcher);
+ g_object_unref (res);
+
g_vfs_job_succeeded (G_VFS_JOB (job));
}
-
static gboolean
try_query_info (GVfsBackend *backend,
GVfsJobQueryInfo *job,
@@ -637,8 +692,9 @@ try_query_info (GVfsBackend *backend,
GFileInfo *info,
GFileAttributeMatcher *attribute_matcher)
{
+ GVfsBackendHttp *op_backend = G_VFS_BACKEND_HTTP (backend);
SoupMessage *msg;
- SoupURI *uri;
+ GUri *uri;
if (g_file_attribute_matcher_matches_only (attribute_matcher,
G_FILE_ATTRIBUTE_THUMBNAIL_PATH))
@@ -650,7 +706,10 @@ try_query_info (GVfsBackend *backend,
uri = http_backend_get_mount_base (backend);
msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri);
- http_backend_queue_message (backend, msg, query_info_ready, job);
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), msg, NULL);
+
+ soup_session_send_async (op_backend->session, msg, G_PRIORITY_DEFAULT,
+ NULL, query_info_ready, job);
return TRUE;
}
@@ -687,15 +746,9 @@ try_query_fs_info (GVfsBackend *backend,
return TRUE;
}
-
-#define DEBUG_MAX_BODY_SIZE (100 * 1024 * 1024)
-
static void
g_vfs_backend_http_class_init (GVfsBackendHttpClass *klass)
{
- const char *debug;
- SoupSessionFeature *cookie_jar;
-
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GVfsBackendClass *backend_class;
@@ -711,43 +764,4 @@ g_vfs_backend_http_class_init (GVfsBackendHttpClass *klass)
backend_class->try_query_info = try_query_info;
backend_class->try_query_info_on_read = try_query_info_on_read;
backend_class->try_query_fs_info = try_query_fs_info;
-
- /* Initialize the SoupSession, common to all backend instances */
- the_session = soup_session_new_with_options ("user-agent",
- "gvfs/" VERSION,
- NULL);
-
- g_object_set (the_session, "ssl-strict", FALSE, NULL);
-
- /* Cookie handling - stored temporarlly in memory, mostly useful for
- * authentication in WebDAV. */
- cookie_jar = g_object_new (SOUP_TYPE_COOKIE_JAR, NULL);
- soup_session_add_feature (the_session, cookie_jar);
- g_object_unref (cookie_jar);
-
- /* Send Accept-Language header (see bug 166795) */
- g_object_set (the_session, "accept-language-auto", TRUE, NULL);
-
- /* Prevent connection timeouts during long operations like COPY. */
- g_object_set (the_session, "timeout", 0, NULL);
-
- /* Logging */
- debug = g_getenv ("GVFS_HTTP_DEBUG");
- if (debug)
- {
- SoupLogger *logger;
- SoupLoggerLogLevel level;
-
- if (g_ascii_strcasecmp (debug, "all") == 0 ||
- g_ascii_strcasecmp (debug, "body") == 0)
- level = SOUP_LOGGER_LOG_BODY;
- else if (g_ascii_strcasecmp (debug, "header") == 0)
- level = SOUP_LOGGER_LOG_HEADERS;
- else
- level = SOUP_LOGGER_LOG_MINIMAL;
-
- logger = soup_logger_new (level, DEBUG_MAX_BODY_SIZE);
- soup_session_add_feature (the_session, SOUP_SESSION_FEATURE (logger));
- g_object_unref (logger);
- }
}