1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_tools.hxx" 26 #include <tools/urlobj.hxx> 27 #include <tools/debug.hxx> 28 #include <tools/inetmime.hxx> 29 #include "com/sun/star/uno/Reference.hxx" 30 #include "com/sun/star/util/XStringWidth.hpp" 31 #include "osl/diagnose.h" 32 #include "osl/file.hxx" 33 #include "rtl/string.h" 34 #include "rtl/textenc.h" 35 #include "rtl/ustring.hxx" 36 #include "sal/types.h" 37 38 #ifndef INCLUDED_ALGORITHM 39 #include <algorithm> 40 #define INCLUDED_ALGORITHM 41 #endif 42 #ifndef INCLUDED_LIMITS 43 #include <limits> 44 #define INCLUDED_LIMITS 45 #endif 46 47 #include <string.h> 48 49 namespace unnamed_tools_urlobj {} using namespace unnamed_tools_urlobj; 50 // unnamed namespaces don't work well yet... 51 52 using namespace com::sun; 53 54 //============================================================================ 55 // 56 // INetURLObject 57 // 58 //============================================================================ 59 60 /* The URI grammar (using RFC 2234 conventions). 61 62 Constructs of the form 63 {reference <rule1> using rule2} 64 stand for a rule matching the given rule1 specified in the given reference, 65 encoded to URI syntax using rule2 (as specified in this URI grammar). 66 67 68 ; RFC 1738, RFC 2396, RFC 2732, private 69 login = [user [":" password] "@"] hostport 70 user = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~") 71 password = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~") 72 hostport = host [":" port] 73 host = incomplete-hostname / hostname / IPv4address / IPv6reference 74 incomplete-hostname = *(domainlabel ".") domainlabel 75 hostname = *(domainlabel ".") toplabel ["."] 76 domainlabel = alphanum [*(alphanum / "-") alphanum] 77 toplabel = ALPHA [*(alphanum / "-") alphanum] 78 IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT 79 IPv6reference = "[" hexpart [":" IPv4address] "]" 80 hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) 81 hexseq = hex4 *(":" hex4) 82 hex4 = 1*4HEXDIG 83 port = *DIGIT 84 escaped = "%" HEXDIG HEXDIG 85 reserved = "$" / "&" / "+" / "," / "/" / ":" / ";" / "=" / "?" / "@" / "[" / "]" 86 mark = "!" / "'" / "(" / ")" / "*" / "-" / "." / "_" / "~" 87 alphanum = ALPHA / DIGIT 88 unreserved = alphanum / mark 89 uric = escaped / reserved / unreserved 90 pchar = escaped / unreserved / "$" / "&" / "+" / "," / ":" / "=" / "@" 91 92 93 ; RFC 1738, RFC 2396 94 ftp-url = "FTP://" login ["/" segment *("/" segment) [";TYPE=" ("A" / "D" / "I")]] 95 segment = *pchar 96 97 98 ; RFC 1738, RFC 2396 99 http-url = "HTTP://" hostport ["/" segment *("/" segment) ["?" *uric]] 100 segment = *(pchar / ";") 101 102 103 ; RFC 1738, RFC 2396, <http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q188997&> 104 file-url = "FILE://" [host / "LOCALHOST" / netbios-name] ["/" segment *("/" segment)] 105 segment = *pchar 106 netbios-name = 1*{<alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "^" / "_" / "{" / "}" / "~"> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "_" / "~")} 107 108 109 ; RFC 2368, RFC 2396 110 mailto-url = "MAILTO:" [to] [headers] 111 to = {RFC 822 <#mailbox> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} 112 headers = "?" header *("&" header) 113 header = hname "=" hvalue 114 hname = {RFC 822 <field-name> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} / "BODY" 115 hvalue = {RFC 822 <field-body> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} 116 117 118 ; private (see RFC 1738, RFC 2396) 119 vnd-sun-star-webdav-url = "VND.SUN.STAR.WEBDAV://" hostport ["/" segment *("/" segment) ["?" *uric]] 120 segment = *(pchar / ";") 121 122 123 ; RFC 1738, RFC 2396, RFC 2732 124 news-url = "NEWS:" grouppart 125 grouppart = "*" / group / article 126 group = alpha *(alphanum / "+" / "-" / "." / "_") 127 article = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "?" / "_" / "~") "@" host 128 129 130 ; private 131 private-url = "PRIVATE:" path ["?" *uric] 132 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") 133 134 135 ; private 136 vnd-sun-star-help-url = "VND.SUN.STAR.HELP://" name *("/" segment) ["?" *uric] 137 name = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") 138 segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") 139 140 141 ; private 142 https-url = "HTTPS://" hostport ["/" segment *("/" segment) ["?" *uric]] 143 segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") 144 145 146 ; private 147 slot-url = "SLOT:" path ["?" *uric] 148 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") 149 150 151 ; private 152 macro-url = "MACRO:" path ["?" *uric] 153 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") 154 155 156 ; private 157 javascript-url = "JAVASCRIPT:" *uric 158 159 160 ; private (see RFC 2192) 161 imap-url = "IMAP://" user [";AUTH=" auth] "@" hostport "/" segment *("/" segment) ["/;UID=" nz_number] 162 user = 1*{RFC 2060 <CHAR8> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "=" / "_" / "~")} 163 auth = {RFC 2060 <atom> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "+" / "," / "-" / "." / "=" / "_" / "~")} 164 segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / "=" / "@" / "_" / "~") 165 nz_number = {RFC 2060 <nz_number> using *DIGIT} 166 167 168 ; private 169 pop3-url = "POP3://" login ["/" ["<" *uric ">"]] 170 171 172 ; RFC 2397 173 data-url = "DATA:" [mediatype] [";BASE64"] "," *uric 174 mediatype = [type "/" subtype] *(";" attribute "=" value) 175 type = {RFC 2045 <type> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} 176 subtype = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} 177 attribute = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} 178 value = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} 179 180 181 ; RFC 2392, RFC 2396 182 cid-url = "CID:" {RFC 822 <addr-spec> using *uric} 183 184 185 ; private 186 out-url = "OUT:///~" name ["/" *uric] 187 name = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "?" / "@" / "_" / "~" 188 189 190 ; private 191 vnd-sun-star-hier-url = "VND.SUN.STAR.HIER:" ["//"reg_name] *("/" *pchar) 192 reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") 193 194 ; private 195 vim-url = "VIM://" +vimc [":" *vimc] ["/" [("INBOX" message) / ("NEWSGROUPS" ["/" [+vimc message]])]] 196 message = ["/" [+vimc [":" +DIGIT "." +DIGIT "." +DIGIT]]] 197 vimc = ("=" HEXDIG HEXDIG) / alphanum 198 199 200 ; private 201 uno-url = ".UNO:" path ["?" *uric] 202 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") 203 204 205 ; private 206 component-url = ".COMPONENT:" path ["?" *uric] 207 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") 208 209 210 ; private 211 vnd-sun-star-pkg-url = "VND.SUN.STAR.PKG://" reg_name *("/" *pchar) ["?" *uric] 212 reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") 213 214 215 ; RFC 2255 216 ldap-url = "LDAP://" [hostport] ["/" [dn ["?" [attrdesct *("," attrdesc)] ["?" ["base" / "one" / "sub"] ["?" [filter] ["?" extension *("," extension)]]]]]] 217 dn = {RFC 2253 <distinguishedName> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} 218 attrdesc = {RFC 2251 <AttributeDescription> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} 219 filter = {RFC 2254 <filter> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} 220 extension = ["!"] ["X-"] extoken ["=" exvalue] 221 extoken = {RFC 2252 <oid> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} 222 exvalue = {RFC 2251 <LDAPString> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} 223 224 225 ; private 226 db-url = "DB:" *uric 227 228 229 ; private 230 vnd-sun-star-cmd-url = "VND.SUN.STAR.CMD:" opaque_part 231 opaque_part = uric_no_slash *uric 232 uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," 233 234 235 ; private 236 vnd-sun-star-url = "VND.SUN.STAR.ODMA:" ["/" *uric_no_slash] 237 uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," 238 239 240 ; RFC 1738 241 telnet-url = "TELNET://" login ["/"] 242 243 244 ; private 245 vnd-sun-star-expand-url = "VND.SUN.STAR.EXPAND:" opaque_part 246 opaque_part = uric_no_slash *uric 247 uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," 248 249 250 ; private 251 vnd-sun-star-tdoc-url = "VND.SUN.STAR.TDOC:/" segment *("/" segment) 252 segment = *pchar 253 254 255 ; private 256 unknown-url = scheme ":" 1*uric 257 scheme = ALPHA *(alphanum / "+" / "-" / ".") 258 259 260 ; private (http://ubiqx.org/cifs/Appendix-D.html): 261 smb-url = "SMB://" login ["/" segment *("/" segment) ["?" *uric]] 262 segment = *(pchar / ";") 263 */ 264 265 //============================================================================ 266 inline sal_Int32 INetURLObject::SubString::clear() 267 { 268 sal_Int32 nDelta = -m_nLength; 269 m_nBegin = -1; 270 m_nLength = 0; 271 return nDelta; 272 } 273 274 inline sal_Int32 INetURLObject::SubString::set(rtl::OUStringBuffer & rString, 275 rtl::OUString const & rSubString) 276 { 277 rtl::OUString sTemp(rString.makeStringAndClear()); 278 sal_Int32 nDelta = set(sTemp, rSubString); 279 rString.append(sTemp); 280 return nDelta; 281 } 282 283 inline sal_Int32 INetURLObject::SubString::set(rtl::OUString & rString, 284 rtl::OUString const & rSubString) 285 { 286 sal_Int32 nDelta = rSubString.getLength() - m_nLength; 287 288 rString = rString.replaceAt(m_nBegin, m_nLength, rSubString); 289 290 m_nLength = rSubString.getLength(); 291 return nDelta; 292 } 293 294 inline sal_Int32 INetURLObject::SubString::set(rtl::OUStringBuffer & rString, 295 rtl::OUString const & rSubString, 296 sal_Int32 nTheBegin) 297 { 298 m_nBegin = nTheBegin; 299 return set(rString, rSubString); 300 } 301 302 //============================================================================ 303 inline void INetURLObject::SubString::operator +=(sal_Int32 nDelta) 304 { 305 if (isPresent()) 306 m_nBegin = m_nBegin + nDelta; 307 } 308 309 //============================================================================ 310 int INetURLObject::SubString::compare(SubString const & rOther, 311 rtl::OUStringBuffer const & rThisString, 312 rtl::OUStringBuffer const & rOtherString) const 313 { 314 sal_Int32 len = std::min(m_nLength, rOther.m_nLength); 315 sal_Unicode const * p1 = rThisString.getStr() + m_nBegin; 316 sal_Unicode const * end = p1 + len; 317 sal_Unicode const * p2 = rOtherString.getStr() + rOther.m_nBegin; 318 while (p1 != end) { 319 if (*p1 < *p2) { 320 return -1; 321 } else if (*p1 > *p2) { 322 return 1; 323 } 324 ++p1; 325 ++p2; 326 } 327 return m_nLength < rOther.m_nLength ? -1 328 : m_nLength > rOther.m_nLength ? 1 329 : 0; 330 } 331 332 //============================================================================ 333 struct INetURLObject::SchemeInfo 334 { 335 sal_Char const * m_pScheme; 336 sal_Char const * m_pPrefix; 337 sal_uInt16 m_nDefaultPort; 338 bool m_bAuthority; 339 bool m_bUser; 340 bool m_bAuth; 341 bool m_bPassword; 342 bool m_bHost; 343 bool m_bPort; 344 bool m_bHierarchical; 345 bool m_bQuery; 346 }; 347 348 //============================================================================ 349 struct INetURLObject::PrefixInfo 350 { 351 enum Kind { OFFICIAL, INTERNAL, EXTERNAL, ALIAS }; // order is important! 352 353 sal_Char const * m_pPrefix; 354 sal_Char const * m_pTranslatedPrefix; 355 INetProtocol m_eScheme; 356 Kind m_eKind; 357 }; 358 359 //============================================================================ 360 static INetURLObject::SchemeInfo const aSchemeInfoMap[INET_PROT_END] 361 = { { "", "", 0, false, false, false, false, false, false, false, 362 false }, 363 { "ftp", "ftp://", 21, true, true, false, true, true, true, true, 364 false }, 365 { "http", "http://", 80, true, false, false, false, true, true, 366 true, true }, 367 { "file", "file://", 0, true, false, false, false, true, false, 368 true, false }, 369 { "mailto", "mailto:", 0, false, false, false, false, false, 370 false, false, true }, 371 { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, false, 372 false, false, true, true, true, true }, 373 { "news", "news:", 0, false, false, false, false, false, false, false, 374 false }, 375 { "private", "private:", 0, false, false, false, false, false, 376 false, false, true }, 377 { "vnd.sun.star.help", "vnd.sun.star.help://", 0, true, false, false, 378 false, false, false, true, true }, 379 { "https", "https://", 443, true, false, false, false, true, true, 380 true, true }, 381 { "slot", "slot:", 0, false, false, false, false, false, false, 382 false, true }, 383 { "macro", "macro:", 0, false, false, false, false, false, false, 384 false, true }, 385 { "javascript", "javascript:", 0, false, false, false, false, 386 false, false, false, false }, 387 { "imap", "imap://", 143, true, true, true, false, true, true, 388 true, false }, 389 { "pop3", "pop3://", 110, true, true, false, true, true, true, 390 false, false }, 391 { "data", "data:", 0, false, false, false, false, false, false, 392 false, false }, 393 { "cid", "cid:", 0, false, false, false, false, false, false, 394 false, false }, 395 { "out", "out://", 0, true, false, false, false, false, false, 396 false, false }, 397 { "vnd.sun.star.hier", "vnd.sun.star.hier:", 0, true, false, false, 398 false, false, false, true, false }, 399 { "vim", "vim://", 0, true, true, false, true, false, false, true, 400 false }, 401 { ".uno", ".uno:", 0, false, false, false, false, false, false, 402 false, true }, 403 { ".component", ".component:", 0, false, false, false, false, 404 false, false, false, true }, 405 { "vnd.sun.star.pkg", "vnd.sun.star.pkg://", 0, true, false, false, 406 false, false, false, true, true }, 407 { "ldap", "ldap://", 389, true, false, false, false, true, true, 408 false, true }, 409 { "db", "db:", 0, false, false, false, false, false, false, false, 410 false }, 411 { "vnd.sun.star.cmd", "vnd.sun.star.cmd:", 0, false, false, false, 412 false, false, false, false, false }, 413 { "vnd.sun.star.odma", "vnd.sun.star.odma:", 0, false, false, false, 414 false, false, false, true, false }, 415 { "telnet", "telnet://", 23, true, true, false, true, true, true, true, 416 false }, 417 { "vnd.sun.star.expand", "vnd.sun.star.expand:", 0, false, false, false, 418 false, false, false, false, false }, 419 { "vnd.sun.star.tdoc", "vnd.sun.star.tdoc:", 0, false, false, false, 420 false, false, false, true, false }, 421 { "", "", 0, false, false, false, false, true, true, true, false }, 422 { "smb", "smb://", 139, true, true, false, true, true, true, true, 423 true }, 424 { "hid", "hid:", 0, false, false, false, false, false, false, 425 false, true } }; 426 427 // static 428 inline INetURLObject::SchemeInfo const & 429 INetURLObject::getSchemeInfo(INetProtocol eTheScheme) 430 { 431 return aSchemeInfoMap[eTheScheme]; 432 }; 433 434 //============================================================================ 435 inline INetURLObject::SchemeInfo const & INetURLObject::getSchemeInfo() const 436 { 437 return getSchemeInfo(m_eScheme); 438 } 439 440 //============================================================================ 441 // static 442 inline void INetURLObject::appendEscape(rtl::OUStringBuffer & rTheText, 443 sal_Char cEscapePrefix, 444 sal_uInt32 nOctet) 445 { 446 rTheText.append(sal_Unicode(cEscapePrefix)); 447 rTheText.append(sal_Unicode(INetMIME::getHexDigit(int(nOctet >> 4)))); 448 rTheText.append(sal_Unicode(INetMIME::getHexDigit(int(nOctet & 15)))); 449 } 450 451 //============================================================================ 452 namespace unnamed_tools_urlobj { 453 454 enum 455 { 456 PA = INetURLObject::PART_OBSOLETE_NORMAL, 457 PB = INetURLObject::PART_OBSOLETE_FILE, 458 PC = INetURLObject::PART_OBSOLETE_PARAM, 459 PD = INetURLObject::PART_USER_PASSWORD, 460 PE = INetURLObject::PART_IMAP_ACHAR, 461 PF = INetURLObject::PART_VIM, 462 PG = INetURLObject::PART_HOST_EXTRA, 463 PH = INetURLObject::PART_FPATH, 464 PI = INetURLObject::PART_AUTHORITY, 465 PJ = INetURLObject::PART_PATH_SEGMENTS_EXTRA, 466 PK = INetURLObject::PART_REL_SEGMENT_EXTRA, 467 PL = INetURLObject::PART_URIC, 468 PM = INetURLObject::PART_HTTP_PATH, 469 PN = INetURLObject::PART_FILE_SEGMENT_EXTRA, 470 PO = INetURLObject::PART_MESSAGE_ID, 471 PP = INetURLObject::PART_MESSAGE_ID_PATH, 472 PQ = INetURLObject::PART_MAILTO, 473 PR = INetURLObject::PART_PATH_BEFORE_QUERY, 474 PS = INetURLObject::PART_PCHAR, 475 PT = INetURLObject::PART_FRAGMENT, 476 PU = INetURLObject::PART_VISIBLE, 477 PV = INetURLObject::PART_VISIBLE_NONSPECIAL, 478 PW = INetURLObject::PART_CREATEFRAGMENT, 479 PX = INetURLObject::PART_UNO_PARAM_VALUE, 480 PY = INetURLObject::PART_UNAMBIGUOUS, 481 PZ = INetURLObject::PART_URIC_NO_SLASH, 482 P1 = INetURLObject::PART_HTTP_QUERY, 483 P2 = INetURLObject::PART_NEWS_ARTICLE_LOCALPART 484 }; 485 486 static sal_uInt32 const aMustEncodeMap[128] 487 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 489 /* */ PY, 490 /* ! */ PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 491 /* " */ PU+PV +PY, 492 /* # */ PU, 493 /* $ */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 494 /* % */ PU, 495 /* & */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN+PO+PP +PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2, 496 /* ' */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 497 /* ( */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 498 /* ) */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 499 /* * */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 500 /* + */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2, 501 /* , */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW +PZ+P1+P2, 502 /* - */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 503 /* . */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 504 /* / */ PA+PB+PC +PH +PJ +PL+PM +PP+PQ+PR +PT+PU+PV +PX +P2, 505 /* 0 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 506 /* 1 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 507 /* 2 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 508 /* 3 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 509 /* 4 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 510 /* 5 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 511 /* 6 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 512 /* 7 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 513 /* 8 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 514 /* 9 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 515 /* : */ PB+PC +PH+PI+PJ +PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2, 516 /* ; */ PC+PD +PI+PJ+PK+PL+PM +PO+PP+PQ+PR +PT+PU +PW +PZ+P1+P2, 517 /* < */ PC +PO+PP +PU+PV +PY, 518 /* = */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN +PR+PS+PT+PU+PV+PW +PZ+P1+P2, 519 /* > */ PC +PO+PP +PU+PV +PY, 520 /* ? */ PC +PL +PT+PU +PW+PX +PZ +P2, 521 /* @ */ PC +PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1, 522 /* A */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 523 /* B */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 524 /* C */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 525 /* D */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 526 /* E */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 527 /* F */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 528 /* G */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 529 /* H */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 530 /* I */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 531 /* J */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 532 /* K */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 533 /* L */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 534 /* M */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 535 /* N */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 536 /* O */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 537 /* P */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 538 /* Q */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 539 /* R */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 540 /* S */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 541 /* T */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 542 /* U */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 543 /* V */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 544 /* W */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 545 /* X */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 546 /* Y */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 547 /* Z */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 548 /* [ */ PL +PU+PV +PX, 549 /* \ */ PB +PU+PV +PY, 550 /* ] */ PL +PU+PV +PX, 551 /* ^ */ PU+PV +PY, 552 /* _ */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 553 /* ` */ PU+PV +PY, 554 /* a */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 555 /* b */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 556 /* c */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 557 /* d */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 558 /* e */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 559 /* f */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 560 /* g */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 561 /* h */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 562 /* i */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 563 /* j */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 564 /* k */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 565 /* l */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 566 /* m */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 567 /* n */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 568 /* o */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 569 /* p */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 570 /* q */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 571 /* r */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 572 /* s */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 573 /* t */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 574 /* u */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 575 /* v */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 576 /* w */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 577 /* x */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 578 /* y */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 579 /* z */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2, 580 /* { */ PU+PV +PY, 581 /* | */ PB+PC +PN +PT+PU+PV +PY, 582 /* } */ PU+PV +PY, 583 /* ~ */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ +P2, 584 0 }; 585 586 inline bool mustEncode(sal_uInt32 nUTF32, INetURLObject::Part ePart) 587 { 588 return !INetMIME::isUSASCII(nUTF32) || !(aMustEncodeMap[nUTF32] & ePart); 589 } 590 591 } 592 593 //============================================================================ 594 void INetURLObject::setInvalid() 595 { 596 m_aAbsURIRef.setLength(0); 597 m_eScheme = INET_PROT_NOT_VALID; 598 m_aScheme.clear(); 599 m_aUser.clear(); 600 m_aAuth.clear(); 601 m_aHost.clear(); 602 m_aPort.clear(); 603 m_aPath.clear(); 604 m_aQuery.clear(); 605 m_aFragment.clear(); 606 } 607 608 //============================================================================ 609 610 namespace unnamed_tools_urlobj { 611 612 INetURLObject::FSysStyle 613 guessFSysStyleByCounting(sal_Unicode const * pBegin, 614 sal_Unicode const * pEnd, 615 INetURLObject::FSysStyle eStyle) 616 { 617 DBG_ASSERT(eStyle 618 & (INetURLObject::FSYS_UNX 619 | INetURLObject::FSYS_DOS 620 | INetURLObject::FSYS_MAC), 621 "guessFSysStyleByCounting(): Bad style"); 622 DBG_ASSERT(std::numeric_limits< sal_Int32 >::min() < pBegin - pEnd 623 && pEnd - pBegin <= std::numeric_limits< sal_Int32 >::max(), 624 "guessFSysStyleByCounting(): Too big"); 625 sal_Int32 nSlashCount 626 = eStyle & INetURLObject::FSYS_UNX ? 627 0 : std::numeric_limits< sal_Int32 >::min(); 628 sal_Int32 nBackslashCount 629 = eStyle & INetURLObject::FSYS_DOS ? 630 0 : std::numeric_limits< sal_Int32 >::min(); 631 sal_Int32 nColonCount 632 = eStyle & INetURLObject::FSYS_MAC ? 633 0 : std::numeric_limits< sal_Int32 >::min(); 634 while (pBegin != pEnd) 635 switch (*pBegin++) 636 { 637 case '/': 638 ++nSlashCount; 639 break; 640 641 case '\\': 642 ++nBackslashCount; 643 break; 644 645 case ':': 646 ++nColonCount; 647 break; 648 } 649 return nSlashCount >= nBackslashCount ? 650 nSlashCount >= nColonCount ? 651 INetURLObject::FSYS_UNX : INetURLObject::FSYS_MAC : 652 nBackslashCount >= nColonCount ? 653 INetURLObject::FSYS_DOS : INetURLObject::FSYS_MAC; 654 } 655 656 rtl::OUString parseScheme( 657 sal_Unicode const ** begin, sal_Unicode const * end, 658 sal_uInt32 fragmentDelimiter) 659 { 660 sal_Unicode const * p = *begin; 661 if (p != end && INetMIME::isAlpha(*p)) { 662 do { 663 ++p; 664 } while (p != end 665 && (INetMIME::isAlphanumeric(*p) || *p == '+' || *p == '-' 666 || *p == '.')); 667 // #i34835# To avoid problems with Windows file paths like "C:\foo", 668 // do not accept generic schemes that are only one character long: 669 if (end - p > 1 && p[0] == ':' && p[1] != fragmentDelimiter 670 && p - *begin >= 2) 671 { 672 rtl::OUString scheme( 673 rtl::OUString(*begin, p - *begin).toAsciiLowerCase()); 674 *begin = p + 1; 675 return scheme; 676 } 677 } 678 return rtl::OUString(); 679 } 680 681 } 682 683 bool INetURLObject::setAbsURIRef(rtl::OUString const & rTheAbsURIRef, 684 bool bOctets, 685 EncodeMechanism eMechanism, 686 rtl_TextEncoding eCharset, 687 bool bSmart, 688 FSysStyle eStyle) 689 { 690 sal_Unicode const * pPos = rTheAbsURIRef.getStr(); 691 sal_Unicode const * pEnd = pPos + rTheAbsURIRef.getLength(); 692 693 setInvalid(); 694 695 sal_uInt32 nFragmentDelimiter = '#'; 696 697 rtl::OUStringBuffer aSynAbsURIRef; 698 699 // Parse <scheme>: 700 sal_Unicode const * p = pPos; 701 PrefixInfo const * pPrefix = getPrefix(p, pEnd); 702 if (pPrefix) 703 { 704 pPos = p; 705 m_eScheme = pPrefix->m_eScheme; 706 707 rtl::OUString sTemp(rtl::OUString::createFromAscii(pPrefix->m_eKind 708 >= PrefixInfo::EXTERNAL ? 709 pPrefix->m_pTranslatedPrefix : 710 pPrefix->m_pPrefix)); 711 aSynAbsURIRef.append(sTemp); 712 m_aScheme = SubString( 0, sTemp.indexOf(static_cast< sal_Unicode >(':')) ); 713 } 714 else 715 { 716 if (bSmart) 717 { 718 // For scheme detection, the first (if any) of the following 719 // productions that matches the input string (and for which the 720 // appropriate style bit is set in eStyle, if applicable) 721 // determines the scheme. The productions use the auxiliary rules 722 // 723 // domain = label *("." label) 724 // label = alphanum [*(alphanum / "-") alphanum] 725 // alphanum = ALPHA / DIGIT 726 // IPv6reference = "[" IPv6address "]" 727 // IPv6address = hexpart [":" IPv4address] 728 // IPv4address = 1*3DIGIT 3("." 1*3DIGIT) 729 // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) 730 // hexseq = hex4 *(":" hex4) 731 // hex4 = 1*4HEXDIG 732 // UCS4 = <any UCS4 character> 733 // 734 // 1st Production (known scheme): 735 // <one of the known schemes, ignoring case> ":" *UCS4 736 // 737 // 2nd Production (mailto): 738 // domain "@" domain 739 // 740 // 3rd Production (ftp): 741 // "FTP" 2*("." label) ["/" *UCS4] 742 // 743 // 4th Production (http): 744 // label 2*("." label) ["/" *UCS4] 745 // 746 // 5th Production (file): 747 // "//" (domain / IPv6reference) ["/" *UCS4] 748 // 749 // 6th Production (Unix file): 750 // "/" *UCS4 751 // 752 // 7th Production (UNC file; FSYS_DOS only): 753 // "\\" domain ["\" *UCS4] 754 // 755 // 8th Production (Unix-like DOS file; FSYS_DOS only): 756 // ALPHA ":" ["/" *UCS4] 757 // 758 // 9th Production (DOS file; FSYS_DOS only): 759 // ALPHA ":" ["\" *UCS4] 760 // 761 // For the 'non URL' file productions 6--9, the interpretation of 762 // the input as a (degenerate) URI is turned off, i.e., escape 763 // sequences and fragments are never detected as such, but are 764 // taken as literal characters. 765 766 sal_Unicode const * p1 = pPos; 767 if (eStyle & FSYS_DOS 768 && pEnd - p1 >= 2 769 && INetMIME::isAlpha(p1[0]) 770 && p1[1] == ':' 771 && (pEnd - p1 == 2 || p1[2] == '/' || p1[2] == '\\')) 772 { 773 m_eScheme = INET_PROT_FILE; // 8th, 9th 774 eMechanism = ENCODE_ALL; 775 nFragmentDelimiter = 0x80000000; 776 } 777 else if (pEnd - p1 >= 2 && p1[0] == '/' && p1[1] == '/') 778 { 779 p1 += 2; 780 if ((scanDomain(p1, pEnd) > 0 || scanIPv6reference(p1, pEnd)) 781 && (p1 == pEnd || *p1 == '/')) 782 m_eScheme = INET_PROT_FILE; // 5th 783 } 784 else if (p1 != pEnd && *p1 == '/') 785 { 786 m_eScheme = INET_PROT_FILE; // 6th 787 eMechanism = ENCODE_ALL; 788 nFragmentDelimiter = 0x80000000; 789 } 790 else if (eStyle & FSYS_DOS 791 && pEnd - p1 >= 2 792 && p1[0] == '\\' 793 && p1[1] == '\\') 794 { 795 p1 += 2; 796 sal_Int32 n = rtl_ustr_indexOfChar_WithLength( 797 p1, pEnd - p1, '\\'); 798 sal_Unicode const * pe = n == -1 ? pEnd : p1 + n; 799 if ( 800 parseHostOrNetBiosName( 801 p1, pe, bOctets, ENCODE_ALL, RTL_TEXTENCODING_DONTKNOW, 802 true, NULL) || 803 (scanDomain(p1, pe) > 0 && p1 == pe) 804 ) 805 { 806 m_eScheme = INET_PROT_FILE; // 7th 807 eMechanism = ENCODE_ALL; 808 nFragmentDelimiter = 0x80000000; 809 } 810 } 811 else 812 { 813 sal_Unicode const * pDomainEnd = p1; 814 sal_uInt32 nLabels = scanDomain(pDomainEnd, pEnd); 815 if (nLabels > 0 && pDomainEnd != pEnd && *pDomainEnd == '@') 816 { 817 ++pDomainEnd; 818 if (scanDomain(pDomainEnd, pEnd) > 0 819 && pDomainEnd == pEnd) 820 m_eScheme = INET_PROT_MAILTO; // 2nd 821 } 822 else if (nLabels >= 3 823 && (pDomainEnd == pEnd || *pDomainEnd == '/')) 824 m_eScheme 825 = pDomainEnd - p1 >= 4 826 && (p1[0] == 'f' || p1[0] == 'F') 827 && (p1[1] == 't' || p1[1] == 'T') 828 && (p1[2] == 'p' || p1[2] == 'P') 829 && p1[3] == '.' ? 830 INET_PROT_FTP : INET_PROT_HTTP; // 3rd, 4th 831 } 832 } 833 834 rtl::OUString aSynScheme; 835 if (m_eScheme == INET_PROT_NOT_VALID) { 836 sal_Unicode const * p1 = pPos; 837 aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter); 838 if (aSynScheme.getLength() > 0) 839 { 840 m_eScheme = INET_PROT_GENERIC; 841 pPos = p1; 842 } 843 } 844 845 if (bSmart && m_eScheme == INET_PROT_NOT_VALID && pPos != pEnd 846 && *pPos != nFragmentDelimiter) 847 { 848 m_eScheme = m_eSmartScheme; 849 } 850 851 if (m_eScheme == INET_PROT_NOT_VALID) 852 { 853 setInvalid(); 854 return false; 855 } 856 857 if (m_eScheme != INET_PROT_GENERIC) { 858 aSynScheme = rtl::OUString::createFromAscii(getSchemeInfo().m_pScheme); 859 } 860 m_aScheme.set(aSynAbsURIRef, aSynScheme, aSynAbsURIRef.getLength()); 861 aSynAbsURIRef.append(sal_Unicode(':')); 862 } 863 864 sal_Char cEscapePrefix = getEscapePrefix(); 865 sal_uInt32 nSegmentDelimiter = '/'; 866 sal_uInt32 nAltSegmentDelimiter = 0x80000000; 867 bool bSkippedInitialSlash = false; 868 869 // Parse //<user>;AUTH=<auth>@<host>:<port> or 870 // //<user>:<password>@<host>:<port> or 871 // //<reg_name> 872 if (getSchemeInfo().m_bAuthority) 873 { 874 sal_Unicode const * pUserInfoBegin = 0; 875 sal_Unicode const * pUserInfoEnd = 0; 876 sal_Unicode const * pHostPortBegin = 0; 877 sal_Unicode const * pHostPortEnd = 0; 878 879 switch (m_eScheme) 880 { 881 case INET_PROT_VND_SUN_STAR_HELP: 882 { 883 if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/') 884 { 885 setInvalid(); 886 return false; 887 } 888 aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 889 rtl::OUStringBuffer aSynAuthority; 890 while (pPos < pEnd 891 && *pPos != '/' && *pPos != '?' 892 && *pPos != nFragmentDelimiter) 893 { 894 EscapeType eEscapeType; 895 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 896 cEscapePrefix, eMechanism, 897 eCharset, eEscapeType); 898 appendUCS4(aSynAuthority, nUTF32, eEscapeType, bOctets, 899 PART_AUTHORITY, cEscapePrefix, eCharset, 900 false); 901 } 902 m_aHost.set(aSynAbsURIRef, 903 aSynAuthority.makeStringAndClear(), 904 aSynAbsURIRef.getLength()); 905 // misusing m_aHost to store the authority 906 break; 907 } 908 909 case INET_PROT_VND_SUN_STAR_HIER: 910 { 911 if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') 912 { 913 pPos += 2; 914 aSynAbsURIRef. 915 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 916 rtl::OUStringBuffer aSynAuthority; 917 while (pPos < pEnd 918 && *pPos != '/' && *pPos != '?' 919 && *pPos != nFragmentDelimiter) 920 { 921 EscapeType eEscapeType; 922 sal_uInt32 nUTF32 = getUTF32(pPos, 923 pEnd, 924 bOctets, 925 cEscapePrefix, 926 eMechanism, 927 eCharset, 928 eEscapeType); 929 appendUCS4(aSynAuthority, 930 nUTF32, 931 eEscapeType, 932 bOctets, 933 PART_AUTHORITY, 934 cEscapePrefix, 935 eCharset, 936 false); 937 } 938 if (aSynAuthority.getLength() == 0) 939 { 940 setInvalid(); 941 return false; 942 } 943 m_aHost.set(aSynAbsURIRef, 944 aSynAuthority.makeStringAndClear(), 945 aSynAbsURIRef.getLength()); 946 // misusing m_aHost to store the authority 947 } 948 break; 949 } 950 951 case INET_PROT_VND_SUN_STAR_PKG: 952 { 953 if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/') 954 { 955 setInvalid(); 956 return false; 957 } 958 aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 959 rtl::OUStringBuffer aSynAuthority; 960 while (pPos < pEnd 961 && *pPos != '/' && *pPos != '?' 962 && *pPos != nFragmentDelimiter) 963 { 964 EscapeType eEscapeType; 965 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 966 cEscapePrefix, eMechanism, 967 eCharset, eEscapeType); 968 appendUCS4(aSynAuthority, nUTF32, eEscapeType, bOctets, 969 PART_AUTHORITY, cEscapePrefix, eCharset, 970 false); 971 } 972 if (aSynAuthority.getLength() == 0) 973 { 974 setInvalid(); 975 return false; 976 } 977 m_aHost.set(aSynAbsURIRef, 978 aSynAuthority.makeStringAndClear(), 979 aSynAbsURIRef.getLength()); 980 // misusing m_aHost to store the authority 981 break; 982 } 983 984 case INET_PROT_FILE: 985 if (bSmart) 986 { 987 // The first of the following seven productions that 988 // matches the rest of the input string (and for which the 989 // appropriate style bit is set in eStyle, if applicable) 990 // determines the used notation. The productions use the 991 // auxiliary rules 992 // 993 // domain = label *("." label) 994 // label = alphanum [*(alphanum / "-") alphanum] 995 // alphanum = ALPHA / DIGIT 996 // IPv6reference = "[" IPv6address "]" 997 // IPv6address = hexpart [":" IPv4address] 998 // IPv4address = 1*3DIGIT 3("." 1*3DIGIT) 999 // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) 1000 // hexseq = hex4 *(":" hex4) 1001 // hex4 = 1*4HEXDIG 1002 // path = <any UCS4 character except "#"> 1003 // UCS4 = <any UCS4 character> 1004 1005 // 1st Production (URL): 1006 // "//" [domain / IPv6reference] ["/" *path] 1007 // ["#" *UCS4] 1008 // becomes 1009 // "file://" domain "/" *path ["#" *UCS4] 1010 if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') 1011 { 1012 sal_Unicode const * p1 = pPos + 2; 1013 while (p1 != pEnd && *p1 != '/' && 1014 *p1 != nFragmentDelimiter) 1015 { 1016 ++p1; 1017 } 1018 if (parseHostOrNetBiosName( 1019 pPos + 2, p1, bOctets, ENCODE_ALL, 1020 RTL_TEXTENCODING_DONTKNOW, true, NULL)) 1021 { 1022 aSynAbsURIRef. 1023 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1024 pHostPortBegin = pPos + 2; 1025 pHostPortEnd = p1; 1026 pPos = p1; 1027 break; 1028 } 1029 } 1030 1031 // 2nd Production (MS IE generated 1; FSYS_DOS only): 1032 // "//" ALPHA ":" ["/" *path] ["#" *UCS4] 1033 // becomes 1034 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] 1035 // replacing "\" by "/" within <*path> 1036 // 1037 // 3rd Production (MS IE generated 2; FSYS_DOS only): 1038 // "//" ALPHA ":" ["\" *path] ["#" *UCS4] 1039 // becomes 1040 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] 1041 // replacing "\" by "/" within <*path> 1042 // 1043 // 4th Production (misscounted slashes): 1044 // "//" *path ["#" *UCS4] 1045 // becomes 1046 // "file:///" *path ["#" *UCS4] 1047 if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') 1048 { 1049 aSynAbsURIRef. 1050 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1051 pPos += 2; 1052 bSkippedInitialSlash = true; 1053 if ((eStyle & FSYS_DOS) != 0 1054 && pEnd - pPos >= 2 1055 && INetMIME::isAlpha(pPos[0]) 1056 && pPos[1] == ':' 1057 && (pEnd - pPos == 2 1058 || pPos[2] == '/' || pPos[2] == '\\')) 1059 nAltSegmentDelimiter = '\\'; 1060 break; 1061 } 1062 1063 // 5th Production (Unix): 1064 // "/" *path ["#" *UCS4] 1065 // becomes 1066 // "file:///" *path ["#" *UCS4] 1067 if (pPos < pEnd && *pPos == '/') 1068 { 1069 aSynAbsURIRef. 1070 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1071 break; 1072 } 1073 1074 // 6th Production (UNC; FSYS_DOS only): 1075 // "\\" domain ["\" *path] ["#" *UCS4] 1076 // becomes 1077 // "file://" domain "/" *path ["#" *UCS4] 1078 // replacing "\" by "/" within <*path> 1079 if (eStyle & FSYS_DOS 1080 && pEnd - pPos >= 2 1081 && pPos[0] == '\\' 1082 && pPos[1] == '\\') 1083 { 1084 sal_Unicode const * p1 = pPos + 2; 1085 sal_Unicode const * pe = p1; 1086 while (pe < pEnd && *pe != '\\' && 1087 *pe != nFragmentDelimiter) 1088 { 1089 ++pe; 1090 } 1091 if ( 1092 parseHostOrNetBiosName( 1093 p1, pe, bOctets, ENCODE_ALL, 1094 RTL_TEXTENCODING_DONTKNOW, true, NULL) || 1095 (scanDomain(p1, pe) > 0 && p1 == pe) 1096 ) 1097 { 1098 aSynAbsURIRef. 1099 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1100 pHostPortBegin = pPos + 2; 1101 pHostPortEnd = pe; 1102 pPos = pe; 1103 nSegmentDelimiter = '\\'; 1104 break; 1105 } 1106 } 1107 1108 // 7th Production (Unix-like DOS; FSYS_DOS only): 1109 // ALPHA ":" ["/" *path] ["#" *UCS4] 1110 // becomes 1111 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] 1112 // replacing "\" by "/" within <*path> 1113 // 1114 // 8th Production (DOS; FSYS_DOS only): 1115 // ALPHA ":" ["\" *path] ["#" *UCS4] 1116 // becomes 1117 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] 1118 // replacing "\" by "/" within <*path> 1119 if (eStyle & FSYS_DOS 1120 && pEnd - pPos >= 2 1121 && INetMIME::isAlpha(pPos[0]) 1122 && pPos[1] == ':' 1123 && (pEnd - pPos == 2 1124 || pPos[2] == '/' 1125 || pPos[2] == '\\')) 1126 { 1127 aSynAbsURIRef. 1128 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1129 nAltSegmentDelimiter = '\\'; 1130 bSkippedInitialSlash = true; 1131 break; 1132 } 1133 1134 // 9th Production (any): 1135 // *path ["#" *UCS4] 1136 // becomes 1137 // "file:///" *path ["#" *UCS4] 1138 // replacing the delimiter by "/" within <*path>. The 1139 // delimiter is that character from the set { "/", "\", 1140 // ":" } which appears most often in <*path> (if FSYS_UNX 1141 // is not among the style bits, "/" is removed from the 1142 // set; if FSYS_DOS is not among the style bits, "\" is 1143 // removed from the set; if FSYS_MAC is not among the 1144 // style bits, ":" is removed from the set). If two or 1145 // more characters appear the same number of times, the 1146 // character mentioned first in that set is chosen. If 1147 // the first character of <*path> is the delimiter, that 1148 // character is not copied. 1149 if (eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC)) 1150 { 1151 aSynAbsURIRef. 1152 appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1153 switch (guessFSysStyleByCounting(pPos, pEnd, eStyle)) 1154 { 1155 case FSYS_UNX: 1156 nSegmentDelimiter = '/'; 1157 break; 1158 1159 case FSYS_DOS: 1160 nSegmentDelimiter = '\\'; 1161 break; 1162 1163 case FSYS_MAC: 1164 nSegmentDelimiter = ':'; 1165 break; 1166 1167 default: 1168 DBG_ERROR( 1169 "INetURLObject::setAbsURIRef():" 1170 " Bad guessFSysStyleByCounting"); 1171 break; 1172 } 1173 bSkippedInitialSlash 1174 = pPos != pEnd && *pPos != nSegmentDelimiter; 1175 break; 1176 } 1177 } 1178 default: 1179 { 1180 // For INET_PROT_FILE, allow an empty authority ("//") to be 1181 // missing if the following path starts with an explicit "/" 1182 // (Java is notorious in generating such file URLs, so be 1183 // liberal here): 1184 if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') 1185 pPos += 2; 1186 else if (!bSmart 1187 && !(m_eScheme == INET_PROT_FILE 1188 && pPos != pEnd && *pPos == '/')) 1189 { 1190 setInvalid(); 1191 return false; 1192 } 1193 aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1194 1195 sal_Unicode const * pAuthority = pPos; 1196 sal_uInt32 c = getSchemeInfo().m_bQuery ? '?' : 0x80000000; 1197 while (pPos < pEnd && *pPos != '/' && *pPos != c 1198 && *pPos != nFragmentDelimiter) 1199 ++pPos; 1200 if (getSchemeInfo().m_bUser) 1201 if (getSchemeInfo().m_bHost) 1202 { 1203 sal_Unicode const * p1 = pAuthority; 1204 while (p1 < pPos && *p1 != '@') 1205 ++p1; 1206 if (p1 == pPos) 1207 { 1208 pHostPortBegin = pAuthority; 1209 pHostPortEnd = pPos; 1210 } 1211 else 1212 { 1213 pUserInfoBegin = pAuthority; 1214 pUserInfoEnd = p1; 1215 pHostPortBegin = p1 + 1; 1216 pHostPortEnd = pPos; 1217 } 1218 } 1219 else 1220 { 1221 pUserInfoBegin = pAuthority; 1222 pUserInfoEnd = pPos; 1223 } 1224 else if (getSchemeInfo().m_bHost) 1225 { 1226 pHostPortBegin = pAuthority; 1227 pHostPortEnd = pPos; 1228 } 1229 else if (pPos != pAuthority) 1230 { 1231 setInvalid(); 1232 return false; 1233 } 1234 break; 1235 } 1236 } 1237 1238 if (pUserInfoBegin) 1239 { 1240 Part ePart = m_eScheme == INET_PROT_IMAP ? 1241 PART_IMAP_ACHAR : 1242 m_eScheme == INET_PROT_VIM ? 1243 PART_VIM : 1244 PART_USER_PASSWORD; 1245 bool bSupportsPassword = getSchemeInfo().m_bPassword; 1246 bool bSupportsAuth 1247 = !bSupportsPassword && getSchemeInfo().m_bAuth; 1248 bool bHasAuth = false; 1249 rtl::OUStringBuffer aSynUser; 1250 sal_Unicode const * p1 = pUserInfoBegin; 1251 while (p1 < pUserInfoEnd) 1252 { 1253 EscapeType eEscapeType; 1254 sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets, 1255 cEscapePrefix, eMechanism, 1256 eCharset, eEscapeType); 1257 if (eEscapeType == ESCAPE_NO) 1258 { 1259 if (nUTF32 == ':' && bSupportsPassword) 1260 { 1261 bHasAuth = true; 1262 break; 1263 } 1264 else if (nUTF32 == ';' && bSupportsAuth 1265 && pUserInfoEnd - p1 1266 > RTL_CONSTASCII_LENGTH("auth=") 1267 && INetMIME::equalIgnoreCase( 1268 p1, 1269 p1 + RTL_CONSTASCII_LENGTH("auth="), 1270 "auth=")) 1271 { 1272 p1 += RTL_CONSTASCII_LENGTH("auth="); 1273 bHasAuth = true; 1274 break; 1275 } 1276 } 1277 appendUCS4(aSynUser, nUTF32, eEscapeType, bOctets, ePart, 1278 cEscapePrefix, eCharset, false); 1279 } 1280 m_aUser.set(aSynAbsURIRef, aSynUser.makeStringAndClear(), 1281 aSynAbsURIRef.getLength()); 1282 if (bHasAuth) 1283 { 1284 if (bSupportsPassword) 1285 { 1286 aSynAbsURIRef.append(sal_Unicode(':')); 1287 rtl::OUStringBuffer aSynAuth; 1288 while (p1 < pUserInfoEnd) 1289 { 1290 EscapeType eEscapeType; 1291 sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets, 1292 cEscapePrefix, 1293 eMechanism, eCharset, 1294 eEscapeType); 1295 appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets, 1296 ePart, cEscapePrefix, eCharset, false); 1297 } 1298 m_aAuth.set(aSynAbsURIRef, aSynAuth.makeStringAndClear(), 1299 aSynAbsURIRef.getLength()); 1300 } 1301 else 1302 { 1303 aSynAbsURIRef. 1304 appendAscii(RTL_CONSTASCII_STRINGPARAM(";AUTH=")); 1305 rtl::OUStringBuffer aSynAuth; 1306 while (p1 < pUserInfoEnd) 1307 { 1308 EscapeType eEscapeType; 1309 sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets, 1310 cEscapePrefix, 1311 eMechanism, eCharset, 1312 eEscapeType); 1313 if (!INetMIME::isIMAPAtomChar(nUTF32)) 1314 { 1315 setInvalid(); 1316 return false; 1317 } 1318 appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets, 1319 ePart, cEscapePrefix, eCharset, false); 1320 } 1321 m_aAuth.set(aSynAbsURIRef, aSynAuth.makeStringAndClear(), 1322 aSynAbsURIRef.getLength()); 1323 } 1324 } 1325 if (pHostPortBegin) 1326 aSynAbsURIRef.append(sal_Unicode('@')); 1327 } 1328 1329 if (pHostPortBegin) 1330 { 1331 sal_Unicode const * pPort = pHostPortEnd; 1332 if ( getSchemeInfo().m_bPort && pHostPortBegin < pHostPortEnd ) 1333 { 1334 sal_Unicode const * p1 = pHostPortEnd - 1; 1335 while (p1 > pHostPortBegin && INetMIME::isDigit(*p1)) 1336 --p1; 1337 if (*p1 == ':') 1338 pPort = p1; 1339 } 1340 bool bNetBiosName = false; 1341 switch (m_eScheme) 1342 { 1343 case INET_PROT_FILE: 1344 // If the host equals "LOCALHOST" (unencoded and ignoring 1345 // case), turn it into an empty host: 1346 if (INetMIME::equalIgnoreCase(pHostPortBegin, pPort, 1347 "localhost")) 1348 pHostPortBegin = pPort; 1349 bNetBiosName = true; 1350 break; 1351 1352 case INET_PROT_LDAP: 1353 case INET_PROT_SMB: 1354 if (pHostPortBegin == pPort && pPort != pHostPortEnd) 1355 { 1356 setInvalid(); 1357 return false; 1358 } 1359 break; 1360 default: 1361 if (pHostPortBegin == pPort) 1362 { 1363 setInvalid(); 1364 return false; 1365 } 1366 break; 1367 } 1368 rtl::OUStringBuffer aSynHost; 1369 if (!parseHostOrNetBiosName( 1370 pHostPortBegin, pPort, bOctets, eMechanism, eCharset, 1371 bNetBiosName, &aSynHost)) 1372 { 1373 setInvalid(); 1374 return false; 1375 } 1376 m_aHost.set(aSynAbsURIRef, aSynHost.makeStringAndClear(), 1377 aSynAbsURIRef.getLength()); 1378 if (pPort != pHostPortEnd) 1379 { 1380 aSynAbsURIRef.append(sal_Unicode(':')); 1381 m_aPort.set(aSynAbsURIRef, 1382 rtl::OUString(pPort + 1, pHostPortEnd - (pPort + 1)), 1383 aSynAbsURIRef.getLength()); 1384 } 1385 } 1386 } 1387 1388 // Parse <path> 1389 rtl::OUStringBuffer aSynPath; 1390 if (!parsePath(m_eScheme, &pPos, pEnd, bOctets, eMechanism, eCharset, 1391 bSkippedInitialSlash, nSegmentDelimiter, 1392 nAltSegmentDelimiter, 1393 getSchemeInfo().m_bQuery ? '?' : 0x80000000, 1394 nFragmentDelimiter, aSynPath)) 1395 { 1396 setInvalid(); 1397 return false; 1398 } 1399 m_aPath.set(aSynAbsURIRef, aSynPath.makeStringAndClear(), 1400 aSynAbsURIRef.getLength()); 1401 1402 // Parse ?<query> 1403 if (getSchemeInfo().m_bQuery && pPos < pEnd && *pPos == '?') 1404 { 1405 aSynAbsURIRef.append(sal_Unicode('?')); 1406 rtl::OUStringBuffer aSynQuery; 1407 for (++pPos; pPos < pEnd && *pPos != nFragmentDelimiter;) 1408 { 1409 EscapeType eEscapeType; 1410 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix, 1411 eMechanism, eCharset, eEscapeType); 1412 appendUCS4(aSynQuery, nUTF32, eEscapeType, bOctets, 1413 PART_URIC, cEscapePrefix, eCharset, true); 1414 } 1415 m_aQuery.set(aSynAbsURIRef, aSynQuery.makeStringAndClear(), 1416 aSynAbsURIRef.getLength()); 1417 } 1418 1419 // Parse #<fragment> 1420 if (pPos < pEnd && *pPos == nFragmentDelimiter) 1421 { 1422 aSynAbsURIRef.append(sal_Unicode(nFragmentDelimiter)); 1423 rtl::OUStringBuffer aSynFragment; 1424 for (++pPos; pPos < pEnd;) 1425 { 1426 EscapeType eEscapeType; 1427 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix, 1428 eMechanism, eCharset, eEscapeType); 1429 appendUCS4(aSynFragment, nUTF32, eEscapeType, bOctets, PART_URIC, 1430 cEscapePrefix, eCharset, true); 1431 } 1432 m_aFragment.set(aSynAbsURIRef, aSynFragment.makeStringAndClear(), 1433 aSynAbsURIRef.getLength()); 1434 } 1435 1436 if (pPos != pEnd) 1437 { 1438 setInvalid(); 1439 return false; 1440 } 1441 1442 m_aAbsURIRef = aSynAbsURIRef; 1443 1444 return true; 1445 } 1446 1447 //============================================================================ 1448 bool INetURLObject::convertRelToAbs(rtl::OUString const & rTheRelURIRef, 1449 bool bOctets, 1450 INetURLObject & rTheAbsURIRef, 1451 bool & rWasAbsolute, 1452 EncodeMechanism eMechanism, 1453 rtl_TextEncoding eCharset, 1454 bool bIgnoreFragment, bool bSmart, 1455 bool bRelativeNonURIs, FSysStyle eStyle) 1456 const 1457 { 1458 sal_Unicode const * p = rTheRelURIRef.getStr(); 1459 sal_Unicode const * pEnd = p + rTheRelURIRef.getLength(); 1460 1461 sal_Unicode const * pPrefixBegin = p; 1462 PrefixInfo const * pPrefix = getPrefix(pPrefixBegin, pEnd); 1463 bool hasScheme = pPrefix != 0; 1464 if (!hasScheme) { 1465 pPrefixBegin = p; 1466 hasScheme = parseScheme(&pPrefixBegin, pEnd, '#').getLength() > 0; 1467 } 1468 1469 sal_uInt32 nSegmentDelimiter = '/'; 1470 sal_uInt32 nQueryDelimiter 1471 = !bSmart || getSchemeInfo().m_bQuery ? '?' : 0x80000000; 1472 sal_uInt32 nFragmentDelimiter = '#'; 1473 Part ePart = PART_VISIBLE; 1474 1475 if (!hasScheme && bSmart) 1476 { 1477 // If the input matches any of the following productions (for which 1478 // the appropriate style bit is set in eStyle), it is assumed to be an 1479 // absolute file system path, rather than a relative URI reference. 1480 // (This is only a subset of the productions used for scheme detection 1481 // in INetURLObject::setAbsURIRef(), because most of those productions 1482 // interfere with the syntax of relative URI references.) The 1483 // productions use the auxiliary rules 1484 // 1485 // domain = label *("." label) 1486 // label = alphanum [*(alphanum / "-") alphanum] 1487 // alphanum = ALPHA / DIGIT 1488 // UCS4 = <any UCS4 character> 1489 // 1490 // 1st Production (UNC file; FSYS_DOS only): 1491 // "\\" domain ["\" *UCS4] 1492 // 1493 // 2nd Production (Unix-like DOS file; FSYS_DOS only): 1494 // ALPHA ":" ["/" *UCS4] 1495 // 1496 // 3rd Production (DOS file; FSYS_DOS only): 1497 // ALPHA ":" ["\" *UCS4] 1498 if (eStyle & FSYS_DOS) 1499 { 1500 bool bFSys = false; 1501 sal_Unicode const * q = p; 1502 if (pEnd - q >= 2 1503 && INetMIME::isAlpha(q[0]) 1504 && q[1] == ':' 1505 && (pEnd - q == 2 || q[2] == '/' || q[2] == '\\')) 1506 bFSys = true; // 2nd, 3rd 1507 else if (pEnd - q >= 2 && q[0] == '\\' && q[1] == '\\') 1508 { 1509 q += 2; 1510 sal_Int32 n = rtl_ustr_indexOfChar_WithLength( 1511 q, pEnd - q, '\\'); 1512 sal_Unicode const * qe = n == -1 ? pEnd : q + n; 1513 if (parseHostOrNetBiosName( 1514 q, qe, bOctets, ENCODE_ALL, RTL_TEXTENCODING_DONTKNOW, 1515 true, NULL)) 1516 { 1517 bFSys = true; // 1st 1518 } 1519 } 1520 if (bFSys) 1521 { 1522 INetURLObject aNewURI; 1523 aNewURI.setAbsURIRef(rTheRelURIRef, bOctets, eMechanism, 1524 eCharset, true, eStyle); 1525 if (!aNewURI.HasError()) 1526 { 1527 rTheAbsURIRef = aNewURI; 1528 rWasAbsolute = true; 1529 return true; 1530 } 1531 } 1532 } 1533 1534 // When the base URL is a file URL, accept relative file system paths 1535 // using "\" or ":" as delimiter (and ignoring URI conventions for "%" 1536 // and "#"), as well as relative URIs using "/" as delimiter: 1537 if (m_eScheme == INET_PROT_FILE) 1538 switch (guessFSysStyleByCounting(p, pEnd, eStyle)) 1539 { 1540 case FSYS_UNX: 1541 nSegmentDelimiter = '/'; 1542 break; 1543 1544 case FSYS_DOS: 1545 nSegmentDelimiter = '\\'; 1546 bRelativeNonURIs = true; 1547 break; 1548 1549 case FSYS_MAC: 1550 nSegmentDelimiter = ':'; 1551 bRelativeNonURIs = true; 1552 break; 1553 1554 default: 1555 DBG_ERROR("INetURLObject::convertRelToAbs():" 1556 " Bad guessFSysStyleByCounting"); 1557 break; 1558 } 1559 1560 if (bRelativeNonURIs) 1561 { 1562 eMechanism = ENCODE_ALL; 1563 nQueryDelimiter = 0x80000000; 1564 nFragmentDelimiter = 0x80000000; 1565 ePart = PART_VISIBLE_NONSPECIAL; 1566 } 1567 } 1568 1569 // If the relative URI has the same scheme as the base URI, and that 1570 // scheme is hierarchical, then ignore its presence in the relative 1571 // URI in order to be backward compatible (cf. RFC 2396 section 5.2 1572 // step 3): 1573 if (pPrefix && pPrefix->m_eScheme == m_eScheme 1574 && getSchemeInfo().m_bHierarchical) 1575 { 1576 hasScheme = false; 1577 while (p != pEnd && *p++ != ':') ; 1578 } 1579 rWasAbsolute = hasScheme; 1580 1581 // Fast solution for non-relative URIs: 1582 if (hasScheme) 1583 { 1584 INetURLObject aNewURI(rTheRelURIRef, eMechanism, eCharset); 1585 if (aNewURI.HasError()) 1586 { 1587 rWasAbsolute = false; 1588 return false; 1589 } 1590 1591 if (bIgnoreFragment) 1592 aNewURI.clearFragment(); 1593 rTheAbsURIRef = aNewURI; 1594 return true; 1595 } 1596 1597 enum State { STATE_AUTH, STATE_ABS_PATH, STATE_REL_PATH, STATE_FRAGMENT, 1598 STATE_DONE }; 1599 1600 rtl::OUStringBuffer aSynAbsURIRef; 1601 // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme 1602 // is empty ("") in that case, so take the scheme from m_aAbsURIRef 1603 if (m_eScheme != INET_PROT_GENERIC) 1604 { 1605 aSynAbsURIRef.appendAscii(getSchemeInfo().m_pScheme); 1606 } 1607 else 1608 { 1609 sal_Unicode const * pSchemeBegin 1610 = m_aAbsURIRef.getStr(); 1611 sal_Unicode const * pSchemeEnd = pSchemeBegin; 1612 while (pSchemeEnd[0] != ':') 1613 { 1614 ++pSchemeEnd; 1615 } 1616 aSynAbsURIRef.append(pSchemeBegin, pSchemeEnd - pSchemeBegin); 1617 } 1618 aSynAbsURIRef.append(sal_Unicode(':')); 1619 1620 sal_Char cEscapePrefix = getEscapePrefix(); 1621 1622 State eState = STATE_AUTH; 1623 bool bSameDoc = true; 1624 1625 if (getSchemeInfo().m_bAuthority) 1626 { 1627 if (pEnd - p >= 2 && p[0] == '/' && p[1] == '/') 1628 { 1629 aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 1630 p += 2; 1631 eState = STATE_ABS_PATH; 1632 bSameDoc = false; 1633 while (p != pEnd) 1634 { 1635 EscapeType eEscapeType; 1636 sal_uInt32 nUTF32 1637 = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism, 1638 eCharset, eEscapeType); 1639 if (eEscapeType == ESCAPE_NO) 1640 { 1641 if (nUTF32 == nSegmentDelimiter) 1642 break; 1643 else if (nUTF32 == nFragmentDelimiter) 1644 { 1645 eState = STATE_FRAGMENT; 1646 break; 1647 } 1648 } 1649 appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, 1650 PART_VISIBLE, cEscapePrefix, eCharset, true); 1651 } 1652 } 1653 else 1654 { 1655 SubString aAuthority(getAuthority()); 1656 aSynAbsURIRef.append(m_aAbsURIRef.getStr() 1657 + aAuthority.getBegin(), 1658 aAuthority.getLength()); 1659 } 1660 } 1661 1662 if (eState == STATE_AUTH) 1663 { 1664 if (p == pEnd) 1665 eState = STATE_DONE; 1666 else if (*p == nFragmentDelimiter) 1667 { 1668 ++p; 1669 eState = STATE_FRAGMENT; 1670 } 1671 else if (*p == nSegmentDelimiter) 1672 { 1673 ++p; 1674 eState = STATE_ABS_PATH; 1675 bSameDoc = false; 1676 } 1677 else 1678 { 1679 eState = STATE_REL_PATH; 1680 bSameDoc = false; 1681 } 1682 } 1683 1684 if (eState == STATE_ABS_PATH) 1685 { 1686 aSynAbsURIRef.append(sal_Unicode('/')); 1687 eState = STATE_DONE; 1688 while (p != pEnd) 1689 { 1690 EscapeType eEscapeType; 1691 sal_uInt32 nUTF32 1692 = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism, 1693 eCharset, eEscapeType); 1694 if (eEscapeType == ESCAPE_NO) 1695 { 1696 if (nUTF32 == nFragmentDelimiter) 1697 { 1698 eState = STATE_FRAGMENT; 1699 break; 1700 } 1701 else if (nUTF32 == nSegmentDelimiter) 1702 nUTF32 = '/'; 1703 } 1704 appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart, 1705 cEscapePrefix, eCharset, true); 1706 } 1707 } 1708 else if (eState == STATE_REL_PATH) 1709 { 1710 if (!getSchemeInfo().m_bHierarchical) 1711 { 1712 // Detect cases where a relative input could not be made absolute 1713 // because the given base URL is broken (most probably because it is 1714 // empty): 1715 OSL_ASSERT(!HasError()); 1716 rWasAbsolute = false; 1717 return false; 1718 } 1719 1720 sal_Unicode const * pBasePathBegin 1721 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 1722 sal_Unicode const * pBasePathEnd 1723 = pBasePathBegin + m_aPath.getLength(); 1724 while (pBasePathEnd != pBasePathBegin) 1725 if (*(--pBasePathEnd) == '/') 1726 { 1727 ++pBasePathEnd; 1728 break; 1729 } 1730 1731 sal_Int32 nPathBegin = aSynAbsURIRef.getLength(); 1732 aSynAbsURIRef.append(pBasePathBegin, pBasePathEnd - pBasePathBegin); 1733 DBG_ASSERT(aSynAbsURIRef.getLength() > nPathBegin 1734 && aSynAbsURIRef.charAt(aSynAbsURIRef.getLength() - 1) == '/', 1735 "INetURLObject::convertRelToAbs(): Bad base path"); 1736 1737 while (p != pEnd && *p != nQueryDelimiter && *p != nFragmentDelimiter) 1738 { 1739 if (*p == '.') 1740 { 1741 if (pEnd - p == 1 1742 || p[1] == nSegmentDelimiter 1743 || p[1] == nQueryDelimiter 1744 || p[1] == nFragmentDelimiter) 1745 { 1746 ++p; 1747 if (p != pEnd && *p == nSegmentDelimiter) 1748 ++p; 1749 continue; 1750 } 1751 else if (pEnd - p >= 2 1752 && p[1] == '.' 1753 && (pEnd - p == 2 1754 || p[2] == nSegmentDelimiter 1755 || p[2] == nQueryDelimiter 1756 || p[2] == nFragmentDelimiter) 1757 && aSynAbsURIRef.getLength() - nPathBegin > 1) 1758 { 1759 p += 2; 1760 if (p != pEnd && *p == nSegmentDelimiter) 1761 ++p; 1762 1763 sal_Int32 i = aSynAbsURIRef.getLength() - 2; 1764 while (i > nPathBegin && aSynAbsURIRef.charAt(i) != '/') 1765 --i; 1766 aSynAbsURIRef.setLength(i + 1); 1767 DBG_ASSERT( 1768 aSynAbsURIRef.getLength() > nPathBegin 1769 && aSynAbsURIRef.charAt(aSynAbsURIRef.getLength() - 1) 1770 == '/', 1771 "INetURLObject::convertRelToAbs(): Bad base path"); 1772 continue; 1773 } 1774 } 1775 1776 while (p != pEnd 1777 && *p != nSegmentDelimiter 1778 && *p != nQueryDelimiter 1779 && *p != nFragmentDelimiter) 1780 { 1781 EscapeType eEscapeType; 1782 sal_uInt32 nUTF32 1783 = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism, 1784 eCharset, eEscapeType); 1785 appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart, 1786 cEscapePrefix, eCharset, true); 1787 } 1788 if (p != pEnd && *p == nSegmentDelimiter) 1789 { 1790 aSynAbsURIRef.append(sal_Unicode('/')); 1791 ++p; 1792 } 1793 } 1794 1795 while (p != pEnd && *p != nFragmentDelimiter) 1796 { 1797 EscapeType eEscapeType; 1798 sal_uInt32 nUTF32 1799 = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism, 1800 eCharset, eEscapeType); 1801 appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart, 1802 cEscapePrefix, eCharset, true); 1803 } 1804 1805 if (p == pEnd) 1806 eState = STATE_DONE; 1807 else 1808 { 1809 ++p; 1810 eState = STATE_FRAGMENT; 1811 } 1812 } 1813 else if (bSameDoc) 1814 { 1815 aSynAbsURIRef.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(), 1816 m_aPath.getLength()); 1817 if (m_aQuery.isPresent()) 1818 aSynAbsURIRef.append(m_aAbsURIRef.getStr() 1819 + m_aQuery.getBegin() - 1, 1820 m_aQuery.getLength() + 1); 1821 } 1822 1823 if (eState == STATE_FRAGMENT && !bIgnoreFragment) 1824 { 1825 aSynAbsURIRef.append(sal_Unicode('#')); 1826 while (p != pEnd) 1827 { 1828 EscapeType eEscapeType; 1829 sal_uInt32 nUTF32 1830 = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism, 1831 eCharset, eEscapeType); 1832 appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, 1833 PART_VISIBLE, cEscapePrefix, eCharset, true); 1834 } 1835 } 1836 1837 INetURLObject aNewURI(aSynAbsURIRef.makeStringAndClear()); 1838 if (aNewURI.HasError()) 1839 { 1840 // Detect cases where a relative input could not be made absolute 1841 // because the given base URL is broken (most probably because it is 1842 // empty): 1843 OSL_ASSERT(!HasError()); 1844 rWasAbsolute = false; 1845 return false; 1846 } 1847 1848 rTheAbsURIRef = aNewURI; 1849 return true; 1850 } 1851 1852 //============================================================================ 1853 bool INetURLObject::convertAbsToRel(rtl::OUString const & rTheAbsURIRef, 1854 bool bOctets, rtl::OUString & rTheRelURIRef, 1855 EncodeMechanism eEncodeMechanism, 1856 DecodeMechanism eDecodeMechanism, 1857 rtl_TextEncoding eCharset, 1858 FSysStyle eStyle) const 1859 { 1860 // Check for hierarchical base URL: 1861 if (!getSchemeInfo().m_bHierarchical) 1862 { 1863 rTheRelURIRef 1864 = decode(rTheAbsURIRef, 1865 getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)), 1866 eDecodeMechanism, eCharset); 1867 return false; 1868 } 1869 1870 // Convert the input (absolute or relative URI ref) to an absolute URI 1871 // ref: 1872 INetURLObject aSubject; 1873 bool bWasAbsolute; 1874 if (!convertRelToAbs(rTheAbsURIRef, bOctets, aSubject, bWasAbsolute, 1875 eEncodeMechanism, eCharset, false, false, false, 1876 eStyle)) 1877 { 1878 rTheRelURIRef 1879 = decode(rTheAbsURIRef, 1880 getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)), 1881 eDecodeMechanism, eCharset); 1882 return false; 1883 } 1884 1885 // Check for differing scheme or authority parts: 1886 if ((m_aScheme.compare( 1887 aSubject.m_aScheme, m_aAbsURIRef, aSubject.m_aAbsURIRef) 1888 != 0) 1889 || (m_aUser.compare( 1890 aSubject.m_aUser, m_aAbsURIRef, aSubject.m_aAbsURIRef) 1891 != 0) 1892 || (m_aAuth.compare( 1893 aSubject.m_aAuth, m_aAbsURIRef, aSubject.m_aAbsURIRef) 1894 != 0) 1895 || (m_aHost.compare( 1896 aSubject.m_aHost, m_aAbsURIRef, aSubject.m_aAbsURIRef) 1897 != 0) 1898 || (m_aPort.compare( 1899 aSubject.m_aPort, m_aAbsURIRef, aSubject.m_aAbsURIRef) 1900 != 0)) 1901 { 1902 rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); 1903 return false; 1904 } 1905 1906 sal_Unicode const * pBasePathBegin 1907 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 1908 sal_Unicode const * pBasePathEnd = pBasePathBegin + m_aPath.getLength(); 1909 sal_Unicode const * pSubjectPathBegin 1910 = aSubject.m_aAbsURIRef.getStr() + aSubject.m_aPath.getBegin(); 1911 sal_Unicode const * pSubjectPathEnd 1912 = pSubjectPathBegin + aSubject.m_aPath.getLength(); 1913 1914 // Make nMatch point past the last matching slash, or past the end of the 1915 // paths, in case they are equal: 1916 sal_Unicode const * pSlash = 0; 1917 sal_Unicode const * p1 = pBasePathBegin; 1918 sal_Unicode const * p2 = pSubjectPathBegin; 1919 for (;;) 1920 { 1921 if (p1 == pBasePathEnd || p2 == pSubjectPathEnd) 1922 { 1923 if (p1 == pBasePathEnd && p2 == pSubjectPathEnd) 1924 pSlash = p1; 1925 break; 1926 } 1927 1928 sal_Unicode c = *p1++; 1929 if (c != *p2++) 1930 break; 1931 if (c == '/') 1932 pSlash = p1; 1933 } 1934 if (!pSlash) 1935 { 1936 // One of the paths does not start with '/': 1937 rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); 1938 return false; 1939 } 1940 sal_Int32 nMatch = pSlash - pBasePathBegin; 1941 1942 // If the two URLs are DOS file URLs starting with different volumes 1943 // (e.g., file:///a:/... and file:///b:/...), the subject is not made 1944 // relative (it could be, but some people do not like that): 1945 if (m_eScheme == INET_PROT_FILE 1946 && nMatch <= 1 1947 && hasDosVolume(eStyle) 1948 && aSubject.hasDosVolume(eStyle)) //TODO! ok to use eStyle for these? 1949 { 1950 rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); 1951 return false; 1952 } 1953 1954 // For every slash in the base path after nMatch, a prefix of "../" is 1955 // added to the new relative URL (if the common prefix of the two paths is 1956 // only "/"---but see handling of file URLs above---, the complete subject 1957 // path could go into the new relative URL instead, but some people don't 1958 // like that): 1959 rtl::OUStringBuffer aSynRelURIRef; 1960 // if (nMatch <= 1) nMatch = 0; else // see comment above 1961 for (sal_Unicode const * p = pBasePathBegin + nMatch; p != pBasePathEnd; 1962 ++p) 1963 { 1964 if (*p == '/') 1965 aSynRelURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("../")); 1966 } 1967 1968 // If the new relative URL would start with "//" (i.e., it would be 1969 // mistaken for a relative URL starting with an authority part), or if the 1970 // new relative URL would neither be empty nor start with <"/"> nor start 1971 // with <1*rseg> (i.e., it could be mistaken for an absolute URL starting 1972 // with a scheme part), then the new relative URL is prefixed with "./": 1973 if (aSynRelURIRef.getLength() == 0) 1974 { 1975 if (pSubjectPathEnd - pSubjectPathBegin >= nMatch + 2 1976 && pSubjectPathBegin[nMatch] == '/' 1977 && pSubjectPathBegin[nMatch + 1] == '/') 1978 { 1979 aSynRelURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("./")); 1980 } 1981 else 1982 { 1983 for (sal_Unicode const * p = pSubjectPathBegin + nMatch; 1984 p != pSubjectPathEnd && *p != '/'; ++p) 1985 { 1986 if (mustEncode(*p, PART_REL_SEGMENT_EXTRA)) 1987 { 1988 aSynRelURIRef. 1989 appendAscii(RTL_CONSTASCII_STRINGPARAM("./")); 1990 break; 1991 } 1992 } 1993 } 1994 } 1995 1996 // The remainder of the subject path, starting at nMatch, is appended to 1997 // the new relative URL: 1998 sal_Char cEscapePrefix = getEscapePrefix(); 1999 aSynRelURIRef.append(decode(pSubjectPathBegin + nMatch, pSubjectPathEnd, 2000 cEscapePrefix, eDecodeMechanism, eCharset)); 2001 2002 // If the subject has defined query or fragment parts, they are appended 2003 // to the new relative URL: 2004 if (aSubject.m_aQuery.isPresent()) 2005 { 2006 aSynRelURIRef.append(sal_Unicode('?')); 2007 aSynRelURIRef.append(aSubject.decode(aSubject.m_aQuery, cEscapePrefix, 2008 eDecodeMechanism, eCharset)); 2009 } 2010 if (aSubject.m_aFragment.isPresent()) 2011 { 2012 aSynRelURIRef.append(sal_Unicode('#')); 2013 aSynRelURIRef.append(aSubject.decode(aSubject.m_aFragment, 2014 cEscapePrefix, eDecodeMechanism, eCharset)); 2015 } 2016 2017 rTheRelURIRef = aSynRelURIRef.makeStringAndClear(); 2018 return true; 2019 } 2020 2021 //============================================================================ 2022 // static 2023 bool INetURLObject::convertIntToExt(rtl::OUString const & rTheIntURIRef, 2024 bool bOctets, rtl::OUString & rTheExtURIRef, 2025 DecodeMechanism eDecodeMechanism, 2026 rtl_TextEncoding eCharset) 2027 { 2028 sal_Char cEscapePrefix 2029 = getEscapePrefix(CompareProtocolScheme(rTheIntURIRef)); 2030 rtl::OUString aSynExtURIRef(encodeText(rTheIntURIRef, bOctets, PART_VISIBLE, 2031 cEscapePrefix, NOT_CANONIC, eCharset, 2032 true)); 2033 sal_Unicode const * pBegin = aSynExtURIRef.getStr(); 2034 sal_Unicode const * pEnd = pBegin + aSynExtURIRef.getLength(); 2035 sal_Unicode const * p = pBegin; 2036 PrefixInfo const * pPrefix = getPrefix(p, pEnd); 2037 bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::INTERNAL; 2038 if (bConvert) 2039 { 2040 aSynExtURIRef = 2041 aSynExtURIRef.replaceAt(0, p - pBegin, 2042 rtl::OUString::createFromAscii(pPrefix->m_pTranslatedPrefix)); 2043 } 2044 rTheExtURIRef = decode(aSynExtURIRef, cEscapePrefix, eDecodeMechanism, 2045 eCharset); 2046 return bConvert; 2047 } 2048 2049 //============================================================================ 2050 // static 2051 bool INetURLObject::convertExtToInt(rtl::OUString const & rTheExtURIRef, 2052 bool bOctets, rtl::OUString & rTheIntURIRef, 2053 DecodeMechanism eDecodeMechanism, 2054 rtl_TextEncoding eCharset) 2055 { 2056 sal_Char cEscapePrefix 2057 = getEscapePrefix(CompareProtocolScheme(rTheExtURIRef)); 2058 rtl::OUString aSynIntURIRef(encodeText(rTheExtURIRef, bOctets, PART_VISIBLE, 2059 cEscapePrefix, NOT_CANONIC, eCharset, 2060 true)); 2061 sal_Unicode const * pBegin = aSynIntURIRef.getStr(); 2062 sal_Unicode const * pEnd = pBegin + aSynIntURIRef.getLength(); 2063 sal_Unicode const * p = pBegin; 2064 PrefixInfo const * pPrefix = getPrefix(p, pEnd); 2065 bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::EXTERNAL; 2066 if (bConvert) 2067 { 2068 aSynIntURIRef = 2069 aSynIntURIRef.replaceAt(0, p - pBegin, 2070 rtl::OUString::createFromAscii(pPrefix->m_pTranslatedPrefix)); 2071 } 2072 rTheIntURIRef = decode(aSynIntURIRef, cEscapePrefix, eDecodeMechanism, 2073 eCharset); 2074 return bConvert; 2075 } 2076 2077 //============================================================================ 2078 // static 2079 INetURLObject::PrefixInfo const * 2080 INetURLObject::getPrefix(sal_Unicode const *& rBegin, 2081 sal_Unicode const * pEnd) 2082 { 2083 static PrefixInfo const aMap[] 2084 = { // dummy entry at front needed, because pLast may point here: 2085 { 0, 0, INET_PROT_NOT_VALID, PrefixInfo::INTERNAL }, 2086 { ".component:", "staroffice.component:", INET_PROT_COMPONENT, 2087 PrefixInfo::INTERNAL }, 2088 { ".uno:", "staroffice.uno:", INET_PROT_UNO, 2089 PrefixInfo::INTERNAL }, 2090 { "cid:", 0, INET_PROT_CID, PrefixInfo::OFFICIAL }, 2091 { "data:", 0, INET_PROT_DATA, PrefixInfo::OFFICIAL }, 2092 { "db:", "staroffice.db:", INET_PROT_DB, PrefixInfo::INTERNAL }, 2093 { "file:", 0, INET_PROT_FILE, PrefixInfo::OFFICIAL }, 2094 { "ftp:", 0, INET_PROT_FTP, PrefixInfo::OFFICIAL }, 2095 { "hid:", "staroffice.hid:", INET_PROT_HID, 2096 PrefixInfo::INTERNAL }, 2097 { "http:", 0, INET_PROT_HTTP, PrefixInfo::OFFICIAL }, 2098 { "https:", 0, INET_PROT_HTTPS, PrefixInfo::OFFICIAL }, 2099 { "imap:", 0, INET_PROT_IMAP, PrefixInfo::OFFICIAL }, 2100 { "javascript:", 0, INET_PROT_JAVASCRIPT, PrefixInfo::OFFICIAL }, 2101 { "ldap:", 0, INET_PROT_LDAP, PrefixInfo::OFFICIAL }, 2102 { "macro:", "staroffice.macro:", INET_PROT_MACRO, 2103 PrefixInfo::INTERNAL }, 2104 { "mailto:", 0, INET_PROT_MAILTO, PrefixInfo::OFFICIAL }, 2105 { "news:", 0, INET_PROT_NEWS, PrefixInfo::OFFICIAL }, 2106 { "out:", "staroffice.out:", INET_PROT_OUT, 2107 PrefixInfo::INTERNAL }, 2108 { "pop3:", "staroffice.pop3:", INET_PROT_POP3, 2109 PrefixInfo::INTERNAL }, 2110 { "private:", "staroffice.private:", INET_PROT_PRIV_SOFFICE, 2111 PrefixInfo::INTERNAL }, 2112 { "private:factory/", "staroffice.factory:", 2113 INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL }, 2114 { "private:helpid/", "staroffice.helpid:", INET_PROT_PRIV_SOFFICE, 2115 PrefixInfo::INTERNAL }, 2116 { "private:java/", "staroffice.java:", INET_PROT_PRIV_SOFFICE, 2117 PrefixInfo::INTERNAL }, 2118 { "private:searchfolder:", "staroffice.searchfolder:", 2119 INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL }, 2120 { "private:trashcan:", "staroffice.trashcan:", 2121 INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL }, 2122 { "slot:", "staroffice.slot:", INET_PROT_SLOT, 2123 PrefixInfo::INTERNAL }, 2124 { "smb:", 0, INET_PROT_SMB, PrefixInfo::OFFICIAL }, 2125 { "staroffice.component:", ".component:", INET_PROT_COMPONENT, 2126 PrefixInfo::EXTERNAL }, 2127 { "staroffice.db:", "db:", INET_PROT_DB, PrefixInfo::EXTERNAL }, 2128 { "staroffice.factory:", "private:factory/", 2129 INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL }, 2130 { "staroffice.helpid:", "private:helpid/", INET_PROT_PRIV_SOFFICE, 2131 PrefixInfo::EXTERNAL }, 2132 { "staroffice.hid:", "hid:", INET_PROT_HID, 2133 PrefixInfo::EXTERNAL }, 2134 { "staroffice.java:", "private:java/", INET_PROT_PRIV_SOFFICE, 2135 PrefixInfo::EXTERNAL }, 2136 { "staroffice.macro:", "macro:", INET_PROT_MACRO, 2137 PrefixInfo::EXTERNAL }, 2138 { "staroffice.out:", "out:", INET_PROT_OUT, 2139 PrefixInfo::EXTERNAL }, 2140 { "staroffice.pop3:", "pop3:", INET_PROT_POP3, 2141 PrefixInfo::EXTERNAL }, 2142 { "staroffice.private:", "private:", INET_PROT_PRIV_SOFFICE, 2143 PrefixInfo::EXTERNAL }, 2144 { "staroffice.searchfolder:", "private:searchfolder:", 2145 INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL }, 2146 { "staroffice.slot:", "slot:", INET_PROT_SLOT, 2147 PrefixInfo::EXTERNAL }, 2148 { "staroffice.trashcan:", "private:trashcan:", 2149 INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL }, 2150 { "staroffice.uno:", ".uno:", INET_PROT_UNO, 2151 PrefixInfo::EXTERNAL }, 2152 { "staroffice.vim:", "vim:", INET_PROT_VIM, 2153 PrefixInfo::EXTERNAL }, 2154 { "staroffice:", "private:", INET_PROT_PRIV_SOFFICE, 2155 PrefixInfo::EXTERNAL }, 2156 { "telnet:", 0, INET_PROT_TELNET, PrefixInfo::OFFICIAL }, 2157 { "vim:", "staroffice.vim:", INET_PROT_VIM, 2158 PrefixInfo::INTERNAL }, 2159 { "vnd.sun.star.cmd:", 0, INET_PROT_VND_SUN_STAR_CMD, 2160 PrefixInfo::OFFICIAL }, 2161 { "vnd.sun.star.expand:", 0, INET_PROT_VND_SUN_STAR_EXPAND, 2162 PrefixInfo::OFFICIAL }, 2163 { "vnd.sun.star.help:", 0, INET_PROT_VND_SUN_STAR_HELP, 2164 PrefixInfo::OFFICIAL }, 2165 { "vnd.sun.star.hier:", 0, INET_PROT_VND_SUN_STAR_HIER, 2166 PrefixInfo::OFFICIAL }, 2167 { "vnd.sun.star.odma:", 0, INET_PROT_VND_SUN_STAR_ODMA, 2168 PrefixInfo::OFFICIAL }, 2169 { "vnd.sun.star.pkg:", 0, INET_PROT_VND_SUN_STAR_PKG, 2170 PrefixInfo::OFFICIAL }, 2171 { "vnd.sun.star.tdoc:", 0, INET_PROT_VND_SUN_STAR_TDOC, 2172 PrefixInfo::OFFICIAL }, 2173 { "vnd.sun.star.webdav:", 0, INET_PROT_VND_SUN_STAR_WEBDAV, 2174 PrefixInfo::OFFICIAL } }; 2175 PrefixInfo const * pFirst = aMap + 1; 2176 PrefixInfo const * pLast = aMap + sizeof aMap / sizeof (PrefixInfo) - 1; 2177 PrefixInfo const * pMatch = 0; 2178 sal_Unicode const * pMatched = rBegin; 2179 sal_Unicode const * p = rBegin; 2180 sal_Int32 i = 0; 2181 for (; pFirst < pLast; ++i) 2182 { 2183 if (pFirst->m_pPrefix[i] == '\0') 2184 { 2185 pMatch = pFirst++; 2186 pMatched = p; 2187 } 2188 if (p >= pEnd) 2189 break; 2190 sal_uInt32 nChar = INetMIME::toLowerCase(*p++); 2191 while (pFirst <= pLast && sal_uChar(pFirst->m_pPrefix[i]) < nChar) 2192 ++pFirst; 2193 while (pFirst <= pLast && sal_uChar(pLast->m_pPrefix[i]) > nChar) 2194 --pLast; 2195 } 2196 if (pFirst == pLast) 2197 { 2198 sal_Char const * q = pFirst->m_pPrefix + i; 2199 while (p < pEnd && *q != '\0' 2200 && INetMIME::toLowerCase(*p) == sal_uChar(*q)) 2201 { 2202 ++p; 2203 ++q; 2204 } 2205 if (*q == '\0') 2206 { 2207 rBegin = p; 2208 return pFirst; 2209 } 2210 } 2211 rBegin = pMatched; 2212 return pMatch; 2213 } 2214 2215 //============================================================================ 2216 sal_Int32 INetURLObject::getAuthorityBegin() const 2217 { 2218 DBG_ASSERT(getSchemeInfo().m_bAuthority, 2219 "INetURLObject::getAuthority(): Bad scheme"); 2220 sal_Int32 nBegin; 2221 if (m_aUser.isPresent()) 2222 nBegin = m_aUser.getBegin(); 2223 else if (m_aHost.isPresent()) 2224 nBegin = m_aHost.getBegin(); 2225 else 2226 nBegin = m_aPath.getBegin(); 2227 nBegin -= RTL_CONSTASCII_LENGTH("//"); 2228 DBG_ASSERT(m_aAbsURIRef.charAt(nBegin) == '/' 2229 && m_aAbsURIRef.charAt(nBegin + 1) == '/', 2230 "INetURLObject::getAuthority(): Bad authority"); 2231 return nBegin; 2232 } 2233 2234 //============================================================================ 2235 INetURLObject::SubString INetURLObject::getAuthority() const 2236 { 2237 sal_Int32 nBegin = getAuthorityBegin(); 2238 sal_Int32 nEnd = m_aPort.isPresent() ? m_aPort.getEnd() : 2239 m_aHost.isPresent() ? m_aHost.getEnd() : 2240 m_aAuth.isPresent() ? m_aAuth.getEnd() : 2241 m_aUser.isPresent() ? m_aUser.getEnd() : 2242 nBegin + RTL_CONSTASCII_LENGTH("//"); 2243 return SubString(nBegin, nEnd - nBegin); 2244 } 2245 2246 //============================================================================ 2247 bool INetURLObject::setUser(rtl::OUString const & rTheUser, 2248 bool bOctets, EncodeMechanism eMechanism, 2249 rtl_TextEncoding eCharset) 2250 { 2251 if ( 2252 !getSchemeInfo().m_bUser || 2253 (m_eScheme == INET_PROT_IMAP && rTheUser.getLength() == 0) 2254 ) 2255 { 2256 return false; 2257 } 2258 2259 rtl::OUString aNewUser(encodeText(rTheUser, bOctets, 2260 m_eScheme == INET_PROT_IMAP ? 2261 PART_IMAP_ACHAR : 2262 m_eScheme == INET_PROT_VIM ? 2263 PART_VIM : 2264 PART_USER_PASSWORD, 2265 getEscapePrefix(), eMechanism, eCharset, 2266 false)); 2267 sal_Int32 nDelta; 2268 if (m_aUser.isPresent()) 2269 nDelta = m_aUser.set(m_aAbsURIRef, aNewUser); 2270 else if (m_aHost.isPresent()) 2271 { 2272 m_aAbsURIRef.insert(m_aHost.getBegin(), sal_Unicode('@')); 2273 nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aHost.getBegin()) + 1; 2274 } 2275 else if (getSchemeInfo().m_bHost) 2276 return false; 2277 else 2278 nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aPath.getBegin()); 2279 m_aAuth += nDelta; 2280 m_aHost += nDelta; 2281 m_aPort += nDelta; 2282 m_aPath += nDelta; 2283 m_aQuery += nDelta; 2284 m_aFragment += nDelta; 2285 return true; 2286 } 2287 2288 namespace 2289 { 2290 void lcl_Erase(rtl::OUStringBuffer &rBuf, sal_Int32 index, sal_Int32 count) 2291 { 2292 rtl::OUString sTemp(rBuf.makeStringAndClear()); 2293 rBuf.append(sTemp.replaceAt(index, count, rtl::OUString())); 2294 } 2295 } 2296 2297 //============================================================================ 2298 bool INetURLObject::clearPassword() 2299 { 2300 if (!getSchemeInfo().m_bPassword) 2301 return false; 2302 if (m_aAuth.isPresent()) 2303 { 2304 lcl_Erase(m_aAbsURIRef, m_aAuth.getBegin() - 1, 2305 m_aAuth.getLength() + 1); 2306 sal_Int32 nDelta = m_aAuth.clear() - 1; 2307 m_aHost += nDelta; 2308 m_aPort += nDelta; 2309 m_aPath += nDelta; 2310 m_aQuery += nDelta; 2311 m_aFragment += nDelta; 2312 } 2313 return true; 2314 } 2315 2316 //============================================================================ 2317 bool INetURLObject::setPassword(rtl::OUString const & rThePassword, 2318 bool bOctets, EncodeMechanism eMechanism, 2319 rtl_TextEncoding eCharset) 2320 { 2321 if (!getSchemeInfo().m_bPassword) 2322 return false; 2323 rtl::OUString aNewAuth(encodeText(rThePassword, bOctets, 2324 m_eScheme == INET_PROT_VIM ? 2325 PART_VIM : PART_USER_PASSWORD, 2326 getEscapePrefix(), eMechanism, eCharset, 2327 false)); 2328 sal_Int32 nDelta; 2329 if (m_aAuth.isPresent()) 2330 nDelta = m_aAuth.set(m_aAbsURIRef, aNewAuth); 2331 else if (m_aUser.isPresent()) 2332 { 2333 m_aAbsURIRef.insert(m_aUser.getEnd(), sal_Unicode(':')); 2334 nDelta 2335 = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aUser.getEnd() + 1) + 1; 2336 } 2337 else if (m_aHost.isPresent()) 2338 { 2339 m_aAbsURIRef.insert(m_aHost.getBegin(), 2340 rtl::OUString::createFromAscii(":@")); 2341 m_aUser.set(m_aAbsURIRef, rtl::OUString(), m_aHost.getBegin()); 2342 nDelta 2343 = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aHost.getBegin() + 1) + 2; 2344 } 2345 else if (getSchemeInfo().m_bHost) 2346 return false; 2347 else 2348 { 2349 m_aAbsURIRef.insert(m_aPath.getBegin(), sal_Unicode(':')); 2350 m_aUser.set(m_aAbsURIRef, rtl::OUString(), m_aPath.getBegin()); 2351 nDelta 2352 = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aPath.getBegin() + 1) + 1; 2353 } 2354 m_aHost += nDelta; 2355 m_aPort += nDelta; 2356 m_aPath += nDelta; 2357 m_aQuery += nDelta; 2358 m_aFragment += nDelta; 2359 return true; 2360 } 2361 2362 //============================================================================ 2363 // static 2364 bool INetURLObject::parseHost( 2365 sal_Unicode const *& rBegin, sal_Unicode const * pEnd, 2366 rtl::OUString & rCanonic) 2367 { 2368 // RFC 2373 is inconsistent about how to write an IPv6 address in which an 2369 // IPv4 address directly follows the abbreviating "::". The ABNF in 2370 // Appendix B suggests ":::13.1.68.3", while an example in 2.2/3 explicitly 2371 // mentions "::13:1.68.3". This algorithm accepts both variants: 2372 enum State { STATE_INITIAL, STATE_LABEL, STATE_LABEL_HYPHEN, 2373 STATE_LABEL_DOT, STATE_TOPLABEL, STATE_TOPLABEL_HYPHEN, 2374 STATE_TOPLABEL_DOT, STATE_IP4, STATE_IP4_DOT, STATE_IP6, 2375 STATE_IP6_COLON, STATE_IP6_2COLON, STATE_IP6_3COLON, 2376 STATE_IP6_HEXSEQ1, STATE_IP6_HEXSEQ1_COLON, 2377 STATE_IP6_HEXSEQ1_MAYBE_IP4, STATE_IP6_HEXSEQ2, 2378 STATE_IP6_HEXSEQ2_COLON, STATE_IP6_HEXSEQ2_MAYBE_IP4, 2379 STATE_IP6_IP4, STATE_IP6_IP4_DOT, STATE_IP6_DONE }; 2380 rtl::OUStringBuffer aTheCanonic; 2381 sal_uInt32 nNumber = 0; 2382 int nDigits = 0; 2383 int nOctets = 0; 2384 State eState = STATE_INITIAL; 2385 sal_Unicode const * p = rBegin; 2386 for (; p != pEnd; ++p) 2387 switch (eState) 2388 { 2389 case STATE_INITIAL: 2390 if (*p == '[') 2391 { 2392 aTheCanonic.append(sal_Unicode('[')); 2393 eState = STATE_IP6; 2394 } 2395 else if (INetMIME::isAlpha(*p)) 2396 eState = STATE_TOPLABEL; 2397 else if (INetMIME::isDigit(*p)) 2398 { 2399 nNumber = INetMIME::getWeight(*p); 2400 nDigits = 1; 2401 nOctets = 1; 2402 eState = STATE_IP4; 2403 } 2404 else 2405 goto done; 2406 break; 2407 2408 case STATE_LABEL: 2409 if (*p == '.') 2410 eState = STATE_LABEL_DOT; 2411 else if (*p == '-') 2412 eState = STATE_LABEL_HYPHEN; 2413 else if (!INetMIME::isAlphanumeric(*p)) 2414 goto done; 2415 break; 2416 2417 case STATE_LABEL_HYPHEN: 2418 if (INetMIME::isAlphanumeric(*p)) 2419 eState = STATE_LABEL; 2420 else if (*p != '-') 2421 goto done; 2422 break; 2423 2424 case STATE_LABEL_DOT: 2425 if (INetMIME::isAlpha(*p)) 2426 eState = STATE_TOPLABEL; 2427 else if (INetMIME::isDigit(*p)) 2428 eState = STATE_LABEL; 2429 else 2430 goto done; 2431 break; 2432 2433 case STATE_TOPLABEL: 2434 if (*p == '.') 2435 eState = STATE_TOPLABEL_DOT; 2436 else if (*p == '-') 2437 eState = STATE_TOPLABEL_HYPHEN; 2438 else if (!INetMIME::isAlphanumeric(*p)) 2439 goto done; 2440 break; 2441 2442 case STATE_TOPLABEL_HYPHEN: 2443 if (INetMIME::isAlphanumeric(*p)) 2444 eState = STATE_TOPLABEL; 2445 else if (*p != '-') 2446 goto done; 2447 break; 2448 2449 case STATE_TOPLABEL_DOT: 2450 if (INetMIME::isAlpha(*p)) 2451 eState = STATE_TOPLABEL; 2452 else if (INetMIME::isDigit(*p)) 2453 eState = STATE_LABEL; 2454 else 2455 goto done; 2456 break; 2457 2458 case STATE_IP4: 2459 if (*p == '.') 2460 if (nOctets < 4) 2461 { 2462 aTheCanonic.append( 2463 rtl::OUString::valueOf(sal_Int32(nNumber))); 2464 aTheCanonic.append(sal_Unicode('.')); 2465 ++nOctets; 2466 eState = STATE_IP4_DOT; 2467 } 2468 else 2469 eState = STATE_LABEL_DOT; 2470 else if (*p == '-') 2471 eState = STATE_LABEL_HYPHEN; 2472 else if (INetMIME::isAlpha(*p)) 2473 eState = STATE_LABEL; 2474 else if (INetMIME::isDigit(*p)) 2475 if (nDigits < 3) 2476 { 2477 nNumber = 10 * nNumber + INetMIME::getWeight(*p); 2478 ++nDigits; 2479 } 2480 else 2481 eState = STATE_LABEL; 2482 else 2483 goto done; 2484 break; 2485 2486 case STATE_IP4_DOT: 2487 if (INetMIME::isAlpha(*p)) 2488 eState = STATE_TOPLABEL; 2489 else if (INetMIME::isDigit(*p)) 2490 { 2491 nNumber = INetMIME::getWeight(*p); 2492 nDigits = 1; 2493 eState = STATE_IP4; 2494 } 2495 else 2496 goto done; 2497 break; 2498 2499 case STATE_IP6: 2500 if (*p == ':') 2501 eState = STATE_IP6_COLON; 2502 else if (INetMIME::isHexDigit(*p)) 2503 { 2504 nNumber = INetMIME::getHexWeight(*p); 2505 nDigits = 1; 2506 eState = STATE_IP6_HEXSEQ1; 2507 } 2508 else 2509 goto done; 2510 break; 2511 2512 case STATE_IP6_COLON: 2513 if (*p == ':') 2514 { 2515 aTheCanonic.appendAscii(RTL_CONSTASCII_STRINGPARAM("::")); 2516 eState = STATE_IP6_2COLON; 2517 } 2518 else 2519 goto done; 2520 break; 2521 2522 case STATE_IP6_2COLON: 2523 if (*p == ']') 2524 eState = STATE_IP6_DONE; 2525 else if (*p == ':') 2526 { 2527 aTheCanonic.append(sal_Unicode(':')); 2528 eState = STATE_IP6_3COLON; 2529 } 2530 else if (INetMIME::isDigit(*p)) 2531 { 2532 nNumber = INetMIME::getWeight(*p); 2533 nDigits = 1; 2534 eState = STATE_IP6_HEXSEQ2_MAYBE_IP4; 2535 } 2536 else if (INetMIME::isHexDigit(*p)) 2537 { 2538 nNumber = INetMIME::getHexWeight(*p); 2539 nDigits = 1; 2540 eState = STATE_IP6_HEXSEQ2; 2541 } 2542 else 2543 goto done; 2544 break; 2545 2546 case STATE_IP6_3COLON: 2547 if (INetMIME::isDigit(*p)) 2548 { 2549 nNumber = INetMIME::getWeight(*p); 2550 nDigits = 1; 2551 nOctets = 1; 2552 eState = STATE_IP6_IP4; 2553 } 2554 else 2555 goto done; 2556 break; 2557 2558 case STATE_IP6_HEXSEQ1: 2559 if (*p == ']') 2560 { 2561 aTheCanonic.append( 2562 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2563 eState = STATE_IP6_DONE; 2564 } 2565 else if (*p == ':') 2566 { 2567 aTheCanonic.append( 2568 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2569 aTheCanonic.append(sal_Unicode(':')); 2570 eState = STATE_IP6_HEXSEQ1_COLON; 2571 } 2572 else if (INetMIME::isHexDigit(*p) && nDigits < 4) 2573 { 2574 nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); 2575 ++nDigits; 2576 } 2577 else 2578 goto done; 2579 break; 2580 2581 case STATE_IP6_HEXSEQ1_COLON: 2582 if (*p == ':') 2583 { 2584 aTheCanonic.append(sal_Unicode(':')); 2585 eState = STATE_IP6_2COLON; 2586 } 2587 else if (INetMIME::isDigit(*p)) 2588 { 2589 nNumber = INetMIME::getWeight(*p); 2590 nDigits = 1; 2591 eState = STATE_IP6_HEXSEQ1_MAYBE_IP4; 2592 } 2593 else if (INetMIME::isHexDigit(*p)) 2594 { 2595 nNumber = INetMIME::getHexWeight(*p); 2596 nDigits = 1; 2597 eState = STATE_IP6_HEXSEQ1; 2598 } 2599 else 2600 goto done; 2601 break; 2602 2603 case STATE_IP6_HEXSEQ1_MAYBE_IP4: 2604 if (*p == ']') 2605 { 2606 aTheCanonic.append( 2607 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2608 eState = STATE_IP6_DONE; 2609 } 2610 else if (*p == ':') 2611 { 2612 aTheCanonic.append( 2613 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2614 aTheCanonic.append(sal_Unicode(':')); 2615 eState = STATE_IP6_HEXSEQ1_COLON; 2616 } 2617 else if (*p == '.') 2618 { 2619 nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15) 2620 + (nNumber & 15); 2621 aTheCanonic.append( 2622 rtl::OUString::valueOf(sal_Int32(nNumber))); 2623 aTheCanonic.append(sal_Unicode('.')); 2624 nOctets = 2; 2625 eState = STATE_IP6_IP4_DOT; 2626 } 2627 else if (INetMIME::isDigit(*p) && nDigits < 3) 2628 { 2629 nNumber = 16 * nNumber + INetMIME::getWeight(*p); 2630 ++nDigits; 2631 } 2632 else if (INetMIME::isHexDigit(*p) && nDigits < 4) 2633 { 2634 nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); 2635 ++nDigits; 2636 eState = STATE_IP6_HEXSEQ1; 2637 } 2638 else 2639 goto done; 2640 break; 2641 2642 case STATE_IP6_HEXSEQ2: 2643 if (*p == ']') 2644 { 2645 aTheCanonic.append( 2646 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2647 eState = STATE_IP6_DONE; 2648 } 2649 else if (*p == ':') 2650 { 2651 aTheCanonic.append( 2652 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2653 aTheCanonic.append(sal_Unicode(':')); 2654 eState = STATE_IP6_HEXSEQ2_COLON; 2655 } 2656 else if (INetMIME::isHexDigit(*p) && nDigits < 4) 2657 { 2658 nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); 2659 ++nDigits; 2660 } 2661 else 2662 goto done; 2663 break; 2664 2665 case STATE_IP6_HEXSEQ2_COLON: 2666 if (INetMIME::isDigit(*p)) 2667 { 2668 nNumber = INetMIME::getWeight(*p); 2669 nDigits = 1; 2670 eState = STATE_IP6_HEXSEQ2_MAYBE_IP4; 2671 } 2672 else if (INetMIME::isHexDigit(*p)) 2673 { 2674 nNumber = INetMIME::getHexWeight(*p); 2675 nDigits = 1; 2676 eState = STATE_IP6_HEXSEQ2; 2677 } 2678 else 2679 goto done; 2680 break; 2681 2682 case STATE_IP6_HEXSEQ2_MAYBE_IP4: 2683 if (*p == ']') 2684 { 2685 aTheCanonic.append( 2686 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2687 eState = STATE_IP6_DONE; 2688 } 2689 else if (*p == ':') 2690 { 2691 aTheCanonic.append( 2692 rtl::OUString::valueOf(sal_Int32(nNumber), 16)); 2693 aTheCanonic.append(sal_Unicode(':')); 2694 eState = STATE_IP6_HEXSEQ2_COLON; 2695 } 2696 else if (*p == '.') 2697 { 2698 nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15) 2699 + (nNumber & 15); 2700 aTheCanonic.append( 2701 rtl::OUString::valueOf(sal_Int32(nNumber))); 2702 aTheCanonic.append(sal_Unicode('.')); 2703 nOctets = 2; 2704 eState = STATE_IP6_IP4_DOT; 2705 } 2706 else if (INetMIME::isDigit(*p) && nDigits < 3) 2707 { 2708 nNumber = 16 * nNumber + INetMIME::getWeight(*p); 2709 ++nDigits; 2710 } 2711 else if (INetMIME::isHexDigit(*p) && nDigits < 4) 2712 { 2713 nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); 2714 ++nDigits; 2715 eState = STATE_IP6_HEXSEQ2; 2716 } 2717 else 2718 goto done; 2719 break; 2720 2721 case STATE_IP6_IP4: 2722 if (*p == ']') 2723 if (nOctets == 4) 2724 { 2725 aTheCanonic.append( 2726 rtl::OUString::valueOf(sal_Int32(nNumber))); 2727 eState = STATE_IP6_DONE; 2728 } 2729 else 2730 goto done; 2731 else if (*p == '.') 2732 if (nOctets < 4) 2733 { 2734 aTheCanonic.append( 2735 rtl::OUString::valueOf(sal_Int32(nNumber))); 2736 aTheCanonic.append(sal_Unicode('.')); 2737 ++nOctets; 2738 eState = STATE_IP6_IP4_DOT; 2739 } 2740 else 2741 goto done; 2742 else if (INetMIME::isDigit(*p) && nDigits < 3) 2743 { 2744 nNumber = 10 * nNumber + INetMIME::getWeight(*p); 2745 ++nDigits; 2746 } 2747 else 2748 goto done; 2749 break; 2750 2751 case STATE_IP6_IP4_DOT: 2752 if (INetMIME::isDigit(*p)) 2753 { 2754 nNumber = INetMIME::getWeight(*p); 2755 nDigits = 1; 2756 eState = STATE_IP6_IP4; 2757 } 2758 else 2759 goto done; 2760 break; 2761 2762 case STATE_IP6_DONE: 2763 goto done; 2764 } 2765 done: 2766 switch (eState) 2767 { 2768 case STATE_LABEL: 2769 case STATE_TOPLABEL: 2770 case STATE_TOPLABEL_DOT: 2771 aTheCanonic.setLength(0); 2772 aTheCanonic.append(rBegin, p - rBegin); 2773 rBegin = p; 2774 rCanonic = aTheCanonic.makeStringAndClear(); 2775 return true; 2776 2777 case STATE_IP4: 2778 if (nOctets == 4) 2779 { 2780 aTheCanonic.append( 2781 rtl::OUString::valueOf(sal_Int32(nNumber))); 2782 rBegin = p; 2783 rCanonic = aTheCanonic.makeStringAndClear(); 2784 return true; 2785 } 2786 return false; 2787 2788 case STATE_IP6_DONE: 2789 aTheCanonic.append(sal_Unicode(']')); 2790 rBegin = p; 2791 rCanonic = aTheCanonic.makeStringAndClear(); 2792 return true; 2793 2794 default: 2795 return false; 2796 } 2797 } 2798 2799 //============================================================================ 2800 // static 2801 bool INetURLObject::parseHostOrNetBiosName( 2802 sal_Unicode const * pBegin, sal_Unicode const * pEnd, bool bOctets, 2803 EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bNetBiosName, 2804 rtl::OUStringBuffer* pCanonic) 2805 { 2806 rtl::OUString aTheCanonic; 2807 if (pBegin < pEnd) 2808 { 2809 sal_Unicode const * p = pBegin; 2810 if (!parseHost(p, pEnd, aTheCanonic) || p != pEnd) 2811 { 2812 if (bNetBiosName) 2813 { 2814 rtl::OUStringBuffer buf; 2815 while (pBegin < pEnd) 2816 { 2817 EscapeType eEscapeType; 2818 sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, bOctets, '%', 2819 eMechanism, eCharset, 2820 eEscapeType); 2821 if (!INetMIME::isVisible(nUTF32)) 2822 return false; 2823 if (!INetMIME::isAlphanumeric(nUTF32)) 2824 switch (nUTF32) 2825 { 2826 case '"': 2827 case '*': 2828 case '+': 2829 case ',': 2830 case '/': 2831 case ':': 2832 case ';': 2833 case '<': 2834 case '=': 2835 case '>': 2836 case '?': 2837 case '[': 2838 case '\\': 2839 case ']': 2840 case '`': 2841 case '|': 2842 return false;; 2843 } 2844 if (pCanonic != NULL) { 2845 appendUCS4( 2846 buf, nUTF32, eEscapeType, bOctets, PART_URIC, '%', 2847 eCharset, true); 2848 } 2849 } 2850 aTheCanonic = buf.makeStringAndClear(); 2851 } 2852 else 2853 return false; 2854 } 2855 } 2856 if (pCanonic != NULL) { 2857 *pCanonic = aTheCanonic; 2858 } 2859 return true; 2860 } 2861 2862 //============================================================================ 2863 // static 2864 rtl::OUString INetURLObject::encodeHostPort(rtl::OUString const & rTheHostPort, 2865 bool bOctets, 2866 EncodeMechanism eMechanism, 2867 rtl_TextEncoding eCharset) 2868 { 2869 sal_Int32 nPort = rTheHostPort.getLength(); 2870 if (nPort != 0) 2871 { 2872 sal_Int32 i = nPort - 1; 2873 while (i != 0 && INetMIME::isDigit(rTheHostPort.getStr()[i])) 2874 --i; 2875 if (rTheHostPort.getStr()[i] == ':') 2876 nPort = i; 2877 } 2878 rtl::OUString aResult(encodeText(rTheHostPort.copy(0, nPort), bOctets, 2879 PART_HOST_EXTRA, '%', eMechanism, eCharset, 2880 true)); 2881 aResult += rTheHostPort.copy(nPort); 2882 return aResult; 2883 } 2884 2885 //============================================================================ 2886 bool INetURLObject::setHost(rtl::OUString const & rTheHost, bool bOctets, 2887 EncodeMechanism eMechanism, 2888 rtl_TextEncoding eCharset) 2889 { 2890 if (!getSchemeInfo().m_bHost) 2891 return false; 2892 rtl::OUStringBuffer aSynHost(rTheHost); 2893 bool bNetBiosName = false; 2894 switch (m_eScheme) 2895 { 2896 case INET_PROT_FILE: 2897 { 2898 rtl::OUString sTemp(aSynHost); 2899 if (sTemp.equalsIgnoreAsciiCaseAsciiL( 2900 RTL_CONSTASCII_STRINGPARAM("localhost"))) 2901 { 2902 aSynHost.setLength(0); 2903 } 2904 bNetBiosName = true; 2905 } 2906 break; 2907 case INET_PROT_LDAP: 2908 if (aSynHost.getLength() == 0 && m_aPort.isPresent()) 2909 return false; 2910 break; 2911 2912 default: 2913 if (aSynHost.getLength() == 0) 2914 return false; 2915 break; 2916 } 2917 if (!parseHostOrNetBiosName( 2918 aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(), 2919 bOctets, eMechanism, eCharset, bNetBiosName, &aSynHost)) 2920 return false; 2921 sal_Int32 nDelta = m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear()); 2922 m_aPort += nDelta; 2923 m_aPath += nDelta; 2924 m_aQuery += nDelta; 2925 m_aFragment += nDelta; 2926 return true; 2927 } 2928 2929 //============================================================================ 2930 // static 2931 bool INetURLObject::parsePath(INetProtocol eScheme, 2932 sal_Unicode const ** pBegin, 2933 sal_Unicode const * pEnd, 2934 bool bOctets, 2935 EncodeMechanism eMechanism, 2936 rtl_TextEncoding eCharset, 2937 bool bSkippedInitialSlash, 2938 sal_uInt32 nSegmentDelimiter, 2939 sal_uInt32 nAltSegmentDelimiter, 2940 sal_uInt32 nQueryDelimiter, 2941 sal_uInt32 nFragmentDelimiter, 2942 rtl::OUStringBuffer &rSynPath) 2943 { 2944 DBG_ASSERT(pBegin, "INetURLObject::parsePath(): Null output param"); 2945 2946 sal_Unicode const * pPos = *pBegin; 2947 rtl::OUStringBuffer aTheSynPath; 2948 2949 switch (eScheme) 2950 { 2951 case INET_PROT_NOT_VALID: 2952 return false; 2953 2954 case INET_PROT_FTP: 2955 case INET_PROT_IMAP: 2956 if (pPos < pEnd && *pPos != '/') 2957 return false; 2958 while (pPos < pEnd && *pPos != nFragmentDelimiter) 2959 { 2960 EscapeType eEscapeType; 2961 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 2962 '%', eMechanism, 2963 eCharset, eEscapeType); 2964 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 2965 PART_HTTP_PATH, '%', eCharset, true); 2966 } 2967 if (aTheSynPath.getLength() == 0) 2968 aTheSynPath.append(sal_Unicode('/')); 2969 break; 2970 2971 case INET_PROT_HTTP: 2972 case INET_PROT_VND_SUN_STAR_WEBDAV: 2973 case INET_PROT_HTTPS: 2974 case INET_PROT_SMB: 2975 if (pPos < pEnd && *pPos != '/') 2976 return false; 2977 while (pPos < pEnd && *pPos != nQueryDelimiter 2978 && *pPos != nFragmentDelimiter) 2979 { 2980 EscapeType eEscapeType; 2981 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 2982 '%', eMechanism, 2983 eCharset, eEscapeType); 2984 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 2985 PART_HTTP_PATH, '%', eCharset, true); 2986 } 2987 if (aTheSynPath.getLength() == 0) 2988 aTheSynPath.append(sal_Unicode('/')); 2989 break; 2990 2991 case INET_PROT_FILE: 2992 { 2993 if (bSkippedInitialSlash) 2994 aTheSynPath.append(sal_Unicode('/')); 2995 else if (pPos < pEnd 2996 && *pPos != nSegmentDelimiter 2997 && *pPos != nAltSegmentDelimiter) 2998 return false; 2999 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3000 { 3001 EscapeType eEscapeType; 3002 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3003 '%', eMechanism, 3004 eCharset, eEscapeType); 3005 if (eEscapeType == ESCAPE_NO) 3006 { 3007 if (nUTF32 == nSegmentDelimiter 3008 || nUTF32 == nAltSegmentDelimiter) 3009 { 3010 aTheSynPath.append(sal_Unicode('/')); 3011 continue; 3012 } 3013 else if (nUTF32 == '|' 3014 && (pPos == pEnd 3015 || *pPos == nFragmentDelimiter 3016 || *pPos == nSegmentDelimiter 3017 || *pPos == nAltSegmentDelimiter) 3018 && aTheSynPath.getLength() == 2 3019 && INetMIME::isAlpha(aTheSynPath.charAt(1))) 3020 { 3021 // A first segment of <ALPHA "|"> is translated to 3022 // <ALPHA ":">: 3023 aTheSynPath.append(sal_Unicode(':')); 3024 continue; 3025 } 3026 } 3027 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3028 PART_PCHAR, '%', eCharset, true); 3029 } 3030 if (aTheSynPath.getLength() == 0) 3031 aTheSynPath.append(sal_Unicode('/')); 3032 break; 3033 } 3034 3035 case INET_PROT_MAILTO: 3036 while (pPos < pEnd && *pPos != nQueryDelimiter 3037 && *pPos != nFragmentDelimiter) 3038 { 3039 EscapeType eEscapeType; 3040 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3041 '%', eMechanism, 3042 eCharset, eEscapeType); 3043 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3044 PART_MAILTO, '%', eCharset, true); 3045 } 3046 break; 3047 3048 case INET_PROT_NEWS: 3049 if (pPos == pEnd || *pPos == nQueryDelimiter 3050 || *pPos == nFragmentDelimiter) 3051 return false; 3052 3053 // Match <"*">: 3054 if (*pPos == '*' 3055 && (pEnd - pPos == 1 || pPos[1] == nQueryDelimiter 3056 || pPos[1] == nFragmentDelimiter)) 3057 { 3058 ++pPos; 3059 aTheSynPath.append(sal_Unicode('*')); 3060 break; 3061 } 3062 3063 // Match <group>: 3064 if (INetMIME::isAlpha(*pPos)) 3065 for (sal_Unicode const * p = pPos + 1;; ++p) 3066 if (p == pEnd || *p == nQueryDelimiter 3067 || *p == nFragmentDelimiter) 3068 { 3069 aTheSynPath.setLength(0); 3070 aTheSynPath.append(pPos, p - pPos); 3071 pPos = p; 3072 goto done; 3073 } 3074 else if (!INetMIME::isAlphanumeric(*p) && *p != '+' 3075 && *p != '-' && *p != '.' && *p != '_') 3076 break; 3077 3078 // Match <article>: 3079 for (;;) 3080 { 3081 if (pPos == pEnd || *pPos == nQueryDelimiter 3082 || *pPos == nFragmentDelimiter) 3083 return false; 3084 if (*pPos == '@') 3085 break; 3086 EscapeType eEscapeType; 3087 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, '%', 3088 eMechanism, eCharset, eEscapeType); 3089 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3090 PART_NEWS_ARTICLE_LOCALPART, '%', eCharset, true); 3091 } 3092 if (aTheSynPath.getLength() == 0) 3093 return false; 3094 ++pPos; 3095 aTheSynPath.append(sal_Unicode('@')); 3096 { 3097 sal_Unicode const * p = pPos; 3098 while (p < pEnd && *pPos != nQueryDelimiter 3099 && *pPos != nFragmentDelimiter) 3100 ++p; 3101 rtl::OUString aCanonic; 3102 if (!parseHost(pPos, p, aCanonic)) 3103 return false; 3104 aTheSynPath.append(aCanonic); 3105 } 3106 3107 done: 3108 break; 3109 3110 case INET_PROT_POP3: 3111 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3112 { 3113 EscapeType eEscapeType; 3114 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3115 '%', eMechanism, 3116 eCharset, eEscapeType); 3117 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3118 PART_MESSAGE_ID_PATH, '%', eCharset, 3119 true); 3120 } 3121 break; 3122 3123 case INET_PROT_PRIV_SOFFICE: 3124 case INET_PROT_SLOT: 3125 case INET_PROT_HID: 3126 case INET_PROT_MACRO: 3127 case INET_PROT_UNO: 3128 case INET_PROT_COMPONENT: 3129 case INET_PROT_LDAP: 3130 while (pPos < pEnd && *pPos != nQueryDelimiter 3131 && *pPos != nFragmentDelimiter) 3132 { 3133 EscapeType eEscapeType; 3134 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3135 '%', eMechanism, 3136 eCharset, eEscapeType); 3137 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3138 PART_PATH_BEFORE_QUERY, '%', eCharset, 3139 true); 3140 } 3141 break; 3142 3143 case INET_PROT_VND_SUN_STAR_HELP: 3144 if (pPos == pEnd 3145 || *pPos == nQueryDelimiter 3146 || *pPos == nFragmentDelimiter) 3147 aTheSynPath.append(sal_Unicode('/')); 3148 else 3149 { 3150 if (*pPos != '/') 3151 return false; 3152 while (pPos < pEnd && *pPos != nQueryDelimiter 3153 && *pPos != nFragmentDelimiter) 3154 { 3155 EscapeType eEscapeType; 3156 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3157 '%', eMechanism, 3158 eCharset, eEscapeType); 3159 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3160 PART_HTTP_PATH, '%', eCharset, true); 3161 } 3162 } 3163 break; 3164 3165 case INET_PROT_JAVASCRIPT: 3166 case INET_PROT_DATA: 3167 case INET_PROT_CID: 3168 case INET_PROT_DB: 3169 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3170 { 3171 EscapeType eEscapeType; 3172 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3173 '%', eMechanism, 3174 eCharset, eEscapeType); 3175 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3176 PART_URIC, '%', eCharset, true); 3177 } 3178 break; 3179 3180 case INET_PROT_OUT: 3181 if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '~') 3182 return false; 3183 aTheSynPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("/~")); 3184 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3185 { 3186 EscapeType eEscapeType; 3187 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3188 '%', eMechanism, 3189 eCharset, eEscapeType); 3190 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3191 PART_URIC, '%', eCharset, true); 3192 } 3193 break; 3194 3195 case INET_PROT_VND_SUN_STAR_HIER: 3196 case INET_PROT_VND_SUN_STAR_PKG: 3197 if (pPos < pEnd && *pPos != '/' 3198 && *pPos != nQueryDelimiter && *pPos != nFragmentDelimiter) 3199 return false; 3200 while (pPos < pEnd && *pPos != nQueryDelimiter 3201 && *pPos != nFragmentDelimiter) 3202 { 3203 EscapeType eEscapeType; 3204 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3205 '%', eMechanism, 3206 eCharset, eEscapeType); 3207 if (eEscapeType == ESCAPE_NO && nUTF32 == '/') 3208 aTheSynPath.append(sal_Unicode('/')); 3209 else 3210 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3211 PART_PCHAR, '%', eCharset, false); 3212 } 3213 if (aTheSynPath.getLength() == 0) 3214 aTheSynPath.append(sal_Unicode('/')); 3215 break; 3216 3217 case INET_PROT_VIM: 3218 { 3219 /* test had to be taken out to make parsePath static; ok since INET_PROT_VIM is 3220 obsolete, anyway 3221 if (m_aUser.isEmpty()) 3222 return false; 3223 */ 3224 sal_Unicode const * pPathEnd = pPos; 3225 while (pPathEnd < pEnd && *pPathEnd != nFragmentDelimiter) 3226 ++pPathEnd; 3227 aTheSynPath.append(sal_Unicode('/')); 3228 if (pPos == pPathEnd) 3229 break; 3230 else if (*pPos++ != '/') 3231 return false; 3232 if (pPos == pPathEnd) 3233 break; 3234 while (pPos < pPathEnd && *pPos != '/') 3235 { 3236 EscapeType eEscapeType; 3237 sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets, 3238 '=', eMechanism, 3239 eCharset, eEscapeType); 3240 appendUCS4(aTheSynPath, 3241 eEscapeType == ESCAPE_NO ? 3242 INetMIME::toLowerCase(nUTF32) : nUTF32, 3243 eEscapeType, bOctets, PART_VIM, '=', 3244 eCharset, false); 3245 } 3246 bool bInbox; 3247 rtl::OUString sCompare(aTheSynPath); 3248 if (sCompare.equalsAscii("/inbox")) 3249 bInbox = true; 3250 else if (sCompare.equalsAscii("/newsgroups")) 3251 bInbox = false; 3252 else 3253 return false; 3254 aTheSynPath.append(sal_Unicode('/')); 3255 if (pPos == pPathEnd) 3256 break; 3257 else if (*pPos++ != '/') 3258 return false; 3259 if (!bInbox) 3260 { 3261 bool bEmpty = true; 3262 while (pPos < pPathEnd && *pPos != '/') 3263 { 3264 EscapeType eEscapeType; 3265 sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets, 3266 '=', eMechanism, 3267 eCharset, eEscapeType); 3268 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3269 PART_VIM, '=', eCharset, false); 3270 bEmpty = false; 3271 } 3272 if (bEmpty) 3273 return false; 3274 aTheSynPath.append(sal_Unicode('/')); 3275 if (pPos == pPathEnd) 3276 break; 3277 else if (*pPos++ != '/') 3278 return false; 3279 } 3280 bool bEmpty = true; 3281 while (pPos < pPathEnd && *pPos != ':') 3282 { 3283 EscapeType eEscapeType; 3284 sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets, 3285 '=', eMechanism, 3286 eCharset, eEscapeType); 3287 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3288 PART_VIM, '=', eCharset, false); 3289 bEmpty = false; 3290 } 3291 if (bEmpty) 3292 return false; 3293 if (pPos == pPathEnd) 3294 break; 3295 else if (*pPos++ != ':') 3296 return false; 3297 aTheSynPath.append(sal_Unicode(':')); 3298 for (int i = 0; i < 3; ++i) 3299 { 3300 if (i != 0) 3301 { 3302 if (pPos == pPathEnd || *pPos++ != '.') 3303 return false; 3304 aTheSynPath.append(sal_Unicode('.')); 3305 } 3306 bEmpty = true; 3307 while (pPos < pPathEnd && *pPos != '.') 3308 { 3309 EscapeType eEscapeType; 3310 sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets, 3311 '=', eMechanism, 3312 eCharset, eEscapeType); 3313 if (!INetMIME::isDigit(nUTF32)) 3314 return false; 3315 aTheSynPath.append(sal_Unicode(nUTF32)); 3316 bEmpty = false; 3317 } 3318 if (bEmpty) 3319 return false; 3320 } 3321 if (pPos != pPathEnd) 3322 return false; 3323 break; 3324 } 3325 3326 case INET_PROT_VND_SUN_STAR_CMD: 3327 case INET_PROT_VND_SUN_STAR_EXPAND: 3328 { 3329 if (pPos == pEnd || *pPos == nFragmentDelimiter) 3330 return false; 3331 Part ePart = PART_URIC_NO_SLASH; 3332 while (pPos != pEnd && *pPos != nFragmentDelimiter) 3333 { 3334 EscapeType eEscapeType; 3335 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3336 '%', eMechanism, 3337 eCharset, eEscapeType); 3338 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, ePart, 3339 '%', eCharset, true); 3340 ePart = PART_URIC; 3341 } 3342 break; 3343 } 3344 3345 case INET_PROT_VND_SUN_STAR_ODMA: 3346 if (pPos < pEnd) 3347 { 3348 if (*pPos == '/') 3349 ++pPos; 3350 else 3351 return false; 3352 } 3353 aTheSynPath.append(sal_Unicode('/')); 3354 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3355 { 3356 EscapeType eEscapeType; 3357 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3358 '%', eMechanism, 3359 eCharset, eEscapeType); 3360 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3361 PART_URIC_NO_SLASH, '%', eCharset, true); 3362 } 3363 break; 3364 3365 case INET_PROT_TELNET: 3366 if (pPos < pEnd) 3367 { 3368 if (*pPos != '/' || pEnd - pPos > 1) 3369 return false; 3370 ++pPos; 3371 } 3372 aTheSynPath.append(sal_Unicode('/')); 3373 break; 3374 3375 case INET_PROT_VND_SUN_STAR_TDOC: 3376 if (pPos == pEnd || *pPos != '/') 3377 return false; 3378 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3379 { 3380 EscapeType eEscapeType; 3381 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3382 '%', eMechanism, 3383 eCharset, eEscapeType); 3384 if (eEscapeType == ESCAPE_NO && nUTF32 == '/') 3385 aTheSynPath.append(sal_Unicode('/')); 3386 else 3387 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3388 PART_PCHAR, '%', eCharset, false); 3389 } 3390 break; 3391 3392 case INET_PROT_GENERIC: 3393 while (pPos < pEnd && *pPos != nFragmentDelimiter) 3394 { 3395 EscapeType eEscapeType; 3396 sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, 3397 '%', eMechanism, 3398 eCharset, eEscapeType); 3399 appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, 3400 PART_URIC, '%', eCharset, true); 3401 } 3402 if (aTheSynPath.getLength() == 0) 3403 return false; 3404 break; 3405 default: 3406 OSL_ASSERT(false); 3407 break; 3408 } 3409 3410 *pBegin = pPos; 3411 rSynPath = aTheSynPath; 3412 return true; 3413 } 3414 3415 //============================================================================ 3416 bool INetURLObject::setPath(rtl::OUString const & rThePath, bool bOctets, 3417 EncodeMechanism eMechanism, 3418 rtl_TextEncoding eCharset) 3419 { 3420 rtl::OUStringBuffer aSynPath; 3421 sal_Unicode const * p = rThePath.getStr(); 3422 sal_Unicode const * pEnd = p + rThePath.getLength(); 3423 if (!parsePath(m_eScheme, &p, pEnd, bOctets, eMechanism, eCharset, false, 3424 '/', 0x80000000, 0x80000000, 0x80000000, aSynPath) 3425 || p != pEnd) 3426 return false; 3427 sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear()); 3428 m_aQuery += nDelta; 3429 m_aFragment += nDelta; 3430 return true; 3431 } 3432 3433 //============================================================================ 3434 bool INetURLObject::checkHierarchical() const { 3435 if (m_eScheme == INET_PROT_VND_SUN_STAR_EXPAND) { 3436 OSL_ENSURE( 3437 false, "INetURLObject::checkHierarchical vnd.sun.star.expand"); 3438 return true; 3439 } else { 3440 return getSchemeInfo().m_bHierarchical; 3441 } 3442 } 3443 3444 //============================================================================ 3445 bool INetURLObject::appendSegment(rtl::OUString const & rTheSegment, 3446 bool bOctets, EncodeMechanism eMechanism, 3447 rtl_TextEncoding eCharset) 3448 { 3449 return insertName(rTheSegment, bOctets, false, LAST_SEGMENT, true, 3450 eMechanism, eCharset); 3451 } 3452 3453 //============================================================================ 3454 INetURLObject::SubString INetURLObject::getSegment(sal_Int32 nIndex, 3455 bool bIgnoreFinalSlash) 3456 const 3457 { 3458 DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT, 3459 "INetURLObject::getSegment(): Bad index"); 3460 3461 if (!checkHierarchical()) 3462 return SubString(); 3463 3464 sal_Unicode const * pPathBegin 3465 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 3466 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 3467 sal_Unicode const * pSegBegin; 3468 sal_Unicode const * pSegEnd; 3469 if (nIndex == LAST_SEGMENT) 3470 { 3471 pSegEnd = pPathEnd; 3472 if (bIgnoreFinalSlash && pSegEnd > pPathBegin && pSegEnd[-1] == '/') 3473 --pSegEnd; 3474 if (pSegEnd <= pPathBegin) 3475 return SubString(); 3476 pSegBegin = pSegEnd - 1; 3477 while (pSegBegin > pPathBegin && *pSegBegin != '/') 3478 --pSegBegin; 3479 } 3480 else 3481 { 3482 pSegBegin = pPathBegin; 3483 while (nIndex-- > 0) 3484 do 3485 { 3486 ++pSegBegin; 3487 if (pSegBegin >= pPathEnd) 3488 return SubString(); 3489 } 3490 while (*pSegBegin != '/'); 3491 pSegEnd = pSegBegin + 1; 3492 while (pSegEnd < pPathEnd && *pSegEnd != '/') 3493 ++pSegEnd; 3494 } 3495 3496 return SubString(pSegBegin - m_aAbsURIRef.getStr(), 3497 pSegEnd - pSegBegin); 3498 } 3499 3500 //============================================================================ 3501 bool INetURLObject::insertName(rtl::OUString const & rTheName, bool bOctets, 3502 bool bAppendFinalSlash, sal_Int32 nIndex, 3503 bool bIgnoreFinalSlash, 3504 EncodeMechanism eMechanism, 3505 rtl_TextEncoding eCharset) 3506 { 3507 DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT, 3508 "INetURLObject::insertName(): Bad index"); 3509 3510 if (!checkHierarchical()) 3511 return false; 3512 3513 sal_Unicode const * pPathBegin 3514 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 3515 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 3516 sal_Unicode const * pPrefixEnd; 3517 bool bInsertSlash; 3518 sal_Unicode const * pSuffixBegin; 3519 if (nIndex == LAST_SEGMENT) 3520 { 3521 pPrefixEnd = pPathEnd; 3522 if (bIgnoreFinalSlash && pPrefixEnd > pPathBegin && 3523 pPrefixEnd[-1] == '/') 3524 { 3525 --pPrefixEnd; 3526 } 3527 bInsertSlash = bAppendFinalSlash; 3528 pSuffixBegin = pPathEnd; 3529 } 3530 else if (nIndex == 0) 3531 { 3532 pPrefixEnd = pPathBegin; 3533 bInsertSlash = 3534 (pPathBegin < pPathEnd && *pPathBegin != '/') || 3535 (pPathBegin == pPathEnd && bAppendFinalSlash); 3536 pSuffixBegin = 3537 (pPathEnd - pPathBegin == 1 && *pPathBegin == '/' && 3538 !bAppendFinalSlash && bIgnoreFinalSlash) 3539 ? pPathEnd : pPathBegin; 3540 } 3541 else 3542 { 3543 pPrefixEnd = pPathBegin; 3544 sal_Unicode const * pEnd = pPathEnd; 3545 if (bIgnoreFinalSlash && pEnd > pPathBegin && pEnd[-1] == '/') 3546 --pEnd; 3547 bool bSkip = pPrefixEnd < pEnd && *pPrefixEnd == '/'; 3548 bInsertSlash = false; 3549 pSuffixBegin = pPathEnd; 3550 while (nIndex-- > 0) 3551 for (;;) 3552 { 3553 if (bSkip) 3554 ++pPrefixEnd; 3555 bSkip = true; 3556 if (pPrefixEnd >= pEnd) 3557 { 3558 if (nIndex == 0) 3559 { 3560 bInsertSlash = bAppendFinalSlash; 3561 break; 3562 } 3563 else 3564 return false; 3565 } 3566 if (*pPrefixEnd == '/') 3567 { 3568 pSuffixBegin = pPrefixEnd; 3569 break; 3570 } 3571 } 3572 } 3573 3574 rtl::OUStringBuffer aNewPath; 3575 aNewPath.append(pPathBegin, pPrefixEnd - pPathBegin); 3576 aNewPath.append(sal_Unicode('/')); 3577 aNewPath.append(encodeText(rTheName, bOctets, PART_PCHAR, getEscapePrefix(), 3578 eMechanism, eCharset, true)); 3579 if (bInsertSlash) { 3580 aNewPath.append(sal_Unicode('/')); 3581 } 3582 aNewPath.append(pSuffixBegin, pPathEnd - pSuffixBegin); 3583 3584 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 3585 RTL_TEXTENCODING_UTF8); 3586 } 3587 3588 //============================================================================ 3589 bool INetURLObject::clearQuery() 3590 { 3591 if (HasError()) 3592 return false; 3593 if (m_aQuery.isPresent()) 3594 { 3595 lcl_Erase(m_aAbsURIRef, m_aQuery.getBegin() - 1, 3596 m_aQuery.getLength() + 1); 3597 m_aFragment += m_aQuery.clear() - 1; 3598 } 3599 return false; 3600 } 3601 3602 //============================================================================ 3603 bool INetURLObject::setQuery(rtl::OUString const & rTheQuery, bool bOctets, 3604 EncodeMechanism eMechanism, 3605 rtl_TextEncoding eCharset) 3606 { 3607 if (!getSchemeInfo().m_bQuery) 3608 return false; 3609 rtl::OUString aNewQuery(encodeText(rTheQuery, bOctets, PART_URIC, 3610 getEscapePrefix(), eMechanism, eCharset, 3611 true)); 3612 sal_Int32 nDelta; 3613 if (m_aQuery.isPresent()) 3614 nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery); 3615 else 3616 { 3617 m_aAbsURIRef.insert(m_aPath.getEnd(), sal_Unicode('?')); 3618 nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery, m_aPath.getEnd() + 1) 3619 + 1; 3620 } 3621 m_aFragment += nDelta; 3622 return true; 3623 } 3624 3625 //============================================================================ 3626 bool INetURLObject::clearFragment() 3627 { 3628 if (HasError()) 3629 return false; 3630 if (m_aFragment.isPresent()) 3631 { 3632 m_aAbsURIRef.setLength(m_aFragment.getBegin() - 1); 3633 m_aFragment.clear(); 3634 } 3635 return true; 3636 } 3637 3638 //============================================================================ 3639 bool INetURLObject::setFragment(rtl::OUString const & rTheFragment, 3640 bool bOctets, EncodeMechanism eMechanism, 3641 rtl_TextEncoding eCharset) 3642 { 3643 if (HasError()) 3644 return false; 3645 rtl::OUString aNewFragment(encodeText(rTheFragment, bOctets, PART_URIC, 3646 getEscapePrefix(), eMechanism, 3647 eCharset, true)); 3648 if (m_aFragment.isPresent()) 3649 m_aFragment.set(m_aAbsURIRef, aNewFragment); 3650 else 3651 { 3652 m_aAbsURIRef.append(sal_Unicode('#')); 3653 m_aFragment.set(m_aAbsURIRef, aNewFragment, m_aAbsURIRef.getLength()); 3654 } 3655 return true; 3656 } 3657 3658 //============================================================================ 3659 INetURLObject::FTPType INetURLObject::getFTPType() const 3660 { 3661 if (m_eScheme == INET_PROT_FTP 3662 && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH(";type=") + 1 3663 && rtl::OUString(m_aAbsURIRef).copy( 3664 m_aPath.getEnd() - (RTL_CONSTASCII_LENGTH(";type=") + 1), 3665 RTL_CONSTASCII_LENGTH(";type=")).equalsIgnoreAsciiCaseAscii(";type=")) 3666 switch (m_aAbsURIRef.charAt(m_aPath.getEnd())) 3667 { 3668 case 'A': 3669 case 'a': 3670 return FTP_TYPE_A; 3671 3672 case 'D': 3673 case 'd': 3674 return FTP_TYPE_D; 3675 3676 case 'I': 3677 case 'i': 3678 return FTP_TYPE_I; 3679 } 3680 return FTP_TYPE_NONE; 3681 } 3682 3683 //============================================================================ 3684 bool INetURLObject::hasDosVolume(FSysStyle eStyle) const 3685 { 3686 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 3687 return (eStyle & FSYS_DOS) != 0 3688 && m_aPath.getLength() >= 3 3689 && p[0] == '/' 3690 && INetMIME::isAlpha(p[1]) 3691 && p[2] == ':' 3692 && (m_aPath.getLength() == 3 || p[3] == '/'); 3693 } 3694 3695 //============================================================================ 3696 sal_uInt32 INetURLObject::getIMAPUID() const 3697 { 3698 if (m_eScheme == INET_PROT_IMAP 3699 && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH("/;uid=") + 1) 3700 { 3701 sal_Unicode const * pBegin = m_aAbsURIRef.getStr() 3702 + m_aPath.getBegin() 3703 + RTL_CONSTASCII_LENGTH("/;uid="); 3704 sal_Unicode const * pEnd = pBegin + m_aPath.getLength(); 3705 sal_Unicode const * p = pEnd; 3706 while (p > pBegin && INetMIME::isDigit(p[-1])) 3707 --p; 3708 if (p < pEnd && *--p != '0' 3709 && rtl::OUString(m_aAbsURIRef).copy( 3710 p - RTL_CONSTASCII_LENGTH("/;uid=") - m_aAbsURIRef.getStr(), 3711 RTL_CONSTASCII_LENGTH("/;uid=")).equalsIgnoreAsciiCaseAscii("/;uid=") 3712 ) 3713 { 3714 sal_uInt32 nUID; 3715 if (INetMIME::scanUnsigned(p, pEnd, false, nUID)) 3716 return nUID; 3717 } 3718 } 3719 return 0; 3720 } 3721 3722 //============================================================================ 3723 // static 3724 rtl::OUString INetURLObject::encodeText(sal_Unicode const * pBegin, 3725 sal_Unicode const * pEnd, bool bOctets, 3726 Part ePart, sal_Char cEscapePrefix, 3727 EncodeMechanism eMechanism, 3728 rtl_TextEncoding eCharset, 3729 bool bKeepVisibleEscapes) 3730 { 3731 rtl::OUStringBuffer aResult; 3732 while (pBegin < pEnd) 3733 { 3734 EscapeType eEscapeType; 3735 sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, bOctets, cEscapePrefix, 3736 eMechanism, eCharset, eEscapeType); 3737 appendUCS4(aResult, nUTF32, eEscapeType, bOctets, ePart, 3738 cEscapePrefix, eCharset, bKeepVisibleEscapes); 3739 } 3740 return aResult.makeStringAndClear(); 3741 } 3742 3743 //============================================================================ 3744 // static 3745 rtl::OUString INetURLObject::decode(sal_Unicode const * pBegin, 3746 sal_Unicode const * pEnd, 3747 sal_Char cEscapePrefix, 3748 DecodeMechanism eMechanism, 3749 rtl_TextEncoding eCharset) 3750 { 3751 switch (eMechanism) 3752 { 3753 case NO_DECODE: 3754 return rtl::OUString(pBegin, pEnd - pBegin); 3755 3756 case DECODE_TO_IURI: 3757 eCharset = RTL_TEXTENCODING_UTF8; 3758 break; 3759 3760 default: 3761 break; 3762 } 3763 rtl::OUStringBuffer aResult; 3764 while (pBegin < pEnd) 3765 { 3766 EscapeType eEscapeType; 3767 sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, false, cEscapePrefix, 3768 WAS_ENCODED, eCharset, eEscapeType); 3769 switch (eEscapeType) 3770 { 3771 case ESCAPE_NO: 3772 aResult.append(sal_Unicode(nUTF32)); 3773 break; 3774 3775 case ESCAPE_OCTET: 3776 appendEscape(aResult, cEscapePrefix, nUTF32); 3777 break; 3778 3779 case ESCAPE_UTF32: 3780 if ( 3781 INetMIME::isUSASCII(nUTF32) && 3782 ( 3783 eMechanism == DECODE_TO_IURI || 3784 ( 3785 eMechanism == DECODE_UNAMBIGUOUS && 3786 mustEncode(nUTF32, PART_UNAMBIGUOUS) 3787 ) 3788 ) 3789 ) 3790 { 3791 appendEscape(aResult, cEscapePrefix, nUTF32); 3792 } 3793 else 3794 aResult.append(sal_Unicode(nUTF32)); 3795 break; 3796 } 3797 } 3798 return aResult.makeStringAndClear(); 3799 } 3800 3801 //============================================================================ 3802 rtl::OUString INetURLObject::GetURLNoPass(DecodeMechanism eMechanism, 3803 rtl_TextEncoding eCharset) const 3804 { 3805 INetURLObject aTemp(*this); 3806 aTemp.clearPassword(); 3807 return aTemp.GetMainURL(eMechanism, eCharset); 3808 } 3809 3810 //============================================================================ 3811 rtl::OUString INetURLObject::GetURLNoMark(DecodeMechanism eMechanism, 3812 rtl_TextEncoding eCharset) const 3813 { 3814 INetURLObject aTemp(*this); 3815 aTemp.clearFragment(); 3816 return aTemp.GetMainURL(eMechanism, eCharset); 3817 } 3818 3819 //============================================================================ 3820 rtl::OUString 3821 INetURLObject::getAbbreviated( 3822 star::uno::Reference< star::util::XStringWidth > const & rStringWidth, 3823 sal_Int32 nWidth, 3824 DecodeMechanism eMechanism, 3825 rtl_TextEncoding eCharset) 3826 const 3827 { 3828 OSL_ENSURE(rStringWidth.is(), "specification violation"); 3829 sal_Char cEscapePrefix = getEscapePrefix(); 3830 rtl::OUStringBuffer aBuffer; 3831 // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme 3832 // is empty ("") in that case, so take the scheme from m_aAbsURIRef 3833 if (m_eScheme != INET_PROT_GENERIC) 3834 { 3835 aBuffer.appendAscii(getSchemeInfo().m_pScheme); 3836 } 3837 else 3838 { 3839 if (m_aAbsURIRef) 3840 { 3841 sal_Unicode const * pSchemeBegin 3842 = m_aAbsURIRef.getStr(); 3843 sal_Unicode const * pSchemeEnd = pSchemeBegin; 3844 3845 while (pSchemeEnd[0] != ':') 3846 { 3847 ++pSchemeEnd; 3848 } 3849 aBuffer.append(pSchemeBegin, pSchemeEnd - pSchemeBegin); 3850 } 3851 } 3852 aBuffer.append(static_cast< sal_Unicode >(':')); 3853 bool bAuthority = getSchemeInfo().m_bAuthority; 3854 sal_Unicode const * pCoreBegin 3855 = m_aAbsURIRef.getStr() + (bAuthority ? getAuthorityBegin() : 3856 m_aPath.getBegin()); 3857 sal_Unicode const * pCoreEnd 3858 = m_aAbsURIRef.getStr() + m_aPath.getBegin() + m_aPath.getLength(); 3859 bool bSegment = false; 3860 if (getSchemeInfo().m_bHierarchical) 3861 { 3862 rtl::OUString aRest; 3863 if (m_aQuery.isPresent()) 3864 aRest = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("?...")); 3865 else if (m_aFragment.isPresent()) 3866 aRest = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("#...")); 3867 rtl::OUStringBuffer aTrailer; 3868 sal_Unicode const * pBegin = pCoreBegin; 3869 sal_Unicode const * pEnd = pCoreEnd; 3870 sal_Unicode const * pPrefixBegin = pBegin; 3871 sal_Unicode const * pSuffixEnd = pEnd; 3872 bool bPrefix = true; 3873 bool bSuffix = true; 3874 do 3875 { 3876 if (bSuffix) 3877 { 3878 sal_Unicode const * p = pSuffixEnd - 1; 3879 if (pSuffixEnd == pCoreEnd && *p == '/') 3880 --p; 3881 while (*p != '/') 3882 --p; 3883 if (bAuthority && p == pCoreBegin + 1) 3884 --p; 3885 rtl::OUString 3886 aSegment(decode(p + (p == pBegin && pBegin != pCoreBegin ? 3887 1 : 0), 3888 pSuffixEnd, 3889 cEscapePrefix, 3890 eMechanism, 3891 eCharset)); 3892 pSuffixEnd = p; 3893 rtl::OUStringBuffer aResult(aBuffer); 3894 if (pSuffixEnd != pBegin) 3895 aResult.appendAscii(RTL_CONSTASCII_STRINGPARAM("...")); 3896 aResult.append(aSegment); 3897 aResult.append(aTrailer); 3898 aResult.append(aRest); 3899 if (rStringWidth-> 3900 queryStringWidth(aResult.makeStringAndClear()) 3901 <= nWidth) 3902 { 3903 aTrailer.insert(0, aSegment); 3904 bSegment = true; 3905 pEnd = pSuffixEnd; 3906 } 3907 else 3908 bSuffix = false; 3909 if (pPrefixBegin > pSuffixEnd) 3910 pPrefixBegin = pSuffixEnd; 3911 if (pBegin == pEnd) 3912 break; 3913 } 3914 if (bPrefix) 3915 { 3916 sal_Unicode const * p 3917 = pPrefixBegin 3918 + (bAuthority && pPrefixBegin == pCoreBegin ? 2 : 3919 1); 3920 OSL_ASSERT(p <= pEnd); 3921 while (p < pEnd && *p != '/') 3922 ++p; 3923 if (p == pCoreEnd - 1 && *p == '/') 3924 ++p; 3925 rtl::OUString 3926 aSegment(decode(pPrefixBegin 3927 + (pPrefixBegin == pCoreBegin ? 0 : 3928 1), 3929 p == pEnd ? p : p + 1, 3930 cEscapePrefix, 3931 eMechanism, 3932 eCharset)); 3933 pPrefixBegin = p; 3934 rtl::OUStringBuffer aResult(aBuffer); 3935 aResult.append(aSegment); 3936 if (pPrefixBegin != pEnd) 3937 aResult.appendAscii(RTL_CONSTASCII_STRINGPARAM("...")); 3938 aResult.append(aTrailer); 3939 aResult.append(aRest); 3940 if (rStringWidth-> 3941 queryStringWidth(aResult.makeStringAndClear()) 3942 <= nWidth) 3943 { 3944 aBuffer.append(aSegment); 3945 bSegment = true; 3946 pBegin = pPrefixBegin; 3947 } 3948 else 3949 bPrefix = false; 3950 if (pPrefixBegin > pSuffixEnd) 3951 pSuffixEnd = pPrefixBegin; 3952 if (pBegin == pEnd) 3953 break; 3954 } 3955 } 3956 while (bPrefix || bSuffix); 3957 if (bSegment) 3958 { 3959 if (pPrefixBegin != pBegin || pSuffixEnd != pEnd) 3960 aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("...")); 3961 aBuffer.append(aTrailer); 3962 } 3963 } 3964 if (!bSegment) 3965 aBuffer.append(decode(pCoreBegin, 3966 pCoreEnd, 3967 cEscapePrefix, 3968 eMechanism, 3969 eCharset)); 3970 if (m_aQuery.isPresent()) 3971 { 3972 aBuffer.append(static_cast< sal_Unicode >('?')); 3973 aBuffer.append(decode(m_aQuery, cEscapePrefix, eMechanism, eCharset)); 3974 } 3975 if (m_aFragment.isPresent()) 3976 { 3977 aBuffer.append(static_cast< sal_Unicode >('#')); 3978 aBuffer. 3979 append(decode(m_aFragment, cEscapePrefix, eMechanism, eCharset)); 3980 } 3981 if (aBuffer.getLength() != 0) 3982 { 3983 rtl::OUStringBuffer aResult(aBuffer); 3984 if (rStringWidth->queryStringWidth(aResult.makeStringAndClear()) 3985 > nWidth) 3986 for (sal_Int32 i = aBuffer.getLength();;) 3987 { 3988 if (i == 0) 3989 { 3990 aBuffer.setLength(aBuffer.getLength() - 1); 3991 if (aBuffer.getLength() == 0) 3992 break; 3993 } 3994 else 3995 { 3996 aBuffer.setLength(--i); 3997 aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("...")); 3998 } 3999 aResult = aBuffer; 4000 if (rStringWidth-> 4001 queryStringWidth(aResult.makeStringAndClear()) 4002 <= nWidth) 4003 break; 4004 } 4005 } 4006 return aBuffer.makeStringAndClear(); 4007 } 4008 4009 //============================================================================ 4010 bool INetURLObject::operator ==(INetURLObject const & rObject) const 4011 { 4012 if (m_eScheme != rObject.m_eScheme) 4013 return false; 4014 if (m_eScheme == INET_PROT_NOT_VALID) 4015 return (m_aAbsURIRef == rObject.m_aAbsURIRef) != false; 4016 if ((m_aScheme.compare( 4017 rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef) 4018 != 0) 4019 || GetUser(NO_DECODE) != rObject.GetUser(NO_DECODE) 4020 || GetPass(NO_DECODE) != rObject.GetPass(NO_DECODE) 4021 || !GetHost(NO_DECODE).equalsIgnoreAsciiCase( 4022 rObject.GetHost(NO_DECODE)) 4023 || GetPort() != rObject.GetPort() 4024 || HasParam() != rObject.HasParam() 4025 || GetParam(NO_DECODE) != rObject.GetParam(NO_DECODE) 4026 || GetMsgId(NO_DECODE) != rObject.GetMsgId(NO_DECODE)) 4027 return false; 4028 rtl::OUString aPath1(GetURLPath(NO_DECODE)); 4029 rtl::OUString aPath2(rObject.GetURLPath(NO_DECODE)); 4030 switch (m_eScheme) 4031 { 4032 case INET_PROT_FILE: 4033 { 4034 // If the URL paths of two file URLs only differ in that one has a 4035 // final '/' and the other has not, take the two paths as 4036 // equivalent (this could be usefull for other schemes, too): 4037 sal_Int32 nLength = aPath1.getLength(); 4038 switch (nLength - aPath2.getLength()) 4039 { 4040 case -1: 4041 if (aPath2.getStr()[nLength] != '/') 4042 return false; 4043 break; 4044 4045 case 0: 4046 break; 4047 4048 case 1: 4049 if (aPath1.getStr()[--nLength] != '/') 4050 return false; 4051 break; 4052 4053 default: 4054 return false; 4055 } 4056 return aPath1.compareTo(aPath2, nLength) == 0; 4057 } 4058 4059 default: 4060 return (aPath1 == aPath2) != false; 4061 } 4062 } 4063 4064 //============================================================================ 4065 bool INetURLObject::operator <(INetURLObject const & rObject) const 4066 { 4067 sal_Int32 nCompare = m_aScheme.compare( 4068 rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef); 4069 if (nCompare < 0) { 4070 return true; 4071 } else if (nCompare > 0) { 4072 return false; 4073 } 4074 sal_uInt32 nPort1 = GetPort(); 4075 sal_uInt32 nPort2 = rObject.GetPort(); 4076 if (nPort1 < nPort2) 4077 return true; 4078 else if (nPort1 > nPort2) 4079 return false; 4080 nCompare = GetUser(NO_DECODE).compareTo(rObject.GetUser(NO_DECODE)); 4081 if (nCompare < 0) 4082 return true; 4083 else if (nCompare > 0) 4084 return false; 4085 nCompare = GetPass(NO_DECODE).compareTo(rObject.GetPass(NO_DECODE)); 4086 if (nCompare < 0) 4087 return true; 4088 else if (nCompare > 0) 4089 return false; 4090 nCompare = GetHost(NO_DECODE).compareTo(rObject.GetHost(NO_DECODE)); 4091 if (nCompare < 0) 4092 return true; 4093 else if (nCompare > 0) 4094 return false; 4095 const rtl::OUString &rPath1(GetURLPath(NO_DECODE)); 4096 const rtl::OUString &rPath2(rObject.GetURLPath(NO_DECODE)); 4097 nCompare = rPath1.compareTo(rPath2); 4098 if (nCompare < 0) 4099 return true; 4100 else if (nCompare > 0) 4101 return false; 4102 nCompare = GetParam(NO_DECODE).compareTo(rObject.GetParam(NO_DECODE)); 4103 if (nCompare < 0) 4104 return true; 4105 else if (nCompare > 0) 4106 return false; 4107 return GetMsgId(NO_DECODE).compareTo(rObject.GetMsgId(NO_DECODE)) < 0; 4108 } 4109 4110 //============================================================================ 4111 bool INetURLObject::ConcatData(INetProtocol eTheScheme, 4112 rtl::OUString const & rTheUser, 4113 rtl::OUString const & rThePassword, 4114 rtl::OUString const & rTheHost, 4115 sal_uInt32 nThePort, 4116 rtl::OUString const & rThePath, 4117 EncodeMechanism eMechanism, 4118 rtl_TextEncoding eCharset) 4119 { 4120 setInvalid(); 4121 m_eScheme = eTheScheme; 4122 if (HasError() || m_eScheme == INET_PROT_GENERIC) 4123 return false; 4124 m_aAbsURIRef.setLength(0); 4125 m_aAbsURIRef.appendAscii(getSchemeInfo().m_pScheme); 4126 m_aAbsURIRef.append(sal_Unicode(':')); 4127 if (getSchemeInfo().m_bAuthority) 4128 { 4129 m_aAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 4130 bool bUserInfo = false; 4131 if (getSchemeInfo().m_bUser) 4132 { 4133 if (m_eScheme == INET_PROT_IMAP && rTheUser.getLength() == 0) 4134 { 4135 setInvalid(); 4136 return false; 4137 } 4138 if (rTheUser.getLength() != 0) 4139 { 4140 m_aUser.set(m_aAbsURIRef, 4141 encodeText(rTheUser, false, 4142 m_eScheme == INET_PROT_IMAP ? 4143 PART_IMAP_ACHAR : 4144 m_eScheme == INET_PROT_VIM ? 4145 PART_VIM : 4146 PART_USER_PASSWORD, 4147 getEscapePrefix(), eMechanism, 4148 eCharset, false), 4149 m_aAbsURIRef.getLength()); 4150 bUserInfo = true; 4151 } 4152 } 4153 else if (rTheUser.getLength() != 0) 4154 { 4155 setInvalid(); 4156 return false; 4157 } 4158 if (rThePassword.getLength() != 0) 4159 { 4160 if (getSchemeInfo().m_bPassword) 4161 { 4162 m_aAbsURIRef.append(sal_Unicode(':')); 4163 m_aAuth.set(m_aAbsURIRef, 4164 encodeText(rThePassword, false, 4165 m_eScheme == INET_PROT_VIM ? 4166 PART_VIM : PART_USER_PASSWORD, 4167 getEscapePrefix(), eMechanism, 4168 eCharset, false), 4169 m_aAbsURIRef.getLength()); 4170 bUserInfo = true; 4171 } 4172 else 4173 { 4174 setInvalid(); 4175 return false; 4176 } 4177 } 4178 if (bUserInfo && getSchemeInfo().m_bHost) 4179 m_aAbsURIRef.append(sal_Unicode('@')); 4180 if (getSchemeInfo().m_bHost) 4181 { 4182 rtl::OUStringBuffer aSynHost(rTheHost); 4183 bool bNetBiosName = false; 4184 switch (m_eScheme) 4185 { 4186 case INET_PROT_FILE: 4187 { 4188 rtl::OUString sTemp(aSynHost); 4189 if (sTemp.equalsIgnoreAsciiCaseAsciiL( 4190 RTL_CONSTASCII_STRINGPARAM("localhost"))) 4191 { 4192 aSynHost.setLength(0); 4193 } 4194 bNetBiosName = true; 4195 } 4196 break; 4197 4198 case INET_PROT_LDAP: 4199 if (aSynHost.getLength() == 0 && nThePort != 0) 4200 { 4201 setInvalid(); 4202 return false; 4203 } 4204 break; 4205 4206 default: 4207 if (aSynHost.getLength() == 0) 4208 { 4209 setInvalid(); 4210 return false; 4211 } 4212 break; 4213 } 4214 if (!parseHostOrNetBiosName( 4215 aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(), 4216 false, eMechanism, eCharset, bNetBiosName, &aSynHost)) 4217 { 4218 setInvalid(); 4219 return false; 4220 } 4221 m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear(), 4222 m_aAbsURIRef.getLength()); 4223 if (nThePort != 0) 4224 { 4225 if (getSchemeInfo().m_bPort) 4226 { 4227 m_aAbsURIRef.append(sal_Unicode(':')); 4228 m_aPort.set(m_aAbsURIRef, 4229 rtl::OUString::valueOf(sal_Int64(nThePort)), 4230 m_aAbsURIRef.getLength()); 4231 } 4232 else 4233 { 4234 setInvalid(); 4235 return false; 4236 } 4237 } 4238 } 4239 else if (rTheHost.getLength() != 0 || nThePort != 0) 4240 { 4241 setInvalid(); 4242 return false; 4243 } 4244 } 4245 rtl::OUStringBuffer aSynPath; 4246 sal_Unicode const * p = rThePath.getStr(); 4247 sal_Unicode const * pEnd = p + rThePath.getLength(); 4248 if (!parsePath(m_eScheme, &p, pEnd, false, eMechanism, eCharset, false, '/', 4249 0x80000000, 0x80000000, 0x80000000, aSynPath) 4250 || p != pEnd) 4251 { 4252 setInvalid(); 4253 return false; 4254 } 4255 m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear(), 4256 m_aAbsURIRef.getLength()); 4257 return true; 4258 } 4259 4260 //============================================================================ 4261 // static 4262 rtl::OUString INetURLObject::GetAbsURL(rtl::OUString const & rTheBaseURIRef, 4263 rtl::OUString const & rTheRelURIRef, 4264 bool bIgnoreFragment, 4265 EncodeMechanism eEncodeMechanism, 4266 DecodeMechanism eDecodeMechanism, 4267 rtl_TextEncoding eCharset, 4268 FSysStyle eStyle) 4269 { 4270 // Backwards compatibility: 4271 if (rTheRelURIRef.getLength() == 0 || rTheRelURIRef[0] == '#') 4272 return rTheRelURIRef; 4273 4274 INetURLObject aTheAbsURIRef; 4275 bool bWasAbsolute; 4276 return INetURLObject(rTheBaseURIRef, eEncodeMechanism, eCharset). 4277 convertRelToAbs(rTheRelURIRef, false, aTheAbsURIRef, 4278 bWasAbsolute, eEncodeMechanism, 4279 eCharset, bIgnoreFragment, false, 4280 false, eStyle) 4281 || eEncodeMechanism != WAS_ENCODED 4282 || eDecodeMechanism != DECODE_TO_IURI 4283 || eCharset != RTL_TEXTENCODING_UTF8 ? 4284 aTheAbsURIRef.GetMainURL(eDecodeMechanism, eCharset) : 4285 rTheRelURIRef; 4286 } 4287 4288 //============================================================================ 4289 rtl::OUString INetURLObject::getExternalURL(DecodeMechanism eMechanism, 4290 rtl_TextEncoding eCharset) const 4291 { 4292 rtl::OUString aTheExtURIRef; 4293 translateToExternal( 4294 rtl::OUString(m_aAbsURIRef), aTheExtURIRef, eMechanism, eCharset); 4295 return aTheExtURIRef; 4296 } 4297 4298 //============================================================================ 4299 // static 4300 rtl::OUString INetURLObject::GetScheme(INetProtocol eTheScheme) 4301 { 4302 return rtl::OUString::createFromAscii(getSchemeInfo(eTheScheme).m_pPrefix); 4303 } 4304 4305 //============================================================================ 4306 // static 4307 INetProtocol INetURLObject::CompareProtocolScheme(rtl::OUString const & 4308 rTheAbsURIRef) 4309 { 4310 sal_Unicode const * p = rTheAbsURIRef.getStr(); 4311 PrefixInfo const * pPrefix = getPrefix(p, p + rTheAbsURIRef.getLength()); 4312 return pPrefix ? pPrefix->m_eScheme : INET_PROT_NOT_VALID; 4313 } 4314 4315 //============================================================================ 4316 bool INetURLObject::hasPassword() const 4317 { 4318 return m_aAuth.isPresent() && getSchemeInfo().m_bPassword; 4319 } 4320 4321 //============================================================================ 4322 void INetURLObject::makeAuthCanonic() 4323 { 4324 if (m_eScheme == INET_PROT_IMAP && m_aAuth.getLength() == 1 4325 && m_aAbsURIRef.charAt(m_aAuth.getBegin()) == '*') 4326 { 4327 lcl_Erase(m_aAbsURIRef, m_aAuth.getBegin() 4328 - RTL_CONSTASCII_LENGTH(";AUTH="), 4329 RTL_CONSTASCII_LENGTH(";AUTH=*")); 4330 sal_Int32 nDelta = m_aAuth.clear() - RTL_CONSTASCII_LENGTH(";AUTH="); 4331 m_aPath += nDelta; 4332 m_aQuery += nDelta; 4333 m_aFragment += nDelta; 4334 } 4335 } 4336 4337 //============================================================================ 4338 rtl::OUString INetURLObject::GetHostPort(DecodeMechanism eMechanism, 4339 rtl_TextEncoding eCharset) 4340 { 4341 // Check because PROT_VND_SUN_STAR_HELP, PROT_VND_SUN_STAR_HIER, and 4342 // PROT_VND_SUN_STAR_PKG misuse m_aHost: 4343 if (!getSchemeInfo().m_bHost) 4344 return rtl::OUString(); 4345 rtl::OUStringBuffer aHostPort(decode(m_aHost, getEscapePrefix(), 4346 eMechanism, eCharset)); 4347 if (m_aPort.isPresent()) 4348 { 4349 aHostPort.append(sal_Unicode(':')); 4350 aHostPort.append(decode(m_aPort, getEscapePrefix(), 4351 eMechanism, eCharset)); 4352 } 4353 return aHostPort.makeStringAndClear(); 4354 } 4355 4356 //============================================================================ 4357 sal_uInt32 INetURLObject::GetPort() const 4358 { 4359 if (m_aPort.isPresent()) 4360 { 4361 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPort.getBegin(); 4362 sal_Unicode const * pEnd = p + m_aPort.getLength(); 4363 sal_uInt32 nThePort; 4364 if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd) 4365 return nThePort; 4366 } 4367 return 0; 4368 } 4369 4370 //============================================================================ 4371 bool INetURLObject::SetPort(sal_uInt32 nThePort) 4372 { 4373 if (getSchemeInfo().m_bPort && m_aHost.isPresent()) 4374 { 4375 rtl::OUString aNewPort(rtl::OUString::valueOf(sal_Int64(nThePort))); 4376 sal_Int32 nDelta; 4377 if (m_aPort.isPresent()) 4378 nDelta = m_aPort.set(m_aAbsURIRef, aNewPort); 4379 else 4380 { 4381 m_aAbsURIRef.insert(m_aHost.getEnd(), sal_Unicode(':')); 4382 nDelta = m_aPort.set(m_aAbsURIRef, aNewPort, m_aHost.getEnd() + 1) 4383 + 1; 4384 } 4385 m_aPath += nDelta; 4386 m_aQuery += nDelta; 4387 m_aFragment += nDelta; 4388 return true; 4389 } 4390 return false; 4391 } 4392 4393 //============================================================================ 4394 void INetURLObject::makePortCanonic() 4395 { 4396 if (m_aPort.isPresent()) 4397 { 4398 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPort.getBegin(); 4399 sal_Unicode const * pEnd = p + m_aPort.getLength(); 4400 sal_uInt32 nThePort; 4401 if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd) 4402 { 4403 sal_Int32 nDelta; 4404 if (nThePort != 0 && nThePort == getSchemeInfo().m_nDefaultPort) 4405 { 4406 lcl_Erase(m_aAbsURIRef, m_aPort.getBegin() - 1, 4407 m_aPort.getLength() + 1); 4408 nDelta = m_aPort.clear() - 1; 4409 } 4410 else 4411 nDelta = m_aPort.set(m_aAbsURIRef, 4412 rtl::OUString::valueOf(sal_Int64(nThePort))); 4413 m_aPath += nDelta; 4414 m_aQuery += nDelta; 4415 m_aFragment += nDelta; 4416 } 4417 } 4418 } 4419 4420 //============================================================================ 4421 sal_Int32 INetURLObject::getSegmentCount(bool bIgnoreFinalSlash) const 4422 { 4423 if (!checkHierarchical()) 4424 return 0; 4425 4426 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4427 sal_Unicode const * pEnd = p + m_aPath.getLength(); 4428 if (bIgnoreFinalSlash && pEnd > p && pEnd[-1] == '/') 4429 --pEnd; 4430 sal_Int32 n = p == pEnd || *p == '/' ? 0 : 1; 4431 while (p != pEnd) 4432 if (*p++ == '/') 4433 ++n; 4434 return n; 4435 } 4436 4437 //============================================================================ 4438 bool INetURLObject::removeSegment(sal_Int32 nIndex, bool bIgnoreFinalSlash) 4439 { 4440 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4441 if (!aSegment.isPresent()) 4442 return false; 4443 4444 rtl::OUStringBuffer aNewPath; 4445 aNewPath.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(), 4446 aSegment.getBegin() - m_aPath.getBegin()); 4447 if (bIgnoreFinalSlash && aSegment.getEnd() == m_aPath.getEnd()) 4448 aNewPath.append(sal_Unicode('/')); 4449 else 4450 aNewPath.append(m_aAbsURIRef.getStr() + aSegment.getEnd(), 4451 m_aPath.getEnd() - aSegment.getEnd()); 4452 if (aNewPath.getLength() == 0 && !aSegment.isEmpty() && 4453 m_aAbsURIRef[aSegment.getBegin()] == '/') 4454 { 4455 aNewPath.append(sal_Unicode('/')); 4456 } 4457 4458 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4459 RTL_TEXTENCODING_UTF8); 4460 } 4461 4462 //============================================================================ 4463 rtl::OUString INetURLObject::getName(sal_Int32 nIndex, bool bIgnoreFinalSlash, 4464 DecodeMechanism eMechanism, 4465 rtl_TextEncoding eCharset) const 4466 { 4467 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4468 if (!aSegment.isPresent()) 4469 return rtl::OUString(); 4470 4471 sal_Unicode const * pSegBegin 4472 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4473 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4474 4475 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4476 ++pSegBegin; 4477 sal_Unicode const * p = pSegBegin; 4478 while (p != pSegEnd && *p != ';') 4479 ++p; 4480 4481 return decode(pSegBegin, p, getEscapePrefix(), eMechanism, eCharset); 4482 } 4483 4484 //============================================================================ 4485 bool INetURLObject::setName(rtl::OUString const & rTheName, sal_Int32 nIndex, 4486 bool bIgnoreFinalSlash, 4487 EncodeMechanism eMechanism, 4488 rtl_TextEncoding eCharset) 4489 { 4490 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4491 if (!aSegment.isPresent()) 4492 return false; 4493 4494 sal_Unicode const * pPathBegin 4495 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4496 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4497 sal_Unicode const * pSegBegin 4498 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4499 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4500 4501 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4502 ++pSegBegin; 4503 sal_Unicode const * p = pSegBegin; 4504 while (p != pSegEnd && *p != ';') 4505 ++p; 4506 4507 rtl::OUStringBuffer aNewPath; 4508 aNewPath.append(pPathBegin, pSegBegin - pPathBegin); 4509 aNewPath.append(encodeText(rTheName, false, PART_PCHAR, getEscapePrefix(), 4510 eMechanism, eCharset, true)); 4511 aNewPath.append(p, pPathEnd - p); 4512 4513 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4514 RTL_TEXTENCODING_UTF8); 4515 } 4516 4517 //============================================================================ 4518 bool INetURLObject::hasExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash) 4519 const 4520 { 4521 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4522 if (!aSegment.isPresent()) 4523 return false; 4524 4525 sal_Unicode const * pSegBegin 4526 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4527 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4528 4529 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4530 ++pSegBegin; 4531 for (sal_Unicode const * p = pSegBegin; p != pSegEnd && *p != ';'; ++p) 4532 if (*p == '.' && p != pSegBegin) 4533 return true; 4534 return false; 4535 } 4536 4537 //============================================================================ 4538 rtl::OUString INetURLObject::getBase(sal_Int32 nIndex, bool bIgnoreFinalSlash, 4539 DecodeMechanism eMechanism, 4540 rtl_TextEncoding eCharset) const 4541 { 4542 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4543 if (!aSegment.isPresent()) 4544 return rtl::OUString(); 4545 4546 sal_Unicode const * pSegBegin 4547 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4548 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4549 4550 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4551 ++pSegBegin; 4552 sal_Unicode const * pExtension = 0; 4553 sal_Unicode const * p = pSegBegin; 4554 for (; p != pSegEnd && *p != ';'; ++p) 4555 if (*p == '.' && p != pSegBegin) 4556 pExtension = p; 4557 if (!pExtension) 4558 pExtension = p; 4559 4560 return decode(pSegBegin, pExtension, getEscapePrefix(), eMechanism, 4561 eCharset); 4562 } 4563 4564 //============================================================================ 4565 bool INetURLObject::setBase(rtl::OUString const & rTheBase, sal_Int32 nIndex, 4566 bool bIgnoreFinalSlash, 4567 EncodeMechanism eMechanism, 4568 rtl_TextEncoding eCharset) 4569 { 4570 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4571 if (!aSegment.isPresent()) 4572 return false; 4573 4574 sal_Unicode const * pPathBegin 4575 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4576 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4577 sal_Unicode const * pSegBegin 4578 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4579 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4580 4581 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4582 ++pSegBegin; 4583 sal_Unicode const * pExtension = 0; 4584 sal_Unicode const * p = pSegBegin; 4585 for (; p != pSegEnd && *p != ';'; ++p) 4586 if (*p == '.' && p != pSegBegin) 4587 pExtension = p; 4588 if (!pExtension) 4589 pExtension = p; 4590 4591 rtl::OUStringBuffer aNewPath; 4592 aNewPath.append(pPathBegin, pSegBegin - pPathBegin); 4593 aNewPath.append(encodeText(rTheBase, false, PART_PCHAR, getEscapePrefix(), 4594 eMechanism, eCharset, true)); 4595 aNewPath.append(pExtension, pPathEnd - pExtension); 4596 4597 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4598 RTL_TEXTENCODING_UTF8); 4599 } 4600 4601 //============================================================================ 4602 rtl::OUString INetURLObject::getExtension(sal_Int32 nIndex, 4603 bool bIgnoreFinalSlash, 4604 DecodeMechanism eMechanism, 4605 rtl_TextEncoding eCharset) const 4606 { 4607 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4608 if (!aSegment.isPresent()) 4609 return rtl::OUString(); 4610 4611 sal_Unicode const * pSegBegin 4612 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4613 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4614 4615 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4616 ++pSegBegin; 4617 sal_Unicode const * pExtension = 0; 4618 sal_Unicode const * p = pSegBegin; 4619 for (; p != pSegEnd && *p != ';'; ++p) 4620 if (*p == '.' && p != pSegBegin) 4621 pExtension = p; 4622 4623 if (!pExtension) 4624 return rtl::OUString(); 4625 4626 return decode(pExtension + 1, p, getEscapePrefix(), eMechanism, eCharset); 4627 } 4628 4629 //============================================================================ 4630 bool INetURLObject::setExtension(rtl::OUString const & rTheExtension, 4631 sal_Int32 nIndex, bool bIgnoreFinalSlash, 4632 EncodeMechanism eMechanism, 4633 rtl_TextEncoding eCharset) 4634 { 4635 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4636 if (!aSegment.isPresent()) 4637 return false; 4638 4639 sal_Unicode const * pPathBegin 4640 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4641 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4642 sal_Unicode const * pSegBegin 4643 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4644 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4645 4646 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4647 ++pSegBegin; 4648 sal_Unicode const * pExtension = 0; 4649 sal_Unicode const * p = pSegBegin; 4650 for (; p != pSegEnd && *p != ';'; ++p) 4651 if (*p == '.' && p != pSegBegin) 4652 pExtension = p; 4653 if (!pExtension) 4654 pExtension = p; 4655 4656 rtl::OUStringBuffer aNewPath; 4657 aNewPath.append(pPathBegin, pExtension - pPathBegin); 4658 aNewPath.append(sal_Unicode('.')); 4659 aNewPath.append(encodeText(rTheExtension, false, PART_PCHAR, 4660 getEscapePrefix(), eMechanism, eCharset, true)); 4661 aNewPath.append(p, pPathEnd - p); 4662 4663 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4664 RTL_TEXTENCODING_UTF8); 4665 } 4666 4667 //============================================================================ 4668 bool INetURLObject::removeExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash) 4669 { 4670 SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); 4671 if (!aSegment.isPresent()) 4672 return false; 4673 4674 sal_Unicode const * pPathBegin 4675 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4676 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4677 sal_Unicode const * pSegBegin 4678 = m_aAbsURIRef.getStr() + aSegment.getBegin(); 4679 sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); 4680 4681 if (pSegBegin < pSegEnd && *pSegBegin == '/') 4682 ++pSegBegin; 4683 sal_Unicode const * pExtension = 0; 4684 sal_Unicode const * p = pSegBegin; 4685 for (; p != pSegEnd && *p != ';'; ++p) 4686 if (*p == '.' && p != pSegBegin) 4687 pExtension = p; 4688 if (!pExtension) 4689 return true; 4690 4691 rtl::OUStringBuffer aNewPath; 4692 aNewPath.append(pPathBegin, pExtension - pPathBegin); 4693 aNewPath.append(p, pPathEnd - p); 4694 4695 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4696 RTL_TEXTENCODING_UTF8); 4697 } 4698 4699 //============================================================================ 4700 bool INetURLObject::hasFinalSlash() const 4701 { 4702 if (!checkHierarchical()) 4703 return false; 4704 4705 sal_Unicode const * pPathBegin 4706 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4707 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4708 return pPathEnd > pPathBegin && pPathEnd[-1] == '/'; 4709 } 4710 4711 //============================================================================ 4712 bool INetURLObject::setFinalSlash() 4713 { 4714 if (!checkHierarchical()) 4715 return false; 4716 4717 sal_Unicode const * pPathBegin 4718 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4719 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4720 if (pPathEnd > pPathBegin && pPathEnd[-1] == '/') 4721 return true; 4722 4723 rtl::OUStringBuffer aNewPath; 4724 aNewPath.append(pPathBegin, pPathEnd - pPathBegin); 4725 aNewPath.append(sal_Unicode('/')); 4726 4727 return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC, 4728 RTL_TEXTENCODING_UTF8); 4729 } 4730 4731 //============================================================================ 4732 bool INetURLObject::removeFinalSlash() 4733 { 4734 if (!checkHierarchical()) 4735 return false; 4736 4737 sal_Unicode const * pPathBegin 4738 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 4739 sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); 4740 if (pPathEnd <= pPathBegin || pPathEnd[-1] != '/') 4741 return true; 4742 4743 --pPathEnd; 4744 if (pPathEnd == pPathBegin && *pPathBegin == '/') 4745 return false; 4746 rtl::OUString aNewPath(pPathBegin, pPathEnd - pPathBegin); 4747 4748 return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8); 4749 } 4750 4751 //============================================================================ 4752 // static 4753 rtl::OUString INetURLObject::createFragment(rtl::OUString const & rText) 4754 { 4755 rtl::OUString aFragment(rText); 4756 for (sal_Int32 i = 0; i < aFragment.getLength();) 4757 { 4758 sal_Unicode c = aFragment.getStr()[i]; 4759 if (mustEncode(c, PART_CREATEFRAGMENT)) 4760 aFragment = aFragment.replaceAt(i, 1, rtl::OUString()); 4761 else 4762 ++i; 4763 } 4764 return aFragment; 4765 } 4766 4767 //============================================================================ 4768 bool INetURLObject::setFSysPath(rtl::OUString const & rFSysPath, 4769 FSysStyle eStyle) 4770 { 4771 sal_Unicode const * pFSysBegin = rFSysPath.getStr(); 4772 sal_Unicode const * pFSysEnd = pFSysBegin + rFSysPath.getLength(); 4773 4774 switch ((eStyle & FSYS_VOS ? 1 : 0) 4775 + (eStyle & FSYS_UNX ? 1 : 0) 4776 + (eStyle & FSYS_DOS ? 1 : 0) 4777 + (eStyle & FSYS_MAC ? 1 : 0)) 4778 { 4779 case 0: 4780 return false; 4781 4782 case 1: 4783 break; 4784 4785 default: 4786 if (eStyle & FSYS_VOS 4787 && pFSysEnd - pFSysBegin >= 2 4788 && pFSysBegin[0] == '/' 4789 && pFSysBegin[1] == '/') 4790 { 4791 if (pFSysEnd - pFSysBegin >= 3 4792 && pFSysBegin[2] == '.' 4793 && (pFSysEnd - pFSysBegin == 3 || pFSysBegin[3] == '/')) 4794 { 4795 eStyle = FSYS_VOS; // Production T1 4796 break; 4797 } 4798 4799 sal_Unicode const * p = pFSysBegin + 2; 4800 rtl::OUString aHost; 4801 if (parseHost(p, pFSysEnd, aHost) 4802 && (p == pFSysEnd || *p == '/')) 4803 { 4804 eStyle = FSYS_VOS; // Production T2 4805 break; 4806 } 4807 } 4808 4809 if (eStyle & FSYS_DOS 4810 && pFSysEnd - pFSysBegin >= 2 4811 && pFSysBegin[0] == '\\' 4812 && pFSysBegin[1] == '\\') 4813 { 4814 sal_Unicode const * p = pFSysBegin + 2; 4815 rtl::OUString aHost; 4816 if (parseHost(p, pFSysEnd, aHost) 4817 && (p == pFSysEnd || *p == '\\')) 4818 { 4819 eStyle = FSYS_DOS; // Production T3 4820 break; 4821 } 4822 } 4823 4824 if (eStyle & FSYS_DOS 4825 && pFSysEnd - pFSysBegin >= 2 4826 && INetMIME::isAlpha(pFSysBegin[0]) 4827 && pFSysBegin[1] == ':' 4828 && (pFSysEnd - pFSysBegin == 2 4829 || pFSysBegin[2] == '/' 4830 || pFSysBegin[2] == '\\')) 4831 { 4832 eStyle = FSYS_DOS; // Productions T4, T5 4833 break; 4834 } 4835 4836 if (!(eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC))) 4837 return false; 4838 4839 eStyle = guessFSysStyleByCounting(pFSysBegin, pFSysEnd, eStyle); 4840 // Production T6 4841 break; 4842 } 4843 4844 rtl::OUStringBuffer aSynAbsURIRef(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://"))); 4845 4846 switch (eStyle) 4847 { 4848 case FSYS_VOS: 4849 { 4850 sal_Unicode const * p = pFSysBegin; 4851 if (pFSysEnd - p < 2 || *p++ != '/' || *p++ != '/') 4852 return false; 4853 if (p != pFSysEnd && *p == '.' 4854 && (pFSysEnd - p == 1 || p[1] == '/')) 4855 ++p; 4856 for (; p != pFSysEnd; ++p) 4857 switch (*p) 4858 { 4859 case '#': 4860 case '%': 4861 appendEscape(aSynAbsURIRef, '%', *p); 4862 break; 4863 4864 default: 4865 aSynAbsURIRef.append(*p); 4866 break; 4867 } 4868 break; 4869 } 4870 4871 case FSYS_UNX: 4872 { 4873 sal_Unicode const * p = pFSysBegin; 4874 if (p != pFSysEnd && *p != '/') 4875 return false; 4876 for (; p != pFSysEnd; ++p) 4877 switch (*p) 4878 { 4879 case '|': 4880 case '#': 4881 case '%': 4882 appendEscape(aSynAbsURIRef, '%', *p); 4883 break; 4884 4885 default: 4886 aSynAbsURIRef.append(*p); 4887 break; 4888 } 4889 break; 4890 } 4891 4892 case FSYS_DOS: 4893 { 4894 sal_uInt32 nAltDelimiter = 0x80000000; 4895 sal_Unicode const * p = pFSysBegin; 4896 if (pFSysEnd - p >= 3 && p[0] == '\\' && p[1] == '\\') 4897 p += 2; 4898 else 4899 { 4900 aSynAbsURIRef.append(sal_Unicode('/')); 4901 if (pFSysEnd - p >= 2 4902 && INetMIME::isAlpha(p[0]) 4903 && p[1] == ':' 4904 && (pFSysEnd - p == 2 || p[2] == '\\' || p[2] == '/')) 4905 nAltDelimiter = '/'; 4906 } 4907 for (; p != pFSysEnd; ++p) 4908 if (*p == '\\' || *p == nAltDelimiter) 4909 aSynAbsURIRef.append(sal_Unicode('/')); 4910 else 4911 switch (*p) 4912 { 4913 case '/': 4914 case '#': 4915 case '%': 4916 appendEscape(aSynAbsURIRef, '%', *p); 4917 break; 4918 4919 default: 4920 aSynAbsURIRef.append(*p); 4921 break; 4922 } 4923 break; 4924 } 4925 4926 case FSYS_MAC: 4927 aSynAbsURIRef.append(sal_Unicode('/')); 4928 {for (sal_Unicode const * p = pFSysBegin; p != pFSysEnd; ++p) 4929 switch (*p) 4930 { 4931 case ':': 4932 aSynAbsURIRef.append(sal_Unicode('/')); 4933 break; 4934 4935 case '/': 4936 case '|': 4937 case '#': 4938 case '%': 4939 appendEscape(aSynAbsURIRef, '%', *p); 4940 break; 4941 4942 default: 4943 aSynAbsURIRef.append(*p); 4944 break; 4945 } 4946 } 4947 break; 4948 4949 default: 4950 OSL_ASSERT(false); 4951 break; 4952 } 4953 4954 INetURLObject aTemp(aSynAbsURIRef.makeStringAndClear(), WAS_ENCODED, 4955 RTL_TEXTENCODING_UTF8); 4956 if (aTemp.HasError()) 4957 return false; 4958 4959 *this = aTemp; 4960 return true; 4961 } 4962 4963 //============================================================================ 4964 rtl::OUString INetURLObject::getFSysPath(FSysStyle eStyle, 4965 sal_Unicode * pDelimiter) const 4966 { 4967 if (m_eScheme != INET_PROT_FILE) 4968 return rtl::OUString(); 4969 4970 if ((eStyle & FSYS_VOS ? 1 : 0) 4971 + (eStyle & FSYS_UNX ? 1 : 0) 4972 + (eStyle & FSYS_DOS ? 1 : 0) 4973 + (eStyle & FSYS_MAC ? 1 : 0) 4974 > 1) 4975 { 4976 eStyle = eStyle & FSYS_VOS 4977 && m_aHost.isPresent() 4978 && m_aHost.getLength() > 0 ? 4979 FSYS_VOS : 4980 hasDosVolume(eStyle) 4981 || ((eStyle & FSYS_DOS) != 0 4982 && m_aHost.isPresent() 4983 && m_aHost.getLength() > 0) ? 4984 FSYS_DOS : 4985 eStyle & FSYS_UNX 4986 && (!m_aHost.isPresent() || m_aHost.getLength() == 0) ? 4987 FSYS_UNX : 4988 FSysStyle(0); 4989 } 4990 4991 switch (eStyle) 4992 { 4993 case FSYS_VOS: 4994 { 4995 if (pDelimiter) 4996 *pDelimiter = '/'; 4997 4998 rtl::OUStringBuffer aSynFSysPath; 4999 aSynFSysPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 5000 if (m_aHost.isPresent() && m_aHost.getLength() > 0) 5001 aSynFSysPath.append(decode(m_aHost, '%', DECODE_WITH_CHARSET, 5002 RTL_TEXTENCODING_UTF8)); 5003 else 5004 aSynFSysPath.append(sal_Unicode('.')); 5005 aSynFSysPath.append(decode(m_aPath, '%', DECODE_WITH_CHARSET, 5006 RTL_TEXTENCODING_UTF8)); 5007 return aSynFSysPath.makeStringAndClear(); 5008 } 5009 5010 case FSYS_UNX: 5011 { 5012 if (m_aHost.isPresent() && m_aHost.getLength() > 0) 5013 return rtl::OUString(); 5014 5015 if (pDelimiter) 5016 *pDelimiter = '/'; 5017 5018 return decode(m_aPath, '%', DECODE_WITH_CHARSET, 5019 RTL_TEXTENCODING_UTF8); 5020 } 5021 5022 case FSYS_DOS: 5023 { 5024 if (pDelimiter) 5025 *pDelimiter = '\\'; 5026 5027 rtl::OUStringBuffer aSynFSysPath; 5028 if (m_aHost.isPresent() && m_aHost.getLength() > 0) 5029 { 5030 aSynFSysPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("\\\\")); 5031 aSynFSysPath.append(decode(m_aHost, '%', DECODE_WITH_CHARSET, 5032 RTL_TEXTENCODING_UTF8)); 5033 aSynFSysPath.append(sal_Unicode('\\')); 5034 } 5035 sal_Unicode const * p 5036 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 5037 sal_Unicode const * pEnd = p + m_aPath.getLength(); 5038 DBG_ASSERT(p < pEnd && *p == '/', 5039 "INetURLObject::getFSysPath(): Bad path"); 5040 ++p; 5041 while (p < pEnd) 5042 { 5043 EscapeType eEscapeType; 5044 sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED, 5045 RTL_TEXTENCODING_UTF8, 5046 eEscapeType); 5047 if (eEscapeType == ESCAPE_NO && nUTF32 == '/') 5048 aSynFSysPath.append(sal_Unicode('\\')); 5049 else 5050 aSynFSysPath.appendUtf32(nUTF32); 5051 } 5052 return aSynFSysPath.makeStringAndClear(); 5053 } 5054 5055 case FSYS_MAC: 5056 { 5057 if (m_aHost.isPresent() && m_aHost.getLength() > 0) 5058 return rtl::OUString(); 5059 5060 if (pDelimiter) 5061 *pDelimiter = ':'; 5062 5063 rtl::OUStringBuffer aSynFSysPath; 5064 sal_Unicode const * p 5065 = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 5066 sal_Unicode const * pEnd = p + m_aPath.getLength(); 5067 DBG_ASSERT(p < pEnd && *p == '/', 5068 "INetURLObject::getFSysPath(): Bad path"); 5069 ++p; 5070 while (p < pEnd) 5071 { 5072 EscapeType eEscapeType; 5073 sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED, 5074 RTL_TEXTENCODING_UTF8, 5075 eEscapeType); 5076 if (eEscapeType == ESCAPE_NO && nUTF32 == '/') 5077 aSynFSysPath.append(sal_Unicode(':')); 5078 else 5079 aSynFSysPath.appendUtf32(nUTF32); 5080 } 5081 return aSynFSysPath.makeStringAndClear(); 5082 } 5083 5084 default: 5085 return rtl::OUString(); 5086 } 5087 } 5088 5089 //============================================================================ 5090 bool INetURLObject::HasMsgId() const 5091 { 5092 if (m_eScheme != INET_PROT_POP3) 5093 return false; 5094 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 5095 sal_Unicode const * pEnd = p + m_aPath.getLength(); 5096 for (; p < pEnd; ++p) 5097 if (*p == '<') 5098 return true; 5099 return false; 5100 } 5101 5102 //============================================================================ 5103 rtl::OUString INetURLObject::GetMsgId(DecodeMechanism eMechanism, 5104 rtl_TextEncoding eCharset) const 5105 { 5106 if (m_eScheme != INET_PROT_POP3) 5107 return rtl::OUString(); 5108 sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); 5109 sal_Unicode const * pEnd = p + m_aPath.getLength(); 5110 for (; p < pEnd; ++p) 5111 if (*p == '<') 5112 return decode(p, pEnd, getEscapePrefix(), eMechanism, eCharset); 5113 return rtl::OUString(); 5114 } 5115 5116 //============================================================================ 5117 // static 5118 void INetURLObject::appendUCS4Escape(rtl::OUStringBuffer & rTheText, 5119 sal_Char cEscapePrefix, sal_uInt32 nUCS4) 5120 { 5121 DBG_ASSERT(nUCS4 < 0x80000000, 5122 "INetURLObject::appendUCS4Escape(): Bad char"); 5123 if (nUCS4 < 0x80) 5124 appendEscape(rTheText, cEscapePrefix, nUCS4); 5125 else if (nUCS4 < 0x800) 5126 { 5127 appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 | 0xC0); 5128 appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80); 5129 } 5130 else if (nUCS4 < 0x10000) 5131 { 5132 appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 | 0xE0); 5133 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80); 5134 appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80); 5135 } 5136 else if (nUCS4 < 0x200000) 5137 { 5138 appendEscape(rTheText, cEscapePrefix, nUCS4 >> 18 | 0xF0); 5139 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80); 5140 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80); 5141 appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80); 5142 } 5143 else if (nUCS4 < 0x4000000) 5144 { 5145 appendEscape(rTheText, cEscapePrefix, nUCS4 >> 24 | 0xF8); 5146 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 18 & 0x3F) | 0x80); 5147 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80); 5148 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80); 5149 appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80); 5150 } 5151 else 5152 { 5153 appendEscape(rTheText, cEscapePrefix, nUCS4 >> 30 | 0xFC); 5154 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 24 & 0x3F) | 0x80); 5155 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 18 & 0x3F) | 0x80); 5156 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80); 5157 appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80); 5158 appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80); 5159 } 5160 } 5161 5162 //============================================================================ 5163 // static 5164 void INetURLObject::appendUCS4(rtl::OUStringBuffer& rTheText, sal_uInt32 nUCS4, 5165 EscapeType eEscapeType, bool bOctets, 5166 Part ePart, sal_Char cEscapePrefix, 5167 rtl_TextEncoding eCharset, 5168 bool bKeepVisibleEscapes) 5169 { 5170 bool bEscape; 5171 rtl_TextEncoding eTargetCharset = RTL_TEXTENCODING_DONTKNOW; 5172 switch (eEscapeType) 5173 { 5174 case ESCAPE_NO: 5175 if (mustEncode(nUCS4, ePart)) 5176 { 5177 bEscape = true; 5178 eTargetCharset = bOctets ? RTL_TEXTENCODING_ISO_8859_1 : 5179 RTL_TEXTENCODING_UTF8; 5180 } 5181 else 5182 bEscape = false; 5183 break; 5184 5185 case ESCAPE_OCTET: 5186 bEscape = true; 5187 eTargetCharset = RTL_TEXTENCODING_ISO_8859_1; 5188 break; 5189 5190 case ESCAPE_UTF32: 5191 if (mustEncode(nUCS4, ePart)) 5192 { 5193 bEscape = true; 5194 eTargetCharset = eCharset; 5195 } 5196 else if (bKeepVisibleEscapes && INetMIME::isVisible(nUCS4)) 5197 { 5198 bEscape = true; 5199 eTargetCharset = RTL_TEXTENCODING_ASCII_US; 5200 } 5201 else 5202 bEscape = false; 5203 break; 5204 default: 5205 bEscape = false; 5206 } 5207 5208 if (bEscape) 5209 { 5210 switch (eTargetCharset) 5211 { 5212 default: 5213 DBG_ERROR("INetURLObject::appendUCS4(): Unsupported charset"); 5214 case RTL_TEXTENCODING_ASCII_US: 5215 case RTL_TEXTENCODING_ISO_8859_1: 5216 appendEscape(rTheText, cEscapePrefix, nUCS4); 5217 break; 5218 5219 case RTL_TEXTENCODING_UTF8: 5220 appendUCS4Escape(rTheText, cEscapePrefix, nUCS4); 5221 break; 5222 } 5223 } 5224 else 5225 rTheText.append(sal_Unicode(nUCS4)); 5226 } 5227 5228 //============================================================================ 5229 // static 5230 sal_uInt32 INetURLObject::getUTF32(sal_Unicode const *& rBegin, 5231 sal_Unicode const * pEnd, bool bOctets, 5232 sal_Char cEscapePrefix, 5233 EncodeMechanism eMechanism, 5234 rtl_TextEncoding eCharset, 5235 EscapeType & rEscapeType) 5236 { 5237 DBG_ASSERT(rBegin < pEnd, "INetURLObject::getUTF32(): Bad sequence"); 5238 sal_uInt32 nUTF32 = bOctets ? *rBegin++ : 5239 INetMIME::getUTF32Character(rBegin, pEnd); 5240 switch (eMechanism) 5241 { 5242 case ENCODE_ALL: 5243 rEscapeType = ESCAPE_NO; 5244 break; 5245 5246 case WAS_ENCODED: 5247 { 5248 int nWeight1; 5249 int nWeight2; 5250 if (nUTF32 == sal_uChar(cEscapePrefix) && rBegin + 1 < pEnd 5251 && (nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0 5252 && (nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0) 5253 { 5254 rBegin += 2; 5255 nUTF32 = nWeight1 << 4 | nWeight2; 5256 switch (eCharset) 5257 { 5258 default: 5259 DBG_ERROR( 5260 "INetURLObject::getUTF32(): Unsupported charset"); 5261 case RTL_TEXTENCODING_ASCII_US: 5262 rEscapeType = INetMIME::isUSASCII(nUTF32) ? 5263 ESCAPE_UTF32 : ESCAPE_OCTET; 5264 break; 5265 5266 case RTL_TEXTENCODING_ISO_8859_1: 5267 rEscapeType = ESCAPE_UTF32; 5268 break; 5269 5270 case RTL_TEXTENCODING_UTF8: 5271 if (INetMIME::isUSASCII(nUTF32)) 5272 rEscapeType = ESCAPE_UTF32; 5273 else 5274 { 5275 if (nUTF32 >= 0xC0 && nUTF32 <= 0xF4) 5276 { 5277 sal_uInt32 nEncoded; 5278 int nShift; 5279 sal_uInt32 nMin; 5280 if (nUTF32 <= 0xDF) 5281 { 5282 nEncoded = (nUTF32 & 0x1F) << 6; 5283 nShift = 0; 5284 nMin = 0x80; 5285 } 5286 else if (nUTF32 <= 0xEF) 5287 { 5288 nEncoded = (nUTF32 & 0x0F) << 12; 5289 nShift = 6; 5290 nMin = 0x800; 5291 } 5292 else 5293 { 5294 nEncoded = (nUTF32 & 0x07) << 18; 5295 nShift = 12; 5296 nMin = 0x10000; 5297 } 5298 sal_Unicode const * p = rBegin; 5299 bool bUTF8 = true; 5300 for (;;) 5301 { 5302 if (pEnd - p < 3 5303 || p[0] != cEscapePrefix 5304 || (nWeight1 5305 = INetMIME::getHexWeight(p[1])) 5306 < 8 5307 || nWeight1 > 11 5308 || (nWeight2 5309 = INetMIME::getHexWeight(p[2])) 5310 < 0) 5311 { 5312 bUTF8 = false; 5313 break; 5314 } 5315 p += 3; 5316 nEncoded 5317 |= ((nWeight1 & 3) << 4 | nWeight2) 5318 << nShift; 5319 if (nShift == 0) 5320 break; 5321 nShift -= 6; 5322 } 5323 if (bUTF8 && nEncoded >= nMin 5324 && !INetMIME::isHighSurrogate(nEncoded) 5325 && !INetMIME::isLowSurrogate(nEncoded) 5326 && nEncoded <= 0x10FFFF) 5327 { 5328 rBegin = p; 5329 nUTF32 = nEncoded; 5330 rEscapeType = ESCAPE_UTF32; 5331 break; 5332 } 5333 } 5334 rEscapeType = ESCAPE_OCTET; 5335 } 5336 break; 5337 } 5338 } 5339 else 5340 rEscapeType = ESCAPE_NO; 5341 break; 5342 } 5343 5344 case NOT_CANONIC: 5345 { 5346 int nWeight1; 5347 int nWeight2; 5348 if (nUTF32 == sal_uChar(cEscapePrefix) && rBegin + 1 < pEnd 5349 && ((nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0) 5350 && ((nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0)) 5351 { 5352 rBegin += 2; 5353 nUTF32 = nWeight1 << 4 | nWeight2; 5354 rEscapeType = ESCAPE_OCTET; 5355 } 5356 else 5357 rEscapeType = ESCAPE_NO; 5358 break; 5359 } 5360 } 5361 return nUTF32; 5362 } 5363 5364 //============================================================================ 5365 // static 5366 sal_uInt32 INetURLObject::scanDomain(sal_Unicode const *& rBegin, 5367 sal_Unicode const * pEnd, 5368 bool bEager) 5369 { 5370 enum State { STATE_DOT, STATE_LABEL, STATE_HYPHEN }; 5371 State eState = STATE_DOT; 5372 sal_Int32 nLabels = 0; 5373 sal_Unicode const * pLastAlphanumeric = 0; 5374 for (sal_Unicode const * p = rBegin;; ++p) 5375 switch (eState) 5376 { 5377 case STATE_DOT: 5378 if (p != pEnd && INetMIME::isAlphanumeric(*p)) 5379 { 5380 ++nLabels; 5381 eState = STATE_LABEL; 5382 break; 5383 } 5384 if (bEager || nLabels == 0) 5385 return 0; 5386 rBegin = p - 1; 5387 return nLabels; 5388 5389 case STATE_LABEL: 5390 if (p != pEnd) 5391 { 5392 if (INetMIME::isAlphanumeric(*p)) 5393 break; 5394 else if (*p == '.') 5395 { 5396 eState = STATE_DOT; 5397 break; 5398 } 5399 else if (*p == '-') 5400 { 5401 pLastAlphanumeric = p; 5402 eState = STATE_HYPHEN; 5403 break; 5404 } 5405 } 5406 rBegin = p; 5407 return nLabels; 5408 5409 case STATE_HYPHEN: 5410 if (p != pEnd) 5411 { 5412 if (INetMIME::isAlphanumeric(*p)) 5413 { 5414 eState = STATE_LABEL; 5415 break; 5416 } 5417 else if (*p == '-') 5418 break; 5419 } 5420 if (bEager) 5421 return 0; 5422 rBegin = pLastAlphanumeric; 5423 return nLabels; 5424 } 5425 } 5426 5427 //============================================================================ 5428 // static 5429 bool INetURLObject::scanIPv6reference(sal_Unicode const *& rBegin, 5430 sal_Unicode const * pEnd) 5431 { 5432 if (rBegin != pEnd && *rBegin == '[') { 5433 sal_Unicode const * p = rBegin + 1; 5434 //TODO: check for valid IPv6address (RFC 2373): 5435 while (p != pEnd && (INetMIME::isHexDigit(*p) || *p == ':' || *p == '.')) 5436 { 5437 ++p; 5438 } 5439 if (p != pEnd && *p == ']') { 5440 rBegin = p + 1; 5441 return true; 5442 } 5443 } 5444 return false; 5445 } 5446 5447 //============================================================================ 5448 rtl::OUString INetURLObject::GetPartBeforeLastName(DecodeMechanism eMechanism, 5449 rtl_TextEncoding eCharset) 5450 const 5451 { 5452 if (!checkHierarchical()) 5453 return rtl::OUString(); 5454 INetURLObject aTemp(*this); 5455 aTemp.clearFragment(); 5456 aTemp.clearQuery(); 5457 aTemp.removeSegment(LAST_SEGMENT, false); 5458 aTemp.setFinalSlash(); 5459 return aTemp.GetMainURL(eMechanism, eCharset); 5460 } 5461 5462 //============================================================================ 5463 rtl::OUString INetURLObject::GetLastName(DecodeMechanism eMechanism, 5464 rtl_TextEncoding eCharset) const 5465 { 5466 return getName(LAST_SEGMENT, true, eMechanism, eCharset); 5467 } 5468 5469 //============================================================================ 5470 rtl::OUString INetURLObject::GetFileExtension(DecodeMechanism eMechanism, 5471 rtl_TextEncoding eCharset) const 5472 { 5473 return getExtension(LAST_SEGMENT, false, eMechanism, eCharset); 5474 } 5475 5476 //============================================================================ 5477 bool INetURLObject::CutLastName() 5478 { 5479 INetURLObject aTemp(*this); 5480 aTemp.clearFragment(); 5481 aTemp.clearQuery(); 5482 if (!aTemp.removeSegment(LAST_SEGMENT, false)) 5483 return false; 5484 *this = aTemp; 5485 return true; 5486 } 5487 5488 //============================================================================ 5489 rtl::OUString INetURLObject::PathToFileName() const 5490 { 5491 if (m_eScheme != INET_PROT_FILE) 5492 return rtl::OUString(); 5493 rtl::OUString aSystemPath; 5494 if (osl::FileBase::getSystemPathFromFileURL( 5495 decode(m_aAbsURIRef.getStr(), 5496 m_aAbsURIRef.getStr() + m_aPath.getEnd(), 5497 getEscapePrefix(), NO_DECODE, RTL_TEXTENCODING_UTF8), 5498 aSystemPath) 5499 != osl::FileBase::E_None) 5500 return rtl::OUString(); 5501 return aSystemPath; 5502 } 5503 5504 //============================================================================ 5505 rtl::OUString INetURLObject::GetFull() const 5506 { 5507 INetURLObject aTemp(*this); 5508 aTemp.removeFinalSlash(); 5509 return aTemp.PathToFileName(); 5510 } 5511 5512 //============================================================================ 5513 rtl::OUString INetURLObject::GetPath() const 5514 { 5515 INetURLObject aTemp(*this); 5516 aTemp.removeSegment(LAST_SEGMENT, true); 5517 aTemp.removeFinalSlash(); 5518 return aTemp.PathToFileName(); 5519 } 5520 5521 //============================================================================ 5522 void INetURLObject::SetBase(rtl::OUString const & rTheBase) 5523 { 5524 setBase(rTheBase, LAST_SEGMENT, true, ENCODE_ALL); 5525 } 5526 5527 //============================================================================ 5528 rtl::OUString INetURLObject::GetBase() const 5529 { 5530 return getBase(LAST_SEGMENT, true, DECODE_WITH_CHARSET); 5531 } 5532 5533 //============================================================================ 5534 void INetURLObject::SetName(rtl::OUString const & rTheName, 5535 EncodeMechanism eMechanism, 5536 rtl_TextEncoding eCharset) 5537 { 5538 INetURLObject aTemp(*this); 5539 if (aTemp.removeSegment(LAST_SEGMENT, true) 5540 && aTemp.insertName(rTheName, false, LAST_SEGMENT, true, eMechanism, 5541 eCharset)) 5542 *this = aTemp; 5543 } 5544 5545 //============================================================================ 5546 rtl::OUString INetURLObject::CutName(DecodeMechanism eMechanism, 5547 rtl_TextEncoding eCharset) 5548 { 5549 rtl::OUString aTheName(getName(LAST_SEGMENT, true, eMechanism, eCharset)); 5550 return removeSegment(LAST_SEGMENT, true) ? aTheName : rtl::OUString(); 5551 } 5552 5553 //============================================================================ 5554 void INetURLObject::SetExtension(rtl::OUString const & rTheExtension, 5555 EncodeMechanism eMechanism, 5556 rtl_TextEncoding eCharset) 5557 { 5558 setExtension(rTheExtension, LAST_SEGMENT, false, eMechanism, eCharset); 5559 } 5560 5561 //============================================================================ 5562 rtl::OUString INetURLObject::CutExtension(DecodeMechanism eMechanism, 5563 rtl_TextEncoding eCharset) 5564 { 5565 rtl::OUString aTheExtension(getExtension(LAST_SEGMENT, false, eMechanism, 5566 eCharset)); 5567 return removeExtension(LAST_SEGMENT, false) 5568 ? aTheExtension : rtl::OUString(); 5569 } 5570 5571 //============================================================================ 5572 bool INetURLObject::IsCaseSensitive() const 5573 { 5574 return true; 5575 } 5576