Files
crm.clientright.ru/erv_ticket/fileupload.php
Fedor 9245768987 🚀 CRM Files Migration & Real-time Features
 Features:
- Migrated ALL files to new S3 structure (Projects, Contacts, Accounts, HelpDesk, Invoice, etc.)
- Added Nextcloud folder buttons to ALL modules
- Fixed Nextcloud editor integration
- WebSocket server for real-time updates
- Redis Pub/Sub integration
- File path manager for organized storage
- Redis caching for performance (Functions.php)

📁 New Structure:
Documents/Project/ProjectName_ID/file_docID.ext
Documents/Contacts/FirstName_LastName_ID/file_docID.ext
Documents/Accounts/AccountName_ID/file_docID.ext

🔧 Technical:
- FilePathManager for standardized paths
- S3StorageService integration
- WebSocket server (Node.js + Docker)
- Redis cache for getBasicModuleInfo()
- Predis library for Redis connectivity

📝 Scripts:
- Migration scripts for all modules
- Test pages for WebSocket/SSE/Polling
- Documentation (MIGRATION_*.md, REDIS_*.md)

🎯 Result: 15,000+ files migrated successfully!
2025-10-24 19:59:28 +03:00

213 lines
8.0 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* ============================================
* FILEUPLOAD.PHP - Загрузка и обработка файлов
* ============================================
*
* БЕЗОПАСНОСТЬ:
* - Генерация безопасных имен файлов
* - Экранирование всех shell команд
* - Валидация типов файлов
* - Защита от command injection
*
* Обновлено: 23.10.2025
*/
header('Content-Type: application/json; charset=utf-8');
$result = array("success" => "false", "message" => "Ошибка обработки", "result" => "");
// Получение данных
$lastname = isset($_POST['lastname']) ? str_replace(' ', '_', $_POST['lastname']) : 'user';
$inputsArray = isset($_POST['files_names']) ? $_POST['files_names'] : array();
$inputLabel = isset($_POST['docs_names']) ? $_POST['docs_names'] : array();
$pdf_page_counts = array();
$img_page_counts = 0;
$pdfFiles = array();
if (empty($inputsArray)) {
$result['message'] = 'Нет файлов для обработки';
echo json_encode($result);
exit;
}
foreach ($inputsArray as $index => $inputsArray_item) {
for ($i = 0; $i < 10; $i++) {
$fileKey = $inputsArray_item . '-' . $i;
if (!isset($_FILES[$fileKey])) {
break; // Нет больше файлов
}
$file = $_FILES[$fileKey];
// Проверка на ошибки загрузки
if (!empty($file['error']) || empty($file['tmp_name'])) {
continue; // Пропускаем проблемный файл
}
if ($file['tmp_name'] == 'none' || !is_uploaded_file($file['tmp_name'])) {
continue;
}
// ✅ ЗАЩИТА: Проверка MIME-type (не расширения!)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
$allowed_mimes = array(
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'application/pdf'
);
if (!in_array($mime_type, $allowed_mimes)) {
continue; // Недопустимый тип файла
}
// ✅ ЗАЩИТА: Генерация БЕЗОПАСНОГО имени файла
$extension = ($mime_type === 'application/pdf') ? 'pdf' : 'jpg';
$safe_name = uniqid('file_', true) . '_' . time() . '.' . $extension;
$upload_path = __DIR__ . '/uploads/';
$full_path = $upload_path . $safe_name;
// Перемещение файла
if (!move_uploaded_file($file['tmp_name'], $full_path)) {
continue; // Не удалось сохранить
}
// Обработка изображений - конвертация в PDF
if ($mime_type !== 'application/pdf') {
$pdf_name = uniqid('pdf_', true) . '_' . time() . '.pdf';
$pdf_path = $upload_path . $pdf_name;
// ✅ ЗАЩИТА: Экранирование путей для shell команды
$safe_input = escapeshellarg($full_path);
$safe_output = escapeshellarg($pdf_path);
// Конвертация изображения в PDF через ImageMagick
$cmd = "convert {$safe_input} {$safe_output} 2>&1";
$output = array();
$return_var = 0;
exec($cmd, $output, $return_var);
if ($return_var === 0 && file_exists($pdf_path)) {
// Успешная конвертация
$pdfFiles[] = $pdf_path;
$img_page_counts++;
// Удаляем оригинальное изображение
@unlink($full_path);
} else {
// Ошибка конвертации - пропускаем файл
@unlink($full_path);
continue;
}
} else {
// Это уже PDF
$pdfFiles[] = $full_path;
$pdf_page_counts[] = get_pdf_count($full_path);
}
}
// Если есть файлы для объединения
if (!empty($pdfFiles)) {
$pages_count = array_sum($pdf_page_counts) + $img_page_counts;
// ✅ ЗАЩИТА: Безопасное имя для результата
$doc_label = translit($inputLabel[$index]);
$safe_lastname = translit($lastname);
$date_str = date('d-m-Y');
$output_name = "{$doc_label}_{$date_str}_{$safe_lastname}_{$pages_count}_CTP.pdf";
$output_path = $upload_path . $output_name;
// ✅ ЗАЩИТА: Экранирование всех путей для Ghostscript
$safe_output_path = escapeshellarg($output_path);
$safe_pdf_files = array_map('escapeshellarg', $pdfFiles);
$files_string = implode(' ', $safe_pdf_files);
// Объединение PDF через Ghostscript
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile={$safe_output_path} {$files_string} 2>&1";
$output = array();
$return_var = 0;
exec($cmd, $output, $return_var);
if ($return_var === 0 && file_exists($output_path)) {
// Успех!
$result['success'] = "true";
$result['message'] = 'uploads/' . $output_name;
// Удаляем временные PDF файлы
foreach ($pdfFiles as $temp_pdf) {
@unlink($temp_pdf);
}
} else {
// Ошибка объединения
$result['message'] = 'Ошибка объединения PDF файлов';
}
} else {
$result['message'] = 'Нет файлов для обработки';
}
}
/**
* Подсчет страниц в PDF файле
*
* @param string $target_pdf Путь к PDF файлу
* @return int Количество страниц
*/
function get_pdf_count($target_pdf) {
// ✅ ЗАЩИТА: Экранирование пути
$safe_path = escapeshellarg($target_pdf);
$cmd = "identify {$safe_path} 2>&1";
$output = array();
$return_var = 0;
exec($cmd, $output, $return_var);
if ($return_var === 0) {
return count($output);
}
return 1; // По умолчанию 1 страница
}
/**
* Транслитерация кириллицы в латиницу
*
* @param string $value Исходная строка
* @return string Транслитерированная строка
*/
function translit($value) {
$converter = array(
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i',
'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n',
'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't',
'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch',
'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '',
'э' => 'e', 'ю' => 'yu', 'я' => 'ya',
'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D',
'Е' => 'E', 'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I',
'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N',
'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T',
'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', 'Ч' => 'Ch',
'Ш' => 'Sh', 'Щ' => 'Sch', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '',
'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya',
);
$value = strtr($value, $converter);
// ✅ ЗАЩИТА: Удаление всех небезопасных символов
$value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
return $value;
}
echo json_encode($result);
?>