📄 props.c
字号:
/* Tests for property handling Copyright (C) 2002-2004, Joe Orton <joe@manyfish.co.uk> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "config.h"#include <sys/types.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "ne_props.h"#include "tests.h"#include "child.h"#include "utils.h"static const ne_propname p_alpha = {"DAV:", "alpha"}, p_beta = {"http://webdav.org/random/namespace", "beta"}, p_delta = {NULL, "delta"};/* Tests little except that ne_proppatch() doesn't segfault. */static int patch_simple(void){ ne_session *sess; ne_proppatch_operation ops[] = { { &p_alpha, ne_propset, "fish" }, { &p_beta, ne_propremove, NULL }, { NULL, ne_propset, NULL } }; CALL(make_session(&sess, single_serve_string, "HTTP/1.1 200 Goferit\r\n" "Connection: close\r\n\r\n")); ONREQ(ne_proppatch(sess, "/fish", ops)); ne_session_destroy(sess); return await_server();}#define RESP207 "HTTP/1.0 207 Stuff\r\n" "Server: foo\r\n\r\n"static void dummy_results(void *ud, const char *href, const ne_prop_result_set *rset){ NE_DEBUG(NE_DBG_HTTP, "dummy_results.\n");}/* Regression tests for propfind bodies which caused segfaults. */static int regress(void){ static const char *bodies[] = { RESP207 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<multistatus xmlns=\"DAV:\">" "<response><propstat><prop><href>" "</href></prop></propstat></response>" "</multistatus>", /* segfaults with neon <= 0.23.5 */ RESP207 "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\">" "<D:response><D:href>/foo/</D:href>" "<D:propstat/>" "<D:status>HTTP/1.1 404 Not Found</D:status>" "</D:multistatus>", /* format string handling with neon <= 0.24.4 */ RESP207 "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\">" "<D:response><D:href>/foo/</D:href>" "<D:propstat/>" "<D:status>%s%s%s%s</D:status>" "</D:response></D:multistatus>", NULL, }; ne_session *sess; int n; for (n = 0; bodies[n] != NULL; n++) { CALL(make_session(&sess, single_serve_string, (void *)bodies[n])); ne_simple_propfind(sess, "/", 0, NULL, dummy_results, NULL); ne_session_destroy(sess); CALL(await_server()); } return OK;}static int patch_regress(void){ static const char *bodies[] = { /* format string handling bugs with neon <= 0.24.4 */ RESP207 "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\">" "<D:response><D:href>/foo/</D:href>" "<D:status>HTTP/1.1 500 Bad Voodoo</D:status>" "<D:responsedescription>%s%s%s%s</D:responsedescription>" "</D:response></D:multistatus>", RESP207 "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\">" "<D:response><D:href>/foo/</D:href>" "<D:status>HTTP/1.1 %s%s%s%s</D:status>", NULL }; ne_session *sess; int n; static const ne_propname pn = { "DAV:", "foobar" }; ne_proppatch_operation pops[] = { { &pn, ne_propset, "fish" }, { NULL, ne_propset, NULL } }; for (n = 0; bodies[n] != NULL; n++) { CALL(make_session(&sess, single_serve_string, (void *)bodies[n])); ne_proppatch(sess, "/", pops); ne_session_destroy(sess); CALL(await_server()); } return OK;}static int pstat_count;/* tos_*: set of 207 callbacks which serialize the data back into a * text stream, which can be easily checked for correctness. */static void *tos_startresp(void *buf, const char *href){ ne_buffer_concat(buf, "start-resp[", href, "];", NULL); pstat_count = 0; return ne_strdup(href);}static void tos_status_descr(ne_buffer *buf, const ne_status *status, const char *description){ if (status) { char s[50]; ne_snprintf(s, sizeof s, "-status={%d %s}", status->code, status->reason_phrase); ne_buffer_zappend(buf, s); } if (description) ne_buffer_concat(buf, "-descr={", description, "}", NULL);}static void tos_endresp(void *buf, void *response, const ne_status *status, const char *description){ char *href = response; ne_buffer_concat(buf, "end-resp[", href, "]", NULL); ne_free(href); tos_status_descr(buf, status, description); ne_buffer_zappend(buf, ";");}static void *tos_startpstat(void *buf, void *resphref){ char num[20], *href; sprintf(num, "-%d", ++pstat_count); href = ne_concat(resphref, num, NULL); ne_buffer_concat(buf, "start-pstat[", href, "];", NULL); return href;}static void tos_endpstat(void *buf, void *href, const ne_status *status, const char *description){ ne_buffer_concat(buf, "end-pstat[", href, "]", NULL); tos_status_descr(buf, status, description); ne_buffer_zappend(buf, ";"); ne_free(href);}struct propctx { ne_207_parser *p207; ne_buffer *buf;};#define STATE_myprop (NE_PROPS_STATE_TOP)static int tos_startprop(void *userdata, int parent, const char *nspace, const char *name, const char **atts){ if (parent == NE_207_STATE_PROP && strcmp(nspace, "DAV:") == 0 && (strcmp(name, "propone") == 0 || strcmp(name, "proptwo") == 0)) { /* Handle this! */ struct propctx *ctx = userdata; char *resphref = ne_207_get_current_response(ctx->p207); char *pstathref = ne_207_get_current_propstat(ctx->p207); ne_buffer_concat(ctx->buf, "start-prop[", resphref, ",", pstathref, ",", name, "];", NULL); return STATE_myprop; } else { return NE_XML_DECLINE; }}static int tos_cdata(void *userdata, int state, const char *cdata, size_t len){ struct propctx *ctx = userdata; ne_buffer_zappend(ctx->buf, "cdata-prop["); ne_buffer_append(ctx->buf, cdata, len); ne_buffer_zappend(ctx->buf, "];"); return 0;}static int tos_endprop(void *userdata, int state, const char *nspace, const char *name){ struct propctx *ctx = userdata; ne_buffer_concat(ctx->buf, "end-prop[", name, "];", NULL); return 0;}static int run_207_response(char *resp, const char *expected){ ne_buffer *buf = ne_buffer_create(); ne_session *sess = ne_session_create("http", "localhost", 7777); ne_xml_parser *p = ne_xml_create(); ne_207_parser *p207 = ne_207_create(p, buf); ne_request *req = ne_request_create(sess, "PROPFIND", "/foo"); struct propctx ctx; ne_add_response_body_reader(req, ne_accept_207, ne_xml_parse_v, p); ne_207_set_response_handlers(p207, tos_startresp, tos_endresp); ne_207_set_propstat_handlers(p207, tos_startpstat, tos_endpstat); ctx.buf = buf; ctx.p207 = p207; ne_xml_push_handler(p, tos_startprop, tos_cdata, tos_endprop, &ctx); CALL(spawn_server(7777, single_serve_string, resp)); ONREQ(ne_request_dispatch(req)); CALL(await_server()); ONV(!ne_xml_valid(p), ("response body was invalid: %s", ne_xml_get_error(p))); ONV(strcmp(buf->data, expected), ("comparison failed.\n" "expected string: `%s'\n" "got string: `%s'", expected, buf->data)); ne_buffer_destroy(buf); ne_207_destroy(p207); ne_xml_destroy(p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -