|
1 <?php |
|
2 |
|
3 |
|
4 class FileTranferTest extends DrupalWebTestCase { |
|
5 protected $hostname = 'localhost'; |
|
6 protected $username = 'drupal'; |
|
7 protected $password = 'password'; |
|
8 protected $port = '42'; |
|
9 |
|
10 public static function getInfo() { |
|
11 return array( |
|
12 'name' => 'FileTransfer unit tests', |
|
13 'description' => 'Test that the jail is respected and that protocols using recursive file move operations work.', |
|
14 'group' => 'System' |
|
15 ); |
|
16 } |
|
17 |
|
18 function setUp() { |
|
19 parent::setUp(); |
|
20 $this->testConnection = TestFileTransfer::factory(DRUPAL_ROOT, array('hostname' => $this->hostname, 'username' => $this->username, 'password' => $this->password, 'port' => $this->port)); |
|
21 } |
|
22 |
|
23 function _getFakeModuleFiles() { |
|
24 $files = array( |
|
25 'fake.module', |
|
26 'fake.info', |
|
27 'theme' => array( |
|
28 'fake.tpl.php' |
|
29 ), |
|
30 'inc' => array( |
|
31 'fake.inc' |
|
32 ) |
|
33 ); |
|
34 return $files; |
|
35 } |
|
36 |
|
37 function _buildFakeModule() { |
|
38 $location = 'temporary://fake'; |
|
39 if (is_dir($location)) { |
|
40 $ret = 0; |
|
41 $output = array(); |
|
42 exec('rm -Rf ' . escapeshellarg($location), $output, $ret); |
|
43 if ($ret != 0) { |
|
44 throw new Exception('Error removing fake module directory.'); |
|
45 } |
|
46 } |
|
47 |
|
48 $files = $this->_getFakeModuleFiles(); |
|
49 $this->_writeDirectory($location, $files); |
|
50 return $location; |
|
51 } |
|
52 |
|
53 function _writeDirectory($base, $files = array()) { |
|
54 mkdir($base); |
|
55 foreach ($files as $key => $file) { |
|
56 if (is_array($file)) { |
|
57 $this->_writeDirectory($base . DIRECTORY_SEPARATOR . $key, $file); |
|
58 } |
|
59 else { |
|
60 //just write the filename into the file |
|
61 file_put_contents($base . DIRECTORY_SEPARATOR . $file, $file); |
|
62 } |
|
63 } |
|
64 } |
|
65 |
|
66 function testJail() { |
|
67 $source = $this->_buildFakeModule(); |
|
68 |
|
69 // This convoluted piece of code is here because our testing framework does |
|
70 // not support expecting exceptions. |
|
71 $gotit = FALSE; |
|
72 try { |
|
73 $this->testConnection->copyDirectory($source, '/tmp'); |
|
74 } |
|
75 catch (FileTransferException $e) { |
|
76 $gotit = TRUE; |
|
77 } |
|
78 $this->assertTrue($gotit, 'Was not able to copy a directory outside of the jailed area.'); |
|
79 |
|
80 $gotit = TRUE; |
|
81 try { |
|
82 $this->testConnection->copyDirectory($source, DRUPAL_ROOT . '/'. variable_get('file_public_path', conf_path() . '/files')); |
|
83 } |
|
84 catch (FileTransferException $e) { |
|
85 $gotit = FALSE; |
|
86 } |
|
87 $this->assertTrue($gotit, 'Was able to copy a directory inside of the jailed area'); |
|
88 } |
|
89 } |
|
90 |
|
91 /** |
|
92 * Mock FileTransfer object for test case. |
|
93 */ |
|
94 class TestFileTransfer extends FileTransfer { |
|
95 protected $host = NULL; |
|
96 protected $username = NULL; |
|
97 protected $password = NULL; |
|
98 protected $port = NULL; |
|
99 |
|
100 /** |
|
101 * This is for testing the CopyRecursive logic. |
|
102 */ |
|
103 public $shouldIsDirectoryReturnTrue = FALSE; |
|
104 |
|
105 function __construct($jail, $username, $password, $hostname = 'localhost', $port = 9999) { |
|
106 parent::__construct($jail, $username, $password, $hostname, $port); |
|
107 } |
|
108 |
|
109 static function factory($jail, $settings) { |
|
110 return new TestFileTransfer($jail, $settings['username'], $settings['password'], $settings['hostname'], $settings['port']); |
|
111 } |
|
112 |
|
113 function connect() { |
|
114 $parts = explode(':', $this->hostname); |
|
115 $port = (count($parts) == 2) ? $parts[1] : $this->port; |
|
116 $this->connection = new MockTestConnection(); |
|
117 $this->connection->connectionString = 'test://' . urlencode($this->username) . ':' . urlencode($this->password) . "@$this->host:$this->port/"; |
|
118 } |
|
119 |
|
120 function copyFileJailed($source, $destination) { |
|
121 $this->connection->run("copyFile $source $destination"); |
|
122 } |
|
123 |
|
124 protected function removeDirectoryJailed($directory) { |
|
125 $this->connection->run("rmdir $directory"); |
|
126 } |
|
127 |
|
128 function createDirectoryJailed($directory) { |
|
129 $this->connection->run("mkdir $directory"); |
|
130 } |
|
131 |
|
132 function removeFileJailed($destination) { |
|
133 if (!ftp_delete($this->connection, $item)) { |
|
134 throw new FileTransferException('Unable to remove to file @file.', NULL, array('@file' => $item)); |
|
135 } |
|
136 } |
|
137 |
|
138 function isDirectory($path) { |
|
139 return $this->shouldIsDirectoryReturnTrue; |
|
140 } |
|
141 |
|
142 function isFile($path) { |
|
143 return FALSE; |
|
144 } |
|
145 |
|
146 function chmodJailed($path, $mode, $recursive) { |
|
147 return; |
|
148 } |
|
149 } |
|
150 |
|
151 /** |
|
152 * Mock connection object for test case. |
|
153 */ |
|
154 class MockTestConnection { |
|
155 |
|
156 var $commandsRun = array(); |
|
157 var $connectionString; |
|
158 |
|
159 function run($cmd) { |
|
160 $this->commandsRun[] = $cmd; |
|
161 } |
|
162 |
|
163 function flushCommands() { |
|
164 $out = $this->commandsRun; |
|
165 $this->commandsRun = array(); |
|
166 return $out; |
|
167 } |
|
168 } |