| [ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 /** 3 * VFS implementation for an FTP server. 4 * 5 * Required values for $params:<pre> 6 * 'username' The username with which to connect to the ftp server. 7 * 'password' The password with which to connect to the ftp server. 8 * 'hostspec' The ftp server to connect to.</pre> 9 * 10 * Optional values for $params:<pre> 11 * 'maplocalids' If true and the POSIX extension is available, the 12 * driver will map the user and group IDs returned from 13 * the FTP server with the local IDs from the local 14 * password file. This is useful only if the FTP server 15 * is running on localhost or if the local user/group 16 * IDs are identical to the remote FTP server. 17 * 'pasv' If true, connection will be set to passive mode. 18 * 'port' The port used to connect to the ftp server if other 19 * than 21. 20 * 'ssl' If true, and PHP had been compiled with OpenSSL 21 * support, TLS transport-level encryption will be 22 * negotiated with the server. 23 * 'timeout' If defined, use this value as the timeout for the 24 * server.</pre> 25 * 26 * $Horde: framework/VFS/VFS/ftp.php,v 1.75.4.21 2006/05/31 04:50:02 slusarz Exp $ 27 * 28 * Copyright 2002-2006 Chuck Hagenbuch <chuck@horde.org> 29 * Copyright 2002-2006 Michael Varghese <mike.varghese@ascellatech.com> 30 * 31 * See the enclosed file COPYING for license information (LGPL). If you did 32 * not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 33 * 34 * @author Chuck Hagenbuch <chuck@horde.org> 35 * @author Michael Varghese <mike.varghese@ascellatech.com> 36 * @package VFS 37 */ 38 class VFS_ftp extends VFS { 39 40 /** 41 * List of additional credentials required for this VFS backend. 42 * 43 * @var array 44 */ 45 var $_credentials = array('username', 'password'); 46 47 /** 48 * List of permissions and if they can be changed in this VFS backend. 49 * 50 * @var array 51 */ 52 var $_permissions = array( 53 'owner' => array('read' => true, 'write' => true, 'execute' => true), 54 'group' => array('read' => true, 'write' => true, 'execute' => true), 55 'all' => array('read' => true, 'write' => true, 'execute' => true)); 56 57 /** 58 * Variable holding the connection to the ftp server. 59 * 60 * @var resource 61 */ 62 var $_stream = false; 63 64 /** 65 * Local cache array for user IDs. 66 * 67 * @var array 68 */ 69 var $_uids = array(); 70 71 /** 72 * Local cache array for group IDs. 73 * 74 * @var array 75 */ 76 var $_gids = array(); 77 78 /** 79 * Returns the size of a file. 80 * 81 * @access public 82 * 83 * @param string $path The path of the file. 84 * @param string $name The filename. 85 * 86 * @return integer The size of the file in bytes or PEAR_Error on 87 * failure. 88 */ 89 function size($path, $name) 90 { 91 $conn = $this->_connect(); 92 if (is_a($conn, 'PEAR_Error')) { 93 return $conn; 94 } 95 96 if (($size = @ftp_size($this->_stream, $this->_getPath($path, $name))) === false) { 97 return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s\"."), $this->_getPath($path, $name))); 98 } 99 100 return $size; 101 } 102 103 /** 104 * Retrieves a file from the VFS. 105 * 106 * @param string $path The pathname to the file. 107 * @param string $name The filename to retrieve. 108 * 109 * @return string The file data. 110 */ 111 function read($path, $name) 112 { 113 $conn = $this->_connect(); 114 if (is_a($conn, 'PEAR_Error')) { 115 return $conn; 116 } 117 118 $tmpFile = $this->_getTempFile(); 119 $fetch = @ftp_get($this->_stream, $tmpFile, 120 $this->_getPath($path, $name), FTP_BINARY); 121 if ($fetch === false) { 122 return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name))); 123 } 124 125 $size = filesize($tmpFile); 126 if ($size === 0) { 127 return ''; 128 } 129 130 if (OS_WINDOWS) { 131 $mode = 'rb'; 132 } else { 133 $mode = 'r'; 134 } 135 136 if (function_exists('file_get_contents')) { 137 $data = file_get_contents($tmpFile); 138 } else { 139 $fp = fopen($tmpFile, $mode); 140 $data = fread($fp, $size); 141 fclose($fp); 142 } 143 unlink($tmpFile); 144 145 return $data; 146 } 147 148 /** 149 * Stores a file in the VFS. 150 * 151 * @param string $path The path to store the file in. 152 * @param string $name The filename to use. 153 * @param string $tmpFile The temporary file containing the data to 154 * be stored. 155 * @param boolean $autocreate Automatically create directories? 156 * 157 * @return mixed True on success or a PEAR_Error object on failure. 158 */ 159 function write($path, $name, $tmpFile, $autocreate = false) 160 { 161 $conn = $this->_connect(); 162 if (is_a($conn, 'PEAR_Error')) { 163 return $conn; 164 } 165 166 $res = $this->_checkQuotaWrite('file', $tmpFile); 167 if (is_a($res, 'PEAR_Error')) { 168 return $res; 169 } 170 171 if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) { 172 if ($autocreate) { 173 $result = $this->autocreatePath($path); 174 if (is_a($result, 'PEAR_Error')) { 175 return $result; 176 } 177 if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) { 178 return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); 179 } 180 } else { 181 return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); 182 } 183 } 184 185 return true; 186 } 187 188 /** 189 * Stores a file in the VFS from raw data. 190 * 191 * @param string $path The path to store the file in. 192 * @param string $name The filename to use. 193 * @param string $data The file data. 194 * @param boolean $autocreate Automatically create directories? 195 * 196 * @return mixed True on success or a PEAR_Error object on failure. 197 */ 198 function writeData($path, $name, $data, $autocreate = false) 199 { 200 $res = $this->_checkQuotaWrite('string', $data); 201 if (is_a($res, 'PEAR_Error')) { 202 return $res; 203 } 204 205 $tmpFile = $this->_getTempFile(); 206 $fp = fopen($tmpFile, 'wb'); 207 fwrite($fp, $data); 208 fclose($fp); 209 210 $result = $this->write($path, $name, $tmpFile, $autocreate); 211 unlink($tmpFile); 212 return $result; 213 } 214 215 /** 216 * Deletes a file from the VFS. 217 * 218 * @param string $path The path to delete the file from. 219 * @param string $name The filename to delete. 220 * 221 * @return mixed True on success or a PEAR_Error object on failure. 222 */ 223 function deleteFile($path, $name) 224 { 225 $res = $this->_checkQuotaDelete($path, $name); 226 if (is_a($res, 'PEAR_Error')) { 227 return $res; 228 } 229 230 $conn = $this->_connect(); 231 if (is_a($conn, 'PEAR_Error')) { 232 return $conn; 233 } 234 235 if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) { 236 return PEAR::raiseError(sprintf(_("Unable to delete VFS file \"%s\"."), $this->_getPath($path, $name))); 237 } 238 239 return true; 240 } 241 242 /** 243 * Checks if a given item is a folder. 244 * 245 * @param string $path The parent folder. 246 * @param string $name The item name. 247 * 248 * @return boolean True if it is a folder, false otherwise. 249 */ 250 function isFolder($path, $name) 251 { 252 $conn = $this->_connect(); 253 if (is_a($conn, 'PEAR_Error')) { 254 return $conn; 255 } 256 257 $result = false; 258 $olddir = $this->getCurrentDirectory(); 259 260 /* See if we can change to the given path. */ 261 if (@ftp_chdir($this->_stream, $this->_getPath($path, $name))) { 262 $result = true; 263 } 264 265 $this->_setPath($olddir); 266 267 return $result; 268 } 269 270 /** 271 * Deletes a folder from the VFS. 272 * 273 * @param string $path The parent folder. 274 * @param string $name The name of the folder to delete. 275 * @param boolean $recursive Force a recursive delete? 276 * 277 * @return mixed True on success or a PEAR_Error object on failure. 278 */ 279 function deleteFolder($path, $name, $recursive = false) 280 { 281 $conn = $this->_connect(); 282 if (is_a($conn, 'PEAR_Error')) { 283 return $conn; 284 } 285 286 $isDir = false; 287 $dirCheck = $this->listFolder($path); 288 foreach ($dirCheck as $file) { 289 if ($file['name'] == $name && $file['type'] == '**dir') { 290 $isDir = true; 291 break; 292 } 293 } 294 295 if ($isDir) { 296 $file_list = $this->listFolder($this->_getPath($path, $name)); 297 if (is_a($file_list, 'PEAR_Error')) { 298 return $file_list; 299 } 300 301 if (count($file_list) && !$recursive) { 302 return PEAR::raiseError(sprintf(_("Unable to delete \"%s\", the directory is not empty."), 303 $this->_getPath($path, $name))); 304 } 305 306 foreach ($file_list as $file) { 307 if ($file['type'] == '**dir') { 308 $result = $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); 309 } else { 310 $result = $this->deleteFile($this->_getPath($path, $name), $file['name']); 311 } 312 if (is_a($result, 'PEAR_Error')) { 313 return $result; 314 } 315 } 316 317 if (!@ftp_rmdir($this->_stream, $this->_getPath($path, $name))) { 318 return PEAR::raiseError(sprintf(_("Cannot remove directory \"%s\"."), $this->_getPath($path, $name))); 319 } 320 } else { 321 if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) { 322 return PEAR::raiseError(sprintf(_("Cannot delete file \"%s\"."), $this->_getPath($path, $name))); 323 } 324 } 325 326 return true; 327 } 328 329 /** 330 * Renames a file in the VFS. 331 * 332 * @param string $oldpath The old path to the file. 333 * @param string $oldname The old filename. 334 * @param string $newpath The new path of the file. 335 * @param string $newname The new filename. 336 * 337 * @return mixed True on success or a PEAR_Error object on failure. 338 */ 339 function rename($oldpath, $oldname, $newpath, $newname) 340 { 341 if (is_a($conn = $this->_connect(), 'PEAR_Error')) { 342 return $conn; 343 } 344 345 if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { 346 return $result; 347 } 348 349 if (!@ftp_rename($this->_stream, $this->_getPath($oldpath, $oldname), $this->_getPath($newpath, $newname))) { 350 return PEAR::raiseError(sprintf(_("Unable to rename VFS file \"%s\"."), $this->_getPath($oldpath, $oldname))); 351 } 352 353 return true; 354 } 355 356 /** 357 * Creates a folder on the VFS. 358 * 359 * @param string $path The parent folder. 360 * @param string $name The name of the new folder. 361 * 362 * @return mixed True on success or a PEAR_Error object on failure. 363 */ 364 function createFolder($path, $name) 365 { 366 $conn = $this->_connect(); 367 if (is_a($conn, 'PEAR_Error')) { 368 return $conn; 369 } 370 371 if (!@ftp_mkdir($this->_stream, $this->_getPath($path, $name))) { 372 return PEAR::raiseError(sprintf(_("Unable to create VFS directory \"%s\"."), $this->_getPath($path, $name))); 373 } 374 375 return true; 376 } 377 378 /** 379 * Changes permissions for an item on the VFS. 380 * 381 * @param string $path The parent folder of the item. 382 * @param string $name The name of the item. 383 * @param string $permission The permission to set. 384 * 385 * @return mixed True on success or a PEAR_Error object on failure. 386 */ 387 function changePermissions($path, $name, $permission) 388 { 389 $conn = $this->_connect(); 390 if (is_a($conn, 'PEAR_Error')) { 391 return $conn; 392 } 393 394 if (!@ftp_site($this->_stream, 'CHMOD ' . $permission . ' ' . $this->_getPath($path, $name))) { 395 return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file \"%s\"."), $this->_getPath($path, $name))); 396 } 397 398 return true; 399 } 400 401 /** 402 * Returns an an unsorted file list of the specified directory. 403 * 404 * @param string $path The path of the directory. 405 * @param mixed $filter String/hash to filter file/dirname on. 406 * @param boolean $dotfiles Show dotfiles? 407 * @param boolean $dironly Show only directories? 408 * 409 * @return array File list on success or PEAR_Error on failure. 410 */ 411 function _listFolder($path = '', $filter = null, $dotfiles = true, 412 $dironly = false) 413 { 414 $conn = $this->_connect(); 415 if (is_a($conn, 'PEAR_Error')) { 416 return $conn; 417 } 418 419 $files = array(); 420 $type = VFS::strtolower(@ftp_systype($this->_stream)); 421 if ($type == 'unknown') { 422 // Go with unix-style listings by default. 423 $type = 'unix'; 424 } elseif (strpos($type, 'win') !== false) { 425 $type = 'win'; 426 } elseif (strpos($type, 'netware') !== false) { 427 $type = 'netware'; 428 } 429 430 $olddir = $this->getCurrentDirectory(); 431 if (!empty($path)) { 432 $res = $this->_setPath($path); 433 if (is_a($res, 'PEAR_Error')) { 434 return $res; 435 } 436 } 437 438 if ($type == 'unix') { 439 // If we don't want dotfiles, We can save work here by not 440 // doing an ls -a and then not doing the check later (by 441 // setting $dotfiles to true, the if is short-circuited). 442 if ($dotfiles) { 443 $list = ftp_rawlist($this->_stream, '-al'); 444 $dotfiles = true; 445 } else { 446 $list = ftp_rawlist($this->_stream, '-l'); 447 } 448 } else { 449 $list = ftp_rawlist($this->_stream, ''); 450 } 451 452 if (!is_array($list)) { 453 if (isset($olddir)) { 454 $res = $this->_setPath($olddir); 455 if (is_a($res, 'PEAR_Error')) { 456 return $res; 457 } 458 } 459 return array(); 460 } 461 462 /* If 'maplocalids' is set, check for the POSIX extension. */ 463 $mapids = false; 464 if (!empty($this->_params['maplocalids']) && 465 extension_loaded('posix')) { 466 $mapids = true; 467 } 468 469 $currtime = time(); 470 471 foreach ($list as $line) { 472 $file = array(); 473 $item = preg_split('/\s+/', $line); 474 if ($type == 'unix' || ($type == 'win' && !preg_match('|\d\d-\d\d-\d\d|', $item[0]))) { 475 if (count($item) < 8 || substr($line, 0, 5) == 'total') { 476 continue; 477 } 478 $file['perms'] = $item[0]; 479 if ($mapids) { 480 if (!isset($this->_uids[$item[2]])) { 481 $entry = posix_getpwuid($item[2]); 482 $this->_uids[$item[2]] = (empty($entry)) ? $item[2] : $entry['name']; 483 } 484 $file['owner'] = $this->_uids[$item[2]]; 485 if (!isset($this->_uids[$item[3]])) { 486 $entry = posix_getgrgid($item[3]); 487 $this->_uids[$item[3]] = (empty($entry)) ? $item[3] : $entry['name']; 488 } 489 $file['group'] = $this->_uids[$item[3]]; 490 491 } else { 492 $file['owner'] = $item[2]; 493 $file['group'] = $item[3]; 494 } 495 $file['name'] = substr($line, strpos($line, sprintf("%s %2s %5s", $item[5], $item[6], $item[7])) + 13); 496 497 // Filter out '.' and '..' entries. 498 if (preg_match('/^\.\.?\/?$/', $file['name'])) { 499 continue; 500 } 501 502 // Filter out dotfiles if they aren't wanted. 503 if (!$dotfiles && substr($file['name'], 0, 1) == '.') { 504 continue; 505 } 506 507 $p1 = substr($file['perms'], 0, 1); 508 if ($p1 === 'l') { 509 $file['link'] = substr($file['name'], strpos($file['name'], '->') + 3); 510 $file['name'] = substr($file['name'], 0, strpos($file['name'], '->') - 1); 511 $file['type'] = '**sym'; 512 513 if ($this->isFolder('', $file['link'])) { 514 $file['linktype'] = '**dir'; 515 } else { 516 $parts = explode('/', $file['link']); 517 $name = explode('.', array_pop($parts)); 518 if (count($name) == 1 || ($name[0] === '' && count($name) == 2)) { 519 $file['linktype'] = '**none'; 520 } else { 521 $file['linktype'] = VFS::strtolower(array_pop($name)); 522 } 523 } 524 } elseif ($p1 === 'd') { 525 $file['type'] = '**dir'; 526 } else { 527 $name = explode('.', $file['name']); 528 if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) { 529 $file['type'] = '**none'; 530 } else { 531 $file['type'] = VFS::strtolower($name[count($name) - 1]); 532 } 533 } 534 if ($file['type'] == '**dir') { 535 $file['size'] = -1; 536 } else { 537 $file['size'] = $item[4]; 538 } 539 if (strpos($item[7], ':') !== false) { 540 $file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . date('Y', $currtime)); 541 // If the ftp server reports a file modification date more 542 // less than one day in the future, don't try to subtract 543 // a year from the date. There is no way to know, for 544 // example, if the VFS server and the ftp server reside 545 // in different timezones. We should simply report to the 546 // user what the FTP server is returning. 547 if ($file['date'] > ($currtime + 86400)) { 548 $file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . (date('Y', $currtime) - 1)); 549 } 550 } else { 551 $file['date'] = strtotime('00:00:00' . $item[5] . ' ' . $item[6] . ' ' . $item[7]); 552 } 553 } elseif ($type == 'netware') { 554 $file = Array(); 555 $file['perms'] = $item[1]; 556 $file['owner'] = $item[2]; 557 if ($item[0] == 'd') { 558 $file['type'] = '**dir'; 559 } else { 560 $file['type'] = '**none'; 561 } 562 $file['size'] = $item[3]; 563 $file['name'] = $item[7]; 564 $index = 8; 565 while ($index < count($item)) { 566 $file['name'] .= ' ' . $item[$index]; 567 $index++; 568 } 569 } else { 570 /* Handle Windows FTP servers returning DOS-style file 571 * listings. */ 572 $file['perms'] = ''; 573 $file['owner'] = ''; 574 $file['group'] = ''; 575 $file['name'] = $item[3]; 576 $index = 4; 577 while ($index < count($item)) { 578 $file['name'] .= ' ' . $item[$index]; 579 $index++; 580 } 581 $file['date'] = strtotime($item[0] . ' ' . $item[1]); 582 if ($item[2] == '<DIR>') { 583 $file['type'] = '**dir'; 584 $file['size'] = -1; 585 } else { 586 $file['size'] = $item[2]; 587 $name = explode('.', $file['name']); 588 if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) { 589 $file['type'] = '**none'; 590 } else { 591 $file['type'] = VFS::strtolower($name[count($name) - 1]); 592 } 593 } 594 } 595 596 // Filtering. 597 if ($this->_filterMatch($filter, $file['name'])) { 598 unset($file); 599 continue; 600 } 601 if ($dironly && $file['type'] !== '**dir') { 602 unset($file); 603 continue; 604 } 605 606 $files[$file['name']] = $file; 607 unset($file); 608 } 609 610 if (isset($olddir)) { 611 $res = $this->_setPath($olddir); 612 if (is_a($res, 'PEAR_Error')) { 613 return $res; 614 } 615 } 616 return $files; 617 } 618 619 /** 620 * Returns a sorted list of folders in the specified directory. 621 * 622 * @param string $path The path of the directory to get the 623 * directory list for. 624 * @param mixed $filter Hash of items to filter based on folderlist. 625 * @param boolean $dotfolders Include dotfolders? 626 * 627 * @return mixed Folder list on success or a PEAR_Error object on failure. 628 */ 629 function listFolders($path = '', $filter = null, $dotfolders = true) 630 { 631 $conn = $this->_connect(); 632 if (is_a($conn, 'PEAR_Error')) { 633 return $conn; 634 } 635 636 $folders = array(); 637 $folder = array(); 638 639 $folderList = $this->listFolder($path, null, $dotfolders, true); 640 if (is_a($folderList, 'PEAR_Error')) { 641 return $folderList; 642 } 643 644 $folder['val'] = $this->_parentDir($path); 645 $folder['abbrev'] = '..'; 646 $folder['label'] = '..'; 647 648 $folders[$folder['val']] = $folder; 649 650 foreach ($folderList as $files) { 651 $folder['val'] = $this->_getPath($path, $files['name']); 652 $folder['abbrev'] = $files['name']; 653 $folder['label'] = $folder['val']; 654 655 $folders[$folder['val']] = $folder; 656 } 657 658 ksort($folders); 659 return $folders; 660 } 661 662 /** 663 * Copies a file through the backend. 664 * 665 * @param string $path The path of the original file. 666 * @param string $name The name of the original file. 667 * @param string $dest The name of the destination directory. 668 * 669 * @return mixed True on success or a PEAR_Error object on failure. 670 */ 671 function copy($path, $name, $dest) 672 { 673 $orig = $this->_getPath($path, $name); 674 if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { 675 return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); 676 } 677 678 $conn = $this->_connect(); 679 if (is_a($conn, 'PEAR_Error')) { 680 return $conn; 681 } 682 683 $fileCheck = $this->listFolder($dest, null, true); 684 if (is_a($fileCheck, 'PEAR_Error')) { 685 return $fileCheck; 686 } 687 foreach ($fileCheck as $file) { 688 if ($file['name'] == $name) { 689 return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); 690 } 691 } 692 693 $isDir = false; 694 $dirCheck = $this->listFolder($path, null, false); 695 if (is_a($dirCheck, 'PEAR_Error')) { 696 return $dirCheck; 697 } 698 foreach ($dirCheck as $file) { 699 if ($file['name'] == $name && $file['type'] == '**dir') { 700 $isDir = true; 701 break; 702 } 703 } 704 705 if ($isDir) { 706 $result = $this->createFolder($dest, $name); 707 708 if (is_a($result, 'PEAR_Error')) { 709 return $result; 710 } 711 712 $file_list = $this->listFolder($this->_getPath($path, $name)); 713 foreach ($file_list as $file) { 714 $result = $this->copy($this->_getPath($path, $name), $file['name'], $this->_getPath($dest, $name)); 715 if (is_a($result, 'PEAR_Error')) { 716 return $result; 717 } 718 } 719 } else { 720 $tmpFile = $this->_getTempFile(); 721 $fetch = @ftp_get($this->_stream, $tmpFile, $orig, FTP_BINARY); 722 if (!$fetch) { 723 unlink($tmpFile); 724 return PEAR::raiseError(sprintf(_("Failed to copy from \"%s\"."), $orig)); 725 } 726 727 if (!@ftp_put($this->_stream, $this->_getPath($dest, $name), $tmpFile, FTP_BINARY)) { 728 unlink($tmpFile); 729 return PEAR::raiseError(sprintf(_("Failed to copy to \"%s\"."), $this->_getPath($dest, $name))); 730 } 731 732 unlink($tmpFile); 733 } 734 735 return true; 736 } 737 738 /** 739 * Moves a file through the backend. 740 * 741 * @param string $path The path of the original file. 742 * @param string $name The name of the original file. 743 * @param string $dest The destination file name. 744 * 745 * @return mixed True on success or a PEAR_Error object on failure. 746 */ 747 function move($path, $name, $dest) 748 { 749 $orig = $this->_getPath($path, $name); 750 if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { 751 return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); 752 } 753 754 $conn = $this->_connect(); 755 if (is_a($conn, 'PEAR_Error')) { 756 return $conn; 757 } 758 759 $fileCheck = $this->listFolder($dest, null, true); 760 foreach ($fileCheck as $file) { 761 if ($file['name'] == $name) { 762 return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); 763 } 764 } 765 766 if (!@ftp_rename($this->_stream, $orig, $this->_getPath($dest, $name))) { 767 return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), $this->_getPath($dest, $name))); 768 } 769 770 return true; 771 } 772 773 /** 774 * Returns the current working directory on the FTP server. 775 * 776 * @return string The current working directory. 777 */ 778 function getCurrentDirectory() 779 { 780 if (is_a($connected = $this->_connect(), 'PEAR_Error')) { 781 return $connected; 782 } 783 return ftp_pwd($this->_stream); 784 } 785 786 /** 787 * Changes the current directory on the server. 788 * 789 * @access private 790 * 791 * @param string $path The path to change to. 792 * 793 * @return mixed True on success, or a PEAR_Error on failure. 794 */ 795 function _setPath($path) 796 { 797 if (!@ftp_chdir($this->_stream, $path)) { 798 return PEAR::raiseError(sprintf(_("Unable to change to %s."), $path)); 799 } 800 return true; 801 } 802 803 /** 804 * Returns the full path of an item. 805 * 806 * @access private 807 * 808 * @param string $path The directory of the item. 809 * @param string $name The name of the item. 810 * 811 * @return mixed Full path to the file when $path is not empty and just 812 * $name when not set. 813 */ 814 function _getPath($path, $name) 815 { 816 if ($path !== '') { 817 return ($path . '/' . $name); 818 } 819 return ($name); 820 } 821 822 /** 823 * Returns the parent directory of the specified path. 824 * 825 * @access private 826 * 827 * @param string $path The path to get the parent of. 828 * 829 * @return string The parent directory (string) on success or a PEAR_Error 830 * object on failure. 831 */ 832 function _parentDir($path) 833 { 834 $conn = $this->_connect(); 835 if (is_a($conn, 'PEAR_Error')) { 836 return $conn; 837 } 838 839 $olddir = $this->getCurrentDirectory(); 840 @ftp_cdup($this->_stream); 841 842 $parent = $this->getCurrentDirectory(); 843 $this->_setPath($olddir); 844 845 if (!$parent) { 846 return PEAR::raiseError(_("Unable to determine current directory.")); 847 } 848 849 return $parent; 850 } 851 852 /** 853 * Attempts to open a connection to the FTP server. 854 * 855 * @access private 856 * 857 * @return mixed True on success or a PEAR_Error object on failure. 858 */ 859 function _connect() 860 { 861 if ($this->_stream === false) { 862 if (!extension_loaded('ftp')) { 863 return PEAR::raiseError(_("The FTP extension is not available.")); 864 } 865 866 if (!is_array($this->_params)) { 867 return PEAR::raiseError(_("No configuration information specified for FTP VFS.")); 868 } 869 870 $required = array('hostspec', 'username', 'password'); 871 foreach ($required as $val) { 872 if (!isset($this->_params[$val])) { 873 return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val)); 874 } 875 } 876 877 /* Connect to the ftp server using the supplied parameters. */ 878 if (!empty($this->_params['ssl'])) { 879 if (function_exists('ftp_ssl_connect')) { 880 $this->_stream = @ftp_ssl_connect($this->_params['hostspec'], $this->_params['port']); 881 } else { 882 return PEAR::raiseError(_("Unable to connect with SSL.")); 883 } 884 } else { 885 $this->_stream = @ftp_connect($this->_params['hostspec'], $this->_params['port']); 886 } 887 if (!$this->_stream) { 888 return PEAR::raiseError(_("Connection to FTP server failed.")); 889 } 890 891 $connected = @ftp_login($this->_stream, $this->_params['username'], $this->_params['password']); 892 if (!$connected) { 893 $this->_disconnect(); 894 return PEAR::raiseError(_("Authentication to FTP server failed.")); 895 } 896 897 if (!empty($this->_params['pasv'])) { 898 @ftp_pasv($this->_stream, true); 899 } 900 901 if (!empty($this->_params['timeout'])) { 902 ftp_set_option($this->_stream, FTP_TIMEOUT_SEC, $this->_params['timeout']); 903 } 904 } 905 906 return true; 907 } 908 909 /** 910 * Disconnects from the FTP server and cleans up the connection. 911 * 912 * @access private 913 */ 914 function _disconnect() 915 { 916 @ftp_quit($this->_stream); 917 $this->_stream = false; 918 } 919 920 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |