From ab8dfc598a2a4a532f54fe3bd296cfadc38c006a Mon Sep 17 00:00:00 2001 From: Mihai Patrascoiu Date: Thu, 21 Mar 2024 16:50:00 +0100 Subject: [PATCH] DMC-1401: Handle subtle length/size differences when calling the XML parser By using the "std::vector::size()" call, the null terminator character also became part of the parsable content. To avoid subtle length/size differences, the content is transformed into a string first, which is then passed to the XMl parser function --- src/fileops/davmeta.cpp | 90 +++++++++++++++++++++++------------------ src/fileops/davmeta.hpp | 11 ----- src/tools/davix_op.cpp | 38 +++++++++-------- 3 files changed, 72 insertions(+), 67 deletions(-) diff --git a/src/fileops/davmeta.cpp b/src/fileops/davmeta.cpp index 69140de2..61acf914 100644 --- a/src/fileops/davmeta.cpp +++ b/src/fileops/davmeta.cpp @@ -71,51 +71,55 @@ struct DirHandle{ }; /** - execute a propfind/stat request on a given HTTP request handle - return a vector with the content of the request if success -*/ -std::vector req_webdav_propfind(HttpRequest* req, DavixError** err){ - int ret =-1; - std::vector res; - - req->addHeaderField("Depth","0"); + * Helper function to execute a PROPFIND/stat request on a given HTTP request handle. + * Returns a string with the HTTP response. + */ +std::string req_webdav_propfind(HttpRequest* req, DavixError** err) { + req->addHeaderField("Depth", "0"); req->setRequestMethod("PROPFIND"); - if( (ret = req->executeRequest(err)) ==0){ - res.swap(req->getAnswerContentVec()); + if (req->executeRequest(err) == 0) { + auto content = req->getAnswerContent(); + + if (content != NULL) { + return {content}; + } } - return res; + return {}; } int dav_stat_mapper_webdav(Context &context, const RequestParams* params, const Uri & url, struct StatInfo& st_info){ - int ret =-1; - DavPropXMLParser parser; - DavixError * tmp_err=NULL; + DavixError* tmp_err = NULL; HttpRequest req(context, url, &tmp_err); + int ret = -1; if( tmp_err == NULL){ req.setParameters(params); - TRY_DAVIX{ - std::vector body = req_webdav_propfind(&req, &tmp_err); - if(!tmp_err){ - parser.parseChunk(&(body[0]), body.size()); + TRY_DAVIX { + std::string response = req_webdav_propfind(&req, &tmp_err); - std::deque & props = parser.getProperties(); - if( props.size() < 1){ - throw DavixException(davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error : properties number < 1"); - }else{ + if (!tmp_err) { + parser.parseChunk(response); + std::deque& props = parser.getProperties(); + + if (props.size() < 1) { + throw DavixException(davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error: properties number < 1"); + } else { st_info = props.front().info; - ret =0; + ret = 0; } } - }CATCH_DAVIX(&tmp_err) - if(tmp_err != NULL) + } CATCH_DAVIX(&tmp_err) + + if (tmp_err != NULL) { ret = -1; + } } + checkDavixError(&tmp_err); return ret; } @@ -254,13 +258,16 @@ void getQuotaInfo(Context & c, const Uri & url, const RequestParams *p, QuotaInf req.setRequestMethod("PROPFIND"); req.setRequestBody(quota_stat); - if(req.executeRequest(&tmp_err) == 0 && !tmp_err) { + if (req.executeRequest(&tmp_err) == 0 && !tmp_err) { DavPropXMLParser parser; - parser.parseChunk(&(req.getAnswerContentVec()[0]), req.getAnswerContentVec().size()); + auto content = req.getAnswerContent(); + std::string response = (content != NULL) ? content : ""; + parser.parseChunk(response); std::deque & props = parser.getProperties(); - if( props.size() < 1){ - throw DavixException(davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error : properties number < 1"); - }else{ + + if (props.size() < 1) { + throw DavixException(davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error: properties number < 1"); + } else { QuotaInfoHandler::setdptr(info, props.front().quota); } } @@ -269,36 +276,39 @@ void getQuotaInfo(Context & c, const Uri & url, const RequestParams *p, QuotaInf } void parse_creation_deletion_result(int code, const Uri & u, const std::string & scope, const std::vector & body){ - switch(code){ + switch(code) { case 200: case 201: case 202: - case 204:{ - return; + case 204: { + return; } - case 207:{ - // parse webdav + case 207: { + // Parse WebDAV DavDeleteXMLParser parser; - parser.parseChunk(&(body[0]), body.size()); - if( parser.getProperties().size() > 0){ - for(unsigned int i=0; i < parser.getProperties().size(); ++i){ + std::string response = (!body.empty()) ? body.data() : ""; + parser.parseChunk(response); + + if (parser.getProperties().size() > 0) { + for (unsigned int i = 0; i < parser.getProperties().size(); ++i) { const int sub_code = parser.getProperties().at(i).req_status; std::ostringstream ss; - ss << "occurred during deletion request for " << parser.getProperties().at(i).filename; - if(httpcodeIsValid(sub_code) == false){ + if (httpcodeIsValid(sub_code) == false) { httpcodeToDavixException(sub_code, scope, ss.str()); } } return; } + // if no properties, properties were filtered because invalid httpcodeToDavixException(404, scope); break; } } + std::ostringstream ss; ss << " with url " << u.getString(); httpcodeToDavixException(code, scope, ss.str()); diff --git a/src/fileops/davmeta.hpp b/src/fileops/davmeta.hpp index 03e20e42..2959e320 100644 --- a/src/fileops/davmeta.hpp +++ b/src/fileops/davmeta.hpp @@ -136,18 +136,7 @@ class SwiftMetaOps : public HttpIOChain{ }; -/* - retrieve a webdav propfind stat request to the given url - @param req : http request where to executethe query - @return vector of characters of the query content - */ -std::vector req_webdav_propfind(HttpRequest* req, DavixError** err); - - - } // Davix - - #endif // DAVMETA_HPP diff --git a/src/tools/davix_op.cpp b/src/tools/davix_op.cpp index 9ce5a9af..9c94e8f9 100644 --- a/src/tools/davix_op.cpp +++ b/src/tools/davix_op.cpp @@ -246,7 +246,7 @@ int DeleteOp::executeOp(){ } } else{ - // cases other than s3, not implenmented for now. WebDAV delete collection already works without the -r switch + // Cases other than S3 not implemented for now. WebDAV delete collection already works without the -r switch return -1; } @@ -254,26 +254,29 @@ int DeleteOp::executeOp(){ } void DeleteOp::parse_deletion_result(int code, const Uri & u, const std::string & scope, const std::vector & body){ - switch(code){ - case 200:{ + switch(code) { + case 200: { // if s3 && scope was davix_scope_rm_str() && batch delete, parse body S3DeleteParser parser; - parser.parseChunk(&(body[0]), body.size()); + std::string response = (!body.empty()) ? body.data() : ""; + parser.parseChunk(response); // check if any of the delete request entry is flagged as error, if so, just print them for now - if( parser.getDeleteStatus().size() > 0){ - for(unsigned int i=0; i < parser.getDeleteStatus().size(); ++i){ - if(parser.getDeleteStatus().at(i).error){ + if (parser.getDeleteStatus().size() > 0) { + for (unsigned int i = 0; i < parser.getDeleteStatus().size(); ++i) { + if (parser.getDeleteStatus().at(i).error) { std::ostringstream ss; ss << "Error: " << parser.getDeleteStatus().at(i).error_code << " -> " << parser.getDeleteStatus().at(i).message << - " encountered while atempting to delete " << + " encountered while attempting to delete " << parser.getDeleteStatus().at(i).filename; std::cerr << std::endl << ss.str() << std::endl; } + return; } + // if no properties, status were filtered because invalid httpcodeToDavixException(404, scope); return; @@ -281,32 +284,35 @@ void DeleteOp::parse_deletion_result(int code, const Uri & u, const std::string } case 201: case 202: - case 204:{ + case 204: { return; } - case 207:{ - // parse webdav + case 207: { + // Parse WebDAV DavDeleteXMLParser parser; - parser.parseChunk(&(body[0]), body.size()); - if( parser.getProperties().size() > 0){ - for(unsigned int i=0; i < parser.getProperties().size(); ++i){ + std::string response = (!body.empty()) ? body.data() : ""; + parser.parseChunk(response); + + if (parser.getProperties().size() > 0) { + for (unsigned int i = 0; i < parser.getProperties().size(); ++i) { const int sub_code = parser.getProperties().at(i).req_status; std::ostringstream ss; - ss << "occurred during deletion request for " << parser.getProperties().at(i).filename; - if(httpcodeIsValid(sub_code) == false){ + if (httpcodeIsValid(sub_code) == false) { httpcodeToDavixException(sub_code, scope, ss.str()); } } return; } + // if no properties, properties were filtered because invalid httpcodeToDavixException(404, scope); break; } } + std::ostringstream ss; ss << " with url " << u.getString(); httpcodeToDavixException(code, scope, ss.str());