Simpletest Coverage - includes/filetransfer/filetransfer.inc

1 <?php
2 // $Id: filetransfer.inc,v 1.2 2009/07/01 13:44:53 dries Exp $
3
4 /*
5 * Base FileTransfer class.
6 *
7 * Classes extending this class perform file operations on directories not
8 * writeable by the webserver. To achieve this, the class should connect back
9 * to the server using some backend (for example FTP or SSH). To keep security,
10 * the password should always be asked from the user and never stored. For
11 * safety, all methods operate only inside a "jail", by default the Drupal root.
12 */
13 abstract class FileTransfer {
14 protected $username;
15 protected $password;
16 protected $hostname = 'localhost';
17 protected $port;
18
19 /**
20 * The constructer for the UpdateConnection class. This method is also called
21 * from the classes that extend this class and override this method.
22 */
23 function __construct($jail, $username, $password, $hostname, $port) {
24 $this->username = $username;
25 $this->password = $password;
26 $this->hostname = $hostname;
27 $this->port = $port;
28 $this->jail = $jail;
29 }
30
31 abstract static function factory($jail, $settings);
32
33 /**
34 * Implementation of the magic __get() method. If the connection isn't set to
35 * anything, this will call the connect() method and set it to and return the
36 * result; afterwards, the connection will be returned directly without using
37 * this method.
38 */
39 function __get($name) {
40 if ($name == 'connection') {
41 $this->connect();
42 return $this->connection;
43 }
44 }
45
46 /**
47 * Connect to the server.
48 */
49 abstract protected function connect();
50
51 /**
52 * Copies a directory.
53 *
54 * @param $source
55 * The source path.
56 * @param $destination
57 * The destination path.
58 */
59 public final function copyDirectory($source, $destination) {
60 $this->checkPath($destination);
61 $this->copyDirectoryJailed($source, $destination);
62 }
63
64 /**
65 * Creates a directory.
66 *
67 * @param $directory
68 * The directory to be created.
69 */
70 public final function createDirectory($directory) {
71 $this->checkPath($directory);
72 $this->createDirectoryJailed($directory);
73 }
74
75 /**
76 * Removes a directory.
77 *
78 * @param $directory
79 * The directory to be removed.
80 */
81 public final function removeDirectory($directory) {
82 $this->checkPath($directory);
83 $this->removeDirectoryJailed($directory);
84 }
85
86 /**
87 * Copies a file.
88 *
89 * @param $source
90 * The source file.
91 * @param $destination
92 * The destination file.
93 */
94 public final function copyFile($source, $destination) {
95 $this->checkPath($destination);
96 $this->copyFileJailed($source, $destination);
97 }
98
99 /**
100 * Removes a file.
101 *
102 * @param $destination
103 * The destination file to be removed.
104 */
105 public final function removeFile($destination) {
106 $this->checkPath($destination);
107 $this->removeFileJailed($destination);
108 }
109
110 /**
111 * Checks that the path is inside the jail and throws an exception if not.
112 *
113 * @param $path
114 * A path to check against the jail.
115 */
116 protected final function checkPath($path) {
117 if (realpath(substr($path, 0, strlen($this->jail))) !== $this->jail) {
118 throw new FileTransferException('@directory is outside of the @jail', NULL, array('@directory' => $path, '@jail' => $this->jail));
119 }
120 }
121
122 /**
123 * Copies a directory.
124 *
125 * We need a separate method to make the $destination is in the jail.
126 *
127 * @param $source
128 * The source path.
129 * @param $destination
130 * The destination path.
131 */
132 protected function copyDirectoryJailed($source, $destination) {
133 if ($this->isDirectory($destination)) {
134 $destination = $destination . '/' . basename($source);
135 }
136 $this->createDirectory($destination);
137 foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
138 $relative_path = substr($filename, strlen($source));
139 if ($file->isDir()) {
140 $this->createDirectory($destination . $relative_path);
141 }
142 else {
143 $this->copyFile($file->getPathName(), $destination . $relative_path);
144 }
145 }
146 }
147
148 /**
149 * Creates a directory.
150 *
151 * @param $directory
152 * The directory to be created.
153 */
154 abstract protected function createDirectoryJailed($directory);
155
156 /**
157 * Removes a directory.
158 *
159 * @param $directory
160 * The directory to be removed.
161 */
162 abstract protected function removeDirectoryJailed($directory);
163
164 /**
165 * Copies a file.
166 *
167 * @param $source
168 * The source file.
169 * @param $destination
170 * The destination file.
171 */
172 abstract protected function copyFileJailed($source, $destination);
173
174 /**
175 * Removes a file.
176 *
177 * @param $destination
178 * The destination file to be removed.
179 */
180 abstract protected function removeFileJailed($destination);
181
182 /**
183 * Checks if a particular path is a directory
184 *
185 * @param $path
186 * The path to check
187 *
188 * @return boolean
189 */
190 abstract public function isDirectory($path);
191 }
192
193 /**
194 * FileTransferException class.
195 */
196 class FileTransferException extends Exception {
197 public $arguments;
198
199 function __construct($message, $code = 0, $arguments = array()) {
200 parent::__construct($message, $code);
201 $this->arguments = $arguments;
202 }
203 }
204

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.