ROOT logo
// @(#)root/net:$Id$
// Author: Fons Rademakers   17/01/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TWebFile                                                             //
//                                                                      //
// A TWebFile is like a normal TFile except that it reads its data      //
// via a standard apache web server. A TWebFile is a read-only file.    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TWebFile.h"
#include "TROOT.h"
#include "TSocket.h"
#include "Bytes.h"
#include "TError.h"
#include "TSystem.h"
#include "TBase64.h"
#include "TVirtualPerfStats.h"
#ifdef R__SSL
#include "TSSLSocket.h"
#endif

#include <errno.h>
#include <stdlib.h>

#ifdef WIN32
# ifndef EADDRINUSE
#  define EADDRINUSE  10048
# endif
# ifndef EISCONN
#  define EISCONN     10056
# endif
#endif

static const char *gUserAgent = "User-Agent: ROOT-TWebFile/1.1";

TUrl TWebFile::fgProxy;


// Internal class used to manage the socket that may stay open between
// calls when HTTP/1.1 protocol is used
class TWebSocket {
private:
   TWebFile *fWebFile;           // associated web file
public:
   TWebSocket(TWebFile *f);
   ~TWebSocket();
   void ReOpen();
};

//______________________________________________________________________________
TWebSocket::TWebSocket(TWebFile *f)
{
   // Open web file socket.

   fWebFile = f;
   if (!f->fSocket)
      ReOpen();
}

//______________________________________________________________________________
TWebSocket::~TWebSocket()
{
   // Close socket in case not HTTP/1.1 protocol or when explicitly requested.

   if (!fWebFile->fHTTP11) {
      delete fWebFile->fSocket;
      fWebFile->fSocket = 0;
   }
}

//______________________________________________________________________________
void TWebSocket::ReOpen()
{
   // Re-open web file socket.

   if (fWebFile->fSocket)
      delete fWebFile->fSocket;

   TUrl connurl;
   if (fWebFile->fProxy.IsValid())
      connurl = fWebFile->fProxy;
   else
      connurl = fWebFile->fUrl;

   for (Int_t i = 0; i < 5; i++) {
      if (strcmp(connurl.GetProtocol(), "https") == 0) {
#ifdef R__SSL
         fWebFile->fSocket = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
#else
         ::Error("TWebSocket::ReOpen", "library compiled without SSL, https not supported");
         return;
#endif
      } else
         fWebFile->fSocket = new TSocket(connurl.GetHost(), connurl.GetPort());

      if (!fWebFile->fSocket || !fWebFile->fSocket->IsValid()) {
         delete fWebFile->fSocket;
         fWebFile->fSocket = 0;
         if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
            gSystem->Sleep(i*10);
         } else {
            ::Error("TWebSocket::ReOpen", "cannot connect to host %s (errno=%d)",
                    fWebFile->fUrl.GetHost(), gSystem->GetErrno());
            return;
         }
      } else
         return;
   }
}


ClassImp(TWebFile)

//______________________________________________________________________________
TWebFile::TWebFile(const char *url, Option_t *opt) : TFile(url, "WEB")
{
   // Create a Web file object. A web file is the same as a read-only
   // TFile except that it is being read via a HTTP server. The url
   // argument must be of the form: http://host.dom.ain/file.root.
   // The opt can be "NOPROXY", to bypass any set "http_proxy" shell
   // variable. The proxy can be specified as (in sh, or equivalent csh):
   //   export http_proxy=http://pcsalo.cern.ch:3128
   // The proxy can also be specified via the static method TWebFile::SetProxy().
   // Basic authentication (AuthType Basic) is supported. The user name and
   // passwd can be specified in the url like this:
   //   http://username:mypasswd@pcsalo.cern.ch/files/aap.root
   // If the file specified in the URL does not exist or is not accessible
   // the kZombie bit will be set in the TWebFile object. Use IsZombie()
   // to see if the file is accessible. The preferred interface to this
   // constructor is via TFile::Open().

   TString option = opt;
   fNoProxy = kFALSE;
   if (option.Contains("NOPROXY", TString::kIgnoreCase))
      fNoProxy = kTRUE;
   CheckProxy();

   Bool_t headOnly = kFALSE;
   if (option.Contains("HEADONLY", TString::kIgnoreCase))
      headOnly = kTRUE;

   if (option == "IO")
      return;

   Init(headOnly);
}

//______________________________________________________________________________
TWebFile::TWebFile(TUrl url, Option_t *opt) : TFile(url.GetUrl(), "WEB")
{
   // Create a Web file object. A web file is the same as a read-only
   // TFile except that it is being read via a HTTP server. Make sure url
   // is a valid TUrl object.
   // The opt can be "NOPROXY", to bypass any set "http_proxy" shell
   // variable. The proxy can be specified as (in sh, or equivalent csh):
   //   export http_proxy=http://pcsalo.cern.ch:3128
   // The proxy can also be specified via the static method TWebFile::SetProxy().
   // Basic authentication (AuthType Basic) is supported. The user name and
   // passwd can be specified in the url like this:
   //   http://username:mypasswd@pcsalo.cern.ch/files/aap.root
   // If the file specified in the URL does not exist or is not accessible
   // the kZombie bit will be set in the TWebFile object. Use IsZombie()
   // to see if the file is accessible.

   TString option = opt;
   fNoProxy = kFALSE;
   if (option.Contains("NOPROXY", TString::kIgnoreCase))
      fNoProxy = kTRUE;
   CheckProxy();

   Bool_t headOnly = kFALSE;
   if (option.Contains("HEADONLY", TString::kIgnoreCase))
      headOnly = kTRUE;

   Init(headOnly);
}

//______________________________________________________________________________
TWebFile::~TWebFile()
{
   // Cleanup.

   delete fSocket;
}

//______________________________________________________________________________
void TWebFile::Init(Bool_t readHeadOnly)
{
   // Initialize a TWebFile object.

   char buf[4];
   int  err;

   fSocket     = 0;
   fSize       = -1;
   fHasModRoot = kFALSE;
   fHTTP11     = kFALSE;

   SetMsgReadBuffer10();

   if ((err = GetHead()) < 0) {
      if (readHeadOnly) {
         fD = -1;
         fWritten = err;
         return;
      }
      if (err == -2) {
         Error("TWebFile", "%s does not exist", fBasicUrl.Data());
         MakeZombie();
         gDirectory = gROOT;
         return;
      }
      // err == -3 HEAD not supported, fall through and try ReadBuffer()
   }
   if (readHeadOnly) {
      fD = -1;
      return;
   }

   if (fIsRootFile) {
      Seek(0);
      if (ReadBuffer(buf, 4)) {
         MakeZombie();
         gDirectory = gROOT;
         return;
      }

      if (strncmp(buf, "root", 4) && strncmp(buf, "PK", 2)) {  // PK is zip file
         Error("TWebFile", "%s is not a ROOT file", fBasicUrl.Data());
         MakeZombie();
         gDirectory = gROOT;
         return;
      }
   }

   TFile::Init(kFALSE);
   fD = -2;   // so TFile::IsOpen() will return true when in TFile::~TFile
}

//______________________________________________________________________________
void TWebFile::SetMsgReadBuffer10(const char *redirectLocation, Bool_t tempRedirect)
{
   // Set GET command for use by ReadBuffer(s)10(), handle redirection if
   // needed. Give full URL so Apache's virtual hosts solution works.

   TUrl oldUrl;
   TString oldBasicUrl;

   if (redirectLocation) {
      if (tempRedirect) { // temp redirect
         fUrlOrg      = fUrl;
         fBasicUrlOrg = fBasicUrl;
      } else {             // permanent redirect
         fUrlOrg      = "";
         fBasicUrlOrg = "";
      }

      oldUrl = fUrl;
      oldBasicUrl = fBasicUrl;

      fUrl.SetUrl(redirectLocation);
      fBasicUrl = fUrl.GetProtocol();
      fBasicUrl += "://";
      fBasicUrl += fUrl.GetHost();
      fBasicUrl += ":";
      fBasicUrl += fUrl.GetPort();
      fBasicUrl += "/";
      fBasicUrl += fUrl.GetFile();
      // add query string again
      TString rdl(redirectLocation); 
      if (rdl.Index("?") >= 0) { 
         rdl = rdl(rdl.Index("?"), rdl.Length()); 
         fBasicUrl += rdl; 
      }
   }

   if (fMsgReadBuffer10 != "") {
      // patch up existing command
      if (oldBasicUrl != "") {
         // change to redirection location
         fMsgReadBuffer10.ReplaceAll(oldBasicUrl, fBasicUrl);
         fMsgReadBuffer10.ReplaceAll(TString("Host: ")+oldUrl.GetHost(), TString("Host: ")+fUrl.GetHost());
      } else if (fBasicUrlOrg != "") {
         // change back from temp redirection location
         fMsgReadBuffer10.ReplaceAll(fBasicUrl, fBasicUrlOrg);
         fMsgReadBuffer10.ReplaceAll(TString("Host: ")+fUrl.GetHost(), TString("Host: ")+fUrlOrg.GetHost());
         fUrl         = fUrlOrg;
         fBasicUrl    = fBasicUrlOrg;
         fUrlOrg      = "";
         fBasicUrlOrg = "";
      }
   }

   if (fBasicUrl == "") {
      fBasicUrl += fUrl.GetProtocol();
      fBasicUrl += "://";
      fBasicUrl += fUrl.GetHost();
      fBasicUrl += ":";
      fBasicUrl += fUrl.GetPort();
      fBasicUrl += "/";
      fBasicUrl += fUrl.GetFile();
      fBasicUrl += "?";
      fBasicUrl += fUrl.GetOptions();
   }

   if (fMsgReadBuffer10 == "") {
      fMsgReadBuffer10 = "GET ";
      fMsgReadBuffer10 += fBasicUrl;
      if (fHTTP11)
         fMsgReadBuffer10 += " HTTP/1.1";
      else
         fMsgReadBuffer10 += " HTTP/1.0";
      fMsgReadBuffer10 += "\r\n";
      if (fHTTP11) {
         fMsgReadBuffer10 += "Host: ";
         fMsgReadBuffer10 += fUrl.GetHost();
         fMsgReadBuffer10 += "\r\n";
      }
      fMsgReadBuffer10 += BasicAuthentication();
      fMsgReadBuffer10 += gUserAgent;
      fMsgReadBuffer10 += "\r\n";
      fMsgReadBuffer10 += "Range: bytes=";
   }
}

