2025-10-21 22:10:47 +03:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Простой редирект на файл в Nextcloud БЕЗ CSRF проверок
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем параметры
|
|
|
|
|
|
$fileName = isset($_GET['fileName']) ? $_GET['fileName'] : '';
|
|
|
|
|
|
$recordId = isset($_GET['recordId']) ? $_GET['recordId'] : '';
|
|
|
|
|
|
|
|
|
|
|
|
// Если fileName содержит полный URL, извлекаем только имя файла
|
|
|
|
|
|
if (strpos($fileName, 'http') === 0) {
|
2025-10-22 18:29:02 +03:00
|
|
|
|
$fileName = urldecode($fileName);
|
|
|
|
|
|
// ИСПРАВЛЕНИЕ: используем правильное извлечение имени файла
|
|
|
|
|
|
$lastSlash = strrpos($fileName, '/');
|
|
|
|
|
|
if ($lastSlash !== false) {
|
|
|
|
|
|
$fileName = substr($fileName, $lastSlash + 1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$fileName = basename($fileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
$fileName = trim($fileName);
|
2025-10-21 22:10:47 +03:00
|
|
|
|
error_log("Nextcloud Editor: Извлечено имя файла из URL: {$fileName}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Настройки Nextcloud
|
|
|
|
|
|
$nextcloudUrl = 'https://office.clientright.ru:8443';
|
|
|
|
|
|
$username = 'admin';
|
|
|
|
|
|
$password = 'office';
|
|
|
|
|
|
|
2025-10-22 18:29:02 +03:00
|
|
|
|
// Подключаемся к БД чтобы получить название проекта
|
|
|
|
|
|
chdir('/var/www/fastuser/data/www/crm.clientright.ru');
|
|
|
|
|
|
require_once 'include/utils/utils.php';
|
|
|
|
|
|
require_once 'include/database/PearDatabase.php';
|
|
|
|
|
|
|
|
|
|
|
|
global $adb;
|
|
|
|
|
|
|
|
|
|
|
|
// Функция для санитизации названия папки
|
|
|
|
|
|
function sanitizeFolderName($name) {
|
|
|
|
|
|
$name = str_replace(['/', '\\', ':', '*', '?', '"', '<', '>', '|', '#'], '_', $name);
|
|
|
|
|
|
$name = preg_replace('/\s+/', '_', $name);
|
|
|
|
|
|
return trim($name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Найдём projectid по связи документа → проекта
|
|
|
|
|
|
$docId = $recordId;
|
|
|
|
|
|
$projectId = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
$sqlProject = "SELECT r.crmid AS projectid
|
|
|
|
|
|
FROM vtiger_senotesrel r
|
|
|
|
|
|
INNER JOIN vtiger_crmentity e ON e.crmid = r.crmid
|
|
|
|
|
|
WHERE r.notesid = ? AND e.setype = 'Project'
|
|
|
|
|
|
ORDER BY r.crmid DESC LIMIT 1";
|
|
|
|
|
|
$resProject = $adb->pquery($sqlProject, [$docId]);
|
|
|
|
|
|
if ($resProject && $adb->num_rows($resProject) > 0) {
|
|
|
|
|
|
$projectRow = $adb->fetchByAssoc($resProject);
|
|
|
|
|
|
$projectId = (string)$projectRow['projectid'];
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
error_log('Nextcloud Editor: DB error while resolving project by document: ' . $e->getMessage());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем название проекта из БД (если нашли projectId)
|
|
|
|
|
|
$projectName = null;
|
|
|
|
|
|
if ($projectId) {
|
|
|
|
|
|
$sql = "SELECT projectname FROM vtiger_project WHERE projectid = ?";
|
|
|
|
|
|
$result = $adb->pquery($sql, [$projectId]);
|
|
|
|
|
|
if ($result && $adb->num_rows($result) > 0) {
|
|
|
|
|
|
$row = $adb->fetchByAssoc($result);
|
|
|
|
|
|
$projectName = sanitizeFolderName($row['projectname']);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Формируем пути к файлу в Nextcloud
|
|
|
|
|
|
// НОВЫЙ формат: crm/crm2/CRM_Active_Files/Documents/{ProjectName}_{ProjectID}/{fileName}
|
|
|
|
|
|
// СТАРЫЙ формат: crm/crm2/CRM_Active_Files/Documents/{DocumentID}/{fileName}
|
|
|
|
|
|
|
|
|
|
|
|
// Вспомогательная функция: кодирование пути по сегментам (WebDAV)
|
|
|
|
|
|
$encodePath = function(array $segments) {
|
|
|
|
|
|
return implode('/', array_map('rawurlencode', $segments));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Список путей для логирования (читаемые) и для запроса (url-encoded)
|
|
|
|
|
|
$humanPaths = [];
|
|
|
|
|
|
$requestPaths = [];
|
|
|
|
|
|
|
|
|
|
|
|
if ($projectName && $projectId) {
|
|
|
|
|
|
$humanPaths[] = "crm/crm2/CRM_Active_Files/Documents/{$projectName}_{$projectId}/{$fileName}";
|
|
|
|
|
|
$requestPaths[] = $encodePath(['crm','crm2','CRM_Active_Files','Documents',"{$projectName}_{$projectId}",$fileName]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Резерв - старый формат (папка по documentId)
|
|
|
|
|
|
$humanPaths[] = "crm/crm2/CRM_Active_Files/Documents/{$docId}/{$fileName}";
|
|
|
|
|
|
$requestPaths[] = $encodePath(['crm','crm2','CRM_Active_Files','Documents',(string)$docId,$fileName]);
|
2025-10-21 22:10:47 +03:00
|
|
|
|
|
|
|
|
|
|
$fileId = null;
|
2025-10-22 18:29:02 +03:00
|
|
|
|
$usedPath = null;
|
2025-10-21 22:10:47 +03:00
|
|
|
|
|
2025-10-22 18:29:02 +03:00
|
|
|
|
// Пробуем найти файл по всем возможным путям
|
|
|
|
|
|
for ($i = 0; $i < count($requestPaths); $i++) {
|
|
|
|
|
|
$tryPath = $requestPaths[$i];
|
|
|
|
|
|
$logPath = $humanPaths[$i];
|
|
|
|
|
|
$propfindUrl = $nextcloudUrl . '/remote.php/dav/files/' . $username . '/' . $tryPath;
|
|
|
|
|
|
// error_log("Nextcloud Editor: PROPFIND -> {$propfindUrl} (читаемый путь: {$logPath})");
|
|
|
|
|
|
|
|
|
|
|
|
// XML запрос для получения fileid
|
|
|
|
|
|
$xmlRequest = '<?xml version="1.0"?>
|
|
|
|
|
|
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
|
|
|
|
|
<d:prop>
|
|
|
|
|
|
<oc:fileid/>
|
|
|
|
|
|
</d:prop>
|
|
|
|
|
|
</d:propfind>';
|
|
|
|
|
|
|
|
|
|
|
|
$ch = curl_init();
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $propfindUrl);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND');
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
|
|
|
|
'Depth: 0',
|
|
|
|
|
|
'Content-Type: application/xml'
|
|
|
|
|
|
]);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
|
|
$response = curl_exec($ch);
|
|
|
|
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
|
|
$curlError = curl_error($ch);
|
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
|
|
|
|
if ($response === false) {
|
|
|
|
|
|
error_log("Nextcloud Editor: Ошибка cURL: " . $curlError);
|
|
|
|
|
|
continue; // Пробуем следующий путь
|
|
|
|
|
|
}
|
2025-10-21 22:10:47 +03:00
|
|
|
|
|
|
|
|
|
|
if ($httpCode === 207 && $response) { // 207 = Multi-Status для PROPFIND
|
|
|
|
|
|
// Простой regex для извлечения fileid
|
|
|
|
|
|
if (preg_match('/<oc:fileid>(\d+)<\/oc:fileid>/', $response, $matches)) {
|
|
|
|
|
|
$fileId = $matches[1];
|
2025-10-22 18:29:02 +03:00
|
|
|
|
$usedPath = $tryPath;
|
|
|
|
|
|
error_log("Nextcloud Editor: ✅ fileId получен: {$fileId} (путь: {$usedPath})");
|
|
|
|
|
|
break; // Нашли файл, выходим из цикла
|
2025-10-21 22:10:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-22 18:29:02 +03:00
|
|
|
|
|
|
|
|
|
|
// error_log("Nextcloud Editor: Файл не найден по пути: {$logPath} (HTTP {$httpCode})");
|
2025-10-21 22:10:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!$fileId) {
|
2025-10-22 18:29:02 +03:00
|
|
|
|
// Простая ошибка без отладки
|
|
|
|
|
|
$errorMsg = "❌ Ошибка: Не удалось получить fileId для файла {$fileName}";
|
|
|
|
|
|
error_log("Nextcloud Editor ERROR: " . $errorMsg);
|
|
|
|
|
|
die($errorMsg);
|
2025-10-21 22:10:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Формируем URL для Nextcloud
|
|
|
|
|
|
// РАБОЧИЙ ФОРМАТ - редирект на файл с автооткрытием редактора!
|
|
|
|
|
|
$redirectUrl = $nextcloudUrl . '/apps/files/files/' . $fileId . '?dir=/&editing=true&openfile=true';
|
|
|
|
|
|
|
|
|
|
|
|
// Логирование
|
|
|
|
|
|
error_log("Nextcloud Editor: Redirect to $redirectUrl for file $fileName (ID: $fileId)");
|
|
|
|
|
|
|
|
|
|
|
|
// Делаем редирект
|
|
|
|
|
|
header('Location: ' . $redirectUrl);
|
|
|
|
|
|
exit;
|
|
|
|
|
|
?>
|