/ scripts / com / adobe / net / URI.as
URI.as
   1  package com.adobe.net
   2  {
   3     public class URI
   4     {
   5        
   6        public static const EQUAL:int = 2;
   7        
   8        public static const PARENT:int = 3;
   9        
  10        public static const URImustEscape:String = " %";
  11        
  12        public static const URIqueryEscape:String = URImustEscape + "#";
  13        
  14        protected static const URIqueryExcludedBitmap:URIEncodingBitmap = new URIEncodingBitmap(URIqueryEscape);
  15        
  16        public static const URIpathEscape:String = URImustEscape + "?#";
  17        
  18        protected static const URIfragmentExcludedBitmap:URIEncodingBitmap = URIqueryExcludedBitmap;
  19        
  20        public static const UNKNOWN_SCHEME:String = "unknown";
  21        
  22        protected static var _resolver:IURIResolver = null;
  23        
  24        public static const URIqueryPartEscape:String = URImustEscape + "#&=";
  25        
  26        protected static const URIqueryPartExcludedBitmap:URIEncodingBitmap = new URIEncodingBitmap(URIqueryPartEscape);
  27        
  28        protected static const URIpathExcludedBitmap:URIEncodingBitmap = new URIEncodingBitmap(URIpathEscape);
  29        
  30        public static const URIbaselineEscape:String = URImustEscape + ":?#/@";
  31        
  32        protected static const URIbaselineExcludedBitmap:URIEncodingBitmap = new URIEncodingBitmap(URIbaselineEscape);
  33        
  34        protected static const URIschemeExcludedBitmap:URIEncodingBitmap = URIbaselineExcludedBitmap;
  35        
  36        protected static const URIuserpassExcludedBitmap:URIEncodingBitmap = URIbaselineExcludedBitmap;
  37        
  38        protected static const URIportExludedBitmap:URIEncodingBitmap = URIbaselineExcludedBitmap;
  39        
  40        protected static const URIauthorityExcludedBitmap:URIEncodingBitmap = URIbaselineExcludedBitmap;
  41        
  42        public static const URInonHierEscape:String = URImustEscape + "?#/";
  43        
  44        protected static const URInonHierexcludedBitmap:URIEncodingBitmap = new URIEncodingBitmap(URInonHierEscape);
  45        
  46        public static const CHILD:int = 1;
  47        
  48        public static const NOT_RELATED:int = 0;
  49         
  50        
  51        protected var _path:String = "";
  52        
  53        protected var _relative:Boolean = false;
  54        
  55        protected var _fragment:String = "";
  56        
  57        protected var _username:String = "";
  58        
  59        protected var _nonHierarchical:String = "";
  60        
  61        protected var _authority:String = "";
  62        
  63        protected var _query:String = "";
  64        
  65        protected var _scheme:String = "";
  66        
  67        protected var _port:String = "";
  68        
  69        protected var _password:String = "";
  70        
  71        protected var _valid:Boolean = false;
  72        
  73        public function URI(uri:String = null)
  74        {
  75           super();
  76           if(uri == null)
  77           {
  78              this.initialize();
  79           }
  80           else
  81           {
  82              this.constructURI(uri);
  83           }
  84        }
  85        
  86        public static function get resolver() : IURIResolver
  87        {
  88           return _resolver;
  89        }
  90        
  91        protected static function compareStr(str1:String, str2:String, sensitive:Boolean = true) : Boolean
  92        {
  93           if(sensitive == false)
  94           {
  95              str1 = str1.toLowerCase();
  96              str2 = str2.toLowerCase();
  97           }
  98           return str1 == str2;
  99        }
 100        
 101        public static function set resolver(resolver:IURIResolver) : void
 102        {
 103           _resolver = resolver;
 104        }
 105        
 106        public static function unescapeChars(escaped:String) : String
 107        {
 108           var unescaped:String = null;
 109           return decodeURIComponent(escaped);
 110        }
 111        
 112        public static function queryPartEscape(unescaped:String) : String
 113        {
 114           var escaped:String = unescaped;
 115           return URI.fastEscapeChars(unescaped,URI.URIqueryPartExcludedBitmap);
 116        }
 117        
 118        public static function escapeChars(unescaped:String) : String
 119        {
 120           return fastEscapeChars(unescaped,URI.URIbaselineExcludedBitmap);
 121        }
 122        
 123        public static function fastEscapeChars(unescaped:String, bitmap:URIEncodingBitmap) : String
 124        {
 125           var c:String = null;
 126           var x:int = 0;
 127           var i:int = 0;
 128           var escaped:String = "";
 129           for(i = 0; i < unescaped.length; i++)
 130           {
 131              c = unescaped.charAt(i);
 132              x = bitmap.ShouldEscape(c);
 133              if(Boolean(x))
 134              {
 135                 c = x.toString(16);
 136                 if(c.length == 1)
 137                 {
 138                    c = "0" + c;
 139                 }
 140                 c = "%" + c;
 141                 c = c.toUpperCase();
 142              }
 143              escaped += c;
 144           }
 145           return escaped;
 146        }
 147        
 148        public static function queryPartUnescape(escaped:String) : String
 149        {
 150           var unescaped:String = escaped;
 151           return unescapeChars(unescaped);
 152        }
 153        
 154        protected static function resolve(uri:URI) : URI
 155        {
 156           var copy:URI = new URI();
 157           copy.copyURI(uri);
 158           if(_resolver != null)
 159           {
 160              return _resolver.resolve(copy);
 161           }
 162           return copy;
 163        }
 164        
 165        public function set queryRaw(queryStr:String) : void
 166        {
 167           this._query = queryStr;
 168        }
 169        
 170        public function get port() : String
 171        {
 172           return URI.unescapeChars(this._port);
 173        }
 174        
 175        public function set port(portStr:String) : void
 176        {
 177           this._port = URI.escapeChars(portStr);
 178           this.hierState = true;
 179        }
 180        
 181        public function getCommonParent(uri:URI, caseSensitive:Boolean = true) : URI
 182        {
 183           var strBefore:String = null;
 184           var strAfter:String = null;
 185           var thisURI:URI = URI.resolve(this);
 186           var thatURI:URI = URI.resolve(uri);
 187           if(!thisURI.isAbsolute() || !thatURI.isAbsolute() || thisURI.isHierarchical() == false || thatURI.isHierarchical() == false)
 188           {
 189              return null;
 190           }
 191           var relation:int = thisURI.getRelation(thatURI);
 192           if(relation == URI.NOT_RELATED)
 193           {
 194              return null;
 195           }
 196           thisURI.chdir(".");
 197           thatURI.chdir(".");
 198           do
 199           {
 200              relation = thisURI.getRelation(thatURI,caseSensitive);
 201              if(relation == URI.EQUAL || relation == URI.PARENT)
 202              {
 203                 break;
 204              }
 205              strBefore = thisURI.toString();
 206              thisURI.chdir("..");
 207              strAfter = thisURI.toString();
 208           }
 209           while(strBefore != strAfter);
 210           
 211           return thisURI;
 212        }
 213        
 214        public function get nonHierarchical() : String
 215        {
 216           return URI.unescapeChars(this._nonHierarchical);
 217        }
 218        
 219        protected function set hierState(state:Boolean) : void
 220        {
 221           if(state)
 222           {
 223              this._nonHierarchical = "";
 224              if(this._scheme == "" || this._scheme == UNKNOWN_SCHEME)
 225              {
 226                 this._relative = true;
 227              }
 228              else
 229              {
 230                 this._relative = false;
 231              }
 232              if(this._authority.length == 0 && this._path.length == 0)
 233              {
 234                 this._valid = false;
 235              }
 236              else
 237              {
 238                 this._valid = true;
 239              }
 240           }
 241           else
 242           {
 243              this._authority = "";
 244              this._username = "";
 245              this._password = "";
 246              this._port = "";
 247              this._path = "";
 248              this._relative = false;
 249              if(this._scheme == "" || this._scheme == UNKNOWN_SCHEME)
 250              {
 251                 this._valid = false;
 252              }
 253              else
 254              {
 255                 this._valid = true;
 256              }
 257           }
 258        }
 259        
 260        public function setQueryValue(name:String, value:String) : void
 261        {
 262           var map:Object = null;
 263           map = this.getQueryByMap();
 264           map[name] = value;
 265           this.setQueryByMap(map);
 266        }
 267        
 268        public function getFilename(minusExtension:Boolean = false) : String
 269        {
 270           var filename:String = null;
 271           var index:int = 0;
 272           if(this.isDirectory())
 273           {
 274              return String("");
 275           }
 276           var pathStr:String = this.path;
 277           index = pathStr.lastIndexOf("/");
 278           if(index != -1)
 279           {
 280              filename = pathStr.substr(index + 1);
 281           }
 282           else
 283           {
 284              filename = pathStr;
 285           }
 286           if(minusExtension)
 287           {
 288              index = filename.lastIndexOf(".");
 289              if(index != -1)
 290              {
 291                 filename = filename.substr(0,index);
 292              }
 293           }
 294           return filename;
 295        }
 296        
 297        public function set authority(authorityStr:String) : void
 298        {
 299           authorityStr = authorityStr.toLowerCase();
 300           this._authority = URI.fastEscapeChars(authorityStr,URI.URIauthorityExcludedBitmap);
 301           this.hierState = true;
 302        }
 303        
 304        protected function initialize() : void
 305        {
 306           this._valid = false;
 307           this._relative = false;
 308           this._scheme = UNKNOWN_SCHEME;
 309           this._authority = "";
 310           this._username = "";
 311           this._password = "";
 312           this._port = "";
 313           this._path = "";
 314           this._query = "";
 315           this._fragment = "";
 316           this._nonHierarchical = "";
 317        }
 318        
 319        public function getQueryByMap() : Object
 320        {
 321           var queryStr:String = null;
 322           var pair:String = null;
 323           var pairs:Array = null;
 324           var item:Array = null;
 325           var name:String = null;
 326           var value:String = null;
 327           var map:Object = new Object();
 328           queryStr = this._query;
 329           pairs = queryStr.split("&");
 330           for each(pair in pairs)
 331           {
 332              if(pair.length != 0)
 333              {
 334                 item = pair.split("=");
 335                 if(item.length > 0)
 336                 {
 337                    name = String(item[0]);
 338                    if(item.length > 1)
 339                    {
 340                       value = String(item[1]);
 341                    }
 342                    else
 343                    {
 344                       value = "";
 345                    }
 346                    name = queryPartUnescape(name);
 347                    value = queryPartUnescape(value);
 348                    map[name] = value;
 349                 }
 350              }
 351           }
 352           return map;
 353        }
 354        
 355        protected function constructURI(uri:String) : Boolean
 356        {
 357           if(!this.parseURI(uri))
 358           {
 359              this._valid = false;
 360           }
 361           return this.isValid();
 362        }
 363        
 364        public function isRelative() : Boolean
 365        {
 366           return this._relative;
 367        }
 368        
 369        public function getExtension(minusDot:Boolean = false) : String
 370        {
 371           var extension:String = null;
 372           var index:int = 0;
 373           var filename:String = this.getFilename();
 374           if(filename == "")
 375           {
 376              return String("");
 377           }
 378           index = filename.lastIndexOf(".");
 379           if(index == -1 || index == 0)
 380           {
 381              return String("");
 382           }
 383           extension = filename.substr(index);
 384           if(minusDot && extension.charAt(0) == ".")
 385           {
 386              extension = extension.substr(1);
 387           }
 388           return extension;
 389        }
 390        
 391        public function get password() : String
 392        {
 393           return URI.unescapeChars(this._password);
 394        }
 395        
 396        public function setParts(schemeStr:String, authorityStr:String, portStr:String, pathStr:String, queryStr:String, fragmentStr:String) : void
 397        {
 398           this.scheme = schemeStr;
 399           this.authority = authorityStr;
 400           this.port = portStr;
 401           this.path = pathStr;
 402           this.query = queryStr;
 403           this.fragment = fragmentStr;
 404           this.hierState = true;
 405        }
 406        
 407        public function set query(queryStr:String) : void
 408        {
 409           this._query = URI.fastEscapeChars(queryStr,URI.URIqueryExcludedBitmap);
 410        }
 411        
 412        public function set fragment(fragmentStr:String) : void
 413        {
 414           this._fragment = URI.fastEscapeChars(fragmentStr,URIfragmentExcludedBitmap);
 415        }
 416        
 417        public function get path() : String
 418        {
 419           return URI.unescapeChars(this._path);
 420        }
 421        
 422        public function setQueryByMap(map:Object) : void
 423        {
 424           var item:String = null;
 425           var name:String = null;
 426           var value:String = null;
 427           var tmpPair:String = null;
 428           var queryStr:String = "";
 429           for(item in map)
 430           {
 431              name = item;
 432              value = String(map[item]);
 433              if(value == null)
 434              {
 435                 value = "";
 436              }
 437              name = queryPartEscape(name);
 438              value = queryPartEscape(value);
 439              tmpPair = name;
 440              if(value.length > 0)
 441              {
 442                 tmpPair += "=";
 443                 tmpPair += value;
 444              }
 445              if(queryStr.length != 0)
 446              {
 447                 queryStr += "&";
 448              }
 449              queryStr += tmpPair;
 450           }
 451           this._query = queryStr;
 452        }
 453        
 454        public function makeAbsoluteURI(base_uri:URI) : Boolean
 455        {
 456           if(this.isAbsolute() || base_uri.isRelative())
 457           {
 458              return false;
 459           }
 460           var base:URI = new URI();
 461           base.copyURI(base_uri);
 462           if(base.chdir(this.toString()) == false)
 463           {
 464              return false;
 465           }
 466           this.copyURI(base);
 467           return true;
 468        }
 469        
 470        public function chdir(reference:String, escape:Boolean = false) : Boolean
 471        {
 472           var uriReference:URI = null;
 473           var thisPath:String = null;
 474           var thatPath:String = null;
 475           var thisParts:Array = null;
 476           var thatParts:Array = null;
 477           var curDir:String = null;
 478           var i:int = 0;
 479           var f:String = null;
 480           var ref:String = reference;
 481           if(escape)
 482           {
 483              ref = URI.escapeChars(reference);
 484           }
 485           if(ref == "")
 486           {
 487              return true;
 488           }
 489           if(ref.substr(0,2) == "//")
 490           {
 491              f = this.scheme + ":" + ref;
 492              return this.constructURI(f);
 493           }
 494           if(ref.charAt(0) == "?")
 495           {
 496              ref = "./" + ref;
 497           }
 498           uriReference = new URI(ref);
 499           if(uriReference.isAbsolute() || uriReference.isHierarchical() == false)
 500           {
 501              this.copyURI(uriReference);
 502              return true;
 503           }
 504           var thisIsDir:Boolean = false;
 505           var thatIsDir:Boolean = false;
 506           var thisIsAbs:Boolean = false;
 507           var thatIsAbs:Boolean = false;
 508           var lastIsDotOperation:Boolean = false;
 509           thisPath = this.path;
 510           thatPath = uriReference.path;
 511           if(thisPath.length > 0)
 512           {
 513              thisParts = thisPath.split("/");
 514           }
 515           else
 516           {
 517              thisParts = new Array();
 518           }
 519           if(thatPath.length > 0)
 520           {
 521              thatParts = thatPath.split("/");
 522           }
 523           else
 524           {
 525              thatParts = new Array();
 526           }
 527           if(thisParts.length > 0 && thisParts[0] == "")
 528           {
 529              thisIsAbs = true;
 530              thisParts.shift();
 531           }
 532           if(thisParts.length > 0 && thisParts[thisParts.length - 1] == "")
 533           {
 534              thisIsDir = true;
 535              thisParts.pop();
 536           }
 537           if(thatParts.length > 0 && thatParts[0] == "")
 538           {
 539              thatIsAbs = true;
 540              thatParts.shift();
 541           }
 542           if(thatParts.length > 0 && thatParts[thatParts.length - 1] == "")
 543           {
 544              thatIsDir = true;
 545              thatParts.pop();
 546           }
 547           if(thatIsAbs)
 548           {
 549              this.path = uriReference.path;
 550              this.queryRaw = uriReference.queryRaw;
 551              this.fragment = uriReference.fragment;
 552              return true;
 553           }
 554           if(thatParts.length == 0 && uriReference.query == "")
 555           {
 556              this.fragment = uriReference.fragment;
 557              return true;
 558           }
 559           if(thisIsDir == false && thisParts.length > 0)
 560           {
 561              thisParts.pop();
 562           }
 563           this.queryRaw = uriReference.queryRaw;
 564           this.fragment = uriReference.fragment;
 565           thisParts = thisParts.concat(thatParts);
 566           for(i = 0; i < thisParts.length; i++)
 567           {
 568              curDir = String(thisParts[i]);
 569              lastIsDotOperation = false;
 570              if(curDir == ".")
 571              {
 572                 thisParts.splice(i,1);
 573                 i -= 1;
 574                 lastIsDotOperation = true;
 575              }
 576              else if(curDir == "..")
 577              {
 578                 if(i >= 1)
 579                 {
 580                    if(thisParts[i - 1] != "..")
 581                    {
 582                       thisParts.splice(i - 1,2);
 583                       i -= 2;
 584                    }
 585                 }
 586                 else if(!this.isRelative())
 587                 {
 588                    thisParts.splice(i,1);
 589                    i -= 1;
 590                 }
 591                 lastIsDotOperation = true;
 592              }
 593           }
 594           var finalPath:String = "";
 595           thatIsDir ||= lastIsDotOperation;
 596           finalPath = this.joinPath(thisParts,thisIsAbs,thatIsDir);
 597           this.path = finalPath;
 598           return true;
 599        }
 600        
 601        public function get scheme() : String
 602        {
 603           return URI.unescapeChars(this._scheme);
 604        }
 605        
 606        public function makeRelativeURI(base_uri:URI, caseSensitive:Boolean = true) : Boolean
 607        {
 608           var thisParts:Array = null;
 609           var thatParts:Array = null;
 610           var thisPart:String = null;
 611           var thatPart:String = null;
 612           var finalPath:String = null;
 613           var i:int = 0;
 614           var base:URI = new URI();
 615           base.copyURI(base_uri);
 616           var finalParts:Array = new Array();
 617           var pathStr:String = this.path;
 618           var queryStr:String = this.queryRaw;
 619           var fragmentStr:String = this.fragment;
 620           var isDir:Boolean = false;
 621           if(this.isRelative())
 622           {
 623              return true;
 624           }
 625           if(base.isRelative())
 626           {
 627              return false;
 628           }
 629           if(this.isOfType(base_uri.scheme) == false || this.authority != base_uri.authority)
 630           {
 631              return false;
 632           }
 633           isDir = this.isDirectory();
 634           base.chdir(".");
 635           thisParts = pathStr.split("/");
 636           thatParts = base.path.split("/");
 637           if(thisParts.length > 0 && thisParts[0] == "")
 638           {
 639              thisParts.shift();
 640           }
 641           if(thisParts.length > 0 && thisParts[thisParts.length - 1] == "")
 642           {
 643              isDir = true;
 644              thisParts.pop();
 645           }
 646           if(thatParts.length > 0 && thatParts[0] == "")
 647           {
 648              thatParts.shift();
 649           }
 650           if(thatParts.length > 0 && thatParts[thatParts.length - 1] == "")
 651           {
 652              thatParts.pop();
 653           }
 654           while(thatParts.length > 0)
 655           {
 656              if(thisParts.length == 0)
 657              {
 658                 break;
 659              }
 660              thisPart = String(thisParts[0]);
 661              thatPart = String(thatParts[0]);
 662              if(!compareStr(thisPart,thatPart,caseSensitive))
 663              {
 664                 break;
 665              }
 666              thisParts.shift();
 667              thatParts.shift();
 668           }
 669           for(i = 0; i < thatParts.length; i++)
 670           {
 671              finalParts.push("..");
 672           }
 673           finalParts = finalParts.concat(thisParts);
 674           finalPath = this.joinPath(finalParts,false,isDir);
 675           if(finalPath.length == 0)
 676           {
 677              finalPath = "./";
 678           }
 679           this.setParts("","","",finalPath,queryStr,fragmentStr);
 680           return true;
 681        }
 682        
 683        public function set password(passwordStr:String) : void
 684        {
 685           this._password = URI.fastEscapeChars(passwordStr,URI.URIuserpassExcludedBitmap);
 686           this.hierState = true;
 687        }
 688        
 689        public function toDisplayString() : String
 690        {
 691           return this.toStringInternal(true);
 692        }
 693        
 694        protected function parseURI(uri:String) : Boolean
 695        {
 696           var index:int = 0;
 697           var index2:int = 0;
 698           var baseURI:String = uri;
 699           this.initialize();
 700           index = baseURI.indexOf("#");
 701           if(index != -1)
 702           {
 703              if(baseURI.length > index + 1)
 704              {
 705                 this._fragment = baseURI.substr(index + 1,baseURI.length - (index + 1));
 706              }
 707              baseURI = baseURI.substr(0,index);
 708           }
 709           index = baseURI.indexOf("?");
 710           if(index != -1)
 711           {
 712              if(baseURI.length > index + 1)
 713              {
 714                 this._query = baseURI.substr(index + 1,baseURI.length - (index + 1));
 715              }
 716              baseURI = baseURI.substr(0,index);
 717           }
 718           index = baseURI.search(":");
 719           index2 = baseURI.search("/");
 720           var containsColon:Boolean = index != -1;
 721           var containsSlash:Boolean = index2 != -1;
 722           var colonBeforeSlash:Boolean = !containsSlash || index < index2;
 723           if(containsColon && colonBeforeSlash)
 724           {
 725              this._scheme = baseURI.substr(0,index);
 726              this._scheme = this._scheme.toLowerCase();
 727              baseURI = baseURI.substr(index + 1);
 728              if(baseURI.substr(0,2) != "//")
 729              {
 730                 this._nonHierarchical = baseURI;
 731                 if((this._valid = this.validateURI()) == false)
 732                 {
 733                    this.initialize();
 734                 }
 735                 return this.isValid();
 736              }
 737              this._nonHierarchical = "";
 738              baseURI = baseURI.substr(2,baseURI.length - 2);
 739           }
 740           else
 741           {
 742              this._scheme = "";
 743              this._relative = true;
 744              this._nonHierarchical = "";
 745           }
 746           if(this.isRelative())
 747           {
 748              this._authority = "";
 749              this._port = "";
 750              this._path = baseURI;
 751           }
 752           else
 753           {
 754              if(baseURI.substr(0,2) == "//")
 755              {
 756                 while(baseURI.charAt(0) == "/")
 757                 {
 758                    baseURI = baseURI.substr(1,baseURI.length - 1);
 759                 }
 760              }
 761              index = baseURI.search("/");
 762              if(index == -1)
 763              {
 764                 this._authority = baseURI;
 765                 this._path = "";
 766              }
 767              else
 768              {
 769                 this._authority = baseURI.substr(0,index);
 770                 this._path = baseURI.substr(index,baseURI.length - index);
 771              }
 772              index = this._authority.search("@");
 773              if(index != -1)
 774              {
 775                 this._username = this._authority.substr(0,index);
 776                 this._authority = this._authority.substr(index + 1);
 777                 index = this._username.search(":");
 778                 if(index != -1)
 779                 {
 780                    this._password = this._username.substring(index + 1,this._username.length);
 781                    this._username = this._username.substr(0,index);
 782                 }
 783                 else
 784                 {
 785                    this._password = "";
 786                 }
 787              }
 788              else
 789              {
 790                 this._username = "";
 791                 this._password = "";
 792              }
 793              index = this._authority.search(":");
 794              if(index != -1)
 795              {
 796                 this._port = this._authority.substring(index + 1,this._authority.length);
 797                 this._authority = this._authority.substr(0,index);
 798              }
 799              else
 800              {
 801                 this._port = "";
 802              }
 803              this._authority = this._authority.toLowerCase();
 804           }
 805           if((this._valid = this.validateURI()) == false)
 806           {
 807              this.initialize();
 808           }
 809           return this.isValid();
 810        }
 811        
 812        public function set username(usernameStr:String) : void
 813        {
 814           this._username = URI.fastEscapeChars(usernameStr,URI.URIuserpassExcludedBitmap);
 815           this.hierState = true;
 816        }
 817        
 818        public function copyURI(uri:URI) : void
 819        {
 820           this._scheme = uri._scheme;
 821           this._authority = uri._authority;
 822           this._username = uri._username;
 823           this._password = uri._password;
 824           this._port = uri._port;
 825           this._path = uri._path;
 826           this._query = uri._query;
 827           this._fragment = uri._fragment;
 828           this._nonHierarchical = uri._nonHierarchical;
 829           this._valid = uri._valid;
 830           this._relative = uri._relative;
 831        }
 832        
 833        public function isAbsolute() : Boolean
 834        {
 835           return !this._relative;
 836        }
 837        
 838        protected function get hierState() : Boolean
 839        {
 840           return this._nonHierarchical.length == 0;
 841        }
 842        
 843        public function get queryRaw() : String
 844        {
 845           return this._query;
 846        }
 847        
 848        public function get query() : String
 849        {
 850           return URI.unescapeChars(this._query);
 851        }
 852        
 853        public function set scheme(schemeStr:String) : void
 854        {
 855           var normalized:String = schemeStr.toLowerCase();
 856           this._scheme = URI.fastEscapeChars(normalized,URI.URIschemeExcludedBitmap);
 857        }
 858        
 859        public function forceEscape() : void
 860        {
 861           this.scheme = this.scheme;
 862           this.setQueryByMap(this.getQueryByMap());
 863           this.fragment = this.fragment;
 864           if(this.isHierarchical())
 865           {
 866              this.authority = this.authority;
 867              this.path = this.path;
 868              this.port = this.port;
 869              this.username = this.username;
 870              this.password = this.password;
 871           }
 872           else
 873           {
 874              this.nonHierarchical = this.nonHierarchical;
 875           }
 876        }
 877        
 878        public function getDefaultPort() : String
 879        {
 880           if(this._scheme == "http")
 881           {
 882              return String("80");
 883           }
 884           if(this._scheme == "ftp")
 885           {
 886              return String("21");
 887           }
 888           if(this._scheme == "file")
 889           {
 890              return String("");
 891           }
 892           if(this._scheme == "sftp")
 893           {
 894              return String("22");
 895           }
 896           return String("");
 897        }
 898        
 899        public function get fragment() : String
 900        {
 901           return URI.unescapeChars(this._fragment);
 902        }
 903        
 904        public function set path(pathStr:String) : void
 905        {
 906           this._path = URI.fastEscapeChars(pathStr,URI.URIpathExcludedBitmap);
 907           if(this._scheme == UNKNOWN_SCHEME)
 908           {
 909              this._scheme = "";
 910           }
 911           this.hierState = true;
 912        }
 913        
 914        public function get authority() : String
 915        {
 916           return URI.unescapeChars(this._authority);
 917        }
 918        
 919        public function isHierarchical() : Boolean
 920        {
 921           return this.hierState;
 922        }
 923        
 924        protected function toStringInternal(forDisplay:Boolean) : String
 925        {
 926           var uri:String = "";
 927           var part:String = "";
 928           if(this.isHierarchical() == false)
 929           {
 930              uri += forDisplay ? this.scheme : this._scheme;
 931              uri += ":";
 932              uri += forDisplay ? this.nonHierarchical : this._nonHierarchical;
 933           }
 934           else
 935           {
 936              if(this.isRelative() == false)
 937              {
 938                 if(this._scheme.length != 0)
 939                 {
 940                    part = forDisplay ? this.scheme : this._scheme;
 941                    uri += part + ":";
 942                 }
 943                 if(this._authority.length != 0 || this.isOfType("file"))
 944                 {
 945                    uri += "//";
 946                    if(this._username.length != 0)
 947                    {
 948                       part = forDisplay ? this.username : this._username;
 949                       uri += part;
 950                       if(this._password.length != 0)
 951                       {
 952                          part = forDisplay ? this.password : this._password;
 953                          uri += ":" + part;
 954                       }
 955                       uri += "@";
 956                    }
 957                    part = forDisplay ? this.authority : this._authority;
 958                    uri += part;
 959                    if(this.port.length != 0)
 960                    {
 961                       uri += ":" + this.port;
 962                    }
 963                 }
 964              }
 965              part = forDisplay ? this.path : this._path;
 966              uri += part;
 967           }
 968           if(this._query.length != 0)
 969           {
 970              part = forDisplay ? this.query : this._query;
 971              uri += "?" + part;
 972           }
 973           if(this.fragment.length != 0)
 974           {
 975              part = forDisplay ? this.fragment : this._fragment;
 976              uri += "#" + part;
 977           }
 978           return uri;
 979        }
 980        
 981        public function get username() : String
 982        {
 983           return URI.unescapeChars(this._username);
 984        }
 985        
 986        public function unknownToURI(unknown:String, defaultScheme:String = "http") : Boolean
 987        {
 988           var temp:String = null;
 989           var path:String = null;
 990           if(unknown.length == 0)
 991           {
 992              this.initialize();
 993              return false;
 994           }
 995           unknown = unknown.replace(/\\/g,"/");
 996           if(unknown.length >= 2)
 997           {
 998              temp = unknown.substr(0,2);
 999              if(temp == "//")
1000              {
1001                 unknown = defaultScheme + ":" + unknown;
1002              }
1003           }
1004           if(unknown.length >= 3)
1005           {
1006              temp = unknown.substr(0,3);
1007              if(temp == "://")
1008              {
1009                 unknown = defaultScheme + unknown;
1010              }
1011           }
1012           var uri:URI = new URI(unknown);
1013           if(uri.isHierarchical() == false)
1014           {
1015              if(uri.scheme == UNKNOWN_SCHEME)
1016              {
1017                 this.initialize();
1018                 return false;
1019              }
1020              this.copyURI(uri);
1021              this.forceEscape();
1022              return true;
1023           }
1024           if(uri.scheme != UNKNOWN_SCHEME && uri.scheme.length > 0)
1025           {
1026              if(uri.authority.length > 0 || uri.scheme == "file")
1027              {
1028                 this.copyURI(uri);
1029                 this.forceEscape();
1030                 return true;
1031              }
1032              if(uri.authority.length == 0 && uri.path.length == 0)
1033              {
1034                 this.setParts(uri.scheme,"","","","","");
1035                 return false;
1036              }
1037           }
1038           else
1039           {
1040              path = uri.path;
1041              if(path == ".." || path == "." || path.length >= 3 && path.substr(0,3) == "../" || path.length >= 2 && path.substr(0,2) == "./")
1042              {
1043                 this.copyURI(uri);
1044                 this.forceEscape();
1045                 return true;
1046              }
1047           }
1048           uri = new URI(defaultScheme + "://" + unknown);
1049           if(uri.scheme.length > 0 && uri.authority.length > 0)
1050           {
1051              this.copyURI(uri);
1052              this.forceEscape();
1053              return true;
1054           }
1055           this.initialize();
1056           return false;
1057        }
1058        
1059        public function isDirectory() : Boolean
1060        {
1061           if(this._path.length == 0)
1062           {
1063              return false;
1064           }
1065           return this._path.charAt(this.path.length - 1) == "/";
1066        }
1067        
1068        protected function verifyAlpha(str:String) : Boolean
1069        {
1070           var index:int = 0;
1071           var pattern:RegExp = /[^a-z]/;
1072           str = str.toLowerCase();
1073           index = str.search(pattern);
1074           if(index == -1)
1075           {
1076              return true;
1077           }
1078           return false;
1079        }
1080        
1081        public function isOfFileType(extension:String) : Boolean
1082        {
1083           var thisExtension:String = null;
1084           var index:int = 0;
1085           index = extension.lastIndexOf(".");
1086           if(index != -1)
1087           {
1088              extension = extension.substr(index + 1);
1089           }
1090           thisExtension = this.getExtension(true);
1091           if(thisExtension == "")
1092           {
1093              return false;
1094           }
1095           if(compareStr(thisExtension,extension,false) == 0)
1096           {
1097              return true;
1098           }
1099           return false;
1100        }
1101        
1102        public function set nonHierarchical(nonHier:String) : void
1103        {
1104           this._nonHierarchical = URI.fastEscapeChars(nonHier,URInonHierexcludedBitmap);
1105           this.hierState = false;
1106        }
1107        
1108        protected function joinPath(parts:Array, isAbs:Boolean, isDir:Boolean) : String
1109        {
1110           var i:int = 0;
1111           var pathStr:String = "";
1112           for(i = 0; i < parts.length; i++)
1113           {
1114              if(pathStr.length > 0)
1115              {
1116                 pathStr += "/";
1117              }
1118              pathStr += parts[i];
1119           }
1120           if(isDir && pathStr.length > 0)
1121           {
1122              pathStr += "/";
1123           }
1124           if(isAbs)
1125           {
1126              pathStr = "/" + pathStr;
1127           }
1128           return pathStr;
1129        }
1130        
1131        public function isValid() : Boolean
1132        {
1133           return this._valid;
1134        }
1135        
1136        public function toString() : String
1137        {
1138           return "";
1139        }
1140        
1141        protected function validateURI() : Boolean
1142        {
1143           if(this.isAbsolute())
1144           {
1145              if(this._scheme.length <= 1 || this._scheme == UNKNOWN_SCHEME)
1146              {
1147                 return false;
1148              }
1149              if(this.verifyAlpha(this._scheme) == false)
1150              {
1151                 return false;
1152              }
1153           }
1154           if(this.hierState)
1155           {
1156              if(this._path.search("\\") != -1)
1157              {
1158                 return false;
1159              }
1160              if(this.isRelative() == false && this._scheme == UNKNOWN_SCHEME)
1161              {
1162                 return false;
1163              }
1164           }
1165           else if(this._nonHierarchical.search("\\") != -1)
1166           {
1167              return false;
1168           }
1169           return true;
1170        }
1171        
1172        public function getRelation(uri:URI, caseSensitive:Boolean = true) : int
1173        {
1174           var thisParts:Array = null;
1175           var thatParts:Array = null;
1176           var thisPart:String = null;
1177           var thatPart:String = null;
1178           var i:int = 0;
1179           var thisURI:URI = URI.resolve(this);
1180           var thatURI:URI = URI.resolve(uri);
1181           if(thisURI.isRelative() || thatURI.isRelative())
1182           {
1183              return URI.NOT_RELATED;
1184           }
1185           if(thisURI.isHierarchical() == false || thatURI.isHierarchical() == false)
1186           {
1187              if(thisURI.isHierarchical() == false && thatURI.isHierarchical() == true || thisURI.isHierarchical() == true && thatURI.isHierarchical() == false)
1188              {
1189                 return URI.NOT_RELATED;
1190              }
1191              if(thisURI.scheme != thatURI.scheme)
1192              {
1193                 return URI.NOT_RELATED;
1194              }
1195              if(thisURI.nonHierarchical != thatURI.nonHierarchical)
1196              {
1197                 return URI.NOT_RELATED;
1198              }
1199              return URI.EQUAL;
1200           }
1201           if(thisURI.scheme != thatURI.scheme)
1202           {
1203              return URI.NOT_RELATED;
1204           }
1205           if(thisURI.authority != thatURI.authority)
1206           {
1207              return URI.NOT_RELATED;
1208           }
1209           var thisPort:String = thisURI.port;
1210           var thatPort:String = thatURI.port;
1211           if(thisPort == "")
1212           {
1213              thisPort = thisURI.getDefaultPort();
1214           }
1215           if(thatPort == "")
1216           {
1217              thatPort = thatURI.getDefaultPort();
1218           }
1219           if(thisPort != thatPort)
1220           {
1221              return URI.NOT_RELATED;
1222           }
1223           if(compareStr(thisURI.path,thatURI.path,caseSensitive))
1224           {
1225              return URI.EQUAL;
1226           }
1227           var thisPath:String = thisURI.path;
1228           var thatPath:String = thatURI.path;
1229           if((thisPath == "/" || thatPath == "/") && (thisPath == "" || thatPath == ""))
1230           {
1231              return URI.EQUAL;
1232           }
1233           thisParts = thisPath.split("/");
1234           thatParts = thatPath.split("/");
1235           if(thisParts.length > thatParts.length)
1236           {
1237              thatPart = String(thatParts[thatParts.length - 1]);
1238              if(thatPart.length > 0)
1239              {
1240                 return URI.NOT_RELATED;
1241              }
1242              thatParts.pop();
1243              for(i = 0; i < thatParts.length; i++)
1244              {
1245                 thisPart = String(thisParts[i]);
1246                 thatPart = String(thatParts[i]);
1247                 if(compareStr(thisPart,thatPart,caseSensitive) == false)
1248                 {
1249                    return URI.NOT_RELATED;
1250                 }
1251              }
1252              return URI.CHILD;
1253           }
1254           if(thisParts.length < thatParts.length)
1255           {
1256              thisPart = String(thisParts[thisParts.length - 1]);
1257              if(thisPart.length > 0)
1258              {
1259                 return URI.NOT_RELATED;
1260              }
1261              thisParts.pop();
1262              for(i = 0; i < thisParts.length; i++)
1263              {
1264                 thisPart = String(thisParts[i]);
1265                 thatPart = String(thatParts[i]);
1266                 if(compareStr(thisPart,thatPart,caseSensitive) == false)
1267                 {
1268                    return URI.NOT_RELATED;
1269                 }
1270              }
1271              return URI.PARENT;
1272           }
1273           return URI.NOT_RELATED;
1274        }
1275        
1276        public function isOfType(scheme:String) : Boolean
1277        {
1278           scheme = scheme.toLowerCase();
1279           return this._scheme == scheme;
1280        }
1281        
1282        public function getQueryValue(name:String) : String
1283        {
1284           var map:Object = null;
1285           var item:String = null;
1286           var value:String = null;
1287           map = this.getQueryByMap();
1288           for(item in map)
1289           {
1290              if(item == name)
1291              {
1292                 return String(map[item]);
1293              }
1294           }
1295           return new String("");
1296        }
1297     }
1298  }