10 defined(
'JPATH_PLATFORM') or die;
26 define(
'CRLF',
"\r\n");
28 if (!defined(
"FTP_AUTOASCII"))
30 define(
"FTP_AUTOASCII", -1);
32 if (!defined(
"FTP_BINARY"))
34 define(
"FTP_BINARY", 1);
36 if (!defined(
"FTP_ASCII"))
38 define(
"FTP_ASCII", 0);
41 if (!defined(
'FTP_NATIVE'))
43 define(
'FTP_NATIVE', (function_exists(
'ftp_connect')) ? 1 : 0);
142 if (!isset($options[
'type']))
144 $options[
'type'] = FTP_BINARY;
151 jimport(
'joomla.utilities.buffer');
167 if (is_resource($this->_conn))
192 public static function getInstance($host =
'127.0.0.1', $port =
'21', array $options = array(), $user = null, $pass = null)
194 $signature = $user .
':' . $pass .
'@' . $host .
":" . $port;
197 if (!isset(self::$instances[$signature]) || !is_object(self::$instances[$signature]))
199 self::$instances[$signature] =
new static($options);
203 self::$instances[$signature]->setOptions($options);
209 $return = self::$instances[$signature]->connect($host, $port);
211 if ($return && $user !== null && $pass !== null)
213 self::$instances[$signature]->login($user, $pass);
217 return self::$instances[$signature];
231 if (isset($options[
'type']))
233 $this->_type = $options[
'type'];
235 if (isset($options[
'timeout']))
237 $this->_timeout = $options[
'timeout'];
252 public function connect($host =
'127.0.0.1', $port = 21)
258 if (is_resource($this->_conn))
266 $this->_conn = @ftp_connect($host, $port, $this->_timeout);
268 if ($this->_conn ===
false)
275 ftp_set_option($this->_conn, FTP_TIMEOUT_SEC, $this->_timeout);
281 $this->_conn = @ fsockopen($host, $port, $errno, $err, $this->_timeout);
291 socket_set_timeout($this->_conn, $this->_timeout, 0);
313 return is_resource($this->_conn);
326 public function login($user =
'anonymous', $pass =
'jftp@joomla.org')
331 if (@ftp_login($this->_conn, $user, $pass) ===
false)
341 if (!$this->
_putCmd(
'USER ' . $user, array(331, 503)))
349 if ($this->_responseCode == 503)
355 if (!$this->
_putCmd(
'PASS ' . $pass, 230))
377 @ftp_close($this->_conn);
383 @fwrite($this->_conn,
"QUIT\r\n");
384 @fclose($this->_conn);
401 if (($ret = @ftp_pwd($this->_conn)) ===
false)
410 $match = array(null);
413 if (!$this->
_putCmd(
'PWD', 257))
421 preg_match(
'/"[^"\r\n]*"/', $this->_response, $match);
424 return preg_replace(
"/\"/",
"", $match[0]);
439 if (($ret = @ftp_systype($this->_conn)) ===
false)
449 if (!$this->
_putCmd(
'SYST', 215))
459 if (strpos(strtoupper($ret),
'MAC') !==
false)
463 elseif (strpos(strtoupper($ret),
'WIN') !==
false)
490 if (@ftp_chdir($this->_conn, $path) ===
false)
500 if (!$this->
_putCmd(
'CWD ' . $path, 250))
524 if (@ftp_site($this->_conn,
'REIN') ===
false)
534 if (!$this->
_putCmd(
'REIN', 220))
559 if (@ftp_rename($this->_conn, $from, $to) ===
false)
569 if (!$this->
_putCmd(
'RNFR ' . $from, 350))
577 if (!$this->
_putCmd(
'RNTO ' . $to, 250))
608 $mode = decoct($mode);
614 if (@ftp_site($this->_conn,
'CHMOD ' . $mode .
' ' . $path) ===
false)
626 if (!$this->
_putCmd(
'SITE CHMOD ' . $mode .
' ' . $path, array(200, 250)))
646 public function delete($path)
651 if (@ftp_delete($this->_conn, $path) ===
false)
653 if (@ftp_rmdir($this->_conn, $path) ===
false)
664 if (!$this->
_putCmd(
'DELE ' . $path, 250))
666 if (!$this->
_putCmd(
'RMD ' . $path, 250))
690 if (@ftp_mkdir($this->_conn, $path) ===
false)
700 if (!$this->
_putCmd(
'MKD ' . $path, 257))
723 if (@ftp_site($this->_conn,
'REST ' . $point) ===
false)
733 if (!$this->
_putCmd(
'REST ' . $point, 350))
758 if (@ftp_pasv($this->_conn,
true) ===
false)
765 $buffer = fopen(
'buffer://tmp',
'r');
767 if (@ftp_fput($this->_conn, $path, $buffer, FTP_ASCII) ===
false)
787 if (!$this->
_putCmd(
'STOR ' . $path, array(150, 125)))
789 @ fclose($this->_dataconn);
796 fclose($this->_dataconn);
818 public function read($remote, &$buffer)
827 if (@ftp_pasv($this->_conn,
true) ===
false)
834 $tmp = fopen(
'buffer://tmp',
'br+');
836 if (@ftp_fget($this->_conn, $tmp, $remote, $mode) ===
false)
849 $buffer .= fread($tmp, 8192);
866 if (!$this->
_putCmd(
'RETR ' . $remote, array(150, 125)))
868 @ fclose($this->_dataconn);
877 while (!feof($this->_dataconn))
879 $buffer .= fread($this->_dataconn, 4096);
883 fclose($this->_dataconn);
886 if ($mode == FTP_ASCII)
895 $buffer = preg_replace(
"/" . CRLF .
"/", $this->_lineEndings[
$os], $buffer);
918 public function get($local, $remote)
927 if (@ftp_pasv($this->_conn,
true) ===
false)
934 if (@ftp_get($this->_conn, $local, $remote, $mode) ===
false)
946 $fp = fopen($local,
"wb");
963 if (!$this->
_putCmd(
'RETR ' . $remote, array(150, 125)))
965 @ fclose($this->_dataconn);
972 while (!feof($this->_dataconn))
974 $buffer = fread($this->_dataconn, 4096);
975 fwrite($fp, $buffer, 4096);
979 fclose($this->_dataconn);
1002 public function store($local, $remote = null)
1006 if ($remote == null)
1008 $remote = basename($local);
1018 if (@ftp_pasv($this->_conn,
true) ===
false)
1025 if (@ftp_put($this->_conn, $remote, $local, $mode) ===
false)
1034 $this->
_mode($mode);
1037 if (@ file_exists($local))
1039 $fp = fopen($local,
"rb");
1065 if (!$this->
_putCmd(
'STOR ' . $remote, array(150, 125)))
1068 @ fclose($this->_dataconn);
1077 $line = fread($fp, 4096);
1081 if (($result = @ fwrite($this->_dataconn, $line)) ===
false)
1087 $line = substr($line, $result);
1089 while ($line !=
"");
1093 fclose($this->_dataconn);
1124 if (@ftp_pasv($this->_conn,
true) ===
false)
1131 $tmp = fopen(
'buffer://tmp',
'br+');
1132 fwrite($tmp, $buffer);
1135 if (@ftp_fput($this->_conn, $remote, $tmp, $mode) ===
false)
1148 $this->
_mode($mode);
1159 if (!$this->
_putCmd(
'STOR ' . $remote, array(150, 125)))
1162 @ fclose($this->_dataconn);
1170 if (($result = @ fwrite($this->_dataconn, $buffer)) ===
false)
1176 $buffer = substr($buffer, $result);
1178 while ($buffer !=
"");
1181 fclose($this->_dataconn);
1214 if (@ftp_pasv($this->_conn,
true) ===
false)
1221 if (($list = @ftp_nlist($this->_conn, $path)) ===
false)
1224 if ($this->
listDetails($path,
'files') === array())
1232 $list = preg_replace(
'#^' . preg_quote($path,
'#') .
'[/\\\\]?#',
'', $list);
1234 if ($keys = array_merge(array_keys($list,
'.'), array_keys($list,
'..')))
1236 foreach ($keys as $key)
1249 $path =
' ' . $path;
1260 if (!$this->
_putCmd(
'NLST' . $path, array(150, 125)))
1262 @ fclose($this->_dataconn);
1265 if ($this->
listDetails($path,
'files') === array())
1275 while (!feof($this->_dataconn))
1277 $data .= fread($this->_dataconn, 4096);
1279 fclose($this->_dataconn);
1289 $data = preg_split(
"/[" . CRLF .
"]+/", $data, -1, PREG_SPLIT_NO_EMPTY);
1290 $data = preg_replace(
'#^' . preg_quote(substr($path, 1),
'#') .
'[/\\\\]?#',
'', $data);
1292 if ($keys = array_merge(array_keys($data,
'.'), array_keys($data,
'..')))
1294 foreach ($keys as $key)
1314 $dir_list = array();
1326 if (@ftp_pasv($this->_conn,
true) ===
false)
1333 if (($contents = @ftp_rawlist($this->_conn, $path)) ===
false)
1355 $path =
' ' . $path;
1359 if (!$this->
_putCmd(($recurse ==
true) ?
'LIST -R' :
'LIST' . $path, array(150, 125)))
1362 @ fclose($this->_dataconn);
1368 while (!feof($this->_dataconn))
1370 $data .= fread($this->_dataconn, 4096);
1372 fclose($this->_dataconn);
1382 $contents = explode(CRLF, $data);
1392 if (empty($contents[0]))
1398 if (strtolower(substr($contents[0], 0, 6)) ==
'total ')
1400 array_shift($contents);
1402 if (!isset($contents[0]) || empty($contents[0]))
1410 'UNIX' =>
'#([-dl][rwxstST-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*)'
1411 .
' ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{1,2}:[0-9]{2})|[0-9]{4}) (.+)#',
1412 'MAC' =>
'#([-dl][rwxstST-]+).* ?([0-9 ]*)?([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*)'
1413 .
' ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)#',
1414 'WIN' =>
'#([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)#'
1420 foreach ($regexps as $k => $v)
1422 if (@preg_match($v, $contents[0]))
1439 if ($osType ==
'UNIX' || $osType ==
'MAC')
1441 foreach ($contents as $file)
1445 if (@preg_match($regexp, $file, $regs))
1447 $fType = (int) strpos(
"-dl", $regs[1]{0});
1450 $tmp_array[
'type'] = $fType;
1451 $tmp_array[
'rights'] = $regs[1];
1454 $tmp_array[
'user'] = $regs[3];
1455 $tmp_array[
'group'] = $regs[4];
1456 $tmp_array[
'size'] = $regs[5];
1457 $tmp_array[
'date'] = @date(
"m-d", strtotime($regs[6]));
1458 $tmp_array[
'time'] = $regs[7];
1459 $tmp_array[
'name'] = $regs[9];
1462 if ($type ==
'files' && $tmp_array[
'type'] == 1)
1467 if ($type ==
'folders' && $tmp_array[
'type'] == 0)
1471 if (is_array($tmp_array) && $tmp_array[
'name'] !=
'.' && $tmp_array[
'name'] !=
'..')
1473 $dir_list[] = $tmp_array;
1479 foreach ($contents as $file)
1483 if (@preg_match($regexp, $file, $regs))
1485 $fType = (int) ($regs[7] ==
'<DIR>');
1486 $timestamp = strtotime(
"$regs[3]-$regs[1]-$regs[2] $regs[4]:$regs[5]$regs[6]");
1489 $tmp_array[
'type'] = $fType;
1490 $tmp_array[
'rights'] =
'';
1493 $tmp_array[
'user'] =
'';
1494 $tmp_array[
'group'] =
'';
1495 $tmp_array[
'size'] = (int) $regs[7];
1496 $tmp_array[
'date'] = date(
'm-d', $timestamp);
1497 $tmp_array[
'time'] = date(
'H:i', $timestamp);
1498 $tmp_array[
'name'] = $regs[8];
1501 if ($type ==
'files' && $tmp_array[
'type'] == 1)
1506 if ($type ==
'folders' && $tmp_array[
'type'] == 0)
1510 if (is_array($tmp_array) && $tmp_array[
'name'] !=
'.' && $tmp_array[
'name'] !=
'..')
1512 $dir_list[] = $tmp_array;
1530 protected function _putCmd($cmd, $expectedResponse)
1533 if (!is_resource($this->_conn))
1541 if (!fwrite($this->_conn, $cmd .
"\r\n"))
1564 $this->_response =
'';
1568 $this->_response .= fgets($this->_conn, 4096);
1570 while (!preg_match(
"/^([0-9]{3})(-(.*" . CRLF .
")+\\1)? [^" . CRLF .
"]+" . CRLF .
"$/", $this->_response, $parts) && time() < $endTime);
1573 if (!isset($parts[1]))
1581 $this->_responseCode = $parts[1];
1582 $this->_responseMsg = $parts[0];
1585 if (is_array($expected))
1587 if (in_array($this->_responseCode, $expected))
1598 if ($this->_responseCode == $expected)
1625 if (!is_resource($this->_conn))
1633 @ fwrite($this->_conn,
"PASV\r\n");
1637 $this->_response =
'';
1641 $this->_response .= fgets($this->_conn, 4096);
1643 while (!preg_match(
"/^([0-9]{3})(-(.*" . CRLF .
")+\\1)? [^" . CRLF .
"]+" . CRLF .
"$/", $this->_response, $parts) && time() < $endTime);
1646 if (!isset($parts[1]))
1654 $this->_responseCode = $parts[1];
1655 $this->_responseMsg = $parts[0];
1658 if ($this->_responseCode !=
'227')
1666 if (preg_match(
'~\((\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))\)~', $this->_responseMsg, $match) == 0)
1674 $this->_pasv = array(
'ip' => $match[1] .
'.' . $match[2] .
'.' . $match[3] .
'.' . $match[4],
'port' => $match[5] * 256 + $match[6]);
1677 $this->_dataconn = @fsockopen($this->_pasv[
'ip'], $this->_pasv[
'port'], $errno, $err, $this->_timeout);
1679 if (!$this->_dataconn)
1682 JText::sprintf(
'JLIB_CLIENT_ERROR_JFTP_PASSIVE_CONNECT', $this->_pasv[
'ip'], $this->_pasv[
'port'], $errno, $err),
1691 socket_set_timeout($this->_conn, $this->_timeout, 0);
1707 if ($this->_type == FTP_AUTOASCII)
1709 $dot = strrpos($fileName,
'.') + 1;
1710 $ext = substr($fileName, $dot);
1712 if (in_array($ext, $this->_autoAscii))
1721 elseif ($this->_type == FTP_ASCII)
1744 if ($mode == FTP_BINARY)
1746 if (!$this->
_putCmd(
"TYPE I", 200))
1755 if (!$this->
_putCmd(
"TYPE A", 200))