ROOT logo
// @(#)root/base:$Id: a94734bd8505d0a8f1833346da666b196a797388 $
// 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TUrl                                                                 //
//                                                                      //
// This class represents a WWW compatible URL.                          //
// It provides member functions to return the different parts of        //
// an URL. The supported url format is:                                 //
//  [proto://][user[:passwd]@]host[:port]/file.ext[#anchor][?options]   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include "TUrl.h"
#include "THashList.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TEnv.h"
#include "TSystem.h"
#include "TMap.h"
#include "TVirtualMutex.h"

TObjArray *TUrl::fgSpecialProtocols = 0;
THashList *TUrl::fgHostFQDNs = 0;

TVirtualMutex *gURLMutex = 0; // local mutex

#ifdef R__COMPLETE_MEM_TERMINATION
namespace {
   class TUrlCleanup {
      TObjArray **fSpecialProtocols;
      THashList **fHostFQDNs;
   public:
      TUrlCleanup(TObjArray **protocols, THashList **hosts) : fSpecialProtocols(protocols),fHostFQDNs(hosts) {}
      ~TUrlCleanup() {
         if (*fSpecialProtocols) (*fSpecialProtocols)->Delete();
         delete *fSpecialProtocols;
         *fSpecialProtocols = 0;
         if (*fHostFQDNs) (*fHostFQDNs)->Delete();
         delete *fHostFQDNs;
         *fHostFQDNs = 0;
      }
   };
}
#endif

ClassImp(TUrl)

//______________________________________________________________________________
TUrl::TUrl(const char *url, Bool_t defaultIsFile)
{
   // Parse url character string and split in its different subcomponents.
   // Use IsValid() to check if URL is legal.
   //
   // url: [proto://][user[:passwd]@]host[:port]/file.ext[?options][#anchor]
   //
   // Known protocols: http, root, proof, ftp, news and any special protocols
   // defined in the rootrc Url.Special key.
   // The default protocol is "http", unless defaultIsFile is true in which
   // case the url is assumed to be of type "file".
   // If a passwd contains a @ it must be escaped by a \\, e.g.
   // "pip@" becomes "pip\\@".
   //
   // Default ports: http=80, root=1094, proof=1093, ftp=20, news=119.
   // Port #1093 has been assigned by IANA (www.iana.org) to proofd.
   // Port #1094 has been assigned by IANA (www.iana.org) to rootd.

   SetUrl(url, defaultIsFile);

#ifdef R__COMPLETE_MEM_TERMINATION
   static TUrlCleanup cleanup(&fgSpecialProtocols,&fgHostFQDNs);
#endif
}

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

   delete fOptionsMap;
}

