Skip to content

Commit 305177f

Browse files
committed
Aggiunge parser per il corpo del messaggio
Il parser viene utilizzato dal PecMessage per ottenere il corpo del messaggio vero e proprio contenuto in postacert.eml
1 parent 1d72d99 commit 305177f

File tree

3 files changed

+207
-7
lines changed

3 files changed

+207
-7
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
/**
3+
* Questo file fa parte del progetto epod4.
4+
* Il codice è fornito senza alcuna garanzia e distribuito
5+
* con licenza di tipo open source.
6+
* Per le informazioni sui diritti e le informazioni sulla licenza
7+
* consultare il file LICENSE che deve essere distribuito
8+
* insieme a questo codice.
9+
*
10+
* (c) Luca Saba <[email protected]>
11+
*
12+
* Created by PhpStorm.
13+
* User: luca
14+
* Date: 13/12/17
15+
* Time: 10.21
16+
*/
17+
18+
namespace PhpPec\Parser;
19+
20+
/**
21+
* Class PostacertParser
22+
* Effettua il parsing di postacert.eml
23+
* Quello che ci serve è il testo della mail originale.
24+
* @package PhpPec\Parser
25+
*/
26+
class PostacertParser
27+
{
28+
/**
29+
* La regular expression per il boundary di una multipart mime mail
30+
*/
31+
const MULTIPART_REGEX='/Content-Type: multipart\/(mixed|alternative);\s+boundary="([\w\\\'\(\)\+,\.\-@\=\/?]+)"/';
32+
33+
private $sevenBitChars = [
34+
'=20', // space.
35+
'=E2=80=99', // single quote.
36+
'=0A', // line break.
37+
'=A0', // non-breaking space.
38+
'=C2=A0', // non-breaking space.
39+
"=\r\n", // joined line.
40+
'=E2=80=A6', // ellipsis.
41+
'=E2=80=A2', // bullet.
42+
];
43+
44+
private $sevenBitSubstitute = [
45+
' ',
46+
"'",
47+
"\r\n",
48+
' ',
49+
' ',
50+
'',
51+
'',
52+
''
53+
];
54+
55+
/**
56+
* Il contenuto di postacert.eml
57+
* @var string
58+
*/
59+
private $content;
60+
61+
/**
62+
* @var array
63+
*/
64+
private $boundaries;
65+
66+
/**
67+
* @var array
68+
*/
69+
private $types;
70+
71+
/**
72+
* @var array
73+
*/
74+
private $fragments;
75+
76+
public function __construct($content)
77+
{
78+
$this->content = $content;
79+
$this->boundaries = array();
80+
$this->types = array();
81+
$this->fragments = array();
82+
$this->parse();
83+
}
84+
85+
/**
86+
* The body must then contain
87+
* one or more body parts, each preceded by a boundary delimiter line,
88+
* and the last one followed by a closing boundary delimiter line.
89+
* After its boundary delimiter line, each body part then consists of a
90+
* header area, a blank line, and a body area.
91+
* --------------------------------------------------------------------
92+
* The boundary delimiter line is then defined as a line
93+
* consisting entirely of two hyphen characters ("-", decimal value 45)
94+
* followed by the boundary parameter value from the Content-Type header
95+
* field, optional linear whitespace, and a terminating CRLF.
96+
* --------------------------------------------------------------------
97+
* boundary := 0*69<bchars> bcharsnospace
98+
* bchars := bcharsnospace / " "
99+
* bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
100+
* "+" / "_" / "," / "-" / "." /
101+
* "/" / ":" / "=" / "?"
102+
*/
103+
private function parse()
104+
{
105+
preg_match_all($this::MULTIPART_REGEX, $this->content, $matches);
106+
/**
107+
* $matches dovrebbe essere un array composto da 3 elementi
108+
* $matches[0] contiene tutte le stringhe che combaciano con la regex
109+
* $matches[1] contiene tutti i tipo di multipart
110+
* $matches[2] contiene tutti i boundary
111+
*/
112+
if(count($matches) != 3) {
113+
return;
114+
}
115+
for($i = 0; $i < count($matches[0]); $i++) {
116+
$this->boundaries[] = '--'.$matches[2][$i];
117+
$this->types[] = $matches[1][$i];
118+
}
119+
120+
/**
121+
* Leggo postacert.eml riga per riga alla ricerca dei vari frammenti
122+
*/
123+
$numeroFrammento = 0;
124+
$partiMessaggio = array();
125+
foreach(preg_split("/((\r?\n)|(\r\n?))/", $this->content) as $line){
126+
if(in_array(trim($line), $this->boundaries)) {
127+
$numeroFrammento++;
128+
continue;
129+
}
130+
if(isset($partiMessaggio[$numeroFrammento])) {
131+
$partiMessaggio[$numeroFrammento] .= $line."\n";
132+
} else {
133+
$partiMessaggio[$numeroFrammento] = $line."\n";
134+
}
135+
}
136+
137+
/**
138+
* A questo punto mi servono i frammenti il cui content type sia
139+
* text/plain o text/html
140+
*/
141+
$this->fragments = array();
142+
foreach ($partiMessaggio as $parteMessaggio) {
143+
if(preg_match('/Content-Type: text\/(html|plain)/', $parteMessaggio, $matches)) {
144+
// Ripulisco il frammento dall'eventuale finale di parte
145+
foreach ($this->boundaries as $boundary) {
146+
$parteMessaggio = str_replace("$boundary--\n", '', $parteMessaggio);
147+
}
148+
149+
// Gestisco l'eventuale encoding del contenuto:
150+
preg_match('/Content-Transfer-Encoding: (\w+)/', $parteMessaggio, $encoding);
151+
if(count($encoding) > 0) {
152+
// Elimino l'intestazione della parte del messaggio
153+
$parteMessaggio = trim(preg_replace('/^Content[\w-\s:\/;=]+\n\n/', '', $parteMessaggio));
154+
switch (strtolower($encoding[1])) {
155+
case 'base64':
156+
$parteMessaggio = base64_decode($parteMessaggio);
157+
break;
158+
case '7bit':
159+
//$parteMessaggio = str_replace($this->sevenBitChars, $this->sevenBitSubstitute, $parteMessaggio);
160+
$parteMessaggio = mb_convert_encoding($parteMessaggio, 'UTF-8', 'UTF-7');
161+
break;
162+
case '8bit':
163+
$parteMessaggio = imap_8bit($parteMessaggio);
164+
break;
165+
case 'quoted':
166+
$parteMessaggio = utf8_encode(quoted_printable_decode($parteMessaggio));
167+
break;
168+
default:
169+
$parteMessaggio .= strtolower($encoding[1]);
170+
}
171+
}
172+
173+
$this->fragments[] = [
174+
'contenuto' => $parteMessaggio,
175+
'tipo' => $matches[1]
176+
];
177+
}
178+
}
179+
}
180+
181+
public function getFragments()
182+
{
183+
return $this->fragments;
184+
}
185+
}

