| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | namespace LeKoala\Encrypt; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | use Exception; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use SilverStripe\Assets\File; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use SilverStripe\ORM\DataExtension; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use ParagonIE\CipherSweet\CipherSweet; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use ParagonIE\CipherSweet\EncryptedFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * Safe and encrypted content file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  * Also make sure that files are not public assets! => use htaccess | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  * @property bool $Encrypted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  * @property File|EncryptedDBFile $owner | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | class EncryptedDBFile extends DataExtension | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     private static $db = [ | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |         "Encrypted" => "Boolean", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |      * @return EncryptedFile | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 25 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 26 |  |  |     protected function getEncryptedFileInstance() | 
            
                                                                        
                            
            
                                    
            
            
                | 27 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 28 |  |  |         $engine = EncryptHelper::getCipherSweet(); | 
            
                                                                        
                            
            
                                    
            
            
                | 29 |  |  |         $encFile = new EncryptedFile($engine); | 
            
                                                                        
                            
            
                                    
            
            
                | 30 |  |  |         return $encFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |      * Check if the actual file on the filesystem is encrypted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |      * You might also use the Encrypted field that should be accurate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |      * @return boolean | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |     public function isEncrypted() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |         $encFile = $this->getEncryptedFileInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |         $stream = $this->owner->getStream(); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |         return $encFile->isStreamEncrypted($stream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |      * Output file using regular php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |      * @throws Exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |      * @return void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     public function sendDecryptedFile() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |         if (ob_get_level()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |             ob_end_clean(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |         $stream = $this->owner->getStream(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |         if ($this->owner->Encrypted) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |             $encFile = $this->getEncryptedFileInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |             $output = fopen('php://temp', 'w+b'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |             // We need to decrypt stream | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |             if ($encFile->isStreamEncrypted($stream)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |                 $success = $encFile->decryptStream($stream, $output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |                 if (!$success) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |                     throw new Exception("Failed to decrypt stream"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |                 // Rewind first | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |                 rewind($output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |                 fpassthru($output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |             fpassthru($stream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |      * Files are not encrypted automatically | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |      * Calls this method to encrypt them | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |      * @throws Exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |      * @return void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |     public function encryptFileIfNeeded() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         $encFile = $this->getEncryptedFileInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |         if (!$this->owner->exists()) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |             throw new Exception("File does not exist"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         $stream = $this->owner->getStream(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         if (!$stream) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |             throw new Exception("Failed to get stream"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         if (!$encFile->isStreamEncrypted($stream)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |             // php://temp is not a file path, it's a pseudo protocol that always creates a new random temp file when used. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |             $output = fopen('php://temp', 'wb'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |             $success =  $encFile->encryptStream($stream, $output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |             if (!$success) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |                 throw new Exception("Failed to encrypt stream"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |             // dont forget to rewind the stream ! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |             rewind($output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |             // Keep the hash ! encrypting file will change it's content and it would update the hash | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             // This would move the file on the filesystem and mess up FileHash link | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |             $fileResult = $this->owner->setFromStream($output, $this->owner->getFilename(), $this->owner->FileHash); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |             // Mark as encrypted in db | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |             $this->owner->Encrypted =  true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |             $this->owner->write(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |         } elseif ($this->owner->Encrypted) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |             // Stream is not encrypted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |             if ($this->owner->Encrypted) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |                 $this->owner->Encrypted = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |                 $this->owner->write(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 120 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 121 |  |  |  |