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/// Read specified byte range from remote file via HTTP daemon. This
410/// routine connects to the remote host, sends the request and returns
411/// the buffer. Returns kTRUE in case of error.
412
414{
415 Int_t st;
416 if ((st = ReadBufferViaCache(buf, len))) {
417 if (st == 2)
418 return kTRUE;
419 return kFALSE;
420 }
421
422 if (!fHasModRoot)
423 return ReadBuffer10(buf, len);
424
425 // Give full URL so Apache's virtual hosts solution works.
426 // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
427 if (fMsgReadBuffer == "") {
428 fMsgReadBuffer = "GET ";
430 fMsgReadBuffer += "?";
431 }
433 msg += fOffset;
434 msg += ":";
435 msg += len;
436 msg += "\r\n";
437
438 if (GetFromWeb(buf, len, msg) == -1)
439 return kTRUE;
440
441 fOffset += len;
442
443 return kFALSE;
444}
445
446////////////////////////////////////////////////////////////////////////////////
447/// Read specified byte range from remote file via HTTP daemon. This
448/// routine connects to the remote host, sends the request and returns
449/// the buffer. Returns kTRUE in case of error.
450
452{
453 SetOffset(pos);
454 return ReadBuffer(buf, len);
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Read specified byte range from remote file via HTTP 1.0 daemon (without
459/// mod-root installed). This routine connects to the remote host, sends the
460/// request and returns the buffer. Returns kTRUE in case of error.
461
463{
465
467 msg += fOffset;
468 msg += "-";
469 msg += fOffset+len-1;
470 msg += "\r\n\r\n";
471
473
474 // in case when server does not support segments, let chance to recover
475 Int_t n = GetFromWeb10(buf, len, msg, 1, &apos, &len);
476 if (n == -1)
477 return kTRUE;
478 // The -2 error condition typically only happens when
479 // GetHead() failed because not implemented, in the first call to
480 // ReadBuffer() in Init(), it is not checked in ReadBuffers10().
481 if (n == -2) {
482 Error("ReadBuffer10", "%s does not exist", fBasicUrl.Data());
483 MakeZombie();
485 return kTRUE;
486 }
487
488 fOffset += len;
489
490 return kFALSE;
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// Read specified byte ranges from remote file via HTTP daemon.
495/// Reads the nbuf blocks described in arrays pos and len,
496/// where pos[i] is the seek position of block i of length len[i].
497/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
498/// This function is overloaded by TNetFile, TWebFile, etc.
499/// Returns kTRUE in case of failure.
500
501Bool_t TWebFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
502{
503 if (!fHasModRoot)
504 return ReadBuffers10(buf, pos, len, nbuf);
505
506 // Give full URL so Apache's virtual hosts solution works.
507 // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
508 if (fMsgReadBuffer == "") {
509 fMsgReadBuffer = "GET ";
511 fMsgReadBuffer += "?";
512 }
514
515 Int_t k = 0, n = 0, cnt = 0;
516 for (Int_t i = 0; i < nbuf; i++) {
517 if (n) msg += ",";
518 msg += pos[i] + fArchiveOffset;
519 msg += ":";
520 msg += len[i];
521 n += len[i];
522 cnt++;
523 if ((msg.Length() > 8000) || (cnt >= 200)) {
524 msg += "\r\n";
525 if (GetFromWeb(&buf[k], n, msg) == -1)
526 return kTRUE;
527 msg = fMsgReadBuffer;
528 k += n;
529 n = 0;
530 cnt = 0;
531 }
532 }
533
534 msg += "\r\n";
535
536 if (GetFromWeb(&buf[k], n, msg) == -1)
537 return kTRUE;
538
539 return kFALSE;
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Read specified byte ranges from remote file via HTTP 1.0 daemon (without
544/// mod-root installed). Read the nbuf blocks described in arrays pos and len,
545/// where pos[i] is the seek position of block i of length len[i].
546/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
547/// This function is overloaded by TNetFile, TWebFile, etc.
548/// Returns kTRUE in case of failure.
549
551{
553
555
556 Int_t k = 0, n = 0, r, cnt = 0;
557 for (Int_t i = 0; i < nbuf; i++) {
558 if (n) msg += ",";
559 msg += pos[i] + fArchiveOffset;
560 msg += "-";
561 msg += pos[i] + fArchiveOffset + len[i] - 1;
562 n += len[i];
563 cnt++;
564 if ((msg.Length() > 8000) || (cnt >= 200) || (i+1 == nbuf)) {
565 msg += "\r\n\r\n";
566 r = GetFromWeb10(&buf[k], n, msg, cnt, pos + (i+1-cnt), len + (i+1-cnt));
567 if (r == -1)
568 return kTRUE;
569 msg = fMsgReadBuffer10;
570 k += n;
571 n = 0;
572 cnt = 0;
573 }
574 }
575
576 return kFALSE;
577}
578
579////////////////////////////////////////////////////////////////////////////////
580/// Extract requested segments from the cached content.
581/// Such cache can be produced when server suddenly returns full data instead of segments
582/// Returns -1 in case of error, 0 in case of success
583
584Int_t TWebFile::GetFromCache(char *buf, Int_t len, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
585{
586 if (!fFullCache) return -1;
587
588 if (gDebug > 0)
589 Info("GetFromCache", "Extract %d segments total len %d from cached data", nseg, len);
590
591 Int_t curr = 0;
592 for (Int_t cnt=0;cnt<nseg;cnt++) {
593 // check that target buffer has enough space
594 if (curr + seg_len[cnt] > len) return -1;
595 // check that segment is inside cached area
596 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fFullCacheSize) return -1;
597 char* src = (char*) fFullCache + fArchiveOffset + seg_pos[cnt];
598 memcpy(buf + curr, src, seg_len[cnt]);
599 curr += seg_len[cnt];
600 }
601
602 return 0;
603}
604
605////////////////////////////////////////////////////////////////////////////////
606/// Read request from web server. Returns -1 in case of error,
607/// 0 in case of success.
608
609Int_t TWebFile::GetFromWeb(char *buf, Int_t len, const TString &msg)
610{
611 TSocket *s;
612
613 if (!len) return 0;
614
615 Double_t start = 0;
616 if (gPerfStats) start = TTimeStamp();
617
618 TUrl connurl;
619 if (fProxy.IsValid())
620 connurl = fProxy;
621 else
622 connurl = fUrl;
623
624 if (strcmp(connurl.GetProtocol(), "https") == 0) {
625#ifdef R__SSL
626 s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
627#else
628 Error("GetFromWeb", "library compiled without SSL, https not supported");
629 return -1;
630#endif
631 } else
632 s = new TSocket(connurl.GetHost(), connurl.GetPort());
633
634 if (!s->IsValid()) {
635 Error("GetFromWeb", "cannot connect to host %s", fUrl.GetHost());
636 delete s;
637 return -1;
638 }
639
640 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
641 Error("GetFromWeb", "error sending command to host %s", fUrl.GetHost());
642 delete s;
643 return -1;
644 }
645
646 if (s->RecvRaw(buf, len) == -1) {
647 Error("GetFromWeb", "error receiving data from host %s", fUrl.GetHost());
648 delete s;
649 return -1;
650 }
651
652 // collect statistics
653 fBytesRead += len;
654 fReadCalls++;
655#ifdef R__WIN32
658#else
659 fgBytesRead += len;
660 fgReadCalls++;
661#endif
662
663 if (gPerfStats)
664 gPerfStats->FileReadEvent(this, len, start);
665
666 delete s;
667 return 0;
668}
669
670////////////////////////////////////////////////////////////////////////////////
671/// Read multiple byte range request from web server.
672/// Uses HTTP 1.0 daemon wihtout mod-root.
673/// Returns -2 in case file does not exist, -1 in case
674/// of error and 0 in case of success.
675
676Int_t TWebFile::GetFromWeb10(char *buf, Int_t len, const TString &msg, Int_t nseg, Long64_t *seg_pos, Int_t *seg_len)
677{
678 if (!len) return 0;
679
680 // if file content was cached, reuse it
681 if (fFullCache && (nseg>0))
682 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
683
684 Double_t start = 0;
685 if (gPerfStats) start = TTimeStamp();
686
687 // open fSocket and close it when going out of scope
688 TWebSocket ws(this);
689
690 if (!fSocket || !fSocket->IsValid()) {
691 Error("GetFromWeb10", "cannot connect to host %s", fUrl.GetHost());
692 return -1;
693 }
694
695 if (gDebug > 0)
696 Info("GetFromWeb10", "sending HTTP request:\n%s", msg.Data());
697
698 if (fSocket->SendRaw(msg.Data(), msg.Length()) == -1) {
699 Error("GetFromWeb10", "error sending command to host %s", fUrl.GetHost());
700 return -1;
701 }
702
703 char line[8192];
704 Int_t n, ret = 0, nranges = 0, ltot = 0, redirect = 0;
705 TString boundary, boundaryEnd;
706 Long64_t first = -1, last = -1, tot, fullsize = 0;
707 TString redir;
708
709 while ((n = GetLine(fSocket, line, sizeof(line))) >= 0) {
710 if (n == 0) {
711 if (ret < 0)
712 return ret;
713 if (redirect) {
714 if (redir.IsNull()) {
715 // Some sites (s3.amazonaws.com) do not return a Location field on 301
716 Error("GetFromWeb10", "error - redirect without location from host %s", fUrl.GetHost());
717 return -1;
718 }
719
720 ws.ReOpen();
721 // set message to reflect the redirectLocation and add bytes field
723 msg_1 += fOffset;
724 msg_1 += "-";
725 msg_1 += fOffset+len-1;
726 msg_1 += "\r\n\r\n";
727 return GetFromWeb10(buf, len, msg_1);
728 }
729
730 if (first >= 0) {
731 Int_t ll = Int_t(last - first) + 1;
732 Int_t rsize;
733 if ((rsize = fSocket->RecvRaw(&buf[ltot], ll)) == -1) {
734 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
735 return -1;
736 }
737 else if (ll != rsize) {
738 Error("GetFromWeb10", "expected %d bytes, got %d", ll, rsize);
739 return -1;
740 }
741 ltot += ll;
742
743 first = -1;
744
745 if (boundary == "")
746 break; // not a multipart response
747 }
748
749 if (fullsize > 0) {
750
751 if (nseg <= 0) {
752 Error("GetFromWeb10","Need segments data to extract parts from full size %lld", fullsize);
753 return -1;
754 }
755
756 if (len > fullsize) {
757 Error("GetFromWeb10","Requested part %d longer than full size %lld", len, fullsize);
758 return -1;
759 }
760
761 if ((fFullCache == 0) && (fullsize <= GetMaxFullCacheSize())) {
762 // try to read file content into cache and than reuse it, limit cache by 2 GB
763 fFullCache = malloc(fullsize);
764 if (fFullCache != 0) {
765 if (fSocket->RecvRaw(fFullCache, fullsize) != fullsize) {
766 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
768 return -1;
769 }
770 fFullCacheSize = fullsize;
771 return GetFromCache(buf, len, nseg, seg_pos, seg_len);
772 }
773 // when cache allocation failed, try without cache
774 }
775
776 // check all segemnts are inside range and in sorted order
777 for (Int_t cnt=0;cnt<nseg;cnt++) {
778 if (fArchiveOffset + seg_pos[cnt] + seg_len[cnt] > fullsize) {
779 Error("GetFromWeb10","Requested segment %lld len %d is outside of full range %lld", seg_pos[cnt], seg_len[cnt], fullsize);
780 return -1;
781 }
782 if ((cnt>0) && (seg_pos[cnt-1] + seg_len[cnt-1] > seg_pos[cnt])) {
783 Error("GetFromWeb10","Requested segments are not in sorted order");
784 return -1;
785 }
786 }
787
788 Long64_t pos = 0;
789 char* curr = buf;
790 char dbuf[2048]; // dummy buffer for skip data
791
792 // now read complete file and take only requested segments into the buffer
793 for (Int_t cnt=0; cnt<nseg; cnt++) {
794 // first skip data before segment
795 while (pos < fArchiveOffset + seg_pos[cnt]) {
796 Long64_t ll = fArchiveOffset + seg_pos[cnt] - pos;
797 if (ll > Int_t(sizeof(dbuf))) ll = sizeof(dbuf);
798 if (fSocket->RecvRaw(dbuf, ll) != ll) {
799 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
800 return -1;
801 }
802 pos += ll;
803 }
804
805 // reading segment itself
806 if (fSocket->RecvRaw(curr, seg_len[cnt]) != seg_len[cnt]) {
807 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
808 return -1;
809 }
810 curr += seg_len[cnt];
811 pos += seg_len[cnt];
812 ltot += seg_len[cnt];
813 }
814
815 // now read file to the end
816 while (pos < fullsize) {
817 Long64_t ll = fullsize - pos;
818 if (ll > Int_t(sizeof(dbuf))) ll = sizeof(dbuf);
819 if (fSocket->RecvRaw(dbuf, ll) != ll) {
820 Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
821 return -1;
822 }
823 pos += ll;
824 }
825
826 if (gDebug>0) Info("GetFromWeb10","Complete reading %d bytes in %d segments out of full size %lld", len, nseg, fullsize);
827
828 break;
829 }
830
831 continue;
832 }
833
834 if (gDebug > 0)
835 Info("GetFromWeb10", "header: %s", line);
836
837 if (boundaryEnd == line) {
838 if (gDebug > 0)
839 Info("GetFromWeb10", "got all headers");
840 break;
841 }
842 if (boundary == line) {
843 nranges++;
844 if (gDebug > 0)
845 Info("GetFromWeb10", "get new multipart byte range (%d)", nranges);
846 }
847
848 TString res = line;
849
850 if (res.BeginsWith("HTTP/1.")) {
851 if (res.BeginsWith("HTTP/1.1")) {
852 if (!fHTTP11)
853 fMsgReadBuffer10 = "";
854 fHTTP11 = kTRUE;
855 }
856 TString scode = res(9, 3);
857 Int_t code = scode.Atoi();
858 if (code >= 500) {
859 ret = -1;
860 TString mess = res(13, 1000);
861 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
862 } else if (code >= 400) {
863 if (code == 404)
864 ret = -2; // file does not exist
865 else {
866 ret = -1;
867 TString mess = res(13, 1000);
868 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
869 }
870 } else if (code >= 300) {
871 if (code == 301 || code == 303) {
872 redirect = 1; // permanent redirect
873 } else if (code == 302 || code == 307) {
874 // treat 302 as 303: permanent redirect
875 redirect = 1;
876 //redirect = 2; // temp redirect
877 } else {
878 ret = -1;
879 TString mess = res(13, 1000);
880 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
881 }
882 } else if (code > 200) {
883 if (code != 206) {
884 ret = -1;
885 TString mess = res(13, 1000);
886 Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
887 }
888 } else if (code == 200) {
889 fullsize = -200; // make indication of code 200
890 Warning("GetFromWeb10",
891 "Server %s response with complete file, but only part of it was requested.\n"
892 "Check MaxRanges configuration parameter (if Apache is used)",
893 fUrl.GetHost());
894
895 }
896 } else if (res.BeginsWith("Content-Type: multipart")) {
897 boundary = res(res.Index("boundary=")+9, 1000);
898 if (boundary[0]=='"' && boundary[boundary.Length()-1]=='"') {
899 boundary = boundary(1,boundary.Length()-2);
900 }
901 boundary = "--" + boundary;
902 boundaryEnd = boundary + "--";
903 } else if (res.BeginsWith("Content-range:")) {
904#ifdef R__WIN32
905 sscanf(res.Data(), "Content-range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
906#else
907 sscanf(res.Data(), "Content-range: bytes %lld-%lld/%lld", &first, &last, &tot);
908#endif
909 if (fSize == -1) fSize = tot;
910 } else if (res.BeginsWith("Content-Range:")) {
911#ifdef R__WIN32
912 sscanf(res.Data(), "Content-Range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
913#else
914 sscanf(res.Data(), "Content-Range: bytes %lld-%lld/%lld", &first, &last, &tot);
915#endif
916 if (fSize == -1) fSize = tot;
917 } else if (res.BeginsWith("Content-Length:") && (fullsize == -200)) {
918#ifdef R__WIN32
919 sscanf(res.Data(), "Content-Length: %I64d", &fullsize);
920#else
921 sscanf(res.Data(), "Content-Length: %lld", &fullsize);
922#endif
923 } else if (res.BeginsWith("Location:") && redirect) {
924 redir = res(10, 1000);
925 if (redirect == 2) // temp redirect
927 else // permanent redirect
929 }
930 }
931
932 if (redirect && redir.IsNull()) {
933 Error("GetFromWeb10", "error - redirect without location from host %s", fUrl.GetHost());
934 }
935
936 if (n == -1 && fHTTP11) {
937 if (gDebug > 0)
938 Info("GetFromWeb10", "HTTP/1.1 socket closed, reopen");
939 if (fBasicUrlOrg != "") {
940 // if we have to close temp redirection, set back to original url
942 }
943 ws.ReOpen();
944 return GetFromWeb10(buf, len, msg);
945 }
946
947 if (ltot != len) {
948 Error("GetFromWeb10", "error receiving expected amount of data (got %d, expected %d) from host %s",
949 ltot, len, fUrl.GetHost());
950 return -1;
951 }
952
953 // collect statistics
954 fBytesRead += len;
955 fReadCalls++;
956#ifdef R__WIN32
959#else
960 fgBytesRead += len;
961 fgReadCalls++;
962#endif
963
964 if (gPerfStats)
965 gPerfStats->FileReadEvent(this, len, start);
966
967 return 0;
968}
969
970////////////////////////////////////////////////////////////////////////////////
971/// Set position from where to start reading.
972
974{
975 switch (pos) {
976 case kBeg:
977 fOffset = offset + fArchiveOffset;
978 break;
979 case kCur:
980 fOffset += offset;
981 break;
982 case kEnd:
983 // this option is not used currently in the ROOT code
984 if (fArchiveOffset)
985 Error("Seek", "seeking from end in archive is not (yet) supported");
986 fOffset = fEND - offset; // is fEND really EOF or logical EOF?
987 break;
988 }
989}
990
991////////////////////////////////////////////////////////////////////////////////
992/// Return maximum file size.
993
995{
996 if (!fHasModRoot || fSize >= 0)
997 return fSize;
998
1000 char asize[64];
1001
1002 TString msg = "GET ";
1003 msg += fBasicUrl;
1004 msg += "?";
1005 msg += -1;
1006 msg += "\r\n";
1007
1008 if (const_cast<TWebFile*>(this)->GetFromWeb(asize, 64, msg) == -1)
1009 return kMaxInt;
1010
1011#ifndef R__WIN32
1012 size = atoll(asize);
1013#else
1014 size = _atoi64(asize);
1015#endif
1016
1017 fSize = size;
1018
1019 return size;
1020}
1021
1022////////////////////////////////////////////////////////////////////////////////
1023/// Get the HTTP header. Depending on the return code we can see if
1024/// the file exists and if the server uses mod_root.
1025/// Returns -1 in case of an error, -2 in case the file does not exists,
1026/// -3 in case HEAD is not supported (dCache HTTP door) and
1027/// 0 in case of success.
1028
1030{
1031 // Give full URL so Apache's virtual hosts solution works.
1032 if (fMsgGetHead == "") {
1033 fMsgGetHead = "HEAD ";
1035 if (fHTTP11)
1036 fMsgGetHead += " HTTP/1.1";
1037 else
1038 fMsgGetHead += " HTTP/1.0";
1039 fMsgGetHead += "\r\n";
1040 if (fHTTP11) {
1041 fMsgGetHead += "Host: ";
1043 fMsgGetHead += "\r\n";
1044 }
1047 fMsgGetHead += "\r\n\r\n";
1048 }
1049 TString msg = fMsgGetHead;
1050
1051 TUrl connurl;
1052 if (fProxy.IsValid())
1053 connurl = fProxy;
1054 else
1055 connurl = fUrl;
1056
1057 TSocket *s = 0;
1058 for (Int_t i = 0; i < 5; i++) {
1059 if (strcmp(connurl.GetProtocol(), "https") == 0) {
1060#ifdef R__SSL
1061 s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
1062#else
1063 Error("GetHead", "library compiled without SSL, https not supported");
1064 return -1;
1065#endif
1066 } else
1067 s = new TSocket(connurl.GetHost(), connurl.GetPort());
1068
1069 if (!s->IsValid()) {
1070 delete s;
1071 if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
1072 s = 0;
1073 gSystem->Sleep(i*10);
1074 } else {
1075 Error("GetHead", "cannot connect to host %s (errno=%d)", fUrl.GetHost(),
1076 gSystem->GetErrno());
1077 return -1;
1078 }
1079 } else
1080 break;
1081 }
1082 if (!s)
1083 return -1;
1084
1085 if (gDebug > 0) {
1086 Info("GetHead", "connected to host %s", connurl.GetHost());
1087 Info("GetHead", "sending HTTP request:\n%s", msg.Data());
1088 }
1089
1090 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
1091 Error("GetHead", "error sending command to host %s", fUrl.GetHost());
1092 delete s;
1093 return -1;
1094 }
1095
1096 char line[8192];
1097 Int_t n, ret = 0, redirect = 0;
1098 TString redir;
1099
1100 while ((n = GetLine(s, line, sizeof(line))) >= 0) {
1101 if (n == 0) {
1102 if (gDebug > 0)
1103 Info("GetHead", "got all headers");
1104 delete s;
1105 if (fBasicUrlOrg != "" && !redirect) {
1106 // set back to original url in case of temp redirect
1108 fMsgGetHead = "";
1109 }
1110 if (ret < 0)
1111 return ret;
1112 if (redirect) {
1113 if (redir.IsNull()) {
1114 // Some sites (s3.amazonaws.com) do not return a Location field on 301
1115 Error("GetHead", "error - redirect without location from host %s", fUrl.GetHost());
1116 return -1;
1117 }
1118 return GetHead();
1119 }
1120 return 0;
1121 }
1122
1123 if (gDebug > 0)
1124 Info("GetHead", "header: %s", line);
1125
1126 TString res = line;
1127 ProcessHttpHeader(res);
1128 if (res.BeginsWith("HTTP/1.")) {
1129 if (res.BeginsWith("HTTP/1.1")) {
1130 if (!fHTTP11) {
1131 fMsgGetHead = "";
1132 fMsgReadBuffer10 = "";
1133 }
1134 fHTTP11 = kTRUE;
1135 }
1136 TString scode = res(9, 3);
1137 Int_t code = scode.Atoi();
1138 if (code >= 500) {
1139 if (code == 500)
1141 else {
1142 ret = -1;
1143 TString mess = res(13, 1000);
1144 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1145 }
1146 } else if (code >= 400) {
1147 if (code == 400)
1148 ret = -3; // command not supported
1149 else if (code == 404)
1150 ret = -2; // file does not exist
1151 else {
1152 ret = -1;
1153 TString mess = res(13, 1000);
1154 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1155 }
1156 } else if (code >= 300) {
1157 if (code == 301 || code == 303)
1158 redirect = 1; // permanent redirect
1159 else if (code == 302 || code == 307)
1160 redirect = 2; // temp redirect
1161 else {
1162 ret = -1;
1163 TString mess = res(13, 1000);
1164 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1165 }
1166 } else if (code > 200) {
1167 ret = -1;
1168 TString mess = res(13, 1000);
1169 Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
1170 }
1171 } else if (res.BeginsWith("Content-Length:")) {
1172 TString slen = res(16, 1000);
1173 fSize = slen.Atoll();
1174 } else if (res.BeginsWith("Location:") && redirect) {
1175 redir = res(10, 1000);
1176 if (redirect == 2) // temp redirect
1177 SetMsgReadBuffer10(redir, kTRUE);
1178 else // permanent redirect
1179 SetMsgReadBuffer10(redir, kFALSE);
1180 fMsgGetHead = "";
1181 }
1182 }
1183
1184 delete s;
1185
1186 return ret;
1187}
1188
1189////////////////////////////////////////////////////////////////////////////////
1190/// Read a line from the socket. Reads at most one less than the number of
1191/// characters specified by maxsize. Reading stops when a newline character
1192/// is found, The newline (\n) and cr (\r), if any, are removed.
1193/// Returns -1 in case of error, or the number of characters read (>= 0)
1194/// otherwise.
1195
1197{
1198 Int_t n = GetHunk(s, line, maxsize);
1199 if (n < 0) {
1200 if (!fHTTP11 || gDebug > 0)
1201 Error("GetLine", "error receiving data from host %s", fUrl.GetHost());
1202 return -1;
1203 }
1204
1205 if (n > 0 && line[n-1] == '\n') {
1206 n--;
1207 if (n > 0 && line[n-1] == '\r')
1208 n--;
1209 line[n] = '\0';
1210 }
1211 return n;
1212}
1213
1214////////////////////////////////////////////////////////////////////////////////
1215/// Read a hunk of data from the socket, up until a terminator. The hunk is
1216/// limited by whatever the TERMINATOR callback chooses as its
1217/// terminator. For example, if terminator stops at newline, the hunk
1218/// will consist of a line of data; if terminator stops at two
1219/// newlines, it can be used to read the head of an HTTP response.
1220/// Upon determining the boundary, the function returns the data (up to
1221/// the terminator) in hunk.
1222///
1223/// In case of read error, -1 is returned. In case of having read some
1224/// data, but encountering EOF before seeing the terminator, the data
1225/// that has been read is returned, but it will (obviously) not contain the
1226/// terminator.
1227///
1228/// The TERMINATOR function is called with three arguments: the
1229/// beginning of the data read so far, the beginning of the current
1230/// block of peeked-at data, and the length of the current block.
1231/// Depending on its needs, the function is free to choose whether to
1232/// analyze all data or just the newly arrived data. If TERMINATOR
1233/// returns 0, it means that the terminator has not been seen.
1234/// Otherwise it should return a pointer to the character immediately
1235/// following the terminator.
1236///
1237/// The idea is to be able to read a line of input, or otherwise a hunk
1238/// of text, such as the head of an HTTP request, without crossing the
1239/// boundary, so that the next call to RecvRaw() etc. reads the data
1240/// after the hunk. To achieve that, this function does the following:
1241///
1242/// 1. Peek at incoming data.
1243///
1244/// 2. Determine whether the peeked data, along with the previously
1245/// read data, includes the terminator.
1246///
1247/// 3a. If yes, read the data until the end of the terminator, and
1248/// exit.
1249///
1250/// 3b. If no, read the peeked data and goto 1.
1251///
1252/// The function is careful to assume as little as possible about the
1253/// implementation of peeking. For example, every peek is followed by
1254/// a read. If the read returns a different amount of data, the
1255/// process is retried until all data arrives safely.
1256///
1257/// Reads at most one less than the number of characters specified by maxsize.
1258
1259Int_t TWebFile::GetHunk(TSocket *s, char *hunk, Int_t maxsize)
1260{
1261 if (maxsize <= 0) return 0;
1262
1263 Int_t bufsize = maxsize;
1264 Int_t tail = 0; // tail position in HUNK
1265
1266 while (1) {
1267 const char *end;
1268 Int_t pklen, rdlen, remain;
1269
1270 // First, peek at the available data.
1271 pklen = s->RecvRaw(hunk+tail, bufsize-1-tail, kPeek);
1272 if (pklen < 0) {
1273 return -1;
1274 }
1275 end = HttpTerminator(hunk, hunk+tail, pklen);
1276 if (end) {
1277 // The data contains the terminator: we'll drain the data up
1278 // to the end of the terminator.
1279 remain = end - (hunk + tail);
1280 if (remain == 0) {
1281 // No more data needs to be read.
1282 hunk[tail] = '\0';
1283 return tail;
1284 }
1285 if (bufsize - 1 < tail + remain) {
1286 Error("GetHunk", "hunk buffer too small for data from host %s (%d bytes needed)",
1287 fUrl.GetHost(), tail + remain + 1);
1288 hunk[tail] = '\0';
1289 return -1;
1290 }
1291 } else {
1292 // No terminator: simply read the data we know is (or should
1293 // be) available.
1294 remain = pklen;
1295 }
1296
1297 // Now, read the data. Note that we make no assumptions about
1298 // how much data we'll get. (Some TCP stacks are notorious for
1299 // read returning less data than the previous MSG_PEEK.)
1300 rdlen = s->RecvRaw(hunk+tail, remain, kDontBlock);
1301 if (rdlen < 0) {
1302 return -1;
1303 }
1304 tail += rdlen;
1305 hunk[tail] = '\0';
1306
1307 if (rdlen == 0) {
1308 // in case of EOF: return the data we've read.
1309 return tail;
1310 }
1311 if (end && rdlen == remain) {
1312 // The terminator was seen and the remaining data drained --
1313 // we got what we came for.
1314 return tail;
1315 }
1316
1317 // Keep looping until all the data arrives.
1318
1319 if (tail == bufsize - 1) {
1320 Error("GetHunk", "hunk buffer too small for data from host %s",
1321 fUrl.GetHost());
1322 return -1;
1323 }
1324 }
1325}
1326
1327////////////////////////////////////////////////////////////////////////////////
1328/// Determine whether [START, PEEKED + PEEKLEN) contains an HTTP new
1329/// line [\\r]\\n. If so, return the pointer to the position after the line,
1330/// otherwise return 0. This is used as callback to GetHunk(). The data
1331/// between START and PEEKED has been read and cannot be "unread"; the
1332/// data after PEEKED has only been peeked.
1333
1334const char *TWebFile::HttpTerminator(const char *start, const char *peeked,
1335 Int_t peeklen)
1336{
1337#if 0
1338 const char *p, *end;
1339
1340 // Look for "[\r]\n", and return the following position if found.
1341 // Start one char before the current to cover the possibility that
1342 // part of the terminator (e.g. "\r") arrived in the previous batch.
1343 p = peeked - start < 1 ? start : peeked - 1;
1344 end = peeked + peeklen;
1345
1346 // Check for \r\n anywhere in [p, end-2).
1347 for (; p < end - 1; p++)
1348 if (p[0] == '\r' && p[1] == '\n')
1349 return p + 2;
1350
1351 // p==end-1: check for \r\n directly preceding END.
1352 if (p[0] == '\r' && p[1] == '\n')
1353 return p + 2;
1354#else
1355 (void) start; // start unused, silence compiler
1356 if (peeked) {
1357 const char *p = (const char*) memchr(peeked, '\n', peeklen);
1358 if (p)
1359 // p+1 because the line must include '\n'
1360 return p + 1;
1361 }
1362#endif
1363 return nullptr;
1364}
1365
1366////////////////////////////////////////////////////////////////////////////////
1367/// Return basic authentication scheme, to be added to the request.
1368
1370{
1371 TString msg;
1372 if (strlen(fUrl.GetUser())) {
1373 TString auth = fUrl.GetUser();
1374 if (strlen(fUrl.GetPasswd())) {
1375 auth += ":";
1376 auth += fUrl.GetPasswd();
1377 }
1378 msg += "Authorization: Basic ";
1379 msg += TBase64::Encode(auth);
1380 msg += "\r\n";
1381 }
1382 return msg;
1383}
1384
1385////////////////////////////////////////////////////////////////////////////////
1386/// Static method setting global proxy URL.
1387
1388void TWebFile::SetProxy(const char *proxy)
1389{
1390 if (proxy && *proxy) {
1391 TUrl p(proxy);
1392 if (strcmp(p.GetProtocol(), "http")) {
1393 :: Error("TWebFile::SetProxy", "protocol must be HTTP in proxy URL %s",
1394 proxy);
1395 return;
1396 }
1397 fgProxy = p;
1398 }
1399}
1400
1401////////////////////////////////////////////////////////////////////////////////
1402/// Static method returning the global proxy URL.
1403
1405{
1406 if (fgProxy.IsValid())
1407 return fgProxy.GetUrl();
1408 return "";
1409}
1410
1411////////////////////////////////////////////////////////////////////////////////
1412/// Process the HTTP header in the argument. This method is intended to be
1413/// overwritten by subclasses that exploit the information contained in the
1414/// HTTP headers.
1415
1417{
1418}
1419
1420////////////////////////////////////////////////////////////////////////////////
1421/// Static method returning maxmimal size of full cache,
1422/// which can be preserved by file instance
1423
1425{
1426 return fgMaxFullCacheSize;
1427}
1428
1429////////////////////////////////////////////////////////////////////////////////
1430/// Static method, set maxmimal size of full cache,
1431// which can be preserved by file instance
1432
1434{
1435 fgMaxFullCacheSize = sz;
1436}
1437
1438
1439////////////////////////////////////////////////////////////////////////////////
1440/// Create helper class that allows directory access via httpd.
1441/// The name must start with '-' to bypass the TSystem singleton check.
1442
1443TWebSystem::TWebSystem() : TSystem("-http", "HTTP Helper System")
1444{
1445 SetName("http");
1446
1447 fDirp = 0;
1448}
1449
1450////////////////////////////////////////////////////////////////////////////////
1451/// Make a directory via httpd. Not supported.
1452
1454{
1455 return -1;
1456}
1457
1458////////////////////////////////////////////////////////////////////////////////
1459/// Open a directory via httpd. Returns an opaque pointer to a dir
1460/// structure. Returns 0 in case of error.
1461
1462void *TWebSystem::OpenDirectory(const char *)
1463{
1464 if (fDirp) {
1465 Error("OpenDirectory", "invalid directory pointer (should never happen)");
1466 fDirp = 0;
1467 }
1468
1469 fDirp = 0; // not implemented for the time being
1470
1471 return fDirp;
1472}
1473
1474////////////////////////////////////////////////////////////////////////////////
1475/// Free directory via httpd.
1476
1478{
1479 if (dirp != fDirp) {
1480 Error("FreeDirectory", "invalid directory pointer (should never happen)");
1481 return;
1482 }
1483
1484 fDirp = 0;
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////
1488/// Get directory entry via httpd. Returns 0 in case no more entries.
1489
1490const char *TWebSystem::GetDirEntry(void *dirp)
1491{
1492 if (dirp != fDirp) {
1493 Error("GetDirEntry", "invalid directory pointer (should never happen)");
1494 return 0;
1495 }
1496
1497 return 0;
1498}
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// Get info about a file. Info is returned in the form of a FileStat_t
1502/// structure (see TSystem.h).
1503/// The function returns 0 in case of success and 1 if the file could
1504/// not be stat'ed.
1505
1507{
1508 TWebFile *f = new TWebFile(path, "HEADONLY");
1509
1510 if (f->fWritten == 0) {
1511
1512 buf.fDev = 0;
1513 buf.fIno = 0;
1514 buf.fMode = 0;
1515 buf.fUid = 0;
1516 buf.fGid = 0;
1517 buf.fSize = f->GetSize();
1518 buf.fMtime = 0;
1519 buf.fIsLink = kFALSE;
1520
1521 delete f;
1522 return 0;
1523 }
1524
1525 delete f;
1526 return 1;
1527}
1528
1529////////////////////////////////////////////////////////////////////////////////
1530/// Returns FALSE if one can access a file using the specified access mode.
1531/// Mode is the same as for the Unix access(2) function.
1532/// Attention, bizarre convention of return value!!
1533
1535{
1536 TWebFile *f = new TWebFile(path, "HEADONLY");
1537 if (f->fWritten == 0) {
1538 delete f;
1539 return kFALSE;
1540 }
1541 delete f;
1542 return kTRUE;
1543}
1544
1545////////////////////////////////////////////////////////////////////////////////
1546/// Unlink, i.e. remove, a file or directory. Returns 0 when successful,
1547/// -1 in case of failure. Not supported for httpd.
1548
1550{
1551 return -1;
1552}
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
ROOT::R::TRInterface & r
Definition Object.C:4
#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
const Int_t kMaxInt
Definition RtypesCore.h:112
const Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:80
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
static const std::string gUserAgent
#define gDirectory
Definition TDirectory.h:385
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:220
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:231
Int_t gDebug
Definition TROOT.cxx:592
#define gROOT
Definition TROOT.h:404
@ kDontBlock
Definition TSystem.h:232
@ kPeek
Definition TSystem.h:231
EAccessMode
Definition TSystem.h:43
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
#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:54
static std::atomic< Long64_t > fgBytesRead
Number of bytes read by all TFile objects.
Definition TFile.h:132
Int_t fReadCalls
Number of read calls ( not counting the cache calls )
Definition TFile.h:90
Long64_t fBytesRead
Number of bytes read from this file.
Definition TFile.h:77
static void SetFileBytesRead(Long64_t bytes=0)
Definition TFile.cxx:4526
static void SetFileReadCalls(Int_t readcalls=0)
Definition TFile.cxx:4532
TUrl fUrl
!URL of file
Definition TFile.h:111
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4492
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition TFile.cxx:1827
Long64_t fArchiveOffset
!Offset at which file starts in archive
Definition TFile.h:102
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition TFile.cxx:574
ERelativeTo
Definition TFile.h:193
@ kCur
Definition TFile.h:193
@ kBeg
Definition TFile.h:193
@ kEnd
Definition TFile.h:193
Int_t fD
File descriptor.
Definition TFile.h:83
Bool_t fIsRootFile
!True is this is a ROOT file, raw file otherwise
Definition TFile.h:105
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TFile.cxx:2191
Long64_t fOffset
!Seek offset cache
Definition TFile.h:97
Long64_t fEND
Last used byte in file.
Definition TFile.h:80
static std::atomic< Int_t > fgReadCalls
Number of bytes read from all TFile objects.
Definition TFile.h:134
Int_t fWritten
Number of objects written so far.
Definition TFile.h:88
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4509
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:963
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:136
Ssiz_t Length() const
Definition TString.h:410
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1946
const char * Data() const
Definition TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:692
@ kIgnoreCase
Definition TString.h:268
void ToUpper()
Change string to upper case.
Definition TString.cxx:1163
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:615
Bool_t IsNull() const
Definition TString.h:407
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
Long64_t Atoll() const
Return long long value of string.
Definition TString.cxx:1972
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:1663
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:71
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:389
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 ReOpen(Option_t *mode)
Reopen a file with a different access mode, like from READ to UPDATE or from NEW, CREATE,...
Definition TWebFile.cxx:394
virtual Int_t GetFromWeb(char *buf, Int_t len, const TString &msg)
Read request from web server.
Definition TWebFile.cxx:609
virtual TString BasicAuthentication()
Return basic authentication scheme, to be added to the request.
Long64_t fSize
Definition TWebFile.h:42
virtual void SetMsgReadBuffer10(const char *redirectLocation=0, Bool_t tempRedirect=kFALSE)
Set GET command for use by ReadBuffer(s)10(), handle redirection if needed.
Definition TWebFile.cxx:268
TSocket * fSocket
Definition TWebFile.h:43
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TWebFile.cxx:973
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.
virtual Bool_t ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
Read specified byte ranges from remote file via HTTP daemon.
Definition TWebFile.cxx:501
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:584
TString fBasicUrlOrg
Definition TWebFile.h:53
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:550
Long64_t fFullCacheSize
complete content of the file, some http server may return complete content
Definition TWebFile.h:55
TUrl fProxy
Definition TWebFile.h:44
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read specified byte range from remote file via HTTP daemon.
Definition TWebFile.cxx:413
TString fMsgGetHead
Definition TWebFile.h:50
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:462
virtual void Init(Bool_t readHeadOnly)
Initialize a TWebFile object.
Definition TWebFile.cxx:212
virtual Long64_t GetSize() const
Return maximum file size.
Definition TWebFile.cxx:994
TWebFile()
Definition TWebFile.h:39
virtual Bool_t IsOpen() const
A TWebFile that has been correctly constructed is always considered open.
Definition TWebFile.cxx:380
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,.
TString fMsgReadBuffer10
Definition TWebFile.h:49
TUrl fUrlOrg
Definition TWebFile.h:52
virtual Int_t GetFromWeb10(char *buf, Int_t len, const TString &msg, Int_t nseg=0, Long64_t *seg_pos=0, Int_t *seg_len=0)
Read multiple byte range request from web server.
Definition TWebFile.cxx:676
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.
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)
Open a directory via httpd.
TWebSystem()
Create helper class that allows directory access via httpd.
Bool_t AccessPathName(const char *path, EAccessMode mode)
Returns FALSE if one can access a file using the specified access mode.
void FreeDirectory(void *dirp)
Free directory via httpd.
void * fDirp
Definition TWebFile.h:101
const char * GetDirEntry(void *dirp)
Get directory entry via httpd. Returns 0 in case no more entries.
Int_t MakeDirectory(const char *name)
Make a directory via httpd. Not supported.
Int_t GetPathInfo(const char *path, FileStat_t &buf)
Get info about a file.
Int_t Unlink(const char *path)
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
void ws()
Definition ws.C:66