2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FBaseUtilUri.cpp
19 * @brief This is the implementation file for Uri class.
24 #include <unique_ptr.h>
25 #include <FBaseUtilUri.h>
26 #include <FBaseInteger.h>
27 #include <FBaseCharacter.h>
28 #include <FBaseShort.h>
29 #include <FBaseUtilStringTokenizer.h>
30 #include <FBaseUtilStringUtil.h>
31 #include <FBaseSysLog.h>
33 namespace Tizen { namespace Base { namespace Utility
36 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'};
38 /////////////////////////////////////////////////////////////////////////////////
49 Uri::Uri(const Uri& uri)
61 Uri::SetUri(const Uri& uri)
63 __scheme = uri.__scheme;
65 __authority = uri.__authority;
67 __fragment = uri.__fragment;
69 __userInfo = uri.__userInfo;
70 __query = uri.__query;
74 __encodedAuth = uri.__encodedAuth;
75 __encodedFragment = uri.__encodedFragment;
76 __encodedPath = uri.__encodedPath;
77 __encodedQuery = uri.__encodedQuery;
78 __encodedSsp = uri.__encodedSsp;
79 __encodedUserInfo = uri.__encodedUserInfo;
82 __hasScheme = uri.__hasScheme;
83 __ipv6ByteCount = uri.__ipv6ByteCount;
87 Uri::SetUri(const Tizen::Base::String& str)
89 SysTryReturnResult(NID_BASE_UTIL, str.GetLength() > 0, E_INVALID_ARG, "Invalid argument is used. An empty String.");
93 result r = ParseUri(str);
94 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_INVALID_FORMAT, "Translating [%s] into [%s].", GetErrorMessage(r), GetErrorMessage(E_INVALID_FORMAT));
100 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& ssp, const Tizen::Base::String& fragment)
104 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
105 return SetUri(scheme, ssp, empty, empty, empty, -1, empty, empty, fragment);
109 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port,
110 const Tizen::Base::String& path, const Tizen::Base::String& query,
111 const Tizen::Base::String& fragment)
115 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
116 return SetUri(scheme, empty, empty, userInfo, host, port, path, query, fragment);
120 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& host, const Tizen::Base::String& path,
121 const Tizen::Base::String& fragment)
125 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
126 return SetUri(scheme, empty, empty, empty, host, -1, path, L"", fragment);
130 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& authority, const Tizen::Base::String& path,
131 const Tizen::Base::String& query,
132 const Tizen::Base::String& fragment)
136 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
137 return SetUri(scheme, empty, authority, empty, empty, -1, path, query, fragment);
140 ////////////////////////////////////////////////////////////////////////////////
144 Uri::operator =(const Uri& rhs)
153 ////////////////////////////////////////////////////////////////////////////////
157 Uri::GetAuthority(void) const
163 Uri::GetFragment(void) const
169 Uri::GetHost(void) const
175 Uri::GetPath(void) const
181 Uri::GetPort(void) const
187 Uri::GetQuery(void) const
193 Uri::GetScheme(void) const
199 Uri::GetSchemeSpecificPart(void) const
205 Uri::GetUserInfo(void) const
211 Uri::GetEncodedAuthority(void) const
213 return __encodedAuth;
217 Uri::GetEncodedFragment(void) const
219 return __encodedFragment;
223 Uri::GetEncodedPath(void) const
225 return __encodedPath;
229 Uri::GetEncodedQuery(void) const
231 return __encodedQuery;
235 Uri::GetEncodedSchemeSpecificPart(void) const
241 Uri::GetEncodedUserInfo(void) const
243 return __encodedUserInfo;
247 Uri::IsAbsolute(void) const
249 // If the URI has a scheme, then it is an absolute URI.
261 Uri::IsOpaque(void) const
263 String scheme = GetScheme();
264 String ssp = GetSchemeSpecificPart();
266 if (scheme.IsEmpty())
289 Uri::GetEncodedString(void) const
294 if (!__scheme.IsEmpty())
296 strbuf.Append(__scheme);
300 if (!__encodedSsp.IsEmpty())
302 strbuf.Append(__encodedSsp);
306 if (!__host.IsEmpty())
309 strbuf.Append(L"//");
311 // Check the Userinfo
312 if (!__encodedUserInfo.IsEmpty())
314 strbuf.Append(__encodedUserInfo);
319 result re = E_SUCCESS;
320 re = __host.IndexOf(L':', 0, indexOf);
322 String openBracket(L"[");
323 String closeBracket(L"]");
325 bool start = __host.StartsWith(openBracket, 0);
326 bool end = __host.EndsWith(closeBracket);
328 bool needBracket = false;
329 if (!start && !end && re == E_SUCCESS)
343 strbuf.Append(__host);
354 strbuf.Append(__port);
357 else if (!__encodedAuth.IsEmpty())
359 strbuf.Append(L"//");
360 strbuf.Append(__encodedAuth);
362 // AppendAuthority end
364 if (!__encodedPath.IsEmpty())
366 strbuf.Append(__encodedPath);
369 if (!__encodedQuery.IsEmpty())
372 strbuf.Append(__encodedQuery);
375 // AppendSchemeSpecificPart end
377 //AppendFragment(strbuf, __encodedFragment);
378 if (!__encodedFragment.IsEmpty())
381 strbuf.Append(__encodedFragment);
383 // AppendFragment end
388 ////////////////////////////////////////////////////////////////////////////////////////////
392 Uri::CompareTo(const Uri& uri) const
394 bool thisOpaque = false;
395 bool thatOpaque = false;
404 String otherFragment;
407 //////////////////////////////////////////////////
409 /////////////////////////////////////////////////
410 thisOpaque = IsOpaque();
411 thatOpaque = uri.IsOpaque();
413 // Both the current instance and a given instance are opaque
414 if (thisOpaque && thatOpaque)
416 // Compare Scheme-specific-part
417 ret = Compare(__ssp, uri.__ssp);
425 ret = Compare(__fragment, uri.__fragment);
430 else if (thisOpaque && !thatOpaque)
434 else if (!thisOpaque && thatOpaque)
439 //////////////////////////////////////////////////
441 /////////////////////////////////////////////////
442 if (!__host.IsEmpty() && !uri.__host.IsEmpty())
446 ret = Compare(__userInfo, uri.__userInfo);
454 ret = Compare(__host, uri.__host);
462 int portDiff = __port - uri.__port;
467 else if (portDiff == 0)
478 // If one of them is registry-based URI, then compare authority.
479 ret = Compare(__authority, uri.__authority);
488 ret = Compare(__path, uri.__path);
495 ret = Compare(__query, uri.__query);
502 ret = Compare(__fragment, uri.__fragment);
508 Uri::Equals(const Tizen::Base::Object& obj) const
510 // Check that obj is an Uri instance.
511 const Uri* pOther = dynamic_cast< const Uri* >(&obj);
517 int ret = CompareTo(*pOther);
527 Uri::GetHashCode(void) const
529 return ToString().GetHashCode();
535 result r = E_SUCCESS;
538 // If the current instance is opaque or the path of the current instance is undefined or an empty string,
540 if (__path.IsEmpty() || IsOpaque())
545 String normalizedUri;
546 normalizedUri = InternalNormalize(__path);
547 if (normalizedUri == __path || GetLastResult() == E_INVALID_ARG)
552 if (!__scheme.IsEmpty())
554 r = resultUri.SetScheme(__scheme);
555 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set scheme.", GetErrorMessage(r));
558 if (!__fragment.IsEmpty())
560 r = resultUri.SetFragment(__fragment);
561 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set fragment.", GetErrorMessage(r));
564 if (!__authority.IsEmpty())
566 r = resultUri.SetAuthority(__authority);
567 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set authority.", GetErrorMessage(r));
570 if (!__userInfo.IsEmpty())
572 r = resultUri.SetUserInfo(__userInfo);
573 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set userinfo.", GetErrorMessage(r));
576 if (!__host.IsEmpty())
578 r = resultUri.SetHost(__host);
579 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set host.", GetErrorMessage(r));
582 resultUri.SetPort(__port);
584 r = resultUri.SetPath(normalizedUri);
585 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set path.", GetErrorMessage(r));
587 if (!__query.IsEmpty())
589 r = resultUri.SetQuery(__query);
590 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set query.", GetErrorMessage(r));
597 Uri::ParseAuthority(Uri& uri)
599 result r = E_SUCCESS;
601 if (!__host.IsEmpty() || __authority.IsEmpty())
607 String str = ToString();
610 r = tempUri.SetUri(str);
611 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
613 r = ParseServerAuthority(str, tempUri.__host, tempUri.__userInfo, tempUri.__port);
614 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
622 Uri::Relativize(const Uri& uri, Uri& resultUri)
624 return Relativize(*this, uri, resultUri);
628 Uri::Resolve(const Uri& uri, Uri& resultUri)
630 return Resolve(*this, uri, resultUri);
634 Uri::SetAuthority(const Tizen::Base::String& authority)
636 bool isAuth = VerifyAuthority(authority);
638 SysTryReturn(NID_BASE_UTIL, isAuth, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Authority.", GetErrorMessage(E_INVALID_FORMAT));
640 if (IsEncoded(authority))
642 __encodedAuth = authority;
643 __authority = Decode(authority);
647 __authority = authority;
648 __encodedAuth = Encode(authority);
655 Uri::SetFragment(const Tizen::Base::String& fragment)
657 bool isFragment = VerifyUriChar(fragment);
659 SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
661 if (IsEncoded(fragment))
663 __encodedFragment = fragment;
664 __fragment = Decode(fragment);
668 __fragment = fragment;
669 __encodedFragment = Encode(fragment);
676 Uri::SetHost(const Tizen::Base::String& host)
678 bool isHost = VerifyHost(host);
680 SysTryReturn(NID_BASE_UTIL, isHost, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Host.", GetErrorMessage(E_INVALID_FORMAT));
688 Uri::SetPath(const Tizen::Base::String& path)
690 bool isPath = VerifyPath(path);
692 SysTryReturn(NID_BASE_UTIL, isPath, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Path.", GetErrorMessage(E_INVALID_FORMAT));
696 __encodedPath = path;
697 __path = Decode(path);
702 __encodedPath = Encode(path);
709 Uri::SetPort(int port)
711 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);
719 Uri::SetQuery(const Tizen::Base::String& query)
721 bool isQuery = VerifyUriChar(query);
723 SysTryReturn(NID_BASE_UTIL, isQuery, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Query.", GetErrorMessage(E_INVALID_FORMAT));
725 if (IsEncoded(query))
727 __encodedQuery = query;
728 __query = Decode(query);
733 __encodedQuery = Encode(query);
740 Uri::SetScheme(const Tizen::Base::String& scheme)
742 bool isScheme = VerifyScheme(scheme);
744 SysTryReturn(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
752 Uri::SetSchemeSpecificPart(const Tizen::Base::String& ssp)
754 bool isSsp = VerifyUriChar(ssp);
756 SysTryReturn(NID_BASE_UTIL, isSsp, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid SchemeSpecificPart.", GetErrorMessage(E_INVALID_FORMAT));
766 __encodedSsp = Encode(ssp);
773 Uri::SetUserInfo(const Tizen::Base::String& userInfo)
775 bool isUserInfo = VerifyUserInfo(userInfo);
777 SysTryReturn(NID_BASE_UTIL, isUserInfo, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid UserInfo.", GetErrorMessage(E_INVALID_FORMAT));
779 if (IsEncoded(userInfo))
781 __encodedUserInfo = userInfo;
782 __userInfo = Decode(userInfo);
786 __userInfo = userInfo;
787 __encodedUserInfo = Encode(userInfo);
794 Uri::ToString(void) const
799 if (!__scheme.IsEmpty())
801 strbuf.Append(__scheme);
807 strbuf.Append(__ssp);
811 if (!__host.IsEmpty())
814 strbuf.Append(L"//");
816 // Check the Userinfo
817 if (!__userInfo.IsEmpty())
819 strbuf.Append(__userInfo);
824 result re = E_SUCCESS;
825 re = __host.IndexOf(L':', 0, indexOf);
827 String openBracket(L"[");
828 String closeBracket(L"]");
830 bool start = __host.StartsWith(openBracket, 0);
831 bool end = __host.EndsWith(closeBracket);
833 bool needBracket = false;
834 if (!start && !end && re == E_SUCCESS)
848 strbuf.Append(__host);
859 strbuf.Append(__port);
862 else if (!__authority.IsEmpty())
864 strbuf.Append(L"//");
865 strbuf.Append(__authority);
867 // AppendAuthority end
869 if (!__path.IsEmpty())
871 strbuf.Append(__path);
874 if (!__query.IsEmpty())
877 strbuf.Append(__query);
880 // AppendSchemeSpecificPart end
882 //AppendFragment(strbuf, __fragment);
883 if (!__fragment.IsEmpty())
886 strbuf.Append(__fragment);
888 // AppendFragment end
893 ////////////////////////////////////////////////////////////////////////
896 // This method constructs an URI instance.
899 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& opaque, const Tizen::Base::String& authority,
900 const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port, const Tizen::Base::String& path,
901 const Tizen::Base::String& query,
902 const Tizen::Base::String& fragment)
904 result r = E_SUCCESS;
909 if (!scheme.IsEmpty())
911 // Check that an extracted scheme is satisfied with RFC2396.
912 bool isScheme = VerifyScheme(scheme);
913 SysTryReturnResult(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, "The scheme is invalid.");
915 r = strbuf.Append(scheme);
916 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the scheme.");
918 r = strbuf.Append(L':');
919 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L':'.");
922 r = AppendSchemeSpecificPart(strbuf, opaque, authority, userInfo, host, port, path, query);
923 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
925 r = AppendFragment(strbuf, fragment);
926 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
931 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to set the uri.");
937 Uri::AppendSchemeSpecificPart(Tizen::Base::String& strbuf, const Tizen::Base::String& opaque, const Tizen::Base::String& authority,
938 const Tizen::Base::String& userInfo, const Tizen::Base::String& host, int port,
939 const Tizen::Base::String& path,
940 const Tizen::Base::String& query) const
942 result r = E_SUCCESS;
944 if (!opaque.IsEmpty())
946 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(opaque), E_INVALID_FORMAT, "The opaque is invalid.");
947 r = strbuf.Append(opaque);
948 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append opaque.");
952 r = AppendAuthority(strbuf, authority, userInfo, host, port);
953 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the authority.");
957 SysTryReturnResult(NID_BASE_UTIL, VerifyPath(path), E_INVALID_FORMAT, "The path is invalid.");
958 r = strbuf.Append(path);
961 if (!query.IsEmpty())
963 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(query), E_INVALID_FORMAT, "The query is invalid.");
964 r = strbuf.Append(L'?');
965 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L'?'.");
967 r = strbuf.Append(query);
968 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the query.");
976 Uri::AppendFragment(Tizen::Base::String& strbuf, const Tizen::Base::String& fragment) const
978 if (!fragment.IsEmpty())
980 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(fragment), E_INVALID_FORMAT, "The fragment is invalid.");
982 result r = strbuf.Append(L'#');
983 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L'#'.");
985 r = strbuf.Append(fragment);
986 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the fragment.");
993 Uri::AppendAuthority(Tizen::Base::String& strbuf, const Tizen::Base::String& authority, const Tizen::Base::String& userInfo,
994 const Tizen::Base::String& host,
997 result r = E_SUCCESS;
999 String doubleSlash(L"//");
1001 if (!host.IsEmpty())
1004 SysTryReturnResult(NID_BASE_UTIL, VerifyHost(host), E_INVALID_FORMAT, "The host is invalid.");
1006 r = strbuf.Append(doubleSlash);
1007 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the doubleSlash.");
1009 // Check the Userinfo
1010 if (!userInfo.IsEmpty())
1012 SysTryReturnResult(NID_BASE_UTIL, VerifyUserInfo(userInfo), E_INVALID_FORMAT, "The userInfo is invalid.");
1013 r = strbuf.Append(userInfo);
1014 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the userInfo.");
1016 r = strbuf.Append(L'@');
1017 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L'@'.");
1021 result re = E_SUCCESS;
1022 re = host.IndexOf(L':', 0, indexOf);
1024 String openBracket(L"[");
1025 String closeBracket(L"]");
1027 bool start = host.StartsWith(openBracket, 0);
1028 bool end = host.EndsWith(closeBracket);
1030 bool needBracket = true;
1031 if (!start && !end && re == E_SUCCESS)
1037 needBracket = false;
1042 r = strbuf.Append(L'[');
1043 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L'['.");
1046 r = strbuf.Append(host);
1047 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the host.");
1051 r = strbuf.Append(L']');
1052 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L']'.");
1056 const int UNDEFINED_PORT = -1;
1059 r = strbuf.Append(L':');
1060 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append L':'.");
1062 r = strbuf.Append(port);
1063 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the port.");
1065 else if (port != UNDEFINED_PORT)
1067 return E_INVALID_FORMAT;
1070 else if (!authority.IsEmpty())
1072 r = strbuf.Append(doubleSlash);
1073 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the doubleSlash.");
1075 SysTryReturnResult(NID_BASE_UTIL, VerifyAuthority(authority), E_INVALID_FORMAT, "The authority is invalid.");
1076 r = strbuf.Append(authority);
1077 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to append the authority.");
1084 // This method breaks a given string into Uri components.
1085 // str : [scheme:]<scheme-specific-part>[#<fragment>]
1088 Uri::ParseUri(const Tizen::Base::String& str)
1090 result r = E_SUCCESS;
1091 wchar_t colon = L':';
1092 wchar_t sharp = L'#';
1095 int curIndex = 0; // points the current index
1096 int startFragment = 0;
1097 int lengthOfUri = str.GetLength();
1103 /////////////////////////////////////////////////////////////////
1104 // First, exract a scheme component from a given string.//
1105 ////////////////////////////////////////////////////////////////
1108 SysTryReturnResult(NID_BASE_UTIL, str[0] != L' ', E_INVALID_FORMAT, "Invalid Scheme.");
1110 // Get a index of ':'
1111 r = str.IndexOf(colon, 0, indexOf);
1112 if (indexOf >= 0 && r == E_SUCCESS)
1114 // There is a scheme componenet.
1116 r = str.SubString(0, indexOf, scheme);
1117 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1119 // Check that an extracted scheme is satisfied with RFC2396.
1120 SysTryReturnResult(NID_BASE_UTIL, VerifyScheme(scheme), E_INVALID_FORMAT, "Invalid Scheme.");
1128 // In case there is no scheme component, the Uri is a hierarchical URI.
1130 __hasScheme = false;
1133 ////////////////////////////////////////////////////////////////////////
1134 // Second, extract a scheme-specific-part from a given string.//
1135 ///////////////////////////////////////////////////////////////////////
1136 if (__hasScheme) // This URI has a scheme.
1138 startSsp = ++curIndex; // skip ':'
1139 SysTryReturnResult(NID_BASE_UTIL, startSsp < lengthOfUri, E_INVALID_FORMAT, "startSsp must be less than lengthOfUri.");
1141 if (str[startSsp] == '/')
1144 r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1145 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1147 SetAndEncodeAuthority(authority, path, query);
1150 r = str.SubString(startSsp, curIndex - startSsp, ssp);
1151 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1155 __ssp = Decode(ssp);
1161 __encodedSsp = Encode(ssp);
1170 r = str.IndexOf(sharp, curIndex, (int&)startFragment);
1171 if (startFragment > curIndex && r == E_SUCCESS)
1173 r = str.SubString(startSsp, startFragment - curIndex, ssp);
1174 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1176 else if (r == E_OBJ_NOT_FOUND)
1179 r = str.SubString(startSsp, lengthOfUri - curIndex, ssp);
1180 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1187 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(ssp), E_INVALID_FORMAT, "Invalid Opaque URI.");
1189 // Opaque URI is not subject to further parsing.
1192 __ssp = Decode(ssp);
1198 __encodedSsp = Encode(ssp);
1201 if (startFragment == 0)
1206 // Check the fragment
1210 r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1211 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1213 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(fragment), E_INVALID_FORMAT, "Invalid Fragment.");
1215 if (IsEncoded(fragment))
1217 __fragment = Decode(fragment);
1218 __encodedFragment = fragment;
1222 __fragment = fragment;
1223 __encodedFragment = Encode(fragment);
1229 else // This URI doesn't have a Scheme. - www.samsung.com[#ocean]
1233 r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1234 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1237 r = str.SubString(startSsp, curIndex - startSsp, ssp);
1238 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1242 __ssp = Decode(ssp);
1248 __encodedSsp = Encode(ssp);
1251 SetAndEncodeAuthority(authority, path, query);
1254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1255 // Parse an authority component. The authority component is registry_based or server_based authority.//
1256 // Server_based authority consists of user-info, host and port.//
1257 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1258 if (!authority.IsEmpty())
1265 r = ParseAuthority(authority, curIndex, newAuth, userInfo, host, port);
1266 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1268 if (!userInfo.IsEmpty())
1270 if (IsEncoded(userInfo))
1272 __userInfo = Decode(userInfo);
1273 __encodedUserInfo = userInfo;
1277 __userInfo = userInfo;
1278 __encodedUserInfo = Encode(userInfo);
1282 if (!host.IsEmpty())
1290 /////////////////////////////////////////////////
1291 // Finally, extract a fragment component //
1292 ////////////////////////////////////////////////
1293 startFragment = curIndex;
1294 if (startFragment < lengthOfUri && str[startFragment] == '#')
1299 if (startFragment < lengthOfUri)
1301 r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1302 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1305 SysTryReturnResult(NID_BASE_UTIL, VerifyUriChar(fragment), E_INVALID_FORMAT, "Invalid Fragment.");
1307 if (IsEncoded(fragment))
1309 __fragment = Decode(fragment);
1310 __encodedFragment = fragment;
1314 __fragment = fragment;
1315 __encodedFragment = Encode(fragment);
1318 curIndex += fragment.GetLength() + 1; // skip '#'
1321 SysTryReturnResult(NID_BASE_UTIL, curIndex >= lengthOfUri, E_INVALID_FORMAT, "curIndex must be greater than or equal to lengthOfUri.");
1327 Uri::SetAndEncodeAuthority(const Tizen::Base::String& authority, const Tizen::Base::String& path, const Tizen::Base::String& query)
1329 bool isEncoded = false;
1332 if (!authority.IsEmpty())
1334 isEncoded = IsEncoded(authority);
1337 __authority = Decode(authority);
1338 __encodedAuth = authority;
1342 __authority = authority;
1343 __encodedAuth = Encode(authority);
1348 if (!path.IsEmpty())
1350 isEncoded = IsEncoded(path);
1353 __path = Decode(path);
1354 __encodedPath = path;
1359 __encodedPath = Encode(path);
1364 if (!query.IsEmpty())
1366 isEncoded = IsEncoded(query);
1369 __query = Decode(query);
1370 __encodedQuery = query;
1375 __encodedQuery = Encode(query);
1381 Uri::ParseHierarchicalUri(const Tizen::Base::String& str, int startSsp, Tizen::Base::String& authority, Tizen::Base::String& path,
1382 Tizen::Base::String& query,
1385 result r = E_SUCCESS;
1386 int curIndex = startSsp;
1389 String queSharp(L"?#");
1390 String doubleSlash(L"//");
1395 bool startsWith = str.StartsWith(doubleSlash, curIndex);
1401 String special(L"/?#");
1402 int index = Scan(str, curIndex, special);
1403 if (index > curIndex)
1405 r = str.SubString(curIndex, index - curIndex, authority);
1406 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1408 else if (index >= str.GetLength())
1410 r = E_INVALID_FORMAT;
1414 curIndex += authority.GetLength();
1415 if (curIndex == str.GetLength())
1422 queSharp.IndexOf(str[0], 0, temp);
1429 position = Scan(str, curIndex, queSharp);
1431 if (position == curIndex && authority.GetLength() == 0)
1433 // If both authority and path are empty, it returns error.
1434 r = E_INVALID_FORMAT;
1439 r = str.SubString(curIndex, position - curIndex, tempPath);
1440 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1442 SysTryReturnResult(NID_BASE_UTIL, VerifyPath(tempPath), E_INVALID_FORMAT, "Invalid Path.");
1446 curIndex = position;
1448 // If there is no query after question-mark "?", this method returns E_SUCCESS and saves empty string as query.
1449 if (curIndex < str.GetLength() && str[curIndex] == L'?' && ++curIndex < str.GetLength())
1454 r = str.IndexOf(L'#', curIndex, indexOf);
1457 r = str.SubString(curIndex, indexOf - curIndex, tempQuery);
1458 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1460 else if (r == E_OBJ_NOT_FOUND)
1462 r = str.SubString(curIndex, tempQuery);
1463 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1467 SysTryCatch(NID_BASE_UTIL, false, , r, "[%s] Propagating.", GetErrorMessage(r));
1470 bool isQuery = VerifyUriChar(tempQuery);
1475 curIndex += query.GetLength();
1484 // This method parses an authority component.
1485 // This component is server based or registrty authority.
1488 Uri::ParseAuthority(const Tizen::Base::String& str, int curIndex, Tizen::Base::String& newAuth, Tizen::Base::String& userInfo,
1489 Tizen::Base::String& host,
1492 result r = E_SUCCESS;
1494 bool isServerChar = VerifyServerAuthority(str);
1495 bool isRegChar = VerifyRegistryAuthority(str);
1497 if (isRegChar && !isServerChar)
1505 r = ParseServerAuthority(str, userInfo, host, port);
1506 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1520 // This method parses a server_based authority componenet.
1521 // server_based authority : [user-info@]<host>[:port]
1524 Uri::ParseServerAuthority(const Tizen::Base::String& str, Tizen::Base::String& user, Tizen::Base::String& host, int& port)
1526 result r = E_SUCCESS;
1532 r = str.IndexOf(L'@', 0, indexOf);
1535 r = str.SubString(0, indexOf, userInfo);
1536 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1538 SysTryReturnResult(NID_BASE_UTIL, VerifyUserInfo(userInfo), E_INVALID_FORMAT, "Invalid UserInfo.");
1542 index += indexOf + 1; // skip '@'
1545 // IPv4 or IPv6 address
1548 // IPv6 not supported
1549 return E_INVALID_FORMAT;
1556 r = ParseIpv4(str, index, count); // length of ipv4 string
1557 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1561 r = str.SubString(0, count, ip4);
1562 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1568 // This is a host name
1571 r = ParseHostName(str, index, tmpHost);
1572 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1585 index += host.GetLength();
1586 if (index < str.GetLength() && str[index] == L':')
1591 r = str.IndexOf(L'/', index, indexOf);
1594 r = str.SubString(index, indexOf - index, tmpPort);
1595 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1597 else if (r == E_OBJ_NOT_FOUND)
1599 r = str.SubString(index, tmpPort);
1600 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1603 int tmpPortLen = tmpPort.GetLength();
1604 for (int i = 0; i < tmpPortLen; i++)
1606 wchar_t ch = tmpPort[i];
1607 SysTryReturnResult(NID_BASE_UTIL, Character::IsDigit(ch), E_INVALID_FORMAT, "The character is not a digit.");
1609 index += tmpPort.GetLength();
1612 r = Integer::Parse(tmpPort, 10, ret);
1620 SysTryReturnResult(NID_BASE_UTIL, index >= str.GetLength(), E_INVALID_FORMAT, "index must be greater than or equal to str.GetLength().");
1626 // This method parses a host name and returns a host name as an out-param.
1629 Uri::ParseHostName(const Tizen::Base::String& str, int index, Tizen::Base::String& host)
1631 result r = E_SUCCESS;
1634 int strLen = str.GetLength();
1635 r = str.IndexOf(L':', index, indexOf);
1638 r = str.SubString(index, indexOf - index, host);
1639 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1641 else if (r == E_OBJ_NOT_FOUND)
1644 r = str.SubString(index, host);
1645 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1648 for (int i = 0; i < strLen; i++)
1652 wchar_t ch1 = str[i + 1];
1653 wchar_t ch2 = str[i + 2];
1654 bool escape = IsEscapedChar(ch1, ch2);
1665 SysTryReturnResult(NID_BASE_UTIL, VerifyHost(host), E_INVALID_FORMAT, "Invalid Host.");
1671 // This method parses an IPv6 address.
1672 // This method covers all and only the following cases :
1674 // hex_seq : IPv4 address
1676 // hex_seq :: hex_seq
1677 // hex_seq :: hex_seq : IPv4 address
1679 // :: hex_seq : IPv4 address
1682 // Additionally, we constrain the IPv6 address as follows :
1683 // 1) IPv6 address without compressed zeros should contain exactly 16 bytes.
1684 // 2) IPv6 address with comporessed zeros should contain less than 16 bytes.
1687 Uri::ParseIpv6(const Tizen::Base::String& ip6, Tizen::Base::String& outIpv6)
1689 // TODO : It will be implemented
1694 Uri::ParseIpv4(const Tizen::Base::String& str, int start, int& count)
1696 result r = E_SUCCESS;
1700 r = str.SubString(start, ipHost);
1701 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1703 // Set the index as an end position of ipv4
1704 count = ipHost.GetLength();
1706 StringTokenizer strTok(ipHost, dot);
1708 // Check that a given string consists of digit or dot.
1709 int ipHostLen = ipHost.GetLength();
1710 for (int i = 0; i < ipHostLen; i++)
1712 wchar_t ch = ipHost[i];
1713 if (ch != L'.' && !(Character::IsDigit(ch)))
1720 while (strTok.HasMoreTokens())
1724 r = strTok.GetNextToken(token);
1725 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1728 r = Integer::Parse(token, 10, ret);
1729 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
1731 // each part of IPv4 address cannot exceed 255.
1732 if (ret < 0 || ret > 255)
1734 return E_INVALID_FORMAT;
1741 //////////////////////////////////////////////////////////////////////////////////////////
1742 // Verify a component
1745 // This method verifies whether a given string is scheme format or not.
1746 // The scheme has an combination of alphabet, digit, plus(+), dash(-) and period(.).
1747 // The first character must be an alphabet.
1750 Uri::VerifyScheme(const Tizen::Base::String& str) const
1752 bool isAlpha = Character::IsLetter(str[0]);
1758 int strLen = str.GetLength();
1759 for (int i = 1; i < strLen; i++)
1761 if ((str[i] != '+') && (str[i] != '-') && (str[i] != '.') && (!Character::IsAlphaNumeric(str[i])) &&
1762 (!Character::IsDigit(str[i])))
1772 Uri::VerifyAuthority(const Tizen::Base::String& str) const
1774 bool isReg = VerifyRegistryAuthority(str);
1775 bool isServer = VerifyServerAuthority(str);
1777 if (isReg || isServer)
1788 Uri::VerifyHost(const Tizen::Base::String& str) const
1790 int length = str.GetLength();
1792 for (int i = 0; i < length; i++)
1794 wchar_t ch = str[i];
1795 if (ch != L'-' && ch != L'.' && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch))
1802 if (i == 0 || i == length - 1)
1812 Uri::VerifyPath(const Tizen::Base::String& str) const
1814 result r = E_SUCCESS;
1815 String reserved(L":@&=+$\",;/");
1817 int strLen = str.GetLength();
1818 for (int i = 0; i < strLen; i++)
1821 r = reserved.IndexOf(str[i], 0, indexOf);
1825 wchar_t ch1 = str[i + 1];
1826 wchar_t ch2 = str[i + 2];
1827 bool escape = IsEscapedChar(ch1, ch2);
1833 else if (str[i] == L' ') // add a space
1836 else if (r == E_OBJ_NOT_FOUND && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
1838 // Check the unicode letter
1839 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
1849 Uri::VerifyUserInfo(const Tizen::Base::String& str) const
1851 String reserved(L";:&=+$,");
1852 int strLen = str.GetLength();
1854 for (int i = 0; i < strLen; i++)
1857 reserved.IndexOf(str[i], 0, indexOf);
1861 wchar_t ch1 = str[i + 1];
1862 wchar_t ch2 = str[i + 2];
1863 bool escape = IsEscapedChar(ch1, ch2);
1869 else if (str[i] == L' ') // add a space
1872 else if (indexOf < 0 && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
1874 // Check the unicode letter
1875 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
1885 Uri::VerifyUriChar(const Tizen::Base::String& str) const
1887 result r = E_SUCCESS;
1888 // [ ] removed form "reserved"
1889 // RFC 2732: (Format for Literal IPv6 Addresses in URLs) is not supported for now.
1890 String reserved(L";/?:@&=+$,");
1891 String delims(L"<>#\""); // <, >, #, %, "
1892 int strLen = str.GetLength();
1894 for (int i = 0; i < strLen; i++)
1896 wchar_t ch = str[i];
1899 r = delims.IndexOf(ch, 0, indexOf); // check delims
1905 r = reserved.IndexOf(ch, 0, indexOf);
1908 wchar_t ch1 = str[i + 1];
1909 wchar_t ch2 = str[i + 2];
1910 bool escape = IsEscapedChar(ch1, ch2);
1916 else if (IsControlChar(ch)) // control
1920 else if ((ch != ' ') && (ch < 0x80) && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch) && !IsMark(ch) &&
1923 // Check the unicode letter
1924 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
1934 // This method checks that a given string consists of only server_based characters.
1935 // @return True if a string consists of only server_based characters.
1938 Uri::VerifyServerAuthority(const Tizen::Base::String& str) const
1940 result r = E_SUCCESS;
1941 String special(L".:@[]");
1944 int strLen = str.GetLength();
1945 // Server based authority consists of alphabets, digits, marks(-_!.~*'()), escaped(%hexhex), and ;:&=+$'',@[]
1946 for (int i = 0; i < strLen; i++)
1948 wchar_t ch = str[i];
1949 r = special.IndexOf(ch, 0, indexOf);
1951 if (ch == L'-' || IsUserInfo(ch) || r == E_SUCCESS)
1953 // This string is a server_based authority character
1957 if (!IsEscapedChar(str[i + 1], str[i + 2]))
1965 // Check the unicode letter
1966 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
1976 // This method checks that a given string consists of only registry_based characters.
1977 // @return True if a string consists of only registry_based characters.
1980 Uri::VerifyRegistryAuthority(const Tizen::Base::String& str) const
1982 result r = E_SUCCESS;
1983 String specialChar(L"@%;:&=+$,");
1986 int strLen = str.GetLength();
1987 for (int i = 0; i < strLen; i++)
1989 wchar_t ch = str[i];
1990 r = specialChar.IndexOf(ch, 0, indexOf);
1992 if (!(Character::IsAlphaNumeric(ch)) && !(Character::IsDigit(ch)) && !IsMark(ch) && !(indexOf >= 0 && r == E_SUCCESS))
1994 // Check the unicode letter
1995 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2000 else if (ch == L'%')
2002 if (!IsEscapedChar(str[i + 1], str[i + 2]))
2012 //////////////////////////////////////////////////////////////////////
2013 // Utility methods such as IsUserInfo, IsMark and so on.
2016 // This method returns true if a given wchar_t is a user-info character.
2017 // user-info char : alphabet, digit, -_.!~*'(), ;:&=+$,
2020 Uri::IsUserInfo(wchar_t mch) const
2022 result r = E_SUCCESS;
2023 String specialChar(L";:&=+$,");
2025 if (mch == L'%' || Character::IsAlphaNumeric(mch) || Character::IsDigit(mch) || IsMark(mch))
2031 r = specialChar.IndexOf(mch, 0, indexOf);
2032 if (indexOf >= 0 && r == E_SUCCESS)
2041 // This method returns true if a given wchar_t is a mark character.
2042 // mark char : -_.!~*'()
2045 Uri::IsMark(wchar_t mch) const
2047 result r = E_SUCCESS;
2048 String mark(L"-_.!~*'()");
2052 r = mark.IndexOf(mch, 0, indexOf);
2053 if (indexOf >= 0 && r == E_SUCCESS)
2062 Uri::IsControlChar(wchar_t ch) const
2064 if ((ch <= 0x009F) && ((ch <= 0x001F) || (ch >= 0x007F)))
2075 Uri::IsEscapedChar(wchar_t ch1, wchar_t ch2) const
2077 if ((ch1 >= L'a' && ch1 <= L'f') || (ch1 >= L'A' && ch1 <= L'F') || Character::IsDigit(ch1))
2079 if ((ch2 >= L'a' && ch2 <= L'f') || (ch2 >= L'A' && ch2 <= L'F') || Character::IsDigit(ch2))
2088 ////////////////////////////////////////////////////////////////////////
2089 // Private operations
2092 // This method finds the first character in the stop-string.
2095 Uri::Scan(const Tizen::Base::String& str, int start, const Tizen::Base::String& stopString)
2097 result r = E_SUCCESS;
2099 int strLen = str.GetLength();
2100 while (index < strLen)
2103 wchar_t ch = str[index];
2105 r = stopString.IndexOf(ch, 0, indexOf);
2117 // This method convers a component represented by UTF8 to a component represented by Unicode.
2120 Uri::Decode(const Tizen::Base::String& str)
2127 result r = E_SUCCESS;
2129 int len = str.GetLength();
2136 if (str[index] != L'%')
2138 decodedBuf.Append(str[index]);
2144 r = bb.Construct(20);
2149 r = str.SubString(index + 1, 2, utf8Str);
2152 r = Short::Parse(utf8Str, 16, ret);
2153 SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, str, r, "[%s] Propagating.", GetErrorMessage(r));
2155 r = bb.SetByte((byte) ret);
2159 if (index >= len || str[index] != '%')
2167 r = StringUtil::Utf8ToString((char*) bb.GetPointer(), unicode);
2171 decodedBuf.Append(L'?');
2175 decodedBuf.Append(unicode);
2183 // This method converts a component represented by Unicode to a component represented by UTF8.
2186 Uri::Encode(const Tizen::Base::String& str) const
2194 WcharBuffer wchar_tBuf;
2196 result r = wchar_tBuf.Construct(str.GetLength() + 1);
2200 r = wchar_tBuf.SetArray(str.GetPointer(), 0, str.GetLength());
2201 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2203 r = wchar_tBuf.Set(L'\0');
2204 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2208 std::unique_ptr< char[] > pChar(new (std::nothrow) char[10]);
2209 SysTryReturn(NID_BASE_UTIL, pChar != null, str, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
2210 memset(pChar.get(), 0, 10);
2212 while (wchar_tBuf.HasRemaining())
2215 r = wchar_tBuf.Get(mch);
2216 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2223 if (mch >= 0x0080 || IsControlChar(mch))
2232 r = tmpBuf.Construct(2);
2233 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2235 r = tmpBuf.Set(mch);
2236 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2238 r = tmpBuf.Set(L'\0');
2239 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2243 tempStr = tmpBuf.GetPointer();
2244 std::unique_ptr< ByteBuffer > pBuf(StringUtil::StringToUtf8N(tempStr));
2245 SysTryReturn(NID_BASE_UTIL, pBuf != null, str, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
2247 while (bbPos < pBuf->GetLimit() - 1) // null
2250 r = pBuf->GetByte(bbPos, b);
2251 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2253 sprintf(pChar.get() + (bbPos * 3), "%%%x", (int) b);
2257 r = StringUtil::Utf8ToString(pChar.get(), unicode);
2258 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2260 r = unicode.ToUpper(upper);
2262 r = strbuf.Append(upper);
2263 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2265 else if (mch == 0x20)
2267 String unicode(L"%20");
2268 r = strbuf.Append(unicode);
2269 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2271 else // ASCII character
2273 r = strbuf.Append(mch);
2274 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2278 SetLastResult(E_SUCCESS);
2283 Uri::AppendEscape(Tizen::Base::String& strbuf, byte b)
2288 result r = strbuf.Append(L'%');
2289 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2291 bt1 = (b >> 4) & 0x0f;
2292 r = strbuf.Append(HEX_DIGITS[bt1]);
2293 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2295 bt2 = (b >> 0) & 0x0f;
2296 r = strbuf.Append(HEX_DIGITS[bt2]);
2297 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2302 // This method compares str1 and str2 after replacing all uppercase letters with their lowercase letters
2304 Uri::Compare(const Tizen::Base::String& str1, const Tizen::Base::String& str2) const
2313 // Both pStr1 and pStr2 are null
2318 // pStr1 is null but pStr isn't.
2326 // pStr1 is not null but pStr2 is null
2331 // Replace all uppercase letters with their lowercase letters
2332 str1.ToLower(small1);
2333 str2.ToLower(small2);
2335 return small1.CompareTo(small2);
2339 //////////////////////////////////////////////////////////////////////////////////////////
2343 Uri::InternalNormalize(const Tizen::Base::String& path)
2345 result r = E_SUCCESS;
2351 std::unique_ptr< WcharBuffer > pBuf(StringUtil::StringToMbN(path, 0, path.GetLength()));
2357 // Get the number of segments from a given path
2358 segCount = GetNumberOfSegments(path);
2364 // Get the first index of each segment
2365 std::unique_ptr< int[] > pSegments(new (std::nothrow) int[segCount]);
2366 SplitIntoSegments(*pBuf, pSegments.get(), segCount);
2369 RemoveDots(*pBuf, pSegments.get(), segCount, path.GetLength());
2371 // Prevent scheme-name confusion
2372 AddLeadingDot(*pBuf, pSegments.get(), segCount);
2374 // Join the remaining segments and returns the result
2375 join = Join(*pBuf, pSegments.get(), segCount);
2377 r = StringUtil::MbToString(*pBuf, str);
2378 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), L"", E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG));
2386 r = str.SubString(0, join - 1, joinedStr);
2387 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), L"", E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG));
2389 if (joinedStr.Equals(path))
2391 return path; // String was already normalized.
2394 SetLastResult(E_SUCCESS);
2399 // This method returns the number of segments from a given path.
2402 Uri::GetNumberOfSegments(const Tizen::Base::String& path) const
2406 int endIndex = path.GetLength() - 1;
2409 // find the index of non-slash character
2410 while (p <= endIndex)
2412 if (path[p] != L'/')
2424 while (p <= endIndex)
2426 // Looking at '.' or '..'
2427 if ((path[p] == L'.') && ((p == endIndex) || ((path[p + 1] == L'/') ||
2428 ((path[p + 1] == L'.') && ((p + 1 == endIndex) || (path[p + 2] == L'/'))))))
2434 // Find the beginning index of next segment
2435 while (p <= endIndex)
2437 if (path[p++] != L'/')
2442 // skip redundant slashes
2443 while (p <= endIndex)
2445 if (path[p] != L'/')
2469 Uri::SplitIntoSegments(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
2471 int end = StringUtil::GetStringLengthInMb(mb);
2473 //int end = mb.GetLimit() - 1;
2475 int index = 0; // the index of current segment
2477 // skip initial slash
2490 if (index >= segCount)
2496 segments[index] = p;
2500 // Find beginning of next segment
2503 if (mb[p++] != L'/')
2509 // skip redundant slash
2522 // index must be equal to the length of segments[]
2526 Uri::RemoveDots(const Tizen::Base::WcharBuffer& mb, int* segments, int segCount, int length)
2530 for (int i = 0; i < segCount; i++)
2532 int dots = 0; // number of dots found
2534 // Find next occurrence of "." or "..
2537 int p = segments[i];
2545 else if (mb[p + 1] == L'\0')
2550 else if ((mb[p + 1] == L'.') && ((p + 1 == end) || (mb[p + 2] == L'\0')))
2558 while (i < segCount);
2560 if ((i > segCount) || (dots == 0))
2565 if (dots == 1 && i < segCount)
2567 // Remove this occurrence of '.'
2572 // If there is a preceding non-".." segment, remove both that segment and this occurrence of "..";
2573 // otherwise, leave this ".." segment as-is.
2575 for (j = i - 1; j >= 0; j--)
2577 if (segments[j] != -1)
2585 int q = segments[j];
2586 if (!((mb[q] == '.') && (mb[q + 1] == '.') && (mb[q + 2] == '\0')))
2597 Uri::AddLeadingDot(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
2601 // The path is absolute
2605 int firstSegment = 0; // Index of first segment
2606 while (firstSegment < segCount)
2608 if (segments[firstSegment] >= 0)
2615 if ((firstSegment >= segCount) || (firstSegment == 0))
2617 // The path is empty, or else the original first segment survived,
2618 // in which case we already know that no leading "." is needed
2622 int p = segments[firstSegment];
2623 while ((mb[p] != L':') && (mb[p] != L'\0') && (p < mb.GetLimit()))
2628 if (mb[p] == L'\0' || p >= mb.GetLimit())
2630 // No colon in first segment, so no "." needed
2634 // At this point we know that the first segment is unused,
2635 // hence we can insert a "." segment at that position
2641 // Join the segments in the given path according to the given segment-index array,
2642 // ignoring those segments whose index entries have been set to -1, and inserting slashes as needed.
2643 // Return the length of the resulting path.
2646 // segs[i] == -1 implies segment i is to be ignored
2647 // path computed by split, as above, with '\0' having replaced '/'
2650 // path[0] .. path[return value] == Resulting path
2653 Uri::Join(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
2656 int end = mb.GetLimit() - 1;
2661 // Restore initial slash for absolute paths
2665 for (int i = 0; i < segCount; i++)
2667 int q = segments[i];
2670 // ignore this segment
2677 while ((p <= end) && (mb[p] != L'\0'))
2683 // Preserve trailing slash
2689 while ((q <= end) && mb[q] != L'\0')
2695 // Preserve trailing slash
2700 if (p == mb.GetLimit())
2702 result r = E_SUCCESS;
2703 r = mb.SetLimit(p + 1);
2714 ///////////////////////////////////////////////////////////////////////////////////////////////
2718 // This method implements Uri resolution in RFC2396 5.2
2721 Uri::Resolve(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
2723 result r = E_SUCCESS;
2725 // If either baseUri or childUri is opaque, then resultUri is childUri
2726 if (baseUri.IsOpaque() || childUri.IsOpaque())
2728 resultUri = childUri;
2732 // 5.2(2) If scheme, authority, path, and query of childUri are null,
2733 // the components of baseUri are copied to components of resultUri.
2734 if ((childUri.__scheme.IsEmpty()) && (childUri.__authority.IsEmpty()) && (childUri.__path.IsEmpty())
2735 && (!childUri.__fragment.IsEmpty()) && (childUri.__query.IsEmpty()))
2737 if ((!baseUri.__fragment.IsEmpty()) && (childUri.__fragment.GetLength() == baseUri.__fragment.GetLength()))
2739 resultUri = baseUri;
2743 if (!baseUri.__scheme.IsEmpty())
2745 r = resultUri.SetScheme(baseUri.__scheme);
2746 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2749 if (!baseUri.__authority.IsEmpty())
2751 r = resultUri.SetAuthority(baseUri.__authority);
2752 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2755 if (!baseUri.__userInfo.IsEmpty())
2757 r = resultUri.SetUserInfo(baseUri.__userInfo);
2758 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2761 if (!baseUri.__host.IsEmpty())
2763 r = resultUri.SetHost(baseUri.__host);
2764 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2767 resultUri.SetPort(baseUri.__port);
2769 if (!baseUri.__path.IsEmpty())
2771 r = resultUri.SetPath(baseUri.__path);
2772 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2775 if (!childUri.__fragment.IsEmpty())
2777 r = resultUri.SetFragment(childUri.__fragment);
2778 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2781 if (!baseUri.__query.IsEmpty())
2783 r = resultUri.SetQuery(baseUri.__query);
2784 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2790 // 5.2(3) child is an absolute URI
2791 if (!childUri.__scheme.IsEmpty())
2793 resultUri = childUri;
2797 if (!baseUri.__scheme.IsEmpty())
2799 r = resultUri.SetScheme(baseUri.__scheme);
2800 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2803 if (!childUri.__query.IsEmpty())
2805 r = resultUri.SetQuery(childUri.__query);
2806 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2809 if (!childUri.__fragment.IsEmpty())
2811 r = resultUri.SetFragment(childUri.__fragment);
2812 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2816 if (childUri.__authority.IsEmpty())
2818 if (!baseUri.__authority.IsEmpty())
2820 r = resultUri.SetAuthority(baseUri.__authority);
2821 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2824 if (!baseUri.__host.IsEmpty())
2826 r = resultUri.SetHost(baseUri.__host);
2827 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2830 if (!baseUri.__userInfo.IsEmpty())
2832 r = resultUri.SetUserInfo(baseUri.__userInfo);
2833 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2836 resultUri.SetPort(baseUri.__port);
2839 String encodedPath = childUri.__encodedPath;
2840 if (!encodedPath.IsEmpty())
2842 resolve = childUri.__encodedPath;
2845 if ((!resolve.IsEmpty()) && (resolve[0] == L'/'))
2847 // 5.2(5) child uri's path is absolute
2848 if (!encodedPath.IsEmpty())
2850 r = resultUri.SetPath(encodedPath);
2851 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2856 String encPath = baseUri.__encodedPath;
2857 if (!encPath.IsEmpty())
2859 // 5.2(6) Resolve relative path
2860 String relPath = ResolvePath(encPath, resolve, baseUri.IsAbsolute());
2861 if (relPath.IsEmpty())
2863 return GetLastResult();
2866 r = resultUri.SetPath(relPath);
2867 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2873 if (!childUri.__authority.IsEmpty())
2875 r = resultUri.SetAuthority(childUri.__authority);
2876 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2879 if (!childUri.__host.IsEmpty())
2881 r = resultUri.SetHost(childUri.__host);
2882 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2885 if (!childUri.__userInfo.IsEmpty())
2887 r = resultUri.SetUserInfo(childUri.__userInfo);
2888 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2891 resultUri.SetPort(childUri.__port);
2893 if (!childUri.__path.IsEmpty())
2895 r = resultUri.SetPath(childUri.__path);
2896 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2905 Uri::ResolvePath(const String& basePath, const String& childPath, bool isAbsolute)
2907 result r = E_SUCCESS;
2911 r = basePath.LastIndexOf(L'/', basePath.GetLength() - 1, indexOf);
2913 int len = childPath.GetLength();
2917 if (indexOf >= 0 && r == E_SUCCESS)
2919 r = basePath.SubString(0, indexOf + 1, path);
2920 SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, String(), r, "[%s] Propagating.", GetErrorMessage(r));
2931 r = basePath.SubString(0, indexOf + 1, tmpath);
2932 SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, String(), r, "[%s] Propagating.", GetErrorMessage(r));
2934 r = strbuf.Append(tmpath);
2935 SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, String(), r, "[%s] Propagating.", GetErrorMessage(r));
2938 r = strbuf.Append(childPath);
2939 SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, String(), r, "[%s] Propagating.", GetErrorMessage(r));
2944 return InternalNormalize(path);
2947 //////////////////////////////////////////////////////////////////////////
2950 Uri::Relativize(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
2952 result r = E_SUCCESS;
2954 // If either base URI or child URI is opaque, result URI is the childUri.
2955 if (baseUri.IsOpaque() || childUri.IsOpaque())
2957 resultUri = childUri;
2961 int ret1 = Compare(baseUri.__scheme, childUri.__scheme);
2964 if (!baseUri.__authority.IsEmpty() && !childUri.__authority.IsEmpty())
2966 equal = EqualsComponent(baseUri.__authority, childUri.__authority);
2969 if ((ret1 != 0) || (!equal))
2971 resultUri = childUri;
2975 String basePath = InternalNormalize(baseUri.__path);
2976 String childPath = InternalNormalize(childUri.__path);
2978 if (basePath.Equals(childPath) == false)
2983 bool endWith = basePath.EndsWith(slash);
2986 String strbuf(basePath);
2988 r = strbuf.Append(slash);
2989 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
2998 bool startsWith = childPath.StartsWith(basePath, 0);
3002 resultUri = childUri;
3008 r = childPath.SubString(basePath.GetLength(), path);
3009 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_SUCCESS, "Translating [%s] into [%s].", GetErrorMessage(r), GetErrorMessage(E_SUCCESS));
3011 r = resultUri.SetPath(path);
3012 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
3014 if (!childUri.__query.IsEmpty())
3016 r = resultUri.SetQuery(childUri.__query);
3017 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
3020 if (!childUri.__fragment.IsEmpty())
3022 r = resultUri.SetFragment(childUri.__fragment);
3023 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Propagating.");
3030 // This method compares two components. If a component is encoded,
3031 // then its raw component is compared with another component.
3034 Uri::EqualsComponent(const Tizen::Base::String& comp1, const Tizen::Base::String& comp2)
3036 result r = E_SUCCESS;
3043 if (comp1.GetLength() != comp2.GetLength())
3049 r = comp1.IndexOf(L'%', 0, indexOf);
3050 if (r == E_OBJ_NOT_FOUND)
3052 return comp1.Equals(comp2);
3055 int len = comp1.GetLength();
3056 for (int i = 0; i < len; )
3058 wchar_t c1 = (comp1)[i];
3059 wchar_t c2 = (comp2)[i];
3071 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3077 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3089 Uri::IsEncoded(const Tizen::Base::String& str) const
3091 int strLen = str.GetLength();
3092 for (int i = 0; i < strLen; i++)
3094 wchar_t ch = str[i];
3095 if (ch >= 0x0080 || ch == L' ' || IsControlChar(ch))
3109 __authority.Clear();
3119 // Encoded Component
3120 __encodedAuth.Clear();
3121 __encodedFragment.Clear();
3122 __encodedPath.Clear();
3123 __encodedQuery.Clear();
3124 __encodedSsp.Clear();
3126 }}} // Tizen::Base::Utility