00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ctype.h>
00025 #include "TUri.h"
00026 #include "TObjArray.h"
00027 #include "TObjString.h"
00028 #include "TPRegexp.h"
00029
00030
00031
00032 const char* const kURI_pchar = "(?:[[:alpha:][:digit:]-._~!$&'()*+,;=:@]|%[0-9A-Fa-f][0-9A-Fa-f])";
00033
00034
00035 const char* const kURI_unreserved = "[[:alpha:][:digit:]-._~]";
00036
00037
00038
00039 const char* const kURI_reserved = "[:/?#[]@!$&'()*+,;=]";
00040
00041
00042
00043 const char* const kURI_gendelims = "[:/?#[]@]";
00044
00045
00046 const char* const kURI_subdelims = "[!$&'()*+,;=]";
00047
00048
00049 ClassImp(TUri)
00050
00051
00052 TUri::TUri(const TString &uri)
00053 {
00054
00055
00056 SetUri(uri);
00057 }
00058
00059
00060 TUri::TUri(const char *uri)
00061 {
00062
00063
00064 SetUri(uri);
00065 }
00066
00067
00068 TUri::TUri(const TUri &uri) : TObject(uri)
00069 {
00070
00071
00072 fScheme = uri.fScheme;
00073 fUserinfo = uri.fUserinfo;
00074 fHost = uri.fHost;
00075 fPort = uri.fPort;
00076 fPath = uri.fPath;
00077 fQuery = uri.fQuery;
00078 fFragment = uri.fFragment;
00079 fHasScheme = uri.fHasScheme;
00080 fHasUserinfo = uri.fHasUserinfo;
00081 fHasHost = uri.fHasHost;
00082 fHasPort = uri.fHasPort;
00083 fHasPath = uri.fHasPath;
00084 fHasQuery = uri.fHasQuery;
00085 fHasFragment = uri.fHasFragment;
00086 }
00087
00088
00089 TUri &TUri::operator= (const TUri & rhs)
00090 {
00091
00092
00093 if (this != &rhs) {
00094 TObject::operator= (rhs);
00095 fScheme = rhs.fScheme;
00096 fUserinfo = rhs.fUserinfo;
00097 fHost = rhs.fHost;
00098 fPort = rhs.fPort;
00099 fPath = rhs.fPath;
00100 fQuery = rhs.fQuery;
00101 fFragment = rhs.fFragment;
00102 fHasScheme = rhs.fHasScheme;
00103 fHasUserinfo = rhs.fHasUserinfo;
00104 fHasHost = rhs.fHasHost;
00105 fHasPort = rhs.fHasPort;
00106 fHasPath = rhs.fHasPath;
00107 fHasQuery = rhs.fHasQuery;
00108 fHasFragment = rhs.fHasFragment;
00109 }
00110 return *this;
00111 }
00112
00113
00114 Bool_t operator== (const TUri &u1, const TUri &u2)
00115 {
00116
00117
00118
00119
00120
00121 TUri u11 = u1;
00122 TUri u22 = u2;
00123
00124 u11.Normalise();
00125 u22.Normalise();
00126
00127 return u11.GetUri() == u22.GetUri();
00128 }
00129
00130
00131 const TString TUri::GetUri() const
00132 {
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 TString result = "";
00144 if (fHasScheme)
00145 result = fScheme + ":";
00146 result += GetHierPart();
00147 if (fHasQuery)
00148 result += TString("?") + fQuery;
00149 if (fHasFragment)
00150 result += TString("#") + fFragment;
00151 return result;
00152 }
00153
00154
00155 const TString TUri::RemoveDotSegments(const TString &inp)
00156 {
00157
00158
00159
00160
00161
00162 TString source = inp;
00163 TString sink = TString("");
00164
00165
00166 while (source.Length() > 0) {
00167
00168 if (TPRegexp("^\\.\\.?/(.*)$").Substitute(source, "/$1") > 0)
00169 continue;
00170
00171
00172 if (TPRegexp("^/\\./(.*)$|^/\\.($)").Substitute(source, "/$1") > 0)
00173 continue;
00174
00175
00176 if (TPRegexp("^/\\.\\./(.*)$|^/\\.\\.($)").Substitute(source, "/$1") > 0) {
00177 Ssiz_t last = sink.Last('/');
00178 if (last == -1)
00179 last = 0;
00180 sink.Remove(last, sink.Length() - last);
00181 continue;
00182 }
00183
00184
00185 if (source.CompareTo(".") == 0 || source.CompareTo("..") == 0) {
00186 source.Remove(0, source.Length() - 11);
00187 continue;
00188 }
00189
00190
00191 TPRegexp regexp = TPRegexp("^(/?[^/]*)(?:/|$)");
00192 TObjArray *tokens = regexp.MatchS(source);
00193 TString segment = ((TObjString*) tokens->At(1))->GetString();
00194 sink += segment;
00195 source.Remove(0, segment.Length());
00196 delete tokens;
00197 }
00198
00199
00200 return sink;
00201 }
00202
00203
00204 Bool_t TUri::IsAbsolute() const
00205 {
00206
00207
00208
00209
00210 return (HasScheme() && HasHierPart() && !HasFragment());
00211 }
00212
00213
00214 Bool_t TUri::IsRelative() const
00215 {
00216
00217
00218
00219
00220 return (!HasScheme() && HasRelativePart());
00221 }
00222
00223
00224 Bool_t TUri::IsUri() const
00225 {
00226
00227
00228
00229
00230 return (HasScheme() && HasHierPart());
00231 }
00232
00233
00234 Bool_t TUri::IsReference() const
00235 {
00236
00237
00238
00239
00240 return (IsUri() || IsRelative());
00241 }
00242
00243
00244 Bool_t TUri::SetScheme(const TString &scheme)
00245 {
00246
00247
00248
00249 if (!scheme) {
00250 fHasScheme = kFALSE;
00251 return kTRUE;
00252 }
00253 if (IsScheme(scheme)) {
00254 fScheme = scheme;
00255 fHasScheme = kTRUE;
00256 return kTRUE;
00257 } else {
00258 Error("SetScheme", "<scheme> component \"%s\" of URI is not compliant with RFC 3986.", scheme.Data());
00259 return kFALSE;
00260 }
00261 }
00262
00263
00264 Bool_t TUri::IsScheme(const TString &string)
00265 {
00266
00267
00268
00269 return TPRegexp(
00270 "^[[:alpha:]][[:alpha:][:digit:]+-.]*$"
00271 ).Match(string);
00272 }
00273
00274
00275 const TString TUri::GetAuthority() const
00276 {
00277
00278
00279
00280 TString authority = fHasUserinfo ? fUserinfo + "@" + fHost : fHost;
00281 if (fHasPort && !fPort.IsNull())
00282
00283 authority += TString(":") + TString(fPort);
00284 return (authority);
00285 }
00286
00287
00288 Bool_t TUri::SetQuery(const TString &query)
00289 {
00290
00291
00292
00293 if (!query) {
00294 fHasQuery = kFALSE;
00295 return kTRUE;
00296 }
00297 if (IsQuery(query)) {
00298 fQuery = query;
00299 fHasQuery = kTRUE;
00300 return kTRUE;
00301 } else {
00302 Error("SetQuery", "<query> component \"%s\" of URI is not compliant with RFC 3986.", query.Data());
00303 return kFALSE;
00304 }
00305 }
00306
00307
00308 Bool_t TUri::IsQuery(const TString &string)
00309 {
00310
00311
00312
00313 return TPRegexp(
00314 TString("^([/?]|") + kURI_pchar + ")*$"
00315 ).Match(string);
00316 }
00317
00318
00319 Bool_t TUri::SetAuthority(const TString &authority)
00320 {
00321
00322
00323
00324
00325
00326
00327
00328
00329 if (authority.IsNull()) {
00330 fHasUserinfo = kFALSE;
00331 fHasHost = kFALSE;
00332 fHasPort = kFALSE;
00333 return kTRUE;
00334 }
00335 TPRegexp regexp = TPRegexp("^(?:(.*@))?([^:]*)((?::.*)?)$");
00336 TObjArray *tokens = regexp.MatchS(authority);
00337
00338 if (tokens->GetEntries() != 4) {
00339 Error("SetAuthority", "<authority> component \"%s\" of URI is not compliant with RFC 3986.", authority.Data());
00340 return kFALSE;
00341 }
00342
00343 Bool_t valid = kTRUE;
00344
00345
00346 TString userinfo = ((TObjString*) tokens->At(1))->GetString();
00347 if (userinfo.EndsWith("@")) {
00348 userinfo.Remove(TString::kTrailing, '@');
00349 valid &= SetUserInfo(userinfo);
00350 }
00351
00352
00353 TString host = ((TObjString*) tokens->At(2))->GetString();
00354 valid &= SetHost(host);
00355
00356
00357 TString port = ((TObjString*) tokens->At(3))->GetString();
00358 if (port.BeginsWith(":")) {
00359 port.Remove(TString::kLeading, ':');
00360 valid &= SetPort(port);
00361 }
00362
00363 return valid;
00364 }
00365
00366
00367 Bool_t TUri::IsAuthority(const TString &string)
00368 {
00369
00370
00371
00372
00373 TPRegexp regexp = TPRegexp("^(?:(.*)@)?([^:]*)(?::(.*))?$");
00374 TObjArray *tokens = regexp.MatchS(string);
00375 TString userinfo = ((TObjString*) tokens->At(1))->GetString();
00376 TString host = ((TObjString*) tokens->At(2))->GetString();
00377 TString port;
00378
00379 if (tokens->GetEntries() == 4)
00380 port = ((TObjString*) tokens->At(3))->GetString();
00381 else
00382 port = "";
00383 return (IsHost(host) && IsUserInfo(userinfo) && IsPort(port));
00384 }
00385
00386
00387 Bool_t TUri::SetUserInfo(const TString &userinfo)
00388 {
00389
00390
00391
00392 if (userinfo.IsNull()) {
00393 fHasUserinfo = kFALSE;
00394 return kTRUE;
00395 }
00396 if (IsUserInfo(userinfo)) {
00397 fUserinfo = userinfo;
00398 fHasUserinfo = kTRUE;
00399 return kTRUE;
00400 } else {
00401 Error("SetUserInfo", "<userinfo> component \"%s\" of URI is not compliant with RFC 3986.", userinfo.Data());
00402 return kFALSE;
00403 }
00404 }
00405
00406
00407 Bool_t TUri::IsUserInfo(const TString &string)
00408 {
00409
00410
00411
00412
00413 return (TPRegexp(
00414 "^" + TString(kURI_pchar) + "*$"
00415 ).Match(string) > 0 && !TString(string).Contains("@"));
00416 }
00417
00418
00419 Bool_t TUri::SetHost(const TString &host)
00420 {
00421
00422
00423
00424
00425 if (IsHost(host)) {
00426 fHost = host;
00427 fHasHost = kTRUE;
00428 return kTRUE;
00429 } else {
00430 Error("SetHost", "<host> component \"%s\" of URI is not compliant with RFC 3986.", host.Data());
00431 return kFALSE;
00432 }
00433 }
00434
00435
00436 Bool_t TUri::SetPort(const TString &port)
00437 {
00438
00439
00440
00441 if (IsPort(port)) {
00442 fPort = port;
00443 fHasPort = kTRUE;
00444 return kTRUE;
00445 }
00446 Error("SetPort", "<port> component \"%s\" of URI is not compliant with RFC 3986.", port.Data());
00447 return kFALSE;
00448 }
00449
00450
00451 Bool_t TUri::SetPath(const TString &path)
00452 {
00453
00454
00455
00456
00457
00458
00459
00460 if (IsPath(path)) {
00461 fPath = path;
00462 fHasPath = kTRUE;
00463 return kTRUE;
00464 }
00465 Error("SetPath", "<path> component \"%s\" of URI is not compliant with RFC 3986.", path.Data());
00466 return kFALSE;
00467 }
00468
00469
00470 Bool_t TUri::SetFragment(const TString &fragment)
00471 {
00472
00473
00474
00475 if (IsFragment(fragment)) {
00476 fFragment = fragment;
00477 fHasFragment = kTRUE;
00478 return kTRUE;
00479 } else {
00480 Error("SetFragment", "<fragment> component \"%s\" of URI is not compliant with RFC 3986.", fragment.Data());
00481 return kFALSE;
00482 }
00483 }
00484
00485
00486
00487 Bool_t TUri::IsFragment(const TString &string)
00488 {
00489
00490
00491
00492 return (TPRegexp(
00493 "^(" + TString(kURI_pchar) + "|[/?])*$"
00494 ).Match(string) > 0);
00495 }
00496
00497
00498 void TUri::Print(Option_t *option) const
00499 {
00500
00501
00502
00503
00504 if (strcmp(option, "d") != 0) {
00505 Printf("%s", GetUri().Data());
00506 return ;
00507 }
00508
00509 Printf("URI: <%s>", GetUri().Data());
00510 Printf("(%c) |--scheme---------<%s>", fHasScheme ? 't' : 'f', fScheme.Data());
00511 Printf(" |--hier-----------<%s>", GetHierPart().Data());
00512 Printf("(%c) |--authority------<%s>", HasAuthority() ? 't' : 'f', GetAuthority().Data());
00513 Printf("(%c) |--userinfo---<%s>", fHasUserinfo ? 't' : 'f', fUserinfo.Data());
00514 Printf("(%c) |--host-------<%s>", fHasHost ? 't' : 'f', fHost.Data());
00515 Printf("(%c) |--port-------<%s>", fHasPort ? 't' : 'f', fPort.Data());
00516 Printf("(%c) |--path-------<%s>", fHasPath ? 't' : 'f', fPath.Data());
00517 Printf("(%c) |--query------<%s>", fHasQuery ? 't' : 'f', fQuery.Data());
00518 Printf("(%c) |--fragment---<%s>", fHasFragment ? 't' : 'f', fFragment.Data());
00519 printf("path flags: ");
00520 if (IsPathAbempty(fPath))
00521 printf("abempty ");
00522 if (IsPathAbsolute(fPath))
00523 printf("absolute ");
00524 if (IsPathRootless(fPath))
00525 printf("rootless ");
00526 if (IsPathEmpty(fPath))
00527 printf("empty ");
00528 printf("\nURI flags: ");
00529 if (IsAbsolute())
00530 printf("absolute-URI ");
00531 if (IsRelative())
00532 printf("relative-ref ");
00533 if (IsUri())
00534 printf("URI ");
00535 if (IsReference())
00536 printf("URI-reference ");
00537 printf("\n");
00538 }
00539
00540
00541 void TUri::Reset()
00542 {
00543
00544
00545
00546
00547 fScheme = "";
00548 fUserinfo = "";
00549 fHost = "";
00550 fPort = "";
00551 fPath = "";
00552 fQuery = "";
00553 fFragment = "";
00554
00555 fHasScheme = kFALSE;
00556 fHasUserinfo = kFALSE;
00557 fHasHost = kFALSE;
00558 fHasPort = kFALSE;
00559 fHasPath = kFALSE;
00560 fHasQuery = kFALSE;
00561 fHasFragment = kFALSE;
00562 }
00563
00564
00565 Bool_t TUri::SetUri(const TString &uri)
00566 {
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 Reset();
00578
00579
00580
00581 TPRegexp regexp = TPRegexp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)([?]([^#]*))?(#(.*))?");
00582 TObjArray *tokens = regexp.MatchS(uri);
00583
00584
00585 Bool_t valid = kTRUE;
00586
00587 switch (tokens->GetEntries()) {
00588 case 10:
00589
00590 valid &= SetFragment(((TObjString*) tokens->At(9))->GetString());
00591
00592
00593 case 8:
00594
00595
00596 if (!((TString)((TObjString*) tokens->At(6))->GetString()).IsNull())
00597 valid &= SetQuery(((TObjString*) tokens->At(7))->GetString());
00598
00599
00600 case 6:
00601
00602 valid &= SetPath(((TObjString*) tokens->At(5))->GetString());
00603
00604 if (!((TString)((TObjString*) tokens->At(3))->GetString()).IsNull())
00605 valid &= SetAuthority(((TObjString*) tokens->At(4))->GetString());
00606
00607 if (!((TString)((TObjString*) tokens->At(1))->GetString()).IsNull())
00608 valid &= SetScheme(((TObjString*) tokens->At(2))->GetString());
00609 break;
00610
00611 default:
00612
00613 Error("SetUri", "URI \"%s\" is not is not compliant with RFC 3986.", uri.Data());
00614 valid = kFALSE;
00615 }
00616
00617
00618 if (!valid)
00619 Reset();
00620
00621 delete tokens;
00622 return valid;
00623 }
00624
00625
00626 const TString TUri::GetHierPart() const
00627 {
00628
00629
00630
00631
00632
00633 if (HasAuthority() && IsPathAbempty(fPath))
00634 return (TString("//") + GetAuthority() + fPath);
00635 else
00636 return fPath;
00637 }
00638
00639
00640 const TString TUri::GetRelativePart() const
00641 {
00642
00643
00644
00645
00646
00647 if (HasAuthority() && IsPathAbempty(fPath))
00648 return (TString("//") + GetAuthority() + fPath);
00649 else
00650 return fPath;
00651 }
00652
00653
00654 Bool_t TUri::SetHierPart(const TString &hier)
00655 {
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 TPRegexp regexp = TPRegexp("^(//([^/?#]*))?([^?#]*)$");
00671 TObjArray *tokens = regexp.MatchS(hier);
00672
00673 if (tokens->GetEntries() == 0) {
00674 Error("SetHierPart", "<hier-part> component \"%s\" of URI is not compliant with RFC 3986.", hier.Data());
00675 delete tokens;
00676 return false;
00677 }
00678
00679 TString delm = ((TObjString*) tokens->At(1))->GetString();
00680 TString auth = ((TObjString*) tokens->At(2))->GetString();
00681 TString path = ((TObjString*) tokens->At(3))->GetString();
00682
00683 Bool_t valid = kTRUE;
00684
00685 if (!delm.IsNull() && IsPathAbempty(path)) {
00686
00687 valid &= SetAuthority(auth);
00688 valid &= SetPath(path);
00689 } else {
00690
00691 if (IsPathAbsolute(path) || IsPathRootless(path) || IsPathEmpty(path))
00692 valid &= SetPath(path);
00693 else {
00694 valid = kFALSE;
00695 Error("SetHierPart", "<hier-part> component \"%s\" of URI is not compliant with RFC 3986.", hier.Data());
00696 }
00697 }
00698 delete tokens;
00699 return valid;
00700 }
00701
00702
00703 Bool_t TUri::IsHierPart(const TString &string)
00704 {
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 TUri uri;
00715 return (uri.SetHierPart(string));
00716 }
00717
00718
00719 Bool_t TUri::IsRelativePart(const TString &string)
00720 {
00721
00722
00723
00724
00725
00726
00727
00728
00729 TUri uri;
00730 return (uri.SetRelativePart(string));
00731 }
00732
00733
00734 Bool_t TUri::SetRelativePart(const TString &relative)
00735 {
00736
00737
00738
00739
00740
00741
00742
00743 TPRegexp regexp = TPRegexp("^(//([^/?#]*))?([^?#]*)$");
00744 TObjArray *tokens = regexp.MatchS(relative);
00745
00746 if (tokens->GetEntries() == 0) {
00747 Error("SetRelativePath", "<relative-part> component \"%s\" of URI is not compliant with RFC 3986.", relative.Data());
00748 delete tokens;
00749 return false;
00750 }
00751 TString delm = ((TObjString*) tokens->At(1))->GetString();
00752 TString auth = ((TObjString*) tokens->At(2))->GetString();
00753 TString path = ((TObjString*) tokens->At(3))->GetString();
00754
00755 Bool_t valid = kTRUE;
00756
00757 if (!delm.IsNull() && IsPathAbempty(path)) {
00758
00759 valid &= SetAuthority(auth);
00760 valid &= SetPath(path);
00761 } else {
00762
00763 if (IsPathAbsolute(path) || IsPathNoscheme(path) || IsPathEmpty(path))
00764 valid &= SetPath(path);
00765 else {
00766 valid = kFALSE;
00767 Error("SetRelativePath", "<relative-part> component \"%s\" of URI is not compliant with RFC 3986.", relative.Data());
00768 }
00769 }
00770 delete tokens;
00771 return valid;
00772 }
00773
00774
00775 const TString TUri::PctEncode(const TString &source)
00776 {
00777
00778
00779
00780 TString sink = "";
00781
00782 for (Int_t i = 0; i < source.Length(); i++) {
00783 if (IsUnreserved(TString(source(i)))) {
00784
00785 sink = sink + source[i];
00786 } else {
00787
00788
00789 char buffer[4];
00790 sprintf(buffer, "%%%02X", source[i]);
00791 sink = sink + buffer;
00792 }
00793 }
00794 return sink;
00795 }
00796
00797
00798 Bool_t TUri::IsHost(const TString &string)
00799 {
00800
00801
00802
00803
00804 return (IsRegName(string) || IsIpv4(string));
00805 }
00806
00807
00808 Bool_t TUri::IsPath(const TString &string)
00809 {
00810
00811
00812
00813
00814
00815
00816
00817 return (IsPathAbempty(string) ||
00818 IsPathAbsolute(string) ||
00819 IsPathNoscheme(string) ||
00820 IsPathRootless(string) ||
00821 IsPathEmpty(string));
00822 }
00823
00824
00825 Bool_t TUri::IsPathAbempty(const TString &string)
00826 {
00827
00828
00829
00830
00831 return (TPRegexp(
00832 TString("^(/") + TString(kURI_pchar) + "*)*$"
00833 ).Match(string) > 0);
00834 }
00835
00836
00837 Bool_t TUri::IsPathAbsolute(const TString &string)
00838 {
00839
00840
00841
00842
00843
00844 return (TPRegexp(
00845 TString("^/(") + TString(kURI_pchar) + "+(/" + TString(kURI_pchar) + "*)*)?$"
00846 ).Match(string) > 0);
00847 }
00848
00849
00850 Bool_t TUri::IsPathNoscheme(const TString &string)
00851 {
00852
00853
00854
00855
00856
00857 return (TPRegexp(
00858 TString("^(([[:alpha:][:digit:]-._~!$&'()*+,;=@]|%[0-9A-Fa-f][0-9A-Fa-f])+)(/") + TString(kURI_pchar) + "*)*$"
00859 ).Match(string) > 0);
00860 }
00861
00862
00863 Bool_t TUri::IsPathRootless(const TString &string)
00864 {
00865
00866
00867
00868 return TPRegexp(
00869 TString("^") + TString(kURI_pchar) + "+(/" + TString(kURI_pchar) + "*)*$"
00870 ).Match(string);
00871 }
00872
00873
00874 Bool_t TUri::IsPathEmpty(const TString &string)
00875 {
00876
00877
00878 return TString(string).IsNull();
00879 }
00880
00881
00882 Bool_t TUri::IsPort(const TString &string)
00883 {
00884
00885
00886
00887 return (TPRegexp("^[[:digit:]]*$").Match(string) > 0);
00888 }
00889
00890
00891 Bool_t TUri::IsRegName(const TString &string)
00892 {
00893
00894
00895
00896
00897
00898
00899
00900 return (TPRegexp(
00901 "^([[:alpha:][:digit:]-._~!$&'()*+,;=]|%[0-9A-Fa-f][0-9A-Fa-f])*$").Match(string) > 0);
00902 }
00903
00904
00905 Bool_t TUri::IsIpv4(const TString &string)
00906 {
00907
00908
00909
00910
00911
00912 return (TPRegexp(
00913 "^([[:digit:]]{1,3}[.]){3}[[:digit:]]{1,3}$").Match(string) > 0);
00914 }
00915
00916
00917 Bool_t TUri::IsUnreserved(const TString &string)
00918 {
00919
00920
00921
00922
00923 return (TPRegexp(
00924 "^" + TString(kURI_unreserved) + "*$").Match(string) > 0);
00925 }
00926
00927
00928 void TUri::Normalise()
00929 {
00930
00931
00932
00933
00934
00935 fScheme.ToLower();
00936 if (fHasHost) {
00937 TString host = GetHost();
00938 host.ToLower();
00939 SetHost(host);
00940 }
00941
00942
00943 fUserinfo = PctNormalise(PctDecodeUnreserved(fUserinfo));
00944 fHost = PctNormalise(PctDecodeUnreserved(fHost));
00945 fPath = PctNormalise(PctDecodeUnreserved(fPath));
00946 fQuery = PctNormalise(PctDecodeUnreserved(fQuery));
00947 fFragment = PctNormalise(PctDecodeUnreserved(fFragment));
00948
00949
00950 if (fHasPath)
00951 SetPath(RemoveDotSegments(GetPath()));
00952 }
00953
00954
00955 TString const TUri::PctDecodeUnreserved(const TString &source)
00956 {
00957
00958
00959
00960 TString sink = "";
00961 Int_t i = 0;
00962 while (i < source.Length()) {
00963 if (source[i] == '%') {
00964 if (source.Length() < i+2) {
00965
00966 return sink;
00967 }
00968
00969
00970 char c1 = tolower(source[i + 1]) - '0';
00971 if (c1 > 9)
00972 c1 -= 39;
00973
00974 char c0 = tolower(source[i + 2]) - '0';
00975 if (c0 > 9)
00976 c0 -= 39;
00977 char decoded = c1 << 4 | c0;
00978 if (TPRegexp(kURI_unreserved).Match(decoded) > 0) {
00979
00980 sink = sink + decoded;
00981 } else {
00982
00983 TString pct = source(i,3);
00984 pct.ToUpper();
00985 sink = sink + pct;
00986 }
00987
00988 i += 2;
00989 } else {
00990
00991 sink = sink + source[i];
00992 }
00993 i++;
00994 }
00995 return sink;
00996 }
00997
00998
00999 TString const TUri::PctNormalise(const TString &source)
01000 {
01001
01002
01003
01004
01005 TString sink = "";
01006 Int_t i = 0;
01007 while (i < source.Length()) {
01008 if (source[i] == '%') {
01009 if (source.Length() < i+2) {
01010
01011 return sink;
01012 }
01013 TString pct = source(i,3);
01014
01015 pct.ToUpper();
01016 sink = sink + pct;
01017
01018 i += 2;
01019 } else {
01020
01021 sink = sink + source[i];
01022 }
01023 i++;
01024 }
01025 return sink;
01026 }
01027
01028
01029 TString const TUri::PctDecode(const TString &source)
01030 {
01031
01032
01033
01034 TString sink = "";
01035 Int_t i = 0;
01036 while (i < source.Length()) {
01037 if (source[i] == '%') {
01038 if (source.Length() < i+2) {
01039
01040 return sink;
01041 }
01042
01043
01044 char c1 = tolower(source[i + 1]) - '0';
01045 if (c1 > 9)
01046 c1 -= 39;
01047
01048 char c0 = tolower(source[i + 2]) - '0';
01049 if (c0 > 9)
01050 c0 -= 39;
01051 sink = sink + (char)(c1 << 4 | c0);
01052
01053 i += 2;
01054 } else {
01055
01056 sink = sink + source[i];
01057 }
01058 i++;
01059 }
01060 return sink;
01061 }
01062
01063
01064 TUri TUri::Transform(const TUri &reference, const TUri &base)
01065 {
01066
01067
01068
01069
01070 TUri target;
01071 if (reference.HasScheme()) {
01072 target.SetScheme(reference.GetScheme());
01073 if (reference.HasAuthority())
01074 target.SetAuthority(reference.GetAuthority());
01075 if (reference.HasPath())
01076 target.SetPath(RemoveDotSegments(reference.GetPath()));
01077 if (reference.HasQuery())
01078 target.SetQuery(reference.GetQuery());
01079 } else {
01080 if (reference.HasAuthority()) {
01081 target.SetAuthority(reference.GetAuthority());
01082 if (reference.HasPath())
01083 target.SetPath(RemoveDotSegments(reference.GetPath()));
01084 if (reference.HasQuery())
01085 target.SetQuery(reference.GetQuery());
01086 } else {
01087 if (reference.GetPath().IsNull()) {
01088 target.SetPath(base.GetPath());
01089 if (reference.HasQuery()) {
01090 target.SetQuery(reference.GetQuery());
01091 } else {
01092 if (base.HasQuery())
01093 target.SetQuery(base.GetQuery());
01094 }
01095 } else {
01096 if (reference.GetPath().BeginsWith("/")) {
01097 target.SetPath(RemoveDotSegments(reference.GetPath()));
01098 } else {
01099 target.SetPath(RemoveDotSegments(MergePaths(reference, base)));
01100 }
01101 if (reference.HasQuery())
01102 target.SetQuery(reference.GetQuery());
01103 }
01104 if (base.HasAuthority())
01105 target.SetAuthority(base.GetAuthority());
01106 }
01107 if (base.HasScheme())
01108 target.SetScheme(base.GetScheme());
01109 }
01110 if (reference.HasFragment())
01111 target.SetFragment(reference.GetFragment());
01112 return target;
01113 }
01114
01115
01116 const TString TUri::MergePaths(const TUri &reference, const TUri &base)
01117 {
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 TString result = "";
01129 if (base.HasAuthority() && base.GetPath().IsNull()) {
01130 result = TString("/") + reference.GetPath();
01131 } else {
01132 TString basepath = base.GetPath();
01133 Ssiz_t last = basepath.Last('/');
01134 if (last == -1)
01135 result = reference.GetPath();
01136 else
01137 result = basepath(0, last + 1) + reference.GetPath();
01138 }
01139 return result;
01140 }