WebDAV: enhance report handling (status, aborting)
Capture the item status and pass it to the response handler. Response handlers are allowed to return a non-zero integer when using the initAbortingReportParser(), which then aborts processing of the response. This leads to errors being returned by ne_xml_dispatch_request(). Session::run() needs to be told if the request was aborted, in which case all errors are ignored.
This commit is contained in:
parent
905ca53824
commit
85df49a68b
|
@ -16,6 +16,7 @@
|
|||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
|
||||
#include <syncevo/util.h>
|
||||
#include <syncevo/Logging.h>
|
||||
|
@ -889,7 +890,7 @@ int XMLParser::reset(std::string &buffer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void XMLParser::initReportParser(const ResponseEndCB_t &responseEnd)
|
||||
void XMLParser::initAbortingReportParser(const ResponseEndCB_t &responseEnd)
|
||||
{
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "multistatus", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "response", _2, _3),
|
||||
|
@ -899,12 +900,32 @@ void XMLParser::initReportParser(const ResponseEndCB_t &responseEnd)
|
|||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "href", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(m_href), _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "propstat", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "status", _2, _3) /* check status? */);
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "status", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(m_status), _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "prop", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "getetag", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(m_etag), _2, _3));
|
||||
}
|
||||
|
||||
static int VoidResponseEndCBWrapper(const XMLParser::VoidResponseEndCB_t &responseEnd,
|
||||
const std::string &href,
|
||||
const std::string &etag,
|
||||
const std::string &status)
|
||||
{
|
||||
responseEnd(href, etag, status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XMLParser::initReportParser(const VoidResponseEndCB_t &responseEnd)
|
||||
{
|
||||
if (responseEnd) {
|
||||
initAbortingReportParser(boost::bind(VoidResponseEndCBWrapper, responseEnd, _1, _2, _3));
|
||||
} else {
|
||||
initAbortingReportParser(ResponseEndCB_t());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Request::Request(Session &session,
|
||||
const std::string &method,
|
||||
const std::string &path,
|
||||
|
@ -974,7 +995,7 @@ void Session::checkAuthorization()
|
|||
}
|
||||
}
|
||||
|
||||
bool Session::run(Request &request, const std::set<int> *expectedCodes)
|
||||
bool Session::run(Request &request, const std::set<int> *expectedCodes, const boost::function<bool ()> &aborted)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -992,6 +1013,11 @@ bool Session::run(Request &request, const std::set<int> *expectedCodes)
|
|||
error = ne_xml_dispatch_request(req, request.getParser()->get());
|
||||
}
|
||||
|
||||
// Was request intentionally aborted?
|
||||
if (error && aborted && aborted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkError(error, request.getStatus()->code, request.getStatus(),
|
||||
request.getResponseHeader("Location"),
|
||||
request.getPath(),
|
||||
|
|
|
@ -375,7 +375,8 @@ class Session {
|
|||
*
|
||||
* @return result of Session::checkError()
|
||||
*/
|
||||
bool run(Request &request, const std::set<int> *expectedCodes);
|
||||
bool run(Request &request, const std::set<int> *expectedCodes,
|
||||
const boost::function<bool ()> &aborted = boost::function<bool ()>());
|
||||
|
||||
/**
|
||||
* to be called after each operation which might have produced debugging output by neon;
|
||||
|
@ -516,12 +517,15 @@ class XMLParser
|
|||
static int reset(std::string &buffer);
|
||||
|
||||
/**
|
||||
* called once a response is completely parse
|
||||
* Called each time a response is completely parsed.
|
||||
*
|
||||
* @param href the path for which the response was sent
|
||||
* @param etag it's etag, empty if not requested or available
|
||||
* @param status it's status line, empty if not requested or unavailable
|
||||
* @return non-zero for aborting the parsing
|
||||
*/
|
||||
typedef boost::function<void (const std::string &, const std::string &)> ResponseEndCB_t;
|
||||
typedef boost::function<int (const std::string &, const std::string &, const std::string &)> ResponseEndCB_t;
|
||||
typedef boost::function<void (const std::string &, const std::string &, const std::string &)> VoidResponseEndCB_t;
|
||||
|
||||
/**
|
||||
* Setup parser for handling REPORT result.
|
||||
|
@ -539,7 +543,8 @@ class XMLParser
|
|||
* when expecting only one response, the callback
|
||||
* is not needed
|
||||
*/
|
||||
void initReportParser(const ResponseEndCB_t &responseEnd = ResponseEndCB_t());
|
||||
void initReportParser(const VoidResponseEndCB_t &responseEnd = VoidResponseEndCB_t());
|
||||
void initAbortingReportParser(const ResponseEndCB_t &responseEnd);
|
||||
|
||||
private:
|
||||
ne_xml_parser *m_parser;
|
||||
|
@ -558,16 +563,18 @@ class XMLParser
|
|||
std::list<Callbacks> m_stack;
|
||||
|
||||
/** buffers for initReportParser() */
|
||||
std::string m_href, m_etag;
|
||||
std::string m_href, m_etag, m_status;
|
||||
|
||||
int doResponseEnd(const ResponseEndCB_t &responseEnd) {
|
||||
int abort = 0;
|
||||
if (responseEnd) {
|
||||
responseEnd(m_href, m_etag);
|
||||
abort = responseEnd(m_href, m_etag, m_status);
|
||||
}
|
||||
// clean up for next response
|
||||
m_href.clear();
|
||||
m_etag.clear();
|
||||
return 0;
|
||||
m_status.clear();
|
||||
return abort;
|
||||
}
|
||||
|
||||
static int startCB(void *userdata, int parent,
|
||||
|
|
Loading…
Reference in New Issue