33 TObjArray *TUrl::fgSpecialProtocols =
nullptr;
34 THashList *TUrl::fgHostFQDNs =
nullptr;
36 #ifdef R__COMPLETE_MEM_TERMINATION
39 TObjArray **fSpecialProtocols;
40 THashList **fHostFQDNs;
42 TUrlCleanup(TObjArray **protocols, THashList **hosts) : fSpecialProtocols(protocols),fHostFQDNs(hosts) {}
44 if (*fSpecialProtocols) (*fSpecialProtocols)->Delete();
45 delete *fSpecialProtocols;
46 *fSpecialProtocols = 0;
47 if (*fHostFQDNs) (*fHostFQDNs)->Delete();
74 TUrl::TUrl(
const char *url, Bool_t defaultIsFile)
76 SetUrl(url, defaultIsFile);
78 #ifdef R__COMPLETE_MEM_TERMINATION
79 static TUrlCleanup cleanup(&fgSpecialProtocols,&fgHostFQDNs);
108 void TUrl::SetUrl(
const char *url, Bool_t defaultIsFile)
110 fOptionsMap =
nullptr;
112 if (!url || !url[0]) {
132 defaultIsFile = kTRUE;
137 char *u, *u0 = Strip(url);
142 for (
int i = 0; i < GetSpecialProtocols()->GetEntriesFast(); i++) {
143 TObjString *os = (TObjString*) GetSpecialProtocols()->UncheckedAt(i);
144 TString s1 = os->GetString();
146 Bool_t stripoff = kFALSE;
147 if (s1.EndsWith(
"/-")) {
149 s1 = s1.Strip(TString::kTrailing,
'-');
152 if (!strncmp(u, s1, l)) {
153 if (s1(0) ==
'/' && s1(l-1) ==
'/') {
155 fProtocol = s1(1, l-2);
162 fProtocol = s1(0, l-1);
164 if (!strncmp(u+l,
"//", 2))
181 if ((s = strstr(u,
":/")) && u+1 != s) {
183 Error(
"TUrl",
"%s malformed, URL must contain \"://\"", u0);
189 SetProtocol(u, kTRUE);
195 char *newu =
new char [strlen(
"file:") + strlen(u0) + 1];
196 sprintf(newu,
"file:%s", u0);
208 if ((s = strchr(t,
'@')) && (
209 ((x = strchr(t,
'/')) && s < x) ||
210 ((x = strchr(t,
'?')) && s < x) ||
211 ((x = strchr(t,
'#')) && s < x) ||
214 if (*(s-1) ==
'\\') {
220 if ((s2 = strchr(u,
':'))) {
227 fPasswd.ReplaceAll(
"\\@",
"@");
238 if ((s = strchr(u,
':')) || (s = strchr(u,
'/')) || (s = strchr(u,
'?')) || (s = strchr(u,
'#'))) {
239 if ((strchr (u,
':') > strchr(u,
'/')) && (strchr (u,
'/')))
253 if ((s = strchr(u,
'/')) || (s = strchr(u,
'?')) || (s = strchr(u,
'#'))) {
268 if (!*s)
goto cleanup;
272 if (*u ==
'/' && fHost.Length())
284 void TUrl::FindFile(
char *u, Bool_t stripDoubleSlash)
289 char *opt = strchr(u,
'?');
290 char *anc = strchr(u,
'#');
293 if (opt && anc && opt > anc) {
298 if ((s = opt) || (s = anc)) {
302 if (stripDoubleSlash)
303 fFile.ReplaceAll(
"//",
"/");
313 if ((s = strchr(u,
'#'))) {
330 if (stripDoubleSlash)
331 fFile.ReplaceAll(
"//",
"/");
342 TUrl::TUrl(
const TUrl &url) : TObject(url)
345 fProtocol = url.fProtocol;
347 fPasswd = url.fPasswd;
350 fAnchor = url.fAnchor;
351 fOptions = url.fOptions;
353 fFileOA = url.fFileOA;
354 fHostFQ = url.fHostFQ;
355 fOptionsMap =
nullptr;
361 TUrl &TUrl::operator=(
const TUrl &rhs)
364 TObject::operator=(rhs);
366 fProtocol = rhs.fProtocol;
368 fPasswd = rhs.fPasswd;
371 fAnchor = rhs.fAnchor;
372 fOptions = rhs.fOptions;
374 fFileOA = rhs.fFileOA;
375 fHostFQ = rhs.fHostFQ;
376 fOptionsMap =
nullptr;
385 const char *TUrl::GetUrl(Bool_t withDeflt)
const
387 if (((TestBit(kUrlWithDefaultPort) && !withDeflt) ||
388 (!TestBit(kUrlWithDefaultPort) && withDeflt)) &&
389 TestBit(kUrlHasDefaultPort))
392 if (IsValid() && fUrl ==
"") {
394 for (
int i = 0; i < GetSpecialProtocols()->GetEntriesFast(); i++) {
395 TObjString *os = (TObjString*) GetSpecialProtocols()->UncheckedAt(i);
396 TString &s = os->String();
398 if (fProtocol == s(0, l-1)) {
400 fUrl = fProtocol +
"://" + fFile;
402 fUrl = fProtocol +
":" + fFile;
403 if (fOptions !=
"") {
415 Bool_t deflt = kFALSE;
416 if ((!fProtocol.CompareTo(
"http") && fPort == 80) ||
417 (fProtocol.BeginsWith(
"proof") && fPort == 1093) ||
418 (fProtocol.BeginsWith(
"root") && fPort == 1094) ||
419 (!fProtocol.CompareTo(
"ftp") && fPort == 20) ||
420 (!fProtocol.CompareTo(
"news") && fPort == 119) ||
421 (!fProtocol.CompareTo(
"https") && fPort == 443) ||
424 ((TUrl *)
this)->SetBit(kUrlHasDefaultPort);
427 fUrl = fProtocol +
"://";
432 TString passwd = fPasswd;
433 passwd.ReplaceAll(
"@",
"\\@");
439 ((TUrl*)
this)->SetBit(kUrlWithDefaultPort);
441 ((TUrl*)
this)->ResetBit(kUrlWithDefaultPort);
443 if (!deflt || withDeflt) {
445 sprintf(p,
"%d", fPort);
446 fUrl = fUrl + fHost +
":" + p +
"/" + fFile;
448 fUrl = fUrl + fHost +
"/" + fFile;
449 if (fOptions !=
"") {
459 fUrl.ReplaceAll(
"////",
"///");
467 const char *TUrl::GetHostFQDN()
const
471 TNamed *fqdn = fgHostFQDNs ? (TNamed *) fgHostFQDNs->FindObject(fHost) : 0;
473 TInetAddress adr(gSystem->GetHostByName(fHost));
475 fHostFQ = adr.GetHostName();
478 R__LOCKGUARD(gROOTMutex);
480 fgHostFQDNs =
new THashList;
481 fgHostFQDNs->SetOwner();
483 if (fgHostFQDNs && !fgHostFQDNs->FindObject(fHost))
484 fgHostFQDNs->Add(
new TNamed(fHost,fHostFQ));
486 fHostFQ = fqdn->GetTitle();
499 const char *TUrl::GetFileAndOptions()
const
503 if (fOptions !=
"") {
518 void TUrl::SetProtocol(
const char *proto, Bool_t setDefaultPort)
521 if (setDefaultPort) {
522 if (!fProtocol.CompareTo(
"http"))
524 else if (!fProtocol.CompareTo(
"https"))
526 else if (fProtocol.BeginsWith(
"proof"))
528 else if (fProtocol.BeginsWith(
"root"))
530 else if (!fProtocol.CompareTo(
"ftp"))
532 else if (!fProtocol.CompareTo(
"news"))
545 Int_t TUrl::Compare(
const TObject *obj)
const
547 if (
this == obj)
return 0;
548 if (TUrl::Class() != obj->IsA())
return -1;
549 return TString(GetUrl()).CompareTo(((TUrl*)obj)->GetUrl(), TString::kExact);
555 void TUrl::Print(Option_t *)
const
558 Printf(
"Illegal URL");
560 Printf(
"%s", GetUrl());
569 TObjArray *TUrl::GetSpecialProtocols()
571 R__LOCKGUARD(gROOTMutex);
572 static Bool_t usedEnv = kFALSE;
575 if (!fgSpecialProtocols)
576 fgSpecialProtocols =
new TObjArray;
577 if (fgSpecialProtocols->GetEntriesFast() == 0)
578 fgSpecialProtocols->Add(
new TObjString(
"file:"));
579 return fgSpecialProtocols;
583 return fgSpecialProtocols;
585 if (fgSpecialProtocols)
586 fgSpecialProtocols->Delete();
588 if (!fgSpecialProtocols)
589 fgSpecialProtocols =
new TObjArray;
591 const char *protos = gEnv->GetValue(
"Url.Special",
"file: hpss: dcache: dcap:");
596 char *p = StrDup(protos);
598 TObjString *proto =
new TObjString(strtok(!cnt ? p : 0,
" "));
599 if (proto->String().IsNull()) {
603 fgSpecialProtocols->Add(proto);
608 return fgSpecialProtocols;
615 void TUrl::ParseOptions()
const
617 if (fOptionsMap)
return;
619 TString urloptions = GetOptions();
620 TObjArray *objOptions = urloptions.Tokenize(
"&");
621 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
622 TString loption = ((TObjString *) objOptions->At(n))->GetName();
623 TObjArray *objTags = loption.Tokenize(
"=");
625 fOptionsMap =
new TMap;
626 fOptionsMap->SetOwnerKeyValue();
628 if (objTags->GetEntries() == 2) {
629 TString key = ((TObjString *) objTags->At(0))->GetName();
630 TString value = ((TObjString *) objTags->At(1))->GetName();
631 fOptionsMap->Add(
new TObjString(key),
new TObjString(value));
633 TString key = ((TObjString *) objTags->At(0))->GetName();
634 fOptionsMap->Add(
new TObjString(key), 0);
646 const char *TUrl::GetValueFromOptions(
const char *key)
const
648 if (!key)
return nullptr;
650 TObject *option = fOptionsMap ? fOptionsMap->GetValue(key) :
nullptr;
651 return (option ? ((TObjString*)fOptionsMap->GetValue(key))->GetName():
nullptr);
658 Int_t TUrl::GetIntValueFromOptions(
const char *key)
const
662 TObject *option = fOptionsMap ? fOptionsMap->GetValue(key) :
nullptr;
663 return (option ? (atoi(((TObjString*)fOptionsMap->GetValue(key))->GetName())) : -1);
669 Bool_t TUrl::HasOption(
const char *key)
const
671 if (!key)
return kFALSE;
674 if (fOptionsMap && fOptionsMap->FindObject(key))
682 void TUrl::CleanRelativePath()
685 while ( (slash = fFile.Index(
"/..") ) != kNPOS) {
687 Bool_t found = kFALSE;
688 for (
int l = slash-1; l >=0; l--) {
689 if (fFile[l] ==
'/') {
691 fFile.Remove(l, slash+3-l);