⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_locks.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    WebDAV Class 2 locking operations   Copyright (C) 1999-2004, Joe Orton <joe@manyfish.co.uk>   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 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   Library General Public License for more details.   You should have received a copy of the GNU Library General Public   License along with this library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   MA 02111-1307, USA*/#include "config.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_LIMITS_H#include <limits.h>#endif#include <ctype.h> /* for isdigit() */#include "ne_alloc.h"#include "ne_request.h"#include "ne_xml.h"#include "ne_locks.h"#include "ne_uri.h"#include "ne_basic.h"#include "ne_props.h"#include "ne_207.h"#include "ne_i18n.h"#define HOOK_ID "http://webdav.org/neon/hooks/webdav-locking"/* A list of lock objects. */struct lock_list {    struct ne_lock *lock;    struct lock_list *next, *prev;};struct ne_lock_store_s {    struct lock_list *locks;    struct lock_list *cursor; /* current position in 'locks' */};struct lh_req_cookie {    const ne_lock_store *store;    struct lock_list *submit;};/* Context for PROPFIND/lockdiscovery callbacks */struct discover_ctx {    ne_session *session;    ne_lock_result results;    void *userdata;    ne_buffer *cdata;};/* Context for handling LOCK response */struct lock_ctx {    struct ne_lock active; /* activelock */    char *token; /* the token we're after. */    int found;    ne_buffer *cdata;};/* use the "application" state space. */#define ELM_LOCK_FIRST (NE_PROPS_STATE_TOP + 66)#define ELM_lockdiscovery (ELM_LOCK_FIRST)#define ELM_activelock (ELM_LOCK_FIRST + 1)#define ELM_lockscope (ELM_LOCK_FIRST + 2)#define ELM_locktype (ELM_LOCK_FIRST + 3)#define ELM_depth (ELM_LOCK_FIRST + 4)#define ELM_owner (ELM_LOCK_FIRST + 5)#define ELM_timeout (ELM_LOCK_FIRST + 6)#define ELM_locktoken (ELM_LOCK_FIRST + 7)#define ELM_lockinfo (ELM_LOCK_FIRST + 8)#define ELM_write (ELM_LOCK_FIRST + 9)#define ELM_exclusive (ELM_LOCK_FIRST + 10)#define ELM_shared (ELM_LOCK_FIRST + 11)#define ELM_href (ELM_LOCK_FIRST + 12)#define ELM_prop (NE_207_STATE_PROP)static const struct ne_xml_idmap element_map[] = {#define ELM(x) { "DAV:", #x, ELM_ ## x }    ELM(lockdiscovery), ELM(activelock), ELM(prop), ELM(lockscope),    ELM(locktype), ELM(depth), ELM(owner), ELM(timeout), ELM(locktoken),    ELM(lockinfo), ELM(lockscope), ELM(locktype), ELM(write), ELM(exclusive),    ELM(shared), ELM(href)    /* no "lockentry" */#undef ELM};static const ne_propname lock_props[] = {    { "DAV:", "lockdiscovery" },    { NULL }};/* this simply registers the accessor for the function. */static void lk_create(ne_request *req, void *session, 		       const char *method, const char *uri){    struct lh_req_cookie *lrc = ne_malloc(sizeof *lrc);    lrc->store = session;    lrc->submit = NULL;    ne_set_request_private(req, HOOK_ID, lrc);}static void lk_pre_send(ne_request *r, void *userdata, ne_buffer *req){    struct lh_req_cookie *lrc = ne_get_request_private(r, HOOK_ID);    if (lrc->submit != NULL) {	struct lock_list *item;	/* Add in the If header */	ne_buffer_zappend(req, "If:");	for (item = lrc->submit; item != NULL; item = item->next) {	    char *uri = ne_uri_unparse(&item->lock->uri);	    ne_buffer_concat(req, " <", uri, "> (<",			     item->lock->token, ">)", NULL);	    ne_free(uri);	}	ne_buffer_zappend(req, EOL);    }}/* Insert 'lock' into lock list *list. */static void insert_lock(struct lock_list **list, struct ne_lock *lock){    struct lock_list *item = ne_malloc(sizeof *item);    if (*list != NULL) {	(*list)->prev = item;    }    item->prev = NULL;    item->next = *list;    item->lock = lock;    *list = item;}static void free_list(struct lock_list *list, int destroy){    struct lock_list *next;    while (list != NULL) {	next = list->next;	if (destroy)	    ne_lock_destroy(list->lock);	ne_free(list);	list = next;    }}static void lk_destroy(ne_request *req, void *userdata){    struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID);    free_list(lrc->submit, 0);    ne_free(lrc);}void ne_lockstore_destroy(ne_lock_store *store){    free_list(store->locks, 1);    ne_free(store);}ne_lock_store *ne_lockstore_create(void){    return ne_calloc(sizeof(ne_lock_store));}#define CURSOR_RET(s) ((s)->cursor?(s)->cursor->lock:NULL)struct ne_lock *ne_lockstore_first(ne_lock_store *store){    store->cursor = store->locks;    return CURSOR_RET(store);}struct ne_lock *ne_lockstore_next(ne_lock_store *store){    store->cursor = store->cursor->next;    return CURSOR_RET(store);}void ne_lockstore_register(ne_lock_store *store, ne_session *sess){    /* Register the hooks */    ne_hook_create_request(sess, lk_create, store);    ne_hook_pre_send(sess, lk_pre_send, store);    ne_hook_destroy_request(sess, lk_destroy, store);}/* Submit the given lock for the given URI */static void submit_lock(struct lh_req_cookie *lrc, struct ne_lock *lock){    struct lock_list *item;    /* Check for dups */    for (item = lrc->submit; item != NULL; item = item->next) {	if (strcasecmp(item->lock->token, lock->token) == 0)	    return;    }    insert_lock(&lrc->submit, lock);}struct ne_lock *ne_lockstore_findbyuri(ne_lock_store *store,				       const ne_uri *uri){    struct lock_list *cur;    for (cur = store->locks; cur != NULL; cur = cur->next) {	if (ne_uri_cmp(&cur->lock->uri, uri) == 0) {	    return cur->lock;	}    }    return NULL;}void ne_lock_using_parent(ne_request *req, const char *path){    struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID);    ne_uri u;    struct lock_list *item;    char *parent;    if (lrc == NULL)	return;        parent = ne_path_parent(path);    if (parent == NULL)	return;        u.authinfo = NULL;    ne_fill_server_uri(ne_get_session(req), &u);    for (item = lrc->store->locks; item != NULL; item = item->next) {	/* Only care about locks which are on this server. */	u.path = item->lock->uri.path;	if (ne_uri_cmp(&u, &item->lock->uri))	    continue;		/* This lock is needed if it is an infinite depth lock which	 * covers the parent, or a lock on the parent itself. */	if ((item->lock->depth == NE_DEPTH_INFINITE && 	     ne_path_childof(item->lock->uri.path, parent)) ||	    ne_path_compare(item->lock->uri.path, parent) == 0) {	    NE_DEBUG(NE_DBG_LOCKS, "Locked parent, %s on %s\n",		     item->lock->token, item->lock->uri.path);	    submit_lock(lrc, item->lock);	}    }    u.path = parent; /* handy: makes u.path valid and ne_free(parent). */    ne_uri_free(&u);}void ne_lock_using_resource(ne_request *req, const char *uri, int depth){    struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID);    struct lock_list *item;    int match;    if (lrc == NULL)	return;	    /* Iterate over the list of stored locks to see if any of them     * apply to this resource */    for (item = lrc->store->locks; item != NULL; item = item->next) {		match = 0;		if (depth == NE_DEPTH_INFINITE &&	    ne_path_childof(uri, item->lock->uri.path)) {	    /* Case 1: this is a depth-infinity request which will 	     * modify a lock somewhere inside the collection. */	    NE_DEBUG(NE_DBG_LOCKS, "Has child: %s\n", item->lock->token);	    match = 1;	} 	else if (ne_path_compare(uri, item->lock->uri.path) == 0) {	    /* Case 2: this request is directly on a locked resource */	    NE_DEBUG(NE_DBG_LOCKS, "Has direct lock: %s\n", item->lock->token);	    match = 1;	}	else if (item->lock->depth == NE_DEPTH_INFINITE && 		 ne_path_childof(item->lock->uri.path, uri)) {	    /* Case 3: there is a higher-up infinite-depth lock which	     * covers the resource that this request will modify. */	    NE_DEBUG(NE_DBG_LOCKS, "Is child of: %s\n", item->lock->token);	    match = 1;	}		if (match) {	    submit_lock(lrc, item->lock);	}    }}void ne_lockstore_add(ne_lock_store *store, struct ne_lock *lock){    insert_lock(&store->locks, lock);}void ne_lockstore_remove(ne_lock_store *store, struct ne_lock *lock){    struct lock_list *item;    /* Find the lock */    for (item = store->locks; item != NULL; item = item->next)	if (item->lock == lock)	    break;        if (item->prev != NULL) {	item->prev->next = item->next;    } else {	store->locks = item->next;    }    if (item->next != NULL) {	item->next->prev = item->prev;    }    ne_free(item);}struct ne_lock *ne_lock_copy(const struct ne_lock *lock){    struct ne_lock *ret = ne_calloc(sizeof *ret);    ret->uri.path = ne_strdup(lock->uri.path);    ret->uri.host = ne_strdup(lock->uri.host);    ret->uri.scheme = ne_strdup(lock->uri.scheme);    ret->uri.port = lock->uri.port;    ret->token = ne_strdup(lock->token);    ret->depth = lock->depth;    ret->type = lock->type;    ret->scope = lock->scope;    if (lock->owner) ret->owner = ne_strdup(lock->owner);    ret->timeout = lock->timeout;    return ret;}struct ne_lock *ne_lock_create(void){    struct ne_lock *lock = ne_calloc(sizeof *lock);    lock->depth = NE_DEPTH_ZERO;    lock->type = ne_locktype_write;    lock->scope = ne_lockscope_exclusive;    lock->timeout = NE_TIMEOUT_INVALID;    return lock;}void ne_lock_free(struct ne_lock *lock){    ne_uri_free(&lock->uri);    NE_FREE(lock->owner);    NE_FREE(lock->token);}void ne_lock_destroy(struct ne_lock *lock){    ne_lock_free(lock);    ne_free(lock);}int ne_unlock(ne_session *sess, const struct ne_lock *lock){    ne_request *req = ne_request_create(sess, "UNLOCK", lock->uri.path);    int ret;        ne_print_request_header(req, "Lock-Token", "<%s>", lock->token);        /* UNLOCK of a lock-null resource removes the resource from the     * parent collection; so an UNLOCK may modify the parent     * collection. (somewhat counter-intuitive, and not easily derived     * from 2518.) */    ne_lock_using_parent(req, lock->uri.path);    ret = ne_request_dispatch(req);        if (ret == NE_OK && ne_get_status(req)->klass == 2) {	ret = NE_OK;        } else {	ret = NE_ERROR;    }    ne_request_destroy(req);        return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -