ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
AbstractFtpAdapter.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use DateTime;
11 
12 abstract class AbstractFtpAdapter extends AbstractAdapter
13 {
17  protected $connection;
18 
22  protected $host;
23 
27  protected $port = 21;
28 
32  protected $ssl = false;
33 
37  protected $timeout = 90;
38 
42  protected $passive = true;
43 
47  protected $separator = '/';
48 
52  protected $root;
53 
57  protected $permPublic = 0744;
58 
62  protected $permPrivate = 0700;
63 
67  protected $configurable = [];
68 
72  protected $systemType;
73 
77  protected $alternativeRecursion = false;
78 
82  protected $safeStorage;
83 
89  public function __construct(array $config)
90  {
91  $this->safeStorage = new SafeStorage();
92  $this->setConfig($config);
93  }
94 
102  public function setConfig(array $config)
103  {
104  foreach ($this->configurable as $setting) {
105  if ( ! isset($config[$setting])) {
106  continue;
107  }
108 
109  $method = 'set' . ucfirst($setting);
110 
111  if (method_exists($this, $method)) {
112  $this->$method($config[$setting]);
113  }
114  }
115 
116  return $this;
117  }
118 
124  public function getHost()
125  {
126  return $this->host;
127  }
128 
136  public function setHost($host)
137  {
138  $this->host = $host;
139 
140  return $this;
141  }
142 
150  public function setPermPublic($permPublic)
151  {
152  $this->permPublic = $permPublic;
153 
154  return $this;
155  }
156 
164  public function setPermPrivate($permPrivate)
165  {
166  $this->permPrivate = $permPrivate;
167 
168  return $this;
169  }
170 
176  public function getPort()
177  {
178  return $this->port;
179  }
180 
186  public function getRoot()
187  {
188  return $this->root;
189  }
190 
198  public function setPort($port)
199  {
200  $this->port = (int) $port;
201 
202  return $this;
203  }
204 
212  public function setRoot($root)
213  {
214  $this->root = rtrim($root, '\\/') . $this->separator;
215 
216  return $this;
217  }
218 
224  public function getUsername()
225  {
226  $username = $this->safeStorage->retrieveSafely('username');
227 
228  return $username !== null ? $username : 'anonymous';
229  }
230 
238  public function setUsername($username)
239  {
240  $this->safeStorage->storeSafely('username', $username);
241 
242  return $this;
243  }
244 
250  public function getPassword()
251  {
252  return $this->safeStorage->retrieveSafely('password');
253  }
254 
262  public function setPassword($password)
263  {
264  $this->safeStorage->storeSafely('password', $password);
265 
266  return $this;
267  }
268 
274  public function getTimeout()
275  {
276  return $this->timeout;
277  }
278 
286  public function setTimeout($timeout)
287  {
288  $this->timeout = (int) $timeout;
289 
290  return $this;
291  }
292 
298  public function getSystemType()
299  {
300  return $this->systemType;
301  }
302 
310  public function setSystemType($systemType)
311  {
312  $this->systemType = strtolower($systemType);
313 
314  return $this;
315  }
316 
320  public function listContents($directory = '', $recursive = false)
321  {
322  return $this->listDirectoryContents($directory, $recursive);
323  }
324 
325  abstract protected function listDirectoryContents($directory, $recursive = false);
326 
335  protected function normalizeListing(array $listing, $prefix = '')
336  {
337  $base = $prefix;
338  $result = [];
339  $listing = $this->removeDotDirectories($listing);
340 
341  while ($item = array_shift($listing)) {
342  if (preg_match('#^.*:$#', $item)) {
343  $base = trim($item, ':');
344  continue;
345  }
346 
347  $result[] = $this->normalizeObject($item, $base);
348  }
349 
350  return $this->sortListing($result);
351  }
352 
360  protected function sortListing(array $result)
361  {
362  $compare = function ($one, $two) {
363  return strnatcmp($one['path'], $two['path']);
364  };
365 
366  usort($result, $compare);
367 
368  return $result;
369  }
370 
381  protected function normalizeObject($item, $base)
382  {
383  $systemType = $this->systemType ?: $this->detectSystemType($item);
384 
385  if ($systemType === 'unix') {
386  return $this->normalizeUnixObject($item, $base);
387  } elseif ($systemType === 'windows') {
388  return $this->normalizeWindowsObject($item, $base);
389  }
390 
392  }
393 
402  protected function normalizeUnixObject($item, $base)
403  {
404  $item = preg_replace('#\s+#', ' ', trim($item), 7);
405 
406  if (count(explode(' ', $item, 9)) !== 9) {
407  throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
408  }
409 
410  list($permissions, /* $number */, /* $owner */, /* $group */, $size, /* $month */, /* $day */, /* $time*/, $name) = explode(' ', $item, 9);
411  $type = $this->detectType($permissions);
412  $path = empty($base) ? $name : $base . $this->separator . $name;
413 
414  if ($type === 'dir') {
415  return compact('type', 'path');
416  }
417 
418  $permissions = $this->normalizePermissions($permissions);
420  $size = (int) $size;
421 
422  return compact('type', 'path', 'visibility', 'size');
423  }
424 
433  protected function normalizeWindowsObject($item, $base)
434  {
435  $item = preg_replace('#\s+#', ' ', trim($item), 3);
436 
437  if (count(explode(' ', $item, 4)) !== 4) {
438  throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
439  }
440 
441  list($date, $time, $size, $name) = explode(' ', $item, 4);
442  $path = empty($base) ? $name : $base . $this->separator . $name;
443 
444  // Check for the correct date/time format
445  $format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
446  $dt = DateTime::createFromFormat($format, $date . $time);
447  $timestamp = $dt ? $dt->getTimestamp() : (int) strtotime("$date $time");
448 
449  if ($size === '<DIR>') {
450  $type = 'dir';
451 
452  return compact('type', 'path', 'timestamp');
453  }
454 
455  $type = 'file';
457  $size = (int) $size;
458 
459  return compact('type', 'path', 'visibility', 'size', 'timestamp');
460  }
461 
469  protected function detectSystemType($item)
470  {
471  return preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', $item) ? 'windows' : 'unix';
472  }
473 
481  protected function detectType($permissions)
482  {
483  return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';
484  }
485 
493  protected function normalizePermissions($permissions)
494  {
495  // remove the type identifier
496  $permissions = substr($permissions, 1);
497 
498  // map the string rights to the numeric counterparts
499  $map = ['-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'];
500  $permissions = strtr($permissions, $map);
501 
502  // split up the permission groups
503  $parts = str_split($permissions, 3);
504 
505  // convert the groups
506  $mapper = function ($part) {
507  return array_sum(str_split($part));
508  };
509 
510  // get the sum of the groups
511  return array_sum(array_map($mapper, $parts));
512  }
513 
521  public function removeDotDirectories(array $list)
522  {
523  $filter = function ($line) {
524  if ( ! empty($line) && ! preg_match('#.* \.(\.)?$|^total#', $line)) {
525  return true;
526  }
527 
528  return false;
529  };
530 
531  return array_filter($list, $filter);
532  }
533 
537  public function has($path)
538  {
539  return $this->getMetadata($path);
540  }
541 
545  public function getSize($path)
546  {
547  return $this->getMetadata($path);
548  }
549 
553  public function getVisibility($path)
554  {
555  return $this->getMetadata($path);
556  }
557 
563  public function ensureDirectory($dirname)
564  {
565  if ( ! empty($dirname) && ! $this->has($dirname)) {
566  $this->createDir($dirname, new Config());
567  }
568  }
569 
573  public function getConnection()
574  {
575  $tries = 0;
576 
577  while ( ! $this->isConnected() && $tries < 3) {
578  $tries++;
579  $this->disconnect();
580  $this->connect();
581  }
582 
583  return $this->connection;
584  }
585 
591  public function getPermPublic()
592  {
593  return $this->permPublic;
594  }
595 
601  public function getPermPrivate()
602  {
603  return $this->permPrivate;
604  }
605 
609  public function __destruct()
610  {
611  $this->disconnect();
612  }
613 
617  abstract public function connect();
618 
622  abstract public function disconnect();
623 
629  abstract public function isConnected();
630 }
setRoot($root)
Set the root folder to work from.
const VISIBILITY_PUBLIC
VISIBILITY_PUBLIC public visibility
$path
Definition: aliased.php:25
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41
$size
Definition: RandomTest.php:84
getSize($path)
Get the size of a file.array|false
ensureDirectory($dirname)
Ensure a directory exists.
$format
Definition: metadata.php:141
$config
Definition: bootstrap.php:15
$result
setPassword($password)
Set the ftp password.
$type
createDir($dirname, Config $config)
Create a directory.
listContents($directory='', $recursive=false)
List contents of a directory.array
setTimeout($timeout)
Set the amount of seconds before the connection should timeout.
normalizeWindowsObject($item, $base)
Normalize a Windows/DOS file entry.
normalizeObject($item, $base)
Normalize a file entry.
detectType($permissions)
Get the file type from the permissions.
const VISIBILITY_PRIVATE
VISIBILITY_PRIVATE private visibility
static forFtpSystemType($systemType)
Create a new exception for a link.
$base
Definition: index.php:4
$time
Definition: cron.php:21
isConnected()
Check if a connection is active.
getMetadata($path)
Get all the meta data of a file or directory.
listDirectoryContents($directory, $recursive=false)
normalizeUnixObject($item, $base)
Normalize a Unix file entry.
getRoot()
Returns the root folder to work from.
getTimeout()
Returns the amount of seconds before the connection will timeout.
sortListing(array $result)
Sort a directory listing.
detectSystemType($item)
Get the system type from a listing item.
has($path)
Check whether a file exists.array|bool|null
normalizeListing(array $listing, $prefix='')
Normalize a directory listing.
removeDotDirectories(array $list)
Filter out dot-directories.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
setSystemType($systemType)
Set the FTP system type (windows or unix).
$password
Definition: cron.php:14
normalizePermissions($permissions)
Normalize a permissions string.
setPermPrivate($permPrivate)
Set the private permission value.
getVisibility($path)
Get the visibility of a file.array|false
setPermPublic($permPublic)
Set the public permission value.
getPermPrivate()
Get the private permission value.
getPermPublic()
Get the public permission value.