Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TWebFile.cxx
Go to the documentation of this file.
1// @(#)root/net:$Id$
2// Author: Fons Rademakers 17/01/97
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TWebFile //
15// //
16// A TWebFile is like a normal TFile except that it reads its data //
17// via a standard apache web server. A TWebFile is a read-only file. //
18// //
19//////////////////////////////////////////////////////////////////////////
20
21#include "TWebFile.h"
22#include "TROOT.h"
23#include "TSocket.h"
24#include "Bytes.h"
25#include "TError.h"
26#include "TSystem.h"
27#include "TBase64.h"
28#include "TVirtualPerfStats.h"
29#ifdef R__SSL
30#include "TSSLSocket.h"
31#endif
32
33#include <errno.h>
34#include <stdlib.h>
35#include <string.h>
36
37#ifdef WIN32
38# ifndef EADDRINUSE
39# define EADDRINUSE 10048
40# endif
41# ifndef EISCONN
42# define EISCONN 10056
43# endif
44#endif
45
46static const char *gUserAgent = "User-Agent: ROOT-TWebFile/1.1";
47
49
51
52
53// Internal class used to manage the socket that may stay open between
54// calls when HTTP/1.1 protocol is used
56private:
57 TWebFile *fWebFile; // associated web file
58public:
61 void ReOpen();
62};
63
64////////////////////////////////////////////////////////////////////////////////
65/// Open web file socket.
66
68{
69 fWebFile = f;
70 if (!f->fSocket)
71 ReOpen();
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Close socket in case not HTTP/1.1 protocol or when explicitly requested.
76
78{
79 if (!fWebFile->fHTTP11) {
80 delete fWebFile->fSocket;
81 fWebFile->fSocket = 0;
82 }
83}
84
85////////////////////////////////////////////////////////////////////////////////
86/// Re-open web file socket.
87
89{
90 if (fWebFile->fSocket) {
91 delete fWebFile->fSocket;
92 fWebFile->fSocket = 0;
93 }
94
95 TUrl connurl;
96 if (fWebFile->fProxy.IsValid())
97 connurl = fWebFile->fProxy;
98 else
99 connurl = fWebFile->fUrl;
100
101 for (Int_t i = 0; i < 5; i++) {
102 if (strcmp(connurl.GetProtocol(), "https") == 0) {
103#ifdef R__SSL
104 fWebFile->fSocket = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
105#else
106 ::Error("TWebSocket::ReOpen", "library compiled without SSL, https not supported");
107 return;
108#endif
109 } else
110 fWebFile->fSocket = new TSocket(connurl.GetHost(), connurl.GetPort());
111
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);
117 } else {
118 ::Error("TWebSocket::ReOpen", "cannot connect to host %s (errno=%d)",
120 return;
121 }
122 } else
123 return;
124 }
125}
126
127
129
130////////////////////////////////////////////////////////////////////////////////
131/// Create a Web file object. A web file is the same as a read-only
132/// TFile except that it is being read via a HTTP server. The url
133/// argument must be of the form: http://host.dom.ain/file.root.
134/// The opt can be "NOPROXY", to bypass any set "http_proxy" shell
135/// variable. The proxy can be specified as (in sh, or equivalent csh):
136/// export http_proxy=http://pcsalo.cern.ch:3128
137/// The proxy can also be specified via the static method TWebFile::SetProxy().
138/// Basic authentication (AuthType Basic) is supported. The user name and
139/// passwd can be specified in the url like this:
140/// http://username:mypasswd@pcsalo.cern.ch/files/aap.root
141/// If the file specified in the URL does not exist or is not accessible
142/// the kZombie bit will be set in the TWebFile object. Use IsZombie()
143/// to see if the file is accessible. The preferred interface to this
144/// constructor is via TFile::Open().
145
146TWebFile::TWebFile(const char *url, Option_t *opt)
147 : TFile(url, strstr(opt, "_WITHOUT_GLOBALREGISTRATION") != nullptr ? "WEB_WITHOUT_GLOBALREGISTRATION" : "WEB"),
148 fSocket(0)
149{
150 TString option = opt;
152 if (option.Contains("NOPROXY", TString::kIgnoreCase))
153 fNoProxy = kTRUE;
154 CheckProxy();
155
156 Bool_t headOnly = kFALSE;
157 if (option.Contains("HEADONLY", TString::kIgnoreCase))
158 headOnly = kTRUE;
159
160 if (option == "IO")
161 return;
162
163 Init(headOnly);
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// Create a Web file object. A web file is the same as a read-only
168/// TFile except that it is being read via a HTTP server. Make sure url
169/// is a valid TUrl object.
170/// The opt can be "NOPROXY", to bypass any set "http_proxy" shell
171/// variable. The proxy can be specified as (in sh, or equivalent csh):
172/// export http_proxy=http://pcsalo.cern.ch:3128
173/// The proxy can also be specified via the static method TWebFile::SetProxy().
174/// Basic authentication (AuthType Basic) is supported. The user name and
175/// passwd can be specified in the url like this:
176/// http://username:mypasswd@pcsalo.cern.ch/files/aap.root
177/// If the file specified in the URL does not exist or is not accessible
178/// the kZombie bit will be set in the TWebFile object. Use IsZombie()
179/// to see if the file is accessible.
180
181TWebFile::TWebFile(TUrl url, Option_t *opt) : TFile(url.GetUrl(), "WEB"), fSocket(0)
182{
183 TString option = opt;
185 if (option.Contains("NOPROXY", TString::kIgnoreCase))
186 fNoProxy = kTRUE;
187 CheckProxy();
188
189 Bool_t headOnly = kFALSE;
190 if (option.Contains("HEADONLY", TString::kIgnoreCase))
191 headOnly = kTRUE;
192
193 Init(headOnly);
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Cleanup.
198
200{
201 delete fSocket;
202 if (fFullCache) {
204 fFullCache = 0;
205 fFullCacheSize = 0;
206 }
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Initialize a TWebFile object.
211
212void TWebFile::Init(Bool_t readHeadOnly)
213{
214 char buf[4];
215 int err;
216
217 fSocket = 0;
218 fSize = -1;
220 fHTTP11 = kFALSE;
221 fFullCache = 0;
222 fFullCacheSize = 0;
224
225 if ((err = GetHead()) < 0) {
226 if (readHeadOnly) {
227 fD = -1;
228 fWritten = err;
229 return;
230 }
231 if (err == -2) {
232 Error("TWebFile", "%s does not exist", fBasicUrl.Data());
233 MakeZombie();
235 return;
236 }
237 // err == -3 HEAD not supported, fall through and try ReadBuffer()
238 }
239 if (readHeadOnly) {
240 fD = -1;
241 return;
242 }
243
244 if (fIsRootFile) {
245 Seek(0);
246 if (ReadBuffer(buf, 4)) {
247 MakeZombie();
249 return;
250 }
251
252 if (strncmp(buf, "root", 4) && strncmp(buf, "PK", 2)) { // PK is zip file
253 Error("TWebFile", "%s is not a ROOT file", fBasicUrl.Data());
254 MakeZombie();
256 return;
257 }
258 }
259
261 fD = -2; // so TFile::IsOpen() will return true when in TFile::~TFile
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Set GET command for use by ReadBuffer(s)10(), handle redirection if
266/// needed. Give full URL so Apache's virtual hosts solution works.
267
268void TWebFile::SetMsgReadBuffer10(const char *redirectLocation, Bool_t tempRedirect)
269{
270 TUrl oldUrl;
271 TString oldBasicUrl;
272
273 if (redirectLocation) {
274 if (tempRedirect) { // temp redirect
275 fUrlOrg = fUrl;
277 } else { // permanent redirect
278 fUrlOrg = "";
279 fBasicUrlOrg = "";
280 }
281
282 oldUrl = fUrl;
283 oldBasicUrl = fBasicUrl;
284
285 fUrl.SetUrl(redirectLocation);
287 fBasicUrl += "://";
289 fBasicUrl += ":";
291 fBasicUrl += "/";
293 // add query string again
294 TString rdl(redirectLocation);
295 if (rdl.Index("?") >= 0) {
296 rdl = rdl(rdl.Index("?"), rdl.Length());
297 fBasicUrl += rdl;
298 }
299 }
300
301 if (fMsgReadBuffer10 != "") {
302 // patch up existing command
303 if (oldBasicUrl != "") {
304 // change to redirection location
306 fMsgReadBuffer10.ReplaceAll(TString("Host: ")+oldUrl.GetHost(), TString("Host: ")+fUrl.GetHost());
307 } else if (fBasicUrlOrg != "") {
308 // change back from temp redirection location
311 fUrl = fUrlOrg;
313 fUrlOrg = "";
314 fBasicUrlOrg = "";
315 }
316 }
317
318 if (fBasicUrl == "") {
320 fBasicUrl += "://";
322 fBasicUrl += ":";
324 fBasicUrl += "/";
326 fBasicUrl += "?";
328 }
329
330 if (fMsgReadBuffer10 == "") {
331 fMsgReadBuffer10 = "GET ";
333 if (fHTTP11)
334 fMsgReadBuffer10 += " HTTP/1.1";
335 else
336 fMsgReadBuffer10 += " HTTP/1.0";
337 fMsgReadBuffer10 += "\r\n";
338 if (fHTTP11) {
339 fMsgReadBuffer10 += "Host: ";
341 fMsgReadBuffer10 += "\r\n";
342 }
345 fMsgReadBuffer10 += "\r\n";
346 fMsgReadBuffer10 += "Range: bytes=";
347 }
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Check if shell var "http_proxy" has been set and should be used.
352
354{
355 if (fNoProxy)
356 return;
357
358 if (fgProxy.IsValid()) {
359 fProxy = fgProxy;
360 return;
361 }
362
363 TString proxy = gSystem->Getenv("http_proxy");
364 if (proxy != "") {
365 TUrl p(proxy);
366 if (strcmp(p.GetProtocol(), "http")) {
367 Error("CheckProxy", "protocol must be HTTP in proxy URL %s",
368 proxy.Data());
369 return;
370 }
371 fProxy = p;
372 if (gDebug > 0)
373 Info("CheckProxy", "using HTTP proxy %s", fProxy.GetUrl());
374 }
375}
376
377////////////////////////////////////////////////////////////////////////////////
378/// A TWebFile that has been correctly constructed is always considered open.
379
381{
382 return IsZombie() ? kFALSE : kTRUE;
383}
384
385////////////////////////////////////////////////////////////////////////////////
386/// Reopen a file with a different access mode, like from READ to
387/// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
388/// mode argument can be either "READ" or "UPDATE". The method returns
389/// 0 in case the mode was successfully modified, 1 in case the mode
390/// did not change (was already as requested or wrong input arguments)
391/// and -1 in case of failure, in which case the file cannot be used
392/// anymore. A TWebFile cannot be reopened in update mode.
393
395{
396 TString opt = mode;
397 opt.ToUpper();
398
399 if (opt != "READ" && opt != "UPDATE")
400 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
401
402 if (opt == "UPDATE")
403 Error("ReOpen", "update mode not allowed for a TWebFile");
404
405 return 1;
406}
407
408////////////////////////////////////////////////////////////////////////////////
409/// Close a Web file. Close the socket connection and delete the cache
410/// See also the TFile::Close() function
411
413{
414 if (fSocket)
415 delete fSocket;
416 fSocket = nullptr;
417 if (fFullCache) {
419 fFullCache = 0;
420 fFullCacheSize = 0;
421 }
422 return TFile::Close(option);
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// Read specified byte range from remote file via HTTP daemon. This
427/// routine connects to the remote host, sends the request and returns
428/// the buffer. Returns kTRUE in case of error.
429
431{
432 Int_t st;
433 if ((st = ReadBufferViaCache(buf, len))) {
434 if (st == 2)
435 return kTRUE;
436 return kFALSE;
437 }
438
439 if (!fHasModRoot)
440 return ReadBuffer10(buf, len);
441
442 // Give full URL so Apache's virtual hosts solution works.
443 // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
444 if (fMsgReadBuffer == "") {
445 fMsgReadBuffer = "GET ";
447 fMsgReadBuffer += "?";
448 }
450 msg += fOffset;
451 msg += ":";
452 msg += len;
453 msg += "\r\n";
454
455 if (GetFromWeb(buf, len, msg) == -1)
456 return kTRUE;
457
458 fOffset += len;
459
460 return kFALSE;
461}
462
463////////////////////////////////////////////////////////////////////////////////
464/// Read specified byte range from remote file via HTTP daemon. This
465/// routine connects to the remote host, sends the request and returns
466/// the buffer. Returns kTRUE in case of error.
467
469{
470 SetOffset(pos);
471 return ReadBuffer(buf, len);
472}
473
474////////////////////////////////////////////////////////////////////////////////
475/// Read specified byte range from remote file via HTTP 1.0 daemon (without
476/// mod-root installed). This routine connects to the remote host, sends the
477/// request and returns the buffer. Returns kTRUE in case of error.
478
480{
482
484 msg += fOffset;
485 msg += "-";
486 msg += fOffset+len-1;
487 msg += "\r\n\r\n";
488
490
491 // in case when server does not support segments, let chance to recover
492 Int_t n = GetFromWeb10(buf, len, msg, 1, &apos, &len);
493 if (n == -1)
494 return kTRUE;
495 // The -2 error condition typically only happens when
496 // GetHead() failed because not implemented, in the first call to
497 // ReadBuffer() in Init(), it is not checked in ReadBuffers10().
498 if (n == -2) {
499 Error("ReadBuffer10", "%s does not exist", fBasicUrl.Data());
500 MakeZombie();
502 return kTRUE;
503 }
504
505 fOffset += len;
506
507 return kFALSE;
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Read specified byte ranges from remote file via HTTP daemon.
512/// Reads the nbuf blocks described in arrays pos and len,
513/// where pos[i] is the seek position of block i of length len[i].
514/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
515/// This function is overloaded by TNetFile, TWebFile, etc.
516/// Returns kTRUE in case of failure.
517
519{
520 if (!fHasModRoot)
521 return ReadBuffers10(buf, pos, len, nbuf);
522
523 // Give full URL so Apache's virtual hosts solution works.
524 // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
525 if (fMsgReadBuffer == "") {
526 fMsgReadBuffer = "GET ";
528 fMsgReadBuffer += "?";
529 }
531
532 Int_t k = 0, n = 0, cnt = 0;
533 for (Int_t i = 0; i < nbuf; i++) {
534 if (n) msg += ",";
535 msg += pos[i] + fArchiveOffset;
536 msg += ":";
537 msg += len[i];
538 n += len[i];
539 cnt++;
540 if ((msg.Length() > 8000) || (cnt >= 200)) {
541 msg += "\r\n";
542 if (GetFromWeb(&buf[k], n, msg) == -1)
543 return kTRUE;
544 msg = fMsgReadBuffer;
545 k += n;
546 n = 0;
547 cnt = 0;
548 }
549 }
550
551 msg += "\r\n";
552
553 if (GetFromWeb(&buf[k], n, msg) == -1)
554 return kTRUE;
555
556 return kFALSE;
557}
558
559////////////////////////////////////////////////////////////////////////////////
560/// Read specified byte ranges from remote file via HTTP 1.0 daemon (without
561/// mod-root installed). Read the nbuf blocks described in arrays pos and len,
562/// where pos[i] is the seek position of block i of length len[i].
563/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
564/// This function is overloaded by TNetFile, TWebFile, etc.
565/// Returns kTRUE in case of failure.
566
568{
570
572
573 Int_t k = 0, n = 0, r, cnt = 0;
574 for (Int_t i = 0; i < nbuf; i++) {
575 if (n) msg += ",";
576 msg += pos[i] + fArchiveOffset;
577 msg += "-";
578 msg += pos[i] + fArchiveOffset + len[i] - 1;
579 n += len[i];
580 cnt++;
581 if ((msg.Length() > 8000) || (cnt >= 200) || (i+1 == nbuf)) {
582 msg += "\r\n\r\n";
583 r = GetFromWeb10(&buf[k], n, msg, cnt, pos + (i+1-cnt), len + (i+1-cnt));
584 if (r == -1)
585 return kTRUE;
586 msg = fMsgReadBuffer10;
587 k += n;
588 n = 0;
589 cnt = 0;
590 }
591 }
592
593 return kFALSE;
594}
595
596////////////////////////////////////////////////////////////////////////////////
597/// Extract requested segments from the cached content.
598/// Such cache can be produced when server suddenly returns full data instead of segments
599/// Returns -1 in case of error, 0 in case of success
600
601Int_t TWebFile::GetFromCache(char *buf, Int_t len, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
602{
603 if (!fFullCache) return -1;
604
605 if (gDebug > 0)
606 Info("GetFromCache", "Extract %d segments total len %d from cached data", nseg, len);
607
608 Int_t curr = 0;
609 for (Int_t cnt=0;cnt<nseg;cnt++) {
610 // check that target buffer has enough space
611 if (curr + seg_len[cnt] > len) return -1;
612 // check that segment is inside cached area
613 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fFullCacheSize) return -1;
614 char* src = (char*) fFullCache + fArchiveOffset + seg_pos[cnt];
615 memcpy(buf + curr, src, seg_len[cnt]);
616 curr += seg_len[cnt];
617 }
618
619 return 0;
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Read request from web server. Returns -1 in case of error,
624/// 0 in case of success.
625
627{
628 TSocket *s;
629
630 if (!len) return 0;
631
632 Double_t start = 0;
633 if (gPerfStats) start = TTimeStamp();
634
635 TUrl connurl;
636 if (fProxy.IsValid())
637 connurl = fProxy;
638 else
639 connurl = fUrl;
640
641 if (strcmp(connurl.GetProtocol(), "https") == 0) {
642#ifdef R__SSL
643 s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
644#else
645 Error("GetFromWeb", "library compiled without SSL, https not supported");
646 return -1;
647#endif
648 } else
649 s = new TSocket(connurl.GetHost(), connurl.GetPort());
650
651 if (!s->IsValid()) {
652 Error("GetFromWeb", "cannot connect to host %s", fUrl.GetHost());
653 delete s;
654 return -1;
655 }
656
657 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
658 Error("GetFromWeb", "error sending command to host %s", fUrl.GetHost());
659 delete s;
660 return -1;
661 }
662
663 if (s->RecvRaw(buf, len) == -1) {
664 Error("GetFromWeb", "error receiving data from host %s", fUrl.GetHost());
665 delete s;
666 return -1;
667 }
668
669 // collect statistics
670 fBytesRead += len;
671 fReadCalls++;
672#ifdef R__WIN32
675#else
676 fgBytesRead += len;
677 fgReadCalls++;
678#endif
679
680 if (gPerfStats)
681 gPerfStats->FileReadEvent(this, len, start);
682
683 delete s;
684 return 0;
685}
686
687////////////////////////////////////////////////////////////////////////////////
688/// Read multiple byte range request from web server.
689/// Uses HTTP 1.0 daemon wihtout mod-root.
690/// Returns -2 in case file does not exist, -1 in case
691/// of error and 0 in case of success.
692
693Int_t TWebFile::GetFromWeb10(char *buf, Int_t len, const TString &msg, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
694{
695 if (!len) return 0;
696
697 // if file content was cached, reuse it
698 if (fFullCache && (nseg>0))
699 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
700
701 Double_t start = 0;
702 if (gPerfStats) start = TTimeStamp();
703
704 // open fSocket and close it when going out of scope
705 TWebSocket ws(this);
706
707 if (!fSocket || !fSocket->IsValid()) {
708 Error("GetFromWeb10", "cannot connect to host %s", fUrl.GetHost());
709 return -1;
710 }
711
712 if (gDebug > 0)
713 Info("GetFromWeb10", "sending HTTP request:\n%s", msg.Data());
714
715 if (fSocket->SendRaw(msg.Data(), msg.Length()) == -1) {
716 Error("GetFromWeb10", "error sending command to host %s", fUrl.GetHost());
717 return -1;
718 }
719
720 char line[8192];
721 Int_t n, ret = 0, nranges = 0, ltot = 0, redirect = 0;
722 TString boundary, boundaryEnd;
723 Long64_t first = -1, last = -1, tot, fullsize = 0;
724 TString redir;
725
726 while ((n = GetLine(fSocket, line, sizeof(line))) >= 0) {
727 if (n == 0) {
728 if (ret < 0)
729 return ret;
730 if (redirect) {
731 if (redir.IsNull()) {
732 // Some sites (s3.amazonaws.com) do not return a Location field on 301
733 Error("GetFromWeb10", "error - redirect without location from host %s", fUrl.GetHost());
734 return -1;
735 }
736
737 ws.ReOpen();
738 // set message to reflect the redirectLocation and add bytes field
740 msg_1 += fOffset;
741 msg_1 += "-";
742 msg_1 += fOffset+len-1;
743 msg_1 += "\r\n\r\n";
744 return GetFromWeb10(buf, len, msg_1);
745 }
746
747 if (first >= 0) {
748 Int_t ll = Int_t(last - first) + 1;
749 Int_t rsize;
750 if ((rsize = fSocket->RecvRaw(&buf[ltot], ll)) == -1) {
751 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
752 return -1;
753 }
754 else if (ll != rsize) {
755 Error("GetFromWeb10", "expected %d bytes, got %d", ll, rsize);
756 return -1;
757 }
758 ltot += ll;
759
760 first = -1;
761
762 if (boundary == "")
763 break; // not a multipart response
764 }
765
766 if (fullsize > 0) {
767
768 if (nseg <= 0) {
769 Error("GetFromWeb10","Need segments data to extract parts from full size %lld", fullsize);
770 return -1;
771 }
772
773 if (len > fullsize) {
774 Error("GetFromWeb10","Requested part %d longer than full size %lld", len, fullsize);
775 return -1;
776 }
777
778 if ((fFullCache == 0) && (fullsize <= GetMaxFullCacheSize())) {
779 // try to read file content into cache and than reuse it, limit cache by 2 GB
780 fFullCache = malloc(fullsize);
781 if (fFullCache != 0) {
782 if (fSocket->RecvRaw(fFullCache, fullsize) != fullsize) {
783 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
785 return -1;
786 }
787 fFullCacheSize = fullsize;
788 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
789 }
790 // when cache allocation failed, try without cache
791 }
792
793 // check all segemnts are inside range and in sorted order
794 for (Int_t cnt=0;cnt<nseg;cnt++) {
795 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fullsize) {
796 Error("GetFromWeb10","Requested segment %lld len %d is outside of full range %lld", seg_pos[cnt], seg_len[cnt], fullsize);
797 return -1;
798 }
799 if ((cnt>0) && (seg_pos[cnt-1] + seg_len[cnt-1] > seg_pos[cnt])) {
800 Error("GetFromWeb10","Requested segments are not in sorted order");
801 return -1;
802 }
803 }
804
805 Long64_t pos = 0;
806 char* curr = buf;
807 char dbuf[2048]; // dummy buffer for skip data
808
809 // now read complete file and take only requested segments into the buffer
810 for (Int_t cnt=0; cnt<nseg; cnt++) {
811 // first skip data before segment
812 while (pos < fArchiveOffset + seg_pos[cnt]) {
813 Long64_t ll = fArchiveOffset + seg_pos[cnt] - pos;
814 if (ll > Int_t(sizeof(dbuf))) ll = sizeof(dbuf);
815 if (fSocket->RecvRaw(dbuf, ll) != ll) {
816 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
817 return -1;
818 }
819 pos += ll;
820 }
821
822 // reading segment itself
823 if (fSocket->RecvRaw(curr, seg_len[cnt]) != seg_len[cnt]) {
824 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
825 return -1;
826 }
827 curr += seg_len[cnt];
828 pos += seg_len[cnt];
829 ltot += seg_len[cnt];
830 }
831
832 // now read file to the end
833 while (pos < fullsize) {
834 Long64_t ll = fullsize - pos;
835 if (ll > Int_t(sizeof(dbuf))) ll = sizeof(dbuf);
836 if (fSocket->RecvRaw(dbuf, ll) != ll) {
837 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
838 return -1;
839 }
840 pos += ll;
841 }
842
843 if (gDebug>0) Info("GetFromWeb10","Complete reading %d bytes in %d segments out of full size %lld", len, nseg, fullsize);
844
845 break;
846 }
847
848 continue;
849 }
850
851 if (gDebug > 0)
852 Info("GetFromWeb10", "header: %s", line);
853
854 if (boundaryEnd == line) {
855 if (gDebug > 0)
856 Info("GetFromWeb10", "got all headers");
857 break;
858 }
859 if (boundary == line) {
860 nranges++;
861 if (gDebug > 0)
862 Info("GetFromWeb10", "get new multipart byte range (%d)", nranges);
863 }
864
865 TString res = line;
866
867 if (res.BeginsWith("HTTP/1.")) {
868 if (res.BeginsWith("HTTP/1.1")) {
869 if (!fHTTP11)
870 fMsgReadBuffer10 = "";
871 fHTTP11 = kTRUE;
872 }
873 TString scode = res(9, 3);
874 Int_t code = scode.Atoi();
875 if (code >= 500) {
876 ret = -1;
877 TString mess = res(13, 1000);
878 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
879 } else if (code >= 400) {
880 if (code == 404)
881 ret = -2; // file does not exist
882 else {
883 ret = -1;
884 TString mess = res(13, 1000);
885 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
886 }
887 } else if (code >= 300) {
888 if (code == 301 || code == 303) {
889 redirect = 1; // permanent redirect
890 } else if (code == 302 || code == 307) {
891 // treat 302 as 303: permanent redirect
892 redirect = 1;
893 //redirect = 2; // temp redirect
894 } else {
895 ret = -1;
896 TString mess = res(13, 1000);
897 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
898 }
899 } else if (code > 200) {
900 if (code != 206) {
901 ret = -1;
902 TString mess = res(13, 1000);
903 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
904 }
905 } else if (code == 200) {
906 fullsize = -200; // make indication of code 200
907 Warning("GetFromWeb10",
908 "Server %s response with complete file, but only part of it was requested.\n"
909 "Check MaxRanges configuration parameter (if Apache is used)",
910 fUrl.GetHost());
911
912 }
913 } else if (res.BeginsWith("Content-Type: multipart")) {
914 boundary = res(res.Index("boundary=")+9, 1000);
915 if (boundary[0]=='"' && boundary[boundary.Length()-1]=='"') {
916 boundary = boundary(1,boundary.Length()-2);
917 }
918 boundary = "--" + boundary;
919 boundaryEnd = boundary + "--";
920 } else if (res.BeginsWith("Content-range:")) {
921#ifdef R__WIN32
922 sscanf(res.Data(), "Content-range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
923#else
924 sscanf(res.Data(), "Content-range: bytes %lld-%lld/%lld", &first, &last, &tot);
925#endif
926 if (fSize == -1) fSize = tot;
927 } else if (res.BeginsWith("Content-Range:")) {
928#ifdef R__WIN32
929 sscanf(res.Data(), "Content-Range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
930#else
931 sscanf(res.Data(), "Content-Range: bytes %lld-%lld/%lld", &first, &last, &tot);
932#endif
933 if (fSize == -1) fSize = tot;
934 } else if (res.BeginsWith("Content-Length:") && (fullsize == -200)) {
935#ifdef R__WIN32
936 sscanf(res.Data(), "Content-Length: %I64d", &fullsize);
937#else
938 sscanf(res.Data(), "Content-Length: %lld", &fullsize);
939#endif
940 } else if (res.BeginsWith("Location:") && redirect) {
941 redir = res(10, 1000);
942 if (redirect == 2) // temp redirect
944 else // permanent redirect
946 }
947 }
948
949 if (redirect && redir.IsNull()) {
950 Error("GetFromWeb10", "error - redirect without location from host %s", fUrl.GetHost());
951 }
952
953 if (n == -1 && fHTTP11) {
954 if (gDebug > 0)
955 Info("GetFromWeb10", "HTTP/1.1 socket closed, reopen");
956 if (fBasicUrlOrg != "") {
957 // if we have to close temp redirection, set back to original url
959 }
960 ws.ReOpen();
961 return GetFromWeb10(buf, len, msg);
962 }
963
964 if (ltot != len) {
965 Error("GetFromWeb10", "error receiving expected amount of data (got %d, expected %d) from host %s",
966 ltot, len, fUrl.GetHost());
967 return -1;
968 }
969
970 // collect statistics
971 fBytesRead += len;
972 fReadCalls++;
973#ifdef R__WIN32
976#else
977 fgBytesRead += len;
978 fgReadCalls++;
979#endif
980
981 if (gPerfStats)
982 gPerfStats->FileReadEvent(this, len, start);
983
984 return 0;
985}
986
987////////////////////////////////////////////////////////////////////////////////
988/// Set position from where to start reading.
989
991{
992 switch (pos) {
993 case kBeg:
995 break;
996 case kCur:
997 fOffset += offset;
998 break;
999 case kEnd:
1000 // this option is not used currently in the ROOT code
1001 if (fArchiveOffset)
1002 Error("Seek", "seeking from end in archive is not (yet) supported");
1003 fOffset = fEND - offset; // is fEND really EOF or logical EOF?
1004 break;
1005 }
1006}
1007
1008////////////////////////////////////////////////////////////////////////////////
1009/// Return maximum file size.
1010
1012{
1013 if (!fHasModRoot || fSize >= 0)
1014 return fSize;
1015
1016 Long64_t size;
1017 char asize[64];
1018
1019 TString msg = "GET ";
1020 msg += fBasicUrl;
1021 msg += "?";
1022 msg += -1;
1023 msg += "\r\n";
1024
1025 if (const_cast<TWebFile*>(this)->GetFromWeb(asize, 64, msg) == -1)
1026 return kMaxInt;
1027
1028#ifndef R__WIN32
1029 size = atoll(asize);
1030#else
1031 size = _atoi64(asize);
1032#endif
1033
1034 fSize = size;
1035
1036 return size;
1037}
1038
1039////////////////////////////////////////////////////////////////////////////////
1040/// Get the HTTP header. Depending on the return code we can see if
1041/// the file exists and if the server uses mod_root.
1042/// Returns -1 in case of an error, -2 in case the file does not exists,
1043/// -3 in case HEAD is not supported (dCache HTTP door) and
1044/// 0 in case of success.
1045
1047{
1048 // Give full URL so Apache's virtual hosts solution works.
1049 if (fMsgGetHead == "") {
1050 fMsgGetHead = "HEAD ";
1052 if (fHTTP11)
1053 fMsgGetHead += " HTTP/1.1";
1054 else
1055 fMsgGetHead += " HTTP/1.0";
1056 fMsgGetHead += "\r\n";
1057 if (fHTTP11) {
1058 fMsgGetHead += "Host: ";
1060 fMsgGetHead += "\r\n";
1061 }
1064 fMsgGetHead += "\r\n\r\n";
1065 }
1066 TString msg = fMsgGetHead;
1067
1068 TUrl connurl;
1069 if (fProxy.IsValid())
1070 connurl = fProxy;
1071 else
1072 connurl = fUrl;
1073
1074 TSocket *s = 0;
1075 for (Int_t i = 0; i < 5; i++) {
1076 if (strcmp(connurl.GetProtocol(), "https") == 0) {
1077#ifdef R__SSL
1078 s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
1079#else
1080 Error("GetHead", "library compiled without SSL, https not supported");
1081 return -1;
1082#endif
1083 } else
1084 s = new TSocket(connurl.GetHost(), connurl.GetPort());
1085
1086 if (!s->IsValid()) {
1087 delete s;
1088 if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
1089 s = 0;
1090 gSystem->Sleep(i*10);
1091 } else {
1092 Error("GetHead", "cannot connect to host %s (errno=%d)", fUrl.GetHost(),
1093 gSystem->GetErrno());
1094 return -1;
1095 }
1096 } else
1097 break;
1098 }
1099 if (!s)
1100 return -1;
1101
1102 if (gDebug > 0) {
1103 Info("GetHead", "connected to host %s", connurl.GetHost());
1104 Info("GetHead", "sending HTTP request:\n%s", msg.Data());
1105 }
1106
1107 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
1108 Error("GetHead", "error sending command to host %s", fUrl.GetHost());
1109 delete s;
1110 return -1;
1111 }
1112
1113 char line[8192];
1114 Int_t n, ret = 0, redirect = 0;
1115 TString redir;
1116
1117 while ((n = GetLine(s, line, sizeof(line))) >= 0) {
1118 if (n == 0) {
1119 if (gDebug > 0)
1120 Info("GetHead", "got all headers");
1121 delete s;
1122 if (fBasicUrlOrg != "" && !redirect) {
1123 // set back to original url in case of temp redirect
1125 fMsgGetHead = "";
1126 }
1127 if (ret < 0)
1128 return ret;
1129 if (redirect) {
1130 if (redir.IsNull()) {
1131 // Some sites (s3.amazonaws.com) do not return a Location field on 301
1132 Error("GetHead", "error - redirect without location from host %s", fUrl.GetHost());
1133 return -1;
1134 }
1135 return GetHead();
1136 }
1137 return 0;
1138 }
1139
1140 if (gDebug > 0)
1141 Info("GetHead", "header: %s", line);
1142
1143 TString res = line;
1144 ProcessHttpHeader(res);
1145 if (res.BeginsWith("HTTP/1.")) {
1146 if (res.BeginsWith("HTTP/1.1")) {
1147 if (!fHTTP11) {
1148 fMsgGetHead = "";
1149 fMsgReadBuffer10 = "";
1150 }
1151 fHTTP11 = kTRUE;
1152 }
1153 TString scode = res(9, 3);
1154 Int_t code = scode.Atoi();
1155 if (code >= 500) {
1156 if (code == 500)
1158 else {
1159 ret = -1;
1160 TString mess = res(13, 1000);
1161 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1162 }
1163 } else if (code >= 400) {
1164 if (code == 400)
1165 ret = -3; // command not supported
1166 else if (code == 404)
1167 ret = -2; // file does not exist
1168 else {
1169 ret = -1;
1170 TString mess = res(13, 1000);
1171 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1172 }
1173 } else if (code >= 300) {
1174 if (code == 301 || code == 303)
1175 redirect = 1; // permanent redirect
1176 else if (code == 302 || code == 307)
1177 redirect = 2; // temp redirect
1178 else {
1179 ret = -1;
1180 TString mess = res(13, 1000);
1181 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1182 }
1183 } else if (code > 200) {
1184 ret = -1;
1185 TString mess = res(13, 1000);
1186 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1187 }
1188 } else if (res.BeginsWith("Content-Length:")) {
1189 TString slen = res(16, 1000);
1190 fSize = slen.Atoll();
1191 } else if (res.BeginsWith("Location:") && redirect) {
1192 redir = res(10, 1000);
1193 if (redirect == 2) // temp redirect
1194 SetMsgReadBuffer10(redir, kTRUE);
1195 else // permanent redirect
1196 SetMsgReadBuffer10(redir, kFALSE);
1197 fMsgGetHead = "";
1198 }
1199 }
1200
1201 delete s;
1202
1203 return ret;
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Read a line from the socket. Reads at most one less than the number of
1208/// characters specified by maxsize. Reading stops when a newline character
1209/// is found, The newline (\\n) and cr (\\r), if any, are removed.
1210/// Returns -1 in case of error, or the number of characters read (>= 0)
1211/// otherwise.
1212
1214{
1215 Int_t n = GetHunk(s, line, maxsize);
1216 if (n < 0) {
1217 if (!fHTTP11 || gDebug > 0)
1218 Error("GetLine", "error receiving data from host %s", fUrl.GetHost());
1219 return -1;
1220 }
1221
1222 if (n > 0 && line[n-1] == '\n') {
1223 n--;
1224 if (n > 0 && line[n-1] == '\r')
1225 n--;
1226 line[n] = '\0';
1227 }
1228 return n;
1229}
1230
1231////////////////////////////////////////////////////////////////////////////////
1232/// Read a hunk of data from the socket, up until a terminator. The hunk is
1233/// limited by whatever the TERMINATOR callback chooses as its
1234/// terminator. For example, if terminator stops at newline, the hunk
1235/// will consist of a line of data; if terminator stops at two
1236/// newlines, it can be used to read the head of an HTTP response.
1237/// Upon determining the boundary, the function returns the data (up to
1238/// the terminator) in hunk.
1239///
1240/// In case of read error, -1 is returned. In case of having read some
1241/// data, but encountering EOF before seeing the terminator, the data
1242/// that has been read is returned, but it will (obviously) not contain the
1243/// terminator.
1244///
1245/// The TERMINATOR function is called with three arguments: the
1246/// beginning of the data read so far, the beginning of the current
1247/// block of peeked-at data, and the length of the current block.
1248/// Depending on its needs, the function is free to choose whether to
1249/// analyze all data or just the newly arrived data. If TERMINATOR
1250/// returns 0, it means that the terminator has not been seen.
1251/// Otherwise it should return a pointer to the character immediately
1252/// following the terminator.
1253///
1254/// The idea is to be able to read a line of input, or otherwise a hunk
1255/// of text, such as the head of an HTTP request, without crossing the
1256/// boundary, so that the next call to RecvRaw() etc. reads the data
1257/// after the hunk. To achieve that, this function does the following:
1258///
1259/// 1. Peek at incoming data.
1260///
1261/// 2. Determine whether the peeked data, along with the previously
1262/// read data, includes the terminator.
1263///
1264/// 3a. If yes, read the data until the end of the terminator, and
1265/// exit.
1266///
1267/// 3b. If no, read the peeked data and goto 1.
1268///
1269/// The function is careful to assume as little as possible about the
1270/// implementation of peeking. For example, every peek is followed by
1271/// a read. If the read returns a different amount of data, the
1272/// process is retried until all data arrives safely.
1273///
1274/// Reads at most one less than the number of characters specified by maxsize.
1275
1276Int_t TWebFile::GetHunk(TSocket *s, char *hunk, Int_t maxsize)
1277{
1278 if (maxsize <= 0) return 0;
1279
1280 Int_t bufsize = maxsize;
1281 Int_t tail = 0; // tail position in HUNK
1282
1283 while (1) {
1284 const char *end;
1285 Int_t pklen, rdlen, remain;
1286
1287 // First, peek at the available data.
1288 pklen = s->RecvRaw(hunk+tail, bufsize-1-tail, kPeek);
1289 if (pklen < 0) {
1290 return -1;
1291 }
1292 end = HttpTerminator(hunk, hunk+tail, pklen);
1293 if (end) {
1294 // The data contains the terminator: we'll drain the data up
1295 // to the end of the terminator.
1296 remain = end - (hunk + tail);
1297 if (remain == 0) {
1298 // No more data needs to be read.
1299 hunk[tail] = '\0';
1300 return tail;
1301 }
1302 if (bufsize - 1 < tail + remain) {
1303 Error("GetHunk", "hunk buffer too small for data from host %s (%d bytes needed)",
1304 fUrl.GetHost(), tail + remain + 1);
1305 hunk[tail] = '\0';
1306 return -1;
1307 }
1308 } else {
1309 // No terminator: simply read the data we know is (or should
1310 // be) available.
1311 remain = pklen;
1312 }
1313
1314 // Now, read the data. Note that we make no assumptions about
1315 // how much data we'll get. (Some TCP stacks are notorious for
1316 // read returning less data than the previous MSG_PEEK.)
1317 rdlen = s->RecvRaw(hunk+tail, remain, kDontBlock);
1318 if (rdlen < 0) {
1319 return -1;
1320 }
1321 tail += rdlen;
1322 hunk[tail] = '\0';
1323
1324 if (rdlen == 0) {
1325 // in case of EOF: return the data we've read.
1326 return tail;
1327 }
1328 if (end && rdlen == remain) {
1329 // The terminator was seen and the remaining data drained --
1330 // we got what we came for.
1331 return tail;
1332 }
1333
1334 // Keep looping until all the data arrives.
1335
1336 if (tail == bufsize - 1) {
1337 Error("GetHunk", "hunk buffer too small for data from host %s",
1338 fUrl.GetHost());
1339 return -1;
1340 }
1341 }
1342}
1343
1344////////////////////////////////////////////////////////////////////////////////
1345/// Determine whether [START, PEEKED + PEEKLEN) contains an HTTP new
1346/// line [\\r]\\n. If so, return the pointer to the position after the line,
1347/// otherwise return 0. This is used as callback to GetHunk(). The data
1348/// between START and PEEKED has been read and cannot be "unread"; the
1349/// data after PEEKED has only been peeked.
1350
1351const char *TWebFile::HttpTerminator(const char *start, const char *peeked,
1352 Int_t peeklen)
1353{
1354#if 0
1355 const char *p, *end;
1356
1357 // Look for "[\r]\n", and return the following position if found.
1358 // Start one char before the current to cover the possibility that
1359 // part of the terminator (e.g. "\r") arrived in the previous batch.
1360 p = peeked - start < 1 ? start : peeked - 1;
1361 end = peeked + peeklen;
1362
1363 // Check for \r\n anywhere in [p, end-2).
1364 for (; p < end - 1; p++)
1365 if (p[0] == '\r' && p[1] == '\n')
1366 return p + 2;
1367
1368 // p==end-1: check for \r\n directly preceding END.
1369 if (p[0] == '\r' && p[1] == '\n')
1370 return p + 2;
1371#else
1372 (void) start; // start unused, silence compiler
1373 if (peeked) {
1374 const char *p = (const char*) memchr(peeked, '\n', peeklen);
1375 if (p)
1376 // p+1 because the line must include '\n'
1377 return p + 1;
1378 }
1379#endif
1380 return nullptr;
1381}
1382
1383////////////////////////////////////////////////////////////////////////////////
1384/// Return basic authentication scheme, to be added to the request.
1385
1387{
1388 TString msg;
1389 if (strlen(fUrl.GetUser())) {
1390 TString auth = fUrl.GetUser();
1391 if (strlen(fUrl.GetPasswd())) {
1392 auth += ":";
1393 auth += fUrl.GetPasswd();
1394 }
1395 msg += "Authorization: Basic ";
1396 msg += TBase64::Encode(auth);
1397 msg += "\r\n";
1398 }
1399 return msg;
1400}
1401
1402////////////////////////////////////////////////////////////////////////////////
1403/// Static method setting global proxy URL.
1404
1405void TWebFile::SetProxy(const char *proxy)
1406{
1407 if (proxy && *proxy) {
1408 TUrl p(proxy);
1409 if (strcmp(p.GetProtocol(), "http")) {
1410 :: Error("TWebFile::SetProxy", "protocol must be HTTP in proxy URL %s",
1411 proxy);
1412 return;
1413 }
1414 fgProxy = p;
1415 }
1416}
1417
1418////////////////////////////////////////////////////////////////////////////////
1419/// Static method returning the global proxy URL.
1420
1422{
1423 if (fgProxy.IsValid())
1424 return fgProxy.GetUrl();
1425 return "";
1426}
1427
1428////////////////////////////////////////////////////////////////////////////////
1429/// Process the HTTP header in the argument. This method is intended to be
1430/// overwritten by subclasses that exploit the information contained in the
1431/// HTTP headers.
1432
1434{
1435}
1436
1437////////////////////////////////////////////////////////////////////////////////
1438/// Static method returning maxmimal size of full cache,
1439/// which can be preserved by file instance
1440
1442{
1443 return fgMaxFullCacheSize;
1444}
1445
1446////////////////////////////////////////////////////////////////////////////////
1447/// Static method, set maxmimal size of full cache,
1448// which can be preserved by file instance
1449
1451{
1452 fgMaxFullCacheSize = sz;
1453}
1454
1455
1456////////////////////////////////////////////////////////////////////////////////
1457/// Create helper class that allows directory access via httpd.
1458/// The name must start with '-' to bypass the TSystem singleton check.
1459
1460TWebSystem::TWebSystem() : TSystem("-http", "HTTP Helper System")
1461{
1462 SetName("http");
1463
1464 fDirp = 0;
1465}
1466
1467////////////////////////////////////////////////////////////////////////////////
1468/// Make a directory via httpd. Not supported.
1469
1471{
1472 return -1;
1473}
1474
1475////////////////////////////////////////////////////////////////////////////////
1476/// Open a directory via httpd. Returns an opaque pointer to a dir
1477/// structure. Returns 0 in case of error.
1478
1479void *TWebSystem::OpenDirectory(const char *)
1480{
1481 if (fDirp) {
1482 Error("OpenDirectory", "invalid directory pointer (should never happen)");
1483 fDirp = 0;
1484 }
1485
1486 fDirp = 0; // not implemented for the time being
1487
1488 return fDirp;
1489}
1490
1491////////////////////////////////////////////////////////////////////////////////
1492/// Free directory via httpd.
1493
1495{
1496 if (dirp != fDirp) {
1497 Error("FreeDirectory", "invalid directory pointer (should never happen)");
1498 return;
1499 }
1500
1501 fDirp = 0;
1502}
1503
1504////////////////////////////////////////////////////////////////////////////////
1505/// Get directory entry via httpd. Returns 0 in case no more entries.
1506
1507const char *TWebSystem::GetDirEntry(void *dirp)
1508{
1509 if (dirp != fDirp) {
1510 Error("GetDirEntry", "invalid directory pointer (should never happen)");
1511 return 0;
1512 }
1513
1514 return 0;
1515}
1516
1517////////////////////////////////////////////////////////////////////////////////
1518/// Get info about a file. Info is returned in the form of a FileStat_t
1519/// structure (see TSystem.h).
1520/// The function returns 0 in case of success and 1 if the file could
1521/// not be stat'ed.
1522
1524{
1525 TWebFile *f = new TWebFile(path, "HEADONLY");
1526
1527 if (f->fWritten == 0) {
1528
1529 buf.fDev = 0;
1530 buf.fIno = 0;
1531 buf.fMode = 0;
1532 buf.fUid = 0;
1533 buf.fGid = 0;
1534 buf.fSize = f->GetSize();
1535 buf.fMtime = 0;
1536 buf.fIsLink = kFALSE;
1537
1538 delete f;
1539 return 0;
1540 }
1541
1542 delete f;
1543 return 1;
1544}
1545
1546////////////////////////////////////////////////////////////////////////////////
1547/// Returns FALSE if one can access a file using the specified access mode.
1548/// Mode is the same as for the Unix access(2) function.
1549/// Attention, bizarre convention of return value!!
1550
1552{
1553 TWebFile *f = new TWebFile(path, "HEADONLY");
1554 if (f->fWritten == 0) {
1555 delete f;
1556 return kFALSE;
1557 }
1558 delete f;
1559 return kTRUE;
1560}
1561
1562////////////////////////////////////////////////////////////////////////////////
1563/// Unlink, i.e. remove, a file or directory. Returns 0 when successful,
1564/// -1 in case of failure. Not supported for httpd.
1565
1567{
1568 return -1;
1569}
#define f(i)
Definition RSha256.hxx:104
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition RtypesCore.h:45
constexpr Int_t kMaxInt
Definition RtypesCore.h:112
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
static const std::string gUserAgent
#define gDirectory
Definition TDirectory.h:386
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:230
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:197
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:241
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Int_t gDebug
Definition TROOT.cxx:585
#define gROOT
Definition TROOT.h:405
@ kDontBlock
Definition TSystem.h:232
@ kPeek
Definition TSystem.h:231
EAccessMode
Definition TSystem.h:43
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define gPerfStats
static const char * gUserAgent
Definition TWebFile.cxx:46
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
static TString Encode(const char *data)
Transform data into a null terminated base64 string.
Definition TBase64.cxx:107
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:51
static std::atomic< Long64_t > fgBytesRead
Number of bytes read by all TFile objects.
Definition TFile.h:129
Int_t fReadCalls
Number of read calls ( not counting the cache calls )
Definition TFile.h:87
Long64_t fBytesRead
Number of bytes read from this file.
Definition TFile.h:74
static void SetFileBytesRead(Long64_t bytes=0)
Definition TFile.cxx:4578
static void SetFileReadCalls(Int_t readcalls=0)
Definition TFile.cxx:4584
TUrl fUrl
!URL of file
Definition TFile.h:108
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4544
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition TFile.cxx:1853
Long64_t fArchiveOffset
!Offset at which file starts in archive
Definition TFile.h:99
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition TFile.cxx:589
ERelativeTo
Definition TFile.h:190
@ kCur
Definition TFile.h:190
@ kBeg
Definition TFile.h:190
@ kEnd
Definition TFile.h:190
Int_t fD
File descriptor.
Definition TFile.h:80
Bool_t fIsRootFile
!True is this is a ROOT file, raw file otherwise
Definition TFile.h:102
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TFile.cxx:2217
Long64_t fOffset
!Seek offset cache
Definition TFile.h:94
Long64_t fEND
Last used byte in file.
Definition TFile.h:77
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:914
static std::atomic< Int_t > fgReadCalls
Number of bytes read from all TFile objects.
Definition TFile.h:131
Int_t fWritten
Number of objects written so far.
Definition TFile.h:85
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4561
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
void MakeZombie()
Definition TObject.h:53
virtual Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition TSocket.cxx:898
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition TSocket.cxx:620
virtual Bool_t IsValid() const
Definition TSocket.h:132
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1966
const char * Data() const
Definition TString.h:380
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kIgnoreCase
Definition TString.h:279
void ToUpper()
Change string to upper case.
Definition TString.cxx:1183
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:627
Bool_t IsNull() const
Definition TString.h:418
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Long64_t Atoll() const
Return long long value of string.
Definition TString.cxx:1992
Abstract base class defining a generic interface to the underlying Operating System.
Definition TSystem.h:266
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:263
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1666
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:440
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:390
const char * GetFile() const
Definition TUrl.h:69
void SetUrl(const char *url, Bool_t defaultIsFile=kFALSE)
Parse url character string and split in its different subcomponents.
Definition TUrl.cxx:110
Bool_t IsValid() const
Definition TUrl.h:79
const char * GetUser() const
Definition TUrl.h:65
const char * GetHost() const
Definition TUrl.h:67
const char * GetPasswd() const
Definition TUrl.h:66
const char * GetOptions() const
Definition TUrl.h:71
const char * GetProtocol() const
Definition TUrl.h:64
Int_t GetPort() const
Definition TUrl.h:78
virtual Int_t GetLine(TSocket *s, char *line, Int_t maxsize)
Read a line from the socket.
virtual ~TWebFile()
Cleanup.
Definition TWebFile.cxx:199
virtual Int_t GetHead()
Get the HTTP header.
virtual Int_t GetFromWeb(char *buf, Int_t len, const TString &msg)
Read request from web server.
Definition TWebFile.cxx:626
virtual TString BasicAuthentication()
Return basic authentication scheme, to be added to the request.
Long64_t fSize
Definition TWebFile.h:42
TSocket * fSocket
Definition TWebFile.h:43
static const char * GetProxy()
Static method returning the global proxy URL.
TString fBasicUrl
Definition TWebFile.h:51
static void SetProxy(const char *url)
Static method setting global proxy URL.
virtual const char * HttpTerminator(const char *start, const char *peeked, Int_t peeklen)
Determine whether [START, PEEKED + PEEKLEN) contains an HTTP new line [\r]\n.
Long64_t GetSize() const override
Return maximum file size.
virtual Int_t GetFromCache(char *buf, Int_t len, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
Extract requested segments from the cached content.
Definition TWebFile.cxx:601
TString fBasicUrlOrg
Definition TWebFile.h:53
Bool_t IsOpen() const override
A TWebFile that has been correctly constructed is always considered open.
Definition TWebFile.cxx:380
Bool_t fHTTP11
Definition TWebFile.h:46
virtual void CheckProxy()
Check if shell var "http_proxy" has been set and should be used.
Definition TWebFile.cxx:353
virtual Bool_t ReadBuffers10(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
Read specified byte ranges from remote file via HTTP 1.0 daemon (without mod-root installed).
Definition TWebFile.cxx:567
Bool_t ReadBuffer(char *buf, Int_t len) override
Read specified byte range from remote file via HTTP daemon.
Definition TWebFile.cxx:430
Long64_t fFullCacheSize
complete content of the file, some http server may return complete content
Definition TWebFile.h:55
Bool_t ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) override
Read specified byte ranges from remote file via HTTP daemon.
Definition TWebFile.cxx:518
TUrl fProxy
Definition TWebFile.h:44
TString fMsgGetHead
Definition TWebFile.h:50
void Seek(Long64_t offset, ERelativeTo pos=kBeg) override
Set position from where to start reading.
Definition TWebFile.cxx:990
TString fMsgReadBuffer
Definition TWebFile.h:48
virtual Bool_t ReadBuffer10(char *buf, Int_t len)
Read specified byte range from remote file via HTTP 1.0 daemon (without mod-root installed).
Definition TWebFile.cxx:479
void Init(Bool_t readHeadOnly) override
Initialize a TWebFile object.
Definition TWebFile.cxx:212
virtual Int_t GetFromWeb10(char *buf, Int_t len, const TString &msg, Int_t nseg=0, Long64_t *seg_pos=nullptr, Int_t *seg_len=nullptr)
Read multiple byte range request from web server.
Definition TWebFile.cxx:693
TWebFile()
Definition TWebFile.h:39
static TUrl fgProxy
size of the cached content
Definition TWebFile.h:57
void * fFullCache
Definition TWebFile.h:54
static void SetMaxFullCacheSize(Long64_t sz)
Static method, set maxmimal size of full cache,.
virtual void SetMsgReadBuffer10(const char *redirectLocation=nullptr, Bool_t tempRedirect=kFALSE)
Set GET command for use by ReadBuffer(s)10(), handle redirection if needed.
Definition TWebFile.cxx:268
TString fMsgReadBuffer10
Definition TWebFile.h:49
TUrl fUrlOrg
Definition TWebFile.h:52
Int_t ReOpen(Option_t *mode) override
Reopen a file with a different access mode, like from READ to UPDATE or from NEW, CREATE,...
Definition TWebFile.cxx:394
static Long64_t GetMaxFullCacheSize()
Static method returning maxmimal size of full cache, which can be preserved by file instance.
Bool_t fHasModRoot
Definition TWebFile.h:45
virtual void ProcessHttpHeader(const TString &headerLine)
Process the HTTP header in the argument.
void Close(Option_t *option="") override
Close a Web file.
Definition TWebFile.cxx:412
virtual Int_t GetHunk(TSocket *s, char *hunk, Int_t maxsize)
Read a hunk of data from the socket, up until a terminator.
static Long64_t fgMaxFullCacheSize
Definition TWebFile.h:58
Bool_t fNoProxy
Definition TWebFile.h:47
TWebFile * fWebFile
Definition TWebFile.cxx:57
~TWebSocket()
Close socket in case not HTTP/1.1 protocol or when explicitly requested.
Definition TWebFile.cxx:77
void ReOpen()
Re-open web file socket.
Definition TWebFile.cxx:88
TWebSocket(TWebFile *f)
Open web file socket.
Definition TWebFile.cxx:67
void * OpenDirectory(const char *name) override
Open a directory via httpd.
Int_t MakeDirectory(const char *name) override
Make a directory via httpd. Not supported.
TWebSystem()
Create helper class that allows directory access via httpd.
void FreeDirectory(void *dirp) override
Free directory via httpd.
Bool_t AccessPathName(const char *path, EAccessMode mode) override
Returns FALSE if one can access a file using the specified access mode.
void * fDirp
Definition TWebFile.h:102
Int_t GetPathInfo(const char *path, FileStat_t &buf) override
Get info about a file.
const char * GetDirEntry(void *dirp) override
Get directory entry via httpd. Returns 0 in case no more entries.
Int_t Unlink(const char *path) override
Unlink, i.e.
TLine * line
const Int_t n
Definition legend1.C:16
Definition first.py:1
Int_t fMode
Definition TSystem.h:127
Long64_t fSize
Definition TSystem.h:130
Long_t fDev
Definition TSystem.h:125
Int_t fGid
Definition TSystem.h:129
Long_t fMtime
Definition TSystem.h:131
Long_t fIno
Definition TSystem.h:126
Bool_t fIsLink
Definition TSystem.h:132
Int_t fUid
Definition TSystem.h:128