file.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. /**
  3. * @group file
  4. */
  5. class Tests_File extends WP_UnitTestCase {
  6. function setUp() {
  7. parent::setUp();
  8. $this->dir = untrailingslashit( get_temp_dir() );
  9. $this->badchars = '"\'[]*&?$';
  10. }
  11. /**
  12. * @group plugins
  13. * @group themes
  14. */
  15. function test_get_file_data() {
  16. $theme_headers = array(
  17. 'Name' => 'Theme Name',
  18. 'ThemeURI' => 'Theme URI',
  19. 'Description' => 'Description',
  20. 'Version' => 'Version',
  21. 'Author' => 'Author',
  22. 'AuthorURI' => 'Author URI',
  23. );
  24. $actual = get_file_data( DIR_TESTDATA . '/themedir1/default/style.css', $theme_headers );
  25. $expected = array(
  26. 'Name' => 'WordPress Default',
  27. 'ThemeURI' => 'http://wordpress.org/',
  28. 'Description' => 'The default WordPress theme based on the famous <a href="http://binarybonsai.com/kubrick/">Kubrick</a>.',
  29. 'Version' => '1.6',
  30. 'Author' => 'Michael Heilemann',
  31. 'AuthorURI' => 'http://binarybonsai.com/',
  32. );
  33. foreach ( $actual as $header => $value ) {
  34. $this->assertSame( $expected[ $header ], $value, $header );
  35. }
  36. }
  37. /**
  38. * @group plugins
  39. * @group themes
  40. */
  41. function test_get_file_data_cr_line_endings() {
  42. $headers = array(
  43. 'SomeHeader' => 'Some Header',
  44. 'Description' => 'Description',
  45. 'Author' => 'Author',
  46. );
  47. $actual = get_file_data( DIR_TESTDATA . '/formatting/cr-line-endings-file-header.php', $headers );
  48. $expected = array(
  49. 'SomeHeader' => 'Some header value!',
  50. 'Description' => 'This file is using CR line endings for a testcase.',
  51. 'Author' => 'A Very Old Mac',
  52. );
  53. foreach ( $actual as $header => $value ) {
  54. $this->assertSame( $expected[ $header ], $value, $header );
  55. }
  56. }
  57. function is_unique_writable_file( $path, $filename ) {
  58. $fullpath = $path . DIRECTORY_SEPARATOR . $filename;
  59. $fp = fopen( $fullpath, 'x' );
  60. // File already exists?
  61. if ( ! $fp ) {
  62. return false;
  63. }
  64. // Write some random contents.
  65. $c = rand_str();
  66. fwrite( $fp, $c );
  67. fclose( $fp );
  68. if ( file_get_contents( $fullpath ) === $c ) {
  69. $result = true;
  70. } else {
  71. $result = false;
  72. }
  73. return $result;
  74. }
  75. function test_unique_filename_is_valid() {
  76. // Make sure it produces a valid, writable, unique filename.
  77. $filename = wp_unique_filename( $this->dir, __FUNCTION__ . '.txt' );
  78. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename ) );
  79. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename );
  80. }
  81. function test_unique_filename_is_unique() {
  82. // Make sure it produces two unique filenames.
  83. $name = __FUNCTION__;
  84. $filename1 = wp_unique_filename( $this->dir, $name . '.txt' );
  85. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename1 ) );
  86. $filename2 = wp_unique_filename( $this->dir, $name . '.txt' );
  87. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename2 ) );
  88. // The two should be different.
  89. $this->assertNotEquals( $filename1, $filename2 );
  90. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename1 );
  91. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename2 );
  92. }
  93. function test_unique_filename_is_sanitized() {
  94. $name = __FUNCTION__;
  95. $filename = wp_unique_filename( $this->dir, $name . $this->badchars . '.txt' );
  96. // Make sure the bad characters were all stripped out.
  97. $this->assertSame( $name . '.txt', $filename );
  98. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename ) );
  99. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename );
  100. }
  101. function test_unique_filename_with_slashes() {
  102. $name = __FUNCTION__;
  103. // "foo/foo.txt"
  104. $filename = wp_unique_filename( $this->dir, $name . '/' . $name . '.txt' );
  105. // The slash should be removed, i.e. "foofoo.txt".
  106. $this->assertSame( $name . $name . '.txt', $filename );
  107. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename ) );
  108. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename );
  109. }
  110. function test_unique_filename_multiple_ext() {
  111. $name = __FUNCTION__;
  112. $filename = wp_unique_filename( $this->dir, $name . '.php.txt' );
  113. // "foo.php.txt" becomes "foo.php_.txt".
  114. $this->assertSame( $name . '.php_.txt', $filename );
  115. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename ) );
  116. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename );
  117. }
  118. function test_unique_filename_no_ext() {
  119. $name = __FUNCTION__;
  120. $filename = wp_unique_filename( $this->dir, $name );
  121. $this->assertSame( $name, $filename );
  122. $this->assertTrue( $this->is_unique_writable_file( $this->dir, $filename ) );
  123. unlink( $this->dir . DIRECTORY_SEPARATOR . $filename );
  124. }
  125. /**
  126. * @dataProvider data_wp_tempnam_filenames
  127. */
  128. function test_wp_tempnam( $case ) {
  129. $file = wp_tempnam( $case );
  130. unlink( $file );
  131. $this->assertNotEmpty( basename( basename( $file, '.tmp' ), '.zip' ) );
  132. }
  133. function data_wp_tempnam_filenames() {
  134. return array(
  135. array( '0.zip' ),
  136. array( '0.1.2.3.zip' ),
  137. array( 'filename.zip' ),
  138. array( 'directory/0.zip' ),
  139. array( 'directory/filename.zip' ),
  140. array( 'directory/0/0.zip' ),
  141. );
  142. }
  143. /**
  144. * @ticket 47186
  145. */
  146. function test_file_signature_functions_as_expected() {
  147. $file = wp_tempnam();
  148. file_put_contents( $file, 'WordPress' );
  149. // The signature of 'WordPress' after SHA384 hashing, for verification against the key within self::filter_trust_plus85Tq_key().
  150. $expected_signature = 'PmNv0b1ziwJAsVhjdpjd4+PQZidZWSlBm5b+GbbwE9m9HVKDFhEyvyRTHkRYOLypB8P2YvbW7CoOMZqGh8mEAA==';
  151. add_filter( 'wp_trusted_keys', array( $this, 'filter_trust_plus85Tq_key' ) );
  152. // Measure how long the call takes.
  153. $timer_start = microtime( 1 );
  154. $verify = verify_file_signature( $file, $expected_signature, 'WordPress' );
  155. $timer_end = microtime( 1 );
  156. $time_taken = ( $timer_end - $timer_start );
  157. unlink( $file );
  158. remove_filter( 'wp_trusted_keys', array( $this, 'filter_trust_plus85Tq_key' ) );
  159. // verify_file_signature() should intentionally never take more than 10s to run.
  160. $this->assertLessThan( 10, $time_taken, 'verify_file_signature() took longer than 10 seconds.' );
  161. // Check to see if the system parameters prevent signature verifications.
  162. if ( is_wp_error( $verify ) && 'signature_verification_unsupported' === $verify->get_error_code() ) {
  163. $this->markTestSkipped( 'This system does not support Signature Verification.' );
  164. }
  165. $this->assertNotWPError( $verify );
  166. $this->assertTrue( $verify );
  167. }
  168. /**
  169. * @ticket 47186
  170. */
  171. function test_file_signature_expected_failure() {
  172. $file = wp_tempnam();
  173. file_put_contents( $file, 'WordPress' );
  174. // Test an invalid signature.
  175. $expected_signature = base64_encode( str_repeat( 'A', SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES ) );
  176. $verify = verify_file_signature( $file, $expected_signature, 'WordPress' );
  177. unlink( $file );
  178. if ( is_wp_error( $verify ) && 'signature_verification_unsupported' === $verify->get_error_code() ) {
  179. $this->markTestSkipped( 'This system does not support Signature Verification.' );
  180. }
  181. $this->assertWPError( $verify );
  182. $this->assertSame( 'signature_verification_failed', $verify->get_error_code() );
  183. }
  184. function filter_trust_plus85Tq_key( $keys ) {
  185. // A static once-off key used to verify verify_file_signature() works as expected.
  186. $keys[] = '+85TqMhxQVAYVW4BSCVkJQvZH4q7z8I9lePbvngvf7A=';
  187. return $keys;
  188. }
  189. }