1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16interface NativeURLSearchParams {
17  new(input?: object | string | Iterable<[]> | null | undefined): NativeURLSearchParams;
18  append(params1: string, params2: string): void;
19  set(setname: string, setvalues: string): void;
20  sort(): void;
21  has(hasname: string): boolean;
22  toString(): string;
23  keys(): Array<string>;
24  values(): Array<string>;
25  getAll(getAllname: string): string[];
26  get(getname: string): string;
27  entries(): Array<Array<string>>;
28  delete(deletename: string): void;
29  updateParams(): void;
30  array: string[];
31}
32
33interface NativeURLParams {
34  new(input?: object | string | Iterable<[]> | null | undefined): NativeURLParams;
35  append(params1: string, params2: string): void;
36  set(setname: string, setvalues: string): void;
37  sort(): void;
38  has(hasname: string): boolean;
39  toString(): string;
40  keys(): Array<string>;
41  values(): Array<string>;
42  getAll(getAllname: string): string[];
43  get(getname: string): string;
44  entries(): Array<Array<string>>;
45  delete(deletename: string): void;
46  updateParams(): void;
47  array: string[];
48}
49
50interface NativeUrl {
51  new(input: string, base?: string | NativeUrl): NativeUrl;
52  new(): NativeUrl;
53  protocol: string;
54  username: string;
55  password: string;
56  hash: string;
57  search: string;
58  hostname: string;
59  host: string;
60  port: string;
61  href(input: string): void;
62  pathname: string;
63  onOrOff: boolean;
64  GetIsIpv6: boolean;
65  parseURL(input: string, base?: string | NativeUrl | URL): NativeUrl;
66}
67interface UrlInterface {
68  URLSearchParams1: NativeURLSearchParams;
69  Url: NativeUrl;
70  URLParams1: NativeURLParams;
71  stringParmas(input: string): string[];
72  fixUSVstring(input: string): string;
73}
74
75declare function requireInternal(s: string): UrlInterface;
76const UrlInterface = requireInternal('url');
77
78
79let seachParamsArr: Array<string> = [];
80const typeErrorCodeId = 401; // 401:ErrorCodeId
81const syntaxErrorCodeId = 10200002; // 10200002:syntaxErrorCodeId
82
83class BusinessError extends Error {
84  code: number;
85  constructor(msg: string) {
86    super(msg);
87    this.name = 'BusinessError';
88    this.code = typeErrorCodeId;
89  }
90}
91
92function decodeSafelyOut(input: string): string {
93  let decodedString: string = '';
94  let decodedTemp: string = '';
95  let index: number = 0;
96  while (index < input.length) {
97    if (input[index] === '%' && /[0-9A-Fa-f]{2}/.test(input.slice(index + 1, index + 3))) {
98      const encodedChar = input.slice(index, index + 3);
99    try {
100      decodedString += decodeURIComponent(decodedTemp + encodedChar);
101      decodedTemp = '';
102    } catch (e) {
103      decodedTemp += encodedChar;
104    }
105      index += 3;
106      continue;
107    }
108    if (decodedTemp === '') {
109      decodedString += input[index];
110    } else {
111      decodedString += decodedTemp;
112      decodedString += input[index];
113      decodedTemp = '';
114    }
115    index++;
116  }
117  return decodedTemp === '' ? decodedString : decodedString += decodedTemp;
118}
119
120function customEncodeForToString(str: string): string {
121  const hexStrLen = 2; // 2:String length of hexadecimal encoded values
122  const hexAdecimal = 16; // 16:Hexadecimal number system
123  const regex = /[!'()~]/g;
124  try {
125    str = encodeURIComponent(str);
126  } catch (error) {
127    str = encodeURIComponent(UrlInterface.fixUSVstring(str));
128  }
129  return str.replace(regex, function (c) {
130    let hex = c.charCodeAt(0).toString(hexAdecimal);
131    return '%' + (hex.length < hexStrLen ? '0' : '') + hex.toUpperCase();
132  })
133    .replace(/%20/g, '+');
134}
135
136function customEncodeURI(str: string, keepCharacters: object): string {
137  let encodedStr = '';
138  try {
139    encodedStr = encodeURI(str);
140  } catch (error) {
141    encodedStr = encodeURI(UrlInterface.fixUSVstring(str));
142  }
143  for (let key in keepCharacters) {
144    encodedStr = encodedStr.replaceAll(`${key}`, keepCharacters[key]);
145  }
146  return encodedStr;
147}
148
149function removeKeyValuePairs(str: string, key: string): string {
150  const regex = new RegExp(`\\b${key}=[^&]*&?`, 'g');
151  let result = str.replace(regex, '');
152  if (result.endsWith('&')) {
153    result = result.slice(0, -1);
154  }
155  return result;
156}
157
158class URLParams {
159  urlClass: NativeURLParams;
160  parentUrl: URL | null = null;
161  constructor(input: object | string | Iterable<[]> | null | undefined) {
162    let out: string[] = parameterProcess(input);
163    this.urlClass = new UrlInterface.URLParams1();
164    this.urlClass.array = out;
165  }
166
167  append(params1: string, params2: string): void {
168    if (arguments.length === 0 || typeof params1 !== 'string') {
169      throw new BusinessError(`Parameter error. The type of ${params1} must be string`);
170    }
171    if (arguments.length === 1 || typeof params2 !== 'string') {
172      throw new BusinessError(`Parameter error. The type of ${params2} must be string`);
173    }
174    this.urlClass.append(params1, params2);
175    if (this.parentUrl !== null) {
176      this.parentUrl.c_info.search = this.toString();
177      this.parentUrl.search_ = this.parentUrl.c_info.search;
178      this.parentUrl.setHref();
179    }
180  }
181
182  set(setName: string, setValues: string): void {
183    if (arguments.length === 0 || typeof setName !== 'string') {
184      throw new BusinessError(`Parameter error. The type of ${setName} must be string`);
185    }
186    if (arguments.length === 1 || typeof setValues !== 'string') {
187      throw new BusinessError(`Parameter error. The type of ${setValues} must be string`);
188    }
189    this.urlClass.set(setName, setValues);
190    if (this.parentUrl !== null) {
191      this.parentUrl.c_info.search = this.toString();
192      this.parentUrl.search_ = this.parentUrl.c_info.search;
193      this.parentUrl.setHref();
194    }
195  }
196
197  sort(): void {
198    this.urlClass.sort();
199    if (this.parentUrl !== null) {
200      this.parentUrl.c_info.search = this.toString();
201      this.parentUrl.search_ = this.parentUrl.c_info.search;
202      this.parentUrl.setHref();
203    }
204  }
205
206  has(hasname: string): boolean {
207    if (typeof hasname !== 'string') {
208      throw new BusinessError(`Parameter error. The type of ${hasname} must be string`);
209    }
210    return this.urlClass.has(hasname);
211  }
212
213  toString(): string {
214    const resultArray: string[] = [];
215    let arrayLen: number = this.urlClass.array.length;
216    let array: string[] = this.urlClass.array;
217    let key: string = '';
218    let value: string = '';
219    for (let pos: number = 0; pos < arrayLen; pos += 2) { // 2:Even subscripts exist as key values
220      key = customEncodeForToString(array[pos]).replace(/=/g, '%3D');
221      value = customEncodeForToString(array[pos + 1]).replace(/=/g, '%3D');
222      resultArray.push(`${pos > 0 ? '&' : ''}${key}=${value}`);
223    }
224    return resultArray.join('');
225  }
226
227  keys(): Object {
228    return this.urlClass.keys();
229  }
230
231  values(): Object {
232    return this.urlClass.values();
233  }
234
235  getAll(getAllname: string): string[] {
236    if ((arguments.length !== 1) || (typeof getAllname !== 'string')) {
237      throw new BusinessError(`Parameter error. The type of ${getAllname} must be string`);
238    }
239    return this.urlClass.getAll(getAllname);
240  }
241
242  get(getname: string): string {
243    if (arguments.length === 0 || typeof getname !== 'string') {
244      throw new BusinessError(`Parameter error. The type of ${getname} must be string`);
245    }
246    return this.urlClass.get(getname);
247  }
248
249  entries(): Object {
250    return this.urlClass.entries();
251  }
252
253  delete(deleteName: string): void {
254    if (arguments.length === 0 || typeof deleteName !== 'string') {
255      throw new BusinessError(`Parameter error. The type of ${deleteName} must be string`);
256    }
257    this.urlClass.delete(deleteName);
258    if (this.parentUrl !== null) {
259      let searchStr: string = removeKeyValuePairs(this.parentUrl.c_info.search, deleteName);
260      this.parentUrl.c_info.search = searchStr;
261      this.parentUrl.search_ = searchStr;
262      this.parentUrl.setHref();
263    }
264  }
265
266  forEach(objfun: Function, thisArg?: Object): void {
267    if (typeof objfun !== 'function') {
268      throw new BusinessError(`Parameter error. The type of ${objfun} must be function`);
269    }
270    let array = this.urlClass.array;
271    if (array.length === 0) {
272      return;
273    }
274    if (typeof thisArg === 'undefined' || thisArg === null) {
275      thisArg = Object;
276    }
277    let size = array.length - 1;
278    for (let i = 0; i < size; i += 2) { // 2:Searching for the number and number of keys and values 2
279      let key = array[i];
280      let value = array[i + 1];
281      objfun.call(thisArg, value, key, this);
282    }
283  }
284
285  [Symbol.iterator](): Object {
286    return this.urlClass.entries();
287  }
288
289  updateParams(input: string): void {
290    let out = [];
291    out = parameterProcess(input);
292    this.urlClass.array = out;
293  }
294}
295
296class URLSearchParams {
297  urlClass: NativeURLSearchParams;
298  parentUrl: URL | null = null;
299  constructor(input: object | string | Iterable<[]> | null | undefined) {
300    let out: string[] = parameterProcessing(input);
301    this.urlClass = new UrlInterface.URLSearchParams1();
302    this.urlClass.array = out;
303  }
304  append(params1: string, params2: string): void {
305    if (arguments.length === 0 || typeof params1 !== 'string') {
306      throw new BusinessError(`Parameter error. The type of ${params1} must be string`);
307    }
308    if (arguments.length === 1 || typeof params2 !== 'string') {
309      throw new BusinessError(`Parameter error. The type of ${params2} must be string`);
310    }
311    this.urlClass.append(params1, params2);
312    if (this.parentUrl !== null) {
313      this.parentUrl.c_info.search = this.toString();
314      this.parentUrl.search_ = this.parentUrl.c_info.search;
315      this.parentUrl.setHref();
316    }
317  }
318
319  set(setName: string, setValues: string): void {
320    if (arguments.length === 0 || typeof setName !== 'string') {
321      throw new BusinessError(`Parameter error. The type of ${setName} must be string`);
322    }
323    if (arguments.length === 1 || typeof setValues !== 'string') {
324      throw new BusinessError(`Parameter error. The type of ${setValues} must be string`);
325    }
326    this.urlClass.set(setName, setValues);
327    if (this.parentUrl !== null) {
328      this.parentUrl.c_info.search = this.toString();
329      this.parentUrl.search_ = this.parentUrl.c_info.search;
330      this.parentUrl.setHref();
331    }
332  }
333
334  sort(): void {
335    this.urlClass.sort();
336    if (this.parentUrl !== null) {
337      this.parentUrl.c_info.search = this.toString();
338      this.parentUrl.search_ = this.parentUrl.c_info.search;
339      this.parentUrl.setHref();
340    }
341  }
342
343  has(hasname: string): boolean {
344    if (typeof hasname !== 'string') {
345      throw new BusinessError(`Parameter error. The type of ${hasname} must be string`);
346    }
347    return this.urlClass.has(hasname);
348  }
349
350  toString(): string {
351    const resultArray: string[] = [];
352    let arrayLen: number = this.urlClass.array.length;
353    let array: string[] = this.urlClass.array;
354    let key: string = '';
355    let value: string = '';
356    for (let pos: number = 0; pos < arrayLen; pos += 2) { // 2:Even subscripts exist as key values
357      key = customEncodeForToString(array[pos]).replace(/=/g, '%3D');
358      value = customEncodeForToString(array[pos + 1]).replace(/=/g, '%3D');
359      resultArray.push(`${pos > 0 ? '&' : ''}${key}=${value}`);
360    }
361    return resultArray.join('');
362  }
363
364  keys(): Object {
365    return this.urlClass.keys();
366  }
367
368  values(): Object {
369    return this.urlClass.values();
370  }
371
372  getAll(getAllname: string): string[] {
373    return this.urlClass.getAll(getAllname);
374  }
375
376  get(getname: string): string {
377    return this.urlClass.get(getname);
378  }
379
380  entries(): Object {
381    return this.urlClass.entries();
382  }
383
384  delete(deleteName: string): void {
385    this.urlClass.delete(deleteName);
386    if (this.parentUrl !== null) {
387      let searchStr: string = removeKeyValuePairs(this.parentUrl.c_info.search, deleteName);
388      this.parentUrl.c_info.search = searchStr;
389      this.parentUrl.search_ = searchStr;
390      this.parentUrl.setHref();
391    }
392  }
393
394  forEach(objfun: Function, thisArg?: Object): void {
395    let array = this.urlClass.array;
396    if (array.length === 0) {
397      return;
398    }
399    if (typeof thisArg === 'undefined' || thisArg === null) {
400      thisArg = Object;
401    }
402    let size = array.length - 1;
403    for (let i = 0; i < size; i += 2) { // 2:Searching for the number and number of keys and values 2
404      let key = array[i];
405      let value = array[i + 1];
406      objfun.call(thisArg, value, key, this);
407    }
408  }
409
410  [Symbol.iterator](): Object {
411    return this.urlClass.entries();
412  }
413
414  updateParams(input: string): void {
415    let out = [];
416    out = parameterProcessing(input);
417    this.urlClass.array = out;
418  }
419}
420
421function toHleString(arg: string | symbol | number): string {
422  return arg.toString();
423}
424
425function parameterProcess(input: object | string | Iterable<[]>): Array<string> {
426  if (input === null || typeof input === 'undefined' || input === '') {
427    seachParamsArr = [];
428    return seachParamsArr;
429  } else if (typeof input === 'object' || typeof input === 'function') {
430    if (input instanceof URLParams) {
431        return input.urlClass.array;
432    }
433    return sysObjectParams(input);
434  } else {
435    return initToStringSeachParams(input);
436  }
437}
438
439function parameterProcessing(input: object | string | Iterable<[]>): Array<string> {
440  if (input === null || typeof input === 'undefined' || input === '') {
441    seachParamsArr = [];
442    return seachParamsArr;
443  } else if (typeof input === 'object' || typeof input === 'function') {
444    if (input instanceof URLSearchParams) {
445        return input.urlClass.array;
446    }
447    return initObjectSeachParams(input);
448  } else {
449    return initToStringSeachParams(input);
450  }
451}
452
453function sysObjectParams(input: object | Iterable<[]>): Array<string> {
454  if (typeof input[Symbol.iterator] === 'function') {
455    return iteratorMethodThrow(input as Iterable<[string]>);
456  }
457  return recordMethod(input);
458}
459
460function initObjectSeachParams(input: object | Iterable<[]>): Array<string> {
461  if (typeof input[Symbol.iterator] === 'function') {
462    return iteratorMethod(input as Iterable<[string]>);
463  }
464  return recordMethod(input);
465}
466
467function recordMethod(input: object) : Array<string> {
468  const keys = Reflect.ownKeys(input);
469  seachParamsArr = [];
470  for (let i = 0; i <= keys.length; i++) {
471    const key = keys[i];
472    const desc = Reflect.getOwnPropertyDescriptor(input, key);
473    if (desc !== undefined && desc.enumerable) {
474      const typedKey = toHleString(key);
475      const typedValue = toHleString(input[key]);
476      seachParamsArr.push(typedKey, typedValue);
477    }
478  }
479  return seachParamsArr;
480}
481
482function iteratorMethodThrow(input: Iterable<[string]>): Array<string> {
483  let pairs = [];
484  seachParamsArr = [];
485  for (const pair of input) {
486    if ((typeof pair !== 'object' && typeof pair !== 'function') || pair === null || typeof pair[Symbol.iterator] !== 'function') {
487      throw new BusinessError(`Parameter error. The type of ${input} must be string[][]`);
488    }
489    const convertedPair = [];
490    for (let element of pair) {
491      convertedPair.push(element);
492    }
493    pairs.push(convertedPair);
494  }
495
496  for (const pair of pairs) {
497    if (pair.length !== 2) { // 2:Searching for the number and number of keys and values 2
498      throw new BusinessError(`Parameter error. The type of ${input} must be string[][]`);
499    }
500    seachParamsArr.push(pair[0], pair[1]);
501  }
502  return seachParamsArr;
503}
504
505function iteratorMethod(input: Iterable<[string]>): Array<string> {
506  let pairs = [];
507  seachParamsArr = [];
508  for (const pair of input) {
509    const convertedPair = [];
510    for (let element of pair) {
511      convertedPair.push(element);
512    }
513    pairs.push(convertedPair);
514  }
515
516  for (const pair of pairs) {
517    if (pair.length !== 2) { // 2:Searching for the number and number of keys and values 2
518      console.error('key-value-is-worong');
519    }
520    seachParamsArr.push(pair[0], pair[1]);
521  }
522  return seachParamsArr;
523}
524
525function decodeStringParmas(input: string): string {
526  let strVal = '';
527  try {
528    strVal = decodeURIComponent(input);
529  } catch (e) {
530    strVal = decodeSafelyOut(input);
531  }
532  return strVal;
533}
534
535function initToStringSeachParams(input: string): Array<string> {
536  if (typeof input !== 'string') {
537    throw new BusinessError(`Parameter error. The type of ${input} must be string`);
538  }
539  if (input[0] === '?') {
540    input = input.slice(1);
541  }
542  let strVal = input.replace(/\+/g, ' ');
543  seachParamsArr = UrlInterface.stringParmas(strVal);
544  return seachParamsArr.map(item => {
545    return item = decodeStringParmas(item);
546  });
547}
548
549class URL {
550  href_: string = '';
551  search_: string = '';
552  origin_: string = '';
553  username_: string = '';
554  password_: string = '';
555  hostname_: string = '';
556  host_: string = '';
557  hash_: string = '';
558  protocol_: string = '';
559  pathname_: string = '';
560  port_: string = '';
561  searchParamsClass_ !: URLSearchParams;
562  URLParamsClass_ !: URLParams;
563  c_info !: NativeUrl;
564  public constructor();
565  public constructor(inputUrl: string, inputBase?: string | URL);
566  public constructor(inputUrl?: string, inputBase?: string | URL) {
567    if (arguments.length === 0) {
568    }
569    let nativeUrl !: NativeUrl;
570    if (arguments.length === 1 || (arguments.length === 2 && (typeof inputBase === 'undefined' || inputBase === null))) {
571      if (typeof inputUrl === 'string' && inputUrl.length > 0) {
572        nativeUrl = new UrlInterface.Url(inputUrl);
573      } else {
574        throw new BusinessError(`Parameter error. The type of ${inputUrl} must be string`);
575      }
576    } else if (arguments.length === 2) { // 2:The number of parameters is 2
577      if (typeof inputUrl === 'string') {
578        if (typeof inputBase === 'string') {
579          if (inputBase.length > 0) {
580            nativeUrl = new UrlInterface.Url(inputUrl, inputBase);
581          } else {
582            throw new BusinessError(`Parameter error. The type of ${inputUrl} must be string`);
583            return;
584          }
585        } else if (typeof inputBase === 'object') {
586          let nativeBase: NativeUrl = inputBase.getInfo();
587          nativeUrl = new UrlInterface.Url(inputUrl, nativeBase);
588        }
589      }
590    }
591    if (arguments.length === 1 || arguments.length === 2) { // 2:The number of parameters is 2
592      this.c_info = nativeUrl;
593      if (nativeUrl.onOrOff) {
594        this.search_ = nativeUrl.search;
595        this.username_ = customEncodeURI(nativeUrl.username, {'%25':'%'});
596        this.password_ = customEncodeURI(nativeUrl.password, {'%25':'%'});
597        if (nativeUrl.GetIsIpv6) {
598          this.hostname_ = nativeUrl.hostname;
599          this.host_ = nativeUrl.host;
600        } else {
601          this.hostname_ = customEncodeURI(nativeUrl.hostname, {});
602          this.host_ = customEncodeURI(nativeUrl.host, {});
603        }
604        this.hash_ = customEncodeURI(nativeUrl.hash,
605          {'%7C': '|', '%5B': '[', '%5D': ']', '%7B': '{', '%7D': '}', '%60': '`', '%25': '%'});
606        this.protocol_ = nativeUrl.protocol;
607        this.pathname_ = customEncodeURI(nativeUrl.pathname, {'%7C': '|', '%5B': '[', '%5D': ']', '%25': '%'});
608        this.port_ = nativeUrl.port;
609        this.origin_ = nativeUrl.protocol + '//' + nativeUrl.host;
610        this.searchParamsClass_ = new URLSearchParams(customEncodeURI(this.search_,
611          {'%7C': '|', '%5B': '[', '%5D': ']', '%5E': '^', '%25': '%'}));
612        this.URLParamsClass_ = new URLParams(customEncodeURI(this.search_,
613          {'%7C': '|', '%5B': '[', '%5D': ']', '%5E': '^', '%25': '%'}));
614        this.URLParamsClass_.parentUrl = this;
615        this.searchParamsClass_.parentUrl = this;
616        this.setHref();
617      } else {
618        console.error('constructor failed');
619      }
620    }
621  }
622
623  static parseURL(inputUrl: string, inputBase?: string | NativeUrl | URL): URL {
624    if (typeof inputUrl !== 'string') {
625      throw new BusinessError(`Parameter error. The type of ${inputUrl} must be string`);
626    }
627    let nativeUrl !: NativeUrl;
628    if (arguments.length === 1 || (arguments.length === 2 && (typeof inputBase === 'undefined' || inputBase === null))) {
629      nativeUrl = new UrlInterface.Url(inputUrl);
630    } else if (arguments.length === 2) { // 2:The number of parameters is 2
631      if (typeof inputBase === 'string') {
632        if (inputBase.length > 0) {
633          nativeUrl = new UrlInterface.Url(inputUrl, inputBase);
634        } else {
635          throw new BusinessError(`Parameter error. The type of ${inputBase} must be string`);
636        }
637      } else if (typeof inputBase === 'object') {
638        let nativeBase: NativeUrl = inputBase.getInfo();
639        nativeUrl = new UrlInterface.Url(inputUrl, nativeBase);
640      } else {
641        throw new BusinessError(`Parameter error. The type of ${inputBase} must be string or URL`);
642      }
643    }
644    let urlHelper = new URL();
645    urlHelper.c_info = nativeUrl;
646    if (nativeUrl.onOrOff) {
647      urlHelper.search_ = nativeUrl.search;
648      urlHelper.username_ = customEncodeURI(nativeUrl.username, {'%25':'%'});
649      urlHelper.password_ = customEncodeURI(nativeUrl.password, {'%25':'%'});
650      if (nativeUrl.GetIsIpv6) {
651        urlHelper.hostname_ = nativeUrl.hostname;
652        urlHelper.host_ = nativeUrl.host;
653      } else {
654        urlHelper.hostname_ = customEncodeURI(nativeUrl.hostname, {});
655        urlHelper.host_ = customEncodeURI(nativeUrl.host, {});
656      }
657      urlHelper.hash_ = customEncodeURI(nativeUrl.hash,
658        {'%7C': '|', '%5B': '[', '%5D': ']', '%7B': '{', '%7D': '}', '%60': '`', '%25': '%'});
659      urlHelper.protocol_ = nativeUrl.protocol;
660      urlHelper.pathname_ = customEncodeURI(nativeUrl.pathname, {'%7C': '|', '%5B': '[', '%5D': ']', '%25': '%'});
661      urlHelper.port_ = nativeUrl.port;
662      urlHelper.origin_ = nativeUrl.protocol + '//' + nativeUrl.host;
663      urlHelper.searchParamsClass_ = new URLSearchParams(customEncodeURI(urlHelper.search_,
664        {'%7C': '|', '%5B': '[', '%5D': ']', '%5E': '^', '%25': '%'}));
665      urlHelper.URLParamsClass_ = new URLParams(customEncodeURI(urlHelper.search_,
666        {'%7C': '|', '%5B': '[', '%5D': ']', '%5E': '^', '%25': '%'}));
667      urlHelper.URLParamsClass_.parentUrl = urlHelper;
668      urlHelper.searchParamsClass_.parentUrl = urlHelper;
669      urlHelper.setHref();
670    } else {
671      let err : BusinessError = new BusinessError('Syntax Error. Invalid Url string');
672      err.code = syntaxErrorCodeId;
673      throw err;
674    }
675    return urlHelper;
676  }
677
678  getInfo(): NativeUrl {
679    return this.c_info;
680  }
681  toString(): string {
682    return this.href_;
683  }
684
685  get protocol(): string {
686    return this.protocol_;
687  }
688  set protocol(scheme) {
689    if (scheme.length === 0) {
690      return;
691    }
692    if (this.protocol_ === 'file:' && (this.host_ === '' || this.host_ === null)) {
693      return;
694    }
695    this.c_info.protocol = scheme;
696    this.protocol_ = this.c_info.protocol;
697    this.setHref();
698  }
699  get origin(): string {
700    let kOpaqueOrigin: string = 'null';
701    switch (this.protocol_) {
702      case 'ftp:':
703      case 'gopher:':
704      case 'http:':
705      case 'https:':
706      case 'ws:':
707      case 'wss:':
708        return this.origin_;
709    }
710    return kOpaqueOrigin;
711  }
712  get username(): string {
713    return this.username_;
714  }
715  set username(input) {
716    if (this.host_ === null || this.host_ === '' || this.protocol_ === 'file:') {
717      return;
718    }
719    const usname_ = customEncodeURI(input, {'%25':'%'});
720    this.c_info.username = usname_;
721    this.username_ = this.c_info.username;
722    this.setHref();
723  }
724  get password(): string {
725    return this.password_;
726  }
727  set password(input) {
728    if (this.host_ === null || this.host_ === '' || this.protocol_ === 'file:') {
729      return;
730    }
731    const passwd_ = customEncodeURI(input, {'%25':'%'});
732    this.c_info.password = passwd_;
733    this.password_ = this.c_info.password;
734    this.setHref();
735  }
736  get hash(): string {
737    return this.hash_;
738  }
739  set hash(fragment) {
740    const fragment_ = customEncodeURI(fragment,
741      {'%7C': '|', '%5B': '[', '%5D': ']', '%7B': '{', '%7D': '}', '%60': '`', '%25': '%'});
742    this.c_info.hash = fragment_;
743    this.hash_ = this.c_info.hash;
744    this.setHref();
745  }
746  get search(): string {
747    return this.search_;
748  }
749  set search(query) {
750    const query_ = customEncodeURI(query,
751      {'%7C': '|', '%5B': '[', '%5D': ']', '%7B': '{', '%7D': '}', '%60': '`', '%5E': '^', '%25': '%'});
752    this.c_info.search = query_;
753    this.search_ = this.c_info.search;
754    this.searchParamsClass_.updateParams(this.search_);
755    this.URLParamsClass_.updateParams(this.search_);
756    this.setHref();
757  }
758  get hostname(): string {
759    return this.hostname_;
760  }
761  set hostname(hostname) {
762    this.c_info.hostname = hostname;
763    if (this.c_info.GetIsIpv6) {
764      this.hostname_ = this.c_info.hostname;
765    } else {
766      this.hostname_ = customEncodeURI(this.c_info.hostname, {});
767    }
768    this.setHref();
769  }
770  get host(): string {
771    return this.host_;
772  }
773  set host(host_) {
774    this.c_info.host = host_;
775    if (this.c_info.GetIsIpv6) {
776      this.host_ = this.c_info.host;
777      this.hostname_ = this.c_info.hostname;
778      this.port_ = this.c_info.port;
779    } else {
780      this.host_ = customEncodeURI(this.c_info.host, {});
781      this.hostname_ = customEncodeURI(this.c_info.hostname, {});
782      this.port_ = this.c_info.port;
783    }
784    this.setHref();
785  }
786  get port(): string {
787    return this.port_;
788  }
789  set port(port) {
790    if (this.host_ === '' || this.protocol_ === 'file:' || port === '') {
791      return;
792    }
793    this.c_info.port = port;
794    this.port_ = this.c_info.port;
795    this.setHref();
796  }
797  get href(): string {
798    return this.href_;
799  }
800  set href(href_) {
801    this.c_info.href(href_);
802    if (this.c_info.onOrOff) {
803      this.search_ = this.c_info.search;
804      this.username_ = customEncodeURI(this.c_info.username, {'%25':'%'});
805      this.password_ = customEncodeURI(this.c_info.password, {'%25':'%'});
806      if (this.c_info.GetIsIpv6) {
807        this.hostname_ = this.c_info.hostname;
808        this.host_ = this.c_info.host;
809      } else {
810        this.hostname_ = customEncodeURI(this.c_info.hostname, {});
811        this.host_ = customEncodeURI(this.c_info.host, {});
812      }
813      this.hash_ = customEncodeURI(this.c_info.hash,
814        {'%7C': '|', '%5B': '[', '%5D': ']', '%7B': '{', '%7D': '}', '%60': '`', '%25': '%'});
815      this.protocol_ = this.c_info.protocol;
816      this.pathname_ = customEncodeURI(this.c_info.pathname, {'%7C': '|', '%5B': '[', '%5D': ']', '%25': '%'});
817      this.port_ = this.c_info.port;
818      this.origin_ = this.protocol_ + '//' + this.host_;
819      this.searchParamsClass_.updateParams(this.search_);
820      this.URLParamsClass_.updateParams(this.search_);
821      this.setHref();
822    }
823  }
824
825  get pathname(): string {
826    return this.pathname_;
827  }
828  set pathname(path) {
829    const path_ = customEncodeURI(path, {'%7C': '|', '%5B': '[', '%5D': ']', '%25': '%'});
830    this.c_info.pathname = path_;
831    this.pathname_ = this.c_info.pathname;
832    this.setHref();
833  }
834
835  get searchParams(): URLSearchParams {
836    return this.searchParamsClass_;
837  }
838
839  get params(): URLParams {
840    return this.URLParamsClass_;
841  }
842
843  toJSON(): string {
844    return this.href_;
845  }
846  setHref(): void {
847    let temp: string = this.protocol_;
848    if (this.hostname_ !== '') {
849      temp += '//';
850      if (this.password_ !== '' || this.username_ !== '') {
851        if (this.username_ !== '') {
852          temp += this.username_;
853        }
854        if (this.password_ !== '') {
855          temp += ':';
856          temp += this.password_;
857        }
858        temp += '@';
859      }
860      temp += this.hostname_;
861      if (this.port_ !== '') {
862        temp += ':';
863        temp += this.port_;
864      }
865    } else if (this.protocol_ === 'file:') {
866      temp += '//';
867    }
868    temp += this.pathname_;
869    if (this.search_) {
870      temp += this.search_;
871    }
872    if (this.hash_) {
873      temp += this.hash_;
874    }
875    this.href_ = temp;
876  }
877}
878
879export default {
880  URLSearchParams: URLSearchParams,
881  URL: URL,
882  URLParams: URLParams,
883};
884