XRootD
Loading...
Searching...
No Matches
XrdHttpChecksumHandler.cc
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// This file is part of XrdHTTP: A pragmatic implementation of the
3// HTTP/WebDAV protocol for the Xrootd framework
4//
5// Copyright (c) 2013 by European Organization for Nuclear Research (CERN)
6// Author: Cedric Caffy <ccaffy@cern.ch>
7// File Date: Mar 2023
8//------------------------------------------------------------------------------
9// XRootD is free software: you can redistribute it and/or modify
10// it under the terms of the GNU Lesser General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13//
14// XRootD is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public License
20// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
21//------------------------------------------------------------------------------
22
25#include "XrdOuc/XrdOucUtils.hh"
26#include <exception>
27#include <algorithm>
28
29std::map<std::string,XrdHttpChecksumHandlerImpl::XrdHttpChecksumPtr> XrdHttpChecksumHandlerImpl::XROOTD_DIGEST_NAME_TO_CKSUMS;
30
31void XrdHttpChecksumHandlerImpl::initializeCksumsMaps() {
32 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("md5","md5",true));
33 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("adler32","adler32",false));
34 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("sha1","sha",true));
35 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("sha256","sha-256",true));
36 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("sha512","sha-512",true));
37 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("cksum","UNIXcksum",false));
38 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("crc32","crc32",false));
39 addChecksumToMaps(std::make_unique<XrdHttpChecksum>("crc32c","crc32c",true));
40}
41
42void XrdHttpChecksumHandlerImpl::addChecksumToMaps(XrdHttpChecksumHandlerImpl::XrdHttpChecksumPtr && checksum) {
43 // We also map xrootd-configured checksum's HTTP names to the corresponding checksums --> this will allow
44 // users to configure algorithms like, for example, `sha-512` and be considered as `sha512` algorithm
45 XROOTD_DIGEST_NAME_TO_CKSUMS[checksum->getHttpNameLowerCase()] = std::make_unique<XrdHttpChecksum>(checksum->getHttpNameLowerCase(), checksum->getHttpName(), checksum->needsBase64Padding());
46 XROOTD_DIGEST_NAME_TO_CKSUMS[checksum->getXRootDConfigDigestName()] = std::move(checksum);
47}
48
50 if(!mConfiguredChecksums.empty()) {
51 std::vector<std::string> userDigests = getUserDigests(userDigestIn);
52 //Loop over the user digests and find the corresponding checksum
53 for(auto userDigest: userDigests) {
54 auto httpCksum = std::find_if(mConfiguredChecksums.begin(), mConfiguredChecksums.end(),[userDigest](const XrdHttpChecksumRawPtr & cksum){
55 return userDigest == cksum->getHttpNameLowerCase();
56 });
57 if(httpCksum != mConfiguredChecksums.end()) {
58 return *httpCksum;
59 }
60 }
61 return mConfiguredChecksums[0];
62 }
63 //If there are no configured checksums, return nullptr
64 return nullptr;
65}
66
67const std::vector<std::string> &XrdHttpChecksumHandlerImpl::getNonIANAConfiguredCksums() const {
68 return mNonIANAConfiguredChecksums;
69}
70
71const std::vector<XrdHttpChecksumHandler::XrdHttpChecksumRawPtr> & XrdHttpChecksumHandlerImpl::getConfiguredChecksums() const {
72 return mConfiguredChecksums;
73}
74
75
76void XrdHttpChecksumHandlerImpl::configure(const char *csList) {
77 initializeCksumsMaps();
78 if(csList != nullptr) {
79 initializeXRootDConfiguredCksums(csList);
80 }
81}
82
83void XrdHttpChecksumHandlerImpl::initializeXRootDConfiguredCksums(const char *csList) {
84 std::vector<std::string> splittedCslist;
85 XrdOucTUtils::splitString(splittedCslist,csList,",");
86 for(auto csElt: splittedCslist) {
87 auto csName = getElement(csElt,":",1);
88 auto checksumItor = XROOTD_DIGEST_NAME_TO_CKSUMS.find(csName);
89 if(checksumItor != XROOTD_DIGEST_NAME_TO_CKSUMS.end()) {
90 mConfiguredChecksums.push_back(checksumItor->second.get());
91 } else {
92 mNonIANAConfiguredChecksums.push_back(csName);
93 }
94 }
95}
96
97std::string XrdHttpChecksumHandlerImpl::getElement(const std::string &input, const std::string & delimiter,
98 const size_t position) {
99 std::vector<std::string> elementsAfterSplit;
100 XrdOucTUtils::splitString(elementsAfterSplit,input,delimiter);
101 return elementsAfterSplit[position];
102}
103
104std::vector<std::string> XrdHttpChecksumHandlerImpl::getUserDigests(const std::string &userDigests) {
105 //userDigest is a comma-separated list with q-values
106 std::vector<std::string> userDigestsRet;
107 std::vector<std::string> userDigestsWithQValues;
108 XrdOucTUtils::splitString(userDigestsWithQValues,userDigests,",");
109 for(auto & userDigestWithQValue: userDigestsWithQValues){
110 std::transform(userDigestWithQValue.begin(),userDigestWithQValue.end(),userDigestWithQValue.begin(),::tolower);
111 auto userDigest = getElement(userDigestWithQValue,";",0);
112 XrdOucUtils::trim(userDigest);
113 userDigestsRet.push_back(userDigest);
114 }
115 return userDigestsRet;
116}
const std::vector< std::string > & getNonIANAConfiguredCksums() const
std::unique_ptr< XrdHttpChecksum > XrdHttpChecksumPtr
XrdHttpChecksumRawPtr getChecksumToRun(const std::string &userDigest) const
void configure(const char *csList)
const std::vector< XrdHttpChecksumRawPtr > & getConfiguredChecksums() const
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
static void trim(std::string &str)