//______________________________________________________________________________
void TUrl::SetUrl(const char *url, Bool_t defaultIsFile)
{
   // Parse url character string and split in its different subcomponents.
   // Use IsValid() to check if URL is legal.
   //
   // url: [proto://][user[:passwd]@]host[:port]/file.ext[?options][#anchor]
   //
   // Known protocols: http, root, proof, ftp, news and any special protocols
   // defined in the rootrc Url.Special key.
   // The default protocol is "http", unless defaultIsFile is true in which
   // case the url is assumed to be of type "file".
   // If a passwd contains a @ it must be escaped by a \\, e.g.
   // "pip@" becomes "pip\\@".
   //
   // Default ports: http=80, root=1094, proof=1093, ftp=20, news=119.
   // Port #1093 has been assigned by IANA (www.iana.org) to proofd.
   // Port #1094 has been assigned by IANA (www.iana.org) to rootd.

   fOptionsMap = 0;

   if (!url || !url[0]) {
      fPort = -1;
      return;
   }

   // Set defaults
   fUrl        = "";
   fProtocol   = "http";
   fUser       = "";
   fPasswd     = "";
   fHost       = "";
   fPort       = 80;
   fFile       = "";
   fAnchor     = "";
   fOptions    = "";
   fFileOA     = "";
   fHostFQ     = "";

   // if url starts with a / consider it as a file url
   if (url[0] == '/')
      defaultIsFile = kTRUE;

   // Find protocol
   char *s, sav;

   char *u, *u0 = Strip(url);
tryfile:
   u = u0;

   // Handle special protocol cases: "file:", "rfio:", etc.
   for (int i = 0; i < GetSpecialProtocols()->GetEntriesFast(); i++) {
      TObjString *os = (TObjString*) GetSpecialProtocols()->UncheckedAt(i);
      TString s1 = os->GetString();
      int l = s1.Length();
      Bool_t stripoff = kFALSE;
      if (s1.EndsWith("/-")) {
         stripoff = kTRUE;
         s1 = s1.Strip(TString::kTrailing, '-');
         l--;
      }
      if (!strncmp(u, s1, l)) {
         if (s1(0) == '/' && s1(l-1) == '/') {
            // case whith file namespace like: /alien/user/file.root
            fProtocol = s1(1, l-2);
            if (stripoff)
               l--;    // strip off namespace prefix from file name
            else
               l = 0;  // leave namespace prefix as part of file name
         } else {
            // case with protocol, like: rfio:machine:/data/file.root
            fProtocol = s1(0, l-1);
         }
         if (!strncmp(u+l, "//", 2))
            u += l+2;
         else
            u += l;
         fPort = 0;

         FindFile(u, kFALSE);

         delete [] u0;
         return;
      }
   }

   u = u0;

   char *x, *t, *s2;
   // allow x:/path as Windows filename
   if ((s = strstr(u, ":/")) && u+1 != s) {
      if (*(s+2) != '/') {
         Error("TUrl", "%s malformed, URL must contain \"://\"", u0);
         fPort = -1;
         goto cleanup;
      }
      sav = *s;
      *s = 0;
      SetProtocol(u, kTRUE);
      *s = sav;
      s += 3;
      // allow url of form: "proto://"
   } else {
      if (defaultIsFile) {
         char *newu = new char [strlen("file:") + strlen(u0) + 1];
         sprintf(newu, "file:%s", u0);
         delete [] u0;
         u0 = newu;
         goto tryfile;
      }
      s = u;
   }

   // Find user and passwd
   u = s;
   t = s;
again:
   if ((s = strchr(t, '@')) && (
       ((x = strchr(t, '/')) && s < x) ||
       ((x = strchr(t, '?')) && s < x) ||
       ((x = strchr(t, '#')) && s < x) ||
       (!strchr(t, '/'))
      )) {
      if (*(s-1) == '\\') {
         t = s+1;
         goto again;
      }
      sav = *s;
      *s = 0;
      if ((s2 = strchr(u, ':'))) {
         *s2 = 0;
         fUser = u;
         *s2 = ':';
         s2++;
         if (*s2) {
            fPasswd = s2;
            fPasswd.ReplaceAll("\\@", "@");
         }
      } else
         fUser = u;
      *s = sav;
      s++;
   } else
      s = u;

   // Find host
   u = s;
   if ((s = strchr(u, ':')) || (s = strchr(u, '/')) || (s = strchr(u, '?')) || (s = strchr(u, '#'))) {
      if ((strchr (u, ':') > strchr(u, '/')) && (strchr (u, '/')))
         s = strchr(u, '/');
      sav = *s;
      *s = 0;
      fHost = u;
      *s = sav;
      if (sav == ':') {
         s++;
         // Get port #
         if (!*s) {
            fPort = -1;
            goto cleanup;
         }
         u = s;
         if ((s = strchr(u, '/')) || (s = strchr(u, '?')) || (s = strchr(u, '#'))) {
            sav = *s;
            *s = 0;
            fPort = atoi(u);
            *s = sav;
         } else {
            fPort = atoi(u);
            goto cleanup;
         }
      }
   } else {
      fHost = u;
      goto cleanup;
   }

   if (!*s) goto cleanup;

   // Find file
   u = s;
   if (*u == '/' && fHost.Length())
      u++;

   FindFile(u);

cleanup:
   delete [] u0;
}

//______________________________________________________________________________
void TUrl::FindFile(char *u, Bool_t stripDoubleSlash)
{
   // Find file and optionally anchor and options.

   char *s, sav;

   // Locate anchor and options, if any
   char *opt = strchr(u, '?');
   char *anc = strchr(u, '#');

   // URL invalid if anchor is coming before the options
   if (opt && anc && opt > anc) {
      fPort = -1;
      return;
   }

   if ((s = opt) || (s = anc)) {
      sav = *s;
      *s = 0;
      fFile = u;
      if (stripDoubleSlash)
         fFile.ReplaceAll("//", "/");
      *s = sav;
      s++;
      if (sav == '?') {
         // Get options
         if (!*s) {
            // options string is empty
            return;
         }
         u = s;
         if ((s = strchr(u, '#'))) {
            sav = *s;
            *s = 0;
            fOptions = u;
            *s = sav;
            s++;
         } else {
            fOptions = u;
            return;
         }
      }
      if (!*s) {
         // anchor string is empty
         return;
      }
   } else {
      fFile = u;
      if (stripDoubleSlash)
         fFile.ReplaceAll("//", "/");
      return;
   }

   // Set anchor
   fAnchor = s;
}

//______________________________________________________________________________
TUrl::TUrl(const TUrl &url) : TObject(url)
{
   // TUrl copy ctor.

   fUrl        = url.fUrl;
   fProtocol   = url.fProtocol;
   fUser       = url.fUser;
   fPasswd     = url.fPasswd;
   fHost       = url.fHost;
   fFile       = url.fFile;
   fAnchor     = url.fAnchor;
   fOptions    = url.fOptions;
   fPort       = url.fPort;
   fFileOA     = url.fFileOA;
   fHostFQ     = url.fHostFQ;
   fOptionsMap = 0;
}

//______________________________________________________________________________
TUrl &TUrl::operator=(const TUrl &rhs)
{
   // TUrl assignment operator.

   if (this != &rhs) {
      TObject::operator=(rhs);
      fUrl        = rhs.fUrl;
      fProtocol   = rhs.fProtocol;
      fUser       = rhs.fUser;
      fPasswd     = rhs.fPasswd;
      fHost       = rhs.fHost;
      fFile       = rhs.fFile;
      fAnchor     = rhs.fAnchor;
      fOptions    = rhs.fOptions;
      fPort       = rhs.fPort;
      fFileOA     = rhs.fFileOA;
      fHostFQ     = rhs.fHostFQ;
      fOptionsMap = 0;
   }
   return *this;
}

