PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php

https://gitlab.com/ealexis.t/trends
PHP | 624 lines | 321 code | 74 blank | 229 comment | 10 complexity | d400f3b2144a83228b2b2587f6c89cd0 MD5 | raw file
  1. <?php
  2. namespace League\Flysystem\Adapter;
  3. use DateTime;
  4. use League\Flysystem\AdapterInterface;
  5. use League\Flysystem\Config;
  6. use League\Flysystem\NotSupportedException;
  7. use RuntimeException;
  8. abstract class AbstractFtpAdapter extends AbstractAdapter
  9. {
  10. /**
  11. * @var mixed
  12. */
  13. protected $connection;
  14. /**
  15. * @var string
  16. */
  17. protected $host;
  18. /**
  19. * @var int
  20. */
  21. protected $port = 21;
  22. /**
  23. * @var string|null
  24. */
  25. protected $username;
  26. /**
  27. * @var string|null
  28. */
  29. protected $password;
  30. /**
  31. * @var bool
  32. */
  33. protected $ssl = false;
  34. /**
  35. * @var int
  36. */
  37. protected $timeout = 90;
  38. /**
  39. * @var bool
  40. */
  41. protected $passive = true;
  42. /**
  43. * @var string
  44. */
  45. protected $separator = '/';
  46. /**
  47. * @var string|null
  48. */
  49. protected $root;
  50. /**
  51. * @var int
  52. */
  53. protected $permPublic = 0744;
  54. /**
  55. * @var int
  56. */
  57. protected $permPrivate = 0700;
  58. /**
  59. * @var array
  60. */
  61. protected $configurable = [];
  62. /**
  63. * @var string
  64. */
  65. protected $systemType;
  66. /**
  67. * Constructor.
  68. *
  69. * @param array $config
  70. */
  71. public function __construct(array $config)
  72. {
  73. $this->setConfig($config);
  74. }
  75. /**
  76. * Set the config.
  77. *
  78. * @param array $config
  79. *
  80. * @return $this
  81. */
  82. public function setConfig(array $config)
  83. {
  84. foreach ($this->configurable as $setting) {
  85. if ( ! isset($config[$setting])) {
  86. continue;
  87. }
  88. $method = 'set' . ucfirst($setting);
  89. if (method_exists($this, $method)) {
  90. $this->$method($config[$setting]);
  91. }
  92. }
  93. return $this;
  94. }
  95. /**
  96. * Returns the host.
  97. *
  98. * @return string
  99. */
  100. public function getHost()
  101. {
  102. return $this->host;
  103. }
  104. /**
  105. * Set the host.
  106. *
  107. * @param string $host
  108. *
  109. * @return $this
  110. */
  111. public function setHost($host)
  112. {
  113. $this->host = $host;
  114. return $this;
  115. }
  116. /**
  117. * Set the public permission value.
  118. *
  119. * @param int $permPublic
  120. *
  121. * @return $this
  122. */
  123. public function setPermPublic($permPublic)
  124. {
  125. $this->permPublic = $permPublic;
  126. return $this;
  127. }
  128. /**
  129. * Set the private permission value.
  130. *
  131. * @param int $permPrivate
  132. *
  133. * @return $this
  134. */
  135. public function setPermPrivate($permPrivate)
  136. {
  137. $this->permPrivate = $permPrivate;
  138. return $this;
  139. }
  140. /**
  141. * Returns the ftp port.
  142. *
  143. * @return int
  144. */
  145. public function getPort()
  146. {
  147. return $this->port;
  148. }
  149. /**
  150. * Returns the root folder to work from.
  151. *
  152. * @return string
  153. */
  154. public function getRoot()
  155. {
  156. return $this->root;
  157. }
  158. /**
  159. * Set the ftp port.
  160. *
  161. * @param int|string $port
  162. *
  163. * @return $this
  164. */
  165. public function setPort($port)
  166. {
  167. $this->port = (int) $port;
  168. return $this;
  169. }
  170. /**
  171. * Set the root folder to work from.
  172. *
  173. * @param string $root
  174. *
  175. * @return $this
  176. */
  177. public function setRoot($root)
  178. {
  179. $this->root = rtrim($root, '\\/') . $this->separator;
  180. return $this;
  181. }
  182. /**
  183. * Returns the ftp username.
  184. *
  185. * @return string username
  186. */
  187. public function getUsername()
  188. {
  189. return empty($this->username) ? 'anonymous' : $this->username;
  190. }
  191. /**
  192. * Set ftp username.
  193. *
  194. * @param string $username
  195. *
  196. * @return $this
  197. */
  198. public function setUsername($username)
  199. {
  200. $this->username = $username;
  201. return $this;
  202. }
  203. /**
  204. * Returns the password.
  205. *
  206. * @return string password
  207. */
  208. public function getPassword()
  209. {
  210. return $this->password;
  211. }
  212. /**
  213. * Set the ftp password.
  214. *
  215. * @param string $password
  216. *
  217. * @return $this
  218. */
  219. public function setPassword($password)
  220. {
  221. $this->password = $password;
  222. return $this;
  223. }
  224. /**
  225. * Returns the amount of seconds before the connection will timeout.
  226. *
  227. * @return int
  228. */
  229. public function getTimeout()
  230. {
  231. return $this->timeout;
  232. }
  233. /**
  234. * Set the amount of seconds before the connection should timeout.
  235. *
  236. * @param int $timeout
  237. *
  238. * @return $this
  239. */
  240. public function setTimeout($timeout)
  241. {
  242. $this->timeout = (int) $timeout;
  243. return $this;
  244. }
  245. /**
  246. * Return the FTP system type.
  247. *
  248. * @return string
  249. */
  250. public function getSystemType()
  251. {
  252. return $this->systemType;
  253. }
  254. /**
  255. * Set the FTP system type (windows or unix).
  256. *
  257. * @param string $systemType
  258. *
  259. * @return $this
  260. */
  261. public function setSystemType($systemType)
  262. {
  263. $this->systemType = strtolower($systemType);
  264. return $this;
  265. }
  266. /**
  267. * @inheritdoc
  268. */
  269. public function listContents($directory = '', $recursive = false)
  270. {
  271. return $this->listDirectoryContents($directory, $recursive);
  272. }
  273. /**
  274. * Normalize a directory listing.
  275. *
  276. * @param array $listing
  277. * @param string $prefix
  278. *
  279. * @return array directory listing
  280. */
  281. protected function normalizeListing(array $listing, $prefix = '')
  282. {
  283. $base = $prefix;
  284. $result = [];
  285. $listing = $this->removeDotDirectories($listing);
  286. while ($item = array_shift($listing)) {
  287. if (preg_match('#^.*:$#', $item)) {
  288. $base = trim($item, ':');
  289. continue;
  290. }
  291. $result[] = $this->normalizeObject($item, $base);
  292. }
  293. return $this->sortListing($result);
  294. }
  295. /**
  296. * Sort a directory listing.
  297. *
  298. * @param array $result
  299. *
  300. * @return array sorted listing
  301. */
  302. protected function sortListing(array $result)
  303. {
  304. $compare = function ($one, $two) {
  305. return strnatcmp($one['path'], $two['path']);
  306. };
  307. usort($result, $compare);
  308. return $result;
  309. }
  310. /**
  311. * Normalize a file entry.
  312. *
  313. * @param string $item
  314. * @param string $base
  315. *
  316. * @return array normalized file array
  317. *
  318. * @throws NotSupportedException
  319. */
  320. protected function normalizeObject($item, $base)
  321. {
  322. $systemType = $this->systemType ?: $this->detectSystemType($item);
  323. if ($systemType === 'unix') {
  324. return $this->normalizeUnixObject($item, $base);
  325. } elseif ($systemType === 'windows') {
  326. return $this->normalizeWindowsObject($item, $base);
  327. }
  328. throw NotSupportedException::forFtpSystemType($systemType);
  329. }
  330. /**
  331. * Normalize a Unix file entry.
  332. *
  333. * @param string $item
  334. * @param string $base
  335. *
  336. * @return array normalized file array
  337. */
  338. protected function normalizeUnixObject($item, $base)
  339. {
  340. $item = preg_replace('#\s+#', ' ', trim($item), 7);
  341. if (count(explode(' ', $item, 9)) !== 9) {
  342. throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
  343. }
  344. list($permissions, /* $number */, /* $owner */, /* $group */, $size, /* $month */, /* $day */, /* $time*/, $name) = explode(' ', $item, 9);
  345. $type = $this->detectType($permissions);
  346. $path = empty($base) ? $name : $base . $this->separator . $name;
  347. if ($type === 'dir') {
  348. return compact('type', 'path');
  349. }
  350. $permissions = $this->normalizePermissions($permissions);
  351. $visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
  352. $size = (int) $size;
  353. return compact('type', 'path', 'visibility', 'size');
  354. }
  355. /**
  356. * Normalize a Windows/DOS file entry.
  357. *
  358. * @param string $item
  359. * @param string $base
  360. *
  361. * @return array normalized file array
  362. */
  363. protected function normalizeWindowsObject($item, $base)
  364. {
  365. $item = preg_replace('#\s+#', ' ', trim($item), 3);
  366. if (count(explode(' ', $item, 4)) !== 4) {
  367. throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
  368. }
  369. list($date, $time, $size, $name) = explode(' ', $item, 4);
  370. $path = empty($base) ? $name : $base . $this->separator . $name;
  371. // Check for the correct date/time format
  372. $format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
  373. $timestamp = DateTime::createFromFormat($format, $date . $time)->getTimestamp();
  374. if ($size === '<DIR>') {
  375. $type = 'dir';
  376. return compact('type', 'path', 'timestamp');
  377. }
  378. $type = 'file';
  379. $visibility = AdapterInterface::VISIBILITY_PUBLIC;
  380. $size = (int) $size;
  381. return compact('type', 'path', 'visibility', 'size', 'timestamp');
  382. }
  383. /**
  384. * Get the system type from a listing item.
  385. *
  386. * @param string $item
  387. *
  388. * @return string the system type
  389. */
  390. protected function detectSystemType($item)
  391. {
  392. if (preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', $item)) {
  393. return $this->systemType = 'windows';
  394. }
  395. return $this->systemType = 'unix';
  396. }
  397. /**
  398. * Get the file type from the permissions.
  399. *
  400. * @param string $permissions
  401. *
  402. * @return string file type
  403. */
  404. protected function detectType($permissions)
  405. {
  406. return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';
  407. }
  408. /**
  409. * Normalize a permissions string.
  410. *
  411. * @param string $permissions
  412. *
  413. * @return int
  414. */
  415. protected function normalizePermissions($permissions)
  416. {
  417. // remove the type identifier
  418. $permissions = substr($permissions, 1);
  419. // map the string rights to the numeric counterparts
  420. $map = ['-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'];
  421. $permissions = strtr($permissions, $map);
  422. // split up the permission groups
  423. $parts = str_split($permissions, 3);
  424. // convert the groups
  425. $mapper = function ($part) {
  426. return array_sum(str_split($part));
  427. };
  428. // get the sum of the groups
  429. return array_sum(array_map($mapper, $parts));
  430. }
  431. /**
  432. * Filter out dot-directories.
  433. *
  434. * @param array $list
  435. *
  436. * @return array
  437. */
  438. public function removeDotDirectories(array $list)
  439. {
  440. $filter = function ($line) {
  441. if ( ! empty($line) && ! preg_match('#.* \.(\.)?$|^total#', $line)) {
  442. return true;
  443. }
  444. return false;
  445. };
  446. return array_filter($list, $filter);
  447. }
  448. /**
  449. * @inheritdoc
  450. */
  451. public function has($path)
  452. {
  453. return $this->getMetadata($path);
  454. }
  455. /**
  456. * @inheritdoc
  457. */
  458. public function getSize($path)
  459. {
  460. return $this->getMetadata($path);
  461. }
  462. /**
  463. * @inheritdoc
  464. */
  465. public function getVisibility($path)
  466. {
  467. return $this->getMetadata($path);
  468. }
  469. /**
  470. * Ensure a directory exists.
  471. *
  472. * @param string $dirname
  473. */
  474. public function ensureDirectory($dirname)
  475. {
  476. if ( ! empty($dirname) && ! $this->has($dirname)) {
  477. $this->createDir($dirname, new Config());
  478. }
  479. }
  480. /**
  481. * @return mixed
  482. */
  483. public function getConnection()
  484. {
  485. if ( ! $this->isConnected()) {
  486. $this->disconnect();
  487. $this->connect();
  488. }
  489. return $this->connection;
  490. }
  491. /**
  492. * Get the public permission value.
  493. *
  494. * @return int
  495. */
  496. public function getPermPublic()
  497. {
  498. return $this->permPublic;
  499. }
  500. /**
  501. * Get the private permission value.
  502. *
  503. * @return int
  504. */
  505. public function getPermPrivate()
  506. {
  507. return $this->permPrivate;
  508. }
  509. /**
  510. * Disconnect on destruction.
  511. */
  512. public function __destruct()
  513. {
  514. $this->disconnect();
  515. }
  516. /**
  517. * Establish a connection.
  518. */
  519. abstract public function connect();
  520. /**
  521. * Close the connection.
  522. */
  523. abstract public function disconnect();
  524. /**
  525. * Check if a connection is active.
  526. *
  527. * @return bool
  528. */
  529. abstract public function isConnected();
  530. }