@@ -94,7 +94,64 @@ private enum CipherType { AES, DES, TripleDES };
94
94
95
95
#endregion
96
96
97
- #region openssl_encrypt/decrypt
97
+ #region openssl_error_string
98
+
99
+ sealed class ErrorList
100
+ {
101
+ /// <summary>
102
+ /// Stack of error messages.
103
+ /// </summary>
104
+ readonly Stack < string > _messages = new Stack < string > ( ) ;
105
+
106
+ public void Push ( string message )
107
+ {
108
+ _messages . Push ( message ?? throw new ArgumentNullException ( nameof ( message ) ) ) ;
109
+ }
110
+
111
+ public bool TryPop ( out string message )
112
+ {
113
+ if ( _messages . Count != 0 )
114
+ {
115
+ message = _messages . Pop ( ) ;
116
+ return true ;
117
+ }
118
+ else
119
+ {
120
+ message = null ;
121
+ return false ;
122
+ }
123
+ }
124
+ }
125
+
126
+ /// <summary>
127
+ /// Helper method that stores an openssl error message within the current context.
128
+ /// </summary>
129
+ private static void HandleError ( Context ctx , string message )
130
+ {
131
+ ctx . GetStatic < ErrorList > ( ) . Push ( message ) ;
132
+ PhpException . Throw ( PhpError . E_WARNING , message ) ;
133
+ }
134
+
135
+ /// <summary>
136
+ /// Gets the last error from the openSSL functions.
137
+ /// Error messages are queued, so this function should be called multiple times to collect all of the information.
138
+ /// The last error will be the most recent one.
139
+ /// </summary>
140
+ [ return : CastToFalse ]
141
+ public static string openssl_error_string ( Context ctx )
142
+ {
143
+ if ( ctx . TryGetStatic < ErrorList > ( out var list ) && list . TryPop ( out var message ) )
144
+ {
145
+ return message ;
146
+ }
147
+
148
+ // FALSE: no more errors
149
+ return null ;
150
+ }
151
+
152
+ #endregion
153
+
154
+ #region openssl_encrypt, openssl_decrypt
98
155
99
156
private static SymmetricAlgorithm PrepareCipher ( byte [ ] decodedKey , Cipher cipher , byte [ ] iv , Options options )
100
157
{
@@ -174,7 +231,7 @@ public static string openssl_decrypt(Context ctx, PhpString data, string method,
174
231
if ( ! Ciphers . TryGetValue ( method , out var cipherMethod ) )
175
232
{
176
233
// Unknown cipher algorithm.
177
- PhpException . Throw ( PhpError . E_WARNING , Resources . LibResources . openssl_unknown_cipher ) ;
234
+ HandleError ( ctx , Resources . LibResources . openssl_unknown_cipher ) ;
178
235
return default ; // FALSE
179
236
}
180
237
@@ -189,7 +246,7 @@ public static string openssl_decrypt(Context ctx, PhpString data, string method,
189
246
}
190
247
catch ( CryptographicException ex )
191
248
{
192
- PhpException . Throw ( PhpError . E_WARNING , ex . Message ) ;
249
+ HandleError ( ctx , ex . Message ) ;
193
250
return default ; // FALSE
194
251
}
195
252
}
@@ -234,7 +291,7 @@ public static PhpString openssl_encrypt(Context ctx, string data, string method,
234
291
if ( ! Ciphers . TryGetValue ( method , out var cipherMethod ) )
235
292
{
236
293
// Unknown cipher algorithm.
237
- PhpException . Throw ( PhpError . E_WARNING , Resources . LibResources . openssl_unknown_cipher ) ;
294
+ HandleError ( ctx , Resources . LibResources . openssl_unknown_cipher ) ;
238
295
return default ; // FALSE
239
296
}
240
297
@@ -255,7 +312,7 @@ public static PhpString openssl_encrypt(Context ctx, string data, string method,
255
312
}
256
313
catch ( CryptographicException ex )
257
314
{
258
- PhpException . Throw ( PhpError . E_WARNING , ex . Message ) ;
315
+ HandleError ( ctx , ex . Message ) ;
259
316
return default ; // FALSE
260
317
}
261
318
}
0 commit comments