FilesDir = ''; } static function GetModelDesc(): ModelDesc { $Desc = new ModelDesc('File'); $Desc->AddString('Name'); $Desc->AddInteger('Size'); $Desc->AddReference('Directory', FileDirectory::GetClassName(), true); $Desc->AddDateTime('Time'); $Desc->AddString('Hash'); $Desc->AddBoolean('Generate'); return $Desc; } function Delete($Id): void { $DbResult = $this->Database->select('File', 'Name', 'Id='.$Id); if ($DbResult->num_rows > 0) { $DbRow = $DbResult->fetch_assoc(); $this->Database->delete('File', 'Id='.$Id); unlink($this->FilesDir.'/'.$Id.'_'.$DbRow['Name']); } } function CreateFromUpload(string $Name): string { // Submited form with file input have to be enctype="multipart/form-data" $Result = 0; if (array_key_exists($Name, $_FILES) and ($_FILES[$Name]['name'] != '')) { if (file_exists($_FILES[$Name]['tmp_name'])) { $FileName = substr($_FILES[$Name]['name'], strrpos($_FILES[$Name]['name'], '/')); $this->Database->query('INSERT INTO File (`Name`, `Size`) VALUES ("'.$FileName.'", '.filesize($_FILES[$Name]['tmp_name']).')'); $InsertId = $this->Database->insert_id; if (move_uploaded_file($_FILES[$Name]['tmp_name'], $this->FilesDir.'/'.$InsertId.'_'.$FileName)) $Result = $InsertId; } } return $Result; } function DetectMimeType(string $FileName): string { $MimeTypes = GetMimeTypes(); $MimeType = pathinfo($FileName, PATHINFO_EXTENSION); $Result = $MimeTypes[$MimeType][0]; return $Result; } function DownloadHash(string $Hash): void { $this->Download('Hash="'.addslashes($Hash).'"'); } function DownloadId(string $Id): void { if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'DownloadById')) echo('Nemáte oprávnění'); $this->Download('Id='.addslashes($Id)); } function Download(string $Where): void { $DbResult = $this->Database->select('File', '*', $Where); if ($DbResult->num_rows > 0) { $DbRow = $DbResult->fetch_assoc(); if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']); else $FileName = $this->FilesDir; $FileName .= $DbRow['Name']; if (file_exists($FileName)) { Header('Content-Type: '.$this->DetectMimeType($FileName)); Header('Content-Disposition: inline; filename="'.$DbRow['Name'].'"'); echo(file_get_contents($FileName)); } else echo('Soubor nenalezen!'); } else echo('Soubor nenalezen!'); } function GetDir(string $Id): string { $DbResult = $this->Database->select('FileDirectory', '*', 'Id='.$Id); $DbRow = $DbResult->fetch_assoc(); if ($DbRow['Parent'] != '') $Result = $this->GetDir($DbRow['Parent']); else $Result = $this->FilesDir; $Result .= $DbRow['Name'].'/'; return $Result; } function GetFullPath(string $Id): string { $DbResult = $this->Database->select('File', '*', 'Id='.addslashes($Id)); if ($DbResult->num_rows > 0) { $DbRow = $DbResult->fetch_assoc(); if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']); else $FileName = $this->FilesDir; $FileName .= $DbRow['Name']; return $FileName; } else echo('Soubor nenalezen!'); } } class PageFile extends Page { function Show(): string { if (array_key_exists('h', $_GET)) { $Hash = $_GET['h']; $this->RawPage = true; ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadHash($Hash); return ''; } else if (array_key_exists('i', $_GET) and is_numeric($_GET['i'])) { $Id = $_GET['i'] * 1; $this->RawPage = true; ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadId($Id); } else return $this->SystemMessage('Chyba', 'Nezadáno id souboru'); return ''; } } class FileDirectory extends Model { static function GetModelDesc(): ModelDesc { $Desc = new ModelDesc('FileDirectory'); $Desc->AddString('Name'); $Desc->AddReference('Parent', FileDirectory::GetClassName(), true); return $Desc; } } class PageFileCheck extends Page { function __construct(System $System) { parent::__construct($System); $this->Title = 'File check'; $this->ParentClass = 'PagePortal'; } function GetAbsolutePath(string $Path): string { $Path = trim($Path); $IsRoot = substr($Path, 0, 1) == '/'; $Path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $Path); $Parts = array_filter(explode(DIRECTORY_SEPARATOR, $Path), 'strlen'); $Absolutes = array(); foreach ($Parts as $Part) { if ('.' == $Part) continue; if ('..' == $Part) { array_pop($Absolutes); } else { $Absolutes[] = $Part; } } $Path = implode(DIRECTORY_SEPARATOR, $Absolutes); if ($IsRoot) $Path = DIRECTORY_SEPARATOR.$Path; return $Path; } function Show(): string { $Output = 'Missing files:
'; if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'Check')) return 'Nemáte oprávnění'; $DbResult = $this->Database->select('File', 'Id'); while ($DbRow = $DbResult->fetch_assoc()) { $Id = $DbRow['Id']; $FileName = $this->GetAbsolutePath(ModuleFile::Cast($this->System->GetModule('File'))->File->GetFullPath($Id)); if (!file_exists($FileName)) $Output .= ''.$FileName.'
'; } return $Output; } } class ModuleFile extends Module { public File $File; function __construct(System $System) { parent::__construct($System); $this->Name = 'File'; $this->Version = '1.0'; $this->Creator = 'Chronos'; $this->License = 'GNU/GPLv3'; $this->Description = 'Base module for file management'; $this->Dependencies = array(ModuleUser::GetName()); $this->Models = array(FileDirectory::GetClassName(), File::GetClassName()); $this->File = new File($this->System); } function DoStart(): void { global $Config; $this->System->RegisterPage(['file'], 'PageFile'); $this->System->RegisterPage(['file-check'], 'PageFileCheck'); $this->File->FilesDir = dirname(__FILE__).'/../../'.$Config['Web']['UploadFileFolder']; $this->System->FormManager->RegisterClass('File', array( 'Title' => 'Soubor', 'Table' => 'File', 'Items' => array( 'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''), 'Directory' => array('Type' => 'TDirectory', 'Caption' => 'Adresář', 'Default' => '', 'Null' => true), 'Size' => array('Type' => 'Integer', 'Caption' => 'Velikost', 'Default' => ''), 'Time' => array('Type' => 'DateTime', 'Caption' => 'Čas vytvoření', 'Default' => ''), 'Hash' => array('Type' => 'String', 'Caption' => 'Haš', 'Default' => ''), 'Invoices' => array('Type' => 'TFinanceInvoiceListFile', 'Caption' => 'Faktury', 'Default' => ''), 'Operations' => array('Type' => 'TFinanceOperationListFile', 'Caption' => 'Operace', 'Default' => ''), 'Contracts' => array('Type' => 'TContractListFile', 'Caption' => 'Smlouvy', 'Default' => ''), 'StockMoves' => array('Type' => 'TStockMoveListFile', 'Caption' => 'Skladové pohyby', 'Default' => ''), ), 'ItemActions' => array( array('Caption' => 'Stáhnout', 'URL' => '/file?i=#RowId'), ), 'Actions' => array( array('Caption' => 'Kontrola souborů', 'URL' => '/file-check'), ), )); $this->System->FormManager->RegisterClass('FileDirectory', array( 'Title' => 'Adresář souborů', 'Table' => 'FileDirectory', 'Items' => array( 'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''), 'Parent' => array('Type' => 'TDirectory', 'Caption' => 'Nadřazený adresář', 'Default' => '', 'Null' => true), 'Files' => array('Type' => 'TFileList', 'Caption' => 'Soubory', 'Default' => ''), 'Subdirectories' => array('Type' => 'TDirectoryList', 'Caption' => 'Podadresáře', 'Default' => ''), ), )); $this->System->FormManager->RegisterFormType('TDirectory', array( 'Type' => 'Reference', 'Table' => 'FileDirectory', 'Id' => 'Id', 'Name' => 'Name', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TFile', array( 'Type' => 'Reference', 'Table' => 'File', 'Id' => 'Id', 'Name' => 'Name', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TFileList', array( 'Type' => 'ManyToOne', 'Table' => 'File', 'Id' => 'Id', 'Ref' => 'Directory', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TDirectoryList', array( 'Type' => 'ManyToOne', 'Table' => 'FileDirectory', 'Id' => 'Id', 'Ref' => 'Parent', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TFinanceInvoiceListFile', array( 'Type' => 'ManyToOne', 'Table' => 'FinanceInvoice', 'Id' => 'Id', 'Ref' => 'File', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TFinanceOperationListFile', array( 'Type' => 'ManyToOne', 'Table' => 'FinanceOperation', 'Id' => 'Id', 'Ref' => 'File', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TContractListFile', array( 'Type' => 'ManyToOne', 'Table' => 'Contract', 'Id' => 'Id', 'Ref' => 'File', 'Filter' => '1', )); $this->System->FormManager->RegisterFormType('TStockMoveListFile', array( 'Type' => 'ManyToOne', 'Table' => 'StockMove', 'Id' => 'Id', 'Ref' => 'File', 'Filter' => '1', )); } static function Cast(Module $Module): ModuleFile { if ($Module instanceof ModuleFile) { return $Module; } throw new Exception('Expected ModuleFile type but got '.gettype($Module)); } }