destinations.ftp.inc
12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
<?php
/**
* @file
* Functions to handle the FTP backup destination.
*/
/**
* A destination for sending database backups to an FTP server.
*
* @ingroup backup_migrate_destinations
*/
class backup_migrate_destination_ftp extends backup_migrate_destination_remote {
var $supported_ops = array('scheduled backup', 'manual backup', 'restore', 'list files', 'configure', 'delete');
var $ftp = NULL;
/**
* Save to the ftp destination.
*/
function _save_file($file, $settings) {
$ftp = $this->ftp_object();
if (drupal_ftp_file_to_ftp($file->filepath(), $file->filename(), '.', $ftp)) {
return $file;
}
return FALSE;
}
/**
* Load from the ftp destination.
*/
function load_file($file_id) {
backup_migrate_include('files');
$file = new backup_file(array('filename' => $file_id));
$this->ftp_object();
if (drupal_ftp_ftp_to_file($file->filepath(), $file_id, '.', $this->ftp)) {
return $file;
}
return FALSE;
}
/**
* Delete from the ftp destination.
*/
function _delete_file($file_id) {
$this->ftp_object();
drupal_ftp_delete_file($file_id, $this->ftp);
}
function _list_files() {
backup_migrate_include('files');
$files = array();
$this->ftp_object();
$ftp_files = drupal_ftp_file_list('.', $this->ftp);
foreach ($ftp_files as $file) {
$files[$file['filename']] = new backup_file($file);
}
return $files;
}
/**
* Get the form for the settings for this filter.
*/
function edit_form() {
$form = parent::edit_form();
$form['scheme']['#type'] = 'value';
$form['scheme']['#value'] = 'ftp';
$form['port'] = array(
"#type" => "textfield",
"#title" => t("Port"),
"#default_value" => @$this->dest_url['port'] ? $this->dest_url['port'] : '21',
"#weight" => 15,
);
$form['pasv'] = array(
'#type' => 'checkbox',
'#title' => t('Use PASV transfers'),
'#default_value' => $this->get_pasv(),
'#weight' => 50,
);
return $form;
}
function set_pasv($value) {
$this->settings['pasv'] = (bool)$value;
}
function get_pasv() {
return isset($this->settings['pasv']) ? $this->settings['pasv'] : FALSE;
}
function ftp_object() {
if (!$this->ftp) {
$this->dest_url['port'] = empty($this->dest_url['port']) ? '21' : $this->dest_url['port'];
$this->dest_url['pasv'] = $this->get_pasv();
$this->ftp = drupal_ftp_ftp_object($this->dest_url['host'], $this->dest_url['port'], $this->dest_url['user'], $this->dest_url['pass'], $this->dest_url['path'], $this->dest_url['pasv']);
}
return $this->ftp;
}
}
// The FTP code below was taken from the ftp module by Aaron Winborn.
// Inspired by http://www.devarticles.com/c/a/PHP/My-FTP-Wrapper-Class-for-PHP/
// It's been drupalized, however, and most of the bugs from that example have been fixed.
// - winborn 2007-06-22 - 2007-06-28
define('DRUPAL_FTP_FT_DIRECTORY', 0);
define('DRUPAL_FTP_FT_FILE', 1);
/**
* creates a new ftp object. if any elements of ftp_map are missing, they'll be filled with the server defaults.
*/
function drupal_ftp_ftp_object($server, $port, $user, $pass, $dir, $pasv) {
$ftp = new stdClass();
$ftp->__server = $server;
$ftp->__port = $port;
$ftp->__user = $user;
$ftp->__password = $pass;
$ftp->__directory = $dir;
$ftp->__pasv = $pasv;
return $ftp;
}
/**
* The drupal_ftp_connect function
* This function connects to an FTP server and attempts to change into the directory specified by
* the fourth parameter, $directory.
*/
function drupal_ftp_connect(&$ftp) {
if (is_NULL($ftp)) {
$ftp = drupal_ftp_ftp_object();
}
if (empty($ftp->__conn) && !drupal_ftp_connected($ftp)) {
// Attempt to connect to the remote server
$ftp->__conn = @ftp_connect($ftp->__server, $ftp->__port);
if (!$ftp->__conn) {
_backup_migrate_message('FTP Error: Couldn\'t connect to server @server', array('@server' => $ftp->__server), 'error');
return FALSE;
}
// Attempt to login to the remote server
$ftp->__login = @ftp_login($ftp->__conn, $ftp->__user, $ftp->__password);
if (!$ftp->__login) {
_backup_migrate_message('FTP Error: Couldn\'t login as user @ftp_user to @server', array('@ftp_user' => $ftp->__user, '@server' => $ftp->__server), 'error');
return FALSE;
}
// Attempt to change into the working directory
$chdir = @ftp_chdir($ftp->__conn, $ftp->__directory);
if (!$chdir) {
_backup_migrate_message('FTP Error: Couldn\'t change into the @directory directory', array('@directory' => $ftp->__directory), 'error');
return FALSE;
}
// Set PASV - if needed
if ($ftp->__pasv) {
$pasv = @ftp_pasv($ftp->__conn, TRUE);
if (!$pasv) {
_backup_migrate_message('FTP Error: Couldn\'t set PASV mode', array(), 'error');
return FALSE;
}
}
}
// Everything worked OK, return TRUE
return TRUE;
}
/**
* The drupal_ftp_connected function
* This function queries the FTP server with the ftp_systype command to check if the connection is still alive.
* It returns TRUE on success or FALSE on disconnection.
*/
function drupal_ftp_connected(&$ftp) {
// Attempt to call the ftp_systype to see if the connect
// to the FTP server is still alive and kicking
if (is_NULL($ftp)) {
$ftp = drupal_ftp_ftp_object();
return FALSE;
}
if (!@ftp_systype($ftp->__conn)) {
// The connection is dead
return FALSE;
}
else {
// The connection is still alive
return TRUE;
}
}
/**
* This function tries to retrieve the contents of a file from the FTP server.
* Firstly it changes into the $directory directory, and then attempts to download the file $filename.
* The file is saved locally and its contents are returned to the caller of the function.
*/
function drupal_ftp_ftp_to_file($file, $filename, $directory, &$ftp) {
// Change into the remote directory and retrieve the content
// of a file. Once retrieve, return this value to the caller
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
// We are now connected, so let's retrieve the file contents.
// Firstly, we change into the directory
$chdir = @ftp_chdir($ftp->__conn, $directory);
if (!$chdir) {
_backup_migrate_message('FTP Error: Couldn\'t change into directory: @directory', array('@directory' => $directory), 'error');
return FALSE;
}
// We have changed into the directory, let's attempt to get the file
$fp = @fopen($file, 'wb');
$get_file = @ftp_fget($ftp->__conn, $fp, $filename, FTP_BINARY);
fclose($fp);
$fp = NULL;
if (!$get_file) {
_backup_migrate_message('FTP Error: Unable to download file: @filename from @directory', array('@filename' => $filename, '@directory' => $directory), 'error');
return FALSE;
}
return TRUE;
}
/**
* Send a file to an FTP server.
*/
function drupal_ftp_file_to_ftp($file, $ftp_filename, $ftp_directory, &$ftp) {
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
if ($source = drupal_realpath($file)) {
// Now we can try to write to the remote file
$complete_filename = $ftp_directory .'/'. $ftp_filename;
$put_file = @ftp_put($ftp->__conn, $complete_filename, $source, FTP_BINARY);
if (!$put_file) {
_backup_migrate_message('FTP Error: Couldn\'t write to @complete_filename when trying to save file on the ftp server.', array('@complete_filename' => $complete_filename), 'error');
return FALSE;
}
// Everything worked OK
return TRUE;
}
else {
_backup_migrate_message('FTP Error: Couldn\'t find @file.', array('@file'), 'error');
return FALSE;
}
}
/**
* The drupal_ftp_change_directory Function
* This function simply changes into the $directory folder on the FTP server.
* If a connection or permission error occurs then _backup_migrate_message() will contain the error message.
*/
function drupal_ftp_change_directory($directory, &$ftp) {
// Switch to another directory on the web server. If we don't
// have permissions then an error will occur
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
// Try and change into another directory
$chdir = ftp_chdir($ftp->__conn, $directory);
if (!$chdir) {
_backup_migrate_message('FTP Error: Couldn\'t change into directory: @directory', array('@directory', $directory), 'error');
return FALSE;
}
else {
// Changing directories worked OK
return TRUE;
}
}
/**
* The drupal_ftp_file_list Function
* This function will change into the $directory folder and get a list of files and directories contained in that folder.
* This function still needs a lot of work, but should work in most cases.
*/
function drupal_ftp_file_list($directory, &$ftp) {
// This function will attempt to change into the specified
// directory and retrieve a list of files as an associative
// array. This list will include file name, size and date last modified
$file_array = array();
// Can we switch to the desired directory?
if (!drupal_ftp_change_directory($directory, $ftp)) {
return FALSE;
}
// We are in the directory, let's retrieve a list of files
// This is slower than parsing the raw return values, but it is faster.
$file_list = ftp_nlist($ftp->__conn, $directory);
// Save the list of files
if (@is_array($file_list)) {
// Interate through the array
foreach ($file_list as $file) {
$file_array[] = array(
'filename' => $file,
'filesize' => ftp_size($ftp->__conn, $directory ."/". $file),
'filetime' => ftp_mdtm($ftp->__conn, $directory ."/". $file),
);
}
}
sort($file_array);
return $file_array;
}
/**
* The drupal_ftp_create_directory Function
* This function tries to make a new directory called $folder_name on the FTP server.
* If it can create the folder, then the folder is given appropriate rights with the CHMOD command.
*/
function drupal_ftp_create_directory($folder_name, &$ftp) {
// Makes a new folder on the web server via FTP
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
$create_result = @ftp_mkdir($ftp->__conn, $folder_name);
if ($create_result == TRUE) {
// Can we change the files permissions?
$exec_result = @ftp_site($ftp->__conn, 'chmod 0777 '. $folder_name .'/');
if ($exec_result == TRUE) {
return TRUE;
}
else {
_backup_migrate_message('FTP Error: Couldn\'t set owner permissions on @folder.', array('@folder', $folder_name), 'error');
return FALSE;
}
}
else {
_backup_migrate_message('FTP Error: Couldn\'t create new folder @folder.', array('@folder', $folder_name), 'error');
return FALSE;
}
}
/**
* The drupal_ftp_delete_file Function
* This function attempts to delete a file called $filename from the FTP server.
*/
function drupal_ftp_delete_file($filename, &$ftp) {
// Remove the specified file from the FTP server
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
$delete_result = @ftp_delete($ftp->__conn, $filename);
if ($delete_result == TRUE) {
// The file/folder was renamed successfully
return TRUE;
}
else {
// Couldn't delete the selected file
_backup_migrate_message('FTP Error: Couldn\'t delete the selected file: @filename', array('@filename' => $filename), 'error');
return FALSE;
}
}
/**
* The drupal_ftp_delete_folder Function
* This function was one of the hardest to write. It recursively deletes all files and folders from a directory called $folder_name.
*/
function drupal_ftp_delete_folder($folder_name, &$ftp) {
if (!@drupal_ftp_connect($ftp)) {
return FALSE;
}
@ftp_chdir($ftp->__conn, $folder_name);
$location = @ftp_pwd($ftp->__conn);
$directories = array();
$files = array();
$dir_counter = 0;
$file_counter = 0;
$content = @ftp_nlist($ftp->__conn, ".");
for ($i = 0; $i < sizeof($content); $i++) {
// If we can change into this then it's a directory.
// If not, it's a file
if ($content[$i] != "." && $content[$i] != "..") {
if (@ftp_chdir($ftp->__conn, $content[$i])) {
// We have a directory
$directories[] = $content[$i];
$dir_counter++;
@ftp_cdup($ftp->__conn);
}
else {
// We have a file
$files[] = $content[$i];
$file_counter++;
}
}
}
for ($j = 0; $j < $file_counter; $j++) {
@ftp_delete($ftp->__conn, $files[$j]);
}
for ($j = 0; $j < $dir_counter; $j++) {
if ($directories[$j] != "." OR $directories[$j] != "..") {
$location = ftp_pwd($ftp->__conn);
drupal_ftp_delete_folder($directories[$j], $ftp);
@ftp_cdup ($ftp->__conn);
@ftp_rmdir($ftp->__conn, $directories[$j]);
}
}
// Lastly, we change into the directory that we want to delete and see
// if we can cdup. If we can, we delete it.
@ftp_chdir($ftp->__conn, $folder_name);
@ftp_cdup($ftp->__conn);
@ftp_rmdir($ftp->__conn, $folder_name);
// Did the recursive folder/file deletion work?
return TRUE;
}