Completed
Push — master ( 5550e1...679a13 )
by Costin
01:05
created

FileVault::setAdapter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace SoareCostin\FileVault;
4
5
use Exception;
6
use Illuminate\Support\Str;
7
use Illuminate\Support\Facades\Storage;
8
9
class FileVault
10
{
11
    /**
12
     * The storage disk.
13
     *
14
     * @var string
15
     */
16
    protected $disk;
17
18
    /**
19
     * The encryption key.
20
     *
21
     * @var string
22
     */
23
    protected $key;
24
25
    /**
26
     * The algorithm used for encryption.
27
     *
28
     * @var string
29
     */
30
    protected $cipher;
31
32
    /**
33
     * The storage adapter.
34
     *
35
     * @var string
36
     */
37
    protected $adapter;
38
39
    public function __construct()
40
    {
41
        $this->disk = config('file-vault.disk');
42
        $this->key = config('file-vault.key');
43
        $this->cipher = config('file-vault.cipher');
44
    }
45
46
    /**
47
     * Set the disk where the files are located.
48
     *
49
     * @param  string  $disk
50
     * @return $this
51
     */
52
    public function disk($disk)
53
    {
54
        $this->disk = $disk;
55
56
        return $this;
57
    }
58
59
    /**
60
     * Set the encryption key.
61
     *
62
     * @param  string  $key
63
     * @return $this
64
     */
65
    public function key($key)
66
    {
67
        $this->key = $key;
68
69
        return $this;
70
    }
71
72
    /**
73
     * Create a new encryption key for the given cipher.
74
     *
75
     * @return string
76
     */
77
    public static function generateKey()
78
    {
79
        return random_bytes(config('file-vault.cipher') === 'AES-128-CBC' ? 16 : 32);
80
    }
81
82
    /**
83
     * Encrypt the passed file and saves the result in a new file with ".enc" as suffix.
84
     *
85
     * @param string $sourceFile Path to file that should be encrypted, relative to the storage disk specified
86
     * @param string $destFile   File name where the encryped file should be written to, relative to the storage disk specified
87
     * @return $this
88
     */
89
    public function encrypt($sourceFile, $destFile = null, $deleteSource = true)
90
    {
91
        $this->registerServices();
92
93
        if (is_null($destFile)) {
94
            $destFile = "{$sourceFile}.enc";
95
        }
96
97
        $sourcePath = $this->getFilePath($sourceFile);
98
        $destPath = $this->getFilePath($destFile);
99
100
        // Create a new encrypter instance
101
        $encrypter = new FileEncrypter($this->key, $this->cipher);
102
103
        // If encryption is successful, delete the source file
104
        if ($encrypter->encrypt($sourcePath, $destPath) && $deleteSource) {
105
            Storage::disk($this->disk)->delete($sourceFile);
106
        }
107
108
        return $this;
109
    }
110
111
    public function encryptCopy($sourceFile, $destFile = null)
112
    {
113
        return self::encrypt($sourceFile, $destFile, false);
114
    }
115
116
    /**
117
     * Dencrypt the passed file and saves the result in a new file, removing the
118
     * last 4 characters from file name.
119
     *
120
     * @param string $sourceFile Path to file that should be decrypted
121
     * @param string $destFile   File name where the decryped file should be written to.
122
     * @return $this
123
     */
124
    public function decrypt($sourceFile, $destFile = null, $deleteSource = true)
125
    {
126
        $this->registerServices();
127
128
        if (is_null($destFile)) {
129
            $destFile = Str::endsWith($sourceFile, '.enc')
130
                        ? Str::replaceLast('.enc', '', $sourceFile)
131
                        : $sourceFile.'.dec';
132
        }
133
134
        $sourcePath = $this->getFilePath($sourceFile);
135
        $destPath = $this->getFilePath($destFile);
136
137
        // Create a new encrypter instance
138
        $encrypter = new FileEncrypter($this->key, $this->cipher);
139
140
        // If decryption is successful, delete the source file
141
        if ($encrypter->decrypt($sourcePath, $destPath) && $deleteSource) {
142
            Storage::disk($this->disk)->delete($sourceFile);
143
        }
144
145
        return $this;
146
    }
147
148
    public function decryptCopy($sourceFile, $destFile = null)
149
    {
150
        return self::decrypt($sourceFile, $destFile, false);
151
    }
152
153
    public function streamDecrypt($sourceFile)
154
    {
155
        $this->registerServices();
156
157
        $sourcePath = $this->getFilePath($sourceFile);
158
159
        // Create a new encrypter instance
160
        $encrypter = new FileEncrypter($this->key, $this->cipher);
161
162
        return $encrypter->decrypt($sourcePath, "php://output");
163
    }
164
165
    protected function getFilePath($file)
166
    {
167
        if ($this->isS3File()) {
168
            return "s3://{$this->adapter->getBucket()}/{$file}";
0 ignored issues
show
Bug introduced by
The method getBucket cannot be called on $this->adapter (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
169
        }
170
171
        return Storage::disk($this->disk)->path($file);
172
    }
173
174
    protected function isS3File()
175
    {
176
        return $this->disk == 's3';
177
    }
178
179
    protected function setAdapter()
180
    {
181
        if ($this->adapter) {
182
            return;
183
        }
184
185
        $this->adapter = Storage::disk($this->disk)->getAdapter();
0 ignored issues
show
Bug introduced by
The method getAdapter() does not seem to exist on object<Illuminate\Contra...\Filesystem\Filesystem>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
186
    }
187
188
    protected function registerServices()
189
    {
190
        $this->setAdapter();
191
192
        if ($this->isS3File()) {
193
            $client = $this->adapter->getClient();
0 ignored issues
show
Bug introduced by
The method getClient cannot be called on $this->adapter (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
194
            $client->registerStreamWrapper();
195
        }
196
    }
197
}
198