WebDAV: moved common href and etag handling into common parser
The handling of href and etag data had to be done by all classes using initResponseHandler(). Now it is in the XML handler itself. In addition, users of the class process the gathered results at the end of the results XML element. At that point, all the response parts are guaranteed to be processed.
This commit is contained in:
parent
7e542c596d
commit
8d038294b8
4 changed files with 60 additions and 39 deletions
|
@ -82,15 +82,14 @@ void CalDAVSource::listAllSubItems(SubRevisionMap_t &revisions)
|
|||
getSession()->startOperation("REPORT 'meta data'", deadline);
|
||||
while (true) {
|
||||
string result;
|
||||
string href, etag, data;
|
||||
string data;
|
||||
Neon::XMLParser parser;
|
||||
parser.initReportParser(href, etag);
|
||||
parser.initReportParser(boost::bind(&CalDAVSource::appendItem, this,
|
||||
boost::ref(revisions),
|
||||
_1, _2, boost::ref(data)));
|
||||
m_cache.clear();
|
||||
parser.pushHandler(boost::bind(Neon::XMLParser::accept, "urn:ietf:params:xml:ns:caldav", "calendar-data", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(data), _2, _3),
|
||||
boost::bind(&CalDAVSource::appendItem, this,
|
||||
boost::ref(revisions),
|
||||
boost::ref(href), boost::ref(etag), boost::ref(data)));
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(data), _2, _3));
|
||||
Neon::Request report(*getSession(), "REPORT", getCalendar().m_path, query, parser);
|
||||
report.addHeader("Depth", "1");
|
||||
report.addHeader("Content-Type", "application/xml; charset=\"utf-8\"");
|
||||
|
@ -103,8 +102,8 @@ void CalDAVSource::listAllSubItems(SubRevisionMap_t &revisions)
|
|||
}
|
||||
|
||||
int CalDAVSource::appendItem(SubRevisionMap_t &revisions,
|
||||
std::string &href,
|
||||
std::string &etag,
|
||||
const std::string &href,
|
||||
const std::string &etag,
|
||||
std::string &data)
|
||||
{
|
||||
Event::unescapeRecurrenceID(data);
|
||||
|
@ -150,8 +149,6 @@ int CalDAVSource::appendItem(SubRevisionMap_t &revisions,
|
|||
|
||||
// reset data for next item
|
||||
data.clear();
|
||||
href.clear();
|
||||
etag.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -753,9 +750,8 @@ CalDAVSource::Event &CalDAVSource::loadItem(Event &event)
|
|||
getSession()->startOperation("REPORT 'single item'", deadline);
|
||||
while (true) {
|
||||
string result;
|
||||
string href, etag;
|
||||
Neon::XMLParser parser;
|
||||
parser.initReportParser(href, etag);
|
||||
parser.initReportParser();
|
||||
item = "";
|
||||
parser.pushHandler(boost::bind(Neon::XMLParser::accept, "urn:ietf:params:xml:ns:caldav", "calendar-data", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(item), _2, _3));
|
||||
|
@ -924,14 +920,13 @@ void CalDAVSource::backupData(const SyncSource::Operations::ConstBackupInfo &old
|
|||
"</C:filter>\n"
|
||||
"</C:calendar-query>\n";
|
||||
string result;
|
||||
string href, etag, data;
|
||||
string data;
|
||||
Neon::XMLParser parser;
|
||||
parser.initReportParser(href, etag);
|
||||
parser.initReportParser(boost::bind(&CalDAVSource::backupItem, this,
|
||||
boost::ref(cache),
|
||||
_1, _2, boost::ref(data)));
|
||||
parser.pushHandler(boost::bind(Neon::XMLParser::accept, "urn:ietf:params:xml:ns:caldav", "calendar-data", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(data), _2, _3),
|
||||
boost::bind(&CalDAVSource::backupItem, this,
|
||||
boost::ref(cache),
|
||||
boost::ref(href), boost::ref(etag), boost::ref(data)));
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(data), _2, _3));
|
||||
Timespec deadline = createDeadline();
|
||||
getSession()->startOperation("REPORT 'full calendar'", deadline);
|
||||
while (true) {
|
||||
|
@ -947,8 +942,8 @@ void CalDAVSource::backupData(const SyncSource::Operations::ConstBackupInfo &old
|
|||
}
|
||||
|
||||
int CalDAVSource::backupItem(ItemCache &cache,
|
||||
std::string &href,
|
||||
std::string &etag,
|
||||
const std::string &href,
|
||||
const std::string &etag,
|
||||
std::string &data)
|
||||
{
|
||||
Event::unescapeRecurrenceID(data);
|
||||
|
@ -958,8 +953,6 @@ int CalDAVSource::backupItem(ItemCache &cache,
|
|||
|
||||
// reset data for next item
|
||||
data.clear();
|
||||
href.clear();
|
||||
etag.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,14 +171,14 @@ class CalDAVSource : public WebDAVSource,
|
|||
|
||||
/** callback for listAllSubItems: parse and add new item */
|
||||
int appendItem(SubRevisionMap_t &revisions,
|
||||
std::string &href,
|
||||
std::string &etag,
|
||||
const std::string &href,
|
||||
const std::string &etag,
|
||||
std::string &data);
|
||||
|
||||
/** callback for backupData(): dump into backup */
|
||||
int backupItem(ItemCache &cache,
|
||||
std::string &href,
|
||||
std::string &etag,
|
||||
const std::string &href,
|
||||
const std::string &etag,
|
||||
std::string &data);
|
||||
};
|
||||
|
||||
|
|
|
@ -777,18 +777,20 @@ int XMLParser::reset(std::string &buffer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void XMLParser::initReportParser(std::string &href,
|
||||
std::string &etag)
|
||||
void XMLParser::initReportParser(const ResponseEndCB_t &responseEnd)
|
||||
{
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "multistatus", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "response", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "response", _2, _3),
|
||||
Neon::XMLParser::DataCB_t(),
|
||||
boost::bind(&Neon::XMLParser::doResponseEnd,
|
||||
this, responseEnd));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "href", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(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:", "prop", _2, _3));
|
||||
pushHandler(boost::bind(Neon::XMLParser::accept, "DAV:", "getetag", _2, _3),
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(etag), _2, _3));
|
||||
boost::bind(Neon::XMLParser::append, boost::ref(m_etag), _2, _3));
|
||||
}
|
||||
|
||||
Request::Request(Session &session,
|
||||
|
|
|
@ -417,15 +417,30 @@ class XMLParser
|
|||
static int reset(std::string &buffer);
|
||||
|
||||
/**
|
||||
* Setup parser for handling REPORT result.
|
||||
* Caller still needs to push a handler for
|
||||
* "urn:ietf:params:xml:ns:caldav", "calendar-data".
|
||||
*
|
||||
* @param href caller's buffer for DAV:href
|
||||
* @param etag caller's buffer for DAV:getetag
|
||||
* called once a response is completely parse
|
||||
*
|
||||
* @param href the path for which the response was sent
|
||||
* @param etag it's etag, empty if not requested or available
|
||||
*/
|
||||
void initReportParser(std::string &href,
|
||||
std::string &etag);
|
||||
typedef boost::function<void (const std::string &, const std::string &)> ResponseEndCB_t;
|
||||
|
||||
/**
|
||||
* Setup parser for handling REPORT result.
|
||||
* Already deals with href and etag, caching it
|
||||
* for each response and passing it to the "response
|
||||
* complete" callback.
|
||||
*
|
||||
* Caller still needs to push a handler for
|
||||
* "urn:ietf:params:xml:ns:caldav", "calendar-data",
|
||||
* or any other elements that it wants to know about.
|
||||
*
|
||||
* @param responseEnd called at the end of processing each response;
|
||||
* this is the only time when all relevant
|
||||
* parts of the response are guaranteed to have been seen;
|
||||
* when expecting only one response, the callback
|
||||
* is not needed
|
||||
*/
|
||||
void initReportParser(const ResponseEndCB_t &responseEnd = ResponseEndCB_t());
|
||||
|
||||
private:
|
||||
ne_xml_parser *m_parser;
|
||||
|
@ -443,6 +458,17 @@ class XMLParser
|
|||
};
|
||||
std::list<Callbacks> m_stack;
|
||||
|
||||
/** buffers for initReportParser() */
|
||||
std::string m_href, m_etag;
|
||||
|
||||
int doResponseEnd(const ResponseEndCB_t &responseEnd) {
|
||||
responseEnd(m_href, m_etag);
|
||||
// clean up for next response
|
||||
m_href.clear();
|
||||
m_etag.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int startCB(void *userdata, int parent,
|
||||
const char *nspace, const char *name,
|
||||
const char **atts);
|
||||
|
|
Loading…
Reference in a new issue