2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FBaseUtilUri.cpp
20 * @brief This is the implementation file for Uri class.
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>
37 namespace Tizen { namespace Base { namespace Utility
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'};
43 /////////////////////////////////////////////////////////////////////////////////
55 Uri::Uri(const Uri& uri)
69 Uri::SetUri(const Uri& uri)
71 __scheme = uri.__scheme;
73 __authority = uri.__authority;
75 __fragment = uri.__fragment;
77 __userInfo = uri.__userInfo;
78 __query = uri.__query;
82 __encodedAuth = uri.__encodedAuth;
83 __encodedFragment = uri.__encodedFragment;
84 __encodedPath = uri.__encodedPath;
85 __encodedQuery = uri.__encodedQuery;
86 __encodedSsp = uri.__encodedSsp;
87 __encodedUserInfo = uri.__encodedUserInfo;
90 __hasScheme = uri.__hasScheme;
91 __ipv6ByteCount = uri.__ipv6ByteCount;
96 Uri::SetUri(const Tizen::Base::String& str)
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));
102 result r = ParseUri(str);
113 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& ssp, const Tizen::Base::String& fragment)
117 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
118 return SetUri(scheme, ssp, empty, empty, empty, -1, empty, empty, fragment);
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)
129 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
130 return SetUri(scheme, empty, empty, userInfo, host, port, path, query, fragment);
135 Uri::SetUri(const Tizen::Base::String& scheme, const Tizen::Base::String& host, const Tizen::Base::String& path,
136 const Tizen::Base::String& fragment)
140 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
141 return SetUri(scheme, empty, empty, empty, host, -1, path, L"", fragment);
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)
152 // scheme, ssp(opaquePart), authority, user-info, host, port, path, query, fragment
153 return SetUri(scheme, empty, authority, empty, empty, -1, path, query, fragment);
157 ////////////////////////////////////////////////////////////////////////////////
161 Uri::operator =(const Uri& rhs)
171 ////////////////////////////////////////////////////////////////////////////////
175 Uri::GetAuthority(void) const
182 Uri::GetFragment(void) const
189 Uri::GetHost(void) const
196 Uri::GetPath(void) const
203 Uri::GetPort(void) const
210 Uri::GetQuery(void) const
217 Uri::GetScheme(void) const
224 Uri::GetSchemeSpecificPart(void) const
231 Uri::GetUserInfo(void) const
238 Uri::GetEncodedAuthority(void) const
240 return __encodedAuth;
245 Uri::GetEncodedFragment(void) const
247 return __encodedFragment;
252 Uri::GetEncodedPath(void) const
254 return __encodedPath;
259 Uri::GetEncodedQuery(void) const
261 return __encodedQuery;
266 Uri::GetEncodedSchemeSpecificPart(void) const
273 Uri::GetEncodedUserInfo(void) const
275 return __encodedUserInfo;
280 Uri::IsAbsolute(void) const
282 // If the URI has a scheme, then it is an absolute URI.
295 Uri::IsOpaque(void) const
297 String scheme = GetScheme();
298 String ssp = GetSchemeSpecificPart();
300 if (scheme.IsEmpty())
324 Uri::GetEncodedString(void) const
329 if (!__scheme.IsEmpty())
331 strbuf.Append(__scheme);
335 //AppendSchemeSpecificPart(strbuf, __encodedSsp, __encodedAuth, __encodedUserInfo, __host, __port, __encodedPath, __encodedQuery);
336 if (!__encodedSsp.IsEmpty())
338 strbuf.Append(__encodedSsp);
342 //r = AppendAuthority(strbuf, __authority, __userInfo, __host, __port);
343 if (!__host.IsEmpty())
346 strbuf.Append(L"//");
348 // Check the Userinfo
349 if (!__encodedUserInfo.IsEmpty())
351 strbuf.Append(__encodedUserInfo);
356 result re = E_SUCCESS;
357 re = __host.IndexOf(L':', 0, indexOf);
359 String openBracket(L"[");
360 String closeBracket(L"]");
362 bool start = __host.StartsWith(openBracket, 0);
363 bool end = __host.EndsWith(closeBracket);
365 bool needBracket = false;
366 if (!start && !end && re == E_SUCCESS)
380 strbuf.Append(__host);
391 strbuf.Append(__port);
394 else if (!__encodedAuth.IsEmpty())
396 strbuf.Append(L"//");
397 strbuf.Append(__encodedAuth);
399 // AppendAuthority end
402 if (!__encodedPath.IsEmpty())
404 strbuf.Append(__encodedPath);
407 if (!__encodedQuery.IsEmpty())
410 strbuf.Append(__encodedQuery);
413 // AppendSchemeSpecificPart end
416 //AppendFragment(strbuf, __encodedFragment);
417 if (!__encodedFragment.IsEmpty())
420 strbuf.Append(__encodedFragment);
422 // AppendFragment end
428 ////////////////////////////////////////////////////////////////////////////////////////////
432 Uri::CompareTo(const Uri& uri) const
434 bool thisOpaque = false;
435 bool thatOpaque = false;
444 String otherFragment;
447 //////////////////////////////////////////////////
449 /////////////////////////////////////////////////
450 thisOpaque = IsOpaque();
451 thatOpaque = uri.IsOpaque();
453 // Both the current instance and a given instance are opaque
454 if (thisOpaque && thatOpaque)
456 // Compare Scheme-specific-part
457 ret = Compare(__ssp, uri.__ssp);
465 ret = Compare(__fragment, uri.__fragment);
470 else if (thisOpaque && !thatOpaque)
474 else if (!thisOpaque && thatOpaque)
480 //////////////////////////////////////////////////
482 /////////////////////////////////////////////////
483 if (!__host.IsEmpty() && !uri.__host.IsEmpty())
487 ret = Compare(__userInfo, uri.__userInfo);
495 ret = Compare(__host, uri.__host);
503 int portDiff = __port - uri.__port;
508 else if (portDiff == 0)
519 // If one of them is registry-based URI, then compare authority.
520 ret = Compare(__authority, uri.__authority);
529 ret = Compare(__path, uri.__path);
536 ret = Compare(__query, uri.__query);
543 ret = Compare(__fragment, uri.__fragment);
550 Uri::Equals(const Tizen::Base::Object& obj) const
552 // Check that obj is an Uri instance.
553 const Uri* pOther = dynamic_cast <const Uri*>(&obj);
559 int ret = CompareTo(*pOther);
570 Uri::GetHashCode(void) const
572 return ToString().GetHashCode();
579 result r = E_SUCCESS;
582 // If the current instance is opaque or the path of the current instance is undefined or an empty string,
584 if (__path.IsEmpty() || IsOpaque())
589 String normalizedUri;
590 normalizedUri = InternalNormalize(__path);
591 if (normalizedUri == __path || GetLastResult() == E_INVALID_ARG)
596 if (!__scheme.IsEmpty())
598 r = resultUri.SetScheme(__scheme);
599 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set scheme.", GetErrorMessage(r));
602 if (!__fragment.IsEmpty())
604 r = resultUri.SetFragment(__fragment);
605 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set fragment.", GetErrorMessage(r));
608 if (!__authority.IsEmpty())
610 r = resultUri.SetAuthority(__authority);
611 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set authority.", GetErrorMessage(r));
614 if (!__userInfo.IsEmpty())
616 r = resultUri.SetUserInfo(__userInfo);
617 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set userinfo.", GetErrorMessage(r));
620 if (!__host.IsEmpty())
622 r = resultUri.SetHost(__host);
623 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set host.", GetErrorMessage(r));
626 resultUri.SetPort(__port);
628 r = resultUri.SetPath(normalizedUri);
629 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set path.", GetErrorMessage(r));
631 if (!__query.IsEmpty())
633 r = resultUri.SetQuery(__query);
634 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), *this, r, "[%s] : Failed to set query.", GetErrorMessage(r));
642 Uri::ParseAuthority(Uri& uri)
644 result r = E_SUCCESS;
646 if (!__host.IsEmpty() || __authority.IsEmpty())
652 String str = ToString();
655 r = tempUri.SetUri(str);
662 r = ParseServerAuthority(str, tempUri.__host, tempUri.__userInfo, tempUri.__port);
675 Uri::Relativize(const Uri& uri, Uri& resultUri)
677 return Relativize(*this, uri, resultUri);
682 Uri::Resolve(const Uri& uri, Uri& resultUri)
684 return Resolve(*this, uri, resultUri);
689 Uri::SetAuthority(const Tizen::Base::String& authority)
691 bool isAuth = VerifyAuthority(authority);
693 SysTryReturn(NID_BASE_UTIL, isAuth, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Authority.", GetErrorMessage(E_INVALID_FORMAT));
695 if (IsEncoded(authority))
697 __encodedAuth = authority;
698 __authority = Decode(authority);
702 __authority = authority;
703 __encodedAuth = Encode(authority);
711 Uri::SetFragment(const Tizen::Base::String& fragment)
713 bool isFragment = VerifyUriChar(fragment);
715 SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
717 if (IsEncoded(fragment))
719 __encodedFragment = fragment;
720 __fragment = Decode(fragment);
724 __fragment = fragment;
725 __encodedFragment = Encode(fragment);
733 Uri::SetHost(const Tizen::Base::String& host)
735 bool isHost = VerifyHost(host);
737 SysTryReturn(NID_BASE_UTIL, isHost, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Host.", GetErrorMessage(E_INVALID_FORMAT));
746 Uri::SetPath(const Tizen::Base::String& path)
748 bool isPath = VerifyPath(path);
750 SysTryReturn(NID_BASE_UTIL, isPath, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Path.", GetErrorMessage(E_INVALID_FORMAT));
754 __encodedPath = path;
755 __path = Decode(path);
760 __encodedPath = Encode(path);
768 Uri::SetPort(int port)
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);
779 Uri::SetQuery(const Tizen::Base::String& query)
781 bool isQuery = VerifyUriChar(query);
783 SysTryReturn(NID_BASE_UTIL, isQuery, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Query.", GetErrorMessage(E_INVALID_FORMAT));
785 if (IsEncoded(query))
787 __encodedQuery = query;
788 __query = Decode(query);
793 __encodedQuery = Encode(query);
801 Uri::SetScheme(const Tizen::Base::String& scheme)
803 bool isScheme = VerifyScheme(scheme);
805 SysTryReturn(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
814 Uri::SetSchemeSpecificPart(const Tizen::Base::String& ssp)
816 bool isSsp = VerifyUriChar(ssp);
818 SysTryReturn(NID_BASE_UTIL, isSsp, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid SchemeSpecificPart.", GetErrorMessage(E_INVALID_FORMAT));
828 __encodedSsp = Encode(ssp);
836 Uri::SetUserInfo(const Tizen::Base::String& userInfo)
838 bool isUserInfo = VerifyUserInfo(userInfo);
840 SysTryReturn(NID_BASE_UTIL, isUserInfo, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid UserInfo.", GetErrorMessage(E_INVALID_FORMAT));
842 if (IsEncoded(userInfo))
844 __encodedUserInfo = userInfo;
845 __userInfo = Decode(userInfo);
849 __userInfo = userInfo;
850 __encodedUserInfo = Encode(userInfo);
858 Uri::ToString(void) const
863 if (!__scheme.IsEmpty())
865 strbuf.Append(__scheme);
869 //AppendSchemeSpecificPart(strbuf, __ssp, __authority, __userInfo, __host, __port, __path, __query);
872 strbuf.Append(__ssp);
876 //r = AppendAuthority(strbuf, __authority, __userInfo, __host, __port);
877 if (!__host.IsEmpty())
880 strbuf.Append(L"//");
882 // Check the Userinfo
883 if (!__userInfo.IsEmpty())
885 strbuf.Append(__userInfo);
890 result re = E_SUCCESS;
891 re = __host.IndexOf(L':', 0, indexOf);
893 String openBracket(L"[");
894 String closeBracket(L"]");
896 bool start = __host.StartsWith(openBracket, 0);
897 bool end = __host.EndsWith(closeBracket);
899 bool needBracket = false;
900 if (!start && !end && re == E_SUCCESS)
914 strbuf.Append(__host);
925 strbuf.Append(__port);
928 else if (!__authority.IsEmpty())
930 strbuf.Append(L"//");
931 strbuf.Append(__authority);
933 // AppendAuthority end
936 if (!__path.IsEmpty())
938 strbuf.Append(__path);
941 if (!__query.IsEmpty())
944 strbuf.Append(__query);
947 // AppendSchemeSpecificPart end
950 //AppendFragment(strbuf, __fragment);
951 if (!__fragment.IsEmpty())
954 strbuf.Append(__fragment);
956 // AppendFragment end
962 ////////////////////////////////////////////////////////////////////////
966 // This method constructs an URI instance.
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)
974 result r = E_SUCCESS;
979 if (!scheme.IsEmpty())
981 // Check that an extracted scheme is satisfied with RFC2396.
982 bool isScheme = VerifyScheme(scheme);
985 r = E_INVALID_FORMAT;
989 r = strbuf.Append(scheme);
995 r = strbuf.Append(L':');
1002 r = AppendSchemeSpecificPart(strbuf, opaque, authority, userInfo, host, port, path, query);
1008 r = AppendFragment(strbuf, fragment);
1016 r = SetUri(fullUri);
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
1033 result r = E_SUCCESS;
1035 if (!opaque.IsEmpty())
1037 if (VerifyUriChar(opaque))
1039 r = strbuf.Append(opaque);
1047 r = E_INVALID_FORMAT;
1053 r = AppendAuthority(strbuf, authority, userInfo, host, port);
1059 if (!path.IsEmpty())
1061 if (VerifyPath(path))
1063 r = strbuf.Append(path);
1067 r = E_INVALID_FORMAT;
1072 if (!query.IsEmpty())
1074 if (VerifyUriChar(query))
1076 r = strbuf.Append(L'?');
1082 r = strbuf.Append(query);
1090 r = E_INVALID_FORMAT;
1102 Uri::AppendFragment(Tizen::Base::String& strbuf, const Tizen::Base::String& fragment) const
1104 result r = E_SUCCESS;
1105 if (!fragment.IsEmpty())
1107 bool isFragment = VerifyUriChar(fragment);
1110 r = strbuf.Append(L'#');
1116 r = strbuf.Append(fragment);
1124 r = E_INVALID_FORMAT;
1135 Uri::AppendAuthority(Tizen::Base::String& strbuf, const Tizen::Base::String& authority, const Tizen::Base::String& userInfo,
1136 const Tizen::Base::String& host,
1139 result r = E_SUCCESS;
1141 String doubleSlash(L"//");
1143 if (!host.IsEmpty())
1146 bool isHost = VerifyHost(host);
1149 r = E_INVALID_FORMAT;
1153 r = strbuf.Append(doubleSlash);
1159 // Check the Userinfo
1160 if (!userInfo.IsEmpty())
1162 bool user = VerifyUserInfo(userInfo);
1165 r = strbuf.Append(userInfo);
1171 r = strbuf.Append(L'@');
1179 r = E_INVALID_FORMAT;
1185 result re = E_SUCCESS;
1186 re = host.IndexOf(L':', 0, indexOf);
1187 //if (IsFailed(r)) goto CATCH;
1189 String openBracket(L"[");
1190 String closeBracket(L"]");
1192 bool start = host.StartsWith(openBracket, 0);
1193 bool end = host.EndsWith(closeBracket);
1195 bool needBracket = true;
1196 if (!start && !end && re == E_SUCCESS)
1202 needBracket = false;
1207 r = strbuf.Append(L'[');
1214 r = strbuf.Append(host);
1222 r = strbuf.Append(L']');
1232 r = strbuf.Append(L':');
1238 r = strbuf.Append(port);
1248 r = E_INVALID_FORMAT;
1253 else if (!authority.IsEmpty())
1255 r = strbuf.Append(doubleSlash);
1261 bool auth = VerifyAuthority(authority);
1264 r = strbuf.Append(authority);
1272 r = E_INVALID_FORMAT;
1283 // This method breaks a given string into Uri components.
1284 // str : [scheme:]<scheme-specific-part>[#<fragment>]
1287 Uri::ParseUri(const Tizen::Base::String& str)
1289 result r = E_SUCCESS;
1290 wchar_t colon = L':';
1291 wchar_t sharp = L'#';
1294 int curIndex = 0; // points the current index
1295 int startFragment = 0;
1296 int lengthOfUri = str.GetLength();
1302 /////////////////////////////////////////////////////////////////
1303 // First, exract a scheme component from a given string.//
1304 ////////////////////////////////////////////////////////////////
1307 SysTryReturn(NID_BASE_UTIL, str[0] != L' ', E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
1309 // Get a index of ':'
1310 r = str.IndexOf(colon, 0, indexOf);
1311 if (indexOf >= 0 && r == E_SUCCESS)
1313 // There is a scheme componenet.
1315 r = str.SubString(0, indexOf, scheme);
1316 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1318 // Check that an extracted scheme is satisfied with RFC2396.
1319 bool isScheme = VerifyScheme(scheme);
1321 SysTryReturn(NID_BASE_UTIL, isScheme, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Scheme.", GetErrorMessage(E_INVALID_FORMAT));
1329 // In case there is no scheme component, the Uri is a hierarchical URI.
1331 __hasScheme = false;
1334 ////////////////////////////////////////////////////////////////////////
1335 // Second, extract a scheme-specific-part from a given string.//
1336 ///////////////////////////////////////////////////////////////////////
1337 if (__hasScheme) // This URI has a scheme.
1339 startSsp = ++curIndex; // skip ':'
1340 if (startSsp >= lengthOfUri)
1342 r = E_INVALID_FORMAT;
1346 if (str[startSsp] == '/')
1349 r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1355 SetAndEncodeAuthority(authority, path, query);
1358 r = str.SubString(startSsp, curIndex - startSsp, ssp);
1366 __ssp = Decode(ssp);
1372 __encodedSsp = Encode(ssp);
1381 r = str.IndexOf(sharp, curIndex, (int&)startFragment);
1382 if (startFragment > curIndex && r == E_SUCCESS)
1384 r = str.SubString(startSsp, startFragment - curIndex, ssp);
1390 else if (r == E_OBJ_NOT_FOUND)
1393 r = str.SubString(startSsp, lengthOfUri - curIndex, ssp);
1404 bool isOpaque = VerifyUriChar(ssp);
1406 SysTryReturn(NID_BASE_UTIL, isOpaque, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Opaque URI.", GetErrorMessage(E_INVALID_FORMAT));
1408 // Opaque URI is not subject to further parsing.
1411 __ssp = Decode(ssp);
1417 __encodedSsp = Encode(ssp);
1420 if (startFragment == 0)
1425 // Check the fragment
1429 r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1435 bool isFragment = VerifyUriChar(fragment);
1437 SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
1439 if (IsEncoded(fragment))
1441 __fragment = Decode(fragment);
1442 __encodedFragment = fragment;
1446 __fragment = fragment;
1447 __encodedFragment = Encode(fragment);
1453 else // This URI doesn't have a Scheme. - www.samsung.com[#ocean]
1457 r = ParseHierarchicalUri(str, startSsp, authority, path, query, curIndex);
1464 r = str.SubString(startSsp, curIndex - startSsp, ssp);
1472 __ssp = Decode(ssp);
1478 __encodedSsp = Encode(ssp);
1481 SetAndEncodeAuthority(authority, path, query);
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())
1495 r = ParseAuthority(authority, curIndex, newAuth, userInfo, host, port);
1501 if (!userInfo.IsEmpty())
1503 if (IsEncoded(userInfo))
1505 __userInfo = Decode(userInfo);
1506 __encodedUserInfo = userInfo;
1510 __userInfo = userInfo;
1511 __encodedUserInfo = Encode(userInfo);
1515 if (!host.IsEmpty())
1523 /////////////////////////////////////////////////
1524 // Finally, extract a fragment component //
1525 ////////////////////////////////////////////////
1526 startFragment = curIndex;
1527 if (startFragment < lengthOfUri && str[startFragment] == '#')
1532 r = str.SubString(startFragment, lengthOfUri - startFragment, fragment);
1538 bool isFragment = VerifyUriChar(fragment);
1540 SysTryReturn(NID_BASE_UTIL, isFragment, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Fragment.", GetErrorMessage(E_INVALID_FORMAT));
1542 if (IsEncoded(fragment))
1544 __fragment = Decode(fragment);
1545 __encodedFragment = fragment;
1549 __fragment = fragment;
1550 __encodedFragment = Encode(fragment);
1553 // curIndex = lengthOfUri;
1554 curIndex += fragment.GetLength() + 1; // skip '#'
1557 if (curIndex < lengthOfUri)
1559 // Invalid URI format
1560 r = E_INVALID_FORMAT;
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();
1573 Uri::SetAndEncodeAuthority(const Tizen::Base::String& authority, const Tizen::Base::String& path, const Tizen::Base::String& query)
1575 bool isEncoded = false;
1578 if (!authority.IsEmpty())
1580 isEncoded = IsEncoded(authority);
1583 __authority = Decode(authority);
1584 __encodedAuth = authority;
1588 __authority = authority;
1589 __encodedAuth = Encode(authority);
1594 if (!path.IsEmpty())
1596 isEncoded = IsEncoded(path);
1599 __path = Decode(path);
1600 __encodedPath = path;
1605 __encodedPath = Encode(path);
1610 if (!query.IsEmpty())
1612 isEncoded = IsEncoded(query);
1615 __query = Decode(query);
1616 __encodedQuery = query;
1621 __encodedQuery = Encode(query);
1628 Uri::ParseHierarchicalUri(const Tizen::Base::String& str, int startSsp, Tizen::Base::String& authority, Tizen::Base::String& path,
1629 Tizen::Base::String& query,
1632 result r = E_SUCCESS;
1633 int curIndex = startSsp;
1634 // bool isServerAuth;
1637 String queSharp(L"?#");
1638 String doubleSlash(L"//");
1640 bool startsWith = str.StartsWith(doubleSlash, curIndex);
1643 bool isPath = false;
1651 String special(L"/?#");
1653 int index = Scan(str, curIndex, special);
1654 if (index > (int) curIndex)
1656 r = str.SubString(curIndex, index - curIndex, authority);
1663 //r = ParseAuthority(str, curIndex, isServer);
1664 //if (IsFailed(r)) goto CATCH;
1666 else if (index < (int) str.GetLength())
1668 // allow an empty authority
1669 // authority = String::Empty();
1674 r = E_INVALID_FORMAT;
1677 curIndex += authority.GetLength();
1680 r = queSharp.IndexOf(str[0], 0, temp);
1687 position = Scan(str, curIndex, queSharp); // may be empty
1690 r = E_INVALID_FORMAT;
1694 if (position == curIndex)
1696 // There is no path and query
1703 r = str.SubString(curIndex, position - curIndex, tempPath);
1709 isPath = VerifyPath(tempPath);
1710 SysTryReturn(NID_BASE_UTIL, isPath, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Path.", GetErrorMessage(E_INVALID_FORMAT));
1714 curIndex = position;
1716 if (curIndex < str.GetLength() && str[curIndex] == L'?')
1722 r = str.IndexOf(L'#', curIndex, indexOf);
1725 r = str.SubString(curIndex, indexOf - curIndex, tempQuery);
1731 else if (r == E_OBJ_NOT_FOUND)
1733 r = str.SubString(curIndex, tempQuery);
1744 bool isQuery = VerifyUriChar(tempQuery);
1749 curIndex += query.GetLength();
1759 // This method parses an authority component.
1760 // This component is server based or registrty authority.
1763 Uri::ParseAuthority(const Tizen::Base::String& str, int curIndex, Tizen::Base::String& newAuth, Tizen::Base::String& userInfo,
1764 Tizen::Base::String& host,
1767 result r = E_SUCCESS;
1769 bool isServerChar = VerifyServerAuthority(str);
1770 bool isRegChar = VerifyRegistryAuthority(str);
1772 if (isRegChar && !isServerChar)
1780 r = ParseServerAuthority(str, userInfo, host, port);
1799 // This method parses a server_based authority componenet.
1800 // server_based authority : [user-info@]<host>[:port]
1803 Uri::ParseServerAuthority(const Tizen::Base::String& str, Tizen::Base::String& user, Tizen::Base::String& host, int& port)
1805 result r = E_SUCCESS;
1811 r = str.IndexOf(L'@', 0, indexOf);
1814 r = str.SubString(0, indexOf, userInfo);
1820 bool isUser = VerifyUserInfo(userInfo);
1822 SysTryReturn(NID_BASE_UTIL, isUser, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid UserInfo.", GetErrorMessage(E_INVALID_FORMAT));
1826 index += indexOf + 1; // skip '@'
1829 // IPv4 or IPv6 address
1832 // IPv6 not supported
1833 return E_INVALID_FORMAT;
1838 if (str[str.GetLength() - 1] == L']')
1843 r = str.SubString(1, str.GetLength() - 2, ip6);
1849 // TODO : Parsing IPv6 is not implemented.
1850 r = ParseIPv6(ip6, outIpv6);
1856 // TODO : Because IPv6 is hardly used, a member variable for IPv6 stores it directly.
1859 index += str.GetLength();
1863 r = E_INVALID_FORMAT; // This component has no closing bracket although it is a IPv6 address.
1873 r = ParseIpv4(str, index, count); // length of ipv4 string
1881 r = str.SubString(0, count, ip4);
1891 // This is a host name
1894 r = ParseHostName(str, index, tmpHost);
1911 index += host.GetLength();
1912 if (index < str.GetLength() && str[index] == L':')
1917 r = str.IndexOf(L'/', index, indexOf);
1920 r = str.SubString(index, indexOf - index, tmpPort);
1926 else if (r == E_OBJ_NOT_FOUND)
1928 r = str.SubString(index, tmpPort);
1935 int tmpPortLen = tmpPort.GetLength();
1936 for (int i = 0; i < tmpPortLen; i++)
1938 wchar_t ch = tmpPort[i];
1939 if (!(Character::IsDigit(ch)))
1941 r = E_INVALID_FORMAT;
1945 index += tmpPort.GetLength();
1948 r = Integer::Parse(tmpPort, 10, ret);
1956 if (index < (int) str.GetLength())
1958 r = E_INVALID_FORMAT;
1970 // This method parses a host name and returns a host name as an out-param.
1973 Uri::ParseHostName(const Tizen::Base::String& str, int index, Tizen::Base::String& host)
1975 result r = E_SUCCESS;
1977 bool isHost = false;
1979 int strLen = str.GetLength();
1980 r = str.IndexOf(L':', index, indexOf);
1983 r = str.SubString(index, indexOf - index, host);
1989 else if (r == E_OBJ_NOT_FOUND)
1992 r = str.SubString(index, host);
1999 for (int i = 0; i < strLen; i++)
2003 wchar_t ch1 = str[i + 1];
2004 wchar_t ch2 = str[i + 2];
2005 bool escape = IsEscapedChar(ch1, ch2);
2016 isHost = VerifyHost(host);
2018 SysTryReturn(NID_BASE_UTIL, isHost, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Invalid Host.", GetErrorMessage(E_INVALID_FORMAT));
2026 // This method parses an IPv6 address.
2027 // This method covers all and only the following cases :
2029 // hex_seq : IPv4 address
2031 // hex_seq :: hex_seq
2032 // hex_seq :: hex_seq : IPv4 address
2034 // :: hex_seq : IPv4 address
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.
2042 Uri::ParseIpv6(const Tizen::Base::String& ip6, Tizen::Base::String& outIpv6)
2044 // TODO : It will be implemented
2050 Uri::ParseIpv4(const Tizen::Base::String& str, int start, int& count)
2052 result r = E_SUCCESS;
2056 r = str.SubString(start, ipHost);
2062 // Set the index as an end position of ipv4
2063 count = ipHost.GetLength();
2065 StringTokenizer strTok(ipHost, dot);
2067 // Check that a given string consists of digit or dot.
2068 int ipHostLen = ipHost.GetLength();
2069 for (int i = 0; i < ipHostLen; i++)
2071 wchar_t ch = ipHost[i];
2072 if (ch != L'.' && !(Character::IsDigit(ch)))
2075 //r = E_INVALID_FORMAT;
2080 while (strTok.HasMoreTokens() == true)
2084 r = strTok.GetNextToken(token);
2091 r = Integer::Parse(token, 10, ret);
2097 // each part of IPv4 address cannot exceed 255.
2098 if (ret < 0 || ret > 255)
2100 r = E_INVALID_FORMAT;
2112 //////////////////////////////////////////////////////////////////////////////////////////
2113 // Verify a component
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.
2121 Uri::VerifyScheme(const Tizen::Base::String& str) const
2123 bool isAlpha = Character::IsLetter(str[0]);
2129 int strLen = str.GetLength();
2130 for (int i = 1; i < strLen; i++)
2132 if ((str[i] != '+') && (str[i] != '-') && (str[i] != '.') && (!Character::IsAlphaNumeric(str[i])) &&
2133 (!Character::IsDigit(str[i])))
2144 Uri::VerifyAuthority(const Tizen::Base::String& str) const
2146 bool isReg = VerifyRegistryAuthority(str);
2147 bool isServer = VerifyServerAuthority(str);
2149 if (isReg || isServer)
2161 Uri::VerifyHost(const Tizen::Base::String& str) const
2163 int length = str.GetLength();
2165 for (int i = 0; i < length; i++)
2167 wchar_t ch = str[i];
2168 if (ch != L'-' && ch != L'.' && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch))
2175 if (i == 0 || i == length - 1)
2186 Uri::VerifyPath(const Tizen::Base::String& str) const
2188 result r = E_SUCCESS;
2189 String reserved(L":@&=+$\",;/");
2191 int strLen = str.GetLength();
2192 for (int i = 0; i < strLen; i++)
2195 r = reserved.IndexOf(str[i], 0, indexOf);
2199 wchar_t ch1 = str[i + 1];
2200 wchar_t ch2 = str[i + 2];
2201 bool escape = IsEscapedChar(ch1, ch2);
2207 else if (str[i] == L' ') // add a space
2210 else if (r == E_OBJ_NOT_FOUND && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
2212 // Check the unicode letter
2213 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2225 Uri::VerifyUserInfo(const Tizen::Base::String& str) const
2227 String reserved(L";:&=+$,");
2228 int strLen = str.GetLength();
2230 for (int i = 0; i < strLen; i++)
2233 reserved.IndexOf(str[i], 0, indexOf);
2237 wchar_t ch1 = str[i + 1];
2238 wchar_t ch2 = str[i + 2];
2239 bool escape = IsEscapedChar(ch1, ch2);
2245 else if (str[i] == L' ') // add a space
2248 else if (indexOf < 0 && !Character::IsAlphaNumeric(str[i]) && !Character::IsDigit(str[i]) && !IsMark(str[i]))
2250 // Check the unicode letter
2251 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2262 Uri::VerifyUriChar(const Tizen::Base::String& str) const
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();
2272 for (int i = 0; i < strLen; i++)
2274 wchar_t ch = str[i];
2277 r = delims.IndexOf(ch, 0, indexOf); // check delims
2283 r = reserved.IndexOf(ch, 0, indexOf);
2286 wchar_t ch1 = str[i + 1];
2287 wchar_t ch2 = str[i + 2];
2288 bool escape = IsEscapedChar(ch1, ch2);
2294 else if (IsControlChar(ch)) // control
2298 else if ((ch != ' ') && (ch < 0x80) && !Character::IsAlphaNumeric(ch) && !Character::IsDigit(ch) && !IsMark(ch) &&
2301 // Check the unicode letter
2302 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
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.
2317 Uri::VerifyServerAuthority(const Tizen::Base::String& str) const
2319 result r = E_SUCCESS;
2320 String special(L".:@[]");
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++)
2327 wchar_t ch = str[i];
2328 r = special.IndexOf(ch, 0, indexOf);
2329 //if (r == E_SUCCESS && indexOf >= 0)
2334 if (ch == L'-' || IsUserInfo(ch) || r == E_SUCCESS)
2336 // This string is a server_based authority character
2340 if (!IsEscapedChar(str[i + 1], str[i + 2]))
2349 // Check the unicode letter
2350 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
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.
2365 Uri::VerifyRegistryAuthority(const Tizen::Base::String& str) const
2367 result r = E_SUCCESS;
2368 String specialChar(L"@%;:&=+$,");
2371 int strLen = str.GetLength();
2372 for (int i = 0; i < strLen; i++)
2374 wchar_t ch = str[i];
2375 r = specialChar.IndexOf(ch, 0, indexOf);
2377 if (!(Character::IsAlphaNumeric(ch)) && !(Character::IsDigit(ch)) && !IsMark(ch) && !(indexOf >= 0 && r == E_SUCCESS))
2379 // Check the unicode letter
2380 if (!(Character::GetUnicodeCategory(str[i]) == UNICODE_LETTER))
2385 else if (ch == L'%')
2387 if (!IsEscapedChar(str[i + 1], str[i + 2]))
2398 //////////////////////////////////////////////////////////////////////
2399 // Utility methods such as IsUserInfo, IsMark and so on.
2402 // This method returns true if a given wchar_t is a user-info character.
2403 // user-info char : alphabet, digit, -_.!~*'(), ;:&=+$,
2406 Uri::IsUserInfo(wchar_t mch) const
2408 result r = E_SUCCESS;
2409 String specialChar(L";:&=+$,");
2411 if (mch == L'%' || Character::IsAlphaNumeric(mch) || Character::IsDigit(mch) || IsMark(mch))
2417 r = specialChar.IndexOf(mch, 0, indexOf);
2418 if (indexOf >= 0 && r == E_SUCCESS)
2428 // This method returns true if a given wchar_t is a mark character.
2429 // mark char : -_.!~*'()
2432 Uri::IsMark(wchar_t mch) const
2434 result r = E_SUCCESS;
2435 String mark(L"-_.!~*'()");
2439 r = mark.IndexOf(mch, 0, indexOf);
2440 if (indexOf >= 0 && r == E_SUCCESS)
2450 Uri::IsControlChar(wchar_t ch) const
2452 if ((ch <= 0x009F) && ((ch <= 0x001F) || (ch >= 0x007F)))
2464 Uri::IsEscapedChar(wchar_t ch1, wchar_t ch2) const
2466 if ((ch1 >= L'a' && ch1 <= L'f') || (ch1 >= L'A' && ch1 <= L'F') || Character::IsDigit(ch1))
2468 if ((ch2 >= L'a' && ch2 <= L'f') || (ch2 >= L'A' && ch2 <= L'F') || Character::IsDigit(ch2))
2478 ////////////////////////////////////////////////////////////////////////
2479 // Private operations
2482 // This method finds the first character in the stop-string.
2485 Uri::Scan(const Tizen::Base::String& str, int start, const Tizen::Base::String& stopString)
2487 result r = E_SUCCESS;
2489 int strLen = str.GetLength();
2490 while (index < strLen)
2493 wchar_t ch = str[index];
2495 r = stopString.IndexOf(ch, 0, indexOf);
2508 // This method convers a component represented by UTF8 to a component represented by Unicode.
2511 Uri::Decode(const Tizen::Base::String& str)
2518 result r = E_SUCCESS;
2520 int len = str.GetLength();
2527 if (str[index] != L'%')
2529 decodedBuf.Append(str[index]);
2535 r = bb.Construct(20);
2540 r = str.SubString(index + 1, 2, utf8Str);
2543 r = Short::Parse(utf8Str, 16, ret);
2549 r = bb.SetByte((byte) ret);
2553 if (index >= len || str[index] != '%')
2561 r = StringUtil::Utf8ToString((char*) bb.GetPointer(), unicode);
2562 // if (IsFailed(r)) goto CATCH;
2565 decodedBuf.Append(L'?');
2569 decodedBuf.Append(unicode);
2581 // This method converts a component represented by Unicode to a component represented by UTF8.
2584 Uri::Encode(const Tizen::Base::String& str) const
2591 result r = E_SUCCESS;
2593 WcharBuffer wchar_tBuf;
2595 r = wchar_tBuf.Construct(str.GetLength() + 1);
2599 r = wchar_tBuf.SetArray(str.GetPointer(), 0, str.GetLength());
2600 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2602 r = wchar_tBuf.Set(L'\0');
2603 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
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);
2611 while (wchar_tBuf.HasRemaining())
2614 r = wchar_tBuf.Get(mch);
2615 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2622 if (mch >= 0x0080 || IsControlChar(mch))
2631 r = tmpBuf.Construct(2);
2632 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2634 r = tmpBuf.Set(mch);
2635 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2637 r = tmpBuf.Set(L'\0');
2638 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
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()));
2646 while (bbPos < pBuf->GetLimit() - 1) // null
2649 r = pBuf->GetByte(bbPos, b);
2650 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2652 sprintf(pChar.get() + (bbPos * 3), "%%%x", (int) b);
2656 r = StringUtil::Utf8ToString(pChar.get(), unicode);
2657 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2659 r = unicode.ToUpper(upper);
2661 r = strbuf.Append(upper);
2662 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2664 else if (mch == 0x20)
2666 String unicode(L"%20");
2667 r = strbuf.Append(unicode);
2668 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2670 else // ASCII character
2672 r = strbuf.Append(mch);
2673 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), str, r, "[%s] Propagating.", GetErrorMessage(r));
2677 SetLastResult(E_SUCCESS);
2683 Uri::AppendEscape(Tizen::Base::String& strbuf, byte b)
2688 result r = E_SUCCESS;
2689 r = strbuf.Append(L'%');
2695 bt1 = (b >> 4) & 0x0f;
2696 r = strbuf.Append(HEX_DIGITS[bt1]);
2702 bt2 = (b >> 0) & 0x0f;
2703 r = strbuf.Append(HEX_DIGITS[bt2]);
2716 // This method compares str1 and str2 after replacing all uppercase letters with their lowercase letters
2718 Uri::Compare(const Tizen::Base::String& str1, const Tizen::Base::String& str2) const
2727 // Both pStr1 and pStr2 are null
2732 // pStr1 is null but pStr isn't.
2740 // pStr1 is not null but pStr2 is null
2745 // Replace all uppercase letters with their lowercase letters
2746 str1.ToLower(small1);
2747 str2.ToLower(small2);
2749 return small1.CompareTo(small2);
2754 //////////////////////////////////////////////////////////////////////////////////////////
2758 Uri::InternalNormalize(const Tizen::Base::String& path)
2760 result r = E_SUCCESS;
2766 std::unique_ptr< WcharBuffer > pBuf(StringUtil::StringToMbN(path, 0, path.GetLength()));
2772 // Get the number of segments from a given path
2773 segCount = GetNumberOfSegments(path);
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);
2784 RemoveDots(*pBuf, pSegments.get(), segCount, path.GetLength());
2786 // Prevent scheme-name confusion
2787 AddLeadingDot(*pBuf, pSegments.get(), segCount);
2789 // Join the remaining segments and returns the result
2790 join = Join(*pBuf, pSegments.get(), segCount);
2792 r = StringUtil::MbToString(*pBuf, str);
2793 SysTryReturn(NID_BASE_UTIL, !IsFailed(r), L"", E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG));
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));
2804 if (joinedStr.Equals(path))
2806 return path; // String was already normalized.
2809 SetLastResult(E_SUCCESS);
2815 // This method returns the number of segments from a given path.
2818 Uri::GetNumberOfSegments(const Tizen::Base::String& path) const
2822 int endIndex = path.GetLength() - 1;
2825 // find the index of non-slash character
2826 while (p <= endIndex)
2828 if (path[p] != L'/')
2840 while (p <= endIndex)
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'/'))))))
2850 // Find the beginning index of next segment
2851 while (p <= endIndex)
2853 if (path[p++] != L'/')
2858 // skip redundant slashes
2859 while (p <= endIndex)
2861 if (path[p] != L'/')
2886 Uri::SplitIntoSegments(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
2888 int end = StringUtil::GetStringLengthInMb(mb);
2890 //int end = mb.GetLimit() - 1;
2892 int index = 0; // the index of current segment
2894 // skip initial slash
2907 if (index >= segCount)
2913 segments[index] = p;
2917 // Find beginning of next segment
2920 if (mb[p++] != L'/')
2926 // skip redundant slash
2939 // index must be equal to the length of segments[]
2944 Uri::RemoveDots(const Tizen::Base::WcharBuffer& mb, int* segments, int segCount, int length)
2948 for (int i = 0; i < segCount; i++)
2950 int dots = 0; // number of dots found
2952 // Find next occurrence of "." or "..
2955 int p = segments[i];
2963 else if (mb[p + 1] == L'\0')
2968 else if ((mb[p + 1] == L'.') && ((p + 1 == end) || (mb[p + 2] == L'\0')))
2976 while (i < segCount);
2978 if ((i > segCount) || (dots == 0))
2983 if (dots == 1 && i < segCount)
2985 // Remove this occurrence of '.'
2990 // If there is a preceding non-".." segment, remove both that segment and this occurrence of "..";
2991 // otherwise, leave this ".." segment as-is.
2993 for (j = i - 1; j >= 0; j--)
2995 if (segments[j] != -1)
3003 int q = segments[j];
3004 if (!((mb[q] == '.') && (mb[q + 1] == '.') && (mb[q + 2] == '\0')))
3016 Uri::AddLeadingDot(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
3020 // The path is absolute
3024 int firstSegment = 0; // Index of first segment
3025 while (firstSegment < segCount)
3027 if (segments[firstSegment] >= 0)
3034 if ((firstSegment >= segCount) || (firstSegment == 0))
3036 // The path is empty, or else the original first segment survived,
3037 // in which case we already know that no leading "." is needed
3041 int p = segments[firstSegment];
3042 while ((mb[p] != L':') && (mb[p] != L'\0') && (p < mb.GetLimit()))
3047 if (mb[p] == L'\0' || p >= mb.GetLimit())
3049 // No colon in first segment, so no "." needed
3053 // At this point we know that the first segment is unused,
3054 // hence we can insert a "." segment at that position
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.
3066 // segs[i] == -1 implies segment i is to be ignored
3067 // path computed by split, as above, with '\0' having replaced '/'
3070 // path[0] .. path[return value] == Resulting path
3073 Uri::Join(Tizen::Base::WcharBuffer& mb, int* segments, int segCount)
3075 //int end = StringUtil::GetStringLengthInMb(mb);
3077 int end = mb.GetLimit() - 1;
3082 // Restore initial slash for absolute paths
3086 for (int i = 0; i < segCount; i++)
3088 int q = segments[i];
3091 // ignore this segment
3098 while ((p <= end) && (mb[p] != L'\0'))
3104 // Preserve trailing slash
3110 while ((q <= end) && mb[q] != L'\0')
3116 // Preserve trailing slash
3121 if (p == mb.GetLimit())
3123 result r = E_SUCCESS;
3124 r = mb.SetLimit(p + 1);
3136 ///////////////////////////////////////////////////////////////////////////////////////////////
3140 // This method implements Uri resolution in RFC2396 5.2
3143 Uri::Resolve(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
3145 result r = E_SUCCESS;
3147 // If either baseUri or childUri is opaque, then resultUri is childUri
3148 if (baseUri.IsOpaque() || childUri.IsOpaque())
3150 resultUri = childUri;
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()))
3160 if ((!baseUri.__fragment.IsEmpty()) && (childUri.__fragment.GetLength() == baseUri.__fragment.GetLength()))
3162 resultUri = baseUri;
3166 if (!baseUri.__scheme.IsEmpty())
3168 r = resultUri.SetScheme(baseUri.__scheme);
3175 if (!baseUri.__authority.IsEmpty())
3177 r = resultUri.SetAuthority(baseUri.__authority);
3184 if (!baseUri.__userInfo.IsEmpty())
3186 r = resultUri.SetUserInfo(baseUri.__userInfo);
3193 if (!baseUri.__host.IsEmpty())
3195 r = resultUri.SetHost(baseUri.__host);
3202 resultUri.SetPort(baseUri.__port);
3204 if (!baseUri.__path.IsEmpty())
3206 r = resultUri.SetPath(baseUri.__path);
3213 if (!childUri.__fragment.IsEmpty())
3215 r = resultUri.SetFragment(childUri.__fragment);
3222 if (!baseUri.__query.IsEmpty())
3224 r = resultUri.SetQuery(baseUri.__query);
3235 // 5.2(3) child is an absolute URI
3236 if (!childUri.__scheme.IsEmpty())
3238 resultUri = childUri;
3243 if (!baseUri.__scheme.IsEmpty())
3245 r = resultUri.SetScheme(baseUri.__scheme);
3252 if (!childUri.__query.IsEmpty())
3254 r = resultUri.SetQuery(childUri.__query);
3261 if (!childUri.__fragment.IsEmpty())
3263 r = resultUri.SetFragment(childUri.__fragment);
3271 if (childUri.__authority.IsEmpty())
3273 if (!baseUri.__authority.IsEmpty())
3275 r = resultUri.SetAuthority(baseUri.__authority);
3282 if (!baseUri.__host.IsEmpty())
3284 r = resultUri.SetHost(baseUri.__host);
3291 if (!baseUri.__userInfo.IsEmpty())
3293 r = resultUri.SetUserInfo(baseUri.__userInfo);
3300 resultUri.SetPort(baseUri.__port);
3303 String encodedPath = childUri.__encodedPath;
3304 if (!encodedPath.IsEmpty())
3306 resolve = childUri.__encodedPath;
3309 if ((!resolve.IsEmpty()) && (resolve[0] == L'/'))
3311 // 5.2(5) child uri's path is absolute
3312 if (!encodedPath.IsEmpty())
3314 r = resultUri.SetPath(encodedPath);
3323 String encPath = baseUri.__encodedPath;
3324 if (!encPath.IsEmpty())
3326 // 5.2(6) Resolve relative path
3327 String relPath = ResolvePath(encPath, resolve, baseUri.IsAbsolute());
3328 if (relPath.IsEmpty())
3330 return GetLastResult();
3333 r = resultUri.SetPath(relPath);
3343 if (!childUri.__authority.IsEmpty())
3345 r = resultUri.SetAuthority(childUri.__authority);
3352 if (!childUri.__host.IsEmpty())
3354 r = resultUri.SetHost(childUri.__host);
3361 if (!childUri.__userInfo.IsEmpty())
3363 r = resultUri.SetUserInfo(childUri.__userInfo);
3370 resultUri.SetPort(childUri.__port);
3372 if (!childUri.__path.IsEmpty())
3374 r = resultUri.SetPath(childUri.__path);
3389 Uri::ResolvePath(const String& basePath, const String& childPath, bool isAbsolute)
3391 result r = E_SUCCESS;
3395 r = basePath.LastIndexOf(L'/', basePath.GetLength() - 1, indexOf);
3397 int len = childPath.GetLength();
3401 if (indexOf >= 0 && r == E_SUCCESS)
3403 r = basePath.SubString(0, indexOf + 1, path);
3418 r = basePath.SubString(0, indexOf + 1, tmpath);
3424 r = strbuf.Append(tmpath);
3431 r = strbuf.Append(childPath);
3440 return InternalNormalize(path);
3448 //////////////////////////////////////////////////////////////////////////
3451 Uri::Relativize(const Uri& baseUri, const Uri& childUri, Uri& resultUri)
3453 result r = E_SUCCESS;
3455 // If either base URI or child URI is opaque, result URI is the childUri.
3456 if (baseUri.IsOpaque() || childUri.IsOpaque())
3458 resultUri = childUri;
3462 int ret1 = Compare(baseUri.__scheme, childUri.__scheme);
3465 if (!baseUri.__authority.IsEmpty() && !childUri.__authority.IsEmpty())
3467 equal = EqualsComponent(baseUri.__authority, childUri.__authority);
3470 if ((ret1 != 0) || (!equal))
3472 resultUri = childUri;
3476 String basePath = InternalNormalize(baseUri.__path);
3477 String childPath = InternalNormalize(childUri.__path);
3479 if (basePath.Equals(childPath) == false)
3484 bool endWith = basePath.EndsWith(slash);
3487 String strbuf(basePath);
3489 r = strbuf.Append(slash);
3502 bool startsWith = childPath.StartsWith(basePath, 0);
3506 resultUri = childUri;
3512 r = childPath.SubString(basePath.GetLength(), path);
3518 r = resultUri.SetPath(path);
3524 if (!childUri.__query.IsEmpty())
3526 r = resultUri.SetQuery(childUri.__query);
3533 if (!childUri.__fragment.IsEmpty())
3535 r = resultUri.SetFragment(childUri.__fragment);
3547 // This method compares two components. If a component is encoded,
3548 // then its raw component is compared with another component.
3551 Uri::EqualsComponent(const Tizen::Base::String& comp1, const Tizen::Base::String& comp2)
3553 result r = E_SUCCESS;
3560 if (comp1.GetLength() != comp2.GetLength())
3566 r = comp1.IndexOf(L'%', 0, indexOf);
3567 if (r == E_OBJ_NOT_FOUND)
3569 return comp1.Equals(comp2);
3572 int len = comp1.GetLength();
3573 for (int i = 0; i < len; )
3575 wchar_t c1 = (comp1)[i];
3576 wchar_t c2 = (comp2)[i];
3589 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3595 if (Character::ToLower(comp1[i]) == Character::ToLower(comp2[i]))
3608 Uri::IsEncoded(const Tizen::Base::String& str) const
3610 int strLen = str.GetLength();
3611 for (int i = 0; i < strLen; i++)
3613 wchar_t ch = str[i];
3614 if (ch >= 0x0080 || ch == L' ' || IsControlChar(ch))
3629 __authority.Clear();
3639 // Encoded Component
3640 __encodedAuth.Clear();
3641 __encodedFragment.Clear();
3642 __encodedPath.Clear();
3643 __encodedQuery.Clear();
3644 __encodedSsp.Clear();
3648 } } } // Tizen::Base::Utility