sync with tizen_2.0
[platform/framework/native/appfw.git] / src / base / utility / FBaseUtilUri.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FBaseUtilUri.cpp
20  * @brief               This is the implementation file for Uri class.
21  */
22
23 // Includes
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <new>
27 #include <unique_ptr.h>
28 #include <FBaseUtilUri.h>
29 #include <FBaseInteger.h>
30 #include <FBaseCharacter.h>
31 #include <FBaseShort.h>
32 #include <FBaseUtilStringTokenizer.h>
33 #include <FBaseUtilStringUtil.h>
34 #include <FBaseSysLog.h>
35
36
37 namespace Tizen { namespace Base { namespace Utility
38 {
39
40 static const wchar_t HEX_DIGITS[] = {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F'};
41
42
43 /////////////////////////////////////////////////////////////////////////////////
44 // Life-cycle
45
46 Uri::Uri(void)
47         : __port(-1)
48         , __hasScheme(false)
49         , __ipv6ByteCount(0)
50         , __pUriImpl(null)
51 {
52 }
53
54
55 Uri::Uri(const Uri& uri)
56         : __pUriImpl(null)
57 {
58         SetUri(uri);
59 }
60
61
62 Uri::~Uri(void)
63 {
64         Clear();
65 }
66
67
68 void
69 Uri::SetUri(const Uri& uri)
70 {
71         __scheme = uri.__scheme;
72         __ssp = uri.__ssp;
73         __authority = uri.__authority;
74         __host = uri.__host;
75         __fragment = uri.__fragment;
76         __path = uri.__path;
77         __userInfo = uri.__userInfo;
78         __query = uri.__query;
79         __ipv4 = uri.__ipv4;
80         __ipv6 = uri.__ipv6;
81
82         __encodedAuth = uri.__encodedAuth;
83         __encodedFragment = uri.__encodedFragment;
84         __encodedPath = uri.__encodedPath;
85         __encodedQuery = uri.__encodedQuery;
86         __encodedSsp = uri.__encodedSsp;
87         __encodedUserInfo = uri.__encodedUserInfo;
88
89         __port = uri.__port;
90         __hasScheme = uri.__hasScheme;
91         __ipv6ByteCount = uri.__ipv6ByteCount;
92 }
93
94
95 result
96 Uri::SetUri(const Tizen::Base::String& str)
97 {
98         SysTryReturn(NID_BASE_UTIL, str.GetLength() > 0, E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used. An empty String.", GetErrorMessage(E_INVALID_ARG));
99
100         Clear();
101
102         result r = ParseUri(str);
103         if (IsFailed(r))
104         {
105                 return r;
106         }
107
108         return E_SUCCESS;
109 }
110
111
112 result
113 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& ssp, const Tizen::Base::String& fragment)
114 {
115         String empty;
116
117         // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
118         return SetUri(scheme, ssp, empty, empty, empty, -1, empty, empty, fragment);
119 }
120
121
122 result
123 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port,
124                         const Tizen::Base::String& path, const Tizen::Base::String& query,
125                         const Tizen::Base::String& fragment)
126 {
127         String empty;
128
129         // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
130         return SetUri(scheme, empty, empty, userInfo, host, port, path, query, fragment);
131 }
132
133
134 result
135 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& host, const Tizen::Base::String& path,
136                         const Tizen::Base::String& fragment)
137 {
138         String empty;
139
140         // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
141         return SetUri(scheme, empty, empty, empty, host, -1, path, L"", fragment);
142 }
143
144
145 result
146 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& authority, const Tizen::Base::String& path,
147                         const Tizen::Base::String& query,
148                         const Tizen::Base::String& fragment)
149 {
150         String empty;
151
152         // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
153         return SetUri(scheme, empty, authority, empty, empty, -1, path, query, fragment);
154 }
155
156
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Operator
159
160 Uri&
161 Uri::operator =(const Uri& rhs)
162 {
163         if (&rhs != this)
164         {
165                 SetUri(rhs);
166         }
167         return *this;
168 }
169
170
171 ////////////////////////////////////////////////////////////////////////////////
172 // Accessor
173
174 Tizen::Base::String
175 Uri::GetAuthority(void) const
176 {
177         return __authority;
178 }
179
180
181 Tizen::Base::String
182 Uri::GetFragment(void) const
183 {
184         return __fragment;
185 }
186
187
188 Tizen::Base::String
189 Uri::GetHost(void) const
190 {
191         return __host;
192 }
193
194
195 Tizen::Base::String
196 Uri::GetPath(void) const
197 {
198         return __path;
199 }
200
201
202 int
203 Uri::GetPort(void) const
204 {
205         return __port;
206 }
207
208
209 Tizen::Base::String
210 Uri::GetQuery(void) const
211 {
212         return __query;
213 }
214
215
216 Tizen::Base::String
217 Uri::GetScheme(void) const
218 {
219         return __scheme;
220 }
221
222
223 Tizen::Base::String
224 Uri::GetSchemeSpecificPart(void) const
225 {
226         return __ssp;
227 }
228
229
230 Tizen::Base::String
231 Uri::GetUserInfo(void) const
232 {
233         return __userInfo;
234 }
235
236
237 Tizen::Base::String
238 Uri::GetEncodedAuthority(void) const
239 {
240         return __encodedAuth;
241 }
242
243
244 Tizen::Base::String
245 Uri::GetEncodedFragment(void) const
246 {
247         return __encodedFragment;
248 }
249
250
251 Tizen::Base::String
252 Uri::GetEncodedPath(void) const
253 {
254         return __encodedPath;
255 }
256
257
258 Tizen::Base::String
259 Uri::GetEncodedQuery(void) const
260 {
261         return __encodedQuery;
262 }
263
264
265 Tizen::Base::String
266 Uri::GetEncodedSchemeSpecificPart(void) const
267 {
268         return __encodedSsp;
269 }
270
271
272 Tizen::Base::String
273 Uri::GetEncodedUserInfo(void) const
274 {
275         return __encodedUserInfo;
276 }
277
278
279 bool
280 Uri::IsAbsolute(void) const
281 {
282         // If the URI has a scheme, then it is an absolute URI.
283         if (__hasScheme)
284         {
285                 return true;
286         }
287         else
288         {
289                 return false;
290         }
291 }
292
293
294 bool
295 Uri::IsOpaque(void) const
296 {
297         String scheme = GetScheme();
298         String ssp = GetSchemeSpecificPart();
299
300         if (scheme.IsEmpty())
301         {
302                 return false;
303         }
304
305         if (!ssp.IsEmpty())
306         {
307                 if (ssp[0] == L'/')
308                 {
309                         return false;
310                 }
311                 else
312                 {
313                         return true;
314                 }
315         }
316         else
317         {
318                 return false;
319         }
320 }
321
322
323 Tizen::Base::String
324 Uri::GetEncodedString(void) const
325 {
326         String strbuf;
327
328         // Scheme
329         if (!__scheme.IsEmpty())
330         {
331                 strbuf.Append(__scheme);
332                 strbuf.Append(L':');
333         }
334
335         //AppendSchemeSpecificPart(strbuf, __encodedSsp, __encodedAuth, __encodedUserInfo, __host, __port, __encodedPath, __encodedQuery);
336         if (!__encodedSsp.IsEmpty())
337         {
338                 strbuf.Append(__encodedSsp);
339         }
340         else
341         {
342                 //r = AppendAuthority(strbuf, __authority, __userInfo, __host, __port);
343                 if (!__host.IsEmpty())
344                 {
345                         // Check the Host
346                         strbuf.Append(L"//");
347
348                         // Check the Userinfo
349                         if (!__encodedUserInfo.IsEmpty())
350                         {
351                                 strbuf.Append(__encodedUserInfo);
352                                 strbuf.Append(L'@');
353                         }
354
355                         int indexOf = 0;
356                         result re = E_SUCCESS;
357                         re = __host.IndexOf(L':', 0, indexOf);
358
359                         String openBracket(L"[");
360                         String closeBracket(L"]");
361
362                         bool start = __host.StartsWith(openBracket, 0);
363                         bool end = __host.EndsWith(closeBracket);
364
365                         bool needBracket = false;
366                         if (!start && !end && re == E_SUCCESS)
367                         {
368                                 needBracket = true;
369                         }
370                         else
371                         {
372                                 needBracket = false;
373                         }
374
375                         if (needBracket)
376                         {
377                                 strbuf.Append(L'[');
378                         }
379
380                         strbuf.Append(__host);
381
382                         if (needBracket)
383                         {
384                                 strbuf.Append(L']');
385                         }
386
387                         // Check the port
388                         if (__port >= 0)
389                         {
390                                 strbuf.Append(L':');
391                                 strbuf.Append(__port);
392                         }
393                 }
394                 else if (!__encodedAuth.IsEmpty())
395                 {
396                         strbuf.Append(L"//");
397                         strbuf.Append(__encodedAuth);
398                 }
399                 // AppendAuthority end
400
401
402                 if (!__encodedPath.IsEmpty())
403                 {
404                         strbuf.Append(__encodedPath);
405                 }
406
407                 if (!__encodedQuery.IsEmpty())
408                 {
409                         strbuf.Append(L'?');
410                         strbuf.Append(__encodedQuery);
411                 }
412         }
413         // AppendSchemeSpecificPart end
414
415
416         //AppendFragment(strbuf, __encodedFragment);
417         if (!__encodedFragment.IsEmpty())
418         {
419                 strbuf.Append(L'#');
420                 strbuf.Append(__encodedFragment);
421         }
422         // AppendFragment end
423
424         return strbuf;
425 }
426
427
428 ////////////////////////////////////////////////////////////////////////////////////////////
429 // Operations
430
431 int
432 Uri::CompareTo(const Uri& uri) const
433 {
434         bool thisOpaque = false;
435         bool thatOpaque = false;
436
437         String query;
438         String otherQuery;
439         String path;
440         String otherPath;
441         String host;
442         String otherHost;
443         String fragment;
444         String otherFragment;
445         int ret = 0;
446
447         //////////////////////////////////////////////////
448         //                   Opaque                         //
449         /////////////////////////////////////////////////
450         thisOpaque = IsOpaque();
451         thatOpaque = uri.IsOpaque();
452
453         // Both the current instance and a given instance are opaque
454         if (thisOpaque && thatOpaque)
455         {
456                 // Compare Scheme-specific-part
457                 ret = Compare(__ssp, uri.__ssp);
458
459                 if (ret != 0)
460                 {
461                         return ret;
462                 }
463
464                 // compare fragment
465                 ret = Compare(__fragment, uri.__fragment);
466
467                 return ret;
468
469         }
470         else if (thisOpaque && !thatOpaque)
471         {
472                 return 1;
473         }
474         else if (!thisOpaque && thatOpaque)
475         {
476                 return -1;
477         }
478
479
480         //////////////////////////////////////////////////
481         //               Hierarchical                  //
482         /////////////////////////////////////////////////
483         if (!__host.IsEmpty() && !uri.__host.IsEmpty())
484         {
485                 // Server-based URI
486                 // Compare User-info
487                 ret = Compare(__userInfo, uri.__userInfo);
488
489                 if (ret != 0)
490                 {
491                         return ret;
492                 }
493
494                 // Compare host
495                 ret = Compare(__host, uri.__host);
496
497                 if (ret != 0)
498                 {
499                         return ret;
500                 }
501
502                 // Compare port
503                 int portDiff = __port - uri.__port;
504                 if (portDiff > 0)
505                 {
506                         return 1;
507                 }
508                 else if (portDiff == 0)
509                 {
510                         ret = 0;
511                 }
512                 else
513                 {
514                         return -1;
515                 }
516         }
517         else
518         {
519                 // If one of them is registry-based URI, then compare authority.
520                 ret = Compare(__authority, uri.__authority);
521
522                 if (ret != 0)
523                 {
524                         return ret;
525                 }
526         }
527
528         // Compare path
529         ret = Compare(__path, uri.__path);
530         if (ret != 0)
531         {
532                 return ret;
533         }
534
535         // Compare query
536         ret = Compare(__query, uri.__query);
537         if (ret != 0)
538         {
539                 return ret;
540         }
541
542         // Compare fragment
543         ret = Compare(__fragment, uri.__fragment);
544
545         return ret;
546 }
547
548
549 bool
550 Uri::Equals(const Tizen::Base::Object& obj) const
551 {
552         // Check that obj is an Uri instance.
553         const Uri* pOther = dynamic_cast <const Uri*>(&obj);
554         if (pOther == null)
555         {
556                 return false;
557         }
558
559         int ret = CompareTo(*pOther);
560         if (ret != 0)
561         {
562                 return false;
563         }
564
565         return true;
566 }
567
568
569 int
570 Uri::GetHashCode(void) const
571 {
572         return ToString().GetHashCode();
573 }
574
575
576 Uri
577 Uri::Normalize(void)
578 {
579         result r = E_SUCCESS;
580         Uri resultUri;
581
582         // If the current instance is opaque or the path of the current instance is undefined or an empty string,
583         // return itself.
584         if (__path.IsEmpty() || IsOpaque())
585         {
586                 return *this;
587         }
588
589         String normalizedUri;
590         normalizedUri = InternalNormalize(__path);
591         if (normalizedUri == __path || GetLastResult() == E_INVALID_ARG)
592         {
593                 return *this;
594         }
595
596         if (!__scheme.IsEmpty())
597         {
598                 r = resultUri.SetScheme(__scheme);
599                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set scheme.", GetErrorMessage(r));
600         }
601
602         if (!__fragment.IsEmpty())
603         {
604                 r = resultUri.SetFragment(__fragment);
605                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set fragment.", GetErrorMessage(r));
606         }
607
608         if (!__authority.IsEmpty())
609         {
610                 r = resultUri.SetAuthority(__authority);
611                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set authority.", GetErrorMessage(r));
612         }
613
614         if (!__userInfo.IsEmpty())
615         {
616                 r = resultUri.SetUserInfo(__userInfo);
617                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set userinfo.", GetErrorMessage(r));
618         }
619
620         if (!__host.IsEmpty())
621         {
622                 r = resultUri.SetHost(__host);
623                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set host.", GetErrorMessage(r));
624         }
625
626         resultUri.SetPort(__port);
627
628         r = resultUri.SetPath(normalizedUri);
629         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set path.", GetErrorMessage(r));
630
631         if (!__query.IsEmpty())
632         {
633                 r = resultUri.SetQuery(__query);
634                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set query.", GetErrorMessage(r));
635         }
636
637         return resultUri;
638 }
639
640
641 result
642 Uri::ParseAuthority(Uri& uri)
643 {
644         result r = E_SUCCESS;
645
646         if (!__host.IsEmpty() || __authority.IsEmpty())
647         {
648                 uri = *this;
649                 return r;
650         }
651
652         String str = ToString();
653
654         Uri tempUri;
655         r = tempUri.SetUri(str);
656
657         if (IsFailed(r))
658         {
659                 return r;
660         }
661
662         r = ParseServerAuthority(str, tempUri.__host, tempUri.__userInfo, tempUri.__port);
663         if (IsFailed(r))
664         {
665                 return r;
666         }
667
668         uri = tempUri;
669
670         return r;
671 }
672
673
674 result
675 Uri::Relativize(const Uri& uri, Uri& resultUri)
676 {
677         return Relativize(*this, uri, resultUri);
678 }
679
680
681 result
682 Uri::Resolve(const Uri& uri, Uri& resultUri)
683 {
684         return Resolve(*this, uri, resultUri);
685 }
686
687
688 result
689 Uri::SetAuthority(const Tizen::Base::String& authority)
690 {
691         bool isAuth = VerifyAuthority(authority);
692
693         SysTryReturn(NID_BASE_UTIL, isAuth, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Authority.", GetErrorMessage(E_INVALID_FORMAT));
694
695         if (IsEncoded(authority))
696         {
697                 __encodedAuth = authority;
698                 __authority = Decode(authority);
699         }
700         else
701         {
702                 __authority = authority;
703                 __encodedAuth = Encode(authority);
704         }
705
706         return E_SUCCESS;
707 }
708
709
710 result
711 Uri::SetFragment(const Tizen::Base::String& fragment)
712 {
713         bool isFragment = VerifyUriChar(fragment);
714
715         SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
716
717         if (IsEncoded(fragment))
718         {
719                 __encodedFragment = fragment;
720                 __fragment = Decode(fragment);
721         }
722         else
723         {
724                 __fragment = fragment;
725                 __encodedFragment = Encode(fragment);
726         }
727
728         return E_SUCCESS;
729 }
730
731
732 result
733 Uri::SetHost(const Tizen::Base::String& host)
734 {
735         bool isHost = VerifyHost(host);
736
737         SysTryReturn(NID_BASE_UTIL, isHost, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Host.", GetErrorMessage(E_INVALID_FORMAT));
738
739         __host = host;
740
741         return E_SUCCESS;
742 }
743
744
745 result
746 Uri::SetPath(const Tizen::Base::String& path)
747 {
748         bool isPath = VerifyPath(path);
749
750         SysTryReturn(NID_BASE_UTIL, isPath, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Path.", GetErrorMessage(E_INVALID_FORMAT));
751
752         if (IsEncoded(path))
753         {
754                 __encodedPath = path;
755                 __path = Decode(path);
756         }
757         else
758         {
759                 __path = path;
760                 __encodedPath = Encode(path);
761         }
762
763         return E_SUCCESS;
764 }
765
766
767 result
768 Uri::SetPort(int port)
769 {
770         SysTryReturn(NID_BASE_UTIL, port >= 0, E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used. The port(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), port);
771
772         __port = port;
773
774         return E_SUCCESS;
775 }
776
777
778 result
779 Uri::SetQuery(const Tizen::Base::String& query)
780 {
781         bool isQuery = VerifyUriChar(query);
782
783         SysTryReturn(NID_BASE_UTIL, isQuery, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Query.", GetErrorMessage(E_INVALID_FORMAT));
784
785         if (IsEncoded(query))
786         {
787                 __encodedQuery = query;
788                 __query = Decode(query);
789         }
790         else
791         {
792                 __query = query;
793                 __encodedQuery = Encode(query);
794         }
795
796         return E_SUCCESS;
797 }
798
799
800 result
801 Uri::SetScheme(const Tizen::Base::String& scheme)
802 {
803         bool isScheme = VerifyScheme(scheme);
804
805         SysTryReturn(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
806
807         __scheme = scheme;
808
809         return E_SUCCESS;
810 }
811
812
813 result
814 Uri::SetSchemeSpecificPart(const Tizen::Base::String& ssp)
815 {
816         bool isSsp = VerifyUriChar(ssp);
817
818         SysTryReturn(NID_BASE_UTIL, isSsp, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid SchemeSpecificPart.", GetErrorMessage(E_INVALID_FORMAT));
819
820         if (IsEncoded(ssp))
821         {
822                 __encodedSsp = ssp;
823                 __ssp = Decode(ssp);
824         }
825         else
826         {
827                 __ssp = ssp;
828                 __encodedSsp = Encode(ssp);
829         }
830
831         return E_SUCCESS;
832 }
833
834
835 result
836 Uri::SetUserInfo(const Tizen::Base::String& userInfo)
837 {
838         bool isUserInfo = VerifyUserInfo(userInfo);
839
840         SysTryReturn(NID_BASE_UTIL, isUserInfo, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid UserInfo.", GetErrorMessage(E_INVALID_FORMAT));
841
842         if (IsEncoded(userInfo))
843         {
844                 __encodedUserInfo = userInfo;
845                 __userInfo = Decode(userInfo);
846         }
847         else
848         {
849                 __userInfo = userInfo;
850                 __encodedUserInfo = Encode(userInfo);
851         }
852
853         return E_SUCCESS;
854 }
855
856
857 Tizen::Base::String
858 Uri::ToString(void) const
859 {
860         String strbuf;
861
862         // Scheme
863         if (!__scheme.IsEmpty())
864         {
865                 strbuf.Append(__scheme);
866                 strbuf.Append(L':');
867         }
868
869         //AppendSchemeSpecificPart(strbuf, __ssp, __authority, __userInfo, __host, __port, __path, __query);
870         if (IsOpaque())
871         {
872                 strbuf.Append(__ssp);
873         }
874         else
875         {
876                 //r = AppendAuthority(strbuf, __authority, __userInfo, __host, __port);
877                 if (!__host.IsEmpty())
878                 {
879                         // Check the Host
880                         strbuf.Append(L"//");
881
882                         // Check the Userinfo
883                         if (!__userInfo.IsEmpty())
884                         {
885                                 strbuf.Append(__userInfo);
886                                 strbuf.Append(L'@');
887                         }
888
889                         int indexOf = 0;
890                         result re = E_SUCCESS;
891                         re = __host.IndexOf(L':', 0, indexOf);
892
893                         String openBracket(L"[");
894                         String closeBracket(L"]");
895
896                         bool start = __host.StartsWith(openBracket, 0);
897                         bool end = __host.EndsWith(closeBracket);
898
899                         bool needBracket = false;
900                         if (!start && !end && re == E_SUCCESS)
901                         {
902                                 needBracket = true;
903                         }
904                         else
905                         {
906                                 needBracket = false;
907                         }
908
909                         if (needBracket)
910                         {
911                                 strbuf.Append(L'[');
912                         }
913
914                         strbuf.Append(__host);
915
916                         if (needBracket)
917                         {
918                                 strbuf.Append(L']');
919                         }
920
921                         // Check the port
922                         if (__port >= 0)
923                         {
924                                 strbuf.Append(L':');
925                                 strbuf.Append(__port);
926                         }
927                 }
928                 else if (!__authority.IsEmpty())
929                 {
930                         strbuf.Append(L"//");
931                         strbuf.Append(__authority);
932                 }
933                 // AppendAuthority end
934
935
936                 if (!__path.IsEmpty())
937                 {
938                         strbuf.Append(__path);
939                 }
940
941                 if (!__query.IsEmpty())
942                 {
943                         strbuf.Append(L'?');
944                         strbuf.Append(__query);
945                 }
946         }
947         // AppendSchemeSpecificPart end
948
949
950         //AppendFragment(strbuf, __fragment);
951         if (!__fragment.IsEmpty())
952         {
953                 strbuf.Append(L'#');
954                 strbuf.Append(__fragment);
955         }
956         // AppendFragment end
957
958         return strbuf;
959 }
960
961
962 ////////////////////////////////////////////////////////////////////////
963 // Private methods
964
965 //
966 // This method constructs an URI instance.
967 //
968 result
969 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& opaque, const Tizen::Base::String& authority,
970                         const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port, const Tizen::Base::String& path,
971                         const Tizen::Base::String& query,
972                         const Tizen::Base::String& fragment)
973 {
974         result r = E_SUCCESS;
975         String fullUri;
976         String strbuf;
977
978         // Scheme
979         if (!scheme.IsEmpty())
980         {
981                 // Check that an extracted scheme is satisfied with RFC2396.
982                 bool isScheme = VerifyScheme(scheme);
983                 if (!isScheme)
984                 {
985                         r = E_INVALID_FORMAT;
986                         goto CATCH;
987                 }
988
989                 r = strbuf.Append(scheme);
990                 if (IsFailed(r))
991                 {
992                         goto CATCH;
993                 }
994
995                 r = strbuf.Append(L':');
996                 if (IsFailed(r))
997                 {
998                         goto CATCH;
999                 }
1000         }
1001
1002         r = AppendSchemeSpecificPart(strbuf, opaque, authority, userInfo, host, port, path, query);
1003         if (IsFailed(r))
1004         {
1005                 goto CATCH;
1006         }
1007
1008         r = AppendFragment(strbuf, fragment);
1009         if (IsFailed(r))
1010         {
1011                 goto CATCH;
1012         }
1013
1014         fullUri = strbuf;
1015
1016         r = SetUri(fullUri);
1017         if (IsFailed(r))
1018         {
1019                 goto CATCH;
1020         }
1021
1022 CATCH:
1023         return r;
1024 }
1025
1026
1027 result
1028 Uri::AppendSchemeSpecificPart(Tizen::Base::String& strbuf, const Tizen::Base::String& opaque, const Tizen::Base::String& authority,
1029                                                           const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port,
1030                                                           const Tizen::Base::String& path,
1031                                                           const Tizen::Base::String& query) const
1032 {
1033         result r = E_SUCCESS;
1034         // Opaque part
1035         if (!opaque.IsEmpty())
1036         {
1037                 if (VerifyUriChar(opaque))
1038                 {
1039                         r = strbuf.Append(opaque);
1040                         if (IsFailed(r))
1041                         {
1042                                 goto CATCH;
1043                         }
1044                 }
1045                 else
1046                 {
1047                         r = E_INVALID_FORMAT;
1048                         goto CATCH;
1049                 }
1050         }
1051         else
1052         {
1053                 r = AppendAuthority(strbuf, authority, userInfo, host, port);
1054                 if (IsFailed(r))
1055                 {
1056                         goto CATCH;
1057                 }
1058
1059                 if (!path.IsEmpty())
1060                 {
1061                         if (VerifyPath(path))
1062                         {
1063                                 r = strbuf.Append(path);
1064                         }
1065                         else
1066                         {
1067                                 r = E_INVALID_FORMAT;
1068                                 goto CATCH;
1069                         }
1070                 }
1071
1072                 if (!query.IsEmpty())
1073                 {
1074                         if (VerifyUriChar(query))
1075                         {
1076                                 r = strbuf.Append(L'?');
1077                                 if (IsFailed(r))
1078                                 {
1079                                         goto CATCH;
1080                                 }
1081
1082                                 r = strbuf.Append(query);
1083                                 if (IsFailed(r))
1084                                 {
1085                                         goto CATCH;
1086                                 }
1087                         }
1088                         else
1089                         {
1090                                 r = E_INVALID_FORMAT;
1091                                 goto CATCH;
1092                         }
1093                 }
1094         }
1095
1096 CATCH:
1097         return r;
1098 }
1099
1100
1101 result
1102 Uri::AppendFragment(Tizen::Base::String& strbuf, const Tizen::Base::String& fragment) const
1103 {
1104         result r = E_SUCCESS;
1105         if (!fragment.IsEmpty())
1106         {
1107                 bool isFragment = VerifyUriChar(fragment);
1108                 if (isFragment)
1109                 {
1110                         r = strbuf.Append(L'#');
1111                         if (IsFailed(r))
1112                         {
1113                                 goto CATCH;
1114                         }
1115
1116                         r = strbuf.Append(fragment);
1117                         if (IsFailed(r))
1118                         {
1119                                 goto CATCH;
1120                         }
1121                 }
1122                 else
1123                 {
1124                         r = E_INVALID_FORMAT;
1125                         goto CATCH;
1126                 }
1127         }
1128
1129 CATCH:
1130         return r;
1131 }
1132
1133
1134 result
1135 Uri::AppendAuthority(Tizen::Base::String& strbuf, const Tizen::Base::String& authority, const Tizen::Base::String& userInfo,
1136                                          const Tizen::Base::String& host,
1137                                          int port) const
1138 {
1139         result r = E_SUCCESS;
1140
1141         String doubleSlash(L"//");
1142
1143         if (!host.IsEmpty())
1144         {
1145                 // Check the Host
1146                 bool isHost = VerifyHost(host);
1147                 if (!isHost)
1148                 {
1149                         r = E_INVALID_FORMAT;
1150                         goto CATCH;
1151                 }
1152
1153                 r = strbuf.Append(doubleSlash);
1154                 if (IsFailed(r))
1155                 {
1156                         goto CATCH;
1157                 }
1158
1159                 // Check the Userinfo
1160                 if (!userInfo.IsEmpty())
1161                 {
1162                         bool user = VerifyUserInfo(userInfo);
1163                         if (user)
1164                         {
1165                                 r = strbuf.Append(userInfo);
1166                                 if (IsFailed(r))
1167                                 {
1168                                         goto CATCH;
1169                                 }
1170
1171                                 r = strbuf.Append(L'@');
1172                                 if (IsFailed(r))
1173                                 {
1174                                         goto CATCH;
1175                                 }
1176                         }
1177                         else
1178                         {
1179                                 r = E_INVALID_FORMAT;
1180                                 goto CATCH;
1181                         }
1182                 }
1183
1184                 int indexOf = 0;
1185                 result re = E_SUCCESS;
1186                 re = host.IndexOf(L':', 0, indexOf);
1187                 //if (IsFailed(r)) goto CATCH;
1188
1189                 String openBracket(L"[");
1190                 String closeBracket(L"]");
1191
1192                 bool start = host.StartsWith(openBracket, 0);
1193                 bool end = host.EndsWith(closeBracket);
1194
1195                 bool needBracket = true;
1196                 if (!start && !end && re == E_SUCCESS)
1197                 {
1198                         needBracket = true;
1199                 }
1200                 else
1201                 {
1202                         needBracket = false;
1203                 }
1204
1205                 if (needBracket)
1206                 {
1207                         r = strbuf.Append(L'[');
1208                         if (IsFailed(r))
1209                         {
1210                                 goto CATCH;
1211                         }
1212                 }
1213
1214                 r = strbuf.Append(host);
1215                 if (IsFailed(r))
1216                 {
1217                         goto CATCH;
1218                 }
1219
1220                 if (needBracket)
1221                 {
1222                         r = strbuf.Append(L']');
1223                         if (IsFailed(r))
1224                         {
1225                                 goto CATCH;
1226                         }
1227                 }
1228
1229                 // Check the port
1230                 if (port >= 0)
1231                 {
1232                         r = strbuf.Append(L':');
1233                         if (IsFailed(r))
1234                         {
1235                                 goto CATCH;
1236                         }
1237
1238                         r = strbuf.Append(port);
1239                         if (IsFailed(r))
1240                         {
1241                                 goto CATCH;
1242                         }
1243                 }
1244                 else
1245                 {
1246                         if (port != -1)
1247                         {
1248                                 r = E_INVALID_FORMAT;
1249                                 goto CATCH;
1250                         }
1251                 }
1252         }
1253         else if (!authority.IsEmpty())
1254         {
1255                 r = strbuf.Append(doubleSlash);
1256                 if (IsFailed(r))
1257                 {
1258                         goto CATCH;
1259                 }
1260
1261                 bool auth = VerifyAuthority(authority);
1262                 if (auth)
1263                 {
1264                         r = strbuf.Append(authority);
1265                         if (IsFailed(r))
1266                         {
1267                                 goto CATCH;
1268                         }
1269                 }
1270                 else
1271                 {
1272                         r = E_INVALID_FORMAT;
1273                         goto CATCH;
1274                 }
1275         }
1276
1277 CATCH:
1278         return r;
1279 }
1280
1281
1282 //
1283 // This method breaks a given string into Uri components.
1284 // str : [scheme:]<scheme-specific-part>[#<fragment>]
1285 //
1286 result
1287 Uri::ParseUri(const Tizen::Base::String& str)
1288 {
1289         result r = E_SUCCESS;
1290         wchar_t colon = L':';
1291         wchar_t sharp = L'#';
1292         int indexOf = 0;
1293         int startSsp = 0;
1294         int curIndex = 0; // points the current index
1295         int startFragment = 0;
1296         int lengthOfUri = str.GetLength();
1297
1298         String authority;
1299         String path;
1300         String query;
1301
1302         /////////////////////////////////////////////////////////////////
1303         // First, exract a scheme component from a given string.//
1304         ////////////////////////////////////////////////////////////////
1305
1306         // Check the space
1307         SysTryReturn(NID_BASE_UTIL, str[0] != L' ', E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
1308
1309         // Get a index of ':'
1310         r = str.IndexOf(colon, 0, indexOf);
1311         if (indexOf >= 0 && r == E_SUCCESS)
1312         {
1313                 // There is a scheme componenet.
1314                 String scheme;
1315                 r = str.SubString(0, indexOf, scheme);
1316                 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1317
1318                 // Check that an extracted scheme is satisfied with RFC2396.
1319                 bool isScheme = VerifyScheme(scheme);
1320
1321                 SysTryReturn(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
1322
1323                 curIndex = indexOf;
1324                 __scheme = scheme;
1325                 __hasScheme = true;
1326         }
1327         else
1328         {
1329                 // In case there is no scheme component, the Uri is a hierarchical URI.
1330                 startSsp = 0;
1331                 __hasScheme = false;
1332         }
1333
1334         ////////////////////////////////////////////////////////////////////////
1335         // Second, extract a scheme-specific-part from a given string.//
1336         ///////////////////////////////////////////////////////////////////////
1337         if (__hasScheme) // This URI has a scheme.
1338         {
1339                 startSsp = ++curIndex; // skip ':'
1340                 if (startSsp >= lengthOfUri)
1341                 {
1342                         r = E_INVALID_FORMAT;
1343                         goto CATCH;
1344                 }
1345
1346                 if (str[startSsp] == '/')
1347                 {
1348                         // Hierarchical URI
1349                         r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1350                         if (IsFailed(r))
1351                         {
1352                                 goto CATCH;
1353                         }
1354
1355                         SetAndEncodeAuthority(authority, path, query);
1356
1357                         String ssp;
1358                         r = str.SubString(startSsp, curIndex - startSsp, ssp);
1359                         if (IsFailed(r))
1360                         {
1361                                 goto CATCH;
1362                         }
1363
1364                         if (IsEncoded(ssp))
1365                         {
1366                                 __ssp = Decode(ssp);
1367                                 __encodedSsp = ssp;
1368                         }
1369                         else
1370                         {
1371                                 __ssp = ssp;
1372                                 __encodedSsp = Encode(ssp);
1373                         }
1374
1375                 }
1376                 else
1377                 {
1378                         // Opaque URI
1379                         String ssp;
1380
1381                         r = str.IndexOf(sharp, curIndex, (int&)startFragment);
1382                         if (startFragment > curIndex && r == E_SUCCESS)
1383                         {
1384                                 r = str.SubString(startSsp, startFragment - curIndex, ssp);
1385                                 if (IsFailed(r))
1386                                 {
1387                                         goto CATCH;
1388                                 }
1389                         }
1390                         else if (r == E_OBJ_NOT_FOUND)
1391                         {
1392                                 startFragment = 0;
1393                                 r = str.SubString(startSsp, lengthOfUri - curIndex, ssp);
1394                                 if (IsFailed(r))
1395                                 {
1396                                         goto CATCH;
1397                                 }
1398                         }
1399                         else
1400                         {
1401                                 goto CATCH;
1402                         }
1403
1404                         bool isOpaque = VerifyUriChar(ssp);
1405
1406                         SysTryReturn(NID_BASE_UTIL, isOpaque, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Opaque URI.", GetErrorMessage(E_INVALID_FORMAT));
1407
1408                         // Opaque URI is not subject to further parsing.
1409                         if (IsEncoded(ssp))
1410                         {
1411                                 __ssp = Decode(ssp);
1412                                 __encodedSsp = ssp;
1413                         }
1414                         else
1415                         {
1416                                 __ssp = ssp;
1417                                 __encodedSsp = Encode(ssp);
1418                         }
1419
1420                         if (startFragment == 0)
1421                         {
1422                                 return E_SUCCESS;
1423                         }
1424
1425                         // Check the fragment
1426                         String fragment;
1427
1428                         startFragment++;
1429                         r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1430                         if (IsFailed(r))
1431                         {
1432                                 goto CATCH;
1433                         }
1434
1435                         bool isFragment = VerifyUriChar(fragment);
1436
1437                         SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
1438
1439                         if (IsEncoded(fragment))
1440                         {
1441                                 __fragment = Decode(fragment);
1442                                 __encodedFragment = fragment;
1443                         }
1444                         else
1445                         {
1446                                 __fragment = fragment;
1447                                 __encodedFragment = Encode(fragment);
1448                         }
1449
1450                         return E_SUCCESS;
1451                 }
1452         }
1453         else // This URI doesn't have a Scheme. - www.samsung.com[#ocean]
1454         {
1455                 startSsp = 0;
1456
1457                 r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1458                 if (IsFailed(r))
1459                 {
1460                         goto CATCH;
1461                 }
1462
1463                 String ssp;
1464                 r = str.SubString(startSsp, curIndex - startSsp, ssp);
1465                 if (IsFailed(r))
1466                 {
1467                         goto CATCH;
1468                 }
1469
1470                 if (IsEncoded(ssp))
1471                 {
1472                         __ssp = Decode(ssp);
1473                         __encodedSsp = ssp;
1474                 }
1475                 else
1476                 {
1477                         __ssp = ssp;
1478                         __encodedSsp = Encode(ssp);
1479                 }
1480
1481                 SetAndEncodeAuthority(authority, path, query);
1482         }
1483
1484         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1485         // Parse an authority component. The authority component is registry_based or server_based authority.//
1486         // Server_based authority consists of user-info, host and port.                                                                                                           //
1487         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1488         if (!authority.IsEmpty())
1489         {
1490                 String userInfo;
1491                 String host;
1492                 int port = 0;
1493
1494                 String newAuth;
1495                 r = ParseAuthority(authority, curIndex, newAuth, userInfo, host, port);
1496                 if (IsFailed(r))
1497                 {
1498                         goto CATCH;
1499                 }
1500
1501                 if (!userInfo.IsEmpty())
1502                 {
1503                         if (IsEncoded(userInfo))
1504                         {
1505                                 __userInfo = Decode(userInfo);
1506                                 __encodedUserInfo = userInfo;
1507                         }
1508                         else
1509                         {
1510                                 __userInfo = userInfo;
1511                                 __encodedUserInfo = Encode(userInfo);
1512                         }
1513                 }
1514
1515                 if (!host.IsEmpty())
1516                 {
1517                         __host = host;
1518                 }
1519
1520                 __port = port;
1521         }
1522
1523         /////////////////////////////////////////////////
1524         // Finally, extract a fragment component //
1525         ////////////////////////////////////////////////
1526         startFragment = curIndex;
1527         if (startFragment < lengthOfUri && str[startFragment] == '#')
1528         {
1529                 startFragment++;
1530                 String fragment;
1531
1532                 r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1533                 if (IsFailed(r))
1534                 {
1535                         goto CATCH;
1536                 }
1537
1538                 bool isFragment = VerifyUriChar(fragment);
1539
1540                 SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
1541
1542                 if (IsEncoded(fragment))
1543                 {
1544                         __fragment = Decode(fragment);
1545                         __encodedFragment = fragment;
1546                 }
1547                 else
1548                 {
1549                         __fragment = fragment;
1550                         __encodedFragment = Encode(fragment);
1551                 }
1552
1553                 // curIndex = lengthOfUri;
1554                 curIndex += fragment.GetLength() + 1; // skip '#'
1555         }
1556
1557         if (curIndex < lengthOfUri)
1558         {
1559                 // Invalid URI format
1560                 r = E_INVALID_FORMAT;
1561                 goto CATCH;
1562         }
1563
1564         // Convert Unicode string to UTF8 string when there is a wchar_t which is greater than 0x0080.
1565         // authority fragment path query ssp
1566         //EncodeAllComponent();
1567 CATCH:
1568         return r;
1569 }
1570
1571
1572 void
1573 Uri::SetAndEncodeAuthority(const Tizen::Base::String& authority, const Tizen::Base::String& path, const Tizen::Base::String& query)
1574 {
1575         bool isEncoded = false;
1576
1577         //// Authority ////
1578         if (!authority.IsEmpty())
1579         {
1580                 isEncoded = IsEncoded(authority);
1581                 if (isEncoded)
1582                 {
1583                         __authority = Decode(authority);
1584                         __encodedAuth = authority;
1585                 }
1586                 else
1587                 {
1588                         __authority = authority;
1589                         __encodedAuth = Encode(authority);
1590                 }
1591         }
1592
1593         //// Path ////
1594         if (!path.IsEmpty())
1595         {
1596                 isEncoded = IsEncoded(path);
1597                 if (isEncoded)
1598                 {
1599                         __path = Decode(path);
1600                         __encodedPath = path;
1601                 }
1602                 else
1603                 {
1604                         __path = path;
1605                         __encodedPath = Encode(path);
1606                 }
1607         }
1608
1609         //// Query ////
1610         if (!query.IsEmpty())
1611         {
1612                 isEncoded = IsEncoded(query);
1613                 if (isEncoded)
1614                 {
1615                         __query = Decode(query);
1616                         __encodedQuery = query;
1617                 }
1618                 else
1619                 {
1620                         __query = query;
1621                         __encodedQuery = Encode(query);
1622                 }
1623         }
1624 }
1625
1626
1627 result
1628 Uri::ParseHierarchicalUri(const Tizen::Base::String& str, int startSsp, Tizen::Base::String& authority, Tizen::Base::String& path,
1629                                                   Tizen::Base::String& query,
1630                                                   int& index)
1631 {
1632         result r = E_SUCCESS;
1633         int curIndex = startSsp;
1634 //      bool isServerAuth;
1635
1636         String tempPath;
1637         String queSharp(L"?#");
1638         String doubleSlash(L"//");
1639
1640         bool startsWith = str.StartsWith(doubleSlash, curIndex);
1641
1642         int position = 0;
1643         bool isPath = false;
1644         int temp = 0;
1645
1646         if (startsWith)
1647         {
1648                 curIndex += 2;
1649 //              int indexOf;
1650
1651                 String special(L"/?#");
1652
1653                 int index = Scan(str, curIndex, special);
1654                 if (index > (int) curIndex)
1655                 {
1656                         r = str.SubString(curIndex, index - curIndex, authority);
1657                         if (IsFailed(r))
1658                         {
1659                                 goto CATCH;
1660                         }
1661
1662                         //bool isServer;
1663                         //r = ParseAuthority(str, curIndex, isServer);
1664                         //if (IsFailed(r)) goto CATCH;
1665                 }
1666                 else if (index < (int) str.GetLength())
1667                 {
1668                         // allow an empty authority
1669 //                      authority = String::Empty();
1670                         // empty statement
1671                 }
1672                 else
1673                 {
1674                         r = E_INVALID_FORMAT;
1675                         goto CATCH;
1676                 }
1677                 curIndex += authority.GetLength();
1678         }
1679
1680         r = queSharp.IndexOf(str[0], 0, temp);
1681         if (r == E_SUCCESS)
1682         {
1683                 position = 0;
1684         }
1685         else
1686         {
1687                 position = Scan(str, curIndex, queSharp); // may be empty
1688                 if (position < 0)
1689                 {
1690                         r = E_INVALID_FORMAT;
1691                         goto CATCH;
1692                 }
1693
1694                 if (position == curIndex)
1695                 {
1696                         // There is no path and query
1697                         r = E_SUCCESS;
1698                         goto CATCH;
1699                 }
1700
1701         }
1702
1703         r = str.SubString(curIndex, position - curIndex, tempPath);
1704         if (IsFailed(r))
1705         {
1706                 goto CATCH;
1707         }
1708
1709         isPath = VerifyPath(tempPath);
1710         SysTryReturn(NID_BASE_UTIL, isPath, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Path.", GetErrorMessage(E_INVALID_FORMAT));
1711
1712         path = tempPath;
1713
1714         curIndex = position;
1715
1716         if (curIndex < str.GetLength() && str[curIndex] == L'?')
1717         {
1718                 String tempQuery;
1719
1720                 curIndex++;
1721                 int indexOf = 0;
1722                 r = str.IndexOf(L'#', curIndex, indexOf);
1723                 if (r == E_SUCCESS)
1724                 {
1725                         r = str.SubString(curIndex, indexOf - curIndex, tempQuery);
1726                         if (IsFailed(r))
1727                         {
1728                                 goto CATCH;
1729                         }
1730                 }
1731                 else if (r == E_OBJ_NOT_FOUND)
1732                 {
1733                         r = str.SubString(curIndex, tempQuery);
1734                         if (IsFailed(r))
1735                         {
1736                                 goto CATCH;
1737                         }
1738                 }
1739                 else
1740                 {
1741                         goto CATCH;
1742                 }
1743
1744                 bool isQuery = VerifyUriChar(tempQuery);
1745                 if (isQuery)
1746                 {
1747                         query = tempQuery;
1748                 }
1749                 curIndex += query.GetLength();
1750         }
1751
1752 CATCH:
1753         index = curIndex;
1754         return r;
1755 }
1756
1757
1758 //
1759 // This method parses an authority component.
1760 // This component is server based or registrty authority.
1761 //
1762 result
1763 Uri::ParseAuthority(const Tizen::Base::String& str, int curIndex, Tizen::Base::String& newAuth, Tizen::Base::String& userInfo,
1764                                         Tizen::Base::String& host,
1765                                         int& port)
1766 {
1767         result r = E_SUCCESS;
1768
1769         bool isServerChar = VerifyServerAuthority(str);
1770         bool isRegChar = VerifyRegistryAuthority(str);
1771
1772         if (isRegChar && !isServerChar)
1773         {
1774                 newAuth = str;
1775                 return E_SUCCESS;
1776         }
1777
1778         if (isServerChar)
1779         {
1780                 r = ParseServerAuthority(str, userInfo, host, port);
1781                 if (IsFailed(r))
1782                 {
1783                         return r;
1784                 }
1785
1786                 newAuth = str;
1787         }
1788
1789         if (isRegChar)
1790         {
1791                 newAuth = str;
1792         }
1793
1794         return E_SUCCESS;
1795 }
1796
1797
1798 //
1799 // This method parses a server_based authority componenet.
1800 // server_based authority : [user-info@]<host>[:port]
1801 //
1802 result
1803 Uri::ParseServerAuthority(const Tizen::Base::String& str, Tizen::Base::String& user, Tizen::Base::String& host, int& port)
1804 {
1805         result r = E_SUCCESS;
1806         int indexOf = 0;
1807         int index = 0;
1808         String userInfo;
1809
1810         // User-info
1811         r = str.IndexOf(L'@', 0, indexOf);
1812         if (r == E_SUCCESS)
1813         {
1814                 r = str.SubString(0, indexOf, userInfo);
1815                 if (IsFailed(r))
1816                 {
1817                         goto CATCH;
1818                 }
1819
1820                 bool isUser = VerifyUserInfo(userInfo);
1821
1822                 SysTryReturn(NID_BASE_UTIL, isUser, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid UserInfo.", GetErrorMessage(E_INVALID_FORMAT));
1823
1824                 user = userInfo;
1825
1826                 index += indexOf + 1; // skip '@'
1827         }
1828
1829         // IPv4 or IPv6 address
1830         if (str[0] == L'[')
1831         {
1832                 // IPv6 not supported
1833                 return E_INVALID_FORMAT;
1834 #if 0
1835                 // IPv6 address
1836                 index++;
1837
1838                 if (str[str.GetLength() - 1] == L']')
1839                 {
1840                         String ip6;
1841                         String outIpv6;
1842
1843                         r = str.SubString(1, str.GetLength() - 2, ip6);
1844                         if (IsFailed(r))
1845                         {
1846                                 goto CATCH;
1847                         }
1848
1849                         // TODO : Parsing IPv6 is not implemented.
1850                         r = ParseIPv6(ip6, outIpv6);
1851                         if (IsFailed(r))
1852                         {
1853                                 goto CATCH;
1854                         }
1855
1856                         // TODO : Because IPv6 is hardly used, a member variable for IPv6 stores it directly.
1857                         __ipv6 = outIpv6;
1858
1859                         index += str.GetLength();
1860                 }
1861                 else
1862                 {
1863                         r = E_INVALID_FORMAT; // This component has no closing bracket although it is a IPv6 address.
1864                         goto CATCH;
1865                 }
1866 #endif
1867         }
1868         else
1869         {
1870                 String ip4;
1871                 int count = 0;
1872
1873                 r = ParseIpv4(str, index, count); // length of ipv4 string
1874                 if (IsFailed(r))
1875                 {
1876                         goto CATCH;
1877                 }
1878
1879                 if (count >= 0)
1880                 {
1881                         r = str.SubString(0, count, ip4);
1882                         if (IsFailed(r))
1883                         {
1884                                 goto CATCH;
1885                         }
1886
1887                         host = ip4;
1888                 }
1889                 else if (count < 0)
1890                 {
1891                         // This is a host name
1892                         String tmpHost;
1893
1894                         r = ParseHostName(str, index, tmpHost);
1895                         if (IsFailed(r))
1896                         {
1897                                 return r;
1898                         }
1899
1900                         host = tmpHost;
1901                 }
1902         }
1903
1904         // Port
1905         if (host.IsEmpty())
1906         {
1907                 port = -1;
1908                 return E_SUCCESS;
1909         }
1910
1911         index += host.GetLength();
1912         if (index < str.GetLength() && str[index] == L':')
1913         {
1914                 String tmpPort;
1915
1916                 index++;
1917                 r = str.IndexOf(L'/', index, indexOf);
1918                 if (r == E_SUCCESS)
1919                 {
1920                         r = str.SubString(index, indexOf - index, tmpPort);
1921                         if (IsFailed(r))
1922                         {
1923                                 goto CATCH;
1924                         }
1925                 }
1926                 else if (r == E_OBJ_NOT_FOUND)
1927                 {
1928                         r = str.SubString(index, tmpPort);
1929                         if (IsFailed(r))
1930                         {
1931                                 goto CATCH;
1932                         }
1933                 }
1934
1935                 int tmpPortLen = tmpPort.GetLength();
1936                 for (int i = 0; i < tmpPortLen; i++)
1937                 {
1938                         wchar_t ch = tmpPort[i];
1939                         if (!(Character::IsDigit(ch)))
1940                         {
1941                                 r = E_INVALID_FORMAT;
1942                                 goto CATCH;
1943                         }
1944                 }
1945                 index += tmpPort.GetLength();
1946
1947                 int ret = 0;
1948                 r = Integer::Parse(tmpPort, 10, ret);
1949                 port = ret;
1950         }
1951         else
1952         {
1953                 port = -1;
1954         }
1955
1956         if (index < (int) str.GetLength())
1957         {
1958                 r = E_INVALID_FORMAT;
1959                 goto CATCH;
1960         }
1961
1962         return E_SUCCESS;
1963
1964 CATCH:
1965         return r;
1966 }
1967
1968
1969 //
1970 // This method parses a host name and returns a host name as an out-param.
1971 //
1972 result
1973 Uri::ParseHostName(const Tizen::Base::String& str, int index, Tizen::Base::String& host)
1974 {
1975         result r = E_SUCCESS;
1976         int indexOf = 0;
1977         bool isHost = false;
1978
1979         int strLen = str.GetLength();
1980         r = str.IndexOf(L':', index, indexOf);
1981         if (r == E_SUCCESS)
1982         {
1983                 r = str.SubString(index, indexOf - index, host);
1984                 if (IsFailed(r))
1985                 {
1986                         goto CATCH;
1987                 }
1988         }
1989         else if (r == E_OBJ_NOT_FOUND)
1990         {
1991                 //host = str;
1992                 r = str.SubString(index, host);
1993                 if (IsFailed(r))
1994                 {
1995                         goto CATCH;
1996                 }
1997         }
1998
1999         for (int i = 0; i < strLen; i++)
2000         {
2001                 if (str[i] == L'%')
2002                 {
2003                         wchar_t ch1 = str[i + 1];
2004                         wchar_t ch2 = str[i + 2];
2005                         bool escape = IsEscapedChar(ch1, ch2);
2006                         if (!escape)
2007                         {
2008                                 break;
2009                         }
2010
2011                         host = L"";
2012                         return E_SUCCESS;
2013                 }
2014         }
2015
2016         isHost = VerifyHost(host);
2017
2018         SysTryReturn(NID_BASE_UTIL, isHost, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Host.", GetErrorMessage(E_INVALID_FORMAT));
2019
2020 CATCH:
2021         return r;
2022 }
2023
2024
2025 //
2026 // This method parses an IPv6 address.
2027 // This method covers all and only the following cases :
2028 //              hex_seq
2029 //              hex_seq : IPv4 address
2030 //              hex_seq ::
2031 //              hex_seq :: hex_seq
2032 //              hex_seq :: hex_seq : IPv4 address
2033 //              :: hex_seq
2034 //              :: hex_seq : IPv4 address
2035 //              ::
2036 //
2037 // Additionally, we constrain the IPv6 address as follows :
2038 //              1) IPv6 address without compressed zeros should contain exactly 16 bytes.
2039 //              2) IPv6 address with comporessed zeros should contain less than 16 bytes.
2040 //
2041 result
2042 Uri::ParseIpv6(const Tizen::Base::String& ip6, Tizen::Base::String& outIpv6)
2043 {
2044         // TODO : It will be implemented
2045         return E_SUCCESS;
2046 }
2047
2048
2049 result
2050 Uri::ParseIpv4(const Tizen::Base::String& str, int start, int& count)
2051 {
2052         result r = E_SUCCESS;
2053         String dot(L".");
2054         String ipHost;
2055
2056         r = str.SubString(start, ipHost);
2057         if (IsFailed(r))
2058         {
2059                 return r;
2060         }
2061
2062         // Set the index as an end position of ipv4
2063         count = ipHost.GetLength();
2064
2065         StringTokenizer strTok(ipHost, dot);
2066
2067         // Check that a given string consists of digit or dot.
2068         int ipHostLen = ipHost.GetLength();
2069         for (int i = 0; i < ipHostLen; i++)
2070         {
2071                 wchar_t ch = ipHost[i];
2072                 if (ch != L'.' && !(Character::IsDigit(ch)))
2073                 {
2074                         count = -1;
2075                         //r = E_INVALID_FORMAT;
2076                         goto CATCH;
2077                 }
2078         }
2079
2080         while (strTok.HasMoreTokens() == true)
2081         {
2082                 String token;
2083
2084                 r = strTok.GetNextToken(token);
2085                 if (IsFailed(r))
2086                 {
2087                         goto CATCH;
2088                 }
2089
2090                 int ret = 0;
2091                 r = Integer::Parse(token, 10, ret);
2092                 if (IsFailed(r))
2093                 {
2094                         goto CATCH;
2095                 }
2096
2097                 // each part of IPv4 address cannot exceed 255.
2098                 if (ret < 0 || ret > 255)
2099                 {
2100                         r = E_INVALID_FORMAT;
2101                         goto CATCH;
2102                 }
2103         }
2104
2105         return E_SUCCESS;
2106
2107 CATCH:
2108         return r;
2109 }
2110
2111
2112 //////////////////////////////////////////////////////////////////////////////////////////
2113 // Verify a component
2114
2115 //
2116 // This method verifies whether a given string is scheme format or not.
2117 // The scheme has an combination of alphabet, digit, plus(+), dash(-) and period(.).
2118 // The first character must be an alphabet.
2119 //
2120 bool
2121 Uri::VerifyScheme(const Tizen::Base::String& str) const
2122 {
2123         bool isAlpha = Character::IsLetter(str[0]);
2124         if (!isAlpha)
2125         {
2126                 return false;
2127         }
2128
2129         int strLen = str.GetLength();
2130         for (int i = 1; i < strLen; i++)
2131         {
2132                 if ((str[i] != '+') && (str[i] != '-') && (str[i] != '.') && (!Character::IsAlphaNumeric(str[i])) &&
2133                         (!Character::IsDigit(str[i])))
2134                 {
2135                         return false;
2136                 }
2137         }
2138
2139         return true;
2140 }
2141
2142
2143 bool
2144 Uri::VerifyAuthority(const Tizen::Base::String& str) const
2145 {
2146         bool isReg = VerifyRegistryAuthority(str);
2147         bool isServer = VerifyServerAuthority(str);
2148
2149         if (isReg || isServer)
2150         {
2151                 return true;
2152         }
2153         else
2154         {
2155                 return false;
2156         }
2157 }
2158
2159
2160 bool
2161 Uri::VerifyHost(const Tizen::Base::String& str) const
2162 {
2163         int length = str.GetLength();
2164
2165         for (int i = 0; i < length; i++)
2166         {
2167                 wchar_t ch = str[i];
2168                 if (ch != L'-' && ch != L'.' && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch))
2169                 {
2170                         return false;
2171                 }
2172
2173                 if (ch == L'-')
2174                 {
2175                         if (i == 0 || i == length - 1)
2176                         {
2177                                 return false;
2178                         }
2179                 }
2180         }
2181         return true;
2182 }
2183
2184
2185 bool
2186 Uri::VerifyPath(const Tizen::Base::String& str) const
2187 {
2188         result r = E_SUCCESS;
2189         String reserved(L":@&=+$\",;/");
2190
2191         int strLen = str.GetLength();
2192         for (int i = 0; i < strLen; i++)
2193         {
2194                 int indexOf = 0;
2195                 r = reserved.IndexOf(str[i], 0, indexOf);
2196
2197                 if (str[i] == L'%')
2198                 {
2199                         wchar_t ch1 = str[i + 1];
2200                         wchar_t ch2 = str[i + 2];
2201                         bool escape = IsEscapedChar(ch1, ch2);
2202                         if (!escape)
2203                         {
2204                                 return false;
2205                         }
2206                 }
2207                 else if (str[i] == L' ')    // add a space
2208                 {
2209                 }
2210                 else if (r == E_OBJ_NOT_FOUND && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
2211                 {
2212                         // Check the unicode letter
2213                         if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2214                         {
2215                                 return false;
2216                         }
2217                 }
2218
2219         }
2220         return true;
2221 }
2222
2223
2224 bool
2225 Uri::VerifyUserInfo(const Tizen::Base::String& str) const
2226 {
2227         String reserved(L";:&=+$,");
2228         int strLen = str.GetLength();
2229
2230         for (int i = 0; i < strLen; i++)
2231         {
2232                 int indexOf = 0;
2233                 reserved.IndexOf(str[i], 0, indexOf);
2234
2235                 if (str[i] == L'%')
2236                 {
2237                         wchar_t ch1 = str[i + 1];
2238                         wchar_t ch2 = str[i + 2];
2239                         bool escape = IsEscapedChar(ch1, ch2);
2240                         if (!escape)
2241                         {
2242                                 return false;
2243                         }
2244                 }
2245                 else if (str[i] == L' ')    // add a space
2246                 {
2247                 }
2248                 else if (indexOf < 0 && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
2249                 {
2250                         // Check the unicode letter
2251                         if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2252                         {
2253                                 return false;
2254                         }
2255                 }
2256         }
2257         return true;
2258 }
2259
2260
2261 bool
2262 Uri::VerifyUriChar(const Tizen::Base::String& str) const
2263 {
2264         result r = E_SUCCESS;
2265 //      String reserved(L";/?:@&=+$,[]");
2266         // [ ] removed form "reserved"
2267         //  RFC 2732: (Format for Literal IPv6 Addresses in URLs) is not supported for now.
2268         String reserved(L";/?:@&=+$,");
2269         String delims(L"<>#\"");    // <, >, #, %, "
2270         int strLen = str.GetLength();
2271
2272         for (int i = 0; i < strLen; i++)
2273         {
2274                 wchar_t ch = str[i];
2275                 int indexOf = 0;
2276
2277                 r = delims.IndexOf(ch, 0, indexOf);     // check delims
2278                 if (r == E_SUCCESS)
2279                 {
2280                         return false;
2281                 }
2282
2283                 r = reserved.IndexOf(ch, 0, indexOf);
2284                 if (ch == L'%')
2285                 {
2286                         wchar_t ch1 = str[i + 1];
2287                         wchar_t ch2 = str[i + 2];
2288                         bool escape = IsEscapedChar(ch1, ch2);
2289                         if (!escape)
2290                         {
2291                                 return false;
2292                         }
2293                 }
2294                 else if (IsControlChar(ch))     // control
2295                 {
2296                         return false;
2297                 }
2298                 else if ((ch != ' ') && (ch < 0x80) && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch) && !IsMark(ch) &&
2299                                  !(r == E_SUCCESS))
2300                 {
2301                         // Check the unicode letter
2302                         if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2303                         {
2304                                 return false;
2305                         }
2306                 }
2307         }
2308         return true;
2309 }
2310
2311
2312 //
2313 // This method checks that a given string consists of only server_based characters.
2314 // @return              True if a string consists of only server_based characters.
2315 //
2316 bool
2317 Uri::VerifyServerAuthority(const Tizen::Base::String& str) const
2318 {
2319         result r = E_SUCCESS;
2320         String special(L".:@[]");
2321
2322         int indexOf = 0;
2323         int strLen = str.GetLength();
2324         // Server based authority consists of alphabets, digits, marks(-_!.~*'()), escaped(%hexhex), and ;:&=+$'',@[]
2325         for (int i = 0; i < strLen; i++)
2326         {
2327                 wchar_t ch = str[i];
2328                 r = special.IndexOf(ch, 0, indexOf);
2329                 //if (r == E_SUCCESS && indexOf >= 0)
2330                 //{
2331                 //    return true;
2332                 //}
2333                 //
2334                 if (ch == L'-' || IsUserInfo(ch) || r == E_SUCCESS)
2335                 {
2336                         // This string is a server_based authority character
2337                         if (ch == L'%')
2338                         {
2339                                 // escaped octets
2340                                 if (!IsEscapedChar(str[i + 1], str[i + 2]))
2341                                 {
2342                                         return false;
2343                                 }
2344                         }
2345 //                      return true;
2346                 }
2347                 else
2348                 {
2349                         // Check the unicode letter
2350                         if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2351                         {
2352                                 return false;
2353                         }
2354                 }
2355         }
2356         return true;
2357 }
2358
2359
2360 //
2361 // This method checks that a given string consists of only registry_based characters.
2362 // @return              True if a string consists of only registry_based characters.
2363 //
2364 bool
2365 Uri::VerifyRegistryAuthority(const Tizen::Base::String& str) const
2366 {
2367         result r = E_SUCCESS;
2368         String specialChar(L"@%;:&=+$,");
2369
2370         int indexOf = 0;
2371         int strLen = str.GetLength();
2372         for (int i = 0; i < strLen; i++)
2373         {
2374                 wchar_t ch = str[i];
2375                 r = specialChar.IndexOf(ch, 0, indexOf);
2376
2377                 if (!(Character::IsAlphaNumeric(ch)) && !(Character::IsDigit(ch)) && !IsMark(ch) && !(indexOf >= 0 && r == E_SUCCESS))
2378                 {
2379                         // Check the unicode letter
2380                         if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2381                         {
2382                                 return false;
2383                         }
2384                 }
2385                 else if (ch == L'%')
2386                 {
2387                         if (!IsEscapedChar(str[i + 1], str[i + 2]))
2388                         {
2389                                 return false;
2390                         }
2391                 }
2392         }
2393
2394         return true;
2395 }
2396
2397
2398 //////////////////////////////////////////////////////////////////////
2399 // Utility methods such as IsUserInfo, IsMark and so on.
2400
2401 //
2402 // This method returns true if a given wchar_t is a user-info character.
2403 // user-info char : alphabet, digit, -_.!~*'(), ;:&=+$,
2404 //
2405 bool
2406 Uri::IsUserInfo(wchar_t mch) const
2407 {
2408         result r = E_SUCCESS;
2409         String specialChar(L";:&=+$,");
2410
2411         if (mch == L'%' || Character::IsAlphaNumeric(mch) || Character::IsDigit(mch) || IsMark(mch))
2412         {
2413                 return true;
2414         }
2415
2416         int indexOf = 0;
2417         r = specialChar.IndexOf(mch, 0, indexOf);
2418         if (indexOf >= 0 && r == E_SUCCESS)
2419         {
2420                 return true;
2421         }
2422
2423         return false;
2424 }
2425
2426
2427 //
2428 // This method returns true if a given wchar_t is a mark character.
2429 // mark char : -_.!~*'()
2430 //
2431 bool
2432 Uri::IsMark(wchar_t mch) const
2433 {
2434         result r = E_SUCCESS;
2435         String mark(L"-_.!~*'()");
2436
2437         int indexOf = 0;
2438
2439         r = mark.IndexOf(mch, 0, indexOf);
2440         if (indexOf >= 0 && r == E_SUCCESS)
2441         {
2442                 return true;
2443         }
2444
2445         return false;
2446 }
2447
2448
2449 bool
2450 Uri::IsControlChar(wchar_t ch) const
2451 {
2452         if ((ch <= 0x009F) && ((ch <= 0x001F) || (ch >= 0x007F)))
2453         {
2454                 return true;
2455         }
2456         else
2457         {
2458                 return false;
2459         }
2460 }
2461
2462
2463 bool
2464 Uri::IsEscapedChar(wchar_t ch1, wchar_t ch2) const
2465 {
2466         if ((ch1 >= L'a' && ch1 <= L'f') || (ch1 >= L'A' && ch1 <= L'F') || Character::IsDigit(ch1))
2467         {
2468                 if ((ch2 >= L'a' && ch2 <= L'f') || (ch2 >= L'A' && ch2 <= L'F') || Character::IsDigit(ch2))
2469                 {
2470                         return true;
2471                 }
2472         }
2473
2474         return false;
2475 }
2476
2477
2478 ////////////////////////////////////////////////////////////////////////
2479 // Private operations
2480
2481 //
2482 // This method finds the first character in the stop-string.
2483 //
2484 int
2485 Uri::Scan(const Tizen::Base::String& str, int start, const Tizen::Base::String& stopString)
2486 {
2487         result r = E_SUCCESS;
2488         int index = start;
2489         int strLen = str.GetLength();
2490         while (index < strLen)
2491         {
2492                 int indexOf = 0;
2493                 wchar_t ch = str[index];
2494
2495                 r = stopString.IndexOf(ch, 0, indexOf);
2496                 if (r == E_SUCCESS)
2497                 {
2498                         break;
2499                 }
2500
2501                 index++;
2502         }
2503         return index;
2504 }
2505
2506
2507 //
2508 // This method convers a component represented by UTF8 to a component represented by Unicode.
2509 //
2510 Tizen::Base::String
2511 Uri::Decode(const Tizen::Base::String& str)
2512 {
2513         if (str.IsEmpty())
2514         {
2515                 return str;
2516         }
2517
2518         result r = E_SUCCESS;
2519
2520         int len = str.GetLength();
2521         int index = 0;
2522
2523         String decodedBuf;
2524
2525         while (index < len)
2526         {
2527                 if (str[index] != L'%')
2528                 {
2529                         decodedBuf.Append(str[index]);
2530                         index++;
2531                         continue;
2532                 }
2533
2534                 ByteBuffer bb;
2535                 r = bb.Construct(20);
2536
2537                 while (1)
2538                 {
2539                         String utf8Str;
2540                         r = str.SubString(index + 1, 2, utf8Str);
2541
2542                         short ret = 0;
2543                         r = Short::Parse(utf8Str, 16, ret);
2544                         if (IsFailed(r))
2545                         {
2546                                 goto CATCH;
2547                         }
2548
2549                         r = bb.SetByte((byte) ret);
2550
2551                         index = index + 3;
2552
2553                         if (index >= len || str[index] != '%')
2554                         {
2555                                 r = bb.SetByte(0);
2556                                 break;
2557                         }
2558                 }
2559
2560                 String unicode;
2561                 r = StringUtil::Utf8ToString((char*) bb.GetPointer(), unicode);
2562 //              if (IsFailed(r)) goto CATCH;
2563                 if (IsFailed(r))
2564                 {
2565                         decodedBuf.Append(L'?');
2566                 }
2567                 else
2568                 {
2569                         decodedBuf.Append(unicode);
2570                 }
2571         }
2572
2573         return decodedBuf;
2574
2575 CATCH:
2576         return str;
2577 }
2578
2579
2580 //
2581 // This method converts a component represented by Unicode to a component represented by UTF8.
2582 //
2583 Tizen::Base::String
2584 Uri::Encode(const Tizen::Base::String& str) const
2585 {
2586         if (str.IsEmpty())
2587         {
2588                 return str;
2589         }
2590
2591         result r = E_SUCCESS;
2592         String upper;
2593         WcharBuffer wchar_tBuf;
2594
2595         r = wchar_tBuf.Construct(str.GetLength() + 1);
2596
2597         String strbuf;
2598
2599         r = wchar_tBuf.SetArray(str.GetPointer(), 0, str.GetLength());
2600         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2601
2602         r = wchar_tBuf.Set(L'\0');
2603         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2604
2605         wchar_tBuf.Flip();
2606
2607         std::unique_ptr< char[] > pChar(new (std::nothrow) char[10]);
2608         SysTryReturn(NID_BASE_UTIL, pChar != null, str, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
2609         memset(pChar.get(), 0, 10);
2610
2611         while (wchar_tBuf.HasRemaining())
2612         {
2613                 wchar_t mch = 0x00;
2614                 r = wchar_tBuf.Get(mch);
2615                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2616
2617                 if (mch == 0)
2618                 {
2619                         break;
2620                 }
2621
2622                 if (mch >= 0x0080 || IsControlChar(mch))
2623                 {
2624                         WcharBuffer tmpBuf;
2625                         String tempStr;
2626
2627                         String unicode;
2628
2629                         int bbPos = 0;
2630
2631                         r = tmpBuf.Construct(2);
2632                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2633
2634                         r = tmpBuf.Set(mch);
2635                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2636
2637                         r = tmpBuf.Set(L'\0');
2638                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2639
2640                         tmpBuf.Flip();
2641
2642                         tempStr = tmpBuf.GetPointer();
2643                         std::unique_ptr< ByteBuffer > pBuf(StringUtil::StringToUtf8N(tempStr));
2644                         SysTryReturn(NID_BASE_UTIL, pBuf != null, str, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
2645
2646                         while (bbPos < pBuf->GetLimit() - 1) // null
2647                         {
2648                                 byte b = '\0';
2649                                 r = pBuf->GetByte(bbPos, b);
2650                                 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2651
2652                                 sprintf(pChar.get() + (bbPos * 3), "%%%x", (int) b);
2653                                 bbPos++;
2654                         }
2655
2656                         r = StringUtil::Utf8ToString(pChar.get(), unicode);
2657                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2658
2659                         r = unicode.ToUpper(upper);
2660
2661                         r = strbuf.Append(upper);
2662                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2663                 }
2664                 else if (mch == 0x20)
2665                 {
2666                         String unicode(L"%20");
2667                         r = strbuf.Append(unicode);
2668                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2669                 }
2670                 else // ASCII character
2671                 {
2672                         r = strbuf.Append(mch);
2673                         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2674                 }
2675         }
2676
2677         SetLastResult(E_SUCCESS);
2678         return strbuf;
2679 }
2680
2681
2682 result
2683 Uri::AppendEscape(Tizen::Base::String& strbuf, byte b)
2684 {
2685         byte bt1 = '\0';
2686         byte bt2 = '\0';
2687
2688         result r = E_SUCCESS;
2689         r = strbuf.Append(L'%');
2690         if (IsFailed(r))
2691         {
2692                 goto CATCH;
2693         }
2694
2695         bt1 = (b >> 4) & 0x0f;
2696         r = strbuf.Append(HEX_DIGITS[bt1]);
2697         if (IsFailed(r))
2698         {
2699                 goto CATCH;
2700         }
2701
2702         bt2 = (b >> 0) & 0x0f;
2703         r = strbuf.Append(HEX_DIGITS[bt2]);
2704         if (IsFailed(r))
2705         {
2706                 goto CATCH;
2707         }
2708
2709         return r;
2710
2711 CATCH:
2712         return r;
2713 }
2714
2715
2716 // This method compares str1 and str2 after replacing all uppercase letters with their lowercase letters
2717 int
2718 Uri::Compare(const Tizen::Base::String& str1, const Tizen::Base::String& str2) const
2719 {
2720         String small1;
2721         String small2;
2722
2723         if (str1.IsEmpty())
2724         {
2725                 if (str2.IsEmpty())
2726                 {
2727                         // Both pStr1 and pStr2 are null
2728                         return 0;
2729                 }
2730                 else
2731                 {
2732                         // pStr1 is null but pStr isn't.
2733                         return -1;
2734                 }
2735         }
2736         else
2737         {
2738                 if (str2.IsEmpty())
2739                 {
2740                         // pStr1 is not null but pStr2 is null
2741                         return 1;
2742                 }
2743         }
2744
2745         // Replace all uppercase letters with their lowercase letters
2746         str1.ToLower(small1);
2747         str2.ToLower(small2);
2748
2749         return small1.CompareTo(small2);
2750
2751 }
2752
2753
2754 //////////////////////////////////////////////////////////////////////////////////////////
2755 // Normalization
2756
2757 Tizen::Base::String
2758 Uri::InternalNormalize(const Tizen::Base::String& path)
2759 {
2760         result r = E_SUCCESS;
2761         String joinedStr;
2762         String str;
2763         int segCount = 0;
2764         int join = 0;
2765
2766         std::unique_ptr< WcharBuffer > pBuf(StringUtil::StringToMbN(path, 0, path.GetLength()));
2767         if (pBuf == null)
2768         {
2769                 return str;
2770         }
2771
2772         // Get the number of segments from a given path
2773         segCount = GetNumberOfSegments(path);
2774         if (segCount <= 0)
2775         {
2776                 return path;
2777         }
2778
2779         // Get the first index of each segment
2780         std::unique_ptr< int[] > pSegments(new (std::nothrow) int[segCount]);
2781         SplitIntoSegments(*pBuf, pSegments.get(), segCount);
2782
2783         // Remove dots
2784         RemoveDots(*pBuf, pSegments.get(), segCount, path.GetLength());
2785
2786         // Prevent scheme-name confusion
2787         AddLeadingDot(*pBuf, pSegments.get(), segCount);
2788
2789         // Join the remaining segments and returns the result
2790         join = Join(*pBuf, pSegments.get(), segCount);
2791
2792         r = StringUtil::MbToString(*pBuf, str);
2793         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), L"", E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG));
2794
2795         // Empty String
2796         if (str.IsEmpty())
2797         {
2798                 return str;
2799         }
2800
2801         r = str.SubString(0, join - 1, joinedStr);
2802         SysTryReturn(NID_BASE_UTIL, !IsFailed(r), L"", E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG));
2803
2804         if (joinedStr.Equals(path))
2805         {
2806                 return path;    // String was already normalized.
2807         }
2808
2809         SetLastResult(E_SUCCESS);
2810         return joinedStr;
2811 }
2812
2813
2814 //
2815 // This method returns the number of segments from a given path.
2816 //
2817 int
2818 Uri::GetNumberOfSegments(const Tizen::Base::String& path) const
2819 {
2820         bool normal = true;
2821         int segCount = 0;
2822         int endIndex = path.GetLength() - 1;
2823         int p = 0;
2824
2825         // find the index of non-slash character
2826         while (p <= endIndex)
2827         {
2828                 if (path[p] != L'/')
2829                 {
2830                         break;
2831                 }
2832                 p++;
2833         }
2834         if (p > 1)
2835         {
2836                 normal = false;
2837         }
2838
2839         // Scan segments
2840         while (p <= endIndex)
2841         {
2842                 // Looking at '.' or '..'
2843                 if ((path[p] == L'.') && ((p == endIndex) || ((path[p + 1] == L'/') ||
2844                                                                                                           ((path[p + 1] == L'.') && ((p + 1 == endIndex) || (path[p + 2] == L'/'))))))
2845                 {
2846                         normal = false;
2847                 }
2848                 segCount++;
2849
2850                 // Find the beginning index of next segment
2851                 while (p <= endIndex)
2852                 {
2853                         if (path[p++] != L'/')
2854                         {
2855                                 continue;
2856                         }
2857
2858                         // skip redundant slashes
2859                         while (p <= endIndex)
2860                         {
2861                                 if (path[p] != L'/')
2862                                 {
2863                                         break;
2864                                 }
2865
2866                                 normal = false;
2867                                 p++;
2868                         }
2869
2870                         break;
2871                 }
2872         }
2873
2874         if (normal)
2875         {
2876                 return -1;
2877         }
2878         else
2879         {
2880                 return segCount;
2881         }
2882 }
2883
2884
2885 void
2886 Uri::SplitIntoSegments(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
2887 {
2888         int end = StringUtil::GetStringLengthInMb(mb);
2889
2890         //int end = mb.GetLimit() - 1;
2891         int p = 0;
2892         int index = 0; // the index of current segment
2893
2894         // skip initial slash
2895         while (p <= end)
2896         {
2897                 if (mb[p] != L'/')
2898                 {
2899                         break;
2900                 }
2901                 mb[p] = L'\0';
2902                 p++;
2903         }
2904
2905         while (p <= end)
2906         {
2907                 if (index >= segCount)
2908                 {
2909                         break;
2910                 }
2911
2912                 // start of segment
2913                 segments[index] = p;
2914                 index++;
2915                 p++;
2916
2917                 // Find beginning of next segment
2918                 while (p <= end)
2919                 {
2920                         if (mb[p++] != L'/')
2921                         {
2922                                 continue;
2923                         }
2924                         mb[p - 1] = L'\0';
2925
2926                         // skip redundant slash
2927                         while (p <= end)
2928                         {
2929                                 if (mb[p] != L'/')
2930                                 {
2931                                         break;
2932                                 }
2933                                 mb[p++] = L'\0';
2934                         }
2935                         break;
2936                 }
2937         }
2938
2939         // index must be equal to the length of segments[]
2940 }
2941
2942
2943 void
2944 Uri::RemoveDots(const Tizen::Base::WcharBuffer& mb, int* segments, int segCount, int length)
2945 {
2946         int end = length;
2947
2948         for (int i = 0; i < segCount; i++)
2949         {
2950                 int dots = 0; // number of dots found
2951
2952                 // Find next occurrence of "." or "..
2953                 do
2954                 {
2955                         int p = segments[i];
2956                         if (mb[p] == '.')
2957                         {
2958                                 if (p == end)
2959                                 {
2960                                         dots = 1;
2961                                         break;
2962                                 }
2963                                 else if (mb[p + 1] == L'\0')
2964                                 {
2965                                         dots = 1;
2966                                         break;
2967                                 }
2968                                 else if ((mb[p + 1] == L'.') && ((p + 1 == end) || (mb[p + 2] == L'\0')))
2969                                 {
2970                                         dots = 2;
2971                                         break;
2972                                 }
2973                         }
2974                         i++;
2975                 }
2976                 while (i < segCount);
2977
2978                 if ((i > segCount) || (dots == 0))
2979                 {
2980                         break;
2981                 }
2982
2983                 if (dots == 1 && i < segCount)
2984                 {
2985                         // Remove this occurrence of '.'
2986                         segments[i] = -1;
2987                 }
2988                 else
2989                 {
2990                         // If there is a preceding non-".." segment, remove both that segment and this occurrence of "..";
2991                         // otherwise, leave this ".." segment as-is.
2992                         int j = 0;
2993                         for (j = i - 1; j >= 0; j--)
2994                         {
2995                                 if (segments[j] != -1)
2996                                 {
2997                                         break;
2998                                 }
2999                         }
3000
3001                         if (j >= 0)
3002                         {
3003                                 int q = segments[j];
3004                                 if (!((mb[q] == '.') && (mb[q + 1] == '.') && (mb[q + 2] == '\0')))
3005                                 {
3006                                         segments[i] = -1;
3007                                         segments[j] = -1;
3008                                 }
3009                         }
3010                 }
3011         }
3012 }
3013
3014
3015 void
3016 Uri::AddLeadingDot(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
3017 {
3018         if (mb[0] == L'\0')
3019         {
3020                 // The path is absolute
3021                 return;
3022         }
3023
3024         int firstSegment = 0;           // Index of first segment
3025         while (firstSegment < segCount)
3026         {
3027                 if (segments[firstSegment] >= 0)
3028                 {
3029                         break;
3030                 }
3031                 firstSegment++;
3032         }
3033
3034         if ((firstSegment >= segCount) || (firstSegment == 0))
3035         {
3036                 // The path is empty, or else the original first segment survived,
3037                 // in which case we already know that no leading "." is needed
3038                 return;
3039         }
3040
3041         int p = segments[firstSegment];
3042         while ((mb[p] != L':') && (mb[p] != L'\0') && (p < mb.GetLimit()))
3043         {
3044                 p++;
3045         }
3046
3047         if (mb[p] == L'\0' || p >= mb.GetLimit())
3048         {
3049                 // No colon in first segment, so no "." needed
3050                 return;
3051         }
3052
3053         // At this point we know that the first segment is unused,
3054         // hence we can insert a "." segment at that position
3055         mb[0] = L'.';
3056         mb[1] = L'\0';
3057         segments[0] = 0;
3058 }
3059
3060
3061 // Join the segments in the given path according to the given segment-index array,
3062 // ignoring those segments whose index entries have been set to -1, and inserting slashes as needed.
3063 // Return the length of the resulting path.
3064 //
3065 // Preconditions:
3066 //   segs[i] == -1 implies segment i is to be ignored
3067 //   path computed by split, as above, with '\0' having replaced '/'
3068 //
3069 // Postconditions:
3070 //   path[0] .. path[return value] == Resulting path
3071 //
3072 int
3073 Uri::Join(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
3074 {
3075         //int end = StringUtil::GetStringLengthInMb(mb);
3076
3077         int end = mb.GetLimit() - 1;
3078         int p = 0;
3079
3080         if (mb[p] == L'\0')
3081         {
3082                 // Restore initial slash for absolute paths
3083                 mb[p++] = L'/';
3084         }
3085
3086         for (int i = 0; i < segCount; i++)
3087         {
3088                 int q = segments[i];
3089                 if (q == -1)
3090                 {
3091                         // ignore this segment
3092                         continue;
3093                 }
3094
3095                 if (p == q)
3096                 {
3097                         // skip to its end
3098                         while ((p <= end) && (mb[p] != L'\0'))
3099                         {
3100                                 p++;
3101                         }
3102                         if (p <= end)
3103                         {
3104                                 // Preserve trailing slash
3105                                 mb[p++] = L'/';
3106                         }
3107                 }
3108                 else if (p < q)
3109                 {
3110                         while ((q <= end) && mb[q] != L'\0')
3111                         {
3112                                 mb[p++] = mb[q++];
3113                         }
3114                         if (q < end)
3115                         {
3116                                 // Preserve trailing slash
3117                                 mb[p++] = L'/';
3118                         }
3119                 }
3120         }
3121         if (p == mb.GetLimit())
3122         {
3123                 result r = E_SUCCESS;
3124                 r = mb.SetLimit(p + 1);
3125                 if (IsFailed(r))
3126                 {
3127                         return p;
3128                 }
3129         }
3130         mb[p++] = L'\0';
3131
3132         return p;
3133 }
3134
3135
3136 ///////////////////////////////////////////////////////////////////////////////////////////////
3137 // Resolution
3138
3139 //
3140 // This method implements Uri resolution in RFC2396 5.2
3141 //
3142 result
3143 Uri::Resolve(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
3144 {
3145         result r = E_SUCCESS;
3146
3147         // If either baseUri or childUri is opaque, then resultUri is childUri
3148         if (baseUri.IsOpaque() || childUri.IsOpaque())
3149         {
3150                 resultUri = childUri;
3151                 return E_SUCCESS;
3152         }
3153
3154
3155         // 5.2(2) If scheme, authority, path, and query of childUri are null,
3156         // the components of baseUri are copied to components of resultUri.
3157         if ((childUri.__scheme.IsEmpty()) && (childUri.__authority.IsEmpty()) && (childUri.__path.IsEmpty())
3158                 && (!childUri.__fragment.IsEmpty()) && (childUri.__query.IsEmpty()))
3159         {
3160                 if ((!baseUri.__fragment.IsEmpty()) && (childUri.__fragment.GetLength() == baseUri.__fragment.GetLength()))
3161                 {
3162                         resultUri = baseUri;
3163                         return E_SUCCESS;
3164                 }
3165
3166                 if (!baseUri.__scheme.IsEmpty())
3167                 {
3168                         r = resultUri.SetScheme(baseUri.__scheme);
3169                         if (IsFailed(r))
3170                         {
3171                                 return r;
3172                         }
3173                 }
3174
3175                 if (!baseUri.__authority.IsEmpty())
3176                 {
3177                         r = resultUri.SetAuthority(baseUri.__authority);
3178                         if (IsFailed(r))
3179                         {
3180                                 return r;
3181                         }
3182                 }
3183
3184                 if (!baseUri.__userInfo.IsEmpty())
3185                 {
3186                         r = resultUri.SetUserInfo(baseUri.__userInfo);
3187                         if (IsFailed(r))
3188                         {
3189                                 return r;
3190                         }
3191                 }
3192
3193                 if (!baseUri.__host.IsEmpty())
3194                 {
3195                         r = resultUri.SetHost(baseUri.__host);
3196                         if (IsFailed(r))
3197                         {
3198                                 return r;
3199                         }
3200                 }
3201
3202                 resultUri.SetPort(baseUri.__port);
3203
3204                 if (!baseUri.__path.IsEmpty())
3205                 {
3206                         r = resultUri.SetPath(baseUri.__path);
3207                         if (IsFailed(r))
3208                         {
3209                                 return r;
3210                         }
3211                 }
3212
3213                 if (!childUri.__fragment.IsEmpty())
3214                 {
3215                         r = resultUri.SetFragment(childUri.__fragment);
3216                         if (IsFailed(r))
3217                         {
3218                                 return r;
3219                         }
3220                 }
3221
3222                 if (!baseUri.__query.IsEmpty())
3223                 {
3224                         r = resultUri.SetQuery(baseUri.__query);
3225                         if (IsFailed(r))
3226                         {
3227                                 return r;
3228                         }
3229                 }
3230
3231                 return E_SUCCESS;
3232         }
3233
3234
3235         // 5.2(3) child is an absolute URI
3236         if (!childUri.__scheme.IsEmpty())
3237         {
3238                 resultUri = childUri;
3239                 return E_SUCCESS;
3240         }
3241
3242
3243         if (!baseUri.__scheme.IsEmpty())
3244         {
3245                 r = resultUri.SetScheme(baseUri.__scheme);
3246                 if (IsFailed(r))
3247                 {
3248                         return r;
3249                 }
3250         }
3251
3252         if (!childUri.__query.IsEmpty())
3253         {
3254                 r = resultUri.SetQuery(childUri.__query);
3255                 if (IsFailed(r))
3256                 {
3257                         return r;
3258                 }
3259         }
3260
3261         if (!childUri.__fragment.IsEmpty())
3262         {
3263                 r = resultUri.SetFragment(childUri.__fragment);
3264                 if (IsFailed(r))
3265                 {
3266                         return r;
3267                 }
3268         }
3269
3270         // 5.2(4) Authority
3271         if (childUri.__authority.IsEmpty())
3272         {
3273                 if (!baseUri.__authority.IsEmpty())
3274                 {
3275                         r = resultUri.SetAuthority(baseUri.__authority);
3276                         if (IsFailed(r))
3277                         {
3278                                 return r;
3279                         }
3280                 }
3281
3282                 if (!baseUri.__host.IsEmpty())
3283                 {
3284                         r = resultUri.SetHost(baseUri.__host);
3285                         if (IsFailed(r))
3286                         {
3287                                 return r;
3288                         }
3289                 }
3290
3291                 if (!baseUri.__userInfo.IsEmpty())
3292                 {
3293                         r = resultUri.SetUserInfo(baseUri.__userInfo);
3294                         if (IsFailed(r))
3295                         {
3296                                 return r;
3297                         }
3298                 }
3299
3300                 resultUri.SetPort(baseUri.__port);
3301
3302                 String resolve;
3303                 String encodedPath = childUri.__encodedPath;
3304                 if (!encodedPath.IsEmpty())
3305                 {
3306                         resolve = childUri.__encodedPath;
3307                 }
3308
3309                 if ((!resolve.IsEmpty()) && (resolve[0] == L'/'))
3310                 {
3311                         // 5.2(5) child uri's path is absolute
3312                         if (!encodedPath.IsEmpty())
3313                         {
3314                                 r = resultUri.SetPath(encodedPath);
3315                                 if (IsFailed(r))
3316                                 {
3317                                         return r;
3318                                 }
3319                         }
3320                 }
3321                 else
3322                 {
3323                         String encPath = baseUri.__encodedPath;
3324                         if (!encPath.IsEmpty())
3325                         {
3326                                 // 5.2(6) Resolve relative path
3327                                 String relPath = ResolvePath(encPath, resolve, baseUri.IsAbsolute());
3328                                 if (relPath.IsEmpty())
3329                                 {
3330                                         return GetLastResult();
3331                                 }
3332
3333                                 r = resultUri.SetPath(relPath);
3334                                 if (IsFailed(r))
3335                                 {
3336                                         return r;
3337                                 }
3338                         }
3339                 }
3340         }
3341         else
3342         {
3343                 if (!childUri.__authority.IsEmpty())
3344                 {
3345                         r = resultUri.SetAuthority(childUri.__authority);
3346                         if (IsFailed(r))
3347                         {
3348                                 return r;
3349                         }
3350                 }
3351
3352                 if (!childUri.__host.IsEmpty())
3353                 {
3354                         r = resultUri.SetHost(childUri.__host);
3355                         if (IsFailed(r))
3356                         {
3357                                 return r;
3358                         }
3359                 }
3360
3361                 if (!childUri.__userInfo.IsEmpty())
3362                 {
3363                         r = resultUri.SetUserInfo(childUri.__userInfo);
3364                         if (IsFailed(r))
3365                         {
3366                                 return r;
3367                         }
3368                 }
3369
3370                 resultUri.SetPort(childUri.__port);
3371
3372                 if (!childUri.__path.IsEmpty())
3373                 {
3374                         r = resultUri.SetPath(childUri.__path);
3375                         if (IsFailed(r))
3376                         {
3377                                 return r;
3378                         }
3379                 }
3380
3381         }
3382
3383         return E_SUCCESS;
3384 }
3385
3386
3387 // RFC2396 5.2(6)
3388 Tizen::Base::String
3389 Uri::ResolvePath(const String& basePath, const String& childPath, bool isAbsolute)
3390 {
3391         result r = E_SUCCESS;
3392         String path;
3393
3394         int indexOf = 0;
3395         r = basePath.LastIndexOf(L'/', basePath.GetLength() - 1, indexOf);
3396
3397         int len = childPath.GetLength();
3398
3399         if (len == 0)
3400         {
3401                 if (indexOf >= 0 && r == E_SUCCESS)
3402                 {
3403                         r = basePath.SubString(0, indexOf + 1, path);
3404                         if (IsFailed(r))
3405                         {
3406                                 goto CATCH;
3407                         }
3408                 }
3409         }
3410         // 5.2 (6a)
3411         else
3412         {
3413                 String strbuf;
3414
3415                 if (r == E_SUCCESS)
3416                 {
3417                         String tmpath;
3418                         r = basePath.SubString(0, indexOf + 1, tmpath);
3419                         if (IsFailed(r))
3420                         {
3421                                 goto CATCH;
3422                         }
3423
3424                         r = strbuf.Append(tmpath);
3425                         if (IsFailed(r))
3426                         {
3427                                 goto CATCH;
3428                         }
3429                 }
3430
3431                 r = strbuf.Append(childPath);
3432                 if (IsFailed(r))
3433                 {
3434                         goto CATCH;
3435                 }
3436
3437                 path = strbuf;
3438         }
3439
3440         return InternalNormalize(path);
3441
3442 CATCH:
3443         SetLastResult(r);
3444         return null;
3445 }
3446
3447
3448 //////////////////////////////////////////////////////////////////////////
3449 // Relativize
3450 result
3451 Uri::Relativize(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
3452 {
3453         result r = E_SUCCESS;
3454
3455         // If either base URI or child URI is opaque, result URI is the childUri.
3456         if (baseUri.IsOpaque() || childUri.IsOpaque())
3457         {
3458                 resultUri = childUri;
3459                 return E_SUCCESS;
3460         }
3461
3462         int ret1 = Compare(baseUri.__scheme, childUri.__scheme);
3463
3464         bool equal = false;
3465         if (!baseUri.__authority.IsEmpty() && !childUri.__authority.IsEmpty())
3466         {
3467                 equal = EqualsComponent(baseUri.__authority, childUri.__authority);
3468         }
3469
3470         if ((ret1 != 0) || (!equal))
3471         {
3472                 resultUri = childUri;
3473                 return E_SUCCESS;
3474         }
3475
3476         String basePath = InternalNormalize(baseUri.__path);
3477         String childPath = InternalNormalize(childUri.__path);
3478
3479         if (basePath.Equals(childPath) == false)
3480         {
3481                 String newBp;
3482                 String slash(L"/");
3483
3484                 bool endWith = basePath.EndsWith(slash);
3485                 if (!endWith)
3486                 {
3487                         String strbuf(basePath);
3488
3489                         r = strbuf.Append(slash);
3490                         if (IsFailed(r))
3491                         {
3492                                 return r;
3493                         }
3494
3495                         newBp = strbuf;
3496                 }
3497                 else
3498                 {
3499                         newBp = basePath;
3500                 }
3501
3502                 bool startsWith = childPath.StartsWith(basePath, 0);
3503
3504                 if (!startsWith)
3505                 {
3506                         resultUri = childUri;
3507                         return E_SUCCESS;
3508                 }
3509         }
3510
3511         String path;
3512         r = childPath.SubString(basePath.GetLength(), path);
3513         if (IsFailed(r))
3514         {
3515                 return E_SUCCESS;
3516         }
3517
3518         r = resultUri.SetPath(path);
3519         if (IsFailed(r))
3520         {
3521                 return r;
3522         }
3523
3524         if (!childUri.__query.IsEmpty())
3525         {
3526                 r = resultUri.SetQuery(childUri.__query);
3527                 if (IsFailed(r))
3528                 {
3529                         return r;
3530                 }
3531         }
3532
3533         if (!childUri.__fragment.IsEmpty())
3534         {
3535                 r = resultUri.SetFragment(childUri.__fragment);
3536                 if (IsFailed(r))
3537                 {
3538                         return r;
3539                 }
3540         }
3541
3542         return r;
3543 }
3544
3545
3546 //
3547 // This method compares two components. If a component is encoded,
3548 // then its raw component is compared with another component.
3549 //
3550 bool
3551 Uri::EqualsComponent(const Tizen::Base::String& comp1, const Tizen::Base::String& comp2)
3552 {
3553         result r =  E_SUCCESS;
3554
3555         if (comp1 == comp2)
3556         {
3557                 return true;
3558         }
3559
3560         if (comp1.GetLength() != comp2.GetLength())
3561         {
3562                 return false;
3563         }
3564
3565         int indexOf = 0;
3566         r = comp1.IndexOf(L'%', 0, indexOf);
3567         if (r == E_OBJ_NOT_FOUND)
3568         {
3569                 return comp1.Equals(comp2);
3570         }
3571
3572         int len = comp1.GetLength();
3573         for (int i = 0; i < len; )
3574         {
3575                 wchar_t c1 = (comp1)[i];
3576                 wchar_t c2 = (comp2)[i];
3577                 if (c1 != L'%')
3578                 {
3579                         if (c1 != c2)
3580                         {
3581                                 return false;
3582                         }
3583                         i++;
3584                         continue;
3585                 }
3586                 i++;
3587
3588
3589                 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3590                 {
3591                         return false;
3592                 }
3593
3594                 i++;
3595                 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3596                 {
3597                         return false;
3598                 }
3599
3600                 i++;
3601         }
3602
3603         return true;
3604 }
3605
3606
3607 bool
3608 Uri::IsEncoded(const Tizen::Base::String& str) const
3609 {
3610         int strLen = str.GetLength();
3611         for (int i = 0; i < strLen; i++)
3612         {
3613                 wchar_t ch = str[i];
3614                 if (ch >= 0x0080 || ch == L' ' || IsControlChar(ch))
3615                 {
3616                         return false;
3617                 }
3618         }
3619         return true;
3620 }
3621
3622
3623 void
3624 Uri::Clear(void)
3625 {
3626         // Component
3627         __scheme.Clear();
3628         __ssp.Clear();
3629         __authority.Clear();
3630         __host.Clear();
3631         __fragment.Clear();
3632         __path.Clear();
3633         __userInfo.Clear();
3634         __query.Clear();
3635         __ipv4.Clear();
3636         __ipv6.Clear();
3637         __port = -1;
3638
3639         // Encoded Component
3640         __encodedAuth.Clear();
3641         __encodedFragment.Clear();
3642         __encodedPath.Clear();
3643         __encodedQuery.Clear();
3644         __encodedSsp.Clear();
3645 }
3646
3647
3648 } } } // Tizen::Base::Utility