Skip to content

Commit

Permalink
Optimized memory usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-svirin committed Dec 14, 2024
1 parent 7f7445c commit 69e188a
Show file tree
Hide file tree
Showing 22 changed files with 495 additions and 100 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.4

* Optimized memory usage.

## 2.3

* Support specify custom keyring details for Electronic Signature.
Expand Down
95 changes: 95 additions & 0 deletions src/Contracts/BufferInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace EbicsApi\Ebics\Contracts;

/**
* Buffer class interface.
*
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @author Andrew Svirin
*/
interface BufferInterface
{
const DEFAULT_READ_LENGTH = 1024;

/**
* Open buffer.
*
* @param string $mode
*
* @return void
*/
public function open(string $mode): void;

/**
* Close buffer.
*
* @return void
*/
public function close(): void;

/**
* Reset pointer.
*
* @return void
*/
public function rewind(): void;

/**
* Write to buffer.
*
* @param string $string
*
* @return void
*/
public function write(string $string): void;

/**
* Read from buffer.
*
* @param int|null $length
*
* @return string
*/
public function read(?int $length = null): string;

/**
* Read from buffer full content.
*
* @return string
*/
public function readContent(): string;

/**
* Is end of file.
*
* @return bool
*/
public function eof(): bool;

/**
* Move to pointer.
*
* @param int $offset
*
* @return int
*/
public function fseek(int $offset): int;

/**
* Apply filter.
*
* @param string $filterName
* @param int $mode
*
* @return void
*/
public function filterAppend(string $filterName, int $mode): void;

/**
* Length of content.
*
* @return int
*/
public function length(): int;
}
15 changes: 15 additions & 0 deletions src/Contracts/Crypt/AESInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace EbicsApi\Ebics\Contracts\Crypt;

use EbicsApi\Ebics\Contracts\BufferInterface;

/**
* Crypt AES representation.
*
Expand Down Expand Up @@ -67,6 +69,19 @@ public function setIV(string $iv);
*/
public function encrypt(string $plaintext);

/**
* Decrypts a message.
*
* If strlen($ciphertext) is not a multiple of the block size, null bytes will be added
* to the end of the string until it is.
*
* @param BufferInterface $ciphertext
* @param BufferInterface $plaintext
*
* @return void
*/
public function decryptBuffer(BufferInterface $ciphertext, BufferInterface $plaintext);

/**
* Decrypts a message.
*
Expand Down
7 changes: 0 additions & 7 deletions src/Contracts/EbicsClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -518,13 +518,6 @@ public function getBank(): Bank;
*/
public function getUser(): User;

/**
* Set http client to subset later in the project.
*
* @param HttpClientInterface $httpClient
*/
public function setHttpClient(HttpClientInterface $httpClient): void;

