EscUrl.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <?php
  2. /**
  3. * @group formatting
  4. */
  5. class Tests_Formatting_EscUrl extends WP_UnitTestCase {
  6. /**
  7. * @ticket 23605
  8. */
  9. function test_spaces() {
  10. $this->assertSame( 'http://example.com/Mr%20WordPress', esc_url( 'http://example.com/Mr WordPress' ) );
  11. $this->assertSame( 'http://example.com/Mr%20WordPress', esc_url( 'http://example.com/Mr%20WordPress' ) );
  12. $this->assertSame( 'http://example.com/Mr%20%20WordPress', esc_url( 'http://example.com/Mr%20%20WordPress' ) );
  13. $this->assertSame( 'http://example.com/Mr+WordPress', esc_url( 'http://example.com/Mr+WordPress' ) );
  14. $this->assertSame( 'http://example.com/Mr+WordPress', esc_url( ' http://example.com/Mr+WordPress' ) );
  15. $this->assertSame( 'http://example.com/?foo=one%20two%20three&#038;bar=four', esc_url( 'http://example.com/?foo=one two three&bar=four' ) );
  16. $this->assertSame( 'http://example.com/?foo=one%20two%20three&#038;bar=four', esc_url( 'http://example.com/?foo=one%20two%20three&bar=four' ) );
  17. }
  18. function test_bad_characters() {
  19. $this->assertSame( 'http://example.com/watchthelinefeedgo', esc_url( 'http://example.com/watchthelinefeed%0Ago' ) );
  20. $this->assertSame( 'http://example.com/watchthelinefeedgo', esc_url( 'http://example.com/watchthelinefeed%0ago' ) );
  21. $this->assertSame( 'http://example.com/watchthecarriagereturngo', esc_url( 'http://example.com/watchthecarriagereturn%0Dgo' ) );
  22. $this->assertSame( 'http://example.com/watchthecarriagereturngo', esc_url( 'http://example.com/watchthecarriagereturn%0dgo' ) );
  23. // Nesting checks.
  24. $this->assertSame( 'http://example.com/watchthecarriagereturngo', esc_url( 'http://example.com/watchthecarriagereturn%0%0ddgo' ) );
  25. $this->assertSame( 'http://example.com/watchthecarriagereturngo', esc_url( 'http://example.com/watchthecarriagereturn%0%0DDgo' ) );
  26. $this->assertSame( 'http://example.com/', esc_url( 'http://example.com/%0%0%0DAD' ) );
  27. $this->assertSame( 'http://example.com/', esc_url( 'http://example.com/%0%0%0ADA' ) );
  28. $this->assertSame( 'http://example.com/', esc_url( 'http://example.com/%0%0%0DAd' ) );
  29. $this->assertSame( 'http://example.com/', esc_url( 'http://example.com/%0%0%0ADa' ) );
  30. }
  31. function test_relative() {
  32. $this->assertSame( '/example.php', esc_url( '/example.php' ) );
  33. $this->assertSame( 'example.php', esc_url( 'example.php' ) );
  34. $this->assertSame( '#fragment', esc_url( '#fragment' ) );
  35. $this->assertSame( '?foo=bar', esc_url( '?foo=bar' ) );
  36. }
  37. function test_all_url_parts() {
  38. $url = 'https://user:pass@host.example.com:1234/path;p=1?query=2&r[]=3#fragment';
  39. $this->assertSame(
  40. array(
  41. 'scheme' => 'https',
  42. 'host' => 'host.example.com',
  43. 'port' => 1234,
  44. 'user' => 'user',
  45. 'pass' => 'pass',
  46. 'path' => '/path;p=1',
  47. 'query' => 'query=2&r[]=3',
  48. 'fragment' => 'fragment',
  49. ),
  50. parse_url( $url )
  51. );
  52. $this->assertSame( 'https://user:pass@host.example.com:1234/path;p=1?query=2&r%5B%5D=3#fragment', esc_url_raw( $url ) );
  53. $this->assertSame( 'https://user:pass@host.example.com:1234/path;p=1?query=2&#038;r%5B%5D=3#fragment', esc_url( $url ) );
  54. }
  55. function test_bare() {
  56. $this->assertSame( 'http://example.com?foo', esc_url( 'example.com?foo' ) );
  57. $this->assertSame( 'http://example.com', esc_url( 'example.com' ) );
  58. $this->assertSame( 'http://localhost', esc_url( 'localhost' ) );
  59. $this->assertSame( 'http://example.com/foo', esc_url( 'example.com/foo' ) );
  60. $this->assertSame( 'http://баба.org/баба', esc_url( 'баба.org/баба' ) );
  61. }
  62. function test_encoding() {
  63. $this->assertSame( 'http://example.com?foo=1&bar=2', esc_url_raw( 'http://example.com?foo=1&bar=2' ) );
  64. $this->assertSame( 'http://example.com?foo=1&amp;bar=2', esc_url_raw( 'http://example.com?foo=1&amp;bar=2' ) );
  65. $this->assertSame( 'http://example.com?foo=1&#038;bar=2', esc_url_raw( 'http://example.com?foo=1&#038;bar=2' ) );
  66. $this->assertSame( 'http://example.com?foo=1&#038;bar=2', esc_url( 'http://example.com?foo=1&bar=2' ) );
  67. $this->assertSame( 'http://example.com?foo=1&#038;bar=2', esc_url( 'http://example.com?foo=1&amp;bar=2' ) );
  68. $this->assertSame( 'http://example.com?foo=1&#038;bar=2', esc_url( 'http://example.com?foo=1&#038;bar=2' ) );
  69. $param = urlencode( 'http://example.com/?one=1&two=2' );
  70. $this->assertSame( "http://example.com?url={$param}", esc_url( "http://example.com?url={$param}" ) );
  71. }
  72. function test_protocol() {
  73. $this->assertSame( 'http://example.com', esc_url( 'http://example.com' ) );
  74. $this->assertSame( '', esc_url( 'nasty://example.com/' ) );
  75. $this->assertSame(
  76. '',
  77. esc_url(
  78. 'example.com',
  79. array(
  80. 'https',
  81. )
  82. )
  83. );
  84. $this->assertSame(
  85. '',
  86. esc_url(
  87. 'http://example.com',
  88. array(
  89. 'https',
  90. )
  91. )
  92. );
  93. $this->assertSame(
  94. 'https://example.com',
  95. esc_url(
  96. 'https://example.com',
  97. array(
  98. 'http',
  99. 'https',
  100. )
  101. )
  102. );
  103. foreach ( wp_allowed_protocols() as $scheme ) {
  104. $this->assertSame( "{$scheme}://example.com", esc_url( "{$scheme}://example.com" ), $scheme );
  105. $this->assertSame(
  106. "{$scheme}://example.com",
  107. esc_url(
  108. "{$scheme}://example.com",
  109. array(
  110. $scheme,
  111. )
  112. ),
  113. $scheme
  114. );
  115. }
  116. $this->assertTrue( ! in_array( 'data', wp_allowed_protocols(), true ) );
  117. $this->assertSame( '', esc_url( 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D' ) );
  118. $this->assertTrue( ! in_array( 'foo', wp_allowed_protocols(), true ) );
  119. $this->assertSame(
  120. 'foo://example.com',
  121. esc_url(
  122. 'foo://example.com',
  123. array(
  124. 'foo',
  125. )
  126. )
  127. );
  128. }
  129. /**
  130. * @ticket 23187
  131. */
  132. function test_protocol_case() {
  133. $this->assertSame( 'http://example.com', esc_url( 'HTTP://example.com' ) );
  134. $this->assertSame( 'http://example.com', esc_url( 'Http://example.com' ) );
  135. }
  136. function test_display_extras() {
  137. $this->assertSame( 'http://example.com/&#039;quoted&#039;', esc_url( 'http://example.com/\'quoted\'' ) );
  138. $this->assertSame( 'http://example.com/\'quoted\'', esc_url( 'http://example.com/\'quoted\'', null, 'notdisplay' ) );
  139. }
  140. function test_non_ascii() {
  141. $this->assertSame( 'http://example.org/баба', esc_url( 'http://example.org/баба' ) );
  142. $this->assertSame( 'http://баба.org/баба', esc_url( 'http://баба.org/баба' ) );
  143. $this->assertSame( 'http://müller.com/', esc_url( 'http://müller.com/' ) );
  144. }
  145. function test_feed() {
  146. $this->assertSame( '', esc_url( 'feed:javascript:alert(1)' ) );
  147. $this->assertSame( '', esc_url( 'feed:javascript:feed:alert(1)' ) );
  148. $this->assertSame( '', esc_url( 'feed:feed:javascript:alert(1)' ) );
  149. $this->assertSame( 'feed:feed:alert(1)', esc_url( 'feed:feed:alert(1)' ) );
  150. $this->assertSame( 'feed:http://wordpress.org/feed/', esc_url( 'feed:http://wordpress.org/feed/' ) );
  151. }
  152. /**
  153. * @ticket 16859
  154. */
  155. function test_square_brackets() {
  156. $this->assertSame( '/example.php?one%5B%5D=two', esc_url( '/example.php?one[]=two' ) );
  157. $this->assertSame( '?foo%5Bbar%5D=baz', esc_url( '?foo[bar]=baz' ) );
  158. $this->assertSame( '//example.com/?foo%5Bbar%5D=baz', esc_url( '//example.com/?foo[bar]=baz' ) );
  159. $this->assertSame( 'http://example.com/?foo%5Bbar%5D=baz', esc_url( 'example.com/?foo[bar]=baz' ) );
  160. $this->assertSame( 'http://localhost?foo%5Bbar%5D=baz', esc_url( 'localhost?foo[bar]=baz' ) );
  161. $this->assertSame( 'http://example.com/?foo%5Bbar%5D=baz', esc_url( 'http://example.com/?foo[bar]=baz' ) );
  162. $this->assertSame( 'http://example.com/?foo%5Bbar%5D=baz', esc_url( 'http://example.com/?foo%5Bbar%5D=baz' ) );
  163. $this->assertSame( 'http://example.com/?baz=bar&#038;foo%5Bbar%5D=baz', esc_url( 'http://example.com/?baz=bar&foo[bar]=baz' ) );
  164. $this->assertSame( 'http://example.com/?baz=bar&#038;foo%5Bbar%5D=baz', esc_url( 'http://example.com/?baz=bar&#038;foo%5Bbar%5D=baz' ) );
  165. }
  166. /**
  167. * Courtesy of http://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding
  168. */
  169. function test_reserved_characters() {
  170. $url = "http://example.com/:@-._~!$&'()*+,=;:@-._~!$&'()*+,=:@-._~!$&'()*+,==?/?:@-._~!$%27()*+,;=/?:@-._~!$%27()*+,;==#/?:@-._~!$&'()*+,;=";
  171. $this->assertSame( $url, esc_url_raw( $url ) );
  172. }
  173. /**
  174. * @ticket 21974
  175. */
  176. function test_protocol_relative_with_colon() {
  177. $this->assertSame( '//example.com/foo?foo=abc:def', esc_url( '//example.com/foo?foo=abc:def' ) );
  178. }
  179. /**
  180. * @ticket 31632
  181. */
  182. function test_mailto_with_newline() {
  183. $body = <<<EOT
  184. Hi there,
  185. I thought you might want to sign up for this newsletter
  186. EOT;
  187. $body = str_replace( "\r\n", "\n", $body );
  188. $email_link = 'mailto:?body=' . rawurlencode( $body );
  189. $email_link = esc_url( $email_link );
  190. $this->assertSame( 'mailto:?body=Hi%20there%2C%0A%0AI%20thought%20you%20might%20want%20to%20sign%20up%20for%20this%20newsletter', $email_link );
  191. }
  192. /**
  193. * @ticket 31632
  194. */
  195. function test_mailto_in_http_url_with_newline() {
  196. $body = <<<EOT
  197. Hi there,
  198. I thought you might want to sign up for this newsletter
  199. EOT;
  200. $body = str_replace( "\r\n", "\n", $body );
  201. $email_link = 'http://example.com/mailto:?body=' . rawurlencode( $body );
  202. $email_link = esc_url( $email_link );
  203. $this->assertSame( 'http://example.com/mailto:?body=Hi%20there%2CI%20thought%20you%20might%20want%20to%20sign%20up%20for%20this%20newsletter', $email_link );
  204. }
  205. /**
  206. * @ticket 23605
  207. */
  208. function test_mailto_with_spaces() {
  209. $body = 'Hi there, I thought you might want to sign up for this newsletter';
  210. $email_link = 'mailto:?body=' . $body;
  211. $email_link = esc_url( $email_link );
  212. $this->assertSame( 'mailto:?body=Hi%20there,%20I%20thought%20you%20might%20want%20to%20sign%20up%20for%20this%20newsletter', $email_link );
  213. }
  214. /**
  215. * @ticket 28015
  216. */
  217. function test_invalid_charaters() {
  218. $this->assertEmpty( esc_url_raw( '"^<>{}`' ) );
  219. }
  220. /**
  221. * @ticket 34202
  222. */
  223. function test_ipv6_hosts() {
  224. $this->assertSame( '//[::127.0.0.1]', esc_url( '//[::127.0.0.1]' ) );
  225. $this->assertSame( 'http://[::FFFF::127.0.0.1]', esc_url( 'http://[::FFFF::127.0.0.1]' ) );
  226. $this->assertSame( 'http://[::127.0.0.1]', esc_url( 'http://[::127.0.0.1]' ) );
  227. $this->assertSame( 'http://[::DEAD:BEEF:DEAD:BEEF:DEAD:BEEF:DEAD:BEEF]', esc_url( 'http://[::DEAD:BEEF:DEAD:BEEF:DEAD:BEEF:DEAD:BEEF]' ) );
  228. // IPv6 with square brackets in the query? Why not.
  229. $this->assertSame( '//[::FFFF::127.0.0.1]/?foo%5Bbar%5D=baz', esc_url( '//[::FFFF::127.0.0.1]/?foo[bar]=baz' ) );
  230. $this->assertSame( 'http://[::FFFF::127.0.0.1]/?foo%5Bbar%5D=baz', esc_url( 'http://[::FFFF::127.0.0.1]/?foo[bar]=baz' ) );
  231. }
  232. }