From 6472eedddcd56ee26db580eb83c24200be6a9b25 Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Sun, 7 Feb 2016 05:08:52 +0000 Subject: [PATCH 1/3] Supported regex type for additional header format. --- doc/man/s3fs.1 | 11 +-- src/curl.cpp | 152 ++++++++++++++++++++++++++++-------------- src/curl.h | 23 ++++--- src/s3fs_util.cpp | 12 ++-- test/sample_ahbe.conf | 45 ++++++++----- 5 files changed, 158 insertions(+), 85 deletions(-) diff --git a/doc/man/s3fs.1 b/doc/man/s3fs.1 index 2bb06d9..e0c9a6c 100644 --- a/doc/man/s3fs.1 +++ b/doc/man/s3fs.1 @@ -105,16 +105,17 @@ specify the path to the password file, which which takes precedence over the pas This option specifies the configuration file path which file is the additional HTTP header by file(object) extension. The configuration file format is below: ----------- - line = [file suffix] HTTP-header [HTTP-values] - file suffix = file(object) suffix, if this field is empty, it means "*"(all object). + line = [file suffix or regex] HTTP-header [HTTP-values] + file suffix = file(object) suffix, if this field is empty, it means "reg:(.*)".(=all object). + regex = regular expression to match the file(object) path. this type starts with "reg:" prefix. HTTP-header = additional HTTP header name HTTP-values = additional HTTP header value ----------- Sample: ----------- - .gz Content-Encoding gzip - .Z Content-Encoding compress - X-S3FS-MYHTTPHEAD myvalue + .gz Content-Encoding gzip + .Z Content-Encoding compress + reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2 ----------- A sample configuration file is uploaded in "test" directory. If you specify this option for set "Content-Encoding" HTTP header, please take care for RFC 2616. diff --git a/src/curl.cpp b/src/curl.cpp index 55d752c..91902af 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -3780,6 +3780,11 @@ int S3fsMultiCurl::Request(void) return 0; } +//------------------------------------------------------------------- +// Symbols +//------------------------------------------------------------------- +#define ADD_HEAD_REGEX "reg:" + //------------------------------------------------------------------- // Class AdditionalHeader //------------------------------------------------------------------- @@ -3821,7 +3826,8 @@ bool AdditionalHeader::Load(const char* file) } // read file - string line; + string line; + PADDHEAD paddhead; while(getline(AH, line)){ if('#' == line[0]){ continue; @@ -3854,26 +3860,44 @@ bool AdditionalHeader::Load(const char* file) return false; } - // set charcntlist - int keylen = key.size(); - charcnt_list_t::iterator iter; - for(iter = charcntlist.begin(); iter != charcntlist.end(); ++iter){ - if(keylen == (*iter)){ - break; + paddhead = new ADDHEAD; + if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){ + // regex + if(key.size() <= strlen(ADD_HEAD_REGEX)){ + S3FS_PRN_ERR("file format error: %s key(suffix) does not have key string.", key.c_str()); + continue; } - } - if(iter == charcntlist.end()){ - charcntlist.push_back(keylen); - } - // set addheader - addheader_t::iterator aiter; - if(addheader.end() == (aiter = addheader.find(key))){ - headerpair_t hpair; - hpair[head] = value; - addheader[key] = hpair; + key = key.substr(strlen(ADD_HEAD_REGEX)); + + // compile + regex_t* preg = new regex_t; + int result; + char errbuf[256]; + if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info + regerror(result, preg, errbuf, sizeof(errbuf)); + S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf); + delete preg; + delete paddhead; + continue; + } + + // set + paddhead->pregex = preg; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; + }else{ - aiter->second[head] = value; + // not regex, directly comparing + paddhead->pregex = NULL; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; } + + // add list + addheadlist.push_back(paddhead); + // set flag if(!is_enable){ is_enable = true; @@ -3885,8 +3909,17 @@ bool AdditionalHeader::Load(const char* file) void AdditionalHeader::Unload(void) { is_enable = false; - charcntlist.clear(); - addheader.clear(); + + for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); iter = addheadlist.erase(iter)){ + PADDHEAD paddhead = *iter; + if(paddhead){ + if(paddhead->pregex){ + regfree(paddhead->pregex); + delete paddhead->pregex; + } + delete paddhead; + } + } } bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const @@ -3898,21 +3931,35 @@ bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const S3FS_PRN_WARN("path is NULL."); return false; } - int nPathLen = strlen(path); - for(charcnt_list_t::const_iterator iter = charcntlist.begin(); iter != charcntlist.end(); ++iter){ - // get target character count - if(nPathLen < (*iter)){ + + size_t pathlength = strlen(path); + + // loop + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){ + const PADDHEAD paddhead = *iter; + if(!paddhead){ continue; } - // make target suffix(same character count) & find - string suffix(&path[nPathLen - (*iter)]); - addheader_t::const_iterator aiter; - if(addheader.end() == (aiter = addheader.find(suffix))){ - continue; - } - for(headerpair_t::const_iterator piter = aiter->second.begin(); piter != aiter->second.end(); ++piter){ - // Adding header - meta[(*piter).first] = (*piter).second; + + if(paddhead->pregex){ + // regex + int result; + regmatch_t match; // not use + + if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + }else{ + // directly comparing + if(paddhead->basestring.length() < pathlength){ + if(0 == paddhead->basestring.length() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + } } } return true; @@ -3939,26 +3986,31 @@ bool AdditionalHeader::Dump(void) const if(!IS_S3FS_LOG_DBG()){ return true; } - // character count list - stringstream ssdbg; - ssdbg << "Character count list[" << charcntlist.size() << "] = {"; - for(charcnt_list_t::const_iterator citer = charcntlist.begin(); citer != charcntlist.end(); ++citer){ - ssdbg << " " << (*citer); - } - ssdbg << " }\n"; - // additional header - ssdbg << "Additional Header list[" << addheader.size() << "] = {\n"; - for(addheader_t::const_iterator aiter = addheader.begin(); aiter != addheader.end(); ++aiter){ - string key = (*aiter).first; - if(0 == key.size()){ - key = "*"; - } - for(headerpair_t::const_iterator piter = (*aiter).second.begin(); piter != (*aiter).second.end(); ++piter){ - ssdbg << " " << key << "\t--->\t" << (*piter).first << ": " << (*piter).second << "\n"; + stringstream ssdbg; + int cnt = 1; + + ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << endl; + + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){ + const PADDHEAD paddhead = *iter; + + ssdbg << " [" << cnt << "] = {" << endl; + + if(paddhead){ + if(paddhead->pregex){ + ssdbg << " type\t\t--->\tregex" << endl; + }else{ + ssdbg << " type\t\t--->\tsuffix matching" << endl; + } + ssdbg << " base string\t--->\t" << paddhead->basestring << endl; + ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << endl; } + ssdbg << " }" << endl; } - ssdbg << "}"; + + + ssdbg << "}" << endl; // print all S3FS_PRN_DBG("%s", ssdbg.str().c_str()); diff --git a/src/curl.h b/src/curl.h index 5955a2c..5d0a989 100644 --- a/src/curl.h +++ b/src/curl.h @@ -428,25 +428,32 @@ class S3fsMultiCurl //---------------------------------------------- // class AdditionalHeader //---------------------------------------------- -typedef std::list charcnt_list_t; -typedef std::map headerpair_t; -typedef std::map addheader_t; +#include + +typedef struct add_header{ + regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly. + std::string basestring; + std::string headkey; + std::string headvalue; +}ADDHEAD, *PADDHEAD; + +typedef std::vector addheadlist_t; class AdditionalHeader { private: static AdditionalHeader singleton; bool is_enable; - charcnt_list_t charcntlist; - addheader_t addheader; + addheadlist_t addheadlist; + + protected: + AdditionalHeader(); + ~AdditionalHeader(); public: // Reference singleton static AdditionalHeader* get(void) { return &singleton; } - AdditionalHeader(); - ~AdditionalHeader(); - bool Load(const char* file); void Unload(void); diff --git a/src/s3fs_util.cpp b/src/s3fs_util.cpp index a95f312..0f5b50d 100644 --- a/src/s3fs_util.cpp +++ b/src/s3fs_util.cpp @@ -954,17 +954,19 @@ void show_help (void) " file is the additional HTTP header by file(object) extension.\n" " The configuration file format is below:\n" " -----------\n" - " line = [file suffix] HTTP-header [HTTP-values]\n" + " line = [file suffix or regex] HTTP-header [HTTP-values]\n" " file suffix = file(object) suffix, if this field is empty,\n" - " it means \"*\"(all object).\n" + " it means \"reg:(.*)\".(=all object).\n" + " regex = regular expression to match the file(object) path.\n" + " this type starts with \"reg:\" prefix.\n" " HTTP-header = additional HTTP header name\n" " HTTP-values = additional HTTP header value\n" " -----------\n" " Sample:\n" " -----------\n" - " .gz Content-Encoding gzip\n" - " .Z Content-Encoding compress\n" - " X-S3FS-MYHTTPHEAD myvalue\n" + " .gz Content-Encoding gzip\n" + " .Z Content-Encoding compress\n" + " reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2\n" " -----------\n" " A sample configuration file is uploaded in \"test\" directory.\n" " If you specify this option for set \"Content-Encoding\" HTTP \n" diff --git a/test/sample_ahbe.conf b/test/sample_ahbe.conf index a93e0a5..4e41b79 100644 --- a/test/sample_ahbe.conf +++ b/test/sample_ahbe.conf @@ -4,21 +4,27 @@ # s3fs loads this file at starting. # # Format: -# line = [file suffix] HTTP-header [HTTP-header-values] +# line = [file suffix or regex] HTTP-header [HTTP-header-values] # file suffix = file(object) suffix, if this field is empty, -# it means "*"(all object). +# it means "reg:(.*)".(=all object). +# regex = regular expression to match the file(object) path. +# this type starts with "reg:" prefix. # HTTP-header = additional HTTP header name # HTTP-header-values = additional HTTP header value # # # +# Verification is done in the order in which they are described in the file. +# That order is very important. +# # Example: -# " Content-Encoding gzip" --> all object -# ".gz Content-Encoding gzip" --> only ".gz" extension file +# " Content-Encoding gzip" --> all object +# ".gz Content-Encoding gzip" --> only ".gz" extension file +# "reg:^/DIR/(.*).t2$ Content-Encoding text2" --> "/DIR/*.t2" extension file # # Notice: -# If you need to set all object, you can specify without "suffix". -# Then all of object(file) is added additional header. +# If you need to set all object, you can specify without "suffix" or regex +# type "reg:(.*)". Then all of object(file) is added additional header. # If you have this configuration file for Content-Encoding, you should # know about RFC 2616. # @@ -27,15 +33,20 @@ # Encoding header, and SHOULD NOT be used in the Content-Encoding # header." # -.gz Content-Encoding gzip -.Z Content-Encoding compress -.bz2 Content-Encoding bzip2 -.svgz Content-Encoding gzip -.svg.gz Content-Encoding gzip -.tgz Content-Encoding gzip -.tar.gz Content-Encoding gzip -.taz Content-Encoding gzip -.tz Content-Encoding gzip -.tbz2 Content-Encoding gzip -gz.js Content-Encoding gzip + +# file suffix type +.gz Content-Encoding gzip +.Z Content-Encoding compress +.bz2 Content-Encoding bzip2 +.svgz Content-Encoding gzip +.svg.gz Content-Encoding gzip +.tgz Content-Encoding gzip +.tar.gz Content-Encoding gzip +.taz Content-Encoding gzip +.tz Content-Encoding gzip +.tbz2 Content-Encoding gzip +gz.js Content-Encoding gzip + +# regex type(test) +reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2 From c7cf86c2ef8df72bd49c6c37c0daa8d11bd85770 Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Sun, 7 Feb 2016 05:41:56 +0000 Subject: [PATCH 2/3] Sepalated AdditionalHeader class from curl.* --- src/Makefile.am | 2 +- src/addhead.cpp | 286 ++++++++++++++++++++++++++++++++++++++++++++++++ src/addhead.h | 70 ++++++++++++ src/curl.cpp | 239 +--------------------------------------- src/curl.h | 38 +------ src/s3fs.cpp | 1 + 6 files changed, 360 insertions(+), 276 deletions(-) create mode 100644 src/addhead.cpp create mode 100644 src/addhead.h diff --git a/src/Makefile.am b/src/Makefile.am index 5741f1b..f102c42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ if USE_GNUTLS_NETTLE AM_CPPFLAGS += -DUSE_GNUTLS_NETTLE endif -s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h common.h +s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h addhead.cpp addhead.h common.h if USE_SSL_OPENSSL s3fs_SOURCES += openssl_auth.cpp endif diff --git a/src/addhead.cpp b/src/addhead.cpp new file mode 100644 index 0000000..be4036f --- /dev/null +++ b/src/addhead.cpp @@ -0,0 +1,286 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "addhead.h" +#include "curl.h" +#include "s3fs.h" + +using namespace std; + +//------------------------------------------------------------------- +// Symbols +//------------------------------------------------------------------- +#define ADD_HEAD_REGEX "reg:" + +//------------------------------------------------------------------- +// Class AdditionalHeader +//------------------------------------------------------------------- +AdditionalHeader AdditionalHeader::singleton; + +//------------------------------------------------------------------- +// Class AdditionalHeader method +//------------------------------------------------------------------- +AdditionalHeader::AdditionalHeader() +{ + if(this == AdditionalHeader::get()){ + is_enable = false; + }else{ + assert(false); + } +} + +AdditionalHeader::~AdditionalHeader() +{ + if(this == AdditionalHeader::get()){ + Unload(); + }else{ + assert(false); + } +} + +bool AdditionalHeader::Load(const char* file) +{ + if(!file){ + S3FS_PRN_WARN("file is NULL."); + return false; + } + Unload(); + + ifstream AH(file); + if(!AH.good()){ + S3FS_PRN_WARN("Could not open file(%s).", file); + return false; + } + + // read file + string line; + PADDHEAD paddhead; + while(getline(AH, line)){ + if('#' == line[0]){ + continue; + } + if(0 == line.size()){ + continue; + } + // load a line + stringstream ss(line); + string key(""); // suffix(key) + string head; // additional HTTP header + string value; // header value + if(0 == isblank(line[0])){ + ss >> key; + } + if(ss){ + ss >> head; + if(ss && static_cast(ss.tellg()) < line.size()){ + value = line.substr(static_cast(ss.tellg()) + 1); + } + } + + // check it + if(0 == head.size()){ + if(0 == key.size()){ + continue; + } + S3FS_PRN_ERR("file format error: %s key(suffix) is no HTTP header value.", key.c_str()); + Unload(); + return false; + } + + paddhead = new ADDHEAD; + if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){ + // regex + if(key.size() <= strlen(ADD_HEAD_REGEX)){ + S3FS_PRN_ERR("file format error: %s key(suffix) does not have key string.", key.c_str()); + continue; + } + key = key.substr(strlen(ADD_HEAD_REGEX)); + + // compile + regex_t* preg = new regex_t; + int result; + char errbuf[256]; + if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info + regerror(result, preg, errbuf, sizeof(errbuf)); + S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf); + delete preg; + delete paddhead; + continue; + } + + // set + paddhead->pregex = preg; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; + + }else{ + // not regex, directly comparing + paddhead->pregex = NULL; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; + } + + // add list + addheadlist.push_back(paddhead); + + // set flag + if(!is_enable){ + is_enable = true; + } + } + return true; +} + +void AdditionalHeader::Unload(void) +{ + is_enable = false; + + for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); iter = addheadlist.erase(iter)){ + PADDHEAD paddhead = *iter; + if(paddhead){ + if(paddhead->pregex){ + regfree(paddhead->pregex); + delete paddhead->pregex; + } + delete paddhead; + } + } +} + +bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const +{ + if(!is_enable){ + return true; + } + if(!path){ + S3FS_PRN_WARN("path is NULL."); + return false; + } + + size_t pathlength = strlen(path); + + // loop + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){ + const PADDHEAD paddhead = *iter; + if(!paddhead){ + continue; + } + + if(paddhead->pregex){ + // regex + int result; + regmatch_t match; // not use + + if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + }else{ + // directly comparing + if(paddhead->basestring.length() < pathlength){ + if(0 == paddhead->basestring.length() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + } + } + } + return true; +} + +struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const char* path) const +{ + headers_t meta; + + if(!AddHeader(meta, path)){ + return list; + } + for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){ + // Adding header + list = curl_slist_sort_insert(list, iter->first.c_str(), iter->second.c_str()); + } + meta.clear(); + S3FS_MALLOCTRIM(0); + return list; +} + +bool AdditionalHeader::Dump(void) const +{ + if(!IS_S3FS_LOG_DBG()){ + return true; + } + + stringstream ssdbg; + int cnt = 1; + + ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << endl; + + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){ + const PADDHEAD paddhead = *iter; + + ssdbg << " [" << cnt << "] = {" << endl; + + if(paddhead){ + if(paddhead->pregex){ + ssdbg << " type\t\t--->\tregex" << endl; + }else{ + ssdbg << " type\t\t--->\tsuffix matching" << endl; + } + ssdbg << " base string\t--->\t" << paddhead->basestring << endl; + ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << endl; + } + ssdbg << " }" << endl; + } + + + ssdbg << "}" << endl; + + // print all + S3FS_PRN_DBG("%s", ssdbg.str().c_str()); + + return true; +} + +/* +* Local variables: +* tab-width: 4 +* c-basic-offset: 4 +* End: +* vim600: noet sw=4 ts=4 fdm=marker +* vim<600: noet sw=4 ts=4 +*/ diff --git a/src/addhead.h b/src/addhead.h new file mode 100644 index 0000000..c2ef9b1 --- /dev/null +++ b/src/addhead.h @@ -0,0 +1,70 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef S3FS_ADDHEAD_H_ +#define S3FS_ADDHEAD_H_ + +#include + +//---------------------------------------------- +// class AdditionalHeader +//---------------------------------------------- +typedef struct add_header{ + regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly. + std::string basestring; + std::string headkey; + std::string headvalue; +}ADDHEAD, *PADDHEAD; + +typedef std::vector addheadlist_t; + +class AdditionalHeader +{ + private: + static AdditionalHeader singleton; + bool is_enable; + addheadlist_t addheadlist; + + protected: + AdditionalHeader(); + ~AdditionalHeader(); + + public: + // Reference singleton + static AdditionalHeader* get(void) { return &singleton; } + + bool Load(const char* file); + void Unload(void); + + bool AddHeader(headers_t& meta, const char* path) const; + struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const; + bool Dump(void) const; +}; + +#endif // S3FS_ADDHEAD_H_ + +/* +* Local variables: +* tab-width: 4 +* c-basic-offset: 4 +* End: +* vim600: noet sw=4 ts=4 fdm=marker +* vim<600: noet sw=4 ts=4 +*/ diff --git a/src/curl.cpp b/src/curl.cpp index 91902af..942ca6a 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -48,6 +48,7 @@ #include "s3fs.h" #include "s3fs_util.h" #include "s3fs_auth.h" +#include "addhead.h" using namespace std; @@ -3780,244 +3781,6 @@ int S3fsMultiCurl::Request(void) return 0; } -//------------------------------------------------------------------- -// Symbols -//------------------------------------------------------------------- -#define ADD_HEAD_REGEX "reg:" - -//------------------------------------------------------------------- -// Class AdditionalHeader -//------------------------------------------------------------------- -AdditionalHeader AdditionalHeader::singleton; - -//------------------------------------------------------------------- -// Class AdditionalHeader method -//------------------------------------------------------------------- -AdditionalHeader::AdditionalHeader() -{ - if(this == AdditionalHeader::get()){ - is_enable = false; - }else{ - assert(false); - } -} - -AdditionalHeader::~AdditionalHeader() -{ - if(this == AdditionalHeader::get()){ - Unload(); - }else{ - assert(false); - } -} - -bool AdditionalHeader::Load(const char* file) -{ - if(!file){ - S3FS_PRN_WARN("file is NULL."); - return false; - } - Unload(); - - ifstream AH(file); - if(!AH.good()){ - S3FS_PRN_WARN("Could not open file(%s).", file); - return false; - } - - // read file - string line; - PADDHEAD paddhead; - while(getline(AH, line)){ - if('#' == line[0]){ - continue; - } - if(0 == line.size()){ - continue; - } - // load a line - stringstream ss(line); - string key(""); // suffix(key) - string head; // additional HTTP header - string value; // header value - if(0 == isblank(line[0])){ - ss >> key; - } - if(ss){ - ss >> head; - if(ss && static_cast(ss.tellg()) < line.size()){ - value = line.substr(static_cast(ss.tellg()) + 1); - } - } - - // check it - if(0 == head.size()){ - if(0 == key.size()){ - continue; - } - S3FS_PRN_ERR("file format error: %s key(suffix) is no HTTP header value.", key.c_str()); - Unload(); - return false; - } - - paddhead = new ADDHEAD; - if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){ - // regex - if(key.size() <= strlen(ADD_HEAD_REGEX)){ - S3FS_PRN_ERR("file format error: %s key(suffix) does not have key string.", key.c_str()); - continue; - } - key = key.substr(strlen(ADD_HEAD_REGEX)); - - // compile - regex_t* preg = new regex_t; - int result; - char errbuf[256]; - if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info - regerror(result, preg, errbuf, sizeof(errbuf)); - S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf); - delete preg; - delete paddhead; - continue; - } - - // set - paddhead->pregex = preg; - paddhead->basestring = key; - paddhead->headkey = head; - paddhead->headvalue = value; - - }else{ - // not regex, directly comparing - paddhead->pregex = NULL; - paddhead->basestring = key; - paddhead->headkey = head; - paddhead->headvalue = value; - } - - // add list - addheadlist.push_back(paddhead); - - // set flag - if(!is_enable){ - is_enable = true; - } - } - return true; -} - -void AdditionalHeader::Unload(void) -{ - is_enable = false; - - for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); iter = addheadlist.erase(iter)){ - PADDHEAD paddhead = *iter; - if(paddhead){ - if(paddhead->pregex){ - regfree(paddhead->pregex); - delete paddhead->pregex; - } - delete paddhead; - } - } -} - -bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const -{ - if(!is_enable){ - return true; - } - if(!path){ - S3FS_PRN_WARN("path is NULL."); - return false; - } - - size_t pathlength = strlen(path); - - // loop - for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){ - const PADDHEAD paddhead = *iter; - if(!paddhead){ - continue; - } - - if(paddhead->pregex){ - // regex - int result; - regmatch_t match; // not use - - if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ - // match -> adding header - meta[paddhead->headkey] = paddhead->headvalue; - break; - } - }else{ - // directly comparing - if(paddhead->basestring.length() < pathlength){ - if(0 == paddhead->basestring.length() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){ - // match -> adding header - meta[paddhead->headkey] = paddhead->headvalue; - break; - } - } - } - } - return true; -} - -struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const char* path) const -{ - headers_t meta; - - if(!AddHeader(meta, path)){ - return list; - } - for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){ - // Adding header - list = curl_slist_sort_insert(list, iter->first.c_str(), iter->second.c_str()); - } - meta.clear(); - S3FS_MALLOCTRIM(0); - return list; -} - -bool AdditionalHeader::Dump(void) const -{ - if(!IS_S3FS_LOG_DBG()){ - return true; - } - - stringstream ssdbg; - int cnt = 1; - - ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << endl; - - for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){ - const PADDHEAD paddhead = *iter; - - ssdbg << " [" << cnt << "] = {" << endl; - - if(paddhead){ - if(paddhead->pregex){ - ssdbg << " type\t\t--->\tregex" << endl; - }else{ - ssdbg << " type\t\t--->\tsuffix matching" << endl; - } - ssdbg << " base string\t--->\t" << paddhead->basestring << endl; - ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << endl; - } - ssdbg << " }" << endl; - } - - - ssdbg << "}" << endl; - - // print all - S3FS_PRN_DBG("%s", ssdbg.str().c_str()); - - return true; -} - //------------------------------------------------------------------- // Utility functions //------------------------------------------------------------------- diff --git a/src/curl.h b/src/curl.h index 5d0a989..92b5db0 100644 --- a/src/curl.h +++ b/src/curl.h @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #ifndef S3FS_CURL_H_ #define S3FS_CURL_H_ @@ -425,43 +426,6 @@ class S3fsMultiCurl int Request(void); }; -//---------------------------------------------- -// class AdditionalHeader -//---------------------------------------------- -#include - -typedef struct add_header{ - regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly. - std::string basestring; - std::string headkey; - std::string headvalue; -}ADDHEAD, *PADDHEAD; - -typedef std::vector addheadlist_t; - -class AdditionalHeader -{ - private: - static AdditionalHeader singleton; - bool is_enable; - addheadlist_t addheadlist; - - protected: - AdditionalHeader(); - ~AdditionalHeader(); - - public: - // Reference singleton - static AdditionalHeader* get(void) { return &singleton; } - - bool Load(const char* file); - void Unload(void); - - bool AddHeader(headers_t& meta, const char* path) const; - struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const; - bool Dump(void) const; -}; - //---------------------------------------------- // Utility Functions //---------------------------------------------- diff --git a/src/s3fs.cpp b/src/s3fs.cpp index 8b3e2fc..c0c941b 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -52,6 +52,7 @@ #include "s3fs_util.h" #include "fdcache.h" #include "s3fs_auth.h" +#include "addhead.h" using namespace std; From 1af7aaeccbaf9b37238b69d4f25878d9e1512a27 Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Sun, 7 Feb 2016 05:53:56 +0000 Subject: [PATCH 3/3] Fixed addhead.cpp for cppcheck --- src/addhead.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/addhead.cpp b/src/addhead.cpp index be4036f..3dcfb40 100644 --- a/src/addhead.cpp +++ b/src/addhead.cpp @@ -201,10 +201,8 @@ bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const if(paddhead->pregex){ // regex - int result; regmatch_t match; // not use - - if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ + if(0 == regexec(paddhead->pregex, path, 1, &match, 0)){ // match -> adding header meta[paddhead->headkey] = paddhead->headvalue; break;