SFTP Plugin
All checks were successful
Gitea Actions / Run-Tests-On-Arm64 (push) Successful in 6m41s
Gitea Actions / Run-Tests-On-Amd64 (push) Successful in 15m7s

This commit is contained in:
Thomas Peterson 2025-05-26 16:40:36 +02:00
parent 140badb63e
commit 7f8f061725
8 changed files with 325 additions and 72 deletions

View File

@ -30,9 +30,6 @@ jobs:
- name: Run Application Image
run: |
make docker-compose-up DOCKER_SERVICE_NAME=application
- name: Load Data
run: |
docker exec -i psc_ci-mongodb-1 /usr/bin/mongorestore --archive < ./dev_db/mongodb.dump
- name: Run Composer Install
run: |
chmod -R 0777 src/new
@ -84,9 +81,6 @@ jobs:
- name: Run Application Image
run: |
make docker-compose-up DOCKER_SERVICE_NAME=application
- name: Load Data
run: |
docker exec -i psc_ci-mongodb-1 /usr/bin/mongorestore --archive < ./dev_db/mongodb.dump
- name: Run Composer Install
run: |
chmod -R 0777 src/new

View File

@ -55,6 +55,7 @@
"paypal/rest-api-sdk-php": "dev-master",
"php-http/guzzle6-adapter": "^1.1",
"phpoffice/phpspreadsheet": "^1.28",
"phpseclib/phpseclib": "~3.0",
"picqer/sendcloud-php-client": "v2.8.1",
"portphp/csv": ">=1.1.0",
"portphp/excel": ">=1.1.0",

179
src/new/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "99334202e137c912623234d7f71ca0ce",
"content-hash": "73e98a07bb5f5f1bcb7f9ff9649aa135",
"packages": [
{
"name": "azuyalabs/yasumi",
@ -6014,6 +6014,73 @@
"abandoned": true,
"time": "2017-03-28T22:19:25+00:00"
},
{
"name": "paragonie/constant_time_encoding",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "df1e7fde177501eee2037dd159cf04f5f301a512"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512",
"reference": "df1e7fde177501eee2037dd159cf04f5f301a512",
"shasum": ""
},
"require": {
"php": "^8"
},
"require-dev": {
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4|^5"
},
"type": "library",
"autoload": {
"psr-4": {
"ParagonIE\\ConstantTime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com",
"role": "Maintainer"
},
{
"name": "Steve 'Sc00bz' Thomas",
"email": "steve@tobtu.com",
"homepage": "https://www.tobtu.com",
"role": "Original Developer"
}
],
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
"keywords": [
"base16",
"base32",
"base32_decode",
"base32_encode",
"base64",
"base64_decode",
"base64_encode",
"bin2hex",
"encoding",
"hex",
"hex2bin",
"rfc4648"
],
"support": {
"email": "info@paragonie.com",
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
"source": "https://github.com/paragonie/constant_time_encoding"
},
"time": "2024-05-08T12:36:18+00:00"
},
{
"name": "paypal/paypal-checkout-sdk",
"version": "dev-master",
@ -6685,6 +6752,116 @@
},
"time": "2025-02-08T02:56:14+00:00"
},
{
"name": "phpseclib/phpseclib",
"version": "3.0.43",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02",
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02",
"shasum": ""
},
"require": {
"paragonie/constant_time_encoding": "^1|^2|^3",
"paragonie/random_compat": "^1.4|^2.0|^9.99.99",
"php": ">=5.6.1"
},
"require-dev": {
"phpunit/phpunit": "*"
},
"suggest": {
"ext-dom": "Install the DOM extension to load XML formatted public keys.",
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"type": "library",
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib3\\": "phpseclib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"homepage": "http://phpseclib.sourceforge.net",
"keywords": [
"BigInteger",
"aes",
"asn.1",
"asn1",
"blowfish",
"crypto",
"cryptography",
"encryption",
"rsa",
"security",
"sftp",
"signature",
"signing",
"ssh",
"twofish",
"x.509",
"x509"
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.43"
},
"funding": [
{
"url": "https://github.com/terrafrost",
"type": "github"
},
{
"url": "https://www.patreon.com/phpseclib",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
"type": "tidelift"
}
],
"time": "2024-12-14T21:12:59+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "2.1.0",

View File

@ -3,7 +3,10 @@ namespace Plugin\System\PSC\Ftp\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use phpseclib3\Net\SFTP;
use phpseclib3\Net\SSH2;
#[Route('/check')]
class CheckController extends AbstractController
@ -11,6 +14,9 @@ class CheckController extends AbstractController
#[Route('/', name: 'psc_plugin_ftp_check')]
public function indexAction(Request $request)
{
$count = 0;
$temp = [];
if($request->get('sftp', 'false') == 'false') {
$ftp = new \FtpClient\FtpClient();
if($request->get('ftpSsl', 'false') == 'false') {
@ -30,10 +36,22 @@ class CheckController extends AbstractController
$data = $ftp->scanDir($request->get('ftpPath', '.', false));
}
$temp = [];
foreach($data as $key => $row) {
$temp[] = $row;
}
}else{
$sftp = new SFTP($request->get('ftpHost'));
if (!$sftp->login($request->get('ftpUsername'), $request->get('ftpPassword'))) {
return new JsonResponse(['success' => false, 'data' => $temp, 'count' => $count]);
}
$data = $sftp->rawlist();
foreach($data as $key => $row) {
$temp[] = ['type' => $row['type'], 'name' => utf8_encode($row['filename'])];
}
$count = count($data);
}
return new JsonResponse(['success' => true, 'data' => $temp, 'count' => $count]);
}

View File

@ -31,6 +31,9 @@ class Ftp
#[Field(type: 'bool')]
protected $passiv;
#[Field(type: 'bool')]
protected $sftp;
/**
* @var string $username
@ -154,6 +157,12 @@ class Ftp
return $this->passiv;
}
public function isSftp()
{
return $this->sftp;
}
/**
* @param bool $passiv
*/
@ -162,5 +171,10 @@ class Ftp
$this->passiv = $passiv;
}
public function setSftp($sftp)
{
$this->sftp = $sftp;
}
}

