📄 ne_props.c
字号:
/* WebDAV property manipulation Copyright (C) 2000-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#include "ne_alloc.h"#include "ne_xml.h"#include "ne_props.h"#include "ne_basic.h"#include "ne_locks.h"/* don't store flat props with a value > 10K */#define MAX_FLATPROP_LEN (102400)struct ne_propfind_handler_s { ne_session *sess; ne_request *request; int has_props; /* whether we've already written some * props to the body. */ ne_buffer *body; ne_207_parser *parser207; ne_xml_parser *parser; /* Callback to create the private structure. */ ne_props_create_complex private_creator; void *private_userdata; /* Current propset, or NULL if none being processed. */ ne_prop_result_set *current; ne_buffer *value; /* current flat property value */ int depth; /* nesting depth within a flat property */ ne_props_result callback; void *userdata;};#define ELM_flatprop (NE_207_STATE_TOP - 1)/* We build up the results of one 'response' element in memory. */struct prop { char *name, *nspace, *value, *lang; /* Store a ne_propname here too, for convienience. pname.name = * name, pname.nspace = nspace, but they are const'ed in pname. */ ne_propname pname;};#define NSPACE(x) ((x) ? (x) : "")struct propstat { struct prop *props; int numprops; ne_status status;};/* Results set. */struct ne_prop_result_set_s { struct propstat *pstats; int numpstats; void *private; char *href;};static int startelm(void *userdata, int state, const char *name, const char *nspace, const char **atts);static int endelm(void *userdata, int state, const char *name, const char *nspace);/* Handle character data; flat property value. */static int chardata(void *userdata, int state, const char *data, size_t len){ ne_propfind_handler *hdl = userdata; if (state == ELM_flatprop && hdl->value->length < MAX_FLATPROP_LEN) ne_buffer_append(hdl->value, data, len); return 0;}ne_xml_parser *ne_propfind_get_parser(ne_propfind_handler *handler){ return handler->parser;}ne_request *ne_propfind_get_request(ne_propfind_handler *handler){ return handler->request;}static int propfind(ne_propfind_handler *handler, ne_props_result results, void *userdata){ int ret; ne_request *req = handler->request; /* Register the flat property handler to catch any properties * which the user isn't handling as 'complex'. */ ne_xml_push_handler(handler->parser, startelm, chardata, endelm, handler); handler->callback = results; handler->userdata = userdata; ne_set_request_body_buffer(req, handler->body->data, ne_buffer_size(handler->body)); ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE); ne_add_response_body_reader(req, ne_accept_207, ne_xml_parse_v, handler->parser); ret = ne_request_dispatch(req); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } else if (!ne_xml_valid(handler->parser)) { ne_set_error(handler->sess, "%s", ne_xml_get_error(handler->parser)); ret = NE_ERROR; } return ret;}static void set_body(ne_propfind_handler *hdl, const ne_propname *names){ ne_buffer *body = hdl->body; int n; if (!hdl->has_props) { ne_buffer_zappend(body, "<prop>" EOL); hdl->has_props = 1; } for (n = 0; names[n].name != NULL; n++) { ne_buffer_concat(body, "<", names[n].name, " xmlns=\"", NSPACE(names[n].nspace), "\"/>" EOL, NULL); }}int ne_propfind_allprop(ne_propfind_handler *handler, ne_props_result results, void *userdata){ ne_buffer_zappend(handler->body, "<allprop/></propfind>" EOL); return propfind(handler, results, userdata);}int ne_propfind_named(ne_propfind_handler *handler, const ne_propname *props, ne_props_result results, void *userdata){ set_body(handler, props); ne_buffer_zappend(handler->body, "</prop></propfind>" EOL); return propfind(handler, results, userdata);}/* The easy one... PROPPATCH */int ne_proppatch(ne_session *sess, const char *uri, const ne_proppatch_operation *items){ ne_request *req = ne_request_create(sess, "PROPPATCH", uri); ne_buffer *body = ne_buffer_create(); int n, ret; /* Create the request body */ ne_buffer_zappend(body, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" EOL "<D:propertyupdate xmlns:D=\"DAV:\">"); for (n = 0; items[n].name != NULL; n++) { const char *elm = (items[n].type == ne_propset) ? "set" : "remove"; /* <set><prop><prop-name>value</prop-name></prop></set> */ ne_buffer_concat(body, "<D:", elm, "><D:prop>" "<", items[n].name->name, NULL); if (items[n].name->nspace) { ne_buffer_concat(body, " xmlns=\"", items[n].name->nspace, "\"", NULL); } if (items[n].type == ne_propset) { ne_buffer_concat(body, ">", items[n].value, NULL); } else { ne_buffer_append(body, ">", 1); } ne_buffer_concat(body, "</", items[n].name->name, "></D:prop></D:", elm, ">" EOL, NULL); } ne_buffer_zappend(body, "</D:propertyupdate>" EOL); ne_set_request_body_buffer(req, body->data, ne_buffer_size(body)); ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE); #ifdef USE_DAV_LOCKS ne_lock_using_resource(req, uri, NE_DEPTH_ZERO);#endif ret = ne_simple_request(sess, req); ne_buffer_destroy(body); return ret;}/* Compare two property names. */static int pnamecmp(const ne_propname *pn1, const ne_propname *pn2){ if (pn1->nspace == NULL && pn2->nspace != NULL) { return 1; } else if (pn1->nspace != NULL && pn2->nspace == NULL) { return -1; } else if (pn1->nspace == NULL) { return strcmp(pn1->name, pn2->name); } else { return (strcmp(pn1->nspace, pn2->nspace) || strcmp(pn1->name, pn2->name)); }}/* Find property in 'set' with name 'pname'. If found, set pstat_ret * to the containing propstat, likewise prop_ret, and returns zero. * If not found, returns non-zero. */static int findprop(const ne_prop_result_set *set, const ne_propname *pname, struct propstat **pstat_ret, struct prop **prop_ret){ int ps, p; for (ps = 0; ps < set->numpstats; ps++) { for (p = 0; p < set->pstats[ps].numprops; p++) { struct prop *prop = &set->pstats[ps].props[p]; if (pnamecmp(&prop->pname, pname) == 0) { if (pstat_ret != NULL) *pstat_ret = &set->pstats[ps]; if (prop_ret != NULL) *prop_ret = prop; return 0; } } } return -1;}const char *ne_propset_value(const ne_prop_result_set *set, const ne_propname *pname){ struct prop *prop; if (findprop(set, pname, NULL, &prop)) { return NULL; } else { return prop->value; }}const char *ne_propset_lang(const ne_prop_result_set *set, const ne_propname *pname){ struct prop *prop; if (findprop(set, pname, NULL, &prop)) { return NULL; } else { return prop->lang; }}void *ne_propfind_current_private(ne_propfind_handler *handler){ return handler->current ? handler->current->private : NULL;}void *ne_propset_private(const ne_prop_result_set *set){ return set->private;}int ne_propset_iterate(const ne_prop_result_set *set, ne_propset_iterator iterator, void *userdata){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -