[phodav: 13/18] wip: move method lock
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [phodav: 13/18] wip: move method lock
- Date: Thu, 10 Apr 2014 17:52:10 +0000 (UTC)
commit ba7c6debcf5890c81395d47831717d397fda0126
Author: Marc-André Lureau <marcandre lureau gmail com>
Date: Thu Apr 10 19:07:48 2014 +0200
wip: move method lock
Makefile.am | 1 +
libphodav/phodav-method-lock.c | 246 ++++++++++++++++++++++++++++++++++++++++
libphodav/phodav-priv.h | 4 +
libphodav/phodav-server.c | 227 +------------------------------------
4 files changed, 254 insertions(+), 224 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index fb90999..51c61b3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,7 @@ libphodav_1_0_la_SOURCES = \
libphodav/phodav-if.c \
libphodav/phodav-method-delete.c \
libphodav/phodav-method-get.c \
+ libphodav/phodav-method-lock.c \
libphodav/phodav-method-mkcol.c \
libphodav/phodav-method-movecopy.c \
libphodav/phodav-method-propfind.c \
diff --git a/libphodav/phodav-method-lock.c b/libphodav/phodav-method-lock.c
new file mode 100644
index 0000000..e7e74c0
--- /dev/null
+++ b/libphodav/phodav-method-lock.c
@@ -0,0 +1,246 @@
+/* -*- 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-priv.h"
+
+#include "guuid.h"
+#include "phodav-multistatus.h"
+#include "phodav-path.h"
+#include "phodav-lock.h"
+#include "phodav-utils.h"
+
+static gboolean G_GNUC_PURE
+check_lock (const gchar *key, Path *path, gpointer data)
+{
+ DAVLock *lock = data;
+ DAVLock *other = NULL;
+ GList *l;
+
+ for (l = path->locks; l; l = l->next)
+ {
+ other = l->data;
+ if (other->scope == LOCK_SCOPE_EXCLUSIVE)
+ return FALSE;
+ }
+
+ if (other && lock->scope == LOCK_SCOPE_EXCLUSIVE)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+try_add_lock (PhodavServer *server, const gchar *path, DAVLock *lock)
+{
+ Path *p;
+
+ if (!server_foreach_parent_path (server, path, check_lock, lock))
+ return FALSE;
+
+ p = server_get_path (server, path);
+ path_add_lock (p, lock);
+
+ return TRUE;
+}
+
+static gboolean
+lock_ensure_file (PathHandler *handler, const char *path,
+ GCancellable *cancellable, GError **err)
+{
+ GError *e = NULL;
+ GFileOutputStream *stream = NULL;
+ GFile *file = NULL;
+ gboolean created = FALSE;
+
+ file = g_file_get_child (handler_get_file (handler), path + 1);
+ stream = g_file_create (file, G_FILE_CREATE_NONE, cancellable, &e);
+ created = !!stream;
+
+ if (e)
+ {
+ if (g_error_matches (e, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ g_clear_error (&e);
+ else
+ g_propagate_error (err, e);
+ }
+
+ g_clear_object (&stream);
+ g_clear_object (&file);
+
+ return created;
+}
+
+static LockScopeType
+parse_lockscope (xmlNodePtr rt)
+{
+ xmlNodePtr node;
+
+ for (node = rt->children; node; node = node->next)
+ if (xml_node_is_element (node))
+ break;
+
+ if (node == NULL)
+ return LOCK_SCOPE_NONE;
+
+ if (!g_strcmp0 ((char *) node->name, "exclusive"))
+ return LOCK_SCOPE_EXCLUSIVE;
+ else if (!g_strcmp0 ((char *) node->name, "shared"))
+ return LOCK_SCOPE_SHARED;
+ else
+ return LOCK_SCOPE_NONE;
+}
+
+static LockType
+parse_locktype (xmlNodePtr rt)
+{
+ xmlNodePtr node;
+
+ for (node = rt->children; node; node = node->next)
+ if (xml_node_is_element (node))
+ break;
+
+ if (node == NULL)
+ return LOCK_NONE;
+
+ if (!g_strcmp0 ((char *) node->name, "write"))
+ return LOCK_WRITE;
+ else
+ return LOCK_NONE;
+}
+
+gint
+phodav_method_lock (PathHandler *handler, SoupMessage *msg,
+ const char *path, GError **err)
+{
+ GCancellable *cancellable = handler_get_cancellable (handler);
+ Path *lpath = NULL;
+ xmlChar *mem = NULL;
+ int size = 0;
+ DavDoc doc = {0, };
+ xmlNodePtr node = NULL, owner = NULL, root = NULL;
+ xmlNsPtr ns = NULL;
+ LockScopeType scope = LOCK_SCOPE_SHARED;
+ LockType type;
+ DepthType depth;
+ guint timeout;
+ gchar *ltoken = NULL, *uuid = NULL, *token = NULL;
+ DAVLock *lock = NULL;
+ gint status = SOUP_STATUS_BAD_REQUEST;
+ gboolean created;
+
+ depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
+ timeout = timeout_from_string (soup_message_headers_get_one (msg->request_headers, "Timeout"));
+
+ if (depth != DEPTH_ZERO && depth != DEPTH_INFINITY)
+ goto end;
+
+ if (!msg->request_body->length)
+ {
+ const gchar *hif = soup_message_headers_get_one (msg->request_headers, "If");
+ gint len = strlen (hif);
+
+ if (len <= 4 || hif[0] != '(' || hif[1] != '<' || hif[len - 2] != '>' || hif[len - 1] != ')')
+ goto end;
+
+ token = g_strndup (hif + 2, len - 4);
+
+ g_debug ("refresh token %s", token);
+ lock = server_path_get_lock (handler_get_server (handler), path, token);
+
+ if (!lock)
+ goto end;
+
+ dav_lock_refresh_timeout (lock, timeout);
+ status = SOUP_STATUS_OK;
+ goto body;
+ }
+
+ if (!davdoc_parse (&doc, msg, msg->request_body, "lockinfo"))
+ goto end;
+
+ node = doc.root;
+ for (node = node->children; node; node = node->next)
+ {
+ if (!xml_node_is_element (node))
+ continue;
+
+ if (xml_node_has_name (node, "lockscope"))
+ {
+ scope = parse_lockscope (node);
+ if (scope == LOCK_SCOPE_NONE)
+ break;
+ }
+ else if (xml_node_has_name (node, "locktype"))
+ {
+ type = parse_locktype (node);
+ if (type == LOCK_NONE)
+ break;
+ }
+ else if (xml_node_has_name (node, "owner"))
+ {
+ if (owner == NULL)
+ owner = node;
+ else
+ g_warn_if_reached ();
+ }
+ }
+
+ g_debug ("lock depth:%d scope:%d type:%d owner:%p, timeout: %u",
+ depth, scope, type, owner, timeout);
+
+ uuid = g_uuid_random ();
+ token = g_strdup_printf ("urn:uuid:%s", uuid);
+ ltoken = g_strdup_printf ("<%s>", token);
+ soup_message_headers_append (msg->response_headers, "Lock-Token", ltoken);
+
+ lpath = server_get_path (handler_get_server (handler), path);
+ lock = dav_lock_new (lpath, token, scope, type, depth, owner, timeout);
+ if (!try_add_lock (handler_get_server (handler), path, lock))
+ {
+ g_warning ("lock failed");
+ dav_lock_free (lock);
+ status = SOUP_STATUS_LOCKED;
+ goto end;
+ }
+
+ created = lock_ensure_file (handler, path, cancellable, err);
+ if (*err)
+ goto end;
+
+ status = created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK;
+
+body:
+ root = xmlNewNode (NULL, BAD_CAST "prop");
+ ns = xmlNewNs (root, BAD_CAST "DAV:", BAD_CAST "D");
+ xmlSetNs (root, ns);
+
+ node = xmlNewChild (root, ns, BAD_CAST "lockdiscovery", NULL);
+ xmlAddChild (node, dav_lock_get_activelock_node (lock, ns));
+
+ xml_node_to_string (root, &mem, &size);
+ soup_message_set_response (msg, "application/xml",
+ SOUP_MEMORY_TAKE, (gchar *) mem, size);
+
+end:
+ g_free (ltoken);
+ g_free (token);
+ g_free (uuid);
+ davdoc_free (&doc);
+
+ return status;
+}
diff --git a/libphodav/phodav-priv.h b/libphodav/phodav-priv.h
index e96f0f7..c960476 100644
--- a/libphodav/phodav-priv.h
+++ b/libphodav/phodav-priv.h
@@ -95,6 +95,8 @@ DAVLock * server_path_get_lock (PhodavServer *serv
gboolean server_path_has_other_locks (PhodavServer *self,
const gchar *path,
GList *locks);
+Path * server_get_path (PhodavServer *self,
+ const gchar *_path);
gint phodav_check_if (PathHandler *handler, SoupMessage *msg,
const gchar *path, GList **locks);
@@ -115,6 +117,8 @@ gint phodav_method_delete (PathHandler *handl
const char *path, GError **err);
gint phodav_method_movecopy (PathHandler *handler, SoupMessage *msg,
const char *path, GError **err);
+gint phodav_method_lock (PathHandler *handler, SoupMessage *msg,
+ const char *path, GError **err);
G_END_DECLS
diff --git a/libphodav/phodav-server.c b/libphodav/phodav-server.c
index 9b82120..74bdab4 100644
--- a/libphodav/phodav-server.c
+++ b/libphodav/phodav-server.c
@@ -77,8 +77,8 @@ static void request_started (SoupServer *server,
SoupClientContext *client,
gpointer user_data);
-static Path *
-get_path (PhodavServer *self, const gchar *_path)
+Path *
+server_get_path (PhodavServer *self, const gchar *_path)
{
Path *p;
gchar *path = g_strdup (_path);
@@ -293,44 +293,6 @@ phodav_server_class_init (PhodavServerClass *klass)
G_PARAM_STATIC_STRINGS));
}
-static LockScopeType
-parse_lockscope (xmlNodePtr rt)
-{
- xmlNodePtr node;
-
- for (node = rt->children; node; node = node->next)
- if (xml_node_is_element (node))
- break;
-
- if (node == NULL)
- return LOCK_SCOPE_NONE;
-
- if (!g_strcmp0 ((char *) node->name, "exclusive"))
- return LOCK_SCOPE_EXCLUSIVE;
- else if (!g_strcmp0 ((char *) node->name, "shared"))
- return LOCK_SCOPE_SHARED;
- else
- return LOCK_SCOPE_NONE;
-}
-
-static LockType
-parse_locktype (xmlNodePtr rt)
-{
- xmlNodePtr node;
-
- for (node = rt->children; node; node = node->next)
- if (xml_node_is_element (node))
- break;
-
- if (node == NULL)
- return LOCK_NONE;
-
- if (!g_strcmp0 ((char *) node->name, "write"))
- return LOCK_WRITE;
- else
- return LOCK_NONE;
-}
-
gboolean
server_foreach_parent_path (PhodavServer *self, const gchar *path, PathCb cb, gpointer data)
{
@@ -461,189 +423,6 @@ server_path_has_other_locks (PhodavServer *self, const gchar *path, GList *locks
return !server_foreach_parent_path (self, path, other_lock_exists, locks);
}
-static gboolean G_GNUC_PURE
-check_lock (const gchar *key, Path *path, gpointer data)
-{
- DAVLock *lock = data;
- DAVLock *other = NULL;
- GList *l;
-
- for (l = path->locks; l; l = l->next)
- {
- other = l->data;
- if (other->scope == LOCK_SCOPE_EXCLUSIVE)
- return FALSE;
- }
-
- if (other && lock->scope == LOCK_SCOPE_EXCLUSIVE)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-try_add_lock (PhodavServer *self, const gchar *path, DAVLock *lock)
-{
- Path *p;
-
- if (!server_foreach_parent_path (self, path, check_lock, lock))
- return FALSE;
-
- p = get_path (self, path);
- path_add_lock (p, lock);
-
- return TRUE;
-}
-
-static gboolean
-lock_ensure_file (PathHandler *handler, const char *path,
- GCancellable *cancellable, GError **err)
-{
- GError *e = NULL;
- GFileOutputStream *stream = NULL;
- GFile *file = NULL;
- gboolean created = FALSE;
-
- file = g_file_get_child (handler->file, path + 1);
- stream = g_file_create (file, G_FILE_CREATE_NONE, cancellable, &e);
- created = !!stream;
-
- if (e)
- {
- if (g_error_matches (e, G_IO_ERROR, G_IO_ERROR_EXISTS))
- g_clear_error (&e);
- else
- g_propagate_error (err, e);
- }
-
- g_clear_object (&stream);
- g_clear_object (&file);
-
- return created;
-}
-
-static gint
-method_lock (PathHandler *handler, SoupMessage *msg,
- const char *path, GError **err)
-{
- PhodavServer *self = handler->self;
- Path *lpath = NULL;
- xmlChar *mem = NULL;
- int size = 0;
- DavDoc doc = {0, };
- xmlNodePtr node = NULL, owner = NULL, root = NULL;
- xmlNsPtr ns = NULL;
- LockScopeType scope = LOCK_SCOPE_SHARED;
- LockType type;
- DepthType depth;
- guint timeout;
- gchar *ltoken = NULL, *uuid = NULL, *token = NULL;
- DAVLock *lock = NULL;
- gint status = SOUP_STATUS_BAD_REQUEST;
- gboolean created;
-
- depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
- timeout = timeout_from_string (soup_message_headers_get_one (msg->request_headers, "Timeout"));
-
- if (depth != DEPTH_ZERO && depth != DEPTH_INFINITY)
- goto end;
-
- if (!msg->request_body->length)
- {
- const gchar *hif = soup_message_headers_get_one (msg->request_headers, "If");
- gint len = strlen (hif);
-
- if (len <= 4 || hif[0] != '(' || hif[1] != '<' || hif[len - 2] != '>' || hif[len - 1] != ')')
- goto end;
-
- token = g_strndup (hif + 2, len - 4);
-
- g_debug ("refresh token %s", token);
- lock = server_path_get_lock (self, path, token);
-
- if (!lock)
- goto end;
-
- dav_lock_refresh_timeout (lock, timeout);
- status = SOUP_STATUS_OK;
- goto body;
- }
-
- if (!davdoc_parse (&doc, msg, msg->request_body, "lockinfo"))
- goto end;
-
- node = doc.root;
- for (node = node->children; node; node = node->next)
- {
- if (!xml_node_is_element (node))
- continue;
-
- if (xml_node_has_name (node, "lockscope"))
- {
- scope = parse_lockscope (node);
- if (scope == LOCK_SCOPE_NONE)
- break;
- }
- else if (xml_node_has_name (node, "locktype"))
- {
- type = parse_locktype (node);
- if (type == LOCK_NONE)
- break;
- }
- else if (xml_node_has_name (node, "owner"))
- {
- if (owner == NULL)
- owner = node;
- else
- g_warn_if_reached ();
- }
- }
-
- g_debug ("lock depth:%d scope:%d type:%d owner:%p, timeout: %u",
- depth, scope, type, owner, timeout);
-
- uuid = g_uuid_random ();
- token = g_strdup_printf ("urn:uuid:%s", uuid);
- ltoken = g_strdup_printf ("<%s>", token);
- soup_message_headers_append (msg->response_headers, "Lock-Token", ltoken);
-
- lpath = get_path (self, path);
- lock = dav_lock_new (lpath, token, scope, type, depth, owner, timeout);
- if (!try_add_lock (self, path, lock))
- {
- g_warning ("lock failed");
- dav_lock_free (lock);
- status = SOUP_STATUS_LOCKED;
- goto end;
- }
-
- created = lock_ensure_file (handler, path, self->cancellable, err);
- if (*err)
- goto end;
-
- status = created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK;
-
-body:
- root = xmlNewNode (NULL, BAD_CAST "prop");
- ns = xmlNewNs (root, BAD_CAST "DAV:", BAD_CAST "D");
- xmlSetNs (root, ns);
-
- node = xmlNewChild (root, ns, BAD_CAST "lockdiscovery", NULL);
- xmlAddChild (node, dav_lock_get_activelock_node (lock, ns));
-
- xml_node_to_string (root, &mem, &size);
- soup_message_set_response (msg, "application/xml",
- SOUP_MEMORY_TAKE, (gchar *) mem, size);
-
-end:
- g_free (ltoken);
- g_free (token);
- g_free (uuid);
- davdoc_free (&doc);
-
- return status;
-}
-
static gchar *
remove_brackets (const gchar *str)
{
@@ -837,7 +616,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
msg->method == SOUP_METHOD_COPY)
status = phodav_method_movecopy (handler, msg, path, &err);
else if (msg->method == SOUP_METHOD_LOCK)
- status = method_lock (handler, msg, path, &err);
+ status = phodav_method_lock (handler, msg, path, &err);
else if (msg->method == SOUP_METHOD_UNLOCK)
status = method_unlock (handler, msg, path, &err);
else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]