From 7c44e645abd3865e01695977bc9c22ae08179970 Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Mon, 16 Jan 2023 16:11:55 +0100 Subject: [PATCH 1/9] XrdHttpReq: Corrected needs_base64_padding logic --- src/XrdHttp/XrdHttpReq.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 66023456957..5641cb79df4 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -148,13 +148,13 @@ static bool needs_base64_padding(const std::string &rfc_name) return true; } else if (!strcasecmp(rfc_name.c_str(), "adler32")) { return false; - } else if (strcasecmp(rfc_name.c_str(), "SHA")) { + } else if (!strcasecmp(rfc_name.c_str(), "SHA")) { return true; - } else if (strcasecmp(rfc_name.c_str(), "SHA-256")) { + } else if (!strcasecmp(rfc_name.c_str(), "SHA-256")) { return true; - } else if (strcasecmp(rfc_name.c_str(), "SHA-512")) { + } else if (!strcasecmp(rfc_name.c_str(), "SHA-512")) { return true; - } else if (strcasecmp(rfc_name.c_str(), "UNIXcksum")) { + } else if (!strcasecmp(rfc_name.c_str(), "UNIXcksum")) { return false; } return false; From 8c9fbb3409e936b2f36861bcc0085c02dc0a9272 Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Mon, 30 Jan 2023 17:21:57 +0100 Subject: [PATCH 2/9] XrdHttp: Modified the checksum handling logic a) Ignore unsupported checksums b) On the first supported checksum return that checksum c) If no requested checksums are supported return the default checksum (with the proper name) d) If checksums are not supported at all, return an error. (405 Method not allowed) Fixes #1707 --- src/XrdCl/XrdClUtils.hh | 21 ++----------- src/XrdHttp/XrdHttpReq.cc | 63 +++++++++++++++++++++++++++++++++++++-- src/XrdHttp/XrdHttpReq.hh | 8 +++++ src/XrdUtils/XrdUtils.hh | 60 +++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 src/XrdUtils/XrdUtils.hh diff --git a/src/XrdCl/XrdClUtils.hh b/src/XrdCl/XrdClUtils.hh index 552ac03be0f..3b66115945a 100644 --- a/src/XrdCl/XrdClUtils.hh +++ b/src/XrdCl/XrdClUtils.hh @@ -31,6 +31,7 @@ #include "XrdCl/XrdClPostMaster.hh" #include "XrdCl/XrdClXRootDTransport.hh" #include "XrdNet/XrdNetUtils.hh" +#include "XrdUtils/XrdUtils.hh" #include @@ -56,25 +57,7 @@ namespace XrdCl const std::string &input, const std::string &delimiter ) { - size_t start = 0; - size_t end = 0; - size_t length = 0; - - do - { - end = input.find( delimiter, start ); - - if( end != std::string::npos ) - length = end - start; - else - length = input.length() - start; - - if( length ) - result.push_back( input.substr( start, length ) ); - - start = end + delimiter.size(); - } - while( end != std::string::npos ); + XrdUtils::Utils::splitString(result,input,delimiter); } //------------------------------------------------------------------------ diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 5641cb79df4..00058e29d0f 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -49,7 +49,7 @@ #include "Xrd/XrdLink.hh" #include "XrdXrootd/XrdXrootdBridge.hh" #include "Xrd/XrdBuffer.hh" - +#include "XrdUtils/XrdUtils.hh" #include #include #include @@ -91,6 +91,10 @@ static std::string convert_digest_rfc_name(const std::string &rfc_name_multiple) return "SHA-512"; } else if (!strcasecmp(rfc_name.c_str(), "UNIXcksum")) { return "UNIXcksum"; + } else if (!strcasecmp(rfc_name.c_str(), "crc32")) { + return "crc32"; + } else if (!strcasecmp(rfc_name.c_str(), "crc32c")) { + return "crc32c"; } } return "unknown"; @@ -117,6 +121,10 @@ static XrdOucString convert_digest_name(const std::string &rfc_name_multiple) return "sha512"; } else if (!strcasecmp(rfc_name.c_str(), "UNIXcksum")) { return "cksum"; + } else if (!strcasecmp(rfc_name.c_str(), "crc32")) { + return "crc32"; + } else if (!strcasecmp(rfc_name.c_str(), "crc32c")) { + return "crc32c"; } } return "unknown"; @@ -137,6 +145,10 @@ static std::string convert_xrootd_to_rfc_name(const std::string &xrootd_name) return "SHA-512"; } else if (!strcasecmp(xrootd_name.c_str(), "cksum")) { return "UNIXcksum"; + } else if (!strcasecmp(xrootd_name.c_str(), "crc32")) { + return "crc32"; + } else if (!strcasecmp(xrootd_name.c_str(), "crc32c")) { + return "crc32c"; } return "unknown"; } @@ -156,6 +168,10 @@ static bool needs_base64_padding(const std::string &rfc_name) return true; } else if (!strcasecmp(rfc_name.c_str(), "UNIXcksum")) { return false; + } else if (!strcasecmp(rfc_name.c_str(), "crc32")) { + return false; + } else if (!strcasecmp(rfc_name.c_str(), "crc32c")) { + return true; } return false; } @@ -271,6 +287,8 @@ int XrdHttpReq::parseLine(char *line, int len) { } else if (!strcmp(key, "Want-Digest")) { m_req_digest.assign(val, line + len - val); trim(m_req_digest); + //Transform the user requests' want-digest to lowercase + std::transform(m_req_digest.begin(),m_req_digest.end(),m_req_digest.begin(),::tolower); } else if (!strcmp(key, "Depth")) { depth = -1; if (strcmp(val, "infinity")) @@ -1032,6 +1050,42 @@ void XrdHttpReq::mapXrdErrorToHttpStatus() { } } +/** + * Select the checksum to be computed depending on the userDigest passed in parameter + * @param userDigest the digest request from the user (extracted from the Want-Digest header) + * @param selectedChecksum the checksum that will be performed + */ +void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & selectedChecksum) { + char * configChecksumList; + selectedChecksum = "unknown"; + if((configChecksumList = getenv("XRD_CSLIST"))) { + //The env variable is set, some checksums have been configured + std::vector userDigestsVec; + XrdUtils::Utils::splitString(userDigestsVec,userDigest,","); + std::vector configChecksums; + XrdUtils::Utils::splitString(configChecksums,configChecksumList,","); + selectedChecksum = configChecksums[0]; + auto configChecksumItor = configChecksums.end(); + std::find_if(userDigestsVec.begin(), userDigestsVec.end(), [&configChecksums, &configChecksumItor](const std::string & userDigest){ + configChecksumItor = std::find_if(configChecksums.begin(),configChecksums.end(),[&userDigest](const std::string & configChecksum){ + std::string userDigestTrimmed = userDigest; + trim(userDigestTrimmed); + if(configChecksum.find(userDigestTrimmed) != std::string::npos) { + return true; + } + return false; + }); + return configChecksumItor != configChecksums.end(); + }); + //By default, the selected checksum is the first one of the configured checksum list. + // If the user gave a checksum that do not exist, then the checksum returned will be the default one + configChecksumItor = configChecksumItor != configChecksums.end() ? configChecksumItor : configChecksums.begin(); + std::vector checksumIdName; + XrdUtils::Utils::splitString(checksumIdName,*configChecksumItor,":"); + selectedChecksum = checksumIdName[1]; + } +} + int XrdHttpReq::ProcessHTTPReq() { kXR_int32 l; @@ -1105,12 +1159,15 @@ int XrdHttpReq::ProcessHTTPReq() { const char *opaque = strchr(resourceplusopaque.c_str(), '?'); // Note that doChksum requires that the memory stays alive until the callback is invoked. m_resource_with_digest = resourceplusopaque; + std::string selectedChecksum; + selectChecksum(m_req_digest,selectedChecksum); + m_req_digest = convert_digest_name(selectedChecksum).c_str(); if (!opaque) { m_resource_with_digest += "?cks.type="; - m_resource_with_digest += convert_digest_name(m_req_digest); + m_resource_with_digest += m_req_digest.c_str(); } else { m_resource_with_digest += "&cks.type="; - m_resource_with_digest += convert_digest_name(m_req_digest); + m_resource_with_digest += m_req_digest.c_str(); } if (prot->doChksum(m_resource_with_digest) < 0) { // In this case, the Want-Digest header was set and PostProcess gave the go-ahead to do a checksum. diff --git a/src/XrdHttp/XrdHttpReq.hh b/src/XrdHttp/XrdHttpReq.hh index 5cbb81ea57a..e3b13cae3a1 100644 --- a/src/XrdHttp/XrdHttpReq.hh +++ b/src/XrdHttp/XrdHttpReq.hh @@ -116,6 +116,14 @@ private: // Sanitize the resource from http[s]://[host]/ questionable prefix void sanitizeResourcePfx(); + + /** + * Select the checksum to be computed depending on the userDigest passed in parameter + * @param userDigest the digest request from the user (extracted from the Want-Digest header) + * @param selectedChecksum the checksum that will be performed + */ + void selectChecksum(const std::string & userDigest, std::string & selectedChecksum); + public: XrdHttpReq(XrdHttpProtocol *protinstance) : keepalive(true) { diff --git a/src/XrdUtils/XrdUtils.hh b/src/XrdUtils/XrdUtils.hh new file mode 100644 index 00000000000..a632669357f --- /dev/null +++ b/src/XrdUtils/XrdUtils.hh @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN) +// Author: Cedric Caffy +//------------------------------------------------------------------------------ +// XRootD is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// XRootD 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 Lesser General Public License +// along with XRootD. If not, see . +//------------------------------------------------------------------------------ + +#ifndef XROOTD_XRDUTILS_HH +#define XROOTD_XRDUTILS_HH + +#include + +namespace XrdUtils { + + class Utils { + public: + //------------------------------------------------------------------------ + //! Split a string + //------------------------------------------------------------------------ + template + static void splitString( Container &result, + const std::string &input, + const std::string &delimiter ) + { + size_t start = 0; + size_t end = 0; + size_t length = 0; + + do + { + end = input.find( delimiter, start ); + + if( end != std::string::npos ) + length = end - start; + else + length = input.length() - start; + + if( length ) + result.push_back( input.substr( start, length ) ); + + start = end + delimiter.size(); + } + while( end != std::string::npos ); + } + }; + +} + +#endif //XROOTD_XRDUTILS_HH From 217c3968ca28629f638f576ee5ab9805c81eb72f Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Mon, 30 Jan 2023 17:28:11 +0100 Subject: [PATCH 3/9] Update notes on issue 1707: XrdHttp checksum logic change --- docs/PreReleaseNotes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/PreReleaseNotes.txt b/docs/PreReleaseNotes.txt index 6a55e1a63cb..35c4ba578e8 100644 --- a/docs/PreReleaseNotes.txt +++ b/docs/PreReleaseNotes.txt @@ -31,6 +31,8 @@ Prerelease Notes **Commit: 0f79a38 **[XrdMacaroons] Fix authentication when different tokens are used in the same TCP session** **Commit: 4410d56 + **[XrdHttp] 500 Internal Server Error on unknown checksum algorithm** + **Commit: 8c9fbb3 + **Miscellaneous** **[Pss]** Convert leftover print statement to debug action. From 94fd932335375d030d7d5b19e1f0acc142d4f4cc Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 09:33:32 +0100 Subject: [PATCH 4/9] XrdHttp: The configured checksum list is now initialized in the Configure() method of the XrdHttpProtocol --- src/XrdHttp/XrdHttpProtocol.cc | 2 ++ src/XrdHttp/XrdHttpProtocol.hh | 3 +++ src/XrdHttp/XrdHttpReq.cc | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/XrdHttp/XrdHttpProtocol.cc b/src/XrdHttp/XrdHttpProtocol.cc index f7ee7b2cc91..f9b8f0dd4c4 100644 --- a/src/XrdHttp/XrdHttpProtocol.cc +++ b/src/XrdHttp/XrdHttpProtocol.cc @@ -108,6 +108,7 @@ XrdSysError XrdHttpProtocol::eDest = 0; // Error message handler XrdSecService *XrdHttpProtocol::CIA = 0; // Authentication Server int XrdHttpProtocol::m_bio_type = 0; // BIO type identifier for our custom BIO. BIO_METHOD *XrdHttpProtocol::m_bio_method = NULL; // BIO method constructor. +char *XrdHttpProtocol::xrd_cslist = nullptr; XrdSysTrace XrdHttpTrace("http"); @@ -1633,6 +1634,7 @@ int XrdHttpProtocol::Configure(char *parms, XrdProtocol_Config * pi) { BPool = pi->BPool; hailWait = 10000; readWait = 30000; + xrd_cslist = getenv("XRD_CSLIST"); Port = pi->Port; diff --git a/src/XrdHttp/XrdHttpProtocol.hh b/src/XrdHttp/XrdHttpProtocol.hh index 51d31c34a4a..ee4f975d841 100644 --- a/src/XrdHttp/XrdHttpProtocol.hh +++ b/src/XrdHttp/XrdHttpProtocol.hh @@ -415,5 +415,8 @@ protected: /// C-style vptr table for our custom BIO objects. static BIO_METHOD *m_bio_method; + + /// The list of checksums that were configured via the xrd.cksum parameter on the server config file + static char * xrd_cslist; }; #endif diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 00058e29d0f..403c1187a5c 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -1056,9 +1056,9 @@ void XrdHttpReq::mapXrdErrorToHttpStatus() { * @param selectedChecksum the checksum that will be performed */ void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & selectedChecksum) { - char * configChecksumList; + char * configChecksumList = XrdHttpProtocol::xrd_cslist; selectedChecksum = "unknown"; - if((configChecksumList = getenv("XRD_CSLIST"))) { + if(configChecksumList != nullptr) { //The env variable is set, some checksums have been configured std::vector userDigestsVec; XrdUtils::Utils::splitString(userDigestsVec,userDigest,","); From 2b4af13e832b25828e8ae1e787b12abb0ba626f4 Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 10:43:23 +0100 Subject: [PATCH 5/9] XrdOucUtils: Added the splitString() method to the XrdOucUtils class and deleted the XrdUtils directory --- src/XrdCl/XrdClUtils.hh | 4 +-- src/XrdHttp/XrdHttpReq.cc | 8 +++--- src/XrdOuc/XrdOucUtils.hh | 34 ++++++++++++++++++++-- src/XrdUtils/XrdUtils.hh | 60 --------------------------------------- 4 files changed, 38 insertions(+), 68 deletions(-) delete mode 100644 src/XrdUtils/XrdUtils.hh diff --git a/src/XrdCl/XrdClUtils.hh b/src/XrdCl/XrdClUtils.hh index 3b66115945a..3d61b5829d3 100644 --- a/src/XrdCl/XrdClUtils.hh +++ b/src/XrdCl/XrdClUtils.hh @@ -31,7 +31,7 @@ #include "XrdCl/XrdClPostMaster.hh" #include "XrdCl/XrdClXRootDTransport.hh" #include "XrdNet/XrdNetUtils.hh" -#include "XrdUtils/XrdUtils.hh" +#include "XrdOuc/XrdOucUtils.hh" #include @@ -57,7 +57,7 @@ namespace XrdCl const std::string &input, const std::string &delimiter ) { - XrdUtils::Utils::splitString(result,input,delimiter); + XrdOucUtils::splitString(result,input,delimiter); } //------------------------------------------------------------------------ diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 403c1187a5c..12f2c6fc062 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -49,12 +49,12 @@ #include "Xrd/XrdLink.hh" #include "XrdXrootd/XrdXrootdBridge.hh" #include "Xrd/XrdBuffer.hh" -#include "XrdUtils/XrdUtils.hh" #include #include #include #include #include +#include "XrdOuc/XrdOucUtils.hh" #include "XrdHttpUtils.hh" @@ -1061,9 +1061,9 @@ void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & sel if(configChecksumList != nullptr) { //The env variable is set, some checksums have been configured std::vector userDigestsVec; - XrdUtils::Utils::splitString(userDigestsVec,userDigest,","); + XrdOucUtils::splitString(userDigestsVec,userDigest,","); std::vector configChecksums; - XrdUtils::Utils::splitString(configChecksums,configChecksumList,","); + XrdOucUtils::splitString(configChecksums,configChecksumList,","); selectedChecksum = configChecksums[0]; auto configChecksumItor = configChecksums.end(); std::find_if(userDigestsVec.begin(), userDigestsVec.end(), [&configChecksums, &configChecksumItor](const std::string & userDigest){ @@ -1081,7 +1081,7 @@ void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & sel // If the user gave a checksum that do not exist, then the checksum returned will be the default one configChecksumItor = configChecksumItor != configChecksums.end() ? configChecksumItor : configChecksums.begin(); std::vector checksumIdName; - XrdUtils::Utils::splitString(checksumIdName,*configChecksumItor,":"); + XrdOucUtils::splitString(checksumIdName,*configChecksumItor,":"); selectedChecksum = checksumIdName[1]; } } diff --git a/src/XrdOuc/XrdOucUtils.hh b/src/XrdOuc/XrdOucUtils.hh index 9442bcc24c9..54844828c2d 100644 --- a/src/XrdOuc/XrdOucUtils.hh +++ b/src/XrdOuc/XrdOucUtils.hh @@ -32,6 +32,7 @@ #include #include +#include class XrdSysError; class XrdOucString; @@ -130,7 +131,36 @@ static bool PidFile(XrdSysError &eDest, const char *path); static int getModificationTime(const char * path, time_t & modificationTime); - XrdOucUtils() {} - ~XrdOucUtils() {} + //------------------------------------------------------------------------ + //! Split a string + //------------------------------------------------------------------------ + template + static void splitString( Container &result, + const std::string &input, + const std::string &delimiter ) + { + size_t start = 0; + size_t end = 0; + size_t length = 0; + + do + { + end = input.find( delimiter, start ); + + if( end != std::string::npos ) + length = end - start; + else + length = input.length() - start; + + if( length ) + result.push_back( input.substr( start, length ) ); + + start = end + delimiter.size(); + } + while( end != std::string::npos ); + } + + XrdOucUtils() {} + ~XrdOucUtils() {} }; #endif diff --git a/src/XrdUtils/XrdUtils.hh b/src/XrdUtils/XrdUtils.hh deleted file mode 100644 index a632669357f..00000000000 --- a/src/XrdUtils/XrdUtils.hh +++ /dev/null @@ -1,60 +0,0 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN) -// Author: Cedric Caffy -//------------------------------------------------------------------------------ -// XRootD is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// XRootD 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 Lesser General Public License -// along with XRootD. If not, see . -//------------------------------------------------------------------------------ - -#ifndef XROOTD_XRDUTILS_HH -#define XROOTD_XRDUTILS_HH - -#include - -namespace XrdUtils { - - class Utils { - public: - //------------------------------------------------------------------------ - //! Split a string - //------------------------------------------------------------------------ - template - static void splitString( Container &result, - const std::string &input, - const std::string &delimiter ) - { - size_t start = 0; - size_t end = 0; - size_t length = 0; - - do - { - end = input.find( delimiter, start ); - - if( end != std::string::npos ) - length = end - start; - else - length = input.length() - start; - - if( length ) - result.push_back( input.substr( start, length ) ); - - start = end + delimiter.size(); - } - while( end != std::string::npos ); - } - }; - -} - -#endif //XROOTD_XRDUTILS_HH From 355bda02f6fc76fee4b318db92131cb80bfc4e94 Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 13:34:58 +0100 Subject: [PATCH 6/9] XrdOucUtils: splitString() implementation moved to .cc file --- src/XrdOuc/XrdOucUtils.cc | 30 ++++++++++++++++++++++++++++++ src/XrdOuc/XrdOucUtils.hh | 33 +++++---------------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/XrdOuc/XrdOucUtils.cc b/src/XrdOuc/XrdOucUtils.cc index 8d45818f5d4..73df31b1879 100644 --- a/src/XrdOuc/XrdOucUtils.cc +++ b/src/XrdOuc/XrdOucUtils.cc @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifdef WIN32 #include @@ -1398,5 +1400,33 @@ int XrdOucUtils::getModificationTime(const char *path, time_t &modificationTime) return statRet; } +template +void XrdOucUtils::splitString(Container &result, const std::string &input, const std::string &delimiter) { + { + size_t start = 0; + size_t end = 0; + size_t length = 0; + + do + { + end = input.find( delimiter, start ); + + if( end != std::string::npos ) + length = end - start; + else + length = input.length() - start; + + if( length ) + result.push_back( input.substr( start, length ) ); + + start = end + delimiter.size(); + } + while( end != std::string::npos ); + } +} + +template void XrdOucUtils::splitString>(std::vector &result, const std::string &input, const std::string &delimiter); +template void XrdOucUtils::splitString>(std::list &result, const std::string &input, const std::string &delimiter); + #endif diff --git a/src/XrdOuc/XrdOucUtils.hh b/src/XrdOuc/XrdOucUtils.hh index 54844828c2d..d609f7f3dcd 100644 --- a/src/XrdOuc/XrdOucUtils.hh +++ b/src/XrdOuc/XrdOucUtils.hh @@ -131,34 +131,11 @@ static bool PidFile(XrdSysError &eDest, const char *path); static int getModificationTime(const char * path, time_t & modificationTime); - //------------------------------------------------------------------------ - //! Split a string - //------------------------------------------------------------------------ - template - static void splitString( Container &result, - const std::string &input, - const std::string &delimiter ) - { - size_t start = 0; - size_t end = 0; - size_t length = 0; - - do - { - end = input.find( delimiter, start ); - - if( end != std::string::npos ) - length = end - start; - else - length = input.length() - start; - - if( length ) - result.push_back( input.substr( start, length ) ); - - start = end + delimiter.size(); - } - while( end != std::string::npos ); - } +//------------------------------------------------------------------------ +//! Split a string +//------------------------------------------------------------------------ +template +static void splitString( Container &result, const std::string &input, const std::string &delimiter ); XrdOucUtils() {} ~XrdOucUtils() {} From 42cdc25d56e4ed223570f30f9f08a9436df4749e Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 15:06:51 +0100 Subject: [PATCH 7/9] XrdClUtils: Added history about the splitString() method --- src/XrdCl/XrdClUtils.hh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/XrdCl/XrdClUtils.hh b/src/XrdCl/XrdClUtils.hh index 3d61b5829d3..77cd8898a31 100644 --- a/src/XrdCl/XrdClUtils.hh +++ b/src/XrdCl/XrdClUtils.hh @@ -57,6 +57,12 @@ namespace XrdCl const std::string &input, const std::string &delimiter ) { + /* + * This was done in order to not duplicate code as this method + * is also used in XrdHttp + * TODO: Maybe this method could be collapsed + * to avoid this middle-man call here + */ XrdOucUtils::splitString(result,input,delimiter); } From 549837e8c2a8fd53b1421429d2130850aa3d26ed Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 15:08:19 +0100 Subject: [PATCH 8/9] Updated pre-release notes for the XrdHttp checksum logic change to follow the RFC --- docs/PreReleaseNotes.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/PreReleaseNotes.txt b/docs/PreReleaseNotes.txt index 35c4ba578e8..99fd876c464 100644 --- a/docs/PreReleaseNotes.txt +++ b/docs/PreReleaseNotes.txt @@ -31,8 +31,8 @@ Prerelease Notes **Commit: 0f79a38 **[XrdMacaroons] Fix authentication when different tokens are used in the same TCP session** **Commit: 4410d56 - **[XrdHttp] 500 Internal Server Error on unknown checksum algorithm** - **Commit: 8c9fbb3 + **[XrdHttp] Follow RFC checksum requirements in XRootD http** + **Commit: TO_BE_MODIFIED + **Miscellaneous** **[Pss]** Convert leftover print statement to debug action. From fc603035d7e5043b667d40fc1781edf3aaa823ce Mon Sep 17 00:00:00 2001 From: Cedric Caffy Date: Wed, 1 Feb 2023 16:49:06 +0100 Subject: [PATCH 9/9] XrdOucTUtils: Created this utility class so that it contains only templated code splitString() has been moved to this class --- src/XrdCl/XrdClUtils.hh | 4 +-- src/XrdHttp/XrdHttpReq.cc | 8 ++--- src/XrdOuc/XrdOucTUtils.hh | 71 ++++++++++++++++++++++++++++++++++++++ src/XrdOuc/XrdOucUtils.cc | 28 --------------- src/XrdOuc/XrdOucUtils.hh | 6 ---- 5 files changed, 77 insertions(+), 40 deletions(-) create mode 100644 src/XrdOuc/XrdOucTUtils.hh diff --git a/src/XrdCl/XrdClUtils.hh b/src/XrdCl/XrdClUtils.hh index 77cd8898a31..6691196f66b 100644 --- a/src/XrdCl/XrdClUtils.hh +++ b/src/XrdCl/XrdClUtils.hh @@ -31,7 +31,7 @@ #include "XrdCl/XrdClPostMaster.hh" #include "XrdCl/XrdClXRootDTransport.hh" #include "XrdNet/XrdNetUtils.hh" -#include "XrdOuc/XrdOucUtils.hh" +#include "XrdOuc/XrdOucTUtils.hh" #include @@ -63,7 +63,7 @@ namespace XrdCl * TODO: Maybe this method could be collapsed * to avoid this middle-man call here */ - XrdOucUtils::splitString(result,input,delimiter); + XrdOucTUtils::splitString(result,input,delimiter); } //------------------------------------------------------------------------ diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 12f2c6fc062..ccd17a22781 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -54,7 +54,7 @@ #include #include #include -#include "XrdOuc/XrdOucUtils.hh" +#include "XrdOuc/XrdOucTUtils.hh" #include "XrdHttpUtils.hh" @@ -1061,9 +1061,9 @@ void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & sel if(configChecksumList != nullptr) { //The env variable is set, some checksums have been configured std::vector userDigestsVec; - XrdOucUtils::splitString(userDigestsVec,userDigest,","); + XrdOucTUtils::splitString(userDigestsVec,userDigest,","); std::vector configChecksums; - XrdOucUtils::splitString(configChecksums,configChecksumList,","); + XrdOucTUtils::splitString(configChecksums,configChecksumList,","); selectedChecksum = configChecksums[0]; auto configChecksumItor = configChecksums.end(); std::find_if(userDigestsVec.begin(), userDigestsVec.end(), [&configChecksums, &configChecksumItor](const std::string & userDigest){ @@ -1081,7 +1081,7 @@ void XrdHttpReq::selectChecksum(const std::string &userDigest, std::string & sel // If the user gave a checksum that do not exist, then the checksum returned will be the default one configChecksumItor = configChecksumItor != configChecksums.end() ? configChecksumItor : configChecksums.begin(); std::vector checksumIdName; - XrdOucUtils::splitString(checksumIdName,*configChecksumItor,":"); + XrdOucTUtils::splitString(checksumIdName,*configChecksumItor,":"); selectedChecksum = checksumIdName[1]; } } diff --git a/src/XrdOuc/XrdOucTUtils.hh b/src/XrdOuc/XrdOucTUtils.hh new file mode 100644 index 00000000000..d723a26c92f --- /dev/null +++ b/src/XrdOuc/XrdOucTUtils.hh @@ -0,0 +1,71 @@ +/******************************************************************************/ +/* */ +/* X r d O u c U t i l s . h h */ +/* */ +/* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University */ +/* All Rights Reserved */ +/* Produced by Andrew Hanushevsky for Stanford University under contract */ +/* DE-AC02-76-SFO0515 with the Department of Energy */ +/* */ +/* This file is part of the XRootD software suite. */ +/* */ +/* XRootD is free software: you can redistribute it and/or modify it under */ +/* the terms of the GNU Lesser General Public License as published by the */ +/* Free Software Foundation, either version 3 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* XRootD 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 Lesser General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ +/* COPYING (GPL license). If not, see . */ +/* */ +/* The copyright holder's institutional names and contributor's names may not */ +/* be used to endorse or promote products derived from this software without */ +/* specific prior written permission of the institution or contributor. */ +/******************************************************************************/ + +#ifndef XROOTD_XRDOUCTUTILS_HH +#define XROOTD_XRDOUCTUTILS_HH + +#include + +/** + * This class is created to contain template code + * for utility reason. Its purpose is basically the same as the XrdOucUtils, + * but it will only contain templated code + */ +class XrdOucTUtils { + +public: + +//------------------------------------------------------------------------ +//! Split a string +//------------------------------------------------------------------------ +template +static void splitString( Container &result, const std::string &input, const std::string &delimiter ) { + size_t start = 0; + size_t end = 0; + size_t length = 0; + + do { + end = input.find(delimiter, start); + + if (end != std::string::npos) + length = end - start; + else + length = input.length() - start; + + if (length) + result.push_back(input.substr(start, length)); + + start = end + delimiter.size(); + } while (end != std::string::npos); +} + +}; + +#endif //XROOTD_XRDOUCTUTILS_HH diff --git a/src/XrdOuc/XrdOucUtils.cc b/src/XrdOuc/XrdOucUtils.cc index 73df31b1879..c3b7e7f1b72 100644 --- a/src/XrdOuc/XrdOucUtils.cc +++ b/src/XrdOuc/XrdOucUtils.cc @@ -1400,33 +1400,5 @@ int XrdOucUtils::getModificationTime(const char *path, time_t &modificationTime) return statRet; } -template -void XrdOucUtils::splitString(Container &result, const std::string &input, const std::string &delimiter) { - { - size_t start = 0; - size_t end = 0; - size_t length = 0; - - do - { - end = input.find( delimiter, start ); - - if( end != std::string::npos ) - length = end - start; - else - length = input.length() - start; - - if( length ) - result.push_back( input.substr( start, length ) ); - - start = end + delimiter.size(); - } - while( end != std::string::npos ); - } -} - -template void XrdOucUtils::splitString>(std::vector &result, const std::string &input, const std::string &delimiter); -template void XrdOucUtils::splitString>(std::list &result, const std::string &input, const std::string &delimiter); - #endif diff --git a/src/XrdOuc/XrdOucUtils.hh b/src/XrdOuc/XrdOucUtils.hh index d609f7f3dcd..96c1a3a1408 100644 --- a/src/XrdOuc/XrdOucUtils.hh +++ b/src/XrdOuc/XrdOucUtils.hh @@ -131,12 +131,6 @@ static bool PidFile(XrdSysError &eDest, const char *path); static int getModificationTime(const char * path, time_t & modificationTime); -//------------------------------------------------------------------------ -//! Split a string -//------------------------------------------------------------------------ -template -static void splitString( Container &result, const std::string &input, const std::string &delimiter ); - XrdOucUtils() {} ~XrdOucUtils() {} };