39 # define EADDRINUSE 10048
42 # define EISCONN 10056
46 static const char *gUserAgent =
"User-Agent: ROOT-TWebFile/1.1";
48 TUrl TWebFile::fgProxy;
50 Long64_t TWebFile::fgMaxFullCacheSize = 500000000;
59 TWebSocket(TWebFile *f);
67 TWebSocket::TWebSocket(TWebFile *f)
77 TWebSocket::~TWebSocket()
79 if (!fWebFile->fHTTP11) {
80 delete fWebFile->fSocket;
81 fWebFile->fSocket = 0;
88 void TWebSocket::ReOpen()
90 if (fWebFile->fSocket) {
91 delete fWebFile->fSocket;
92 fWebFile->fSocket = 0;
96 if (fWebFile->fProxy.IsValid())
97 connurl = fWebFile->fProxy;
99 connurl = fWebFile->fUrl;
101 for (Int_t i = 0; i < 5; i++) {
102 if (strcmp(connurl.GetProtocol(),
"https") == 0) {
104 fWebFile->fSocket =
new TSSLSocket(connurl.GetHost(), connurl.GetPort());
106 ::Error(
"TWebSocket::ReOpen",
"library compiled without SSL, https not supported");
110 fWebFile->fSocket =
new TSocket(connurl.GetHost(), connurl.GetPort());
112 if (!fWebFile->fSocket || !fWebFile->fSocket->IsValid()) {
113 delete fWebFile->fSocket;
114 fWebFile->fSocket = 0;
115 if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
116 gSystem->Sleep(i*10);
118 ::Error(
"TWebSocket::ReOpen",
"cannot connect to host %s (errno=%d)",
119 fWebFile->fUrl.GetHost(), gSystem->GetErrno());
146 TWebFile::TWebFile(
const char *url, Option_t *opt) : TFile(url,
"WEB"), fSocket(0)
148 TString option = opt;
150 if (option.Contains(
"NOPROXY", TString::kIgnoreCase))
154 Bool_t headOnly = kFALSE;
155 if (option.Contains(
"HEADONLY", TString::kIgnoreCase))
179 TWebFile::TWebFile(TUrl url, Option_t *opt) : TFile(url.GetUrl(),
"WEB"), fSocket(0)
181 TString option = opt;
183 if (option.Contains(
"NOPROXY", TString::kIgnoreCase))
187 Bool_t headOnly = kFALSE;
188 if (option.Contains(
"HEADONLY", TString::kIgnoreCase))
197 TWebFile::~TWebFile()
210 void TWebFile::Init(Bool_t readHeadOnly)
217 fHasModRoot = kFALSE;
221 SetMsgReadBuffer10();
223 if ((err = GetHead()) < 0) {
230 Error(
"TWebFile",
"%s does not exist", fBasicUrl.Data());
244 if (ReadBuffer(buf, 4)) {
250 if (strncmp(buf,
"root", 4) && strncmp(buf,
"PK", 2)) {
251 Error(
"TWebFile",
"%s is not a ROOT file", fBasicUrl.Data());
266 void TWebFile::SetMsgReadBuffer10(
const char *redirectLocation, Bool_t tempRedirect)
271 if (redirectLocation) {
274 fBasicUrlOrg = fBasicUrl;
281 oldBasicUrl = fBasicUrl;
283 fUrl.SetUrl(redirectLocation);
284 fBasicUrl = fUrl.GetProtocol();
286 fBasicUrl += fUrl.GetHost();
288 fBasicUrl += fUrl.GetPort();
290 fBasicUrl += fUrl.GetFile();
292 TString rdl(redirectLocation);
293 if (rdl.Index(
"?") >= 0) {
294 rdl = rdl(rdl.Index(
"?"), rdl.Length());
299 if (fMsgReadBuffer10 !=
"") {
301 if (oldBasicUrl !=
"") {
303 fMsgReadBuffer10.ReplaceAll(oldBasicUrl, fBasicUrl);
304 fMsgReadBuffer10.ReplaceAll(TString(
"Host: ")+oldUrl.GetHost(), TString(
"Host: ")+fUrl.GetHost());
305 }
else if (fBasicUrlOrg !=
"") {
307 fMsgReadBuffer10.ReplaceAll(fBasicUrl, fBasicUrlOrg);
308 fMsgReadBuffer10.ReplaceAll(TString(
"Host: ")+fUrl.GetHost(), TString(
"Host: ")+fUrlOrg.GetHost());
310 fBasicUrl = fBasicUrlOrg;
316 if (fBasicUrl ==
"") {
317 fBasicUrl += fUrl.GetProtocol();
319 fBasicUrl += fUrl.GetHost();
321 fBasicUrl += fUrl.GetPort();
323 fBasicUrl += fUrl.GetFile();
325 fBasicUrl += fUrl.GetOptions();
328 if (fMsgReadBuffer10 ==
"") {
329 fMsgReadBuffer10 =
"GET ";
330 fMsgReadBuffer10 += fBasicUrl;
332 fMsgReadBuffer10 +=
" HTTP/1.1";
334 fMsgReadBuffer10 +=
" HTTP/1.0";
335 fMsgReadBuffer10 +=
"\r\n";
337 fMsgReadBuffer10 +=
"Host: ";
338 fMsgReadBuffer10 += fUrl.GetHost();
339 fMsgReadBuffer10 +=
"\r\n";
341 fMsgReadBuffer10 += BasicAuthentication();
342 fMsgReadBuffer10 += gUserAgent;
343 fMsgReadBuffer10 +=
"\r\n";
344 fMsgReadBuffer10 +=
"Range: bytes=";
351 void TWebFile::CheckProxy()
356 if (fgProxy.IsValid()) {
361 TString proxy = gSystem->Getenv(
"http_proxy");
364 if (strcmp(p.GetProtocol(),
"http")) {
365 Error(
"CheckProxy",
"protocol must be HTTP in proxy URL %s",
371 Info(
"CheckProxy",
"using HTTP proxy %s", fProxy.GetUrl());
378 Bool_t TWebFile::IsOpen()
const
380 return IsZombie() ? kFALSE : kTRUE;
392 Int_t TWebFile::ReOpen(Option_t *mode)
397 if (opt !=
"READ" && opt !=
"UPDATE")
398 Error(
"ReOpen",
"mode must be either READ or UPDATE, not %s", opt.Data());
401 Error(
"ReOpen",
"update mode not allowed for a TWebFile");
411 Bool_t TWebFile::ReadBuffer(
char *buf, Int_t len)
414 if ((st = ReadBufferViaCache(buf, len))) {
421 return ReadBuffer10(buf, len);
425 if (fMsgReadBuffer ==
"") {
426 fMsgReadBuffer =
"GET ";
427 fMsgReadBuffer += fBasicUrl;
428 fMsgReadBuffer +=
"?";
430 TString msg = fMsgReadBuffer;
436 if (GetFromWeb(buf, len, msg) == -1)
449 Bool_t TWebFile::ReadBuffer(
char *buf, Long64_t pos, Int_t len)
452 return ReadBuffer(buf, len);
460 Bool_t TWebFile::ReadBuffer10(
char *buf, Int_t len)
462 SetMsgReadBuffer10();
464 TString msg = fMsgReadBuffer10;
467 msg += fOffset+len-1;
470 Long64_t apos = fOffset - fArchiveOffset;
473 Int_t n = GetFromWeb10(buf, len, msg, 1, &apos, &len);
480 Error(
"ReadBuffer10",
"%s does not exist", fBasicUrl.Data());
499 Bool_t TWebFile::ReadBuffers(
char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
502 return ReadBuffers10(buf, pos, len, nbuf);
506 if (fMsgReadBuffer ==
"") {
507 fMsgReadBuffer =
"GET ";
508 fMsgReadBuffer += fBasicUrl;
509 fMsgReadBuffer +=
"?";
511 TString msg = fMsgReadBuffer;
513 Int_t k = 0, n = 0, cnt = 0;
514 for (Int_t i = 0; i < nbuf; i++) {
516 msg += pos[i] + fArchiveOffset;
521 if ((msg.Length() > 8000) || (cnt >= 200)) {
523 if (GetFromWeb(&buf[k], n, msg) == -1)
525 msg = fMsgReadBuffer;
534 if (GetFromWeb(&buf[k], n, msg) == -1)
548 Bool_t TWebFile::ReadBuffers10(
char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
550 SetMsgReadBuffer10();
552 TString msg = fMsgReadBuffer10;
554 Int_t k = 0, n = 0, r, cnt = 0;
555 for (Int_t i = 0; i < nbuf; i++) {
557 msg += pos[i] + fArchiveOffset;
559 msg += pos[i] + fArchiveOffset + len[i] - 1;
562 if ((msg.Length() > 8000) || (cnt >= 200) || (i+1 == nbuf)) {
564 r = GetFromWeb10(&buf[k], n, msg, cnt, pos + (i+1-cnt), len + (i+1-cnt));
567 msg = fMsgReadBuffer10;
582 Int_t TWebFile::GetFromCache(
char *buf, Int_t len, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
584 if (!fFullCache)
return -1;
587 Info(
"GetFromCache",
"Extract %d segments total len %d from cached data", nseg, len);
590 for (Int_t cnt=0;cnt<nseg;cnt++) {
592 if (curr + seg_len[cnt] > len)
return -1;
594 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fFullCacheSize)
return -1;
595 char* src = (
char*) fFullCache + fArchiveOffset + seg_pos[cnt];
596 memcpy(buf + curr, src, seg_len[cnt]);
597 curr += seg_len[cnt];
607 Int_t TWebFile::GetFromWeb(
char *buf, Int_t len,
const TString &msg)
614 if (gPerfStats) start = TTimeStamp();
617 if (fProxy.IsValid())
622 if (strcmp(connurl.GetProtocol(),
"https") == 0) {
624 s =
new TSSLSocket(connurl.GetHost(), connurl.GetPort());
626 Error(
"GetFromWeb",
"library compiled without SSL, https not supported");
630 s =
new TSocket(connurl.GetHost(), connurl.GetPort());
633 Error(
"GetFromWeb",
"cannot connect to host %s", fUrl.GetHost());
638 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
639 Error(
"GetFromWeb",
"error sending command to host %s", fUrl.GetHost());
644 if (s->RecvRaw(buf, len) == -1) {
645 Error(
"GetFromWeb",
"error receiving data from host %s", fUrl.GetHost());
654 SetFileBytesRead(GetFileBytesRead() + len);
655 SetFileReadCalls(GetFileReadCalls() + 1);
662 gPerfStats->FileReadEvent(
this, len, start);
674 Int_t TWebFile::GetFromWeb10(
char *buf, Int_t len,
const TString &msg, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
679 if (fFullCache && (nseg>0))
680 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
683 if (gPerfStats) start = TTimeStamp();
688 if (!fSocket || !fSocket->IsValid()) {
689 Error(
"GetFromWeb10",
"cannot connect to host %s", fUrl.GetHost());
694 Info(
"GetFromWeb10",
"sending HTTP request:\n%s", msg.Data());
696 if (fSocket->SendRaw(msg.Data(), msg.Length()) == -1) {
697 Error(
"GetFromWeb10",
"error sending command to host %s", fUrl.GetHost());
702 Int_t n, ret = 0, nranges = 0, ltot = 0, redirect = 0;
703 TString boundary, boundaryEnd;
704 Long64_t first = -1, last = -1, tot, fullsize = 0;
707 while ((n = GetLine(fSocket, line,
sizeof(line))) >= 0) {
712 if (redir.IsNull()) {
714 Error(
"GetFromWeb10",
"error - redirect without location from host %s", fUrl.GetHost());
720 TString msg_1 = fMsgReadBuffer10;
723 msg_1 += fOffset+len-1;
725 return GetFromWeb10(buf, len, msg_1);
729 Int_t ll = Int_t(last - first) + 1;
731 if ((rsize = fSocket->RecvRaw(&buf[ltot], ll)) == -1) {
732 Error(
"GetFromWeb10",
"error receiving data from host %s", fUrl.GetHost());
735 else if (ll != rsize) {
736 Error(
"GetFromWeb10",
"expected %d bytes, got %d", ll, rsize);
750 Error(
"GetFromWeb10",
"Need segments data to extract parts from full size %lld", fullsize);
754 if (len > fullsize) {
755 Error(
"GetFromWeb10",
"Requested part %d longer than full size %lld", len, fullsize);
759 if ((fFullCache == 0) && (fullsize <= GetMaxFullCacheSize())) {
761 fFullCache = malloc(fullsize);
762 if (fFullCache != 0) {
763 if (fSocket->RecvRaw(fFullCache, fullsize) != fullsize) {
764 Error(
"GetFromWeb10",
"error receiving data from host %s", fUrl.GetHost());
765 free(fFullCache); fFullCache = 0;
768 fFullCacheSize = fullsize;
769 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
775 for (Int_t cnt=0;cnt<nseg;cnt++) {
776 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fullsize) {
777 Error(
"GetFromWeb10",
"Requested segment %lld len %d is outside of full range %lld", seg_pos[cnt], seg_len[cnt], fullsize);
780 if ((cnt>0) && (seg_pos[cnt-1] + seg_len[cnt-1] > seg_pos[cnt])) {
781 Error(
"GetFromWeb10",
"Requested segments are not in sorted order");
791 for (Int_t cnt=0; cnt<nseg; cnt++) {
793 while (pos < fArchiveOffset + seg_pos[cnt]) {
794 Long64_t ll = fArchiveOffset + seg_pos[cnt] - pos;
795 if (ll > Int_t(
sizeof(dbuf))) ll =
sizeof(dbuf);
796 if (fSocket->RecvRaw(dbuf, ll) != ll) {
797 Error(
"GetFromWeb10",
"error receiving data from host %s", fUrl.GetHost());
804 if (fSocket->RecvRaw(curr, seg_len[cnt]) != seg_len[cnt]) {
805 Error(
"GetFromWeb10",
"error receiving data from host %s", fUrl.GetHost());
808 curr += seg_len[cnt];
810 ltot += seg_len[cnt];
814 while (pos < fullsize) {
815 Long64_t ll = fullsize - pos;
816 if (ll > Int_t(
sizeof(dbuf))) ll =
sizeof(dbuf);
817 if (fSocket->RecvRaw(dbuf, ll) != ll) {
818 Error(
"GetFromWeb10",
"error receiving data from host %s", fUrl.GetHost());
824 if (gDebug>0) Info(
"GetFromWeb10",
"Complete reading %d bytes in %d segments out of full size %lld", len, nseg, fullsize);
833 Info(
"GetFromWeb10",
"header: %s", line);
835 if (boundaryEnd == line) {
837 Info(
"GetFromWeb10",
"got all headers");
840 if (boundary == line) {
843 Info(
"GetFromWeb10",
"get new multipart byte range (%d)", nranges);
848 if (res.BeginsWith(
"HTTP/1.")) {
849 if (res.BeginsWith(
"HTTP/1.1")) {
851 fMsgReadBuffer10 =
"";
854 TString scode = res(9, 3);
855 Int_t code = scode.Atoi();
858 TString mess = res(13, 1000);
859 Error(
"GetFromWeb10",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
860 }
else if (code >= 400) {
865 TString mess = res(13, 1000);
866 Error(
"GetFromWeb10",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
868 }
else if (code >= 300) {
869 if (code == 301 || code == 303) {
871 }
else if (code == 302 || code == 307) {
877 TString mess = res(13, 1000);
878 Error(
"GetFromWeb10",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
880 }
else if (code > 200) {
883 TString mess = res(13, 1000);
884 Error(
"GetFromWeb10",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
886 }
else if (code == 200) {
888 Warning(
"GetFromWeb10",
889 "Server %s response with complete file, but only part of it was requested.\n"
890 "Check MaxRanges configuration parameter (if Apache is used)",
894 }
else if (res.BeginsWith(
"Content-Type: multipart")) {
895 boundary = res(res.Index(
"boundary=")+9, 1000);
896 if (boundary[0]==
'"' && boundary[boundary.Length()-1]==
'"') {
897 boundary = boundary(1,boundary.Length()-2);
899 boundary =
"--" + boundary;
900 boundaryEnd = boundary +
"--";
901 }
else if (res.BeginsWith(
"Content-range:")) {
903 sscanf(res.Data(),
"Content-range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
905 sscanf(res.Data(),
"Content-range: bytes %lld-%lld/%lld", &first, &last, &tot);
907 if (fSize == -1) fSize = tot;
908 }
else if (res.BeginsWith(
"Content-Range:")) {
910 sscanf(res.Data(),
"Content-Range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
912 sscanf(res.Data(),
"Content-Range: bytes %lld-%lld/%lld", &first, &last, &tot);
914 if (fSize == -1) fSize = tot;
915 }
else if (res.BeginsWith(
"Content-Length:") && (fullsize == -200)) {
917 sscanf(res.Data(),
"Content-Length: %I64d", &fullsize);
919 sscanf(res.Data(),
"Content-Length: %lld", &fullsize);
921 }
else if (res.BeginsWith(
"Location:") && redirect) {
922 redir = res(10, 1000);
924 SetMsgReadBuffer10(redir, kTRUE);
926 SetMsgReadBuffer10(redir, kFALSE);
930 if (redirect && redir.IsNull()) {
932 Error(
"GetFromWeb10",
"error - redirect without location from host %s", fUrl.GetHost());
935 if (n == -1 && fHTTP11) {
937 Info(
"GetFromWeb10",
"HTTP/1.1 socket closed, reopen");
938 if (fBasicUrlOrg !=
"") {
940 SetMsgReadBuffer10();
943 return GetFromWeb10(buf, len, msg);
947 Error(
"GetFromWeb10",
"error receiving expected amount of data (got %d, expected %d) from host %s",
948 ltot, len, fUrl.GetHost());
956 SetFileBytesRead(GetFileBytesRead() + len);
957 SetFileReadCalls(GetFileReadCalls() + 1);
964 gPerfStats->FileReadEvent(
this, len, start);
972 void TWebFile::Seek(Long64_t offset, ERelativeTo pos)
976 fOffset = offset + fArchiveOffset;
984 Error(
"Seek",
"seeking from end in archive is not (yet) supported");
985 fOffset = fEND - offset;
993 Long64_t TWebFile::GetSize()
const
995 if (!fHasModRoot || fSize >= 0)
1001 TString msg =
"GET ";
1007 if (const_cast<TWebFile*>(
this)->GetFromWeb(asize, 64, msg) == -1)
1011 size = atoll(asize);
1013 size = _atoi64(asize);
1028 Int_t TWebFile::GetHead()
1031 if (fMsgGetHead ==
"") {
1032 fMsgGetHead =
"HEAD ";
1033 fMsgGetHead += fBasicUrl;
1035 fMsgGetHead +=
" HTTP/1.1";
1037 fMsgGetHead +=
" HTTP/1.0";
1038 fMsgGetHead +=
"\r\n";
1040 fMsgGetHead +=
"Host: ";
1041 fMsgGetHead += fUrl.GetHost();
1042 fMsgGetHead +=
"\r\n";
1044 fMsgGetHead += BasicAuthentication();
1045 fMsgGetHead += gUserAgent;
1046 fMsgGetHead +=
"\r\n\r\n";
1048 TString msg = fMsgGetHead;
1051 if (fProxy.IsValid())
1057 for (Int_t i = 0; i < 5; i++) {
1058 if (strcmp(connurl.GetProtocol(),
"https") == 0) {
1060 s =
new TSSLSocket(connurl.GetHost(), connurl.GetPort());
1062 Error(
"GetHead",
"library compiled without SSL, https not supported");
1066 s =
new TSocket(connurl.GetHost(), connurl.GetPort());
1068 if (!s->IsValid()) {
1070 if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
1072 gSystem->Sleep(i*10);
1074 Error(
"GetHead",
"cannot connect to host %s (errno=%d)", fUrl.GetHost(),
1075 gSystem->GetErrno());
1085 Info(
"GetHead",
"connected to host %s", connurl.GetHost());
1086 Info(
"GetHead",
"sending HTTP request:\n%s", msg.Data());
1089 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
1090 Error(
"GetHead",
"error sending command to host %s", fUrl.GetHost());
1096 Int_t n, ret = 0, redirect = 0;
1099 while ((n = GetLine(s, line,
sizeof(line))) >= 0) {
1102 Info(
"GetHead",
"got all headers");
1104 if (fBasicUrlOrg !=
"" && !redirect) {
1106 SetMsgReadBuffer10();
1112 if (redir.IsNull()) {
1114 Error(
"GetHead",
"error - redirect without location from host %s", fUrl.GetHost());
1123 Info(
"GetHead",
"header: %s", line);
1126 ProcessHttpHeader(res);
1127 if (res.BeginsWith(
"HTTP/1.")) {
1128 if (res.BeginsWith(
"HTTP/1.1")) {
1131 fMsgReadBuffer10 =
"";
1135 TString scode = res(9, 3);
1136 Int_t code = scode.Atoi();
1139 fHasModRoot = kTRUE;
1142 TString mess = res(13, 1000);
1143 Error(
"GetHead",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1145 }
else if (code >= 400) {
1148 else if (code == 404)
1152 TString mess = res(13, 1000);
1153 Error(
"GetHead",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1155 }
else if (code >= 300) {
1156 if (code == 301 || code == 303)
1158 else if (code == 302 || code == 307)
1162 TString mess = res(13, 1000);
1163 Error(
"GetHead",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1165 }
else if (code > 200) {
1167 TString mess = res(13, 1000);
1168 Error(
"GetHead",
"%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1170 }
else if (res.BeginsWith(
"Content-Length:")) {
1171 TString slen = res(16, 1000);
1172 fSize = slen.Atoll();
1173 }
else if (res.BeginsWith(
"Location:") && redirect) {
1174 redir = res(10, 1000);
1176 SetMsgReadBuffer10(redir, kTRUE);
1178 SetMsgReadBuffer10(redir, kFALSE);
1195 Int_t TWebFile::GetLine(TSocket *s,
char *line, Int_t maxsize)
1197 Int_t n = GetHunk(s, line, maxsize);
1199 if (!fHTTP11 || gDebug > 0)
1200 Error(
"GetLine",
"error receiving data from host %s", fUrl.GetHost());
1204 if (n > 0 && line[n-1] ==
'\n') {
1206 if (n > 0 && line[n-1] ==
'\r')
1258 Int_t TWebFile::GetHunk(TSocket *s,
char *hunk, Int_t maxsize)
1260 if (maxsize <= 0)
return 0;
1262 Int_t bufsize = maxsize;
1267 Int_t pklen, rdlen, remain;
1270 pklen = s->RecvRaw(hunk+tail, bufsize-1-tail, kPeek);
1274 end = HttpTerminator(hunk, hunk+tail, pklen);
1278 remain = end - (hunk + tail);
1284 if (bufsize - 1 < tail + remain) {
1285 Error(
"GetHunk",
"hunk buffer too small for data from host %s (%d bytes needed)",
1286 fUrl.GetHost(), tail + remain + 1);
1299 rdlen = s->RecvRaw(hunk+tail, remain, kDontBlock);
1310 if (end && rdlen == remain) {
1318 if (tail == bufsize - 1) {
1319 Error(
"GetHunk",
"hunk buffer too small for data from host %s",
1333 const char *TWebFile::HttpTerminator(
const char *start,
const char *peeked,
1337 const char *p, *end;
1342 p = peeked - start < 1 ? start : peeked - 1;
1343 end = peeked + peeklen;
1346 for (; p < end - 1; p++)
1347 if (p[0] ==
'\r' && p[1] ==
'\n')
1351 if (p[0] ==
'\r' && p[1] ==
'\n')
1355 const char *p = (
const char*) memchr(peeked,
'\n', peeklen);
1366 TString TWebFile::BasicAuthentication()
1369 if (strlen(fUrl.GetUser())) {
1370 TString auth = fUrl.GetUser();
1371 if (strlen(fUrl.GetPasswd())) {
1373 auth += fUrl.GetPasswd();
1375 msg +=
"Authorization: Basic ";
1376 msg += TBase64::Encode(auth);
1385 void TWebFile::SetProxy(
const char *proxy)
1387 if (proxy && *proxy) {
1389 if (strcmp(p.GetProtocol(),
"http")) {
1390 :: Error(
"TWebFile::SetProxy",
"protocol must be HTTP in proxy URL %s",
1401 const char *TWebFile::GetProxy()
1403 if (fgProxy.IsValid())
1404 return fgProxy.GetUrl();
1413 void TWebFile::ProcessHttpHeader(
const TString&)
1421 Long64_t TWebFile::GetMaxFullCacheSize()
1423 return fgMaxFullCacheSize;
1430 void TWebFile::SetMaxFullCacheSize(Long64_t sz)
1432 fgMaxFullCacheSize = sz;
1440 TWebSystem::TWebSystem() : TSystem(
"-http",
"HTTP Helper System")
1450 Int_t TWebSystem::MakeDirectory(
const char *)
1459 void *TWebSystem::OpenDirectory(
const char *)
1462 Error(
"OpenDirectory",
"invalid directory pointer (should never happen)");
1474 void TWebSystem::FreeDirectory(
void *dirp)
1476 if (dirp != fDirp) {
1477 Error(
"FreeDirectory",
"invalid directory pointer (should never happen)");
1487 const char *TWebSystem::GetDirEntry(
void *dirp)
1489 if (dirp != fDirp) {
1490 Error(
"GetDirEntry",
"invalid directory pointer (should never happen)");
1503 Int_t TWebSystem::GetPathInfo(
const char *path, FileStat_t &buf)
1505 TWebFile *f =
new TWebFile(path,
"HEADONLY");
1507 if (f->fWritten == 0) {
1514 buf.fSize = f->GetSize();
1516 buf.fIsLink = kFALSE;
1531 Bool_t TWebSystem::AccessPathName(
const char *path, EAccessMode)
1533 TWebFile *f =
new TWebFile(path,
"HEADONLY");
1534 if (f->fWritten == 0) {
1546 Int_t TWebSystem::Unlink(
const char *)