|
28 | 28 | * @property string type
|
29 | 29 | * @property string content_type
|
30 | 30 | * @property string id
|
| 31 | + * @property string hash |
31 | 32 | * @property string name
|
32 | 33 | * @property string description
|
33 | 34 | * @property string filename
|
|
44 | 45 | * @method string setContentType(string $content_type)
|
45 | 46 | * @method string getId()
|
46 | 47 | * @method string setId(string $id)
|
| 48 | + * @method string getHash() |
| 49 | + * @method string setHash(string $hash) |
47 | 50 | * @method string getSize()
|
48 | 51 | * @method string setSize(integer $size)
|
49 | 52 | * @method string getName()
|
@@ -74,17 +77,18 @@ class Attachment {
|
74 | 77 | * @var array $attributes
|
75 | 78 | */
|
76 | 79 | protected array $attributes = [
|
77 |
| - 'content' => null, |
78 |
| - 'type' => null, |
79 |
| - 'part_number' => 0, |
| 80 | + 'content' => null, |
| 81 | + 'hash' => null, |
| 82 | + 'type' => null, |
| 83 | + 'part_number' => 0, |
80 | 84 | 'content_type' => null,
|
81 |
| - 'id' => null, |
82 |
| - 'name' => null, |
83 |
| - 'filename' => null, |
84 |
| - 'description' => null, |
85 |
| - 'disposition' => null, |
86 |
| - 'img_src' => null, |
87 |
| - 'size' => null, |
| 85 | + 'id' => null, |
| 86 | + 'name' => null, |
| 87 | + 'filename' => null, |
| 88 | + 'description' => null, |
| 89 | + 'disposition' => null, |
| 90 | + 'img_src' => null, |
| 91 | + 'size' => null, |
88 | 92 | ];
|
89 | 93 |
|
90 | 94 | /**
|
@@ -203,10 +207,26 @@ protected function fetch(): void {
|
203 | 207 | $this->content_type = $this->part->content_type;
|
204 | 208 | $this->content = $this->oMessage->decodeString($content, $this->part->encoding);
|
205 | 209 |
|
| 210 | + // Create a hash of the raw part - this can be used to identify the attachment in the message context. However, |
| 211 | + // it is not guaranteed to be unique and collisions are possible. |
| 212 | + // Some additional online resources: |
| 213 | + // - https://en.wikipedia.org/wiki/Hash_collision |
| 214 | + // - https://www.php.net/manual/en/function.hash.php |
| 215 | + // - https://php.watch/articles/php-hash-benchmark |
| 216 | + // Benchmark speeds: |
| 217 | + // -xxh3 ~15.19(GB/s) (requires php-xxhash extension or >= php8.1) |
| 218 | + // -crc32c ~14.12(GB/s) |
| 219 | + // -sha256 ~0.25(GB/s) |
| 220 | + // xxh3 would be nice to use, because of its extra speed and 32 instead of 8 bytes, but it is not compatible with |
| 221 | + // php < 8.1. crc32c is the next fastest and is compatible with php >= 5.1. sha256 is the slowest, but is compatible |
| 222 | + // with php >= 5.1 and is the most likely to be unique. crc32c is the best compromise between speed and uniqueness. |
| 223 | + // Unique enough for our purposes, but not so slow that it could be a bottleneck. |
| 224 | + $this->hash = hash("crc32c", $this->part->getHeader()->raw."\r\n\r\n".$this->part->content); |
| 225 | + |
206 | 226 | if (($id = $this->part->id) !== null) {
|
207 | 227 | $this->id = str_replace(['<', '>'], '', $id);
|
208 |
| - }else{ |
209 |
| - $this->id = hash("sha256", uniqid((string) rand(10000, 99999), true)); |
| 228 | + }else { |
| 229 | + $this->id = $this->hash; |
210 | 230 | }
|
211 | 231 |
|
212 | 232 | $this->size = $this->part->bytes;
|
|
0 commit comments