@@ -48,6 +48,53 @@ public static function unescapeAndEncode($uri)
48
48
{
49
49
$ decoded = html_entity_decode ($ uri );
50
50
51
- return strtr (rawurlencode (rawurldecode ($ decoded )), self ::$ dontEncode );
51
+ return self ::encode (self ::decode ($ decoded ));
52
+ }
53
+
54
+ /**
55
+ * Decode a percent-encoded URI
56
+ *
57
+ * @param string $uri
58
+ *
59
+ * @return string
60
+ */
61
+ private static function decode ($ uri )
62
+ {
63
+ return preg_replace_callback ('/%([0-9a-f]{2})/iu ' , function ($ matches ) {
64
+ // Convert percent-encoded codes to uppercase
65
+ $ upper = strtoupper ($ matches [0 ]);
66
+ // Keep excluded characters as-is
67
+ if (array_key_exists ($ upper , self ::$ dontEncode )) {
68
+ return $ upper ;
69
+ }
70
+
71
+ // Otherwise, return the character for this codepoint
72
+ return chr (hexdec ($ matches [1 ]));
73
+ }, $ uri );
74
+ }
75
+
76
+ /**
77
+ * Encode a URI, preserving already-encoded and excluded characters
78
+ *
79
+ * @param string $uri
80
+ *
81
+ * @return string
82
+ */
83
+ private static function encode ($ uri )
84
+ {
85
+ return preg_replace_callback ('/(%[0-9a-f]{2})|./iu ' , function ($ matches ){
86
+ // Keep already-encoded characters as-is
87
+ if (count ($ matches ) > 1 ) {
88
+ return $ matches [0 ];
89
+ }
90
+
91
+ // Keep excluded characters as-is
92
+ if (in_array ($ matches [0 ], self ::$ dontEncode )) {
93
+ return $ matches [0 ];
94
+ }
95
+
96
+ // Otherwise, encode the character
97
+ return rawurlencode ($ matches [0 ]);
98
+ }, $ uri );
52
99
}
53
100
}
0 commit comments