//______________________________________________________________________________
void TWebFile::CheckProxy()
{
   // Check if shell var "http_proxy" has been set and should be used.

   if (fNoProxy)
      return;

   if (fgProxy.IsValid()) {
      fProxy = fgProxy;
      return;
   }

   TString proxy = gSystem->Getenv("http_proxy");
   if (proxy != "") {
      TUrl p(proxy);
      if (strcmp(p.GetProtocol(), "http")) {
         Error("CheckProxy", "protocol must be HTTP in proxy URL %s",
               proxy.Data());
         return;
      }
      fProxy = p;
      if (gDebug > 0)
         Info("CheckProxy", "using HTTP proxy %s", fProxy.GetUrl());
   }
}

//______________________________________________________________________________
Bool_t TWebFile::IsOpen() const
{
   // A TWebFile that has been correctly constructed is always considered open.

   return IsZombie() ? kFALSE : kTRUE;
}

//______________________________________________________________________________
Int_t TWebFile::ReOpen(Option_t *mode)
{
   // Reopen a file with a different access mode, like from READ to
   // UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
   // mode argument can be either "READ" or "UPDATE". The method returns
   // 0 in case the mode was successfully modified, 1 in case the mode
   // did not change (was already as requested or wrong input arguments)
   // and -1 in case of failure, in which case the file cannot be used
   // anymore. A TWebFile cannot be reopened in update mode.

   TString opt = mode;
   opt.ToUpper();

   if (opt != "READ" && opt != "UPDATE")
      Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());

   if (opt == "UPDATE")
      Error("ReOpen", "update mode not allowed for a TWebFile");

   return 1;
}

//______________________________________________________________________________
Bool_t TWebFile::ReadBuffer(char *buf, Int_t len)
{
   // Read specified byte range from remote file via HTTP daemon. This
   // routine connects to the remote host, sends the request and returns
   // the buffer. Returns kTRUE in case of error.

   Int_t st;
   if ((st = ReadBufferViaCache(buf, len))) {
      if (st == 2)
         return kTRUE;
      return kFALSE;
   }

   if (!fHasModRoot)
      return ReadBuffer10(buf, len);

   // Give full URL so Apache's virtual hosts solution works.
   // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
   if (fMsgReadBuffer == "") {
      fMsgReadBuffer = "GET ";
      fMsgReadBuffer += fBasicUrl;
      fMsgReadBuffer += "?";
   }
   TString msg = fMsgReadBuffer;
   msg += fOffset;
   msg += ":";
   msg += len;
   msg += "\r\n";

   if (GetFromWeb(buf, len, msg) == -1)
      return kTRUE;

   fOffset += len;

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TWebFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
{
   // Read specified byte range from remote file via HTTP daemon. This
   // routine connects to the remote host, sends the request and returns
   // the buffer. Returns kTRUE in case of error.

   SetOffset(pos);
   return ReadBuffer(buf, len);
}

//______________________________________________________________________________
Bool_t TWebFile::ReadBuffer10(char *buf, Int_t len)
{
   // Read specified byte range from remote file via HTTP 1.0 daemon (without
   // mod-root installed). This routine connects to the remote host, sends the
   // request and returns the buffer. Returns kTRUE in case of error.

   SetMsgReadBuffer10();

   TString msg = fMsgReadBuffer10;
   msg += fOffset;
   msg += "-";
   msg += fOffset+len-1;
   msg += "\r\n\r\n";

   Int_t n = GetFromWeb10(buf, len, msg);
   if (n == -1)
      return kTRUE;
   // The -2 error condition typically only happens when
   // GetHead() failed because not implemented, in the first call to
   // ReadBuffer() in Init(), it is not checked in ReadBuffers10().
   if (n == -2) {
      Error("ReadBuffer10", "%s does not exist", fBasicUrl.Data());
      MakeZombie();
      gDirectory = gROOT;
      return kTRUE;
   }

   fOffset += len;

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TWebFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
{
   // Read specified byte ranges from remote file via HTTP daemon.
   // Reads the nbuf blocks described in arrays pos and len,
   // where pos[i] is the seek position of block i of length len[i].
   // Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
   // This function is overloaded by TNetFile, TWebFile, etc.
   // Returns kTRUE in case of failure.

   if (!fHasModRoot)
      return ReadBuffers10(buf, pos, len, nbuf);

   // Give full URL so Apache's virtual hosts solution works.
   // Use protocol 0.9 for efficiency, we are not interested in the 1.0 headers.
   if (fMsgReadBuffer == "") {
      fMsgReadBuffer = "GET ";
      fMsgReadBuffer += fBasicUrl;
      fMsgReadBuffer += "?";
   }
   TString msg = fMsgReadBuffer;

   Int_t k = 0, n = 0;
   for (Int_t i = 0; i < nbuf; i++) {
      if (n) msg += ",";
      msg += pos[i] + fArchiveOffset;
      msg += ":";
      msg += len[i];
      n   += len[i];
      if (msg.Length() > 8000) {
         msg += "\r\n";
         if (GetFromWeb(&buf[k], n, msg) == -1)
            return kTRUE;
         msg = fMsgReadBuffer;
         k += n;
         n = 0;
      }
   }

   msg += "\r\n";

   if (GetFromWeb(&buf[k], n, msg) == -1)
      return kTRUE;

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TWebFile::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). Read the nbuf blocks described in arrays pos and len,
   // where pos[i] is the seek position of block i of length len[i].
   // Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer
   // This function is overloaded by TNetFile, TWebFile, etc.
   // Returns kTRUE in case of failure.

   SetMsgReadBuffer10();

   TString msg = fMsgReadBuffer10;

   Int_t k = 0, n = 0, r;
   for (Int_t i = 0; i < nbuf; i++) {
      if (n) msg += ",";
      msg += pos[i] + fArchiveOffset;
      msg += "-";
      msg += pos[i] + fArchiveOffset + len[i] - 1;
      n   += len[i];
      if (msg.Length() > 8000) {
         msg += "\r\n\r\n";
         r = GetFromWeb10(&buf[k], n, msg);
         if (r == -1)
            return kTRUE;
         msg = fMsgReadBuffer10;
         k += n;
         n = 0;
      }
   }

   msg += "\r\n\r\n";

   r = GetFromWeb10(&buf[k], n, msg);
   if (r == -1)
      return kTRUE;

   return kFALSE;
}

//______________________________________________________________________________
Int_t TWebFile::GetFromWeb(char *buf, Int_t len, const TString &msg)
{
   // Read request from web server. Returns -1 in case of error,
   // 0 in case of success.

   TSocket *s;

   if (!len) return 0;

   Double_t start = 0;
   if (gPerfStats) start = TTimeStamp();

   TUrl connurl;
   if (fProxy.IsValid())
      connurl = fProxy;
   else
      connurl = fUrl;

   if (strcmp(connurl.GetProtocol(), "https") == 0) {
#ifdef R__SSL
      s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
#else
      Error("GetFromWeb", "library compiled without SSL, https not supported");
      return -1;
#endif
   } else
      s = new TSocket(connurl.GetHost(), connurl.GetPort());
     
   if (!s->IsValid()) {
      Error("GetFromWeb", "cannot connect to host %s", fUrl.GetHost());
      delete s;
      return -1;
   }

   if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
      Error("GetFromWeb", "error sending command to host %s", fUrl.GetHost());
      delete s;
      return -1;
   }

   if (s->RecvRaw(buf, len) == -1) {
      Error("GetFromWeb", "error receiving data from host %s", fUrl.GetHost());
      delete s;
      return -1;
   }

   // collect statistics
   fBytesRead += len;
   fReadCalls++;
#ifdef R__WIN32
   SetFileBytesRead(GetFileBytesRead() + len);
   SetFileReadCalls(GetFileReadCalls() + 1);
#else
   fgBytesRead += len;
   fgReadCalls++;
#endif

   if (gPerfStats)
      gPerfStats->FileReadEvent(this, len, start);

   delete s;
   return 0;
}

