[phodav: 4/18] wip: move get method



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]