/**
* Get response handler for manual process response.
*
Expand Down
15 changes: 12 additions & 3 deletions src/EbicsBankLetter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use EbicsApi\Ebics\Contracts\BankLetter\FormatterInterface;
use EbicsApi\Ebics\Factories\BankLetterFactory;
use EbicsApi\Ebics\Factories\CertificateX509Factory;
use EbicsApi\Ebics\Factories\SignatureBankLetterFactory;
use EbicsApi\Ebics\Models\Bank;
use EbicsApi\Ebics\Models\BankLetter;
use EbicsApi\Ebics\Models\Keyring;
Expand All @@ -12,6 +14,7 @@
use EbicsApi\Ebics\Services\BankLetter\Formatter\PdfBankLetterFormatter;
use EbicsApi\Ebics\Services\BankLetter\Formatter\TxtBankLetterFormatter;
use EbicsApi\Ebics\Services\BankLetterService;
use EbicsApi\Ebics\Services\CryptService;
use EbicsApi\Ebics\Services\DigestResolverV2;
use EbicsApi\Ebics\Services\DigestResolverV3;
use LogicException;
Expand All @@ -27,10 +30,16 @@ final class EbicsBankLetter
{
private BankLetterService $bankLetterService;
private BankLetterFactory $bankLetterFactory;
private CryptService $cryptService;

public function __construct()
{
$this->bankLetterService = new BankLetterService();
$this->cryptService = new CryptService();
$this->bankLetterService = new BankLetterService(
$this->cryptService,
new SignatureBankLetterFactory(),
new CertificateX509Factory()
);
$this->bankLetterFactory = new BankLetterFactory();
}

Expand All @@ -47,9 +56,9 @@ public function __construct()
public function prepareBankLetter(Bank $bank, User $user, Keyring $keyring): BankLetter
{
if (Keyring::VERSION_25 === $keyring->getVersion() || Keyring::VERSION_24 === $keyring->getVersion()) {
$digestResolver = new DigestResolverV2();
$digestResolver = new DigestResolverV2($this->cryptService);
} elseif (Keyring::VERSION_30 === $keyring->getVersion()) {
$digestResolver = new DigestResolverV3();
$digestResolver = new DigestResolverV3($this->cryptService);
} else {
throw new LogicException(sprintf('Version "%s" is not implemented', $keyring->getVersion()));
}
Expand Down
74 changes: 51 additions & 23 deletions src/EbicsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace EbicsApi\Ebics;

use DateTimeInterface;
use EbicsApi\Ebics\Contexts\BTDContext;
use EbicsApi\Ebics\Contexts\BTUContext;
use EbicsApi\Ebics\Contexts\FDLContext;
Expand Down Expand Up @@ -51,11 +52,11 @@
use EbicsApi\Ebics\Models\UploadTransaction;
use EbicsApi\Ebics\Models\User;
use EbicsApi\Ebics\Models\X509\ContentX509Generator;
use EbicsApi\Ebics\Services\BufferFactory;
use EbicsApi\Ebics\Services\CryptService;
use EbicsApi\Ebics\Services\CurlHttpClient;
use EbicsApi\Ebics\Services\XmlService;
use EbicsApi\Ebics\Services\ZipService;
use DateTimeInterface;
use LogicException;

/**
Expand All @@ -81,45 +82,64 @@ final class EbicsClient implements EbicsClientInterface
private HttpClientInterface $httpClient;
private TransactionFactory $transactionFactory;
private SegmentFactory $segmentFactory;
private BufferFactory $bufferFactory;

/**
* Constructor.
*
* @param Bank $bank
* @param User $user
* @param Keyring $keyring
* @param array $options
*/
public function __construct(Bank $bank, User $user, Keyring $keyring)
public function __construct(Bank $bank, User $user, Keyring $keyring, array $options = [])
{
$this->bank = $bank;
$this->user = $user;
$this->keyring = $keyring;

$this->segmentFactory = new SegmentFactory();
$this->cryptService = new CryptService();
$this->zipService = new ZipService();
$this->bufferFactory = new BufferFactory($options['buffer_filename'] ?? 'php://memory');

if (Keyring::VERSION_24 === $keyring->getVersion()) {
$this->requestFactory = new RequestFactoryV24($bank, $user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV24($user, $keyring);
$this->responseHandler = new ResponseHandlerV24();
$this->responseHandler = new ResponseHandlerV24(
$this->segmentFactory,
$this->cryptService,
$this->zipService,
$this->bufferFactory
);
} elseif (Keyring::VERSION_25 === $keyring->getVersion()) {
$this->requestFactory = new RequestFactoryV25($bank, $user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV25($user, $keyring);
$this->responseHandler = new ResponseHandlerV25();
$this->responseHandler = new ResponseHandlerV25(
$this->segmentFactory,
$this->cryptService,
$this->zipService,
$this->bufferFactory
);
} elseif (Keyring::VERSION_30 === $keyring->getVersion()) {
$this->requestFactory = new RequestFactoryV3($bank, $user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV3($user, $keyring);
$this->responseHandler = new ResponseHandlerV3();
$this->responseHandler = new ResponseHandlerV3(
$this->segmentFactory,
$this->cryptService,
$this->zipService,
$this->bufferFactory
);
} else {
throw new LogicException(sprintf('Version "%s" is not implemented', $keyring->getVersion()));
}

$this->cryptService = new CryptService();
$this->xmlService = new XmlService();
$this->zipService = new ZipService();
$this->signatureFactory = new SignatureFactory();
$this->documentFactory = new DocumentFactory();
$this->orderResultFactory = new OrderResultFactory();
$this->transactionFactory = new TransactionFactory();
$this->segmentFactory = new SegmentFactory();
$this->httpClient = new CurlHttpClient();
$this->httpClient = $options['http_client'] ?? new CurlHttpClient();
}

/**
Expand Down Expand Up @@ -1065,19 +1085,35 @@ private function downloadTransaction(callable $requestClosure, callable $ackClos

$this->transferReceipt($transaction, $acknowledged);

$orderDataEncrypted = '';
$orderDataEncoded = $this->bufferFactory->create();
foreach ($transaction->getSegments() as $segment) {
$orderDataEncrypted .= $segment->getOrderData();
$orderDataEncoded->write($segment->getOrderData());
$segment->setOrderData('');
}
$orderDataEncoded->rewind();

$orderDataDecoded = $this->bufferFactory->create();
while (!$orderDataEncoded->eof()) {
$orderDataDecoded->write(base64_decode($orderDataEncoded->read()));
}
$orderDataDecoded->rewind();
unset($orderDataEncoded);

$orderDataCompressed = $this->cryptService->decryptOrderDataCompressed(
$orderDataCompressed = $this->bufferFactory->create();
$this->cryptService->decryptOrderDataCompressed(
$this->keyring,
$orderDataEncrypted,
$orderDataDecoded,
$orderDataCompressed,
$lastSegment->getTransactionKey()
);
$orderData = $this->zipService->uncompress($orderDataCompressed);
unset($orderDataDecoded);

$transaction->setOrderData($orderData);
$orderData = $this->bufferFactory->create();
$this->zipService->uncompress($orderDataCompressed, $orderData);
unset($orderDataCompressed);

$transaction->setOrderData($orderData->readContent());
unset($orderData);

return $transaction;
}
Expand Down Expand Up @@ -1271,14 +1307,6 @@ public function getUser(): User
return $this->user;
}

/**
* @inheritDoc
*/
public function setHttpClient(HttpClientInterface $httpClient): void
{
$this->httpClient = $httpClient;
}

/**
* Get user signature.
*
Expand Down
3 changes: 2 additions & 1 deletion src/Factories/RequestFactoryV24.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use EbicsApi\Ebics\Models\Keyring;
use EbicsApi\Ebics\Models\UploadTransaction;
use EbicsApi\Ebics\Models\User;
use EbicsApi\Ebics\Services\CryptService;
use EbicsApi\Ebics\Services\DigestResolverV2;
use LogicException;

Expand All @@ -30,7 +31,7 @@ public function __construct(Bank $bank, User $user, Keyring $keyring)
$this->authSignatureHandler = new AuthSignatureHandlerV24($keyring);
$this->userSignatureHandler = new UserSignatureHandlerV2($user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV24($user, $keyring);
$this->digestResolver = new DigestResolverV2();
$this->digestResolver = new DigestResolverV2(new CryptService());
parent::__construct($bank, $user, $keyring);
}

Expand Down
3 changes: 2 additions & 1 deletion src/Factories/RequestFactoryV25.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use EbicsApi\Ebics\Models\UploadTransaction;
use EbicsApi\Ebics\Models\User;
use EbicsApi\Ebics\Models\UserSignature;
use EbicsApi\Ebics\Services\CryptService;
use EbicsApi\Ebics\Services\DigestResolverV2;
use LogicException;

Expand All @@ -39,7 +40,7 @@ public function __construct(Bank $bank, User $user, Keyring $keyring)
$this->authSignatureHandler = new AuthSignatureHandlerV25($keyring);
$this->userSignatureHandler = new UserSignatureHandlerV2($user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV25($user, $keyring);
$this->digestResolver = new DigestResolverV2();
$this->digestResolver = new DigestResolverV2(new CryptService());
parent::__construct($bank, $user, $keyring);
}

Expand Down
3 changes: 2 additions & 1 deletion src/Factories/RequestFactoryV3.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use EbicsApi\Ebics\Models\UploadTransaction;
use EbicsApi\Ebics\Models\User;
use EbicsApi\Ebics\Models\UserSignature;
use EbicsApi\Ebics\Services\CryptService;
use EbicsApi\Ebics\Services\DigestResolverV3;

/**
Expand All @@ -40,7 +41,7 @@ public function __construct(Bank $bank, User $user, Keyring $keyring)
$this->authSignatureHandler = new AuthSignatureHandlerV3($keyring);
$this->userSignatureHandler = new UserSignatureHandlerV3($user, $keyring);
$this->orderDataHandler = new OrderDataHandlerV3($user, $keyring);
$this->digestResolver = new DigestResolverV3();
$this->digestResolver = new DigestResolverV3(new CryptService());
parent::__construct($bank, $user, $keyring);
}

Expand Down
Loading

0 comments on commit 69e188a

Please sign in to comment.