//______________________________________________________________________________
const char *TUrl::GetUrl(Bool_t withDeflt) const
{
   // Return full URL. If withDflt is kTRUE, explicitly add the port even
   // if it matches the default value for the URL protocol.

   if (((TestBit(kUrlWithDefaultPort) && !withDeflt) ||
       (!TestBit(kUrlWithDefaultPort) && withDeflt)) &&
       TestBit(kUrlHasDefaultPort))
      fUrl = "";

   if (IsValid() && fUrl == "") {
      // Handle special protocol cases: file:, rfio:, etc.
      for (int i = 0; i < GetSpecialProtocols()->GetEntriesFast(); i++) {
         TObjString *os = (TObjString*) GetSpecialProtocols()->UncheckedAt(i);
         TString &s = os->String();
         int l = s.Length();
         if (fProtocol == s(0, l-1)) {
            if (fFile[0] == '/')
               fUrl = fProtocol + "://" + fFile;
            else
               fUrl = fProtocol + ":" + fFile;
            if (fOptions != "") {
               fUrl += "?";
               fUrl += fOptions;
            }
            if (fAnchor != "") {
               fUrl += "#";
               fUrl += fAnchor;
            }
            return fUrl;
         }
      }

      Bool_t deflt = kFALSE;
      if ((!fProtocol.CompareTo("http")  && fPort == 80)   ||
          (fProtocol.BeginsWith("proof") && fPort == 1093) ||
          (fProtocol.BeginsWith("root")  && fPort == 1094) ||
          (!fProtocol.CompareTo("ftp")   && fPort == 20)   ||
          (!fProtocol.CompareTo("news")  && fPort == 119)  ||
          (!fProtocol.CompareTo("https") && fPort == 443)  ||
          fPort == 0) {
         deflt = kTRUE;
         ((TUrl *)this)->SetBit(kUrlHasDefaultPort);
      }

      fUrl = fProtocol + "://";
      if (fUser != "") {
         fUrl += fUser;
         if (fPasswd != "") {
            fUrl += ":";
            TString passwd = fPasswd;
            passwd.ReplaceAll("@", "\\@");
            fUrl += passwd;
         }
         fUrl += "@";
      }
      if (withDeflt)
         ((TUrl*)this)->SetBit(kUrlWithDefaultPort);
      else
         ((TUrl*)this)->ResetBit(kUrlWithDefaultPort);

      if (!deflt || withDeflt) {
         char p[10];
         sprintf(p, "%d", fPort);
         fUrl = fUrl + fHost + ":" + p + "/" + fFile;
      } else
         fUrl = fUrl + fHost + "/" + fFile;
      if (fOptions != "") {
         fUrl += "?";
         fUrl += fOptions;
      }
      if (fAnchor != "") {
         fUrl += "#";
         fUrl += fAnchor;
      }
   }

   fUrl.ReplaceAll("////", "///");
   return fUrl;
}

//______________________________________________________________________________
const char *TUrl::GetHostFQDN() const
{
   // Return fully qualified domain name of url host. If host cannot be
   // resolved or not valid return the host name as originally specified.

   if (fHostFQ == "") {
      // Check if we already resolved it
      TNamed *fqdn = fgHostFQDNs ? (TNamed *) fgHostFQDNs->FindObject(fHost) : 0;
      if (!fqdn) {
         TInetAddress adr(gSystem->GetHostByName(fHost));
         if (adr.IsValid()) {
            fHostFQ = adr.GetHostName();
         } else
            fHostFQ = "-";
         R__LOCKGUARD2(gURLMutex);
         if (!fgHostFQDNs) {
            fgHostFQDNs = new THashList;
            fgHostFQDNs->SetOwner();
         }
         if (fgHostFQDNs && !fgHostFQDNs->FindObject(fHost))
            fgHostFQDNs->Add(new TNamed(fHost,fHostFQ));
      } else {
         fHostFQ = fqdn->GetTitle();
      }
   }
   if (fHostFQ == "-")
      return fHost;
   return fHostFQ;
}

//______________________________________________________________________________
const char *TUrl::GetFileAndOptions() const
{
   // Return the file and its options (the string specified behind the ?).
   // Convenience function useful when the option is used to pass
   // authetication/access information for the specified file.

   if (fFileOA == "") {
      fFileOA = fFile;
      if (fOptions != "") {
         fFileOA += "?";
         fFileOA += fOptions;
      }
      if (fAnchor != "") {
         fFileOA += "#";
         fFileOA += fAnchor;
      }
   }
   return fFileOA;
}

//______________________________________________________________________________
void TUrl::SetProtocol(const char *proto, Bool_t setDefaultPort)
{
   // Set protocol and, optionally, change the port accordingly.

   fProtocol = proto;
   if (setDefaultPort) {
      if (!fProtocol.CompareTo("http"))
         fPort = 80;
      else if (!fProtocol.CompareTo("https"))
         fPort = 443;
      else if (fProtocol.BeginsWith("proof"))  // can also be proofs or proofk
         fPort = 1093;
      else if (fProtocol.BeginsWith("root"))   // can also be roots or rootk
         fPort = 1094;
      else if (!fProtocol.CompareTo("ftp"))
         fPort = 20;
      else if (!fProtocol.CompareTo("news"))
         fPort = 119;
      else {
         // generic protocol (no default port)
         fPort = 0;
      }
   }
   fUrl = "";
}