View File

@ -5,7 +5,7 @@ use PSC\System\PluginBundle\Plugin\Base;
class Plugin extends Base implements \PSC\System\PluginBundle\Interfaces\Plugin {
protected $name = 'FTP Queue';
protected $name = 'FTP / SFTP Queue';
public function getType()
{
@ -14,7 +14,7 @@ class Plugin extends Base implements \PSC\System\PluginBundle\Interfaces\Plugin
public function getDescription()
{
return 'Überträgt Pakete per FTP auf einen entfernten Rechner';
return 'Überträgt Pakete per FTP / SFTP auf einen entfernten Rechner';
}
public function getVersion()

View File

@ -24,6 +24,7 @@ use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use phpseclib3\Net\SFTP;
class Ftp implements QueueInterface, ConfigurableElementInterface
{
@ -53,7 +54,7 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
public function getDescription()
{
return 'Verschiebt Package auf einen FTP Server';
return 'Verschiebt Package auf einen FTP / SFTP Server';
}
public function getGroup()
@ -63,11 +64,12 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
public function getName()
{
return 'Ftp';
return 'Ftp / SFTP';
}
public function getForm(FormBuilderInterface $builder, $form_options, EventInterface $event)
{
$builder->add("sftp", CheckboxType::class, array('label' => 'SFTP', 'required' => false));
$builder->add("host", TextType::class, array('label' => 'Server'));
$builder->add("username", TextType::class, array('label' => 'Benutzer'));
$builder->add("password", TextType::class, array('label' => 'Passwort'));
@ -80,6 +82,7 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
public function injectDocument(Form $form, EventInterface $event, Queue $objQueue)
{
$url = new \Plugin\System\PSC\Ftp\Document\Ftp();
$url->setSftp($form->get('sftp')->getData());
$url->setHost($form->get('host')->getData());
$url->setUsername($form->get('username')->getData());
$url->setPassword($form->get('password')->getData());
@ -92,6 +95,7 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
public function setFormData(Form $form, EventInterface $event, Queue $queueObj)
{
$form->get('sftp')->setData($queueObj->getQueueDocument()->isSftp());
$form->get('host')->setData($queueObj->getQueueDocument()->getHost());
$form->get('username')->setData($queueObj->getQueueDocument()->getUsername());
$form->get('password')->setData($queueObj->getQueueDocument()->getPassword());
@ -130,6 +134,19 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
->findOneBy(['id' => new \MongoId($order[1])]);
try {
if($ftpDoc->isSftp()) {
$sftp = new SFTP($ftpDoc->getHost());
if ($sftp->login($ftpDoc->getUsername(), $ftpDoc->getPassword())) {
$sftp->chdir($ftpDoc->getPath());
$sftp->put($upload->getFilename(), $upload->getFile()->getMongoGridFSFile()->getBytes(), SFTP::SOURCE_LOCAL_FILE);
}
$pc = new Uploaded();
$pc->setOrder($eventDoc->getOrder());
$pc->setShop($eventDoc->getShop());
$this->_eventManager->addJob($pc);
}else{
$ftp = new \FtpClient\FtpClient();
if ($ftpDoc->getPort() == "") {
@ -145,6 +162,13 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
$ftp->chdir($ftpDoc->getPath());
$ftp->putFromString($upload->getFilename(), $upload->getFile()->getMongoGridFSFile()->getBytes());
$pc = new Uploaded();
$pc->setOrder($eventDoc->getOrder());
$pc->setShop($eventDoc->getShop());
$this->_eventManager->addJob($pc);
}
} catch (\Exception $e) {
$this->_error = $e->getMessage();
@ -153,6 +177,20 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
}else {
try {
if($ftpDoc->isSftp()) {
$sftp = new SFTP($ftpDoc->getHost());
if ($sftp->login($ftpDoc->getUsername(), $ftpDoc->getPassword())) {
$sftp->chdir($ftpDoc->getPath());
$sftp->put(basename($eventDoc->getPath()), $eventDoc->getPath(), SFTP::SOURCE_LOCAL_FILE);
$pc = new Uploaded();
$pc->setOrder($eventDoc->getOrder());
$pc->setShop($eventDoc->getShop());
$this->_eventManager->addJob($pc);
}
}else{
$ftp = new \FtpClient\FtpClient();
if ($ftpDoc->getPort() == "") {
@ -173,7 +211,7 @@ class Ftp implements QueueInterface, ConfigurableElementInterface
$pc->setShop($eventDoc->getShop());
$this->_eventManager->addJob($pc);
}
} catch (\Exception $e) {
$this->_error = $e->getMessage();
return false;

View File

@ -1,9 +1,19 @@
<div class="panel">
<div class="header">
<h4>Details FTP</h4>
<h4>Details</h4>
</div>
<div class="body">
<div class="row">
<div class="col-md-6">
<div class="form-group row">
{{ form_label(form.sftp) }}
<div class="col-md-8">
{{ form_widget(form.sftp) }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group row">
@ -78,14 +88,15 @@
</div>
</div>
</div>
<script>
<script type="module">
import $ from 'jquery';
$(function() {
$('.testFtp').click(function() {
$.getJSON('{{ path('psc_plugin_ftp_check') }}', {
ftpHost: $('#form_host').val(),
ftpSsl: $('#form_ssl').is( ":checked" ),
sftp: $('#form_sftp').is( ":checked" ),
ftpPassiv: $('#form_passiv').is( ":checked" ),
ftpPort: $('#form_port').val(),
ftpUsername: $('#form_username').val(),