| /* |
| * Copyright (C) 2014 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "config.h" |
| |
| #import <wtf/Vector.h> |
| #import <wtf/cocoa/NSURLExtras.h> |
| #import <wtf/text/WTFString.h> |
| |
| namespace TestWebKitAPI { |
| |
| static NSData *literalAsData(const char* literal) |
| { |
| return [NSData dataWithBytes:literal length:strlen(literal)]; |
| } |
| |
| static const char* dataAsString(NSData *data) |
| { |
| static char buffer[1000]; |
| if ([data length] > sizeof(buffer) - 1) |
| return "ERROR"; |
| if (memchr([data bytes], 0, [data length])) |
| return "ERROR"; |
| memcpy(buffer, [data bytes], [data length]); |
| buffer[[data length]] = '\0'; |
| return buffer; |
| } |
| |
| static const char* originalDataAsString(NSURL *URL) |
| { |
| return dataAsString(WTF::originalURLData(URL)); |
| } |
| |
| static const char* userVisibleString(NSURL *URL) |
| { |
| return [WTF::userVisibleString(URL) UTF8String]; |
| } |
| |
| static NSURL *literalURL(const char* literal) |
| { |
| return WTF::URLWithData(literalAsData(literal), nil); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras) |
| { |
| EXPECT_STREQ("http://site.com", originalDataAsString(literalURL("http://site.com"))); |
| EXPECT_STREQ("http://%77ebsite.com", originalDataAsString(literalURL("http://%77ebsite.com"))); |
| |
| EXPECT_STREQ("http://site.com", userVisibleString(literalURL("http://site.com"))); |
| EXPECT_STREQ("http://%77ebsite.com", userVisibleString(literalURL("http://%77ebsite.com"))); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_Spoof) |
| { |
| Vector<String> punycodedSpoofHosts = { |
| "xn--cfa45g", // U+0131, U+0307 |
| "xn--tma03b", // U+0237, U+0307 |
| "xn--tma03bxga", // U+0237, U+034F, U+034F, U+0307 |
| "xn--tma03bl01e", // U+0237, U+200B, U+0307 |
| "xn--a-egb", // a, U+034F |
| "xn--a-qgn", // a, U+200B |
| "xn--a-mgn", // a, U+2009 |
| "xn--u7f", // U+1D04 |
| "xn--57f", // U+1D0F |
| "xn--i38a", // U+A731 |
| "xn--j8f", // U+1D1C |
| "xn--n8f", // U+1D20 |
| "xn--o8f", // U+1D21 |
| "xn--p8f", // U+1D22 |
| "xn--0na", // U+0261 |
| "xn--cn-ded", // U+054D |
| "xn--ews-nfe.org", // U+054D |
| "xn--yotube-qkh", // U+0578 |
| "xn--cla-7fe.edu", // U+0578 |
| "xn--rsa94l", // U+05D5 U+0307 |
| "xn--hdb9c", // U+05D5 U+05B9 |
| "xn--idb7c", // U+05D5 U+05BA |
| "xn--pdb3b", // U+05D5 U+05C1 |
| "xn--qdb1b", // U+05D5 U+05C2 |
| "xn--sdb7a", // U+05D5 U+05C4 |
| "xn--2-zic", // U+0032 U+05E1 |
| "xn--uoa", // U+027E |
| "xn--fja", // U+01C0 |
| }; |
| for (const String& host : punycodedSpoofHosts) { |
| auto url = makeString("http://", host, "/").utf8(); |
| EXPECT_STREQ(url.data(), userVisibleString(literalURL(url.data()))); |
| } |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_NotSpoofed) |
| { |
| // Valid mixtures of Armenian and other scripts |
| EXPECT_STREQ("https://en.wikipedia.org/wiki/.\u0570\u0561\u0575", userVisibleString(literalURL("https://en.wikipedia.org/wiki/.\u0570\u0561\u0575"))); |
| EXPECT_STREQ("https://\u0573\u0574\u0578.\u0570\u0561\u0575", userVisibleString(literalURL("https://\u0573\u0574\u0578.\u0570\u0561\u0575"))); |
| EXPECT_STREQ("https://\u0573-1-\u0574\u0578.\u0570\u0561\u0575", userVisibleString(literalURL("https://\u0573-1-\u0574\u0578.\u0570\u0561\u0575"))); |
| EXPECT_STREQ("https://2\u0573_\u0574\u0578.\u0570\u0561\u0575", userVisibleString(literalURL("https://2\u0573_\u0574\u0578.\u0570\u0561\u0575"))); |
| EXPECT_STREQ("https://\u0573_\u0574\u05783.\u0570\u0561\u0575", userVisibleString(literalURL("https://\u0573_\u0574\u05783.\u0570\u0561\u0575"))); |
| EXPECT_STREQ("https://got\u0551\u0535\u0543.com", userVisibleString(literalURL("https://got\u0551\u0535\u0543.com"))); |
| EXPECT_STREQ("https://\u0551\u0535\u0543fans.net", userVisibleString(literalURL("https://\u0551\u0535\u0543fans.net"))); |
| EXPECT_STREQ("https://\u0551\u0535or\u0575\u0543.biz", userVisibleString(literalURL("https://\u0551\u0535or\u0575\u0543.biz"))); |
| EXPECT_STREQ("https://\u0551\u0535and!$^&*()-~+={}or<>,.?\u0575\u0543.biz", userVisibleString(literalURL("https://\u0551\u0535and!$^&*()-~+={}or<>,.?\u0575\u0543.biz"))); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_DivisionSign) |
| { |
| // Selected the division sign as an example of a non-ASCII character that is allowed in host names, since it's a lookalike character. |
| |
| // Code path similar to the one used when typing in a URL. |
| EXPECT_STREQ("http://site.xn--comothersite-kjb.org", originalDataAsString(WTF::URLWithUserTypedString(@"http://site.com\xC3\xB7othersite.org", nil))); |
| EXPECT_STREQ("http://site.com\xC3\xB7othersite.org", userVisibleString(WTF::URLWithUserTypedString(@"http://site.com\xC3\xB7othersite.org", nil))); |
| |
| // Code paths similar to the ones used for URLs found in webpages or HTTP responses. |
| EXPECT_STREQ("http://site.com\xC3\xB7othersite.org", originalDataAsString(literalURL("http://site.com\xC3\xB7othersite.org"))); |
| EXPECT_STREQ("http://site.com\xC3\xB7othersite.org", userVisibleString(literalURL("http://site.com\xC3\xB7othersite.org"))); |
| EXPECT_STREQ("http://site.com%C3%B7othersite.org", originalDataAsString(literalURL("http://site.com%C3%B7othersite.org"))); |
| EXPECT_STREQ("http://site.com\xC3\xB7othersite.org", userVisibleString(literalURL("http://site.com%C3%B7othersite.org"))); |
| |
| // Separate functions that deal with just a host name on its own. |
| EXPECT_STREQ("site.xn--comothersite-kjb.org", [WTF::encodeHostName(@"site.com\xC3\xB7othersite.org") UTF8String]); |
| EXPECT_STREQ("site.com\xC3\xB7othersite.org", [WTF::decodeHostName(@"site.com\xC3\xB7othersite.org") UTF8String]); |
| } |
| |
| TEST(WTF, URLExtras_Solidus) |
| { |
| // Selected full width solidus, which looks like the solidus, which is the character that indicates the end of the host name. |
| |
| // Code path similar to the one used when typing in a URL. |
| EXPECT_STREQ("http://site.com/othersite.org", originalDataAsString(WTF::URLWithUserTypedString(@"http://site.com\xEF\xBC\x8Fothersite.org", nil))); |
| EXPECT_STREQ("http://site.com/othersite.org", userVisibleString(WTF::URLWithUserTypedString(@"http://site.com\xEF\xBC\x8Fothersite.org", nil))); |
| |
| // Code paths similar to the ones used for URLs found in webpages or HTTP responses. |
| EXPECT_STREQ("http://site.com\xEF\xBC\x8Fothersite.org", originalDataAsString(literalURL("http://site.com\xEF\xBC\x8Fothersite.org"))); |
| EXPECT_STREQ("http://site.com%EF%BC%8Fothersite.org", userVisibleString(literalURL("http://site.com\xEF\xBC\x8Fothersite.org"))); |
| EXPECT_STREQ("http://site.com%EF%BC%8Fothersite.org", originalDataAsString(literalURL("http://site.com%EF%BC%8Fothersite.org"))); |
| EXPECT_STREQ("http://site.com%EF%BC%8Fothersite.org", userVisibleString(literalURL("http://site.com%EF%BC%8Fothersite.org"))); |
| |
| // Separate functions that deal with just a host name on its own. |
| EXPECT_STREQ("site.com/othersite.org", [WTF::encodeHostName(@"site.com\xEF\xBC\x8Fothersite.org") UTF8String]); |
| EXPECT_STREQ("site.com/othersite.org", [WTF::decodeHostName(@"site.com\xEF\xBC\x8Fothersite.org") UTF8String]); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_Space) |
| { |
| // Selected ideographic space, which looks like the ASCII space, which is not allowed unescaped. |
| |
| // Code path similar to the one used when typing in a URL. |
| EXPECT_STREQ("http://site.com%20othersite.org", originalDataAsString(WTF::URLWithUserTypedString(@"http://site.com\xE3\x80\x80othersite.org", nil))); |
| EXPECT_STREQ("http://site.com%20othersite.org", userVisibleString(WTF::URLWithUserTypedString(@"http://site.com\xE3\x80\x80othersite.org", nil))); |
| |
| // Code paths similar to the ones used for URLs found in webpages or HTTP responses. |
| EXPECT_STREQ("http://site.com\xE3\x80\x80othersite.org", originalDataAsString(literalURL("http://site.com\xE3\x80\x80othersite.org"))); |
| EXPECT_STREQ("http://site.com%E3%80%80othersite.org", userVisibleString(literalURL("http://site.com\xE3\x80\x80othersite.org"))); |
| EXPECT_STREQ("http://site.com%E3%80%80othersite.org", originalDataAsString(literalURL("http://site.com%E3%80%80othersite.org"))); |
| EXPECT_STREQ("http://site.com%E3%80%80othersite.org", userVisibleString(literalURL("http://site.com%E3%80%80othersite.org"))); |
| |
| // Separate functions that deal with just a host name on its own. |
| EXPECT_STREQ("site.com othersite.org", [WTF::encodeHostName(@"site.com\xE3\x80\x80othersite.org") UTF8String]); |
| EXPECT_STREQ("site.com\xE3\x80\x80othersite.org", [WTF::decodeHostName(@"site.com\xE3\x80\x80othersite.org") UTF8String]); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_File) |
| { |
| EXPECT_STREQ("file:///%E2%98%83", [[WTF::URLWithUserTypedString(@"file:///☃", nil) absoluteString] UTF8String]); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_ParsingError) |
| { |
| // Expect IDN failure. |
| NSURL *url = WTF::URLWithUserTypedString(@"http://.com", nil); |
| EXPECT_TRUE(url == nil); |
| |
| NSString *encodedHostName = WTF::encodeHostName(@"http://.com"); |
| EXPECT_TRUE(encodedHostName == nil); |
| } |
| |
| TEST(WTF_URLExtras, URLExtras_Nil) |
| { |
| NSURL *url1 = WTF::URLWithUserTypedString(nil, nil); |
| EXPECT_TRUE(url1 == nil); |
| |
| NSURL *url2 = WTF::URLWithUserTypedStringDeprecated(nil, nil); |
| EXPECT_TRUE(url2 == nil); |
| } |
| |
| } // namespace TestWebKitAPI |
| |