//______________________________________________________________________________
Int_t TUrl::Compare(const TObject *obj) const
{
   // Compare two urls as strings.

   if (this == obj) return 0;
   if (TUrl::Class() != obj->IsA()) return -1;
   return TString(GetUrl()).CompareTo(((TUrl*)obj)->GetUrl(), TString::kExact);
}

//______________________________________________________________________________
void TUrl::Print(Option_t *) const
{
   // Print URL on stdout.

   if (fPort == -1)
      Printf("Illegal URL");

   Printf("%s", GetUrl());
}

//______________________________________________________________________________
TObjArray *TUrl::GetSpecialProtocols()
{
   // Read the list of special protocols from the rootrc files.
   // These protocols will be parsed in a protocol and a file part,
   // no host or other info will be determined. This is typically
   // used for legacy file descriptions like: rfio:host:/path/file.root.

   static Bool_t usedEnv = kFALSE;

   if (!gEnv) {
      R__LOCKGUARD2(gURLMutex);
      if (!fgSpecialProtocols)
         fgSpecialProtocols = new TObjArray;
      if (fgSpecialProtocols->GetEntriesFast() == 0)
         fgSpecialProtocols->Add(new TObjString("file:"));
      return fgSpecialProtocols;
   }

   if (usedEnv)
      return fgSpecialProtocols;

   R__LOCKGUARD2(gURLMutex);
   if (fgSpecialProtocols)
      fgSpecialProtocols->Delete();

   if (!fgSpecialProtocols)
      fgSpecialProtocols = new TObjArray;

   const char *protos = gEnv->GetValue("Url.Special", "file: rfio: hpss: castor: dcache: dcap:");
   usedEnv = kTRUE;

   if (protos) {
      Int_t cnt = 0;
      char *p = StrDup(protos);
      while (1) {
         TObjString *proto = new TObjString(strtok(!cnt ? p : 0, " "));
         if (proto->String().IsNull()) {
            delete proto;
            break;
         }
         fgSpecialProtocols->Add(proto);
         cnt++;
      }
      delete [] p;
   }
   return fgSpecialProtocols;
}


//______________________________________________________________________________
void TUrl::ParseOptions() const
{
   // Parse URL options into a key/value map.

   if (fOptionsMap) return;

   TString urloptions = GetOptions();
   TObjArray *objOptions = urloptions.Tokenize("&");
   for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
      TString loption = ((TObjString *) objOptions->At(n))->GetName();
      TObjArray *objTags = loption.Tokenize("=");
      if (!fOptionsMap) {
         fOptionsMap = new TMap;
         fOptionsMap->SetOwnerKeyValue();
      }
      if (objTags->GetEntries() == 2) {
         TString key = ((TObjString *) objTags->At(0))->GetName();
         TString value = ((TObjString *) objTags->At(1))->GetName();
         fOptionsMap->Add(new TObjString(key), new TObjString(value));
      } else {
         TString key = ((TObjString *) objTags->At(0))->GetName();
         fOptionsMap->Add(new TObjString(key), 0);
      }
      delete objTags;
   }
   delete objOptions;
}


//______________________________________________________________________________
const char *TUrl::GetValueFromOptions(const char *key) const
{
   // Return a value for a given key from the URL options.
   // Returns 0 in case key is not found.

   if (!key) return 0;
   ParseOptions();
   TObject *option = fOptionsMap ? fOptionsMap->GetValue(key) : 0;
   return (option ? ((TObjString*)fOptionsMap->GetValue(key))->GetName(): 0);
}

//______________________________________________________________________________
Int_t TUrl::GetIntValueFromOptions(const char *key) const
{
   // Return a value for a given key from the URL options as an Int_t,
   // a missing key returns -1.

   if (!key) return -1;
   ParseOptions();
   TObject *option = fOptionsMap ? fOptionsMap->GetValue(key) : 0;
   return (option ? (atoi(((TObjString*)fOptionsMap->GetValue(key))->GetName())) : -1);
}

