Merge pull request #19165 from eileenmcnaughton/pdf
[civicrm-core.git] / CRM / Utils / Verp.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Class to handle encoding and decoding Variable Enveleope Return Path (VERP)
14 * headers.
15 *
16 * @package CRM
17 * @copyright CiviCRM LLC https://civicrm.org/licensing
18 */
19 class CRM_Utils_Verp {
20 /**
21 * Mapping of reserved characters to hex codes
22 * @var array
23 */
24 public static $encodeMap = [
25 '+' => '2B',
26 '@' => '40',
27 ':' => '3A',
28 '%' => '25',
29 '!' => '21',
30 '-' => '2D',
31 '[' => '5B',
32 ']' => '5D',
33 ];
34
35 /**
36 * Mapping of hex codes to reserved characters
37 * @var array
38 */
39 public static $decodeMap = [
40 '40' => '@',
41 '3A' => ':',
42 '25' => '%',
43 '21' => '!',
44 '2D' => '-',
45 '5B' => '[',
46 '5D' => ']',
47 '2B' => '+',
48 ];
49
50 /**
51 * Encode the sender's address with the VERPed recipient.
52 *
53 * @param string $sender
54 * The address of the sender.
55 * @param string $recipient
56 * The address of the recipient.
57 *
58 * @return string
59 * The VERP encoded address
60 */
61 public static function encode($sender, $recipient) {
62 preg_match('/(.+)\@([^\@]+)$/', $sender, $match);
63 $slocal = $match[1];
64 $sdomain = $match[2];
65
66 preg_match('/(.+)\@([^\@]+)$/', $recipient, $match);
67 $rlocal = $match[1] ?? NULL;
68 $rdomain = $match[2] ?? NULL;
69
70 foreach (self::$encodeMap as $char => $code) {
71 $rlocal = preg_replace('/' . preg_quote($char) . '/i', "+$code", $rlocal);
72 $rdomain = preg_replace('/' . preg_quote($char) . '/i', "+$code", $rdomain);
73 }
74
75 return "$slocal-$rlocal=$rdomain@$sdomain";
76 }
77
78 /**
79 * Decode the address and return the sender and recipient as an array.
80 *
81 * @param string $address
82 * The address to be decoded.
83 *
84 * @return array
85 * The tuple ($sender, $recipient)
86 */
87 public static function &verpdecode($address) {
88 preg_match('/^(.+)-([^=]+)=([^\@]+)\@(.+)/', $address, $match);
89
90 $slocal = $match[1];
91 $rlocal = $match[2];
92 $rdomain = $match[3];
93 $sdomain = $match[4];
94
95 foreach (self::$decodeMap as $code => $char) {
96 $rlocal = preg_replace("/+$code/i", $char, $rlocal);
97 $rdomain = preg_replace("/+$code/i", $char, $rdomain);
98 }
99
100 return ["$slocal@$sdomain", "$rlocal@$rdomain"];
101 }
102
103 }