Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like EE_Encryption often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use EE_Encryption, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class EE_Encryption |
||
17 | { |
||
18 | |||
19 | /** |
||
20 | * key used for saving the encryption key to the wp_options table |
||
21 | */ |
||
22 | const ENCRYPTION_OPTION_KEY = 'ee_encryption_key'; |
||
23 | |||
24 | /** |
||
25 | * the OPENSSL cipher method used |
||
26 | */ |
||
27 | const OPENSSL_CIPHER_METHOD = 'AES-128-CBC'; |
||
28 | |||
29 | /** |
||
30 | * WP "options_name" used to store a verified available cipher method |
||
31 | */ |
||
32 | const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method'; |
||
33 | |||
34 | /** |
||
35 | * the OPENSSL digest method used |
||
36 | */ |
||
37 | const OPENSSL_DIGEST_METHOD = 'sha512'; |
||
38 | |||
39 | /** |
||
40 | * separates the encrypted text from the initialization vector |
||
41 | */ |
||
42 | const OPENSSL_IV_DELIMITER = ':iv:'; |
||
43 | |||
44 | /** |
||
45 | * appended to text encrypted using the acme encryption |
||
46 | */ |
||
47 | const ACME_ENCRYPTION_FLAG = '::ae'; |
||
48 | |||
49 | |||
50 | |||
51 | /** |
||
52 | * instance of the EE_Encryption object |
||
53 | */ |
||
54 | protected static $_instance; |
||
55 | |||
56 | /** |
||
57 | * @var string $_encryption_key |
||
58 | */ |
||
59 | protected $_encryption_key; |
||
60 | |||
61 | /** |
||
62 | * @var string $cipher_method |
||
63 | */ |
||
64 | private $cipher_method = ''; |
||
65 | |||
66 | /** |
||
67 | * @var array $cipher_methods |
||
68 | */ |
||
69 | private $cipher_methods = array(); |
||
70 | |||
71 | /** |
||
72 | * @var array $digest_methods |
||
73 | */ |
||
74 | private $digest_methods = array(); |
||
75 | |||
76 | /** |
||
77 | * @var boolean $_use_openssl_encrypt |
||
78 | */ |
||
79 | protected $_use_openssl_encrypt = false; |
||
80 | |||
81 | /** |
||
82 | * @var boolean $_use_mcrypt |
||
83 | */ |
||
84 | protected $_use_mcrypt = false; |
||
85 | |||
86 | /** |
||
87 | * @var boolean $_use_base64_encode |
||
88 | */ |
||
89 | protected $_use_base64_encode = false; |
||
90 | |||
91 | |||
92 | |||
93 | /** |
||
94 | * protected constructor to prevent direct creation |
||
95 | */ |
||
96 | protected function __construct() |
||
110 | |||
111 | |||
112 | |||
113 | /** |
||
114 | * singleton method used to instantiate class object |
||
115 | * |
||
116 | * @return EE_Encryption |
||
117 | */ |
||
118 | public static function instance() |
||
126 | |||
127 | |||
128 | |||
129 | /** |
||
130 | * get encryption key |
||
131 | * |
||
132 | * @return string |
||
133 | */ |
||
134 | public function get_encryption_key() |
||
152 | |||
153 | |||
154 | |||
155 | /** |
||
156 | * encrypts data |
||
157 | * |
||
158 | * @param string $text_string - the text to be encrypted |
||
159 | * @return string |
||
160 | * @throws RuntimeException |
||
161 | */ |
||
162 | public function encrypt($text_string = '') |
||
175 | |||
176 | |||
177 | |||
178 | /** |
||
179 | * decrypts data |
||
180 | * |
||
181 | * @param string $encrypted_text - the text to be decrypted |
||
182 | * @return string |
||
183 | * @throws RuntimeException |
||
184 | */ |
||
185 | public function decrypt($encrypted_text = '') |
||
199 | |||
200 | |||
201 | |||
202 | /** |
||
203 | * encodes string with PHP's base64 encoding |
||
204 | * |
||
205 | * @see http://php.net/manual/en/function.base64-encode.php |
||
206 | * @param string $text_string the text to be encoded |
||
207 | * @return string |
||
208 | */ |
||
209 | public function base64_string_encode($text_string = '') |
||
218 | |||
219 | |||
220 | |||
221 | /** |
||
222 | * decodes string that has been encoded with PHP's base64 encoding |
||
223 | * |
||
224 | * @see http://php.net/manual/en/function.base64-encode.php |
||
225 | * @param string $encoded_string the text to be decoded |
||
226 | * @return string |
||
227 | */ |
||
228 | public function base64_string_decode($encoded_string = '') |
||
237 | |||
238 | |||
239 | |||
240 | /** |
||
241 | * encodes url string with PHP's base64 encoding |
||
242 | * |
||
243 | * @see http://php.net/manual/en/function.base64-encode.php |
||
244 | * @param string $text_string the text to be encoded |
||
245 | * @return string |
||
246 | */ |
||
247 | public function base64_url_encode($text_string = '') |
||
258 | |||
259 | |||
260 | |||
261 | /** |
||
262 | * decodes url string that has been encoded with PHP's base64 encoding |
||
263 | * |
||
264 | * @see http://php.net/manual/en/function.base64-encode.php |
||
265 | * @param string $encoded_string the text to be decoded |
||
266 | * @return string |
||
267 | */ |
||
268 | public function base64_url_decode($encoded_string = '') |
||
279 | |||
280 | |||
281 | |||
282 | /** |
||
283 | * encrypts data using PHP's openssl functions |
||
284 | * |
||
285 | * @param string $text_string the text to be encrypted |
||
286 | * @return string |
||
287 | * @throws RuntimeException |
||
288 | */ |
||
289 | protected function openssl_encrypt($text_string = '') |
||
323 | |||
324 | |||
325 | |||
326 | /** |
||
327 | * Returns a cipher method that has been verified to work. |
||
328 | * First checks if the cached cipher has been set already and if so, returns that. |
||
329 | * Then tests the incoming default and returns that if it's good. |
||
330 | * If not, then it retrieves the previously tested and saved cipher method. |
||
331 | * But if that doesn't exist, then calls getAvailableCipherMethod() |
||
332 | * to see what is available on the server, and returns the results. |
||
333 | * |
||
334 | * @param string $cipher_method |
||
335 | * @return string |
||
336 | * @throws RuntimeException |
||
337 | */ |
||
338 | protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD) |
||
339 | { |
||
340 | if($this->cipher_method !== ''){ |
||
341 | return $this->cipher_method; |
||
342 | } |
||
343 | // verify that the default cipher method can produce an initialization vector |
||
344 | if (openssl_cipher_iv_length($cipher_method) === false) { |
||
345 | // nope? okay let's get what we found in the past to work |
||
346 | $cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, ''); |
||
347 | // oops... haven't tested available cipher methods yet |
||
348 | if($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) { |
||
349 | $cipher_method = $this->getAvailableCipherMethod($cipher_method); |
||
350 | } |
||
351 | } |
||
352 | return $cipher_method; |
||
353 | } |
||
354 | |||
355 | |||
356 | |||
357 | /** |
||
358 | * @param string $cipher_method |
||
359 | * @return string |
||
360 | * @throws \RuntimeException |
||
361 | */ |
||
362 | protected function getAvailableCipherMethod($cipher_method) |
||
363 | { |
||
364 | // verify that the incoming cipher method can produce an initialization vector |
||
365 | if (openssl_cipher_iv_length($cipher_method) === false) { |
||
366 | // nope? then check the next cipher in the list of available cipher methods |
||
367 | $cipher_method = next($this->cipher_methods); |
||
368 | // what? there's no list? then generate that list and cache it, |
||
369 | if (empty($this->cipher_methods)) { |
||
370 | $this->cipher_methods = openssl_get_cipher_methods(); |
||
371 | // then grab the first item from the list |
||
372 | $cipher_method = reset($this->cipher_methods); |
||
373 | } |
||
374 | if($cipher_method === false){ |
||
375 | throw new RuntimeException( |
||
376 | esc_html__( |
||
377 | 'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.', |
||
378 | 'event_espresso' |
||
379 | ) |
||
380 | ); |
||
381 | } |
||
382 | // verify that the next cipher method works |
||
383 | return $this->getAvailableCipherMethod($cipher_method); |
||
384 | } |
||
385 | // if we've gotten this far, then we found an available cipher method that works |
||
386 | // so save that for next time |
||
387 | update_option( |
||
388 | EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, |
||
389 | $cipher_method |
||
390 | ); |
||
391 | return $cipher_method; |
||
392 | } |
||
393 | |||
394 | |||
395 | |||
396 | /** |
||
397 | * decrypts data that has been encrypted with PHP's openssl functions |
||
398 | * |
||
399 | * @param string $encrypted_text the text to be decrypted |
||
400 | * @return string |
||
401 | * @throws RuntimeException |
||
402 | */ |
||
403 | protected function openssl_decrypt($encrypted_text = '') |
||
433 | |||
434 | |||
435 | |||
436 | /** |
||
437 | * Computes the digest hash value using the specified digest method. |
||
438 | * If that digest method fails to produce a valid hash value, |
||
439 | * then we'll grab the next digest method and recursively try again until something works. |
||
440 | * |
||
441 | * @param string $digest_method |
||
442 | * @return string |
||
443 | * @throws RuntimeException |
||
444 | */ |
||
445 | protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD){ |
||
452 | |||
453 | |||
454 | |||
455 | /** |
||
456 | * Returns the NEXT element in the $digest_methods array. |
||
457 | * If the $digest_methods array is empty, then we populate it |
||
458 | * with the available values returned from openssl_get_md_methods(). |
||
459 | * |
||
460 | * @return string |
||
461 | * @throws \RuntimeException |
||
462 | */ |
||
463 | protected function getDigestMethod(){ |
||
479 | |||
480 | |||
481 | /** |
||
482 | * encrypts data for acme servers that didn't bother to install PHP mcrypt |
||
483 | * |
||
484 | * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php |
||
485 | * @param string $text_string the text to be decrypted |
||
486 | * @return string |
||
487 | */ |
||
488 | protected function acme_encrypt($text_string = '') |
||
513 | |||
514 | |||
515 | |||
516 | /** |
||
517 | * decrypts data for acme servers that didn't bother to install PHP mcrypt |
||
518 | * |
||
519 | * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php |
||
520 | * @param string $encrypted_text the text to be decrypted |
||
521 | * @return string |
||
522 | * @throws RuntimeException |
||
523 | */ |
||
524 | protected function acme_decrypt($encrypted_text = '') |
||
556 | |||
557 | |||
558 | |||
559 | /** |
||
560 | * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906 |
||
561 | * @param $string |
||
562 | * @return bool |
||
563 | */ |
||
564 | protected function valid_base_64($string) |
||
582 | |||
583 | |||
584 | |||
585 | /** |
||
586 | * generate random string |
||
587 | * |
||
588 | * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php |
||
589 | * @param int $length number of characters for random string |
||
590 | * @return string |
||
591 | */ |
||
592 | public function generate_random_string($length = 40) |
||
602 | |||
603 | |||
604 | |||
605 | /** |
||
606 | * encrypts data using PHP's mcrypt functions |
||
607 | * |
||
608 | * @deprecated 4.9.39 |
||
609 | * @param string $text_string |
||
610 | * @internal param $string - the text to be encrypted |
||
611 | * @return string |
||
612 | * @throws RuntimeException |
||
613 | */ |
||
614 | protected function m_encrypt($text_string = '') |
||
642 | |||
643 | |||
644 | |||
645 | /** |
||
646 | * decrypts data that has been encrypted with PHP's mcrypt functions |
||
647 | * |
||
648 | * @deprecated 4.9.39 |
||
649 | * @param string $encrypted_text the text to be decrypted |
||
650 | * @return string |
||
651 | * @throws RuntimeException |
||
652 | */ |
||
653 | protected function m_decrypt($encrypted_text = '') |
||
682 | |||
683 | } |
||
684 | /* End of file EE_Encryption.class.php */ |
||
686 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.