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 | * This file is part of the Icybee package. |
||
5 | * |
||
6 | * (c) Olivier Laviale <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Icybee\Modules\Files\Operation; |
||
13 | |||
14 | use ICanboogie\ErrorCollection; |
||
15 | use ICanBoogie\HTTP\File as HTTPFile; |
||
16 | use ICanBoogie\HTTP\Request; |
||
17 | use ICanBoogie\Operation; |
||
18 | |||
19 | use Icybee\Binding\Core\PrototypedBindings; |
||
20 | use Icybee\Modules\Files\File; |
||
21 | use Icybee\Modules\Files\Module; |
||
22 | |||
23 | /** |
||
24 | * Upload a file to the repository's temporary folder. |
||
25 | * |
||
26 | * @property-read HTTPFile $file The uploaded file. |
||
27 | * @property Module $module |
||
28 | * @property \ICanBoogie\Core|\Icybee\Binding\Core\CoreBindings|\Icybee\Modules\Registry\Binding\CoreBindings $app |
||
29 | */ |
||
30 | class UploadOperation extends Operation |
||
31 | { |
||
32 | use PrototypedBindings; |
||
33 | |||
34 | /** |
||
35 | * @var HTTPFile The target file of the operation. |
||
36 | */ |
||
37 | protected $file; |
||
38 | |||
39 | protected function get_file() |
||
40 | { |
||
41 | return $this->file; |
||
42 | } |
||
43 | |||
44 | /** |
||
45 | * @var array Accepted file types. |
||
46 | */ |
||
47 | protected $accept; |
||
48 | |||
49 | /** |
||
50 | * Controls for the operation: permission(create). |
||
51 | */ |
||
52 | protected function get_controls() |
||
53 | { |
||
54 | return [ |
||
55 | |||
56 | self::CONTROL_PERMISSION => Module::PERMISSION_CREATE |
||
57 | |||
58 | ] + parent::get_controls(); |
||
59 | } |
||
60 | |||
61 | public function action(Request $request) |
||
62 | { |
||
63 | $this->module->clean_temporary_files(); |
||
64 | |||
65 | return parent::action($request); |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Validates the operation if the file upload succeeded. |
||
70 | * |
||
71 | * @inheritdoc |
||
72 | */ |
||
73 | protected function validate(ErrorCollection $errors) |
||
0 ignored issues
–
show
|
|||
74 | { |
||
75 | # |
||
76 | # forces 'application/json' response type |
||
77 | # |
||
78 | |||
79 | $_SERVER['HTTP_ACCEPT'] = 'application/json'; |
||
80 | |||
81 | $this->file = $file = $this->request->files[File::HTTP_FILE]; |
||
82 | |||
83 | if (!$file) |
||
84 | { |
||
85 | $errors->add(SaveOperation::USERFILE, "No file was uploaded."); |
||
86 | |||
87 | return false; |
||
88 | } |
||
89 | |||
90 | $error_message = $file->error_message; |
||
91 | |||
92 | $max_file_size = $this->app->registry["{$this->module->flat_id}.max_file_size"] * 1024; |
||
93 | |||
94 | View Code Duplication | if ($max_file_size && $max_file_size < $file->size) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
95 | { |
||
96 | $error_message = null; |
||
97 | $errors->add( |
||
98 | File::HTTP_FILE, |
||
99 | "Maximum file size is :size Mb", |
||
100 | [ ':size' => round($max_file_size / 1024) ] |
||
101 | ); |
||
102 | } |
||
103 | |||
104 | View Code Duplication | if (!$file->match($this->accept)) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
105 | { |
||
106 | $error_message = null; |
||
107 | $errors->add( |
||
108 | File::HTTP_FILE, |
||
109 | "Only the following file types are accepted: %accepted.", |
||
110 | [ '%accepted' => implode(', ', $this->accept) ] |
||
111 | ); |
||
112 | } |
||
113 | |||
114 | if ($error_message) |
||
115 | { |
||
116 | $errors->add(File::HTTP_FILE, (string) $error_message); |
||
117 | } |
||
118 | |||
119 | return true; |
||
120 | } |
||
121 | |||
122 | protected function process() |
||
0 ignored issues
–
show
process uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
123 | { |
||
124 | $file = $this->file; |
||
125 | $title = $file->unsuffixed_name; |
||
126 | $type = $file->type; |
||
127 | $pathname = $this->create_temporary_file($file); |
||
128 | $relative_pathname = \ICanBoogie\strip_root($pathname); |
||
129 | |||
130 | $this->response['infos'] = null; |
||
131 | |||
132 | if (isset($_SERVER['HTTP_X_USING_FILE_API'])) |
||
133 | { |
||
134 | $size = \ICanBoogie\I18n\format_size($file->size); |
||
135 | |||
136 | $this->response['infos'] = <<<EOT |
||
137 | <ul class="details"> |
||
138 | <li><span title="{$relative_pathname}">{$title}</span></li> |
||
139 | <li>$type</li> |
||
140 | <li>$size</li> |
||
141 | </ul> |
||
142 | EOT; |
||
143 | |||
144 | } |
||
145 | |||
146 | return array_merge($file->to_array(), [ |
||
147 | |||
148 | 'title' => $title, |
||
149 | 'type' => $type, |
||
150 | 'pathname' => $relative_pathname |
||
151 | |||
152 | ]); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Creates temporary file with attached information. |
||
157 | * |
||
158 | * @param HTTPFile $file |
||
159 | * |
||
160 | * @return string |
||
161 | */ |
||
162 | protected function create_temporary_file(HTTPFile $file) |
||
163 | { |
||
164 | $pathname = \ICanBoogie\REPOSITORY . 'tmp' . DIRECTORY_SEPARATOR . \ICanBoogie\generate_v4_uuid() . $file->extension; |
||
165 | |||
166 | $file->move($pathname); |
||
167 | |||
168 | file_put_contents($pathname . '.info', json_encode($file->to_array())); |
||
169 | |||
170 | return $pathname; |
||
171 | } |
||
172 | } |
||
173 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: