mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-24 01:35:26 +00:00
Add simple XML parsing wrapper
Also simplify check_region_error.
This commit is contained in:
parent
21321a9d96
commit
b8ff6a647e
81
src/curl.cpp
81
src/curl.cpp
@ -31,9 +31,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <libxml/xpath.h>
|
|
||||||
#include <libxml/xpathInternals.h>
|
|
||||||
#include <libxml/tree.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -2531,50 +2528,6 @@ string S3fsCurl::CalcSignature(const string& method, const string& canonical_uri
|
|||||||
return Signature;
|
return Signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XML in BodyData has UploadId, Parse XML body for UploadId
|
|
||||||
bool S3fsCurl::GetUploadId(string& upload_id)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if(!bodydata){
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
upload_id.clear();
|
|
||||||
|
|
||||||
xmlDocPtr doc;
|
|
||||||
if(NULL == (doc = xmlReadMemory(bodydata->str(), bodydata->size(), "", NULL, 0))){
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if(NULL == doc->children){
|
|
||||||
S3FS_XMLFREEDOC(doc);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for(xmlNodePtr cur_node = doc->children->children; NULL != cur_node; cur_node = cur_node->next){
|
|
||||||
// For DEBUG
|
|
||||||
// string cur_node_name(reinterpret_cast<const char *>(cur_node->name));
|
|
||||||
// printf("cur_node_name: %s\n", cur_node_name.c_str());
|
|
||||||
|
|
||||||
if(XML_ELEMENT_NODE == cur_node->type){
|
|
||||||
string elementName = reinterpret_cast<const char*>(cur_node->name);
|
|
||||||
// For DEBUG
|
|
||||||
// printf("elementName: %s\n", elementName.c_str());
|
|
||||||
|
|
||||||
if(cur_node->children){
|
|
||||||
if(XML_TEXT_NODE == cur_node->children->type){
|
|
||||||
if(elementName == "UploadId") {
|
|
||||||
upload_id = reinterpret_cast<const char *>(cur_node->children->content);
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
S3FS_XMLFREEDOC(doc);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void S3fsCurl::insertV4Headers()
|
void S3fsCurl::insertV4Headers()
|
||||||
{
|
{
|
||||||
string server_path = type == REQTYPE_LISTBUCKET ? "/" : path;
|
string server_path = type == REQTYPE_LISTBUCKET ? "/" : path;
|
||||||
@ -3449,8 +3402,7 @@ int S3fsCurl::PreMultipartPostRequest(const char* tpath, headers_t& meta, string
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse XML body for UploadId
|
if(!simple_parse_xml(bodydata->str(), bodydata->size(), "UploadId", upload_id)){
|
||||||
if(!S3fsCurl::GetUploadId(upload_id)){
|
|
||||||
delete bodydata;
|
delete bodydata;
|
||||||
bodydata = NULL;
|
bodydata = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
@ -3793,33 +3745,12 @@ bool S3fsCurl::CopyMultipartPostCallback(S3fsCurl* s3fscurl)
|
|||||||
|
|
||||||
bool S3fsCurl::CopyMultipartPostComplete()
|
bool S3fsCurl::CopyMultipartPostComplete()
|
||||||
{
|
{
|
||||||
// parse ETag from response
|
std::string etag;
|
||||||
xmlDocPtr doc;
|
partdata.uploaded = simple_parse_xml(bodydata->str(), bodydata->size(), "ETag", etag);
|
||||||
if(NULL == (doc = xmlReadMemory(bodydata->str(), bodydata->size(), "", NULL, 0))){
|
if(etag.size() >= 2 && *etag.begin() == '"' && *etag.rbegin() == '"'){
|
||||||
return false;
|
etag.assign(etag.substr(1, etag.size() - 2));
|
||||||
}
|
}
|
||||||
if(NULL == doc->children){
|
partdata.etaglist->at(partdata.etagpos).assign(etag);
|
||||||
S3FS_XMLFREEDOC(doc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for(xmlNodePtr cur_node = doc->children->children; NULL != cur_node; cur_node = cur_node->next){
|
|
||||||
if(XML_ELEMENT_NODE == cur_node->type){
|
|
||||||
string elementName = reinterpret_cast<const char*>(cur_node->name);
|
|
||||||
if(cur_node->children){
|
|
||||||
if(XML_TEXT_NODE == cur_node->children->type){
|
|
||||||
if(elementName == "ETag") {
|
|
||||||
string etag = reinterpret_cast<const char *>(cur_node->children->content);
|
|
||||||
if(etag.size() >= 2 && *etag.begin() == '"' && *etag.rbegin() == '"'){
|
|
||||||
etag.assign(etag.substr(1, etag.size() - 2));
|
|
||||||
}
|
|
||||||
partdata.etaglist->at(partdata.etagpos).assign(etag);
|
|
||||||
partdata.uploaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
S3FS_XMLFREEDOC(doc);
|
|
||||||
|
|
||||||
delete bodydata;
|
delete bodydata;
|
||||||
bodydata = NULL;
|
bodydata = NULL;
|
||||||
|
@ -379,7 +379,6 @@ class S3fsCurl
|
|||||||
void insertAuthHeaders();
|
void insertAuthHeaders();
|
||||||
std::string CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource);
|
std::string CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource);
|
||||||
std::string CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601);
|
std::string CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601);
|
||||||
bool GetUploadId(std::string& upload_id);
|
|
||||||
int GetIAMCredentials(void);
|
int GetIAMCredentials(void);
|
||||||
|
|
||||||
int UploadMultipartPostSetup(const char* tpath, int part_num, const std::string& upload_id);
|
int UploadMultipartPostSetup(const char* tpath, int part_num, const std::string& upload_id);
|
||||||
|
37
src/s3fs.cpp
37
src/s3fs.cpp
@ -3766,39 +3766,30 @@ static int s3fs_utility_processing(time_t abort_time)
|
|||||||
|
|
||||||
//
|
//
|
||||||
// If calling with wrong region, s3fs gets following error body as 400 error code.
|
// If calling with wrong region, s3fs gets following error body as 400 error code.
|
||||||
// "<Error><Code>AuthorizationHeaderMalformed</Code><Message>The authorization header is
|
// "<Error>
|
||||||
// malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1'</Message>
|
// <Code>AuthorizationHeaderMalformed</Code>
|
||||||
// <Region>ap-northeast-1</Region><RequestId>...</RequestId><HostId>...</HostId>
|
// <Message>The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1'</Message>
|
||||||
|
// <Region>ap-northeast-1</Region>
|
||||||
|
// <RequestId>...</RequestId>
|
||||||
|
// <HostId>...</HostId>
|
||||||
// </Error>"
|
// </Error>"
|
||||||
//
|
//
|
||||||
// So this is cheep codes but s3fs should get correct region automatically.
|
// So this is cheap code but s3fs should get correct region automatically.
|
||||||
//
|
//
|
||||||
static bool check_region_error(const char* pbody, const string& currentep, string& expectregion)
|
static bool check_region_error(const char* pbody, size_t len, string& expectregion)
|
||||||
{
|
{
|
||||||
if(!pbody){
|
if(!pbody){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const char* region;
|
|
||||||
const char* regionend;
|
std::string code;
|
||||||
if(NULL == (region = strcasestr(pbody, "<Message>The authorization header is malformed; the region "))){
|
if(!simple_parse_xml(pbody, len, "Code", code) || code != "AuthorizationHeaderMalformed"){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check current endpoint region in body.
|
|
||||||
if(NULL == (region = strcasestr(region, currentep.c_str()))){
|
if(!simple_parse_xml(pbody, len, "Region", expectregion)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(NULL == (region = strcasestr(region, "expecting \'"))){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
region += strlen("expecting \'");
|
|
||||||
if(NULL == (regionend = strchr(region, '\''))){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
string strtmp(region, (regionend - region));
|
|
||||||
if(0 == strtmp.length()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
expectregion = strtmp;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3825,7 +3816,7 @@ static int s3fs_check_service()
|
|||||||
// check region error(for putting message or retrying)
|
// check region error(for putting message or retrying)
|
||||||
BodyData* body = s3fscurl.GetBodyData();
|
BodyData* body = s3fscurl.GetBodyData();
|
||||||
string expectregion;
|
string expectregion;
|
||||||
if(check_region_error(body->str(), endpoint, expectregion)){
|
if(check_region_error(body->str(), body->size(), expectregion)){
|
||||||
// [NOTE]
|
// [NOTE]
|
||||||
// If endpoint is not specified(using us-east-1 region) and
|
// If endpoint is not specified(using us-east-1 region) and
|
||||||
// an error is encountered accessing a different region, we
|
// an error is encountered accessing a different region, we
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -972,6 +975,50 @@ bool is_need_check_obj_detail(headers_t& meta)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool simple_parse_xml(const char* data, size_t len, const char* key, std::string& value)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if(!data || !key){
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
value.clear();
|
||||||
|
|
||||||
|
xmlDocPtr doc;
|
||||||
|
if(NULL == (doc = xmlReadMemory(data, len, "", NULL, 0))){
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NULL == doc->children){
|
||||||
|
S3FS_XMLFREEDOC(doc);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for(xmlNodePtr cur_node = doc->children->children; NULL != cur_node; cur_node = cur_node->next){
|
||||||
|
// For DEBUG
|
||||||
|
// string cur_node_name(reinterpret_cast<const char *>(cur_node->name));
|
||||||
|
// printf("cur_node_name: %s\n", cur_node_name.c_str());
|
||||||
|
|
||||||
|
if(XML_ELEMENT_NODE == cur_node->type){
|
||||||
|
string elementName = reinterpret_cast<const char*>(cur_node->name);
|
||||||
|
// For DEBUG
|
||||||
|
// printf("elementName: %s\n", elementName.c_str());
|
||||||
|
|
||||||
|
if(cur_node->children){
|
||||||
|
if(XML_TEXT_NODE == cur_node->children->type){
|
||||||
|
if(elementName == key) {
|
||||||
|
value = reinterpret_cast<const char *>(cur_node->children->content);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
S3FS_XMLFREEDOC(doc);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Help
|
// Help
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
@ -133,6 +133,7 @@ time_t cvtIAMExpireStringToTime(const char* s);
|
|||||||
time_t get_lastmodified(const char* s);
|
time_t get_lastmodified(const char* s);
|
||||||
time_t get_lastmodified(headers_t& meta);
|
time_t get_lastmodified(headers_t& meta);
|
||||||
bool is_need_check_obj_detail(headers_t& meta);
|
bool is_need_check_obj_detail(headers_t& meta);
|
||||||
|
bool simple_parse_xml(const char* data, size_t len, const char* key, std::string& value);
|
||||||
|
|
||||||
void show_usage(void);
|
void show_usage(void);
|
||||||
void show_help(void);
|
void show_help(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user