//______________________________________________________________________________
Int_t TWebFile::GetFromWeb10(char *buf, Int_t len, const TString &msg)
{
   // Read multiple byte range request from web server.
   // Uses HTTP 1.0 daemon wihtout mod-root.
   // Returns -2 in case file does not exist, -1 in case
   // of error and 0 in case of success.

   if (!len) return 0;

   Double_t start = 0;
   if (gPerfStats) start = TTimeStamp();

   // open fSocket and close it when going out of scope
   TWebSocket ws(this);

   if (!fSocket || !fSocket->IsValid()) {
      Error("GetFromWeb10", "cannot connect to host %s", fUrl.GetHost());
      return -1;
   }

   if (gDebug > 0)
      Info("GetFromWeb10", "sending HTTP request:\n%s", msg.Data());
   
   if (fSocket->SendRaw(msg.Data(), msg.Length()) == -1) {
      Error("GetFromWeb10", "error sending command to host %s", fUrl.GetHost());
      return -1;
   }

   char line[8192];
   Int_t n, ret = 0, nranges = 0, ltot = 0, redirect = 0;
   TString boundary, boundaryEnd;
   Long64_t first = -1, last = -1, tot;

   while ((n = GetLine(fSocket, line, sizeof(line))) >= 0) {
      if (n == 0) {
         if (ret < 0)
            return ret;
         if (redirect) {
            ws.ReOpen();
            // set message to reflect the redirectLocation and add bytes field
            TString msg_1 = fMsgReadBuffer10; 
            msg_1 += fOffset; 
            msg_1 += "-"; 
            msg_1 += fOffset+len-1; 
            msg_1 += "\r\n\r\n"; 
            return GetFromWeb10(buf, len, msg_1);
         }

         if (first >= 0) {
            Int_t ll = Int_t(last - first) + 1;
            Int_t rsize;
            if ((rsize = fSocket->RecvRaw(&buf[ltot], ll)) == -1) {
               Error("GetFromWeb10", "error receiving data from host %s", fUrl.GetHost());
               return -1;
            }
            else if (ll != rsize) {
               Error("GetFromWeb10", "expected %d bytes, got %d", ll, rsize);
               return -1;
            }
            ltot += ll;

            first = -1;

            if (boundary == "")
               break;  // not a multipart response
         }

         continue;
      }

      if (gDebug > 0)
         Info("GetFromWeb10", "header: %s", line);

      if (boundaryEnd == line) {
         if (gDebug > 0)
            Info("GetFromWeb10", "got all headers");
         break;
      }
      if (boundary == line) {
         nranges++;
         if (gDebug > 0)
            Info("GetFromWeb10", "get new multipart byte range (%d)", nranges);
      }

      TString res = line;

      if (res.BeginsWith("HTTP/1.")) {
         if (res.BeginsWith("HTTP/1.1")) {
            if (!fHTTP11)
               fMsgReadBuffer10  = "";
            fHTTP11 = kTRUE;
         }
         TString scode = res(9, 3);
         Int_t code = scode.Atoi();
         if (code >= 500) {
            ret = -1;
            TString mess = res(13, 1000);
            Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
         } else if (code >= 400) {
            if (code == 404)
               ret = -2;   // file does not exist
            else {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         } else if (code >= 300) {
            if (code == 301 || code == 303) {
               redirect = 1;   // permanent redirect
            } else if (code == 302 || code == 307) {
               // treat 302 as 303: permanent redirect 
               redirect = 1; 
               //redirect = 2; // temp redirect
            } else {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         } else if (code > 200) {
            if (code != 206) {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetFromWeb10", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         }
      } else if (res.BeginsWith("Content-Type: multipart")) {
         boundary = res(res.Index("boundary=")+9, 1000);
         if (boundary[0]=='"' && boundary[boundary.Length()-1]=='"') {
            boundary = boundary(1,boundary.Length()-2);
         }
         boundary = "--" + boundary;
         boundaryEnd = boundary + "--";
      } else if (res.BeginsWith("Content-range:")) {
#ifdef R__WIN32
         sscanf(res.Data(), "Content-range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
#else
         sscanf(res.Data(), "Content-range: bytes %lld-%lld/%lld", &first, &last, &tot);
#endif
         if (fSize == -1) fSize = tot;
      } else if (res.BeginsWith("Content-Range:")) {
#ifdef R__WIN32
         sscanf(res.Data(), "Content-Range: bytes %I64d-%I64d/%I64d", &first, &last, &tot);
#else
         sscanf(res.Data(), "Content-Range: bytes %lld-%lld/%lld", &first, &last, &tot);
#endif
         if (fSize == -1) fSize = tot;
      } else if (res.BeginsWith("Location:") && redirect) {
         TString redir = res(10, 1000);
         if (redirect == 2)   // temp redirect
            SetMsgReadBuffer10(redir, kTRUE);
         else               // permanent redirect
            SetMsgReadBuffer10(redir, kFALSE);
      }
   }

   if (n == -1 && fHTTP11) {
      if (gDebug > 0)
         Info("GetFromWeb10", "HTTP/1.1 socket closed, reopen");
      if (fBasicUrlOrg != "") {
         // if we have to close temp redirection, set back to original url
         SetMsgReadBuffer10();
      }
      ws.ReOpen();
      return GetFromWeb10(buf, len, msg);
   }

   if (ltot != len) {
      Error("GetFromWeb10", "error receiving expected amount of data (got %d, expected %d) from host %s",
            ltot, len, fUrl.GetHost());
      return -1;
   }

   // collect statistics
   fBytesRead += len;
   fReadCalls++;
#ifdef R__WIN32
   SetFileBytesRead(GetFileBytesRead() + len);
   SetFileReadCalls(GetFileReadCalls() + 1);
#else
   fgBytesRead += len;
   fgReadCalls++;
#endif

   if (gPerfStats)
      gPerfStats->FileReadEvent(this, len, start);

   return 0;
}

//______________________________________________________________________________
void TWebFile::Seek(Long64_t offset, ERelativeTo pos)
{
   // Set position from where to start reading.

   switch (pos) {
   case kBeg:
      fOffset = offset + fArchiveOffset;
      break;
   case kCur:
      fOffset += offset;
      break;
   case kEnd:
      // this option is not used currently in the ROOT code
      if (fArchiveOffset)
         Error("Seek", "seeking from end in archive is not (yet) supported");
      fOffset = fEND - offset;  // is fEND really EOF or logical EOF?
      break;
   }
}

//______________________________________________________________________________
Long64_t TWebFile::GetSize() const
{
   // Return maximum file size.

   if (!fHasModRoot || fSize >= 0)
      return fSize;

   Long64_t size;
   char     asize[64];

   TString msg = "GET ";
   msg += fBasicUrl;
   msg += "?";
   msg += -1;
   msg += "\r\n";

   if (const_cast<TWebFile*>(this)->GetFromWeb(asize, 64, msg) == -1)
      return kMaxInt;

#ifndef R__WIN32
   size = atoll(asize);
#else
   size = _atoi64(asize);
#endif

   fSize = size;

   return size;
}

//______________________________________________________________________________
Int_t TWebFile::GetHead()
{
   // Get the HTTP header. Depending on the return code we can see if
   // the file exists and if the server uses mod_root.
   // Returns -1 in case of an error, -2 in case the file does not exists,
   // -3 in case HEAD is not supported (dCache HTTP door) and
   // 0 in case of success.

   // Give full URL so Apache's virtual hosts solution works.
   if (fMsgGetHead == "") {
      fMsgGetHead = "HEAD ";
      fMsgGetHead += fBasicUrl;
      if (fHTTP11)
         fMsgGetHead += " HTTP/1.1";
      else
         fMsgGetHead += " HTTP/1.0";
      fMsgGetHead += "\r\n";
      if (fHTTP11) {
         fMsgGetHead += "Host: ";
         fMsgGetHead += fUrl.GetHost();
         fMsgGetHead += "\r\n";
      }
      fMsgGetHead += BasicAuthentication();
      fMsgGetHead += gUserAgent;
      fMsgGetHead += "\r\n\r\n";
   }
   TString msg = fMsgGetHead;
 
   TUrl connurl;
   if (fProxy.IsValid())
      connurl = fProxy;
   else
      connurl = fUrl;

   TSocket *s = 0;
   for (Int_t i = 0; i < 5; i++) {
      if (strcmp(connurl.GetProtocol(), "https") == 0) {
#ifdef R__SSL
         s = new TSSLSocket(connurl.GetHost(), connurl.GetPort());
#else
         Error("GetHead", "library compiled without SSL, https not supported");
         return -1;
#endif
      } else
         s = new TSocket(connurl.GetHost(), connurl.GetPort());

      if (!s->IsValid()) {
         delete s;
         if (gSystem->GetErrno() == EADDRINUSE || gSystem->GetErrno() == EISCONN) {
            s = 0;
            gSystem->Sleep(i*10);
         } else {
            Error("GetHead", "cannot connect to host %s (errno=%d)", fUrl.GetHost(),
                  gSystem->GetErrno());
            return -1;
         }
      } else
         break;
   }
   if (!s)
      return -1;

   if (gDebug > 0) {
      Info("GetHead", "connected to host %s", connurl.GetHost());
      Info("GetHead", "sending HTTP request:\n%s", msg.Data());
   }

   if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
      Error("GetHead", "error sending command to host %s", fUrl.GetHost());
      delete s;
      return -1;
   }

   char line[8192];
   Int_t n, ret = 0, redirect = 0;

   while ((n = GetLine(s, line, sizeof(line))) >= 0) {
      if (n == 0) {
         if (gDebug > 0)
            Info("GetHead", "got all headers");
         delete s;
         if (fBasicUrlOrg != "" && !redirect) {
            // set back to original url in case of temp redirect
            SetMsgReadBuffer10();
            fMsgGetHead = "";
         }
         if (ret < 0)
            return ret;
         if (redirect)
            return GetHead();
         return 0;
      }

      if (gDebug > 0)
         Info("GetHead", "header: %s", line);

      TString res = line;
      ProcessHttpHeader(res);
      if (res.BeginsWith("HTTP/1.")) {
         if (res.BeginsWith("HTTP/1.1")) {
            if (!fHTTP11) {
               fMsgGetHead = "";
               fMsgReadBuffer10 = "";
            }
            fHTTP11 = kTRUE;
         }
         TString scode = res(9, 3);
         Int_t code = scode.Atoi();
         if (code >= 500) {
            if (code == 500)
               fHasModRoot = kTRUE;
            else {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         } else if (code >= 400) {
            if (code == 400)
               ret = -3;   // command not supported
            else if (code == 404)
               ret = -2;   // file does not exist
            else {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         } else if (code >= 300) {
            if (code == 301 || code == 303)
               redirect = 1;   // permanent redirect
            else if (code == 302 || code == 307)
               redirect = 2;   // temp redirect
            else {
               ret = -1;
               TString mess = res(13, 1000);
               Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
            }
         } else if (code > 200) {
            ret = -1;
            TString mess = res(13, 1000);
            Error("GetHead", "%s: %s (%d)", fBasicUrl.Data(), mess.Data(), code);
         }
      } else if (res.BeginsWith("Content-Length:")) {
         TString slen = res(16, 1000);
         fSize = slen.Atoll();
      } else if (res.BeginsWith("Location:") && redirect) {
         TString redir = res(10, 1000);
         if (redirect == 2)   // temp redirect
            SetMsgReadBuffer10(redir, kTRUE);
         else               // permanent redirect
            SetMsgReadBuffer10(redir, kFALSE);
         fMsgGetHead = "";
      }
   }

   delete s;

   return ret;
}

//______________________________________________________________________________
Int_t TWebFile::GetLine(TSocket *s, char *line, Int_t maxsize)
{
   // Read a line from the socket. Reads at most one less than the number of
   // characters specified by maxsize. Reading stops when a newline character
   // is found, The newline (\n) and cr (\r), if any, are removed.
   // Returns -1 in case of error, or the number of characters read (>= 0)
   // otherwise.

   Int_t n = GetHunk(s, line, maxsize);
   if (n < 0) {
      if (!fHTTP11 || gDebug > 0)
         Error("GetLine", "error receiving data from host %s", fUrl.GetHost());
      return -1;
   }

   if (n > 0 && line[n-1] == '\n') {
      n--;
      if (n > 0 && line[n-1] == '\r')
         n--;
      line[n] = '\0';
   }
   return n;
}

//______________________________________________________________________________
Int_t TWebFile::GetHunk(TSocket *s, char *hunk, Int_t maxsize)
{
   // Read a hunk of data from the socket, up until a terminator. The hunk is
   // limited by whatever the TERMINATOR callback chooses as its
   // terminator. For example, if terminator stops at newline, the hunk
   // will consist of a line of data; if terminator stops at two
   // newlines, it can be used to read the head of an HTTP response.
   // Upon determining the boundary, the function returns the data (up to
   // the terminator) in hunk.
   //
   // In case of read error, -1 is returned. In case of having read some
   // data, but encountering EOF before seeing the terminator, the data
   // that has been read is returned, but it will (obviously) not contain the
   // terminator.
   //
   // The TERMINATOR function is called with three arguments: the
   // beginning of the data read so far, the beginning of the current
   // block of peeked-at data, and the length of the current block.
   // Depending on its needs, the function is free to choose whether to
   // analyze all data or just the newly arrived data. If TERMINATOR
   // returns 0, it means that the terminator has not been seen.
   // Otherwise it should return a pointer to the character immediately
   // following the terminator.
   //
   // The idea is to be able to read a line of input, or otherwise a hunk
   // of text, such as the head of an HTTP request, without crossing the
   // boundary, so that the next call to RecvRaw() etc. reads the data
   // after the hunk. To achieve that, this function does the following:
   //
   // 1. Peek at incoming data.
   //
   // 2. Determine whether the peeked data, along with the previously
   //    read data, includes the terminator.
   //
   // 3a. If yes, read the data until the end of the terminator, and
   //     exit.
   //
   // 3b. If no, read the peeked data and goto 1.
   //
   // The function is careful to assume as little as possible about the
   // implementation of peeking.  For example, every peek is followed by
   // a read. If the read returns a different amount of data, the
   // process is retried until all data arrives safely.
   //
   // Reads at most one less than the number of characters specified by maxsize.

   if (maxsize <= 0) return 0;

   Int_t bufsize = maxsize;
   Int_t tail = 0;                 // tail position in HUNK

   while (1) {
      const char *end;
      Int_t pklen, rdlen, remain;

      // First, peek at the available data.
      pklen = s->RecvRaw(hunk+tail, bufsize-1-tail, kPeek);
      if (pklen < 0) {
         return -1;
      }
      end = HttpTerminator(hunk, hunk+tail, pklen);
      if (end) {
         // The data contains the terminator: we'll drain the data up
         // to the end of the terminator.
         remain = end - (hunk + tail);
         if (remain == 0) {
            // No more data needs to be read.
            hunk[tail] = '\0';
            return tail;
         }
         if (bufsize - 1 < tail + remain) {
            Error("GetHunk", "hunk buffer too small for data from host %s (%d bytes needed)",
                  fUrl.GetHost(), tail + remain + 1);
            hunk[tail] = '\0';
            return -1;
         }
      } else {
         // No terminator: simply read the data we know is (or should
         // be) available.
         remain = pklen;
      }

      // Now, read the data. Note that we make no assumptions about
      // how much data we'll get. (Some TCP stacks are notorious for
      // read returning less data than the previous MSG_PEEK.)
      rdlen = s->RecvRaw(hunk+tail, remain, kDontBlock);
      if (rdlen < 0) {
         return -1;
      }
      tail += rdlen;
      hunk[tail] = '\0';

      if (rdlen == 0) {
         if (tail == 0) {
            // EOF without anything having been read
            return tail;
         } else {
            // EOF seen: return the data we've read.
            return tail;
         }
      }
      if (end && rdlen == remain) {
         // The terminator was seen and the remaining data drained --
         // we got what we came for.
         return tail;
      }

      // Keep looping until all the data arrives.

      if (tail == bufsize - 1) {
         Error("GetHunk", "hunk buffer too small for data from host %s",
               fUrl.GetHost());
         return -1;
      }
   }
}

//______________________________________________________________________________
const char *TWebFile::HttpTerminator(const char *start, const char *peeked,
                                     Int_t peeklen)
{
   // Determine whether [START, PEEKED + PEEKLEN) contains an HTTP new
   // line [\r]\n. If so, return the pointer to the position after the line,
   // otherwise return 0. This is used as callback to GetHunk(). The data
   // between START and PEEKED has been read and cannot be "unread"; the
   // data after PEEKED has only been peeked.
#if 0
   const char *p, *end;

   // Look for "[\r]\n", and return the following position if found.
   // Start one char before the current to cover the possibility that
   // part of the terminator (e.g. "\r") arrived in the previous batch.
   p = peeked - start < 1 ? start : peeked - 1;
   end = peeked + peeklen;

   // Check for \r\n anywhere in [p, end-2).
   for (; p < end - 1; p++)
      if (p[0] == '\r' && p[1] == '\n')
         return p + 2;

   // p==end-1: check for \r\n directly preceding END.
   if (p[0] == '\r' && p[1] == '\n')
      return p + 2;
#else
   if (start) { }   // start unused, silence compiler
   const char *p = (const char*) memchr(peeked, '\n', peeklen);
   if (p)
      // p+1 because the line must include '\n'
      return p + 1;
#endif
   return 0;
}

//______________________________________________________________________________
TString TWebFile::BasicAuthentication()
{
   // Return basic authentication scheme, to be added to the request.

   TString msg;
   if (strlen(fUrl.GetUser())) {
      TString auth = fUrl.GetUser();
      if (strlen(fUrl.GetPasswd())) {
         auth += ":";
         auth += fUrl.GetPasswd();
      }
      msg += "Authorization: Basic ";
      msg += TBase64::Encode(auth);
      msg += "\r\n";
   }
   return msg;
}

//______________________________________________________________________________
void TWebFile::SetProxy(const char *proxy)
{
   // Static method setting global proxy URL.

   if (proxy && *proxy) {
      TUrl p(proxy);
      if (strcmp(p.GetProtocol(), "http")) {
         :: Error("TWebFile::SetProxy", "protocol must be HTTP in proxy URL %s",
                  proxy);
         return;
      }
      fgProxy = p;
   }
}

//______________________________________________________________________________
const char *TWebFile::GetProxy()
{
   // Static method returning the global proxy URL.

   if (fgProxy.IsValid())
      return fgProxy.GetUrl();
   return "";
}

//______________________________________________________________________________
void TWebFile::ProcessHttpHeader(const TString&)
{
   // Process the HTTP header in the argument. This method is intended to be
   // overwritten by subclasses that exploit the information contained in the
   // HTTP headers.
}

//______________________________________________________________________________
TWebSystem::TWebSystem() : TSystem("-http", "HTTP Helper System")
{
   // Create helper class that allows directory access via httpd.
   // The name must start with '-' to bypass the TSystem singleton check.

   SetName("http");

   fDirp = 0;
}

//______________________________________________________________________________
Int_t TWebSystem::MakeDirectory(const char *)
{
   // Make a directory via httpd. Not supported.

   return -1;
}

//______________________________________________________________________________
void *TWebSystem::OpenDirectory(const char *)
{
   // Open a directory via httpd. Returns an opaque pointer to a dir
   // structure. Returns 0 in case of error.

   if (fDirp) {
      Error("OpenDirectory", "invalid directory pointer (should never happen)");
      fDirp = 0;
   }

   fDirp = 0;   // not implemented for the time being

   return fDirp;
}

//______________________________________________________________________________
void TWebSystem::FreeDirectory(void *dirp)
{
   // Free directory via httpd.

   if (dirp != fDirp) {
      Error("FreeDirectory", "invalid directory pointer (should never happen)");
      return;
   }

   fDirp = 0;
}

//______________________________________________________________________________
const char *TWebSystem::GetDirEntry(void *dirp)
{
   // Get directory entry via httpd. Returns 0 in case no more entries.

   if (dirp != fDirp) {
      Error("GetDirEntry", "invalid directory pointer (should never happen)");
      return 0;
   }

   return 0;
}

//______________________________________________________________________________
Int_t TWebSystem::GetPathInfo(const char *path, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   TWebFile *f = new TWebFile(path, "HEADONLY");

   if (f->fWritten == 0) {

      buf.fDev    = 0;
      buf.fIno    = 0;
      buf.fMode   = 0;
      buf.fUid    = 0;
      buf.fGid    = 0;
      buf.fSize   = f->GetSize();
      buf.fMtime  = 0;
      buf.fIsLink = kFALSE;

      delete f;
      return 0;
   }

   delete f;
   return 1;
}

//______________________________________________________________________________
Bool_t TWebSystem::AccessPathName(const char *path, EAccessMode)
{
   // Returns FALSE if one can access a file using the specified access mode.
   // Mode is the same as for the Unix access(2) function.
   // Attention, bizarre convention of return value!!

   TWebFile *f = new TWebFile(path, "HEADONLY");
   if (f->fWritten == 0) {
      delete f;
      return kFALSE;
   }
   delete f;
   return kTRUE;
}

//______________________________________________________________________________
Int_t TWebSystem::Unlink(const char *)
{
   // Unlink, i.e. remove, a file or directory. Returns 0 when successful,
   // -1 in case of failure. Not supported for httpd.

   return -1;
}
 TWebFile.cxx:1
 TWebFile.cxx:2
 TWebFile.cxx:3
 TWebFile.cxx:4
 TWebFile.cxx:5
 TWebFile.cxx:6
 TWebFile.cxx:7
 TWebFile.cxx:8
 TWebFile.cxx:9
 TWebFile.cxx:10
 TWebFile.cxx:11
 TWebFile.cxx:12
 TWebFile.cxx:13
 TWebFile.cxx:14
 TWebFile.cxx:15
 TWebFile.cxx:16
 TWebFile.cxx:17
 TWebFile.cxx:18
 TWebFile.cxx:19
 TWebFile.cxx:20
 TWebFile.cxx:21
 TWebFile.cxx:22
 TWebFile.cxx:23
 TWebFile.cxx:24
 TWebFile.cxx:25
 TWebFile.cxx:26
 TWebFile.cxx:27
 TWebFile.cxx:28
 TWebFile.cxx:29
 TWebFile.cxx:30
 TWebFile.cxx:31
 TWebFile.cxx:32
 TWebFile.cxx:33
 TWebFile.cxx:34
 TWebFile.cxx:35
 TWebFile.cxx:36
 TWebFile.cxx:37
 TWebFile.cxx:38
 TWebFile.cxx:39
 TWebFile.cxx:40
 TWebFile.cxx:41
 TWebFile.cxx:42
 TWebFile.cxx:43
 TWebFile.cxx:44
 TWebFile.cxx:45
 TWebFile.cxx:46
 TWebFile.cxx:47
 TWebFile.cxx:48
 TWebFile.cxx:49
 TWebFile.cxx:50
 TWebFile.cxx:51
 TWebFile.cxx:52
 TWebFile.cxx:53
 TWebFile.cxx:54
 TWebFile.cxx:55
 TWebFile.cxx:56
 TWebFile.cxx:57
 TWebFile.cxx:58
 TWebFile.cxx:59
 TWebFile.cxx:60
 TWebFile.cxx:61
 TWebFile.cxx:62
 TWebFile.cxx:63
 TWebFile.cxx:64
 TWebFile.cxx:65
 TWebFile.cxx:66
 TWebFile.cxx:67
 TWebFile.cxx:68
 TWebFile.cxx:69
 TWebFile.cxx:70
 TWebFile.cxx:71
 TWebFile.cxx:72
 TWebFile.cxx:73
 TWebFile.cxx:74
 TWebFile.cxx:75
 TWebFile.cxx:76
 TWebFile.cxx:77
 TWebFile.cxx:78
 TWebFile.cxx:79
 TWebFile.cxx:80
 TWebFile.cxx:81
 TWebFile.cxx:82
 TWebFile.cxx:83
 TWebFile.cxx:84
 TWebFile.cxx:85
 TWebFile.cxx:86
 TWebFile.cxx:87
 TWebFile.cxx:88
 TWebFile.cxx:89
 TWebFile.cxx:90
 TWebFile.cxx:91
 TWebFile.cxx:92
 TWebFile.cxx:93
 TWebFile.cxx:94
 TWebFile.cxx:95
 TWebFile.cxx:96
 TWebFile.cxx:97
 TWebFile.cxx:98
 TWebFile.cxx:99
 TWebFile.cxx:100
 TWebFile.cxx:101
 TWebFile.cxx:102
 TWebFile.cxx:103
 TWebFile.cxx:104
 TWebFile.cxx:105
 TWebFile.cxx:106
 TWebFile.cxx:107
 TWebFile.cxx:108
 TWebFile.cxx:109
 TWebFile.cxx:110
 TWebFile.cxx:111
 TWebFile.cxx:112
 TWebFile.cxx:113
 TWebFile.cxx:114
 TWebFile.cxx:115
 TWebFile.cxx:116
 TWebFile.cxx:117
 TWebFile.cxx:118
 TWebFile.cxx:119
 TWebFile.cxx:120
 TWebFile.cxx:121
 TWebFile.cxx:122
 TWebFile.cxx:123
 TWebFile.cxx:124
 TWebFile.cxx:125
 TWebFile.cxx:126
 TWebFile.cxx:127
 TWebFile.cxx:128
 TWebFile.cxx:129
 TWebFile.cxx:130
 TWebFile.cxx:131
 TWebFile.cxx:132
 TWebFile.cxx:133
 TWebFile.cxx:134
 TWebFile.cxx:135
 TWebFile.cxx:136
 TWebFile.cxx:137
 TWebFile.cxx:138
 TWebFile.cxx:139
 TWebFile.cxx:140
 TWebFile.cxx:141
 TWebFile.cxx:142
 TWebFile.cxx:143
 TWebFile.cxx:144
 TWebFile.cxx:145
 TWebFile.cxx:146
 TWebFile.cxx:147
 TWebFile.cxx:148
 TWebFile.cxx:149
 TWebFile.cxx:150
 TWebFile.cxx:151
 TWebFile.cxx:152
 TWebFile.cxx:153
 TWebFile.cxx:154
 TWebFile.cxx:155
 TWebFile.cxx:156
 TWebFile.cxx:157
 TWebFile.cxx:158
 TWebFile.cxx:159
 TWebFile.cxx:160
 TWebFile.cxx:161
 TWebFile.cxx:162
 TWebFile.cxx:163
 TWebFile.cxx:164
 TWebFile.cxx:165
 TWebFile.cxx:166
 TWebFile.cxx:167
 TWebFile.cxx:168
 TWebFile.cxx:169
 TWebFile.cxx:170
 TWebFile.cxx:171
 TWebFile.cxx:172
 TWebFile.cxx:173
 TWebFile.cxx:174
 TWebFile.cxx:175
 TWebFile.cxx:176
 TWebFile.cxx:177
 TWebFile.cxx:178
 TWebFile.cxx:179
 TWebFile.cxx:180
 TWebFile.cxx:181
 TWebFile.cxx:182
 TWebFile.cxx:183
 TWebFile.cxx:184
 TWebFile.cxx:185
 TWebFile.cxx:186
 TWebFile.cxx:187
 TWebFile.cxx:188
 TWebFile.cxx:189
 TWebFile.cxx:190
 TWebFile.cxx:191
 TWebFile.cxx:192
 TWebFile.cxx:193
 TWebFile.cxx:194
 TWebFile.cxx:195
 TWebFile.cxx:196
 TWebFile.cxx:197
 TWebFile.cxx:198
 TWebFile.cxx:199
 TWebFile.cxx:200
 TWebFile.cxx:201
 TWebFile.cxx:202
 TWebFile.cxx:203
 TWebFile.cxx:204
 TWebFile.cxx:205
 TWebFile.cxx:206
 TWebFile.cxx:207
 TWebFile.cxx:208
 TWebFile.cxx:209
 TWebFile.cxx:210
 TWebFile.cxx:211
 TWebFile.cxx:212
 TWebFile.cxx:213
 TWebFile.cxx:214
 TWebFile.cxx:215
 TWebFile.cxx:216
 TWebFile.cxx:217
 TWebFile.cxx:218
 TWebFile.cxx:219
 TWebFile.cxx:220
 TWebFile.cxx:221
 TWebFile.cxx:222
 TWebFile.cxx:223
 TWebFile.cxx:224
 TWebFile.cxx:225
 TWebFile.cxx:226
 TWebFile.cxx:227
 TWebFile.cxx:228
 TWebFile.cxx:229
 TWebFile.cxx:230
 TWebFile.cxx:231
 TWebFile.cxx:232
 TWebFile.cxx:233
 TWebFile.cxx:234
 TWebFile.cxx:235
 TWebFile.cxx:236
 TWebFile.cxx:237
 TWebFile.cxx:238
 TWebFile.cxx:239
 TWebFile.cxx:240
 TWebFile.cxx:241
 TWebFile.cxx:242
 TWebFile.cxx:243
 TWebFile.cxx:244
 TWebFile.cxx:245
 TWebFile.cxx:246
 TWebFile.cxx:247
 TWebFile.cxx:248
 TWebFile.cxx:249
 TWebFile.cxx:250
 TWebFile.cxx:251
 TWebFile.cxx:252
 TWebFile.cxx:253
 TWebFile.cxx:254
 TWebFile.cxx:255
 TWebFile.cxx:256
 TWebFile.cxx:257
 TWebFile.cxx:258
 TWebFile.cxx:259
 TWebFile.cxx:260
 TWebFile.cxx:261
 TWebFile.cxx:262
 TWebFile.cxx:263
 TWebFile.cxx:264
 TWebFile.cxx:265
 TWebFile.cxx:266
 TWebFile.cxx:267
 TWebFile.cxx:268
 TWebFile.cxx:269
 TWebFile.cxx:270
 TWebFile.cxx:271
 TWebFile.cxx:272
 TWebFile.cxx:273
 TWebFile.cxx:274
 TWebFile.cxx:275
 TWebFile.cxx:276
 TWebFile.cxx:277
 TWebFile.cxx:278
 TWebFile.cxx:279
 TWebFile.cxx:280
 TWebFile.cxx:281
 TWebFile.cxx:282
 TWebFile.cxx:283
 TWebFile.cxx:284
 TWebFile.cxx:285
 TWebFile.cxx:286
 TWebFile.cxx:287
 TWebFile.cxx:288
 TWebFile.cxx:289
 TWebFile.cxx:290
 TWebFile.cxx:291
 TWebFile.cxx:292
 TWebFile.cxx:293
 TWebFile.cxx:294
 TWebFile.cxx:295
 TWebFile.cxx:296
 TWebFile.cxx:297
 TWebFile.cxx:298
 TWebFile.cxx:299
 TWebFile.cxx:300
 TWebFile.cxx:301
 TWebFile.cxx:302
 TWebFile.cxx:303
 TWebFile.cxx:304
 TWebFile.cxx:305
 TWebFile.cxx:306
 TWebFile.cxx:307
 TWebFile.cxx:308
 TWebFile.cxx:309
 TWebFile.cxx:310
 TWebFile.cxx:311
 TWebFile.cxx:312
 TWebFile.cxx:313
 TWebFile.cxx:314
 TWebFile.cxx:315
 TWebFile.cxx:316
 TWebFile.cxx:317
 TWebFile.cxx:318
 TWebFile.cxx:319
 TWebFile.cxx:320
 TWebFile.cxx:321
 TWebFile.cxx:322
 TWebFile.cxx:323
 TWebFile.cxx:324
 TWebFile.cxx:325
 TWebFile.cxx:326
 TWebFile.cxx:327
 TWebFile.cxx:328
 TWebFile.cxx:329
 TWebFile.cxx:330
 TWebFile.cxx:331
 TWebFile.cxx:332
 TWebFile.cxx:333
 TWebFile.cxx:334
 TWebFile.cxx:335
 TWebFile.cxx:336
 TWebFile.cxx:337
 TWebFile.cxx:338
 TWebFile.cxx:339
 TWebFile.cxx:340
 TWebFile.cxx:341
 TWebFile.cxx:342
 TWebFile.cxx:343
 TWebFile.cxx:344
 TWebFile.cxx:345
 TWebFile.cxx:346
 TWebFile.cxx:347
 TWebFile.cxx:348
 TWebFile.cxx:349
 TWebFile.cxx:350
 TWebFile.cxx:351
 TWebFile.cxx:352
 TWebFile.cxx:353
 TWebFile.cxx:354
 TWebFile.cxx:355
 TWebFile.cxx:356
 TWebFile.cxx:357
 TWebFile.cxx:358
 TWebFile.cxx:359
 TWebFile.cxx:360
 TWebFile.cxx:361
 TWebFile.cxx:362
 TWebFile.cxx:363
 TWebFile.cxx:364
 TWebFile.cxx:365
 TWebFile.cxx:366
 TWebFile.cxx:367
 TWebFile.cxx:368
 TWebFile.cxx:369
 TWebFile.cxx:370
 TWebFile.cxx:371
 TWebFile.cxx:372
 TWebFile.cxx:373
 TWebFile.cxx:374
 TWebFile.cxx:375
 TWebFile.cxx:376
 TWebFile.cxx:377
 TWebFile.cxx:378
 TWebFile.cxx:379
 TWebFile.cxx:380
 TWebFile.cxx:381
 TWebFile.cxx:382
 TWebFile.cxx:383
 TWebFile.cxx:384
 TWebFile.cxx:385
 TWebFile.cxx:386
 TWebFile.cxx:387
 TWebFile.cxx:388
 TWebFile.cxx:389
 TWebFile.cxx:390
 TWebFile.cxx:391
 TWebFile.cxx:392
 TWebFile.cxx:393
 TWebFile.cxx:394
 TWebFile.cxx:395
 TWebFile.cxx:396
 TWebFile.cxx:397
 TWebFile.cxx:398
 TWebFile.cxx:399
 TWebFile.cxx:400
 TWebFile.cxx:401
 TWebFile.cxx:402
 TWebFile.cxx:403
 TWebFile.cxx:404
 TWebFile.cxx:405
 TWebFile.cxx:406
 TWebFile.cxx:407
 TWebFile.cxx:408
 TWebFile.cxx:409
 TWebFile.cxx:410
 TWebFile.cxx:411
 TWebFile.cxx:412
 TWebFile.cxx:413
 TWebFile.cxx:414
 TWebFile.cxx:415
 TWebFile.cxx:416
 TWebFile.cxx:417
 TWebFile.cxx:418
 TWebFile.cxx:419
 TWebFile.cxx:420
 TWebFile.cxx:421
 TWebFile.cxx:422
 TWebFile.cxx:423
 TWebFile.cxx:424
 TWebFile.cxx:425
 TWebFile.cxx:426
 TWebFile.cxx:427
 TWebFile.cxx:428
 TWebFile.cxx:429
 TWebFile.cxx:430
 TWebFile.cxx:431
 TWebFile.cxx:432
 TWebFile.cxx:433
 TWebFile.cxx:434
 TWebFile.cxx:435
 TWebFile.cxx:436
 TWebFile.cxx:437
 TWebFile.cxx:438
 TWebFile.cxx:439
 TWebFile.cxx:440
 TWebFile.cxx:441
 TWebFile.cxx:442
 TWebFile.cxx:443
 TWebFile.cxx:444
 TWebFile.cxx:445
 TWebFile.cxx:446
 TWebFile.cxx:447
 TWebFile.cxx:448
 TWebFile.cxx:449
 TWebFile.cxx:450
 TWebFile.cxx:451
 TWebFile.cxx:452
 TWebFile.cxx:453
 TWebFile.cxx:454
 TWebFile.cxx:455
 TWebFile.cxx:456
 TWebFile.cxx:457
 TWebFile.cxx:458
 TWebFile.cxx:459
 TWebFile.cxx:460
 TWebFile.cxx:461
 TWebFile.cxx:462
 TWebFile.cxx:463
 TWebFile.cxx:464
 TWebFile.cxx:465
 TWebFile.cxx:466
 TWebFile.cxx:467
 TWebFile.cxx:468
 TWebFile.cxx:469
 TWebFile.cxx:470
 TWebFile.cxx:471
 TWebFile.cxx:472
 TWebFile.cxx:473
 TWebFile.cxx:474
 TWebFile.cxx:475
 TWebFile.cxx:476
 TWebFile.cxx:477
 TWebFile.cxx:478
 TWebFile.cxx:479
 TWebFile.cxx:480
 TWebFile.cxx:481
 TWebFile.cxx:482
 TWebFile.cxx:483
 TWebFile.cxx:484
 TWebFile.cxx:485
 TWebFile.cxx:486
 TWebFile.cxx:487
 TWebFile.cxx:488
 TWebFile.cxx:489
 TWebFile.cxx:490
 TWebFile.cxx:491
 TWebFile.cxx:492
 TWebFile.cxx:493
 TWebFile.cxx:494
 TWebFile.cxx:495
 TWebFile.cxx:496
 TWebFile.cxx:497
 TWebFile.cxx:498
 TWebFile.cxx:499
 TWebFile.cxx:500
 TWebFile.cxx:501
 TWebFile.cxx:502
 TWebFile.cxx:503
 TWebFile.cxx:504
 TWebFile.cxx:505
 TWebFile.cxx:506
 TWebFile.cxx:507
 TWebFile.cxx:508
 TWebFile.cxx:509
 TWebFile.cxx:510
 TWebFile.cxx:511
 TWebFile.cxx:512
 TWebFile.cxx:513
 TWebFile.cxx:514
 TWebFile.cxx:515
 TWebFile.cxx:516
 TWebFile.cxx:517
 TWebFile.cxx:518
 TWebFile.cxx:519
 TWebFile.cxx:520
 TWebFile.cxx:521
 TWebFile.cxx:522
 TWebFile.cxx:523
 TWebFile.cxx:524
 TWebFile.cxx:525
 TWebFile.cxx:526
 TWebFile.cxx:527
 TWebFile.cxx:528
 TWebFile.cxx:529
 TWebFile.cxx:530
 TWebFile.cxx:531
 TWebFile.cxx:532
 TWebFile.cxx:533
 TWebFile.cxx:534
 TWebFile.cxx:535
 TWebFile.cxx:536
 TWebFile.cxx:537
 TWebFile.cxx:538
 TWebFile.cxx:539
 TWebFile.cxx:540
 TWebFile.cxx:541
 TWebFile.cxx:542
 TWebFile.cxx:543
 TWebFile.cxx:544
 TWebFile.cxx:545
 TWebFile.cxx:546
 TWebFile.cxx:547
 TWebFile.cxx:548
 TWebFile.cxx:549
 TWebFile.cxx:550
 TWebFile.cxx:551
 TWebFile.cxx:552
 TWebFile.cxx:553
 TWebFile.cxx:554
 TWebFile.cxx:555
 TWebFile.cxx:556
 TWebFile.cxx:557
 TWebFile.cxx:558
 TWebFile.cxx:559
 TWebFile.cxx:560
 TWebFile.cxx:561
 TWebFile.cxx:562
 TWebFile.cxx:563
 TWebFile.cxx:564
 TWebFile.cxx:565
 TWebFile.cxx:566
 TWebFile.cxx:567
 TWebFile.cxx:568
 TWebFile.cxx:569
 TWebFile.cxx:570
 TWebFile.cxx:571
 TWebFile.cxx:572
 TWebFile.cxx:573
 TWebFile.cxx:574
 TWebFile.cxx:575
 TWebFile.cxx:576
 TWebFile.cxx:577
 TWebFile.cxx:578
 TWebFile.cxx:579
 TWebFile.cxx:580
 TWebFile.cxx:581
 TWebFile.cxx:582
 TWebFile.cxx:583
 TWebFile.cxx:584
 TWebFile.cxx:585
 TWebFile.cxx:586
 TWebFile.cxx:587
 TWebFile.cxx:588
 TWebFile.cxx:589
 TWebFile.cxx:590
 TWebFile.cxx:591
 TWebFile.cxx:592
 TWebFile.cxx:593
 TWebFile.cxx:594
 TWebFile.cxx:595
 TWebFile.cxx:596
 TWebFile.cxx:597
 TWebFile.cxx:598
 TWebFile.cxx:599
 TWebFile.cxx:600
 TWebFile.cxx:601
 TWebFile.cxx:602
 TWebFile.cxx:603
 TWebFile.cxx:604
 TWebFile.cxx:605
 TWebFile.cxx:606
 TWebFile.cxx:607
 TWebFile.cxx:608
 TWebFile.cxx:609
 TWebFile.cxx:610
 TWebFile.cxx:611
 TWebFile.cxx:612
 TWebFile.cxx:613
 TWebFile.cxx:614
 TWebFile.cxx:615
 TWebFile.cxx:616
 TWebFile.cxx:617
 TWebFile.cxx:618
 TWebFile.cxx:619
 TWebFile.cxx:620
 TWebFile.cxx:621
 TWebFile.cxx:622
 TWebFile.cxx:623
 TWebFile.cxx:624
 TWebFile.cxx:625
 TWebFile.cxx:626
 TWebFile.cxx:627
 TWebFile.cxx:628
 TWebFile.cxx:629
 TWebFile.cxx:630
 TWebFile.cxx:631
 TWebFile.cxx:632
 TWebFile.cxx:633
 TWebFile.cxx:634
 TWebFile.cxx:635
 TWebFile.cxx:636
 TWebFile.cxx:637
 TWebFile.cxx:638
 TWebFile.cxx:639
 TWebFile.cxx:640
 TWebFile.cxx:641
 TWebFile.cxx:642
 TWebFile.cxx:643
 TWebFile.cxx:644
 TWebFile.cxx:645
 TWebFile.cxx:646
 TWebFile.cxx:647
 TWebFile.cxx:648
 TWebFile.cxx:649
 TWebFile.cxx:650
 TWebFile.cxx:651
 TWebFile.cxx:652
 TWebFile.cxx:653
 TWebFile.cxx:654
 TWebFile.cxx:655
 TWebFile.cxx:656
 TWebFile.cxx:657
 TWebFile.cxx:658
 TWebFile.cxx:659
 TWebFile.cxx:660
 TWebFile.cxx:661
 TWebFile.cxx:662
 TWebFile.cxx:663
 TWebFile.cxx:664
 TWebFile.cxx:665
 TWebFile.cxx:666
 TWebFile.cxx:667
 TWebFile.cxx:668
 TWebFile.cxx:669
 TWebFile.cxx:670
 TWebFile.cxx:671
 TWebFile.cxx:672
 TWebFile.cxx:673
 TWebFile.cxx:674
 TWebFile.cxx:675
 TWebFile.cxx:676
 TWebFile.cxx:677
 TWebFile.cxx:678
 TWebFile.cxx:679
 TWebFile.cxx:680
 TWebFile.cxx:681
 TWebFile.cxx:682
 TWebFile.cxx:683
 TWebFile.cxx:684
 TWebFile.cxx:685
 TWebFile.cxx:686
 TWebFile.cxx:687
 TWebFile.cxx:688
 TWebFile.cxx:689
 TWebFile.cxx:690
 TWebFile.cxx:691
 TWebFile.cxx:692
 TWebFile.cxx:693
 TWebFile.cxx:694
 TWebFile.cxx:695
 TWebFile.cxx:696
 TWebFile.cxx:697
 TWebFile.cxx:698
 TWebFile.cxx:699
 TWebFile.cxx:700
 TWebFile.cxx:701
 TWebFile.cxx:702
 TWebFile.cxx:703
 TWebFile.cxx:704
 TWebFile.cxx:705
 TWebFile.cxx:706
 TWebFile.cxx:707
 TWebFile.cxx:708
 TWebFile.cxx:709
 TWebFile.cxx:710
 TWebFile.cxx:711
 TWebFile.cxx:712
 TWebFile.cxx:713
 TWebFile.cxx:714
 TWebFile.cxx:715
 TWebFile.cxx:716
 TWebFile.cxx:717
 TWebFile.cxx:718
 TWebFile.cxx:719
 TWebFile.cxx:720
 TWebFile.cxx:721
 TWebFile.cxx:722
 TWebFile.cxx:723
 TWebFile.cxx:724
 TWebFile.cxx:725
 TWebFile.cxx:726
 TWebFile.cxx:727
 TWebFile.cxx:728
 TWebFile.cxx:729
 TWebFile.cxx:730
 TWebFile.cxx:731
 TWebFile.cxx:732
 TWebFile.cxx:733
 TWebFile.cxx:734
 TWebFile.cxx:735
 TWebFile.cxx:736
 TWebFile.cxx:737
 TWebFile.cxx:738
 TWebFile.cxx:739
 TWebFile.cxx:740
 TWebFile.cxx:741
 TWebFile.cxx:742
 TWebFile.cxx:743
 TWebFile.cxx:744
 TWebFile.cxx:745
 TWebFile.cxx:746
 TWebFile.cxx:747
 TWebFile.cxx:748
 TWebFile.cxx:749
 TWebFile.cxx:750
 TWebFile.cxx:751
 TWebFile.cxx:752
 TWebFile.cxx:753
 TWebFile.cxx:754
 TWebFile.cxx:755
 TWebFile.cxx:756
 TWebFile.cxx:757
 TWebFile.cxx:758
 TWebFile.cxx:759
 TWebFile.cxx:760
 TWebFile.cxx:761
 TWebFile.cxx:762
 TWebFile.cxx:763
 TWebFile.cxx:764
 TWebFile.cxx:765
 TWebFile.cxx:766
 TWebFile.cxx:767
 TWebFile.cxx:768
 TWebFile.cxx:769
 TWebFile.cxx:770
 TWebFile.cxx:771
 TWebFile.cxx:772
 TWebFile.cxx:773
 TWebFile.cxx:774
 TWebFile.cxx:775
 TWebFile.cxx:776
 TWebFile.cxx:777
 TWebFile.cxx:778
 TWebFile.cxx:779
 TWebFile.cxx:780
 TWebFile.cxx:781
 TWebFile.cxx:782
 TWebFile.cxx:783
 TWebFile.cxx:784
 TWebFile.cxx:785
 TWebFile.cxx:786
 TWebFile.cxx:787
 TWebFile.cxx:788
 TWebFile.cxx:789
 TWebFile.cxx:790
 TWebFile.cxx:791
 TWebFile.cxx:792
 TWebFile.cxx:793
 TWebFile.cxx:794
 TWebFile.cxx:795
 TWebFile.cxx:796
 TWebFile.cxx:797
 TWebFile.cxx:798
 TWebFile.cxx:799
 TWebFile.cxx:800
 TWebFile.cxx:801
 TWebFile.cxx:802
 TWebFile.cxx:803
 TWebFile.cxx:804
 TWebFile.cxx:805
 TWebFile.cxx:806
 TWebFile.cxx:807
 TWebFile.cxx:808
 TWebFile.cxx:809
 TWebFile.cxx:810
 TWebFile.cxx:811
 TWebFile.cxx:812
 TWebFile.cxx:813
 TWebFile.cxx:814
 TWebFile.cxx:815
 TWebFile.cxx:816
 TWebFile.cxx:817
 TWebFile.cxx:818
 TWebFile.cxx:819
 TWebFile.cxx:820
 TWebFile.cxx:821
 TWebFile.cxx:822
 TWebFile.cxx:823
 TWebFile.cxx:824
 TWebFile.cxx:825
 TWebFile.cxx:826
 TWebFile.cxx:827
 TWebFile.cxx:828
 TWebFile.cxx:829
 TWebFile.cxx:830
 TWebFile.cxx:831
 TWebFile.cxx:832
 TWebFile.cxx:833
 TWebFile.cxx:834
 TWebFile.cxx:835
 TWebFile.cxx:836
 TWebFile.cxx:837
 TWebFile.cxx:838
 TWebFile.cxx:839
 TWebFile.cxx:840
 TWebFile.cxx:841
 TWebFile.cxx:842
 TWebFile.cxx:843
 TWebFile.cxx:844
 TWebFile.cxx:845
 TWebFile.cxx:846
 TWebFile.cxx:847
 TWebFile.cxx:848
 TWebFile.cxx:849
 TWebFile.cxx:850
 TWebFile.cxx:851
 TWebFile.cxx:852
 TWebFile.cxx:853
 TWebFile.cxx:854
 TWebFile.cxx:855
 TWebFile.cxx:856
 TWebFile.cxx:857
 TWebFile.cxx:858
 TWebFile.cxx:859
 TWebFile.cxx:860
 TWebFile.cxx:861
 TWebFile.cxx:862
 TWebFile.cxx:863
 TWebFile.cxx:864
 TWebFile.cxx:865
 TWebFile.cxx:866
 TWebFile.cxx:867
 TWebFile.cxx:868
 TWebFile.cxx:869
 TWebFile.cxx:870
 TWebFile.cxx:871
 TWebFile.cxx:872
 TWebFile.cxx:873
 TWebFile.cxx:874
 TWebFile.cxx:875
 TWebFile.cxx:876
 TWebFile.cxx:877
 TWebFile.cxx:878
 TWebFile.cxx:879
 TWebFile.cxx:880
 TWebFile.cxx:881
 TWebFile.cxx:882
 TWebFile.cxx:883
 TWebFile.cxx:884
 TWebFile.cxx:885
 TWebFile.cxx:886
 TWebFile.cxx:887
 TWebFile.cxx:888
 TWebFile.cxx:889
 TWebFile.cxx:890
 TWebFile.cxx:891
 TWebFile.cxx:892
 TWebFile.cxx:893
 TWebFile.cxx:894
 TWebFile.cxx:895
 TWebFile.cxx:896
 TWebFile.cxx:897
 TWebFile.cxx:898
 TWebFile.cxx:899
 TWebFile.cxx:900
 TWebFile.cxx:901
 TWebFile.cxx:902
 TWebFile.cxx:903
 TWebFile.cxx:904
 TWebFile.cxx:905
 TWebFile.cxx:906
 TWebFile.cxx:907
 TWebFile.cxx:908
 TWebFile.cxx:909
 TWebFile.cxx:910
 TWebFile.cxx:911
 TWebFile.cxx:912
 TWebFile.cxx:913
 TWebFile.cxx:914
 TWebFile.cxx:915
 TWebFile.cxx:916
 TWebFile.cxx:917
 TWebFile.cxx:918
 TWebFile.cxx:919
 TWebFile.cxx:920
 TWebFile.cxx:921
 TWebFile.cxx:922
 TWebFile.cxx:923
 TWebFile.cxx:924
 TWebFile.cxx:925
 TWebFile.cxx:926
 TWebFile.cxx:927
 TWebFile.cxx:928
 TWebFile.cxx:929
 TWebFile.cxx:930
 TWebFile.cxx:931
 TWebFile.cxx:932
 TWebFile.cxx:933
 TWebFile.cxx:934
 TWebFile.cxx:935
 TWebFile.cxx:936
 TWebFile.cxx:937
 TWebFile.cxx:938
 TWebFile.cxx:939
 TWebFile.cxx:940
 TWebFile.cxx:941
 TWebFile.cxx:942
 TWebFile.cxx:943
 TWebFile.cxx:944
 TWebFile.cxx:945
 TWebFile.cxx:946
 TWebFile.cxx:947
 TWebFile.cxx:948
 TWebFile.cxx:949
 TWebFile.cxx:950
 TWebFile.cxx:951
 TWebFile.cxx:952
 TWebFile.cxx:953
 TWebFile.cxx:954
 TWebFile.cxx:955
 TWebFile.cxx:956
 TWebFile.cxx:957
 TWebFile.cxx:958
 TWebFile.cxx:959
 TWebFile.cxx:960
 TWebFile.cxx:961
 TWebFile.cxx:962
 TWebFile.cxx:963
 TWebFile.cxx:964
 TWebFile.cxx:965
 TWebFile.cxx:966
 TWebFile.cxx:967
 TWebFile.cxx:968
 TWebFile.cxx:969
 TWebFile.cxx:970
 TWebFile.cxx:971
 TWebFile.cxx:972
 TWebFile.cxx:973
 TWebFile.cxx:974
 TWebFile.cxx:975
 TWebFile.cxx:976
 TWebFile.cxx:977
 TWebFile.cxx:978
 TWebFile.cxx:979
 TWebFile.cxx:980
 TWebFile.cxx:981
 TWebFile.cxx:982
 TWebFile.cxx:983
 TWebFile.cxx:984
 TWebFile.cxx:985
 TWebFile.cxx:986
 TWebFile.cxx:987
 TWebFile.cxx:988
 TWebFile.cxx:989
 TWebFile.cxx:990
 TWebFile.cxx:991
 TWebFile.cxx:992
 TWebFile.cxx:993
 TWebFile.cxx:994
 TWebFile.cxx:995
 TWebFile.cxx:996
 TWebFile.cxx:997
 TWebFile.cxx:998
 TWebFile.cxx:999
 TWebFile.cxx:1000
 TWebFile.cxx:1001
 TWebFile.cxx:1002
 TWebFile.cxx:1003
 TWebFile.cxx:1004
 TWebFile.cxx:1005
 TWebFile.cxx:1006
 TWebFile.cxx:1007
 TWebFile.cxx:1008
 TWebFile.cxx:1009
 TWebFile.cxx:1010
 TWebFile.cxx:1011
 TWebFile.cxx:1012
 TWebFile.cxx:1013
 TWebFile.cxx:1014
 TWebFile.cxx:1015
 TWebFile.cxx:1016
 TWebFile.cxx:1017
 TWebFile.cxx:1018
 TWebFile.cxx:1019
 TWebFile.cxx:1020
 TWebFile.cxx:1021
 TWebFile.cxx:1022
 TWebFile.cxx:1023
 TWebFile.cxx:1024
 TWebFile.cxx:1025
 TWebFile.cxx:1026
 TWebFile.cxx:1027
 TWebFile.cxx:1028
 TWebFile.cxx:1029
 TWebFile.cxx:1030
 TWebFile.cxx:1031
 TWebFile.cxx:1032
 TWebFile.cxx:1033
 TWebFile.cxx:1034
 TWebFile.cxx:1035
 TWebFile.cxx:1036
 TWebFile.cxx:1037
 TWebFile.cxx:1038
 TWebFile.cxx:1039
 TWebFile.cxx:1040
 TWebFile.cxx:1041
 TWebFile.cxx:1042
 TWebFile.cxx:1043
 TWebFile.cxx:1044
 TWebFile.cxx:1045
 TWebFile.cxx:1046
 TWebFile.cxx:1047
 TWebFile.cxx:1048
 TWebFile.cxx:1049
 TWebFile.cxx:1050
 TWebFile.cxx:1051
 TWebFile.cxx:1052
 TWebFile.cxx:1053
 TWebFile.cxx:1054
 TWebFile.cxx:1055
 TWebFile.cxx:1056
 TWebFile.cxx:1057
 TWebFile.cxx:1058
 TWebFile.cxx:1059
 TWebFile.cxx:1060
 TWebFile.cxx:1061
 TWebFile.cxx:1062
 TWebFile.cxx:1063
 TWebFile.cxx:1064
 TWebFile.cxx:1065
 TWebFile.cxx:1066
 TWebFile.cxx:1067
 TWebFile.cxx:1068
 TWebFile.cxx:1069
 TWebFile.cxx:1070
 TWebFile.cxx:1071
 TWebFile.cxx:1072
 TWebFile.cxx:1073
 TWebFile.cxx:1074
 TWebFile.cxx:1075
 TWebFile.cxx:1076
 TWebFile.cxx:1077
 TWebFile.cxx:1078
 TWebFile.cxx:1079
 TWebFile.cxx:1080
 TWebFile.cxx:1081
 TWebFile.cxx:1082
 TWebFile.cxx:1083
 TWebFile.cxx:1084
 TWebFile.cxx:1085
 TWebFile.cxx:1086
 TWebFile.cxx:1087
 TWebFile.cxx:1088
 TWebFile.cxx:1089
 TWebFile.cxx:1090
 TWebFile.cxx:1091
 TWebFile.cxx:1092
 TWebFile.cxx:1093
 TWebFile.cxx:1094
 TWebFile.cxx:1095
 TWebFile.cxx:1096
 TWebFile.cxx:1097
 TWebFile.cxx:1098
 TWebFile.cxx:1099
 TWebFile.cxx:1100
 TWebFile.cxx:1101
 TWebFile.cxx:1102
 TWebFile.cxx:1103
 TWebFile.cxx:1104
 TWebFile.cxx:1105
 TWebFile.cxx:1106
 TWebFile.cxx:1107
 TWebFile.cxx:1108
 TWebFile.cxx:1109
 TWebFile.cxx:1110
 TWebFile.cxx:1111
 TWebFile.cxx:1112
 TWebFile.cxx:1113
 TWebFile.cxx:1114
 TWebFile.cxx:1115
 TWebFile.cxx:1116
 TWebFile.cxx:1117
 TWebFile.cxx:1118
 TWebFile.cxx:1119
 TWebFile.cxx:1120
 TWebFile.cxx:1121
 TWebFile.cxx:1122
 TWebFile.cxx:1123
 TWebFile.cxx:1124
 TWebFile.cxx:1125
 TWebFile.cxx:1126
 TWebFile.cxx:1127
 TWebFile.cxx:1128
 TWebFile.cxx:1129
 TWebFile.cxx:1130
 TWebFile.cxx:1131
 TWebFile.cxx:1132
 TWebFile.cxx:1133
 TWebFile.cxx:1134
 TWebFile.cxx:1135
 TWebFile.cxx:1136
 TWebFile.cxx:1137
 TWebFile.cxx:1138
 TWebFile.cxx:1139
 TWebFile.cxx:1140
 TWebFile.cxx:1141
 TWebFile.cxx:1142
 TWebFile.cxx:1143
 TWebFile.cxx:1144
 TWebFile.cxx:1145
 TWebFile.cxx:1146
 TWebFile.cxx:1147
 TWebFile.cxx:1148
 TWebFile.cxx:1149
 TWebFile.cxx:1150
 TWebFile.cxx:1151
 TWebFile.cxx:1152
 TWebFile.cxx:1153
 TWebFile.cxx:1154
 TWebFile.cxx:1155
 TWebFile.cxx:1156
 TWebFile.cxx:1157
 TWebFile.cxx:1158
 TWebFile.cxx:1159
 TWebFile.cxx:1160
 TWebFile.cxx:1161
 TWebFile.cxx:1162
 TWebFile.cxx:1163
 TWebFile.cxx:1164
 TWebFile.cxx:1165
 TWebFile.cxx:1166
 TWebFile.cxx:1167
 TWebFile.cxx:1168
 TWebFile.cxx:1169
 TWebFile.cxx:1170
 TWebFile.cxx:1171
 TWebFile.cxx:1172
 TWebFile.cxx:1173
 TWebFile.cxx:1174
 TWebFile.cxx:1175
 TWebFile.cxx:1176
 TWebFile.cxx:1177
 TWebFile.cxx:1178
 TWebFile.cxx:1179
 TWebFile.cxx:1180
 TWebFile.cxx:1181
 TWebFile.cxx:1182
 TWebFile.cxx:1183
 TWebFile.cxx:1184
 TWebFile.cxx:1185
 TWebFile.cxx:1186
 TWebFile.cxx:1187
 TWebFile.cxx:1188
 TWebFile.cxx:1189
 TWebFile.cxx:1190
 TWebFile.cxx:1191
 TWebFile.cxx:1192
 TWebFile.cxx:1193
 TWebFile.cxx:1194
 TWebFile.cxx:1195
 TWebFile.cxx:1196
 TWebFile.cxx:1197
 TWebFile.cxx:1198
 TWebFile.cxx:1199
 TWebFile.cxx:1200
 TWebFile.cxx:1201
 TWebFile.cxx:1202
 TWebFile.cxx:1203
 TWebFile.cxx:1204
 TWebFile.cxx:1205
 TWebFile.cxx:1206
 TWebFile.cxx:1207
 TWebFile.cxx:1208
 TWebFile.cxx:1209
 TWebFile.cxx:1210
 TWebFile.cxx:1211
 TWebFile.cxx:1212
 TWebFile.cxx:1213
 TWebFile.cxx:1214
 TWebFile.cxx:1215
 TWebFile.cxx:1216
 TWebFile.cxx:1217
 TWebFile.cxx:1218
 TWebFile.cxx:1219
 TWebFile.cxx:1220
 TWebFile.cxx:1221
 TWebFile.cxx:1222
 TWebFile.cxx:1223
 TWebFile.cxx:1224
 TWebFile.cxx:1225
 TWebFile.cxx:1226
 TWebFile.cxx:1227
 TWebFile.cxx:1228
 TWebFile.cxx:1229
 TWebFile.cxx:1230
 TWebFile.cxx:1231
 TWebFile.cxx:1232
 TWebFile.cxx:1233
 TWebFile.cxx:1234
 TWebFile.cxx:1235
 TWebFile.cxx:1236
 TWebFile.cxx:1237
 TWebFile.cxx:1238
 TWebFile.cxx:1239
 TWebFile.cxx:1240
 TWebFile.cxx:1241
 TWebFile.cxx:1242
 TWebFile.cxx:1243
 TWebFile.cxx:1244
 TWebFile.cxx:1245
 TWebFile.cxx:1246
 TWebFile.cxx:1247
 TWebFile.cxx:1248
 TWebFile.cxx:1249
 TWebFile.cxx:1250
 TWebFile.cxx:1251
 TWebFile.cxx:1252
 TWebFile.cxx:1253
 TWebFile.cxx:1254
 TWebFile.cxx:1255
 TWebFile.cxx:1256
 TWebFile.cxx:1257
 TWebFile.cxx:1258
 TWebFile.cxx:1259
 TWebFile.cxx:1260
 TWebFile.cxx:1261
 TWebFile.cxx:1262
 TWebFile.cxx:1263
 TWebFile.cxx:1264
 TWebFile.cxx:1265
 TWebFile.cxx:1266
 TWebFile.cxx:1267
 TWebFile.cxx:1268
 TWebFile.cxx:1269
 TWebFile.cxx:1270
 TWebFile.cxx:1271
 TWebFile.cxx:1272
 TWebFile.cxx:1273
 TWebFile.cxx:1274
 TWebFile.cxx:1275
 TWebFile.cxx:1276
 TWebFile.cxx:1277
 TWebFile.cxx:1278
 TWebFile.cxx:1279
 TWebFile.cxx:1280
 TWebFile.cxx:1281
 TWebFile.cxx:1282
 TWebFile.cxx:1283
 TWebFile.cxx:1284
 TWebFile.cxx:1285
 TWebFile.cxx:1286
 TWebFile.cxx:1287
 TWebFile.cxx:1288
 TWebFile.cxx:1289
 TWebFile.cxx:1290
 TWebFile.cxx:1291
 TWebFile.cxx:1292
 TWebFile.cxx:1293
 TWebFile.cxx:1294
 TWebFile.cxx:1295
 TWebFile.cxx:1296
 TWebFile.cxx:1297
 TWebFile.cxx:1298
 TWebFile.cxx:1299
 TWebFile.cxx:1300
 TWebFile.cxx:1301
 TWebFile.cxx:1302
 TWebFile.cxx:1303
 TWebFile.cxx:1304
 TWebFile.cxx:1305
 TWebFile.cxx:1306
 TWebFile.cxx:1307
 TWebFile.cxx:1308
 TWebFile.cxx:1309
 TWebFile.cxx:1310
 TWebFile.cxx:1311
 TWebFile.cxx:1312
 TWebFile.cxx:1313
 TWebFile.cxx:1314
 TWebFile.cxx:1315
 TWebFile.cxx:1316
 TWebFile.cxx:1317
 TWebFile.cxx:1318
 TWebFile.cxx:1319
 TWebFile.cxx:1320
 TWebFile.cxx:1321
 TWebFile.cxx:1322
 TWebFile.cxx:1323
 TWebFile.cxx:1324
 TWebFile.cxx:1325
 TWebFile.cxx:1326
 TWebFile.cxx:1327
 TWebFile.cxx:1328
 TWebFile.cxx:1329
 TWebFile.cxx:1330
 TWebFile.cxx:1331
 TWebFile.cxx:1332
 TWebFile.cxx:1333
 TWebFile.cxx:1334
 TWebFile.cxx:1335
 TWebFile.cxx:1336
 TWebFile.cxx:1337
 TWebFile.cxx:1338
 TWebFile.cxx:1339
 TWebFile.cxx:1340
 TWebFile.cxx:1341
 TWebFile.cxx:1342
 TWebFile.cxx:1343
 TWebFile.cxx:1344
 TWebFile.cxx:1345
 TWebFile.cxx:1346
 TWebFile.cxx:1347
 TWebFile.cxx:1348
 TWebFile.cxx:1349
 TWebFile.cxx:1350
 TWebFile.cxx:1351
 TWebFile.cxx:1352
 TWebFile.cxx:1353
 TWebFile.cxx:1354
 TWebFile.cxx:1355
 TWebFile.cxx:1356
 TWebFile.cxx:1357
 TWebFile.cxx:1358
 TWebFile.cxx:1359
 TWebFile.cxx:1360
 TWebFile.cxx:1361
 TWebFile.cxx:1362
 TWebFile.cxx:1363
 TWebFile.cxx:1364
 TWebFile.cxx:1365
 TWebFile.cxx:1366
 TWebFile.cxx:1367
 TWebFile.cxx:1368
 TWebFile.cxx:1369
 TWebFile.cxx:1370
 TWebFile.cxx:1371
 TWebFile.cxx:1372
 TWebFile.cxx:1373
 TWebFile.cxx:1374
 TWebFile.cxx:1375
 TWebFile.cxx:1376
 TWebFile.cxx:1377