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:
1 | <?php namespace Wubbajack\Encryption; |
||
21 | class FileEncrypter |
||
22 | { |
||
23 | |||
24 | const CHUNK_BYTES = 8192; |
||
25 | |||
26 | /** |
||
27 | * The encryption key. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $key; |
||
32 | |||
33 | /** |
||
34 | * The algorithm used for encryption. |
||
35 | * |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $cipher = MCRYPT_RIJNDAEL_128; |
||
39 | |||
40 | /** |
||
41 | * The mode used for encryption. |
||
42 | * |
||
43 | * @var string |
||
44 | */ |
||
45 | protected $mode = MCRYPT_MODE_CBC; |
||
46 | |||
47 | /** |
||
48 | * The block size of the cipher. |
||
49 | * |
||
50 | * @var int |
||
51 | */ |
||
52 | protected $block = 16; |
||
53 | |||
54 | /** |
||
55 | * FileEncrypter constructor. |
||
56 | * |
||
57 | * @param $key |
||
58 | */ |
||
59 | public function __construct($key) |
||
63 | |||
64 | /** |
||
65 | * Set the encryption key. |
||
66 | * |
||
67 | * @param string $key |
||
68 | * @return void |
||
69 | */ |
||
70 | public function setKey($key) |
||
74 | |||
75 | /** |
||
76 | * Set the encryption cipher. |
||
77 | * |
||
78 | * @param string $cipher |
||
79 | * @return $this |
||
80 | */ |
||
81 | public function setCipher($cipher) |
||
88 | |||
89 | /** |
||
90 | * Set the encryption mode. |
||
91 | * |
||
92 | * @param string $mode |
||
93 | * @return $this |
||
94 | */ |
||
95 | public function setMode($mode) |
||
102 | |||
103 | /** |
||
104 | * Encrypts a file and returns the checksum of the encrypted file. |
||
105 | * You can use the checksum to verify integrity as this method of encryption (symmetrical) |
||
106 | * doesn't allow for easy integrity verification. |
||
107 | * |
||
108 | * It's not required but highly recommended as an attacker can shift bytes and thus changes the data |
||
109 | * on the encrypted file. |
||
110 | * |
||
111 | * @param string $source |
||
112 | * @param string $target |
||
113 | * @return string The checksum of the encrypted file |
||
114 | * @throws EncryptException |
||
115 | */ |
||
116 | public function encrypt($source, $target) |
||
134 | |||
135 | /** |
||
136 | * Decrypts the source file to a target file. The checksum is an optional parameter |
||
137 | * that can be used to verify integrity of the file some ciphers offer no integrity check of their own. |
||
138 | * |
||
139 | * It's an optional parameter but be warned, the file may have been tampered with by an attacker. |
||
140 | * |
||
141 | * @param EncryptedFile $encryptedFile |
||
142 | * @param string $target |
||
143 | * @return string Path to the target file |
||
144 | * @throws DecryptException |
||
145 | */ |
||
146 | public function decrypt(EncryptedFile $encryptedFile, $target) |
||
165 | |||
166 | /** |
||
167 | * Decrypts a file in a stream, performing the callback on each successive decrypted block. |
||
168 | * If the checksum is provided it checks it against the encrypted file for integrity. |
||
169 | * |
||
170 | * The callback can accept two arguments: |
||
171 | * - $data - A chunk of decrypted data |
||
172 | * - $stream - The resource stream that is decrypting |
||
173 | * |
||
174 | * @param EncryptedFile $encryptedFile |
||
175 | * @param \Closure $callback |
||
176 | * @throws DecryptException |
||
177 | */ |
||
178 | public function streamDecrypt(EncryptedFile $encryptedFile, \Closure $callback) |
||
196 | |||
197 | /** |
||
198 | * Encrypts the file |
||
199 | * |
||
200 | * @param string $source_file |
||
201 | * @param string $target_file |
||
202 | * @param string $iv |
||
203 | * |
||
204 | * @return void |
||
205 | */ |
||
206 | View Code Duplication | protected function encryptFile($source_file, $target_file, $iv) |
|
221 | |||
222 | /** |
||
223 | * Decrypts a source file into a target file |
||
224 | * |
||
225 | * @param string $source |
||
226 | * @param string $target |
||
227 | * @param string $iv |
||
228 | * @param int $padding |
||
229 | * |
||
230 | * @return void |
||
231 | */ |
||
232 | View Code Duplication | protected function decryptFile($source, $target, $iv, $padding = 0) |
|
245 | |||
246 | /** |
||
247 | * Creates a stream that encrypts when written to |
||
248 | * |
||
249 | * @param string $target |
||
250 | * @param array $options |
||
251 | * |
||
252 | * @return resource |
||
253 | * @throws EncryptException |
||
254 | */ |
||
255 | protected function createEncryptionStream($target, array $options) |
||
266 | |||
267 | /** |
||
268 | * Creates a stream that is decrypted when read from |
||
269 | * |
||
270 | * @param string $source |
||
271 | * @param array $options |
||
272 | * |
||
273 | * @return resource |
||
274 | */ |
||
275 | protected function createDecryptionStream($source, array $options) |
||
285 | |||
286 | /** |
||
287 | * Copies a source stream to a target stream. |
||
288 | * If the padding parameter is set it will remove said amount of bytes from the end of the file. |
||
289 | * |
||
290 | * This method does not use stream_copy_to_stream on purpose because this way we have more control |
||
291 | * over the process of moving data from one stream to another. |
||
292 | * |
||
293 | * @param resource $source |
||
294 | * @param resource $target |
||
295 | * @param null|int $padding |
||
296 | * |
||
297 | * @return void |
||
298 | */ |
||
299 | protected function copyStream($source, $target, $padding = null) |
||
313 | |||
314 | /** |
||
315 | * Returns the options for the stream filter |
||
316 | * @param null $iv If no IV is set, one will be created |
||
317 | * |
||
318 | * @return array Returns an array with 'mode','key' and 'iv' |
||
319 | */ |
||
320 | protected function getOptions($iv = null) |
||
332 | |||
333 | /** |
||
334 | * Get the IV size for the cipher. |
||
335 | * |
||
336 | * @return int |
||
337 | */ |
||
338 | protected function getIvSize() |
||
342 | |||
343 | /** |
||
344 | * Returns the encryption cipher for the stream filter |
||
345 | * |
||
346 | * @return string |
||
347 | */ |
||
348 | protected function getEncryptionFilterName() |
||
352 | |||
353 | /** |
||
354 | * Returns the decryption cipher for the stream filter |
||
355 | * |
||
356 | * @return string |
||
357 | */ |
||
358 | protected function getDecryptionFilterName() |
||
362 | |||
363 | /** |
||
364 | * Get the random data source available for the OS. |
||
365 | * |
||
366 | * @return int |
||
367 | */ |
||
368 | protected function getRandomizer() |
||
382 | |||
383 | /** |
||
384 | * Compares the given checksum with the actual file checksum. |
||
385 | * Returns true if they match, false if not |
||
386 | * |
||
387 | * @param string $file |
||
388 | * @param string $checksum |
||
389 | * @return bool |
||
390 | */ |
||
391 | protected function verifyChecksum($file, $checksum) |
||
395 | |||
396 | /** |
||
397 | * Update the block size for the current cipher and mode. |
||
398 | * |
||
399 | * @return void |
||
400 | */ |
||
401 | protected function updateBlockSize() |
||
405 | |||
406 | /** |
||
407 | * Calculates the padding that was added during encryption |
||
408 | * |
||
409 | * @param string $source Path the the source file |
||
410 | * @param string $target Path to the target file |
||
411 | * @return int |
||
412 | */ |
||
413 | protected function calculatePadding($source, $target) |
||
417 | |||
418 | /** |
||
419 | * Calculates the checksum of the file |
||
420 | * |
||
421 | * @param string $file |
||
422 | * @return string |
||
423 | */ |
||
424 | protected function calculateChecksum($file) |
||
428 | } |
||
429 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.