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