source: trunk/Modules/File/File.php

Last change on this file was 958, checked in by chronos, 15 months ago
  • Fixed: Numeric check for input values.
File size: 10.1 KB
Line 
1<?php
2
3include_once(dirname(__FILE__).'/MimeTypes.php');
4
5class File extends Model
6{
7 public string $FilesDir;
8
9 function __construct(System $System)
10 {
11 parent::__construct($System);
12 $this->FilesDir = '';
13 }
14
15 static function GetModelDesc(): ModelDesc
16 {
17 $Desc = new ModelDesc('File');
18 $Desc->AddString('Name');
19 $Desc->AddInteger('Size');
20 $Desc->AddReference('Directory', FileDirectory::GetClassName(), true);
21 $Desc->AddDateTime('Time');
22 $Desc->AddString('Hash');
23 $Desc->AddBoolean('Generate');
24 return $Desc;
25 }
26
27 function Delete($Id): void
28 {
29 $DbResult = $this->Database->select('File', 'Name', 'Id='.$Id);
30 if ($DbResult->num_rows > 0)
31 {
32 $DbRow = $DbResult->fetch_assoc();
33 $this->Database->delete('File', 'Id='.$Id);
34 unlink($this->FilesDir.'/'.$Id.'_'.$DbRow['Name']);
35 }
36 }
37
38 function CreateFromUpload(string $Name): string
39 {
40 // Submited form with file input have to be enctype="multipart/form-data"
41 $Result = 0;
42 if (array_key_exists($Name, $_FILES) and ($_FILES[$Name]['name'] != ''))
43 {
44 if (file_exists($_FILES[$Name]['tmp_name']))
45 {
46 $FileName = substr($_FILES[$Name]['name'], strrpos($_FILES[$Name]['name'], '/'));
47 $this->Database->query('INSERT INTO File (`Name`, `Size`) VALUES ("'.$FileName.'", '.filesize($_FILES[$Name]['tmp_name']).')');
48 $InsertId = $this->Database->insert_id;
49 if (move_uploaded_file($_FILES[$Name]['tmp_name'], $this->FilesDir.'/'.$InsertId.'_'.$FileName)) $Result = $InsertId;
50 }
51 }
52 return $Result;
53 }
54
55 function DetectMimeType(string $FileName): string
56 {
57 $MimeTypes = GetMimeTypes();
58 $MimeType = pathinfo($FileName, PATHINFO_EXTENSION);
59 $Result = $MimeTypes[$MimeType][0];
60 return $Result;
61 }
62
63 function DownloadHash(string $Hash): void
64 {
65 $this->Download('Hash="'.addslashes($Hash).'"');
66 }
67
68 function DownloadId(string $Id): void
69 {
70 if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'DownloadById'))
71 echo('Nemáte oprávnění');
72 $this->Download('Id='.addslashes($Id));
73 }
74
75 function Download(string $Where): void
76 {
77 $DbResult = $this->Database->select('File', '*', $Where);
78 if ($DbResult->num_rows > 0)
79 {
80 $DbRow = $DbResult->fetch_assoc();
81 if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']);
82 else $FileName = $this->FilesDir;
83 $FileName .= $DbRow['Name'];
84 if (file_exists($FileName))
85 {
86 Header('Content-Type: '.$this->DetectMimeType($FileName));
87 Header('Content-Disposition: inline; filename="'.$DbRow['Name'].'"');
88 echo(file_get_contents($FileName));
89 } else echo('Soubor nenalezen!');
90 } else echo('Soubor nenalezen!');
91 }
92
93 function GetDir(string $Id): string
94 {
95 $DbResult = $this->Database->select('FileDirectory', '*', 'Id='.$Id);
96 $DbRow = $DbResult->fetch_assoc();
97 if ($DbRow['Parent'] != '') $Result = $this->GetDir($DbRow['Parent']);
98 else $Result = $this->FilesDir;
99 $Result .= $DbRow['Name'].'/';
100 return $Result;
101 }
102
103 function GetFullPath(string $Id): string
104 {
105 $DbResult = $this->Database->select('File', '*', 'Id='.addslashes($Id));
106 if ($DbResult->num_rows > 0)
107 {
108 $DbRow = $DbResult->fetch_assoc();
109 if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']);
110 else $FileName = $this->FilesDir;
111 $FileName .= $DbRow['Name'];
112 return $FileName;
113 } else echo('Soubor nenalezen!');
114 }
115}
116
117class PageFile extends Page
118{
119 function Show(): string
120 {
121 if (array_key_exists('h', $_GET))
122 {
123 $Hash = $_GET['h'];
124 $this->RawPage = true;
125 ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadHash($Hash);
126 return '';
127 }
128 else if (array_key_exists('i', $_GET) and is_numeric($_GET['i']))
129 {
130 $Id = $_GET['i'] * 1;
131 $this->RawPage = true;
132 ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadId($Id);
133 }
134 else return $this->SystemMessage('Chyba', 'Nezadáno id souboru');
135 return '';
136 }
137}
138
139class FileDirectory extends Model
140{
141 static function GetModelDesc(): ModelDesc
142 {
143 $Desc = new ModelDesc('FileDirectory');
144 $Desc->AddString('Name');
145 $Desc->AddReference('Parent', FileDirectory::GetClassName(), true);
146 return $Desc;
147 }
148}
149
150class PageFileCheck extends Page
151{
152 function __construct(System $System)
153 {
154 parent::__construct($System);
155 $this->Title = 'File check';
156 $this->ParentClass = 'PagePortal';
157 }
158
159 function GetAbsolutePath(string $Path): string
160 {
161 $Path = trim($Path);
162 $IsRoot = substr($Path, 0, 1) == '/';
163 $Path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $Path);
164 $Parts = array_filter(explode(DIRECTORY_SEPARATOR, $Path), 'strlen');
165 $Absolutes = array();
166 foreach ($Parts as $Part)
167 {
168 if ('.' == $Part) continue;
169 if ('..' == $Part)
170 {
171 array_pop($Absolutes);
172 } else
173 {
174 $Absolutes[] = $Part;
175 }
176 }
177 $Path = implode(DIRECTORY_SEPARATOR, $Absolutes);
178 if ($IsRoot) $Path = DIRECTORY_SEPARATOR.$Path;
179 return $Path;
180 }
181
182 function Show(): string
183 {
184 $Output = '<strong>Missing files:</strong><br>';
185 if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'Check'))
186 return 'Nemáte oprávnění';
187 $DbResult = $this->Database->select('File', 'Id');
188 while ($DbRow = $DbResult->fetch_assoc())
189 {
190 $Id = $DbRow['Id'];
191 $FileName = $this->GetAbsolutePath(ModuleFile::Cast($this->System->GetModule('File'))->File->GetFullPath($Id));
192 if (!file_exists($FileName))
193 $Output .= '<a href="'.$this->System->Link('/is/?a=view&amp;t=File&amp;i='.$Id).'">'.$FileName.'</a><br>';
194 }
195 return $Output;
196 }
197}
198
199class ModuleFile extends Module
200{
201 public File $File;
202
203 function __construct(System $System)
204 {
205 parent::__construct($System);
206 $this->Name = 'File';
207 $this->Version = '1.0';
208 $this->Creator = 'Chronos';
209 $this->License = 'GNU/GPLv3';
210 $this->Description = 'Base module for file management';
211 $this->Dependencies = array(ModuleUser::GetName());
212 $this->Models = array(FileDirectory::GetClassName(), File::GetClassName());
213
214 $this->File = new File($this->System);
215 }
216
217 function DoStart(): void
218 {
219 global $Config;
220
221 $this->System->RegisterPage(['file'], 'PageFile');
222 $this->System->RegisterPage(['file-check'], 'PageFileCheck');
223 $this->File->FilesDir = dirname(__FILE__).'/../../'.$Config['Web']['UploadFileFolder'];
224 $this->System->FormManager->RegisterClass('File', array(
225 'Title' => 'Soubor',
226 'Table' => 'File',
227 'Items' => array(
228 'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''),
229 'Directory' => array('Type' => 'TDirectory', 'Caption' => 'Adresář', 'Default' => '', 'Null' => true),
230 'Size' => array('Type' => 'Integer', 'Caption' => 'Velikost', 'Default' => ''),
231 'Time' => array('Type' => 'DateTime', 'Caption' => 'Čas vytvoření', 'Default' => ''),
232 'Hash' => array('Type' => 'String', 'Caption' => 'Haš', 'Default' => ''),
233 'Invoices' => array('Type' => 'TFinanceInvoiceListFile', 'Caption' => 'Faktury', 'Default' => ''),
234 'Operations' => array('Type' => 'TFinanceOperationListFile', 'Caption' => 'Operace', 'Default' => ''),
235 'Contracts' => array('Type' => 'TContractListFile', 'Caption' => 'Smlouvy', 'Default' => ''),
236 'StockMoves' => array('Type' => 'TStockMoveListFile', 'Caption' => 'Skladové pohyby', 'Default' => ''),
237 ),
238 'ItemActions' => array(
239 array('Caption' => 'Stáhnout', 'URL' => '/file?i=#RowId'),
240 ),
241 'Actions' => array(
242 array('Caption' => 'Kontrola souborů', 'URL' => '/file-check'),
243 ),
244 ));
245 $this->System->FormManager->RegisterClass('FileDirectory', array(
246 'Title' => 'Adresář souborů',
247 'Table' => 'FileDirectory',
248 'Items' => array(
249 'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''),
250 'Parent' => array('Type' => 'TDirectory', 'Caption' => 'Nadřazený adresář', 'Default' => '', 'Null' => true),
251 'Files' => array('Type' => 'TFileList', 'Caption' => 'Soubory', 'Default' => ''),
252 'Subdirectories' => array('Type' => 'TDirectoryList', 'Caption' => 'Podadresáře', 'Default' => ''),
253 ),
254 ));
255 $this->System->FormManager->RegisterFormType('TDirectory', array(
256 'Type' => 'Reference',
257 'Table' => 'FileDirectory',
258 'Id' => 'Id',
259 'Name' => 'Name',
260 'Filter' => '1',
261 ));
262 $this->System->FormManager->RegisterFormType('TFile', array(
263 'Type' => 'Reference',
264 'Table' => 'File',
265 'Id' => 'Id',
266 'Name' => 'Name',
267 'Filter' => '1',
268 ));
269 $this->System->FormManager->RegisterFormType('TFileList', array(
270 'Type' => 'ManyToOne',
271 'Table' => 'File',
272 'Id' => 'Id',
273 'Ref' => 'Directory',
274 'Filter' => '1',
275 ));
276 $this->System->FormManager->RegisterFormType('TDirectoryList', array(
277 'Type' => 'ManyToOne',
278 'Table' => 'FileDirectory',
279 'Id' => 'Id',
280 'Ref' => 'Parent',
281 'Filter' => '1',
282 ));
283 $this->System->FormManager->RegisterFormType('TFinanceInvoiceListFile', array(
284 'Type' => 'ManyToOne',
285 'Table' => 'FinanceInvoice',
286 'Id' => 'Id',
287 'Ref' => 'File',
288 'Filter' => '1',
289 ));
290 $this->System->FormManager->RegisterFormType('TFinanceOperationListFile', array(
291 'Type' => 'ManyToOne',
292 'Table' => 'FinanceOperation',
293 'Id' => 'Id',
294 'Ref' => 'File',
295 'Filter' => '1',
296 ));
297 $this->System->FormManager->RegisterFormType('TContractListFile', array(
298 'Type' => 'ManyToOne',
299 'Table' => 'Contract',
300 'Id' => 'Id',
301 'Ref' => 'File',
302 'Filter' => '1',
303 ));
304 $this->System->FormManager->RegisterFormType('TStockMoveListFile', array(
305 'Type' => 'ManyToOne',
306 'Table' => 'StockMove',
307 'Id' => 'Id',
308 'Ref' => 'File',
309 'Filter' => '1',
310 ));
311 }
312
313 static function Cast(Module $Module): ModuleFile
314 {
315 if ($Module instanceof ModuleFile)
316 {
317 return $Module;
318 }
319 throw new Exception('Expected ModuleFile type but got '.gettype($Module));
320 }
321}
Note: See TracBrowser for help on using the repository browser.