38 auto verbs = instance.Get(target.empty() ?
m_url : target);
40 curl_easy_setopt(
m_curl.get(), CURLOPT_CUSTOMREQUEST,
"PROPFIND");
42 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 0L);
45 m_is_propfind =
false;
46 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 1L);
59 auto verbs = instance.Get(target);
66 curl_easy_setopt(
m_curl.get(), CURLOPT_CUSTOMREQUEST,
"PROPFIND");
68 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 0L);
71 m_is_propfind =
false;
72 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 1L);
81 curl_easy_setopt(
m_curl.get(), CURLOPT_WRITEFUNCTION, CurlStatOp::WriteCallback);
82 curl_easy_setopt(
m_curl.get(), CURLOPT_WRITEDATA,
this);
85 auto verbs = instance.Get(
m_url);
87 curl_easy_setopt(
m_curl.get(), CURLOPT_CUSTOMREQUEST,
"PROPFIND");
89 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 0L);
92 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 1L);
100 if (
m_curl ==
nullptr)
return;
101 curl_easy_setopt(
m_curl.get(), CURLOPT_NOBODY, 0L);
103 curl_easy_setopt(
m_curl.get(), CURLOPT_CUSTOMREQUEST,
nullptr);
105 curl_easy_setopt(
m_curl.get(), CURLOPT_WRITEFUNCTION,
nullptr);
106 curl_easy_setopt(
m_curl.get(), CURLOPT_WRITEDATA,
nullptr);
111CurlStatOp::WriteCallback(
char *buffer,
size_t size,
size_t nitems,
void *this_ptr)
114 if (me->m_is_propfind) {
115 if (size * nitems + me->m_response.size() > 1'000'000) {
116 me->m_logger->Error(
kLogXrdClHttp,
"Response too large for PROPFIND operation");
119 me->UpdateBytes(size * nitems);
120 me->m_response.append(buffer, size * nitems);
122 return size * nitems;
125std::pair<int64_t, bool>
126CurlStatOp::ParseProp(TiXmlElement *prop) {
127 if (prop ==
nullptr) {
130 for (
auto child = prop->FirstChildElement();
child !=
nullptr;
child =
child->NextSiblingElement()) {
131 if (!strcasecmp(
child->Value(),
"D:getcontentlength") || !strcasecmp(
child->Value(),
"lp1:getcontentlength")) {
132 auto len =
child->GetText();
134 m_length = std::stoll(len);
136 }
else if (!strcasecmp(
child->Value(),
"D:resourcetype") || !strcasecmp(
child->Value(),
"lp1:resourcetype")) {
137 m_is_dir =
child->FirstChildElement(
"D:collection") !=
nullptr;
140 if (m_length < 0 && m_is_dir) {
144 return {m_length, m_is_dir};
147std::pair<int64_t, bool>
149 if (!m_is_propfind) {
151 return {m_length,
false};
154 return {m_length, m_is_dir};
158 doc.Parse(m_response.c_str());
160 m_logger->Error(
kLogXrdClHttp,
"Failed to parse XML response: %s", m_response.substr(0, 1024).c_str());
164 auto elem = doc.RootElement();
165 if (strcasecmp(elem->Value(),
"D:multistatus")) {
169 auto found_response =
false;
170 for (
auto response = elem->FirstChildElement(); response !=
nullptr; response = response->NextSiblingElement()) {
171 if (!strcasecmp(response->Value(),
"D:response")) {
172 found_response =
true;
177 if (!found_response) {
178 m_logger->Error(
kLogXrdClHttp,
"Failed to find response element in XML response: %s", m_response.substr(0, 1024).c_str());
181 for (
auto child = elem->FirstChildElement();
child !=
nullptr;
child =
child->NextSiblingElement()) {
182 if (strcasecmp(
child->Value(),
"D:propstat")) {
185 for (
auto prop =
child->FirstChildElement(); prop !=
nullptr; prop = prop->NextSiblingElement()) {
186 if (!strcasecmp(prop->Value(),
"D:prop")) {
187 return ParseProp(prop);
191 m_logger->Error(
kLogXrdClHttp,
"Failed to find properties in XML response: %s", m_response.substr(0, 1024).c_str());
198 auto verbs = instance.Get(
m_url);
222 m_logger->Debug(
kLogXrdClHttp,
"Successful propfind operation on %s (size %lld, isdir %d)",
m_url.c_str(),
static_cast<long long>(size), isdir);
228 if (m_response_info){
239 }
else if (m_response_info) {
void SetDone(bool has_failed)
std::unique_ptr< ResponseInfo > MoveResponseInfo()
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
virtual void ReleaseHandle()
std::vector< std::pair< std::string, std::string > > m_headers_list
virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &)
virtual RedirectAction Redirect(std::string &target)
XrdCl::ResponseHandler * m_handler
virtual bool Setup(CURL *curl, CurlWorker &)
void ReleaseHandle() override
void SuccessImpl(bool returnObj)
virtual bool RequiresOptions() const override
bool Setup(CURL *curl, CurlWorker &) override
RedirectAction Redirect(std::string &target) override
std::pair< int64_t, bool > GetStatInfo()
virtual void OptionsDone() override
static VerbsCache & Instance()
void Set(Type object, bool own=true)
@ IsReadable
Read access is allowed.
@ IsDir
This is a directory.
const uint64_t kLogXrdClHttp
const uint16_t errErrorResponse