This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Directus – <http://getdirectus.com> |
||
5 | * |
||
6 | * @link The canonical repository – <https://github.com/directus/directus> |
||
7 | * @copyright Copyright 2006-2016 RANGER Studio, LLC – <http://rangerstudio.com> |
||
8 | * @license GNU General Public License (v3) – <http://www.gnu.org/copyleft/gpl.html> |
||
9 | */ |
||
10 | |||
11 | namespace Directus\SDK; |
||
12 | |||
13 | use Directus\Config\Config; |
||
14 | use Directus\Database\Connection; |
||
15 | use Directus\Database\TableGateway\BaseTableGateway; |
||
16 | use Directus\Database\TableGateway\DirectusSettingsTableGateway; |
||
17 | use Directus\Filesystem\Files; |
||
18 | use Directus\Filesystem\Filesystem; |
||
19 | use Directus\Filesystem\FilesystemFactory; |
||
20 | use Directus\Hash\HashManager; |
||
21 | use Directus\Hook\Emitter; |
||
22 | use Directus\Util\ArrayUtils; |
||
23 | use Directus\Database\TableSchema; |
||
24 | |||
25 | /** |
||
26 | * Client |
||
27 | * |
||
28 | * @author Welling Guzmán <[email protected]> |
||
29 | */ |
||
30 | class ClientFactory |
||
31 | { |
||
32 | /** |
||
33 | * @var ClientFactory |
||
34 | */ |
||
35 | protected static $instance = null; |
||
36 | |||
37 | /** |
||
38 | * @var Container |
||
39 | */ |
||
40 | protected $container; |
||
41 | |||
42 | /** |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $config = []; |
||
46 | |||
47 | protected $settings = []; |
||
48 | |||
49 | protected $emitter; |
||
50 | |||
51 | protected $files; |
||
52 | |||
53 | /** |
||
54 | * @var array |
||
55 | */ |
||
56 | protected $defaultConfig = [ |
||
57 | 'environment' => 'development', |
||
58 | 'database' => [ |
||
59 | 'driver' => 'pdo_mysql', |
||
60 | 'charset' => 'utf8mb4', |
||
61 | 'port' => 3306 |
||
62 | ], |
||
63 | 'status' => [ |
||
64 | 'column_name' => 'status', |
||
65 | 'deleted_value' => 0, |
||
66 | 'active_value' => 1, |
||
67 | 'draft_value' => 2, |
||
68 | 'mapping' => [ |
||
69 | 0 => [ |
||
70 | 'name' => 'Deleted', |
||
71 | 'text_color' => '#FFFFFF', |
||
72 | 'background_color' => '#F44336', |
||
73 | 'subdued_in_listing' => true, |
||
74 | 'show_listing_badge' => true, |
||
75 | 'hidden_globally' => true, |
||
76 | 'hard_delete' => false, |
||
77 | 'published' => false, |
||
78 | 'sort' => 3 |
||
79 | ], |
||
80 | 1 => [ |
||
81 | 'name' => 'Published', |
||
82 | 'text_color' => '#FFFFFF', |
||
83 | 'background_color' => '#3498DB', |
||
84 | 'subdued_in_listing' => false, |
||
85 | 'show_listing_badge' => false, |
||
86 | 'hidden_globally' => false, |
||
87 | 'hard_delete' => false, |
||
88 | 'published' => true, |
||
89 | 'sort' => 1 |
||
90 | ], |
||
91 | 2 => [ |
||
92 | 'name' => 'Draft', |
||
93 | 'text_color' => '#999999', |
||
94 | 'background_color' => '#EEEEEE', |
||
95 | 'subdued_in_listing' => true, |
||
96 | 'show_listing_badge' => true, |
||
97 | 'hidden_globally' => false, |
||
98 | 'hard_delete' => false, |
||
99 | 'published' => false, |
||
100 | 'sort' => 2 |
||
101 | ] |
||
102 | ] |
||
103 | ], |
||
104 | 'filesystem' => [ |
||
105 | 'adapter' => 'local', |
||
106 | // By default media directory are located at the same level of directus root |
||
107 | // To make them a level up outsite the root directory |
||
108 | // use this instead |
||
109 | // Ex: 'root' => realpath(BASE_PATH.'/../storage/uploads'), |
||
110 | // Note: BASE_PATH constant doesn't end with trailing slash |
||
111 | 'root' => '/storage/uploads', |
||
112 | // This is the url where all the media will be pointing to |
||
113 | // here all assets will be (yourdomain)/storage/uploads |
||
114 | // same with thumbnails (yourdomain)/storage/uploads/thumbs |
||
115 | 'root_url' => '/storage/uploads', |
||
116 | 'root_thumb_url' => '/storage/uploads/thumbs', |
||
117 | // 'key' => 's3-key', |
||
118 | // 'secret' => 's3-key', |
||
119 | // 'region' => 's3-region', |
||
120 | // 'version' => 's3-version', |
||
121 | // 'bucket' => 's3-bucket' |
||
122 | ], |
||
123 | ]; |
||
124 | |||
125 | /** |
||
126 | * @param $userToken |
||
127 | * @param array $options |
||
128 | * |
||
129 | * @return ClientLocal|ClientRemote |
||
130 | */ |
||
131 | 38 | public static function create($userToken, $options = []) |
|
132 | { |
||
133 | 38 | if (static::$instance == null) { |
|
134 | 2 | static::$instance = new static; |
|
135 | 1 | } |
|
136 | |||
137 | 38 | if (!is_array($userToken)) { |
|
138 | 38 | $newClient = static::$instance->createRemoteClient($userToken, $options); |
|
139 | 19 | } else { |
|
140 | $options = $userToken; |
||
141 | $newClient = static::$instance->createLocalClient($options); |
||
142 | } |
||
143 | |||
144 | 38 | return $newClient; |
|
145 | } |
||
146 | |||
147 | /** |
||
148 | * Creates a new local client instance |
||
149 | * |
||
150 | * @param array $options |
||
151 | * |
||
152 | * @return ClientLocal |
||
153 | */ |
||
154 | public function createLocalClient(array $options) |
||
155 | { |
||
156 | $this->container = $container = new Container(); |
||
157 | |||
158 | $options = ArrayUtils::defaults($this->defaultConfig, $options); |
||
159 | $container->set('config', new Config($options)); |
||
160 | |||
161 | $dbConfig = ArrayUtils::get($options, 'database', []); |
||
162 | |||
163 | $config = ArrayUtils::omit($options, 'database'); |
||
164 | // match the actual directus status mapping config key |
||
165 | $config['statusMapping'] = $config['status']['mapping']; |
||
166 | unset($config['status']['mapping']); |
||
167 | |||
168 | if (!defined('STATUS_DELETED_NUM')) { |
||
169 | define('STATUS_DELETED_NUM', ArrayUtils::get($config, 'status.deleted_value', 0)); |
||
170 | } |
||
171 | |||
172 | if (!defined('STATUS_ACTIVE_NUM')) { |
||
173 | define('STATUS_ACTIVE_NUM', ArrayUtils::get($config, 'status.active_value', 1)); |
||
174 | } |
||
175 | |||
176 | if (!defined('STATUS_DRAFT_NUM')) { |
||
177 | define('STATUS_DRAFT_NUM', ArrayUtils::get($config, 'status.draft_value', 2)); |
||
178 | } |
||
179 | |||
180 | if (!defined('STATUS_COLUMN_NAME')) { |
||
181 | define('STATUS_COLUMN_NAME', ArrayUtils::get($config, 'status.column_name', 'status')); |
||
182 | } |
||
183 | |||
184 | if (!defined('DIRECTUS_ENV')) { |
||
185 | define('DIRECTUS_ENV', ArrayUtils::get($config, 'environment', 'development')); |
||
186 | } |
||
187 | |||
188 | $connection = new Connection($dbConfig); |
||
189 | $connection->connect(); |
||
190 | $container->set('connection', $connection); |
||
191 | $container->set('zendDb', $connection); |
||
192 | |||
193 | $acl = new \Directus\Permissions\Acl(); |
||
194 | $acl->setUserId(1); |
||
195 | $acl->setGroupId(1); |
||
196 | $acl->setGroupPrivileges([ |
||
197 | '*' => [ |
||
198 | 'id' => 1, |
||
199 | 'table_name' => '*', |
||
200 | 'group_id' => 1, |
||
201 | 'read_field_blacklist' => [], |
||
202 | 'write_field_blacklist' => [], |
||
203 | 'nav_listed' => 1, |
||
204 | 'status_id' => 0, |
||
205 | 'allow_view' => 2, |
||
206 | 'allow_add' => 1, |
||
207 | 'allow_edit' => 2, |
||
208 | 'allow_delete' => 2, |
||
209 | 'allow_alter' => 1 |
||
210 | ] |
||
211 | ]); |
||
212 | $container->set('acl', $acl); |
||
213 | |||
214 | $schema = new \Directus\Database\Schemas\Sources\MySQLSchema($connection); |
||
215 | $container->set('schemaSource', $schema); |
||
216 | $schema = new \Directus\Database\SchemaManager($schema); |
||
217 | $container->set('schemaManager', $schema); |
||
218 | TableSchema::setSchemaManagerInstance($schema); |
||
219 | TableSchema::setAclInstance($acl); |
||
220 | TableSchema::setConnectionInstance($connection); |
||
221 | TableSchema::setConfig(new Config($config)); |
||
222 | |||
223 | $container->singleton('emitter', function() { |
||
224 | return $this->getEmitter(); |
||
225 | }); |
||
226 | $container->set('files_settings', function(Container $container) { |
||
227 | $adapter = $container->get('connection'); |
||
228 | $acl = $container->get('acl'); |
||
229 | $Settings = new DirectusSettingsTableGateway($adapter, $acl); |
||
0 ignored issues
–
show
|
|||
230 | |||
231 | return $Settings->fetchCollection('files', [ |
||
0 ignored issues
–
show
$Settings does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$ ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
232 | 'thumbnail_size', 'thumbnail_quality', 'thumbnail_crop_enabled' |
||
233 | ]); |
||
234 | }); |
||
235 | $container->set('app.settings', function (Container $container) { |
||
236 | $DirectusSettingsTableGateway = new \Zend\Db\TableGateway\TableGateway('directus_settings', $container->get('zendDb')); |
||
0 ignored issues
–
show
$DirectusSettingsTableGateway does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$ ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
237 | $rowSet = $DirectusSettingsTableGateway->select(); |
||
0 ignored issues
–
show
$DirectusSettingsTableGateway does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$ ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
238 | |||
239 | $settings = []; |
||
240 | foreach ($rowSet as $setting) { |
||
241 | $settings[$setting['collection']][$setting['name']] = $setting['value']; |
||
242 | } |
||
243 | |||
244 | return $settings; |
||
245 | }); |
||
246 | |||
247 | $container->singleton('hashManager', function () { |
||
248 | return new HashManager(); |
||
249 | }); |
||
250 | |||
251 | $container->singleton('files', function() { |
||
252 | return $this->getFiles(); |
||
253 | }); |
||
254 | |||
255 | BaseTableGateway::setHookEmitter($container->get('emitter')); |
||
256 | BaseTableGateway::setContainer($container); |
||
257 | |||
258 | $client = new ClientLocal($connection); |
||
259 | $client->setContainer($container); |
||
260 | |||
261 | return $client; |
||
262 | } |
||
263 | |||
264 | public function getFiles() |
||
265 | { |
||
266 | static $files = null; |
||
267 | if ($files == null) { |
||
268 | $config = $this->container->get('config'); |
||
269 | $filesystemConfig = $config->get('filesystem', []); |
||
270 | $filesystem = new Filesystem(FilesystemFactory::createAdapter($filesystemConfig)); |
||
0 ignored issues
–
show
It seems like
\Directus\Filesystem\Fil...pter($filesystemConfig) can be null ; however, __construct() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
![]() |
|||
271 | $settings = $this->container->get('files_settings'); |
||
272 | $emitter = $this->container->get('emitter'); |
||
273 | $files = new Files($filesystem, $filesystemConfig, $settings, $emitter); |
||
274 | } |
||
275 | |||
276 | return $files; |
||
277 | } |
||
278 | |||
279 | protected function getEmitter() |
||
280 | { |
||
281 | static $emitter = null; |
||
282 | if ($emitter) { |
||
283 | return $emitter; |
||
284 | } |
||
285 | |||
286 | $emitter = new Emitter(); |
||
287 | $acl = $this->container->get('acl'); |
||
288 | $adapter = $this->container->get('connection'); |
||
289 | |||
290 | $emitter->addAction('table.insert.directus_groups', function ($data) use ($acl, $adapter) { |
||
291 | $privilegesTable = new DirectDirectusPrivilegesTableGateway($adapter, $acl); |
||
292 | |||
293 | $privilegesTable->insertPrivilege([ |
||
294 | 'group_id' => $data['id'], |
||
295 | 'allow_view' => 1, |
||
296 | 'allow_add' => 0, |
||
297 | 'allow_edit' => 1, |
||
298 | 'allow_delete' => 0, |
||
299 | 'allow_alter' => 0, |
||
300 | 'table_name' => 'directus_users', |
||
301 | 'read_field_blacklist' => 'token', |
||
302 | 'write_field_blacklist' => 'group,token' |
||
303 | ]); |
||
304 | }); |
||
305 | |||
306 | $emitter->addFilter('table.insert.directus_files:before', function ($payload) { |
||
307 | unset($payload['data']); |
||
308 | $payload['user'] = 1; |
||
309 | |||
310 | return $payload; |
||
311 | }); |
||
312 | |||
313 | // Add file url and thumb url |
||
314 | $config = $this->container->get('config'); |
||
315 | $files = $this->container->get('files'); |
||
316 | $emitter->addFilter('table.select', function ($payload) use ($config, $files) { |
||
317 | $selectState = $payload->attribute('selectState'); |
||
318 | |||
319 | if ($selectState['table'] == 'directus_files') { |
||
320 | $rows = $payload->toArray(); |
||
321 | foreach ($rows as &$row) { |
||
322 | $fileURL = $config->get('filesystem.root_url', ''); |
||
323 | $thumbnailURL = $config->get('filesystem.root_thumb_url', ''); |
||
324 | $thumbnailFilenameParts = explode('.', $row['name']); |
||
325 | $thumbnailExtension = array_pop($thumbnailFilenameParts); |
||
326 | |||
327 | $row['url'] = $fileURL . '/' . $row['name']; |
||
328 | if (in_array($thumbnailExtension, ['tif', 'tiff', 'psd', 'pdf'])) { |
||
329 | $thumbnailExtension = 'jpg'; |
||
330 | } |
||
331 | |||
332 | $thumbnailFilename = $row['id'] . '.' . $thumbnailExtension; |
||
333 | $row['thumbnail_url'] = $thumbnailURL . '/' . $thumbnailFilename; |
||
334 | |||
335 | // filename-ext-100-100-true.jpg |
||
336 | // @TODO: This should be another hook listener |
||
337 | $row['thumbnail_url'] = null; |
||
338 | $filename = implode('.', $thumbnailFilenameParts); |
||
339 | if ($row['type'] == 'embed/vimeo') { |
||
340 | $oldThumbnailFilename = $row['name'] . '-vimeo-220-124-true.jpg'; |
||
341 | } else { |
||
342 | $oldThumbnailFilename = $filename . '-' . $thumbnailExtension . '-160-160-true.jpg'; |
||
343 | } |
||
344 | |||
345 | // 314551321-vimeo-220-124-true.jpg |
||
346 | // hotfix: there's not thumbnail for this file |
||
347 | $row['old_thumbnail_url'] = $thumbnailURL . '/' . $oldThumbnailFilename; |
||
348 | $row['thumbnail_url'] = $thumbnailURL . '/' . $thumbnailFilename; |
||
349 | |||
350 | /* |
||
351 | $embedManager = Bootstrap::get('embedManager'); |
||
352 | $provider = $embedManager->getByType($row['type']); |
||
353 | $row['html'] = null; |
||
354 | if ($provider) { |
||
355 | $row['html'] = $provider->getCode($row); |
||
356 | } |
||
357 | */ |
||
358 | } |
||
359 | |||
360 | $payload->replace($rows); |
||
361 | } |
||
362 | |||
363 | return $payload; |
||
364 | }); |
||
365 | |||
366 | return $emitter; |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Create a new remote client instance |
||
371 | * |
||
372 | * @param $userToken |
||
373 | * @param array $options |
||
374 | * |
||
375 | * @return ClientRemote |
||
376 | */ |
||
377 | 38 | public function createRemoteClient($userToken, array $options = []) |
|
378 | { |
||
379 | 38 | return new ClientRemote($userToken, $options); |
|
380 | } |
||
381 | } |
||
382 |
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.