//______________________________________________________________________________
Bool_t TUrl::HasOption(const char *key) const
{
   // Returns true if the given key appears in the URL options list.
   
   if (!key) return kFALSE;
   ParseOptions();
   
   if (fOptionsMap && fOptionsMap->FindObject(key))
      return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TUrl::CleanRelativePath()
{
   // Recompute the path removing all relative directory jumps via '..'.

   Ssiz_t slash = 0;
   while ( (slash = fFile.Index("/..") ) != kNPOS) {
      // find backwards the next '/'
      Bool_t found = kFALSE;
      for (int l = slash-1; l >=0; l--) {
         if (fFile[l] == '/') {
            // found previous '/'
            fFile.Remove(l, slash+3-l);
            found = kTRUE;
            break;
         }
      }
      if (!found)
        break;
   }
}
 TUrl.cxx:1
 TUrl.cxx:2
 TUrl.cxx:3
 TUrl.cxx:4
 TUrl.cxx:5
 TUrl.cxx:6
 TUrl.cxx:7
 TUrl.cxx:8
 TUrl.cxx:9
 TUrl.cxx:10
 TUrl.cxx:11
 TUrl.cxx:12
 TUrl.cxx:13
 TUrl.cxx:14
 TUrl.cxx:15
 TUrl.cxx:16
 TUrl.cxx:17
 TUrl.cxx:18
 TUrl.cxx:19
 TUrl.cxx:20
 TUrl.cxx:21
 TUrl.cxx:22
 TUrl.cxx:23
 TUrl.cxx:24
 TUrl.cxx:25
 TUrl.cxx:26
 TUrl.cxx:27
 TUrl.cxx:28
 TUrl.cxx:29
 TUrl.cxx:30
 TUrl.cxx:31
 TUrl.cxx:32
 TUrl.cxx:33
 TUrl.cxx:34
 TUrl.cxx:35
 TUrl.cxx:36
 TUrl.cxx:37
 TUrl.cxx:38
 TUrl.cxx:39
 TUrl.cxx:40
 TUrl.cxx:41
 TUrl.cxx:42
 TUrl.cxx:43
 TUrl.cxx:44
 TUrl.cxx:45
 TUrl.cxx:46
 TUrl.cxx:47
 TUrl.cxx:48
 TUrl.cxx:49
 TUrl.cxx:50
 TUrl.cxx:51
 TUrl.cxx:52
 TUrl.cxx:53
 TUrl.cxx:54
 TUrl.cxx:55
 TUrl.cxx:56
 TUrl.cxx:57
 TUrl.cxx:58
 TUrl.cxx:59
 TUrl.cxx:60
 TUrl.cxx:61
 TUrl.cxx:62
 TUrl.cxx:63
 TUrl.cxx:64
 TUrl.cxx:65
 TUrl.cxx:66
 TUrl.cxx:67
 TUrl.cxx:68
 TUrl.cxx:69
 TUrl.cxx:70
 TUrl.cxx:71
 TUrl.cxx:72
 TUrl.cxx:73
 TUrl.cxx:74
 TUrl.cxx:75
 TUrl.cxx:76
 TUrl.cxx:77
 TUrl.cxx:78
 TUrl.cxx:79
 TUrl.cxx:80
 TUrl.cxx:81
 TUrl.cxx:82
 TUrl.cxx:83
 TUrl.cxx:84
 TUrl.cxx:85
 TUrl.cxx:86
 TUrl.cxx:87
 TUrl.cxx:88
 TUrl.cxx:89
 TUrl.cxx:90
 TUrl.cxx:91
 TUrl.cxx:92
 TUrl.cxx:93
 TUrl.cxx:94
 TUrl.cxx:95
 TUrl.cxx:96
 TUrl.cxx:97
 TUrl.cxx:98
 TUrl.cxx:99
 TUrl.cxx:100
 TUrl.cxx:101
 TUrl.cxx:102
 TUrl.cxx:103
 TUrl.cxx:104
 TUrl.cxx:105
 TUrl.cxx:106
 TUrl.cxx:107
 TUrl.cxx:108
 TUrl.cxx:109
 TUrl.cxx:110
 TUrl.cxx:111
 TUrl.cxx:112
 TUrl.cxx:113
 TUrl.cxx:114
 TUrl.cxx:115
 TUrl.cxx:116
 TUrl.cxx:117
 TUrl.cxx:118
 TUrl.cxx:119
 TUrl.cxx:120
 TUrl.cxx:121
 TUrl.cxx:122
 TUrl.cxx:123
 TUrl.cxx:124
 TUrl.cxx:125
 TUrl.cxx:126
 TUrl.cxx:127
 TUrl.cxx:128
 TUrl.cxx:129
 TUrl.cxx:130
 TUrl.cxx:131
 TUrl.cxx:132
 TUrl.cxx:133
 TUrl.cxx:134
 TUrl.cxx:135
 TUrl.cxx:136
 TUrl.cxx:137
 TUrl.cxx:138
 TUrl.cxx:139
 TUrl.cxx:140
 TUrl.cxx:141
 TUrl.cxx:142
 TUrl.cxx:143
 TUrl.cxx:144
 TUrl.cxx:145
 TUrl.cxx:146
 TUrl.cxx:147
 TUrl.cxx:148
 TUrl.cxx:149
 TUrl.cxx:150
 TUrl.cxx:151
 TUrl.cxx:152
 TUrl.cxx:153
 TUrl.cxx:154
 TUrl.cxx:155
 TUrl.cxx:156
 TUrl.cxx:157
 TUrl.cxx:158
 TUrl.cxx:159
 TUrl.cxx:160
 TUrl.cxx:161
 TUrl.cxx:162
 TUrl.cxx:163
 TUrl.cxx:164
 TUrl.cxx:165
 TUrl.cxx:166
 TUrl.cxx:167
 TUrl.cxx:168
 TUrl.cxx:169
 TUrl.cxx:170
 TUrl.cxx:171
 TUrl.cxx:172
 TUrl.cxx:173
 TUrl.cxx:174
 TUrl.cxx:175
 TUrl.cxx:176
 TUrl.cxx:177
 TUrl.cxx:178
 TUrl.cxx:179
 TUrl.cxx:180
 TUrl.cxx:181
 TUrl.cxx:182
 TUrl.cxx:183
 TUrl.cxx:184
 TUrl.cxx:185
 TUrl.cxx:186
 TUrl.cxx:187
 TUrl.cxx:188
 TUrl.cxx:189
 TUrl.cxx:190
 TUrl.cxx:191
 TUrl.cxx:192
 TUrl.cxx:193
 TUrl.cxx:194
 TUrl.cxx:195
 TUrl.cxx:196
 TUrl.cxx:197
 TUrl.cxx:198
 TUrl.cxx:199
 TUrl.cxx:200
 TUrl.cxx:201
 TUrl.cxx:202
 TUrl.cxx:203
 TUrl.cxx:204
 TUrl.cxx:205
 TUrl.cxx:206
 TUrl.cxx:207
 TUrl.cxx:208
 TUrl.cxx:209
 TUrl.cxx:210
 TUrl.cxx:211
 TUrl.cxx:212
 TUrl.cxx:213
 TUrl.cxx:214
 TUrl.cxx:215
 TUrl.cxx:216
 TUrl.cxx:217
 TUrl.cxx:218
 TUrl.cxx:219
 TUrl.cxx:220
 TUrl.cxx:221
 TUrl.cxx:222
 TUrl.cxx:223
 TUrl.cxx:224
 TUrl.cxx:225
 TUrl.cxx:226
 TUrl.cxx:227
 TUrl.cxx:228
 TUrl.cxx:229
 TUrl.cxx:230
 TUrl.cxx:231
 TUrl.cxx:232
 TUrl.cxx:233
 TUrl.cxx:234
 TUrl.cxx:235
 TUrl.cxx:236
 TUrl.cxx:237
 TUrl.cxx:238
 TUrl.cxx:239
 TUrl.cxx:240
 TUrl.cxx:241
 TUrl.cxx:242
 TUrl.cxx:243
 TUrl.cxx:244
 TUrl.cxx:245
 TUrl.cxx:246
 TUrl.cxx:247
 TUrl.cxx:248
 TUrl.cxx:249
 TUrl.cxx:250
 TUrl.cxx:251
 TUrl.cxx:252
 TUrl.cxx:253
 TUrl.cxx:254
 TUrl.cxx:255
 TUrl.cxx:256
 TUrl.cxx:257
 TUrl.cxx:258
 TUrl.cxx:259
 TUrl.cxx:260
 TUrl.cxx:261
 TUrl.cxx:262
 TUrl.cxx:263
 TUrl.cxx:264
 TUrl.cxx:265
 TUrl.cxx:266
 TUrl.cxx:267
 TUrl.cxx:268
 TUrl.cxx:269
 TUrl.cxx:270
 TUrl.cxx:271
 TUrl.cxx:272
 TUrl.cxx:273
 TUrl.cxx:274
 TUrl.cxx:275
 TUrl.cxx:276
 TUrl.cxx:277
 TUrl.cxx:278
 TUrl.cxx:279
 TUrl.cxx:280
 TUrl.cxx:281
 TUrl.cxx:282
 TUrl.cxx:283
 TUrl.cxx:284
 TUrl.cxx:285
 TUrl.cxx:286
 TUrl.cxx:287
 TUrl.cxx:288
 TUrl.cxx:289
 TUrl.cxx:290
 TUrl.cxx:291
 TUrl.cxx:292
 TUrl.cxx:293
 TUrl.cxx:294
 TUrl.cxx:295
 TUrl.cxx:296
 TUrl.cxx:297
 TUrl.cxx:298
 TUrl.cxx:299
 TUrl.cxx:300
 TUrl.cxx:301
 TUrl.cxx:302
 TUrl.cxx:303
 TUrl.cxx:304
 TUrl.cxx:305
 TUrl.cxx:306
 TUrl.cxx:307
 TUrl.cxx:308
 TUrl.cxx:309
 TUrl.cxx:310
 TUrl.cxx:311
 TUrl.cxx:312
 TUrl.cxx:313
 TUrl.cxx:314
 TUrl.cxx:315
 TUrl.cxx:316
 TUrl.cxx:317
 TUrl.cxx:318
 TUrl.cxx:319
 TUrl.cxx:320
 TUrl.cxx:321
 TUrl.cxx:322
 TUrl.cxx:323
 TUrl.cxx:324
 TUrl.cxx:325
 TUrl.cxx:326
 TUrl.cxx:327
 TUrl.cxx:328
 TUrl.cxx:329
 TUrl.cxx:330
 TUrl.cxx:331
 TUrl.cxx:332
 TUrl.cxx:333
 TUrl.cxx:334
 TUrl.cxx:335
 TUrl.cxx:336
 TUrl.cxx:337
 TUrl.cxx:338
 TUrl.cxx:339
 TUrl.cxx:340
 TUrl.cxx:341
 TUrl.cxx:342
 TUrl.cxx:343
 TUrl.cxx:344
 TUrl.cxx:345
 TUrl.cxx:346
 TUrl.cxx:347
 TUrl.cxx:348
 TUrl.cxx:349
 TUrl.cxx:350
 TUrl.cxx:351
 TUrl.cxx:352
 TUrl.cxx:353
 TUrl.cxx:354
 TUrl.cxx:355
 TUrl.cxx:356
 TUrl.cxx:357
 TUrl.cxx:358
 TUrl.cxx:359
 TUrl.cxx:360
 TUrl.cxx:361
 TUrl.cxx:362
 TUrl.cxx:363
 TUrl.cxx:364
 TUrl.cxx:365
 TUrl.cxx:366
 TUrl.cxx:367
 TUrl.cxx:368
 TUrl.cxx:369
 TUrl.cxx:370
 TUrl.cxx:371
 TUrl.cxx:372
 TUrl.cxx:373
 TUrl.cxx:374
 TUrl.cxx:375
 TUrl.cxx:376
 TUrl.cxx:377
 TUrl.cxx:378
 TUrl.cxx:379
 TUrl.cxx:380
 TUrl.cxx:381
 TUrl.cxx:382
 TUrl.cxx:383
 TUrl.cxx:384
 TUrl.cxx:385
 TUrl.cxx:386
 TUrl.cxx:387
 TUrl.cxx:388
 TUrl.cxx:389
 TUrl.cxx:390
 TUrl.cxx:391
 TUrl.cxx:392
 TUrl.cxx:393
 TUrl.cxx:394
 TUrl.cxx:395
 TUrl.cxx:396
 TUrl.cxx:397
 TUrl.cxx:398
 TUrl.cxx:399
 TUrl.cxx:400
 TUrl.cxx:401
 TUrl.cxx:402
 TUrl.cxx:403
 TUrl.cxx:404
 TUrl.cxx:405
 TUrl.cxx:406
 TUrl.cxx:407
 TUrl.cxx:408
 TUrl.cxx:409
 TUrl.cxx:410
 TUrl.cxx:411
 TUrl.cxx:412
 TUrl.cxx:413
 TUrl.cxx:414
 TUrl.cxx:415
 TUrl.cxx:416
 TUrl.cxx:417
 TUrl.cxx:418
 TUrl.cxx:419
 TUrl.cxx:420
 TUrl.cxx:421
 TUrl.cxx:422
 TUrl.cxx:423
 TUrl.cxx:424
 TUrl.cxx:425
 TUrl.cxx:426
 TUrl.cxx:427
 TUrl.cxx:428
 TUrl.cxx:429
 TUrl.cxx:430
 TUrl.cxx:431
 TUrl.cxx:432
 TUrl.cxx:433
 TUrl.cxx:434
 TUrl.cxx:435
 TUrl.cxx:436
 TUrl.cxx:437
 TUrl.cxx:438
 TUrl.cxx:439
 TUrl.cxx:440
 TUrl.cxx:441
 TUrl.cxx:442
 TUrl.cxx:443
 TUrl.cxx:444
 TUrl.cxx:445
 TUrl.cxx:446
 TUrl.cxx:447
 TUrl.cxx:448
 TUrl.cxx:449
 TUrl.cxx:450
 TUrl.cxx:451
 TUrl.cxx:452
 TUrl.cxx:453
 TUrl.cxx:454
 TUrl.cxx:455
 TUrl.cxx:456
 TUrl.cxx:457
 TUrl.cxx:458
 TUrl.cxx:459
 TUrl.cxx:460
 TUrl.cxx:461
 TUrl.cxx:462
 TUrl.cxx:463
 TUrl.cxx:464
 TUrl.cxx:465
 TUrl.cxx:466
 TUrl.cxx:467
 TUrl.cxx:468
 TUrl.cxx:469
 TUrl.cxx:470
 TUrl.cxx:471
 TUrl.cxx:472
 TUrl.cxx:473
 TUrl.cxx:474
 TUrl.cxx:475
 TUrl.cxx:476
 TUrl.cxx:477
 TUrl.cxx:478
 TUrl.cxx:479
 TUrl.cxx:480
 TUrl.cxx:481
 TUrl.cxx:482
 TUrl.cxx:483
 TUrl.cxx:484
 TUrl.cxx:485
 TUrl.cxx:486
 TUrl.cxx:487
 TUrl.cxx:488
 TUrl.cxx:489
 TUrl.cxx:490
 TUrl.cxx:491
 TUrl.cxx:492
 TUrl.cxx:493
 TUrl.cxx:494
 TUrl.cxx:495
 TUrl.cxx:496
 TUrl.cxx:497
 TUrl.cxx:498
 TUrl.cxx:499
 TUrl.cxx:500
 TUrl.cxx:501
 TUrl.cxx:502
 TUrl.cxx:503
 TUrl.cxx:504
 TUrl.cxx:505
 TUrl.cxx:506
 TUrl.cxx:507
 TUrl.cxx:508
 TUrl.cxx:509
 TUrl.cxx:510
 TUrl.cxx:511
 TUrl.cxx:512
 TUrl.cxx:513
 TUrl.cxx:514
 TUrl.cxx:515
 TUrl.cxx:516
 TUrl.cxx:517
 TUrl.cxx:518
 TUrl.cxx:519
 TUrl.cxx:520
 TUrl.cxx:521
 TUrl.cxx:522
 TUrl.cxx:523
 TUrl.cxx:524
 TUrl.cxx:525
 TUrl.cxx:526
 TUrl.cxx:527
 TUrl.cxx:528
 TUrl.cxx:529
 TUrl.cxx:530
 TUrl.cxx:531
 TUrl.cxx:532
 TUrl.cxx:533
 TUrl.cxx:534
 TUrl.cxx:535
 TUrl.cxx:536
 TUrl.cxx:537
 TUrl.cxx:538
 TUrl.cxx:539
 TUrl.cxx:540
 TUrl.cxx:541
 TUrl.cxx:542
 TUrl.cxx:543
 TUrl.cxx:544
 TUrl.cxx:545
 TUrl.cxx:546
 TUrl.cxx:547
 TUrl.cxx:548
 TUrl.cxx:549
 TUrl.cxx:550
 TUrl.cxx:551
 TUrl.cxx:552
 TUrl.cxx:553
 TUrl.cxx:554
 TUrl.cxx:555
 TUrl.cxx:556
 TUrl.cxx:557
 TUrl.cxx:558
 TUrl.cxx:559
 TUrl.cxx:560
 TUrl.cxx:561
 TUrl.cxx:562
 TUrl.cxx:563
 TUrl.cxx:564
 TUrl.cxx:565
 TUrl.cxx:566
 TUrl.cxx:567
 TUrl.cxx:568
 TUrl.cxx:569
 TUrl.cxx:570
 TUrl.cxx:571
 TUrl.cxx:572
 TUrl.cxx:573
 TUrl.cxx:574
 TUrl.cxx:575
 TUrl.cxx:576
 TUrl.cxx:577
 TUrl.cxx:578
 TUrl.cxx:579
 TUrl.cxx:580
 TUrl.cxx:581
 TUrl.cxx:582
 TUrl.cxx:583
 TUrl.cxx:584
 TUrl.cxx:585
 TUrl.cxx:586
 TUrl.cxx:587
 TUrl.cxx:588
 TUrl.cxx:589
 TUrl.cxx:590
 TUrl.cxx:591
 TUrl.cxx:592
 TUrl.cxx:593
 TUrl.cxx:594
 TUrl.cxx:595
 TUrl.cxx:596
 TUrl.cxx:597
 TUrl.cxx:598
 TUrl.cxx:599
 TUrl.cxx:600
 TUrl.cxx:601
 TUrl.cxx:602
 TUrl.cxx:603
 TUrl.cxx:604
 TUrl.cxx:605
 TUrl.cxx:606
 TUrl.cxx:607
 TUrl.cxx:608
 TUrl.cxx:609
 TUrl.cxx:610
 TUrl.cxx:611
 TUrl.cxx:612
 TUrl.cxx:613
 TUrl.cxx:614
 TUrl.cxx:615
 TUrl.cxx:616
 TUrl.cxx:617
 TUrl.cxx:618
 TUrl.cxx:619
 TUrl.cxx:620
 TUrl.cxx:621
 TUrl.cxx:622
 TUrl.cxx:623
 TUrl.cxx:624
 TUrl.cxx:625
 TUrl.cxx:626
 TUrl.cxx:627
 TUrl.cxx:628
 TUrl.cxx:629
 TUrl.cxx:630
 TUrl.cxx:631
 TUrl.cxx:632
 TUrl.cxx:633
 TUrl.cxx:634
 TUrl.cxx:635
 TUrl.cxx:636
 TUrl.cxx:637
 TUrl.cxx:638
 TUrl.cxx:639
 TUrl.cxx:640
 TUrl.cxx:641
 TUrl.cxx:642
 TUrl.cxx:643
 TUrl.cxx:644
 TUrl.cxx:645
 TUrl.cxx:646
 TUrl.cxx:647
 TUrl.cxx:648
 TUrl.cxx:649
 TUrl.cxx:650
 TUrl.cxx:651
 TUrl.cxx:652
 TUrl.cxx:653
 TUrl.cxx:654
 TUrl.cxx:655
 TUrl.cxx:656
 TUrl.cxx:657
 TUrl.cxx:658
 TUrl.cxx:659
 TUrl.cxx:660
 TUrl.cxx:661
 TUrl.cxx:662
 TUrl.cxx:663
 TUrl.cxx:664
 TUrl.cxx:665
 TUrl.cxx:666
 TUrl.cxx:667
 TUrl.cxx:668
 TUrl.cxx:669
 TUrl.cxx:670
 TUrl.cxx:671
 TUrl.cxx:672
 TUrl.cxx:673
 TUrl.cxx:674
 TUrl.cxx:675
 TUrl.cxx:676
 TUrl.cxx:677
 TUrl.cxx:678
 TUrl.cxx:679
 TUrl.cxx:680
 TUrl.cxx:681
 TUrl.cxx:682
 TUrl.cxx:683
 TUrl.cxx:684
 TUrl.cxx:685
 TUrl.cxx:686
 TUrl.cxx:687
 TUrl.cxx:688
 TUrl.cxx:689
 TUrl.cxx:690
 TUrl.cxx:691
 TUrl.cxx:692
 TUrl.cxx:693
 TUrl.cxx:694
 TUrl.cxx:695
 TUrl.cxx:696
 TUrl.cxx:697
 TUrl.cxx:698
 TUrl.cxx:699
 TUrl.cxx:700
 TUrl.cxx:701
 TUrl.cxx:702