PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Front_End/vendor/league/flysystem/src/Adapter/Ftp.php

https://gitlab.com/Sigpot/AirSpot
PHP | 505 lines | 292 code | 86 blank | 127 comment | 32 complexity | 6462dca5cc10e54a5afea579775939a1 MD5 | raw file
  1. <?php
  2. namespace League\Flysystem\Adapter;
  3. use ErrorException;
  4. use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
  5. use League\Flysystem\AdapterInterface;
  6. use League\Flysystem\Config;
  7. use League\Flysystem\Util;
  8. use League\Flysystem\Util\MimeType;
  9. use RuntimeException;
  10. class Ftp extends AbstractFtpAdapter
  11. {
  12. use StreamedCopyTrait;
  13. /**
  14. * @var int
  15. */
  16. protected $transferMode = FTP_BINARY;
  17. /**
  18. * @var null|bool
  19. */
  20. protected $ignorePassiveAddress = null;
  21. /**
  22. * @var bool
  23. */
  24. protected $recurseManually = false;
  25. /**
  26. * @var array
  27. */
  28. protected $configurable = [
  29. 'host',
  30. 'port',
  31. 'username',
  32. 'password',
  33. 'ssl',
  34. 'timeout',
  35. 'root',
  36. 'permPrivate',
  37. 'permPublic',
  38. 'passive',
  39. 'transferMode',
  40. 'systemType',
  41. 'ignorePassiveAddress',
  42. 'recurseManually',
  43. ];
  44. /**
  45. * Set the transfer mode.
  46. *
  47. * @param int $mode
  48. *
  49. * @return $this
  50. */
  51. public function setTransferMode($mode)
  52. {
  53. $this->transferMode = $mode;
  54. return $this;
  55. }
  56. /**
  57. * Set if Ssl is enabled.
  58. *
  59. * @param bool $ssl
  60. *
  61. * @return $this
  62. */
  63. public function setSsl($ssl)
  64. {
  65. $this->ssl = (bool) $ssl;
  66. return $this;
  67. }
  68. /**
  69. * Set if passive mode should be used.
  70. *
  71. * @param bool $passive
  72. */
  73. public function setPassive($passive = true)
  74. {
  75. $this->passive = $passive;
  76. }
  77. /**
  78. * @param bool $ignorePassiveAddress
  79. */
  80. public function setIgnorePassiveAddress($ignorePassiveAddress)
  81. {
  82. $this->ignorePassiveAddress = $ignorePassiveAddress;
  83. }
  84. /**
  85. * @param bool $recurseManually
  86. */
  87. public function setRecurseManually($recurseManually)
  88. {
  89. $this->recurseManually = $recurseManually;
  90. }
  91. /**
  92. * Connect to the FTP server.
  93. */
  94. public function connect()
  95. {
  96. if ($this->ssl) {
  97. $this->connection = ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
  98. } else {
  99. $this->connection = ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
  100. }
  101. if ( ! $this->connection) {
  102. throw new RuntimeException('Could not connect to host: ' . $this->getHost() . ', port:' . $this->getPort());
  103. }
  104. $this->login();
  105. $this->setConnectionPassiveMode();
  106. $this->setConnectionRoot();
  107. }
  108. /**
  109. * Set the connections to passive mode.
  110. *
  111. * @throws RuntimeException
  112. */
  113. protected function setConnectionPassiveMode()
  114. {
  115. if (is_bool($this->ignorePassiveAddress) && defined('FTP_USEPASVADDRESS')) {
  116. ftp_set_option($this->connection, FTP_USEPASVADDRESS, ! $this->ignorePassiveAddress);
  117. }
  118. if ( ! ftp_pasv($this->connection, $this->passive)) {
  119. throw new RuntimeException(
  120. 'Could not set passive mode for connection: ' . $this->getHost() . '::' . $this->getPort()
  121. );
  122. }
  123. }
  124. /**
  125. * Set the connection root.
  126. */
  127. protected function setConnectionRoot()
  128. {
  129. $root = $this->getRoot();
  130. $connection = $this->connection;
  131. if (empty($root) === false && ! ftp_chdir($connection, $root)) {
  132. throw new RuntimeException('Root is invalid or does not exist: ' . $this->getRoot());
  133. }
  134. // Store absolute path for further reference.
  135. // This is needed when creating directories and
  136. // initial root was a relative path, else the root
  137. // would be relative to the chdir'd path.
  138. $this->root = ftp_pwd($connection);
  139. }
  140. /**
  141. * Login.
  142. *
  143. * @throws RuntimeException
  144. */
  145. protected function login()
  146. {
  147. set_error_handler(
  148. function () {
  149. }
  150. );
  151. $isLoggedIn = ftp_login($this->connection, $this->getUsername(), $this->getPassword());
  152. restore_error_handler();
  153. if ( ! $isLoggedIn) {
  154. $this->disconnect();
  155. throw new RuntimeException(
  156. 'Could not login with connection: ' . $this->getHost() . '::' . $this->getPort(
  157. ) . ', username: ' . $this->getUsername()
  158. );
  159. }
  160. }
  161. /**
  162. * Disconnect from the FTP server.
  163. */
  164. public function disconnect()
  165. {
  166. if ($this->isConnected()) {
  167. ftp_close($this->connection);
  168. }
  169. $this->connection = null;
  170. }
  171. /**
  172. * @inheritdoc
  173. */
  174. public function write($path, $contents, Config $config)
  175. {
  176. $stream = fopen('php://temp', 'w+b');
  177. fwrite($stream, $contents);
  178. rewind($stream);
  179. $result = $this->writeStream($path, $stream, $config);
  180. fclose($stream);
  181. if ($result === false) {
  182. return false;
  183. }
  184. $result['contents'] = $contents;
  185. $result['mimetype'] = Util::guessMimeType($path, $contents);
  186. return $result;
  187. }
  188. /**
  189. * @inheritdoc
  190. */
  191. public function writeStream($path, $resource, Config $config)
  192. {
  193. $this->ensureDirectory(Util::dirname($path));
  194. if ( ! ftp_fput($this->getConnection(), $path, $resource, $this->transferMode)) {
  195. return false;
  196. }
  197. if ($visibility = $config->get('visibility')) {
  198. $this->setVisibility($path, $visibility);
  199. }
  200. return compact('path', 'visibility');
  201. }
  202. /**
  203. * @inheritdoc
  204. */
  205. public function update($path, $contents, Config $config)
  206. {
  207. return $this->write($path, $contents, $config);
  208. }
  209. /**
  210. * @inheritdoc
  211. */
  212. public function updateStream($path, $resource, Config $config)
  213. {
  214. return $this->writeStream($path, $resource, $config);
  215. }
  216. /**
  217. * @inheritdoc
  218. */
  219. public function rename($path, $newpath)
  220. {
  221. return ftp_rename($this->getConnection(), $path, $newpath);
  222. }
  223. /**
  224. * @inheritdoc
  225. */
  226. public function delete($path)
  227. {
  228. return ftp_delete($this->getConnection(), $path);
  229. }
  230. /**
  231. * @inheritdoc
  232. */
  233. public function deleteDir($dirname)
  234. {
  235. $connection = $this->getConnection();
  236. $contents = array_reverse($this->listDirectoryContents($dirname));
  237. foreach ($contents as $object) {
  238. if ($object['type'] === 'file') {
  239. if ( ! ftp_delete($connection, $object['path'])) {
  240. return false;
  241. }
  242. } elseif ( ! ftp_rmdir($connection, $object['path'])) {
  243. return false;
  244. }
  245. }
  246. return ftp_rmdir($connection, $dirname);
  247. }
  248. /**
  249. * @inheritdoc
  250. */
  251. public function createDir($dirname, Config $config)
  252. {
  253. $connection = $this->getConnection();
  254. $directories = explode('/', $dirname);
  255. foreach ($directories as $directory) {
  256. if (false === $this->createActualDirectory($directory, $connection)) {
  257. $this->setConnectionRoot();
  258. return false;
  259. }
  260. ftp_chdir($connection, $directory);
  261. }
  262. $this->setConnectionRoot();
  263. return ['path' => $dirname];
  264. }
  265. /**
  266. * Create a directory.
  267. *
  268. * @param string $directory
  269. * @param resource $connection
  270. *
  271. * @return bool
  272. */
  273. protected function createActualDirectory($directory, $connection)
  274. {
  275. // List the current directory
  276. $listing = ftp_nlist($connection, '.') ?: [];
  277. foreach ($listing as $key => $item) {
  278. if (preg_match('~^\./.*~', $item)) {
  279. $listing[$key] = substr($item, 2);
  280. }
  281. }
  282. if (in_array($directory, $listing)) {
  283. return true;
  284. }
  285. return (boolean) ftp_mkdir($connection, $directory);
  286. }
  287. /**
  288. * @inheritdoc
  289. */
  290. public function getMetadata($path)
  291. {
  292. $connection = $this->getConnection();
  293. if ($path === '') {
  294. return ['type' => 'dir', 'path' => ''];
  295. }
  296. if (@ftp_chdir($connection, $path) === true) {
  297. $this->setConnectionRoot();
  298. return ['type' => 'dir', 'path' => $path];
  299. }
  300. $listing = ftp_rawlist($connection, '-A ' . str_replace('*', '\\*', $path));
  301. if (empty($listing)) {
  302. return false;
  303. }
  304. if (preg_match('/.* not found/', $listing[0])) {
  305. return false;
  306. }
  307. if (preg_match('/^total [0-9]*$/', $listing[0])) {
  308. array_shift($listing);
  309. }
  310. return $this->normalizeObject($listing[0], '');
  311. }
  312. /**
  313. * @inheritdoc
  314. */
  315. public function getMimetype($path)
  316. {
  317. if ( ! $metadata = $this->getMetadata($path)) {
  318. return false;
  319. }
  320. $metadata['mimetype'] = MimeType::detectByFilename($path);
  321. return $metadata;
  322. }
  323. /**
  324. * @inheritdoc
  325. */
  326. public function getTimestamp($path)
  327. {
  328. $timestamp = ftp_mdtm($this->getConnection(), $path);
  329. return ($timestamp !== -1) ? ['timestamp' => $timestamp] : false;
  330. }
  331. /**
  332. * @inheritdoc
  333. */
  334. public function read($path)
  335. {
  336. if ( ! $object = $this->readStream($path)) {
  337. return false;
  338. }
  339. $object['contents'] = stream_get_contents($object['stream']);
  340. fclose($object['stream']);
  341. unset($object['stream']);
  342. return $object;
  343. }
  344. /**
  345. * @inheritdoc
  346. */
  347. public function readStream($path)
  348. {
  349. $stream = fopen('php://temp', 'w+b');
  350. $result = ftp_fget($this->getConnection(), $stream, $path, $this->transferMode);
  351. rewind($stream);
  352. if ( ! $result) {
  353. fclose($stream);
  354. return false;
  355. }
  356. return compact('stream');
  357. }
  358. /**
  359. * @inheritdoc
  360. */
  361. public function setVisibility($path, $visibility)
  362. {
  363. $mode = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();
  364. if ( ! ftp_chmod($this->getConnection(), $mode, $path)) {
  365. return false;
  366. }
  367. return compact('visibility');
  368. }
  369. /**
  370. * @inheritdoc
  371. *
  372. * @param string $directory
  373. */
  374. protected function listDirectoryContents($directory, $recursive = true)
  375. {
  376. $directory = str_replace('*', '\\*', $directory);
  377. if ($recursive && $this->recurseManually) {
  378. return $this->listDirectoryContentsRecursive($directory);
  379. }
  380. $options = $recursive ? '-alnR' : '-aln';
  381. $listing = ftp_rawlist($this->getConnection(), $options . ' ' . $directory);
  382. return $listing ? $this->normalizeListing($listing, $directory) : [];
  383. }
  384. /**
  385. * @inheritdoc
  386. *
  387. * @param string $directory
  388. */
  389. protected function listDirectoryContentsRecursive($directory)
  390. {
  391. $listing = $this->normalizeListing(ftp_rawlist($this->getConnection(), '-aln' . ' ' . $directory) ?: []);
  392. $output = [];
  393. foreach ($listing as $directory) {
  394. $output[] = $directory;
  395. if ($directory['type'] !== 'dir') continue;
  396. $output = array_merge($output, $this->listDirectoryContentsRecursive($directory['path']));
  397. }
  398. return $output;
  399. }
  400. /**
  401. * Check if the connection is open.
  402. *
  403. * @return bool
  404. * @throws ErrorException
  405. */
  406. public function isConnected()
  407. {
  408. try {
  409. return is_resource($this->connection) && ftp_rawlist($this->connection, '/') !== false;
  410. } catch (ErrorException $e) {
  411. fclose($this->connection);
  412. $this->connection = null;
  413. if (strpos($e->getMessage(), 'ftp_rawlist') === false) {
  414. throw $e;
  415. }
  416. return false;
  417. }
  418. }
  419. }