src/PhpPec/PecMessage.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Fetch\Attachment;
2121
use Fetch\Message;
2222
use Fetch\Server;
23+
use PhpPec\Parser\PostacertParser;
2324

2425
/**
2526
* Class PecMessage
@@ -32,6 +33,8 @@
3233
*/
3334
class PecMessage extends Message implements PecMessageInterface
3435
{
36+
private $allegatiDiServizio = ['daticert.xml', 'smime.p7s', 'postacert.eml'];
37+
3538
/**
3639
* @var string|null
3740
*/
@@ -136,14 +139,19 @@ function realeMittente()
136139

137140
/**
138141
* Il messaggio originale è contenuto in un allegato della busta PEC.
139-
* Questa funzione dovrebbe restituirne il contenuto
142+
* Questa funzione dovrebbe restituirne il contenuto.
143+
* Gli allegati sono contenuti direttamente nella busta, quindi non
144+
* è necessario estrarli dal messaggio originale
140145
*
141146
* @param bool $inHtml Se true, il metodo tenta di restituire la versione HTML del messagio
142-
* @return null|string
147+
* @return null|array
143148
*/
144-
function getTestoOriginale($inHtml = false)
149+
function getTestiOriginali($inHtml = false)
145150
{
146-
// TODO: Implement getTestoOriginale() method.
151+
$postacert = $this->getAttachments('postacert.eml');
152+
/* @var Attachment $postacert */
153+
$parser = new PostacertParser($postacert->getData());
154+
return $parser->getFragments();
147155
}
148156

149157
/**
@@ -158,7 +166,14 @@ function getTestoOriginale($inHtml = false)
158166
*/
159167
function getAllegati()
160168
{
161-
// TODO: Implement getAllegati() method.
169+
$allegati = array();
170+
foreach ($this->getAttachments() as $attachment) {
171+
if(! in_array($attachment->getFileName(), $this->allegatiDiServizio)) {
172+
$allegati[] = $attachment;
173+
}
174+
}
175+
176+
return $allegati;
162177
}
163178

164179
/**

src/PhpPec/PecMessageInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ function realeMittente();
5050
* Questa funzione dovrebbe restituirne il contenuto
5151
*
5252
* @param bool $inHtml Se true, il metodo tenta di restituire la versione HTML del messagio
53-
* @return null|string
53+
* @return null|array
5454
*/
55-
function getTestoOriginale($inHtml = false);
55+
function getTestiOriginali($inHtml = false);
5656

5757
/**
5858
* Restituisce gli allegati originali

0 commit comments

Comments
 (0)