Non puoi selezionare più di 25 argomenti
Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
559 righe
21 KiB
559 righe
21 KiB
<?php |
|
|
|
class File { |
|
|
|
public static function GetValidName($oldName) { |
|
$newName = ""; |
|
$name = $oldName; |
|
for ($i = 0; $i < strlen($name); $i++) { |
|
$char = substr($name, $i, 1); |
|
if (!preg_match("/^[a-zA-Z0-9]$/", $char)) { |
|
$char = "_"; |
|
} |
|
$newName .= $char; |
|
} |
|
return $newName; |
|
} |
|
|
|
/** |
|
* |
|
* @param type $oldName |
|
* @param type $newExt |
|
* @param type $arrayExt estensioni da controllare di secondo livello nel filename es: array('.pdf','.doc','.zip') |
|
* @return type |
|
*/ |
|
public static function GetValidFilename($oldName, $newExt = "", $arrayExt = array('.pdf')) { |
|
$newName = ""; |
|
$name = $oldName; |
|
$ext = self::GetFilenameExtension($name); |
|
if ($ext != "") { |
|
$name = substr($name, 0, strlen($name) - strlen($ext)); |
|
$ext2 = self::GetFilenameExtension($name); |
|
if (in_array($ext2, $arrayExt)) { |
|
$name = substr($name, 0, strlen($name) - strlen($ext2)); |
|
$ext = $ext2 . $ext; |
|
} |
|
} |
|
for ($i = 0; $i < strlen($name); $i++) { |
|
$char = substr($name, $i, 1); |
|
if (!preg_match("/^[a-zA-Z0-9-]$/", $char)) { |
|
$char = "_"; |
|
} |
|
$newName .= $char; |
|
} |
|
$newName = str_replace(" ", "_", $newName); |
|
$newName .= ($newExt != "" ? $newExt : $ext); |
|
return $newName; |
|
} |
|
|
|
public static function GetFilenameExtension($filename) { |
|
$i = strrpos($filename, "."); |
|
if ($i === false) { |
|
return ""; |
|
} |
|
return substr($filename, $i); |
|
} |
|
|
|
public static function CheckValidityExtension($estensione) { |
|
if ($estensione == "p7m") { |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
/** |
|
* Verifico se il certificato del file firmato p7m è valido e se il codice fiscale del firmatario corrisponde al codice fiscale dell'utente loggato o del codice fiscale passato per riferimento |
|
* @global type $LoggedAccount |
|
* @param type $leggoCertificato |
|
* @param type $codicefiscale |
|
* @return string |
|
*/ |
|
public static function verifyCertificato($leggoCertificato, $codicefiscale = '') { |
|
global $LoggedAccount, $CODICI_ERRORE_UPLOAD_P7M; |
|
if (!DISABLED_SIGNED_CONTROL) { |
|
$return = Utils::initDefaultResponse(); |
|
$cfiscaleFirmatario = ($codicefiscale != "" ? $codicefiscale : $LoggedAccount->CODICE_FISCALE); |
|
$cerco = Utils::tag_contents($leggoCertificato, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----"); |
|
foreach ($cerco as $scorrolefirme) { |
|
$datiCertificatoSearch = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n" . trim($scorrolefirme) . "\n-----END CERTIFICATE-----"); |
|
//echo self::extractCf($datiCertificatoSearch['subject']['serialNumber']); exit(); |
|
if ($cfiscaleFirmatario == self::extractCf($datiCertificatoSearch['subject']['serialNumber'])) { |
|
$verifyValidCertificateDate = self::verifyValidCertificateDate($datiCertificatoSearch['validFrom_time_t'], $datiCertificatoSearch['validTo_time_t']); |
|
if ($verifyValidCertificateDate['esito'] == 1) { |
|
$return['esito'] = 1; |
|
$return['erroreDescrizione'] = ""; |
|
} else { |
|
$return = $verifyValidCertificateDate; |
|
} |
|
return $return; |
|
} else { |
|
$return['esito'] = 202079; |
|
$return['erroreDescrizione'] = $CODICI_ERRORE_UPLOAD_P7M[202079]; |
|
} |
|
} |
|
} else { |
|
$return = Utils::initDefaultResponse(1, ''); |
|
} |
|
|
|
return $return; |
|
} |
|
|
|
/** |
|
* Verifica la scadenza del certificato p7m |
|
* @param type $validFrom |
|
* @param type $validTo |
|
* @return string |
|
*/ |
|
public static function verifyValidCertificateDate($validFrom, $validTo) { |
|
global $CODICI_ERRORE_UPLOAD_P7M; |
|
$dataAttuale = time(); |
|
$return = Utils::initDefaultResponse(); |
|
if ($dataAttuale >= $validFrom && $dataAttuale <= $validTo) { |
|
$return['esito'] = 1; |
|
$return['erroreDescrizione'] = ""; |
|
} else { |
|
$return['esito'] = 2020100; |
|
$return['erroreDescrizione'] = $CODICI_ERRORE_UPLOAD_P7M[2020100]; |
|
} |
|
return $return; |
|
} |
|
|
|
public static function verifyCertificatoRevisore($datiCertificato = "") { |
|
global $LoggedAccount; |
|
$dataAttuale = time(); |
|
$validFrom = $datiCertificato['validFrom_time_t']; |
|
$validTo = $datiCertificato['validTo_time_t']; |
|
if ($dataAttuale >= $validFrom && $dataAttuale <= $validTo) { |
|
$return['esito'] = 1; |
|
} else { |
|
$return['esito'] = -999; |
|
$return['erroreDescrizione'] = "Certificato di firma digitale scaduto"; |
|
} |
|
return $return; |
|
} |
|
|
|
/** |
|
* Estrai li codice fiscale dal tag del certificato p7m |
|
* @param type $codice_fiscale |
|
* @return type |
|
*/ |
|
public static function extractCf($codice_fiscale) { |
|
$cfrevisitedexplode = explode("-", $codice_fiscale); |
|
if ($cfrevisitedexplode[1] == "") { |
|
$cfrevisitedexplode = explode(":", $codice_fiscale); |
|
$cfrevisited = $cfrevisitedexplode[1]; |
|
} else { |
|
$cfrevisited = $cfrevisitedexplode[1]; |
|
} |
|
return $cfrevisited; |
|
} |
|
|
|
/** |
|
* Funzioni controllo file |
|
*/ |
|
/* * *********************************** TEST GIGI ************************************************** */ |
|
// public static function checkFileAllegato($uploadedName = '', $max_file_size = MAX_SIZE_FILE_UPLOAD, $format = 'p7m') { |
|
// $response = Utils::initDefaultResponse(); |
|
// if ($uploadedName != '') { |
|
// if (intval($_FILES[$uploadedName]['size']) <= 0) { |
|
// $response['erroreDescrizione'] = "Dimensione file non consistente"; |
|
// } else if (intval($_FILES[$uploadedName]['size']) > $max_file_size) { |
|
// $response['erroreDescrizione'] = "Dimensione file non consentita"; |
|
// } else if ($_FILES[$uploadedName]['tmp_name'] == "") { |
|
// $response['erroreDescrizione'] = "Nessun file allegato"; |
|
// } else { |
|
// $mymeType = self::extractMimeTypeFromFile($_FILES[$uploadedName]['tmp_name']); |
|
// if (ATTIVA_CONTROLLO_MIME_TYPE && $mymeType != MIME_TYPE) { |
|
// $response['erroreDescrizione'] = "Formato del file non valido!"; |
|
// } else { |
|
// $response['esito'] = 1; |
|
// $response['filesize'] = intval($_FILES[$uploadedName]['size']); |
|
// $response['name'] = $_FILES[$uploadedName]['name']; |
|
// } |
|
// } |
|
// } |
|
// return $response; |
|
// } |
|
|
|
public static function checkFileAllegato($uploadedName = '', $max_file_size = MAX_SIZE_FILE_UPLOAD, $format = 'p7m') { |
|
$response = Utils::initDefaultResponse(); |
|
|
|
if ($uploadedName === '' || !isset($_FILES[$uploadedName])) { |
|
$response['erroreDescrizione'] = "Nessun campo upload trovato"; |
|
return $response; |
|
} |
|
|
|
$f = $_FILES[$uploadedName]; |
|
|
|
// error code PHP |
|
if (!isset($f['error']) || $f['error'] !== UPLOAD_ERR_OK) { |
|
$response['erroreDescrizione'] = "Errore upload (code {$f['error']})"; |
|
return $response; |
|
} |
|
|
|
// size checks |
|
$size = isset($f['size']) ? (int)$f['size'] : 0; |
|
if ($size <= 0) { |
|
$response['erroreDescrizione'] = "Dimensione file non consistente"; |
|
return $response; |
|
} |
|
if ($size > (int)$max_file_size) { |
|
$response['erroreDescrizione'] = "Dimensione file non consentita"; |
|
return $response; |
|
} |
|
|
|
// tmp path |
|
$tmp = isset($f['tmp_name']) ? $f['tmp_name'] : ''; |
|
if ($tmp === '' || !is_uploaded_file($tmp)) { |
|
$response['erroreDescrizione'] = "Nessun file allegato"; |
|
return $response; |
|
} |
|
|
|
// MIME by content |
|
$mime = self::extractMimeTypeFromFile($tmp); |
|
|
|
if (defined('ATTIVA_CONTROLLO_MIME_TYPE') && ATTIVA_CONTROLLO_MIME_TYPE) { |
|
// se hai un solo MIME ammesso (es. application/pdf) usa la tua costante MIME_TYPE |
|
if (defined('MIME_TYPE') && strtolower($mime) !== strtolower(MIME_TYPE)) { |
|
$response['erroreDescrizione'] = "Formato del file non valido!"; |
|
return $response; |
|
} |
|
} |
|
|
|
// Anti-polyglot generico: blocca firme di codice/eseguibili |
|
// if (self::hasForbiddenSignatures($tmp)) { |
|
// $response['erroreDescrizione'] = "File non valido [1]"; //Contenuto sospetto (polyglot/signature proibita) |
|
// return $response; |
|
// } |
|
|
|
// Hardening specifico PDF |
|
if (strtolower($mime) === 'application/pdf') { |
|
if (!self::pdfHeaderOK($tmp)) { |
|
$response['erroreDescrizione'] = "File non valido [2]"; // Header PDF non valido |
|
return $response; |
|
} |
|
// if (!self::pdfEndsAtEOF($tmp)) { |
|
// $response['erroreDescrizione'] = "File non valido [3]"; //Dati extra dopo %%EOF (possibile polyglot) |
|
// return $response; |
|
// } |
|
// if (self::fileContainsPhpTags($tmp)) { |
|
// $response['erroreDescrizione'] = "File non valido [4]"; //Tag PHP rilevati nel PDF |
|
// return $response; |
|
// } |
|
} |
|
|
|
// OK |
|
$response['esito'] = 1; |
|
$response['filesize'] = $size; |
|
$response['name'] = $f['name']; |
|
$response['mime'] = $mime; |
|
return $response; |
|
} |
|
|
|
/** |
|
* Verifico se le dimensioni e MD5 del file temporaneo sono uguali al file copiato |
|
* @param type $tmp_name |
|
* @param type $filePath |
|
* @return type |
|
*/ |
|
public static function checkMd5File($tmp_name = '', $filePath = '') { |
|
$response = false; |
|
if ($tmp_name != '' && $filePath != '') { |
|
$response = (filesize($tmp_name) == filesize($filePath) && md5_file($tmp_name) == md5_file($filePath)); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function getSha256File($tmp_name = '') { |
|
$response = ""; |
|
if ($tmp_name != '') { |
|
$response = hash_file('sha256', $tmp_name); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function checkFileConsistency($filePath = '') { |
|
$response = false; |
|
if ($filePath != '') { |
|
$response = (file_exists($filePath) && filesize($filePath) > 0); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function extractMimeTypeFromFile($uploadedFile = '') { |
|
$response = ""; |
|
$finfo = finfo_open(FILEINFO_MIME_TYPE); |
|
$response = finfo_file($finfo, $uploadedFile); |
|
finfo_close($finfo); |
|
return strtolower($response); |
|
} |
|
|
|
public static function extractExtensionFromFile($uploadedName = '') { |
|
$response = ""; |
|
if ($uploadedName != '' && isset($_FILES[$uploadedName]) && !empty($_FILES[$uploadedName]['name'])) { |
|
$ricavoExt = $_FILES[$uploadedName]['name']; |
|
$file = pathinfo($_FILES[$uploadedName]['name']); |
|
$response = strtolower($file['extension']); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function getValidFilenameFromFile($uploadedName = '') { |
|
$response = ""; |
|
if ($uploadedName != "" && isset($_FILES[$uploadedName])) { |
|
$response = self::GetValidFilename($_FILES[$uploadedName]['name']); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function getFolderFromDomanda($domanda = null, $root_upload = '') { |
|
global $LoggedAccount; |
|
$folder = ''; |
|
if (!empty($domanda) && !empty($domanda->ID) && !empty($domanda->ID_ACCOUNT) && !empty($root_upload) && !empty($LoggedAccount->CODICE_FISCALE)) { |
|
$folder = $root_upload . $domanda->ID . "_" . $LoggedAccount->CODICE_FISCALE; |
|
} |
|
return $folder; |
|
} |
|
|
|
/* * *********************************************************************************** */ |
|
|
|
public static function maxDimension($dimensione = "", $max_file_size = 0) { |
|
return ($dimensione > $max_file_size ? true : false ); |
|
} |
|
|
|
public static function checkTmpName($name = "") { |
|
$response = false; |
|
if ($name != "") { |
|
$response = ($_FILES[$name]['tmp_name'] == "" ? true : false); |
|
} |
|
return $response; |
|
} |
|
|
|
public static function extensionFile($tipo_file = "", $estenzione_file = "p7m") { |
|
return ($tipo_file != $estenzione_file ? true : false ); |
|
} |
|
|
|
public static function md5NameFile($nomeFile = "") { |
|
return ($nomeFile == "" ? "" : md5($nomeFile) ); |
|
} |
|
|
|
public static function createPath($path = "") { |
|
if (is_dir($path) === false) { |
|
mkdir($path, 0755, true); |
|
} |
|
if (is_dir($path) === false) { // controllo se la cartella è stata creata |
|
$path = ''; |
|
} |
|
return $path; |
|
} |
|
|
|
public static function checkCertificatoP7m($fileSource = '', $fileDest = '', $fileDestPem = '', $codicefiscale = '', $hashfile = '') { |
|
global $CODICI_ERRORE_UPLOAD_P7M; |
|
$response = Utils::initDefaultResponse(); |
|
|
|
$fileSourceTMPbase64 = self::setFileNamep7mTMP($fileSource); |
|
self::shellExecBase64($fileSource, $fileSourceTMPbase64); |
|
|
|
if (filesize($fileSourceTMPbase64) > 0) { |
|
$fileSource = $fileSourceTMPbase64; |
|
} else { |
|
unlink($fileSourceTMPbase64); |
|
} |
|
|
|
|
|
self::shellExecCms($fileSource, $fileDest); |
|
$hashestratto = self::md5File($fileDest); |
|
if (filesize($fileDest) > 0) { |
|
if ($hashestratto == $hashfile || DISABLED_HASH_CONTROL) { |
|
self::shellExecPkcs7($fileSource, $fileDestPem); |
|
if (filesize($fileDestPem) > 0) { |
|
self::shellExecX509($fileDestPem); |
|
$leggoCertificato = file_get_contents($fileDestPem); |
|
$response = self::verifyCertificato($leggoCertificato, $codicefiscale); |
|
if ($response['esito'] == 1) { |
|
if (filesize($fileSourceTMPbase64) > 0) { |
|
unlink($fileSourceTMPbase64); |
|
} |
|
} |
|
} else { |
|
$response['esito'] = 2020276; |
|
$response['erroreDescrizione'] = $CODICI_ERRORE_UPLOAD_P7M[2020276]; |
|
} |
|
} else { |
|
$response['esito'] = 2020280; |
|
$response['erroreDescrizione'] = $CODICI_ERRORE_UPLOAD_P7M[2020280]; |
|
} |
|
} else { |
|
$response['esito'] = 2020277; |
|
$response['erroreDescrizione'] = $CODICI_ERRORE_UPLOAD_P7M[2020277]; // . ($fileDest); |
|
} |
|
return $response; |
|
} |
|
|
|
/** |
|
* crea il nome del file temporaneo p7m per utilizzarlo nella decodifica in base64 |
|
* @param type $fileSource |
|
* @return type |
|
*/ |
|
public static function setFileNamep7mTMP($fileSource = '') { |
|
$file = pathinfo($fileSource); |
|
return $file['dirname'] . '/FILETMP_' . $file['basename']; |
|
} |
|
|
|
public static function extractPemFromP7m() { |
|
|
|
} |
|
|
|
public static function shellExecCms($file = "", $fileEstratto = "") { |
|
return shell_exec('openssl cms -verify -noverify -in ' . $file . ' -inform DER -out ' . $fileEstratto); |
|
} |
|
|
|
public static function shellExecPkcs7($file = "", $fileEstrattoPem = "") { |
|
return shell_exec('openssl pkcs7 -inform DER -in ' . $file . ' -print_certs -out ' . $fileEstrattoPem); |
|
} |
|
|
|
public static function shellExecX509($fileEstrattoPem = "") { |
|
return shell_exec('openssl x509 -in ' . $fileEstrattoPem . ' -text -noout'); |
|
} |
|
|
|
public static function md5File($nomeFile = 0) { |
|
return md5_file($nomeFile); |
|
} |
|
|
|
public static function shellExecBase64($file = "", $fileDest = "") { |
|
return shell_exec('base64 -d ' . $file . ' > ' . $fileDest); |
|
//return shell_exec('openssl base64 -d -in '.$file.' -out '.$fileDest); |
|
} |
|
|
|
/** |
|
* in caso di errore viene fatta una copia del file p7m che ha generato l'errore e viene salvato tutto nell'apposita tabella di logs |
|
* @param type $fileName |
|
* @param type $domanda |
|
* @param type $fileFullPath |
|
* @param string $fileFullPathLogsp7m |
|
* @param type $errore |
|
* @param type $fase |
|
* @return type |
|
*/ |
|
public static function copyFileandSaveLogs($fileName = "", $domanda = null, $fileFullPath = "", $fileFullPathLogsp7m = "", $errore = "", $fase = DOCUMENTI_FASE_1) { |
|
$response = Utils::initDefaultResponse(); |
|
if (!empty($fileFullPath) && !empty($fileFullPathLogsp7m) && !empty($domanda) && !empty($fileName)) { |
|
|
|
$folderLOGSP7M = $domanda->generateDirForUpload(ROOT_UPLOAD_PRESENTAZIONE, ROOT_UPLOAD_PRESENTAZIONE_LOGS_P7M); |
|
$fileFullPathLogsp7m = $folderLOGSP7M . "/" . $fileName; |
|
if ($folderLOGSP7M) { |
|
copy($fileFullPath, $fileFullPathLogsp7m); |
|
$logUploadP7m = new LogsP7mFile(); |
|
$logUploadP7m->ID_DOMANDA = $domanda->ID; |
|
$logUploadP7m->ERRORE = $errore; |
|
$logUploadP7m->FILEPATH = $fileFullPathLogsp7m; |
|
$logUploadP7m->FASE = $fase; |
|
$response = $logUploadP7m->Save(); |
|
} else { |
|
$response['erroreDescrizione'] = "Al momento non è possibile allegare il file, contattare un amministratore!"; |
|
} |
|
} |
|
return $response; |
|
} |
|
|
|
public static function deleteFileTemp($fileFullPath = '', $fileFullPathEstratto = '', $fileFullPathEstrattoPem = '') { |
|
|
|
if (!empty($fileFullPath)) { |
|
unlink($fileFullPath); |
|
} |
|
if (!empty($fileFullPathEstratto)) { |
|
unlink($fileFullPathEstratto); |
|
} |
|
if (!empty($fileFullPathEstrattoPem)) { |
|
unlink($fileFullPathEstrattoPem); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
/* =================== helper anti-polyglot =================== */ |
|
|
|
// Firme generiche per bloccare script/eseguibili nascosti in qualunque file |
|
private static function hasForbiddenSignatures(string $path): bool { |
|
$patterns = [ |
|
'/<\?(php|\=|\s)/i', // PHP |
|
'/<script\b/i', // HTML/JS |
|
'/^#!\/bin\/(bash|sh|python|perl)/i', // shebang script |
|
'/^\x7fELF/', // binario Linux |
|
'/^MZ/', // eseguibile Windows (PE) |
|
]; |
|
$fp = @fopen($path, 'rb'); |
|
if (!$fp) return true; |
|
|
|
$overlap = ''; |
|
while (!feof($fp)) { |
|
$chunk = fread($fp, 8192); |
|
if ($chunk === false) break; |
|
$scan = $overlap . $chunk; |
|
|
|
foreach ($patterns as $re) { |
|
if (preg_match($re, $scan)) { |
|
fclose($fp); |
|
return true; |
|
} |
|
} |
|
$overlap = substr($scan, -64); |
|
} |
|
fclose($fp); |
|
return false; |
|
} |
|
|
|
private static function fileContainsPhpTags(string $path): bool { |
|
$fp = @fopen($path, 'rb'); |
|
if (!$fp) return true; |
|
|
|
$overlap = ''; |
|
while (!feof($fp)) { |
|
$chunk = fread($fp, 8192); |
|
if ($chunk === false) break; |
|
$scan = $overlap . $chunk; |
|
|
|
if (preg_match('/<\?(php|\=|\s)/i', $scan)) { |
|
fclose($fp); |
|
return true; |
|
} |
|
$overlap = substr($scan, -10); |
|
} |
|
fclose($fp); |
|
return false; |
|
} |
|
|
|
// Deve iniziare con %PDF-1.[0-7] |
|
private static function pdfHeaderOK(string $path): bool { |
|
$fp = @fopen($path, 'rb'); |
|
if (!$fp) return false; |
|
$head = fread($fp, 8); |
|
fclose($fp); |
|
return ($head !== false) && (bool)preg_match('/^%PDF-1\.[0-7]/', $head); |
|
} |
|
|
|
// L’ultimo %%EOF deve essere realmente a fine file (solo whitespace dopo) |
|
private static function pdfEndsAtEOF(string $path): bool { |
|
$size = filesize($path); |
|
if ($size === false) return false; |
|
|
|
$fp = @fopen($path, 'rb'); |
|
if (!$fp) return false; |
|
|
|
$tailLen = min(65536, $size); |
|
fseek($fp, -$tailLen, SEEK_END); |
|
$tail = fread($fp, $tailLen); |
|
fclose($fp); |
|
if ($tail === false) return false; |
|
|
|
$lastEofPos = strripos($tail, '%%EOF'); |
|
if ($lastEofPos === false) return false; |
|
|
|
$after = substr($tail, $lastEofPos + 5); |
|
// consenti solo spazio, tab, \n, \r, form-feed |
|
$after = preg_replace('/[\x20\x09\x0A\x0D\x0C]+/', '', $after); |
|
return $after === ''; |
|
} |
|
}
|
|
|