[phodav: 4/18] wip: move get method
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [phodav: 4/18] wip: move get method
- Date: Thu, 10 Apr 2014 17:51:25 +0000 (UTC)
commit 030c02a181b61e1b5b6c43ae7c222aa220fa6a5f
Author: Marc-André Lureau <marcandre lureau gmail com>
Date: Thu Apr 10 16:54:17 2014 +0200
wip: move get method
Makefile.am | 2 +
libphodav/phodav-method-get.c | 177 +++++++++++++++++++++++++++++++++++++++++
libphodav/phodav-method-get.h | 30 +++++++
libphodav/phodav-server.c | 161 +------------------------------------
4 files changed, 211 insertions(+), 159 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0e15c78..5b083ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,8 @@ libphodav_1_0_la_SOURCES = \
libphodav/phodav-path.h \
libphodav/phodav-lock.c \
libphodav/phodav-lock.h \
+ libphodav/phodav-method-get.c \
+ libphodav/phodav-method-get.h \
libphodav/phodav-multistatus.c \
libphodav/phodav-multistatus.h \
libphodav/phodav-server.c \
diff --git a/libphodav/phodav-method-get.c b/libphodav/phodav-method-get.c
new file mode 100644
index 0000000..604b0df
--- /dev/null
+++ b/libphodav/phodav-method-get.c
@@ -0,0 +1,177 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "phodav-method-get.h"
+
+static int
+compare_strings (gconstpointer a, gconstpointer b)
+{
+ const char **sa = (const char * *) a;
+ const char **sb = (const char * *) b;
+
+ return g_strcmp0 (*sa, *sb);
+}
+
+static GString *
+get_directory_listing (GFile *file, GCancellable *cancellable, GError **err)
+{
+ GString *listing;
+ GPtrArray *entries;
+ GFileEnumerator *e;
+ gchar *escaped;
+ gchar *name;
+ gint i;
+
+ e = g_file_enumerate_children (file, "standard::*", G_FILE_QUERY_INFO_NONE,
+ cancellable, err);
+ g_return_val_if_fail (e != NULL, NULL);
+
+ entries = g_ptr_array_new ();
+ while (1)
+ {
+ GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
+ gboolean dir;
+
+ if (!info)
+ break;
+
+ dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+
+ escaped = g_markup_printf_escaped ("%s%s",
+ g_file_info_get_name (info), dir ? "/" : "");
+ g_ptr_array_add (entries, escaped);
+ g_object_unref (info);
+ }
+ g_file_enumerator_close (e, cancellable, NULL);
+ g_clear_object (&e);
+
+ g_ptr_array_sort (entries, compare_strings);
+
+ listing = g_string_new ("<html>\r\n");
+ name = g_file_get_basename (file);
+ escaped = g_markup_escape_text (name, -1);
+ g_free (name);
+ g_string_append_printf (listing, "<head><title>Index of %s</title></head>\r\n", escaped);
+ g_string_append_printf (listing, "<body><h1>Index of %s</h1>\r\n<p>\r\n", escaped);
+ g_free (escaped);
+ for (i = 0; i < entries->len; i++)
+ {
+ g_string_append_printf (listing, "<a href=\"%s\">%s</a><br/>\r\n",
+ (gchar *) entries->pdata[i],
+ (gchar *) entries->pdata[i]);
+ g_free (entries->pdata[i]);
+ }
+ g_string_append (listing, "</p></body>\r\n</html>\r\n");
+
+ g_ptr_array_free (entries, TRUE);
+ return listing;
+}
+
+gint
+phodav_method_get (SoupMessage *msg, GFile *file,
+ GCancellable *cancellable, GError **err)
+{
+ GError *error = NULL;
+ gint status = SOUP_STATUS_NOT_FOUND;
+ GFileInfo *info;
+ const gchar *etag;
+
+ info = g_file_query_info (file, "standard::*,etag::*",
+ G_FILE_QUERY_INFO_NONE, cancellable, &error);
+ if (!info)
+ goto end;
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ {
+ GString *listing;
+
+ listing = get_directory_listing (file, cancellable, err);
+ soup_message_set_response (msg, "text/html; charset=utf-8",
+ SOUP_MEMORY_TAKE,
+ listing->str, listing->len);
+ g_string_free (listing, FALSE);
+ status = SOUP_STATUS_OK;
+ goto end;
+ }
+
+ etag = g_file_info_get_etag (info);
+ g_warn_if_fail (etag != NULL);
+
+ if (etag)
+ {
+ gchar *tmp = g_strdup_printf ("\"%s\"", etag);
+ soup_message_headers_append (msg->response_headers, "ETag", tmp);
+ g_free (tmp);
+ }
+
+ soup_message_headers_set_content_type (msg->response_headers,
+ g_file_info_get_content_type (info), NULL);
+
+ if (msg->method == SOUP_METHOD_GET)
+ {
+ GMappedFile *mapping;
+ SoupBuffer *buffer;
+ gchar *path = g_file_get_path (file);
+
+ mapping = g_mapped_file_new (path, FALSE, NULL);
+ g_free (path);
+ if (!mapping)
+ {
+ status = SOUP_STATUS_INTERNAL_SERVER_ERROR;
+ goto end;
+ }
+
+ buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping),
+ g_mapped_file_get_length (mapping),
+ mapping, (GDestroyNotify) g_mapped_file_unref);
+ soup_message_body_append_buffer (msg->response_body, buffer);
+ soup_buffer_free (buffer);
+ status = SOUP_STATUS_OK;
+ }
+ else if (msg->method == SOUP_METHOD_HEAD)
+ {
+ gchar *length;
+
+ /* We could just use the same code for both GET and
+ * HEAD (soup-message-server-io.c will fix things up).
+ * But we'll optimize and avoid the extra I/O.
+ */
+ length = g_strdup_printf ("%" G_GUINT64_FORMAT, g_file_info_get_size (info));
+ soup_message_headers_append (msg->response_headers, "Content-Length", length);
+
+ g_free (length);
+ status = SOUP_STATUS_OK;
+ }
+ else
+ g_warn_if_reached ();
+
+end:
+ if (error)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_debug ("getfile: %s", error->message);
+ g_clear_error (&error);
+ }
+ else
+ g_propagate_error (err, error);
+ }
+
+ g_clear_object (&info);
+ return status;
+}
diff --git a/libphodav/phodav-method-get.h b/libphodav/phodav-method-get.h
new file mode 100644
index 0000000..95f59fb
--- /dev/null
+++ b/libphodav/phodav-method-get.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __PHODAV_METHOD_GET_H__
+#define __PHODAV_METHOD_GET_H__
+
+#include <libsoup/soup.h>
+#include "phodav-priv.h"
+
+G_BEGIN_DECLS
+
+gint phodav_method_get (SoupMessage *msg, GFile *file,
+ GCancellable *cancellable, GError **err);
+G_END_DECLS
+
+#endif /* __PHODAV_METHOD_GET_H__ */
diff --git a/libphodav/phodav-server.c b/libphodav/phodav-server.c
index 0185f88..dfb7147 100644
--- a/libphodav/phodav-server.c
+++ b/libphodav/phodav-server.c
@@ -29,6 +29,7 @@
#include "phodav-path.h"
#include "phodav-lock.h"
#include "phodav-utils.h"
+#include "phodav-method-get.h"
/**
* SECTION:phodav-server
@@ -398,164 +399,6 @@ locktype_to_string (LockType type)
g_return_val_if_reached (NULL);
}
-static int
-compare_strings (gconstpointer a, gconstpointer b)
-{
- const char **sa = (const char * *) a;
- const char **sb = (const char * *) b;
-
- return g_strcmp0 (*sa, *sb);
-}
-
-static GString *
-get_directory_listing (GFile *file, GCancellable *cancellable, GError **err)
-{
- GString *listing;
- GPtrArray *entries;
- GFileEnumerator *e;
- gchar *escaped;
- gchar *name;
- gint i;
-
- e = g_file_enumerate_children (file, "standard::*", G_FILE_QUERY_INFO_NONE,
- cancellable, err);
- g_return_val_if_fail (e != NULL, NULL);
-
- entries = g_ptr_array_new ();
- while (1)
- {
- GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
- gboolean dir;
-
- if (!info)
- break;
-
- dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
-
- escaped = g_markup_printf_escaped ("%s%s",
- g_file_info_get_name (info), dir ? "/" : "");
- g_ptr_array_add (entries, escaped);
- g_object_unref (info);
- }
- g_file_enumerator_close (e, cancellable, NULL);
- g_clear_object (&e);
-
- g_ptr_array_sort (entries, compare_strings);
-
- listing = g_string_new ("<html>\r\n");
- name = g_file_get_basename (file);
- escaped = g_markup_escape_text (name, -1);
- g_free (name);
- g_string_append_printf (listing, "<head><title>Index of %s</title></head>\r\n", escaped);
- g_string_append_printf (listing, "<body><h1>Index of %s</h1>\r\n<p>\r\n", escaped);
- g_free (escaped);
- for (i = 0; i < entries->len; i++)
- {
- g_string_append_printf (listing, "<a href=\"%s\">%s</a><br/>\r\n",
- (gchar *) entries->pdata[i],
- (gchar *) entries->pdata[i]);
- g_free (entries->pdata[i]);
- }
- g_string_append (listing, "</p></body>\r\n</html>\r\n");
-
- g_ptr_array_free (entries, TRUE);
- return listing;
-}
-
-static gint
-do_get_file (SoupMessage *msg, GFile *file,
- GCancellable *cancellable, GError **err)
-{
- GError *error = NULL;
- gint status = SOUP_STATUS_NOT_FOUND;
- GFileInfo *info;
- const gchar *etag;
-
- info = g_file_query_info (file, "standard::*,etag::*",
- G_FILE_QUERY_INFO_NONE, cancellable, &error);
- if (!info)
- goto end;
-
- if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
- {
- GString *listing;
-
- listing = get_directory_listing (file, cancellable, err);
- soup_message_set_response (msg, "text/html; charset=utf-8",
- SOUP_MEMORY_TAKE,
- listing->str, listing->len);
- g_string_free (listing, FALSE);
- status = SOUP_STATUS_OK;
- goto end;
- }
-
- etag = g_file_info_get_etag (info);
- g_warn_if_fail (etag != NULL);
-
- if (etag)
- {
- gchar *tmp = g_strdup_printf ("\"%s\"", etag);
- soup_message_headers_append (msg->response_headers, "ETag", tmp);
- g_free (tmp);
- }
-
- soup_message_headers_set_content_type (msg->response_headers,
- g_file_info_get_content_type (info), NULL);
-
- if (msg->method == SOUP_METHOD_GET)
- {
- GMappedFile *mapping;
- SoupBuffer *buffer;
- gchar *path = g_file_get_path (file);
-
- mapping = g_mapped_file_new (path, FALSE, NULL);
- g_free (path);
- if (!mapping)
- {
- status = SOUP_STATUS_INTERNAL_SERVER_ERROR;
- goto end;
- }
-
- buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping),
- g_mapped_file_get_length (mapping),
- mapping, (GDestroyNotify) g_mapped_file_unref);
- soup_message_body_append_buffer (msg->response_body, buffer);
- soup_buffer_free (buffer);
- status = SOUP_STATUS_OK;
- }
- else if (msg->method == SOUP_METHOD_HEAD)
- {
- gchar *length;
-
- /* We could just use the same code for both GET and
- * HEAD (soup-message-server-io.c will fix things up).
- * But we'll optimize and avoid the extra I/O.
- */
- length = g_strdup_printf ("%" G_GUINT64_FORMAT, g_file_info_get_size (info));
- soup_message_headers_append (msg->response_headers, "Content-Length", length);
-
- g_free (length);
- status = SOUP_STATUS_OK;
- }
- else
- g_warn_if_reached ();
-
-end:
- if (error)
- {
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_debug ("getfile: %s", error->message);
- g_clear_error (&error);
- }
- else
- g_propagate_error (err, error);
- }
-
- g_clear_object (&info);
- return status;
-}
-
typedef enum _PropFindType {
PROPFIND_ALLPROP,
PROPFIND_PROPNAME,
@@ -1564,7 +1407,7 @@ method_get (PathHandler *handler, SoupMessage *msg, const char *path, GError **e
gint status;
file = g_file_get_child (handler->file, path + 1);
- status = do_get_file (msg, file, self->cancellable, err);
+ status = phodav_method_get (msg, file, self->cancellable, err);
g_object_unref (file);
return status;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]