Skip to content

Instantly share code, notes, and snippets.

@csaq5507
Last active January 28, 2021 12:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csaq5507/99610bacc8f8fb6c7687631458a4008d to your computer and use it in GitHub Desktop.
Save csaq5507/99610bacc8f8fb6c7687631458a4008d to your computer and use it in GitHub Desktop.
Sometimes I'm getting fatturas that openssl cant convert because after the header are missing the BOM characters (). I don't know if this is a mistake on my side but nevertheless, if someone is facing the same issue this patch should accept this fatturas as well. This code is a patch of filippotoso/p7m-extractor.
<?php
namespace FilippoToso\P7MExtractor;
use FilippoToso\P7MExtractor\Exceptions\FileNotWritable;
use FilippoToso\P7MExtractor\Exceptions\CouldNotExtractFile;
use FilippoToso\P7MExtractor\Exceptions\P7MNotFound;
use Symfony\Component\Process\Process;
class P7M
{
protected $source;
protected $sourceWithBOM;
protected $destination;
protected $binPath;
public function __construct(string $binPath = null)
{
$this->binPath = $binPath ?? '/usr/bin/openssl';
}
public function setSource(string $source) : self
{
$this->checkSource($source);
$this->source = $source;
return $this;
}
protected function checkSource(string $source)
{
if (!is_readable($source)) {
throw new P7MNotFound(sprintf('Could not find or read p7m `%s`', $source));
}
}
protected function checkBOM(string &$source)
{
$data = file_get_contents($source);
// check if BOM characters are present after the header
if(strpos(chr(239) . chr(187) . chr(191),$data))
file_put_contents("temp.xml.p7m",$data);
else
{
//insert BOM characters after header
$data = explode("<?xml",$data);
$header = $data[0].chr(239) . chr(187) . chr(191);
$body = "<?xml".$data[1];
file_put_contents("temp.xml.p7m",$header.$body);
}
$this->sourceWithBOM = "temp.xml.p7m";
}
public function setDestination(string $destination) : self
{
$this->checkDestination($destination);
$this->destination = $destination;
return $this;
}
protected function checkDestination(string $destination)
{
if (file_exists($destination) && !is_writable($destination)) {
throw new FileNotWritable(sprintf('Could not wrtie file `%s`', $destination));
}
}
public function save()
{
$this->checkSource($this->source);
$this->checkBOM($source);
$this->checkDestination($this->destination);
$process = $this->getProcess();
$process->run();
unlink($this->sourceWithBOM);
if (!$process->isSuccessful()) {
throw new CouldNotExtractFile($process);
}
return true;
}
protected function getProcess() {
$options = [$this->binPath, 'smime', '-verify', '-noverify', '-binary', '-in', $this->sourceWithBOM, '-inform', 'DER', '-out', $this->destination];
return new Process($options);
}
public function get() {
$this->checkSource($this->source);
$this->checkBOM($source);
$originalDestination = $this->destination;
$this->destination = $this->getTemporaryFile();
$process = $this->getProcess();
$process->run();
unlink($this->sourceWithBOM);
if (!$process->isSuccessful()) {
throw new CouldNotExtractFile($process);
}
$content = file_get_contents($this->destination);
$this->destination = $originalDestination;
return $content;
}
protected function getTemporaryFile() {
$tempDir = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR);
return tempnam($tempDir, 'p7m');
}
public static function convert(string $source, string $destination, string $binPath = null)
{
return (new static($binPath))
->setSource($source)
->setDestination($destination)
->save()
;
}
public static function extract(string $source, string $binPath = null)
{
return (new static($binPath))
->setSource($source)
->get()
;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment