|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* balloon |
|
7
|
|
|
* |
|
8
|
|
|
* @copyright Copryright (c) 2012-2018 gyselroth GmbH (https://gyselroth.com) |
|
9
|
|
|
* @license GPL-3.0 https://opensource.org/licenses/GPL-3.0 |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
namespace Balloon\Filesystem\Storage\Adapter\Smb; |
|
13
|
|
|
|
|
14
|
|
|
use Balloon\Filesystem\Storage\Adapter\AdapterInterface; |
|
15
|
|
|
use Balloon\Filesystem\Storage\Adapter\Smb; |
|
16
|
|
|
use Icewind\SMB\AnonymousAuth; |
|
17
|
|
|
use Icewind\SMB\BasicAuth; |
|
18
|
|
|
use Icewind\SMB\ServerFactory; |
|
19
|
|
|
use InvalidArgumentException; |
|
20
|
|
|
use ParagonIE\Halite\Symmetric\Crypto as Symmetric; |
|
21
|
|
|
use ParagonIE\Halite\Symmetric\EncryptionKey; |
|
22
|
|
|
use Psr\Log\LoggerInterface; |
|
23
|
|
|
|
|
24
|
|
|
class Factory |
|
25
|
|
|
{ |
|
26
|
|
|
/** |
|
27
|
|
|
* Logger. |
|
28
|
|
|
* |
|
29
|
|
|
* @var LoggerInterface |
|
30
|
|
|
*/ |
|
31
|
|
|
protected $logger; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* Balloon system folder. |
|
35
|
|
|
* |
|
36
|
|
|
* @var string |
|
37
|
|
|
*/ |
|
38
|
|
|
protected $system_folder = '.balloon'; |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* Encryption key. |
|
42
|
|
|
* |
|
43
|
|
|
* @var EncryptionKey |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $key; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* Construct. |
|
49
|
|
|
*/ |
|
50
|
|
|
public function __construct(LoggerInterface $logger, EncryptionKey $key, array $config = []) |
|
51
|
|
|
{ |
|
52
|
|
|
$this->logger = $logger; |
|
53
|
|
|
$this->key = $key; |
|
54
|
|
|
$this->setOptions($config); |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* Create adapter. |
|
59
|
|
|
**/ |
|
60
|
|
|
public function build(array $options): AdapterInterface |
|
61
|
|
|
{ |
|
62
|
|
|
$options = $this->validate($options); |
|
63
|
|
|
|
|
64
|
|
|
$factory = new ServerFactory(); |
|
65
|
|
|
|
|
66
|
|
|
if (!isset($options['username']) || !isset($options['password'])) { |
|
67
|
|
|
$auth = new AnonymousAuth(); |
|
68
|
|
|
} else { |
|
69
|
|
|
$this->logger->debug('decrypt basic auth credentials for username ['.$options['username'].']', [ |
|
70
|
|
|
'category' => get_class($this), |
|
71
|
|
|
]); |
|
72
|
|
|
|
|
73
|
|
|
$options = array_merge(['workgroup' => null], $options); |
|
74
|
|
|
|
|
75
|
|
|
try { |
|
76
|
|
|
$decrypted = Symmetric::decrypt($options['password'], $this->key); |
|
77
|
|
|
$auth = new BasicAuth($options['username'], $options['workgroup'], $decrypted->getString()); |
|
78
|
|
|
} catch (\Exception $e) { |
|
79
|
|
|
$this->logger->error('failed decrypt basic auth credentials, fallback to anonymous auth', [ |
|
80
|
|
|
'category' => get_class($this), |
|
81
|
|
|
'exception' => $e, |
|
82
|
|
|
]); |
|
83
|
|
|
|
|
84
|
|
|
$auth = new AnonymousAuth(); |
|
85
|
|
|
} |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
$smb = $factory->createServer($options['host'], $auth); |
|
89
|
|
|
$share = $smb->getShare($options['share']); |
|
90
|
|
|
|
|
91
|
|
|
return new Smb($share, $this->logger, [ |
|
92
|
|
|
Smb::OPTION_SYSTEM_FOLDER => $this->system_folder, |
|
93
|
|
|
]); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Validate. |
|
98
|
|
|
*/ |
|
99
|
|
|
public function validate(array $options): array |
|
100
|
|
|
{ |
|
101
|
|
|
return Validator::validate($options); |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* Set options. |
|
106
|
|
|
*/ |
|
107
|
|
|
protected function setOptions(array $config = []): self |
|
108
|
|
|
{ |
|
109
|
|
View Code Duplication |
foreach ($config as $option => $value) { |
|
|
|
|
|
|
110
|
|
|
switch ($option) { |
|
111
|
|
|
case 'system_folder': |
|
112
|
|
|
$this->{$option} = (string) $value; |
|
113
|
|
|
|
|
114
|
|
|
break; |
|
115
|
|
|
default: |
|
116
|
|
|
throw new InvalidArgumentException('unknown option '.$option.' given'); |
|
117
|
|
|
} |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
return $this; |
|
121
|
|
|
} |
|
122
|
|
|
} |
|
123
|
|
|
|
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.