Completed
Push — master ( 0179b0...cb1a9c )
by Malte
02:07
created

Part::parse()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 36
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 25
c 2
b 0
f 0
dl 0
loc 36
rs 8.8977
cc 6
nc 16
nop 0
1
<?php
2
/*
3
* File: Part.php
4
* Category: -
5
* Author: M.Goldenbaum
6
* Created: 17.09.20 20:38
7
* Updated: -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\PHPIMAP;
14
15
16
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
17
18
/**
19
 * Class Part
20
 *
21
 * @package Webklex\PHPIMAP
22
 */
23
class Part {
24
25
    /**
26
     * Raw part
27
     *
28
     * @var string $raw
29
     */
30
    public $raw = "";
31
32
    /**
33
     * Part type
34
     *
35
     * @var int $type
36
     */
37
    public $type = IMAP::MESSAGE_TYPE_TEXT;
38
39
    /**
40
     * Part content
41
     *
42
     * @var string $content
43
     */
44
    public $content = "";
45
46
    /**
47
     * Part subtype
48
     *
49
     * @var string $subtype
50
     */
51
    public $subtype = null;
52
53
    /**
54
     * Part charset - if available
55
     *
56
     * @var string $charset
57
     */
58
    public $charset = "utf-8";
59
60
    /**
61
     * Part encoding method
62
     *
63
     * @var int $encoding
64
     */
65
    public $encoding = IMAP::MESSAGE_ENC_OTHER;
66
67
    /**
68
     * Alias to check if the part is an attachment
69
     *
70
     * @var boolean $ifdisposition
71
     */
72
    public $ifdisposition = false;
73
74
    /**
75
     * Indicates if the part is an attachment
76
     *
77
     * @var string $disposition
78
     */
79
    public $disposition = null;
80
81
    /**
82
     * Alias to check if the part has a description
83
     *
84
     * @var boolean $ifdescription
85
     */
86
    public $ifdescription = false;
87
88
    /**
89
     * Part description if available
90
     *
91
     * @var string $description
92
     */
93
    public $description = null;
94
95
    /**
96
     * Part filename if available
97
     *
98
     * @var string $filename
99
     */
100
    public $filename = null;
101
102
    /**
103
     * Part name if available
104
     *
105
     * @var string $name
106
     */
107
    public $name = null;
108
109
    /**
110
     * Part id if available
111
     *
112
     * @var string $id
113
     */
114
    public $id = null;
115
116
    /**
117
     * The part number of the current part
118
     *
119
     * @var integer $part_number
120
     */
121
    public $part_number = 0;
122
123
    /**
124
     * Part length in bytes
125
     *
126
     * @var integer $bytes
127
     */
128
    public $bytes = null;
129
130
    /**
131
     * Part content type
132
     *
133
     * @var string|null $content_type
134
     */
135
    public $content_type = null;
136
137
    /**
138
     * @var Header $header
139
     */
140
    private $header = null;
141
142
    /**
143
     * Part constructor.
144
     * @param $raw_part
145
     * @param Header $header
146
     * @param integer $part_number
147
     *
148
     * @throws InvalidMessageDateException
149
     */
150
    public function __construct($raw_part, $header = null, $part_number = 0) {
151
        $this->raw = $raw_part;
152
        $this->header = $header;
153
        $this->part_number = $part_number;
154
        $this->parse();
155
    }
156
157
    /**
158
     * Parse the raw parts
159
     *
160
     * @throws InvalidMessageDateException
161
     */
162
    protected function parse(){
163
        if ($this->header === null) {
164
            $body = $this->findHeaders();
165
        }else{
166
            $body = $this->raw;
167
        }
168
169
        $this->parseSubtype();
170
        $this->parseDisposition();
171
        $this->parseDescription();
172
        $this->parseEncoding();
173
174
        $this->charset = $this->header->get("charset");
175
        $this->name = $this->header->get("name");
176
        $this->filename = $this->header->get("filename");
177
178
        if(!empty($this->header->get("id"))) {
179
            $this->id = $this->header->get("id");
180
        } else if(!empty($this->header->get("x-attachment-id"))){
181
            $this->id = $this->header->get("x-attachment-id");
182
        } else if(!empty($this->header->get("content-id"))){
183
            $this->id = strtr($this->header->get("content-id"), [
0 ignored issues
show
Bug introduced by
It seems like $this->header->get('content-id') can also be of type null; however, parameter $str of strtr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

183
            $this->id = strtr(/** @scrutinizer ignore-type */ $this->header->get("content-id"), [
Loading history...
184
                '<' => '',
185
                '>' => ''
186
            ]);
187
        }
188
189
        if(!empty($this->header->get("content-type"))){
190
            $rawContentType = $this->header->get("content-type");
191
            $contentTypeArray = explode(';', $rawContentType);
192
            $this->content_type = trim($contentTypeArray[0]);
193
        }
194
195
196
        $this->content = trim(rtrim($body));
197
        $this->bytes = strlen($this->content);
198
    }
199
200
    /**
201
     * Find all available headers and return the left over body segment
202
     *
203
     * @return string
204
     * @throws InvalidMessageDateException
205
     */
206
    private function findHeaders(){
207
        $body = $this->raw;
208
        while (($pos = strpos($body, "\r\n")) > 0) {
209
            $body = substr($body, $pos + 2);
210
        }
211
        $headers = substr($this->raw, 0, strlen($body) * -1);
212
        $body = substr($body, 0, -2);
213
214
        $this->header = new Header($headers);
215
216
        return (string) $body;
217
    }
218
219
    /**
220
     * Try to parse the subtype if any is present
221
     */
222
    private function parseSubtype(){
223
        $content_type = $this->header->get("content-type");
224
        if (($pos = strpos($content_type, "/")) !== false){
225
            $this->subtype = substr($content_type, $pos + 1);
226
        }
227
    }
228
229
    /**
230
     * Try to parse the disposition if any is present
231
     */
232
    private function parseDisposition(){
233
        $content_disposition = $this->header->get("content-disposition");
234
        if($content_disposition !== null) {
235
            $this->ifdisposition = true;
236
            $this->disposition = $content_disposition;
237
        }
238
    }
239
240
    /**
241
     * Try to parse the description if any is present
242
     */
243
    private function parseDescription(){
244
        $content_description = $this->header->get("content-description");
245
        if($content_description !== null) {
246
            $this->ifdescription = true;
247
            $this->description = $content_description;
248
        }
249
    }
250
251
    /**
252
     * Try to parse the encoding if any is present
253
     */
254
    private function parseEncoding(){
255
        $encoding = $this->header->get("content-transfer-encoding");
256
        if($encoding !== null) {
257
            switch (strtolower($encoding)) {
258
                case "quoted-printable":
259
                    $this->encoding = IMAP::MESSAGE_ENC_QUOTED_PRINTABLE;
260
                    break;
261
                case "base64":
262
                    $this->encoding = IMAP::MESSAGE_ENC_BASE64;
263
                    break;
264
                case "7bit":
265
                    $this->encoding = IMAP::MESSAGE_ENC_7BIT;
266
                    break;
267
                case "8bit":
268
                    $this->encoding = IMAP::MESSAGE_ENC_8BIT;
269
                    break;
270
                case "binary":
271
                    $this->encoding = IMAP::MESSAGE_ENC_BINARY;
272
                    break;
273
                default:
274
                    $this->encoding = IMAP::MESSAGE_ENC_OTHER;
275
                    break;
276
277
            }
278
        }
279
    }
280
281
}