884 lines
28 KiB
PHP
884 lines
28 KiB
PHP
|
|
<?php
|
|||
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/config.php");
|
|||
|
|
|
|||
|
|
if (!class_exists('SelectelApi')) {
|
|||
|
|
$p1 = $_SERVER['DOCUMENT_ROOT'] . "/SelectelApi.php";
|
|||
|
|
$p2 = $_SERVER['DOCUMENT_ROOT'] . "/classes/SelectelApi.php";
|
|||
|
|
$p3 = $_SERVER['DOCUMENT_ROOT'] . "/lib/SelectelApi.php";
|
|||
|
|
if (file_exists($p1)) require_once($p1);
|
|||
|
|
else if (file_exists($p2)) require_once($p2);
|
|||
|
|
else if (file_exists($p3)) require_once($p3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
header('Content-Type: application/json; charset=utf-8');
|
|||
|
|
|
|||
|
|
function ps_json($arr) {
|
|||
|
|
echo json_encode($arr);
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_need_auth() {
|
|||
|
|
if (empty($_SESSION['agency_id']) || empty($_SESSION['id'])) {
|
|||
|
|
ps_json(array('ok' => false, 'error' => 'Нет доступа'));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_es($s) {
|
|||
|
|
return mysql_real_escape_string($s);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_post_str($key, $def) {
|
|||
|
|
if (isset($_POST[$key])) return (string)$_POST[$key];
|
|||
|
|
return (string)$def;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_post_int($key) {
|
|||
|
|
if (isset($_POST[$key])) return (int)$_POST[$key];
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_safe_ext($name) {
|
|||
|
|
$name = (string)$name;
|
|||
|
|
$pos = strrpos($name, '.');
|
|||
|
|
if ($pos === false) return '';
|
|||
|
|
$ext = substr($name, $pos + 1);
|
|||
|
|
$ext = preg_replace('/[^a-zA-Z0-9]+/', '', $ext);
|
|||
|
|
$ext = strtolower($ext);
|
|||
|
|
if (strlen($ext) > 12) $ext = substr($ext, 0, 12);
|
|||
|
|
return $ext;
|
|||
|
|
}
|
|||
|
|
function ps_max_file_size_bytes() {
|
|||
|
|
return 20 * 1024 * 1024;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_allowed_ext_map() {
|
|||
|
|
return array(
|
|||
|
|
'pdf' => array('application/pdf'),
|
|||
|
|
'doc' => array('application/msword', 'application/octet-stream'),
|
|||
|
|
'docx' => array(
|
|||
|
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|||
|
|
'application/zip',
|
|||
|
|
'application/octet-stream'
|
|||
|
|
),
|
|||
|
|
'rtf' => array('application/rtf', 'text/rtf', 'application/octet-stream'),
|
|||
|
|
'txt' => array('text/plain', 'application/octet-stream'),
|
|||
|
|
'xls' => array('application/vnd.ms-excel', 'application/octet-stream'),
|
|||
|
|
'xlsx' => array(
|
|||
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|||
|
|
'application/zip',
|
|||
|
|
'application/octet-stream'
|
|||
|
|
),
|
|||
|
|
'csv' => array('text/csv', 'text/plain', 'application/vnd.ms-excel', 'application/octet-stream'),
|
|||
|
|
'jpg' => array('image/jpeg'),
|
|||
|
|
'jpeg' => array('image/jpeg'),
|
|||
|
|
'png' => array('image/png'),
|
|||
|
|
'webp' => array('image/webp'),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_denied_ext_list() {
|
|||
|
|
return array(
|
|||
|
|
'exe','bat','cmd','com','msi','sh',
|
|||
|
|
'js','mjs','cjs',
|
|||
|
|
'php','php3','php4','php5','phtml','phar',
|
|||
|
|
'xlsm','docm','pptm',
|
|||
|
|
'zip','rar','7z','tar','gz'
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_detect_mime($tmpPath) {
|
|||
|
|
$mime = '';
|
|||
|
|
if (function_exists('finfo_open')) {
|
|||
|
|
$fi = @finfo_open(FILEINFO_MIME_TYPE);
|
|||
|
|
if ($fi) {
|
|||
|
|
$m = @finfo_file($fi, $tmpPath);
|
|||
|
|
if (is_string($m)) $mime = $m;
|
|||
|
|
@finfo_close($fi);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if ($mime === '' && function_exists('mime_content_type')) {
|
|||
|
|
$m = @mime_content_type($tmpPath);
|
|||
|
|
if (is_string($m)) $mime = $m;
|
|||
|
|
}
|
|||
|
|
return strtolower(trim((string)$mime));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_read_magic($tmpPath, $len) {
|
|||
|
|
$fh = @fopen($tmpPath, 'rb');
|
|||
|
|
if (!$fh) return '';
|
|||
|
|
$bin = @fread($fh, (int)$len);
|
|||
|
|
@fclose($fh);
|
|||
|
|
if (!is_string($bin)) return '';
|
|||
|
|
return $bin;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_is_zip_like($tmpPath) {
|
|||
|
|
$head = ps_read_magic($tmpPath, 4);
|
|||
|
|
return (substr($head, 0, 2) === "PK");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_magic_ok_by_ext($ext, $tmpPath) {
|
|||
|
|
$ext = strtolower((string)$ext);
|
|||
|
|
|
|||
|
|
if ($ext === 'pdf') {
|
|||
|
|
$h = ps_read_magic($tmpPath, 5);
|
|||
|
|
return (substr($h, 0, 4) === '%PDF');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($ext === 'jpg' || $ext === 'jpeg') {
|
|||
|
|
$h = ps_read_magic($tmpPath, 3);
|
|||
|
|
return ($h === "\xFF\xD8\xFF");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($ext === 'png') {
|
|||
|
|
$h = ps_read_magic($tmpPath, 8);
|
|||
|
|
return ($h === "\x89PNG\x0D\x0A\x1A\x0A");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($ext === 'webp') {
|
|||
|
|
$h = ps_read_magic($tmpPath, 12);
|
|||
|
|
return (substr($h, 0, 4) === 'RIFF' && substr($h, 8, 4) === 'WEBP');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($ext === 'docx' || $ext === 'xlsx') {
|
|||
|
|
return ps_is_zip_like($tmpPath);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_is_allowed_file($origName, $tmpPath, &$errorCode, &$detectedMime) {
|
|||
|
|
$errorCode = '';
|
|||
|
|
$detectedMime = '';
|
|||
|
|
|
|||
|
|
$ext = ps_safe_ext($origName);
|
|||
|
|
if ($ext === '') {
|
|||
|
|
$errorCode = 'bad_ext';
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$denied = ps_denied_ext_list();
|
|||
|
|
if (in_array($ext, $denied, true)) {
|
|||
|
|
$errorCode = 'bad_ext';
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$allowedMap = ps_allowed_ext_map();
|
|||
|
|
if (!isset($allowedMap[$ext])) {
|
|||
|
|
$errorCode = 'bad_ext';
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$detectedMime = ps_detect_mime($tmpPath);
|
|||
|
|
|
|||
|
|
if (!ps_magic_ok_by_ext($ext, $tmpPath)) {
|
|||
|
|
$errorCode = 'bad_mime';
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$okMime = false;
|
|||
|
|
$allowMimes = $allowedMap[$ext];
|
|||
|
|
$i = 0;
|
|||
|
|
while ($i < count($allowMimes)) {
|
|||
|
|
if ($detectedMime === strtolower($allowMimes[$i])) {
|
|||
|
|
$okMime = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
$i++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!$okMime && $detectedMime !== '') {
|
|||
|
|
$errorCode = 'bad_mime';
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_random_file_name($ext) {
|
|||
|
|
$ext = ps_safe_ext($ext);
|
|||
|
|
if ($ext === '') $ext = 'bin';
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
if (function_exists('random_bytes')) {
|
|||
|
|
$b = random_bytes(16);
|
|||
|
|
$hex = bin2hex($b);
|
|||
|
|
} else {
|
|||
|
|
$hex = md5(uniqid('', true) . mt_rand());
|
|||
|
|
}
|
|||
|
|
} catch (Exception $e) {
|
|||
|
|
$hex = md5(uniqid('', true) . mt_rand());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 8-4-4-4-12
|
|||
|
|
$name = substr($hex, 0, 8) . '-' .
|
|||
|
|
substr($hex, 8, 4) . '-' .
|
|||
|
|
substr($hex, 12, 4) . '-' .
|
|||
|
|
substr($hex, 16, 4) . '-' .
|
|||
|
|
substr($hex, 20, 12);
|
|||
|
|
|
|||
|
|
return $name . '.' . $ext;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_err_text_by_code($code, $ext) {
|
|||
|
|
if ($code === 'too_big') return 'Файл слишком большой. Максимум 20 МБ';
|
|||
|
|
if ($code === 'bad_ext') return 'Формат .' . $ext . ' не поддерживается';
|
|||
|
|
if ($code === 'bad_mime') return 'Формат .' . $ext . ' не поддерживается';
|
|||
|
|
return 'Ошибка загрузки файла';
|
|||
|
|
}
|
|||
|
|
function ps_public_root() {
|
|||
|
|
return 'https://data.joywork.ru';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_storage_prefix() {
|
|||
|
|
return 'partner/partner-materials';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_public_prefix_url() {
|
|||
|
|
return ps_public_root() . '/' . ps_storage_prefix();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_mime_by_ext($ext) {
|
|||
|
|
$ext = strtolower((string)$ext);
|
|||
|
|
|
|||
|
|
if ($ext === 'pdf') return 'application/pdf';
|
|||
|
|
if ($ext === 'doc') return 'application/msword';
|
|||
|
|
if ($ext === 'docx') return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
|||
|
|
if ($ext === 'rtf') return 'application/rtf';
|
|||
|
|
if ($ext === 'txt') return 'text/plain';
|
|||
|
|
if ($ext === 'xls') return 'application/vnd.ms-excel';
|
|||
|
|
if ($ext === 'xlsx') return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|||
|
|
if ($ext === 'csv') return 'text/csv';
|
|||
|
|
if ($ext === 'jpg' || $ext === 'jpeg') return 'image/jpeg';
|
|||
|
|
if ($ext === 'png') return 'image/png';
|
|||
|
|
if ($ext === 'webp') return 'image/webp';
|
|||
|
|
|
|||
|
|
return 'application/octet-stream';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_files_table() {
|
|||
|
|
return 'partner_material_documents';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_auth() {
|
|||
|
|
static $cached = null;
|
|||
|
|
if ($cached !== null) return $cached;
|
|||
|
|
|
|||
|
|
if (!empty($_SESSION['selectel_token']) && !empty($_SESSION['selectel_storage_url']) && !empty($_SESSION['selectel_token_till'])) {
|
|||
|
|
if ((int)$_SESSION['selectel_token_till'] > time() + 60) {
|
|||
|
|
$cached = array((string)$_SESSION['selectel_token'], (string)$_SESSION['selectel_storage_url']);
|
|||
|
|
return $cached;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!class_exists('SelectelApi')) {
|
|||
|
|
$cached = array('', '');
|
|||
|
|
return $cached;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!method_exists('SelectelApi', 'getTokenAndUrl')) {
|
|||
|
|
$cached = array('', '');
|
|||
|
|
return $cached;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$r = SelectelApi::getTokenAndUrl();
|
|||
|
|
|
|||
|
|
$token = (string)($r[0]);
|
|||
|
|
$storageUrl = (string)($r[1]);
|
|||
|
|
if ($token === '' || $storageUrl === '') {
|
|||
|
|
$cached = array('', '');
|
|||
|
|
return $cached;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$_SESSION['selectel_token'] = $token;
|
|||
|
|
$_SESSION['selectel_storage_url'] = $storageUrl;
|
|||
|
|
$_SESSION['selectel_token_till'] = time() + 3600;
|
|||
|
|
|
|||
|
|
$cached = array($token, $storageUrl);
|
|||
|
|
return $cached;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_jwdata_base($storageUrl) {
|
|||
|
|
$storageUrl = rtrim((string)$storageUrl, '/');
|
|||
|
|
return $storageUrl . '/jwdata/';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_object_from_any($value) {
|
|||
|
|
$s = trim((string)$value);
|
|||
|
|
if ($s === '') return '';
|
|||
|
|
|
|||
|
|
if (strpos($s, 'http://') === 0 || strpos($s, 'https://') === 0) {
|
|||
|
|
$path = parse_url($s, PHP_URL_PATH);
|
|||
|
|
$s = (string)$path;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$s = ltrim($s, '/');
|
|||
|
|
|
|||
|
|
$prefix = rtrim(ps_storage_prefix(), '/') . '/';
|
|||
|
|
if (strpos($s, $prefix) === 0) return $s;
|
|||
|
|
|
|||
|
|
if (preg_match('~^\d+/\d+/~', $s)) {
|
|||
|
|
return $prefix . $s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return $prefix . $s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_upload_raw($baseUrl, $token, $tmpPath, $objectName, $contentType) {
|
|||
|
|
$fh = @fopen($tmpPath, 'rb');
|
|||
|
|
if (!$fh) return false;
|
|||
|
|
|
|||
|
|
$size = @filesize($tmpPath);
|
|||
|
|
if ($size === false) $size = 0;
|
|||
|
|
|
|||
|
|
$url = rtrim((string)$baseUrl, '/') . '/' . ltrim((string)$objectName, '/');
|
|||
|
|
|
|||
|
|
$ch = curl_init();
|
|||
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
|||
|
|
curl_setopt($ch, CURLOPT_UPLOAD, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_INFILE, $fh);
|
|||
|
|
if ($size > 0) curl_setopt($ch, CURLOPT_INFILESIZE, $size);
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|||
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 180);
|
|||
|
|
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 1024);
|
|||
|
|
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 20);
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|||
|
|
"X-Auth-Token: $token",
|
|||
|
|
"Content-Type: $contentType",
|
|||
|
|
"Expect:"
|
|||
|
|
));
|
|||
|
|
|
|||
|
|
curl_exec($ch);
|
|||
|
|
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|||
|
|
$err = (int)curl_errno($ch);
|
|||
|
|
|
|||
|
|
curl_close($ch);
|
|||
|
|
fclose($fh);
|
|||
|
|
|
|||
|
|
if ($err) return false;
|
|||
|
|
return ($code === 201);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_delete_raw($baseUrl, $token, $objectName) {
|
|||
|
|
$url = rtrim((string)$baseUrl, '/') . '/' . ltrim((string)$objectName, '/');
|
|||
|
|
|
|||
|
|
$ch = curl_init();
|
|||
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|||
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
|||
|
|
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 1024);
|
|||
|
|
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 20);
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Auth-Token: $token"));
|
|||
|
|
|
|||
|
|
curl_exec($ch);
|
|||
|
|
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|||
|
|
$err = (int)curl_errno($ch);
|
|||
|
|
|
|||
|
|
curl_close($ch);
|
|||
|
|
|
|||
|
|
if ($err) return false;
|
|||
|
|
if ($code === 204) return true;
|
|||
|
|
if ($code === 404) return true;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_head_raw($baseUrl, $token, $objectName) {
|
|||
|
|
$url = rtrim((string)$baseUrl, '/') . '/' . ltrim((string)$objectName, '/');
|
|||
|
|
|
|||
|
|
$ch = curl_init();
|
|||
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|||
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
|||
|
|
|
|||
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Auth-Token: $token"));
|
|||
|
|
|
|||
|
|
curl_exec($ch);
|
|||
|
|
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|||
|
|
$err = (int)curl_errno($ch);
|
|||
|
|
|
|||
|
|
curl_close($ch);
|
|||
|
|
|
|||
|
|
if ($err) return 0;
|
|||
|
|
return $code;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_upload_object($tmpPath, $objectName, $contentType) {
|
|||
|
|
$r = ps_selectel_auth();
|
|||
|
|
$token = (string)$r[0];
|
|||
|
|
$storageUrl = (string)$r[1];
|
|||
|
|
if ($token === '' || $storageUrl === '') return false;
|
|||
|
|
|
|||
|
|
$base = ps_selectel_jwdata_base($storageUrl);
|
|||
|
|
return ps_selectel_upload_raw($base, $token, $tmpPath, $objectName, $contentType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_delete_any($value) {
|
|||
|
|
$r = ps_selectel_auth();
|
|||
|
|
$token = (string)$r[0];
|
|||
|
|
$storageUrl = (string)$r[1];
|
|||
|
|
if ($token === '' || $storageUrl === '') return false;
|
|||
|
|
|
|||
|
|
$obj = ps_selectel_object_from_any($value);
|
|||
|
|
if ($obj === '') return false;
|
|||
|
|
|
|||
|
|
$base = ps_selectel_jwdata_base($storageUrl);
|
|||
|
|
return ps_selectel_delete_raw($base, $token, $obj);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ps_selectel_head_object($objectName) {
|
|||
|
|
$r = ps_selectel_auth();
|
|||
|
|
$token = (string)$r[0];
|
|||
|
|
$storageUrl = (string)$r[1];
|
|||
|
|
if ($token === '' || $storageUrl === '') return 0;
|
|||
|
|
|
|||
|
|
$base = ps_selectel_jwdata_base($storageUrl);
|
|||
|
|
return ps_selectel_head_raw($base, $token, $objectName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_need_auth();
|
|||
|
|
|
|||
|
|
$agencyId = (int)$_SESSION['agency_id'];
|
|||
|
|
$userId = (int)$_SESSION['id'];
|
|||
|
|
|
|||
|
|
$action = ps_post_str('action', '');
|
|||
|
|
if ($action === '' && isset($_GET['action'])) $action = (string)$_GET['action'];
|
|||
|
|
|
|||
|
|
$filesTable = ps_files_table();
|
|||
|
|
|
|||
|
|
if ($action === 'url_save') {
|
|||
|
|
$partners = new Partners();
|
|||
|
|
|
|||
|
|
$val = trim(ps_post_str('partner_url', ''));
|
|||
|
|
$ok = $partners->savePartnerUrl($val);
|
|||
|
|
|
|||
|
|
if (!$ok) {
|
|||
|
|
$err = 'Ошибка';
|
|||
|
|
if (!empty($partners->errors)) $err = implode('<br>', $partners->errors);
|
|||
|
|
ps_json(array('ok' => false, 'error' => $err));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$slug = $partners->getPartnerUrl($userId);
|
|||
|
|
$full = $partners->getPartnerCabinetUrl($_SESSION['agency_id'], $_SESSION['id']);
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'partner_url' => $slug, 'full_url' => $full));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_list') {
|
|||
|
|
$cats = array();
|
|||
|
|
|
|||
|
|
$res = mysql_query("SELECT id, title FROM partner_material_categories WHERE agency_id={$agencyId} ORDER BY id ASC");
|
|||
|
|
if ($res) {
|
|||
|
|
while ($r = mysql_fetch_assoc($res)) {
|
|||
|
|
$id = (int)$r['id'];
|
|||
|
|
$cats[$id] = array('id' => $id, 'title' => (string)$r['title'], 'files' => array());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!empty($cats)) {
|
|||
|
|
$ids = implode(',', array_keys($cats));
|
|||
|
|
|
|||
|
|
$res2 = mysql_query("SELECT id, category_id, file_path, file_name, file_size FROM {$filesTable} WHERE agency_id={$agencyId} AND category_id IN ({$ids}) AND doc_type='file' ORDER BY id ASC");
|
|||
|
|
if ($res2) {
|
|||
|
|
while ($f = mysql_fetch_assoc($res2)) {
|
|||
|
|
$cid = (int)$f['category_id'];
|
|||
|
|
if (!isset($cats[$cid])) continue;
|
|||
|
|
|
|||
|
|
$path = (string)$f['file_path'];
|
|||
|
|
$url = '';
|
|||
|
|
|
|||
|
|
if ($path !== '') {
|
|||
|
|
if (strpos($path, 'http://') === 0 || strpos($path, 'https://') === 0) {
|
|||
|
|
$url = $path;
|
|||
|
|
} else {
|
|||
|
|
$url = ps_public_prefix_url() . '/' . ltrim($path, '/');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$cats[$cid]['files'][] = array(
|
|||
|
|
'id' => (int)$f['id'],
|
|||
|
|
'category_id' => $cid,
|
|||
|
|
'file_name' => (string)$f['file_name'],
|
|||
|
|
'file_size' => (int)$f['file_size'],
|
|||
|
|
'file_url' => $url,
|
|||
|
|
'file_path' => $path
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'categories' => array_values($cats)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_category_create') {
|
|||
|
|
$title = trim(ps_post_str('title', ''));
|
|||
|
|
if ($title === '') ps_json(array('ok' => false, 'error' => 'Введите название'));
|
|||
|
|
|
|||
|
|
$t = ps_es($title);
|
|||
|
|
$ok = mysql_query("INSERT INTO partner_material_categories (agency_id, title) VALUES ({$agencyId}, '{$t}')");
|
|||
|
|
if (!$ok) ps_json(array('ok' => false, 'error' => 'Ошибка создания категории'));
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'id' => (int)mysql_insert_id(), 'title' => $title));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_category_rename') {
|
|||
|
|
$categoryId = ps_post_int('category_id');
|
|||
|
|
$title = trim(ps_post_str('title', ''));
|
|||
|
|
|
|||
|
|
if ($categoryId <= 0) ps_json(array('ok' => false, 'error' => 'Категория не выбрана'));
|
|||
|
|
if ($title === '') ps_json(array('ok' => false, 'error' => 'Введите название'));
|
|||
|
|
|
|||
|
|
$t = ps_es($title);
|
|||
|
|
$ok = mysql_query("UPDATE partner_material_categories SET title='{$t}' WHERE agency_id={$agencyId} AND id={$categoryId} LIMIT 1");
|
|||
|
|
if (!$ok) ps_json(array('ok' => false, 'error' => 'Ошибка переименования'));
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_category_delete') {
|
|||
|
|
$categoryId = ps_post_int('category_id');
|
|||
|
|
if ($categoryId <= 0) ps_json(array('ok' => false, 'error' => 'Категория не выбрана'));
|
|||
|
|
|
|||
|
|
$res = mysql_query("SELECT file_path FROM {$filesTable} WHERE agency_id={$agencyId} AND category_id={$categoryId} AND doc_type='file'");
|
|||
|
|
if ($res) {
|
|||
|
|
while ($r = mysql_fetch_assoc($res)) {
|
|||
|
|
$p = (string)$r['file_path'];
|
|||
|
|
if ($p !== '') ps_selectel_delete_any($p);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mysql_query("DELETE FROM {$filesTable} WHERE agency_id={$agencyId} AND category_id={$categoryId} AND doc_type='file'");
|
|||
|
|
|
|||
|
|
$ok = mysql_query("DELETE FROM partner_material_categories WHERE agency_id={$agencyId} AND id={$categoryId} LIMIT 1");
|
|||
|
|
if (!$ok) ps_json(array('ok' => false, 'error' => 'Ошибка удаления категории'));
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_files_upload') {
|
|||
|
|
$categoryId = ps_post_int('category_id');
|
|||
|
|
if ($categoryId <= 0) ps_json(array('ok' => false, 'error' => 'Категория не выбрана'));
|
|||
|
|
|
|||
|
|
$chk = mysql_query("SELECT id FROM partner_material_categories WHERE agency_id={$agencyId} AND id={$categoryId} LIMIT 1");
|
|||
|
|
if (!$chk || !mysql_num_rows($chk)) ps_json(array('ok' => false, 'error' => 'Категория не найдена'));
|
|||
|
|
|
|||
|
|
if (!isset($_FILES['files'])) ps_json(array('ok' => false, 'error' => 'Файлы не переданы'));
|
|||
|
|
|
|||
|
|
$names = $_FILES['files']['name'];
|
|||
|
|
$tmp = $_FILES['files']['tmp_name'];
|
|||
|
|
$size = $_FILES['files']['size'];
|
|||
|
|
$err = $_FILES['files']['error'];
|
|||
|
|
|
|||
|
|
if (!is_array($names)) {
|
|||
|
|
$names = array($names);
|
|||
|
|
$tmp = array($tmp);
|
|||
|
|
$size = array($size);
|
|||
|
|
$err = array($err);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$count = count($names);
|
|||
|
|
if ($count <= 0) ps_json(array('ok' => false, 'error' => 'Файлы не выбраны'));
|
|||
|
|
|
|||
|
|
$r = ps_selectel_auth();
|
|||
|
|
if ((string)$r[0] === '' || (string)$r[1] === '') {
|
|||
|
|
ps_json(array('ok' => false, 'error' => 'Selectel token/url пустые'));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$created = array();
|
|||
|
|
$errorsOut = array();
|
|||
|
|
|
|||
|
|
$i = 0;
|
|||
|
|
while ($i < $count) {
|
|||
|
|
$e = (int)$err[$i];
|
|||
|
|
$origName = isset($names[$i]) ? (string)$names[$i] : '';
|
|||
|
|
$tmpName = isset($tmp[$i]) ? (string)$tmp[$i] : '';
|
|||
|
|
$fsize = isset($size[$i]) ? (int)$size[$i] : 0;
|
|||
|
|
|
|||
|
|
if ($e !== 0 || $tmpName === '' || !is_uploaded_file($tmpName)) {
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => 'Ошибка загрузки файла'
|
|||
|
|
);
|
|||
|
|
$i++;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$ext = ps_safe_ext($origName);
|
|||
|
|
if ($ext === '') $ext = 'unknown';
|
|||
|
|
|
|||
|
|
if ($fsize <= 0 || $fsize > ps_max_file_size_bytes()) {
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => ps_err_text_by_code('too_big', $ext)
|
|||
|
|
);
|
|||
|
|
$i++;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$detectedMime = '';
|
|||
|
|
$errCode = '';
|
|||
|
|
if (!ps_is_allowed_file($origName, $tmpName, $errCode, $detectedMime)) {
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => ps_err_text_by_code($errCode, $ext)
|
|||
|
|
);
|
|||
|
|
$i++;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$storedFileName = ps_random_file_name($ext);
|
|||
|
|
|
|||
|
|
$objectName = rtrim(ps_storage_prefix(), '/') . '/' . $agencyId . '/' . $categoryId . '/' . $storedFileName;
|
|||
|
|
$publicUrl = ps_public_root() . '/' . ltrim($objectName, '/');
|
|||
|
|
|
|||
|
|
$contentType = ps_mime_by_ext($ext);
|
|||
|
|
|
|||
|
|
$uploaded = ps_selectel_upload_object($tmpName, $objectName, $contentType);
|
|||
|
|
if (!$uploaded) {
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => 'Ошибка загрузки файла'
|
|||
|
|
);
|
|||
|
|
$i++;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$swiftCode = ps_selectel_head_object($objectName);
|
|||
|
|
if ($swiftCode !== 200) {
|
|||
|
|
ps_selectel_delete_any($objectName);
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => 'Ошибка загрузки файла'
|
|||
|
|
);
|
|||
|
|
$i++;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$dbMime = ($detectedMime !== '') ? $detectedMime : $contentType;
|
|||
|
|
|
|||
|
|
$fp = ps_es($publicUrl);
|
|||
|
|
$on = ps_es($origName);
|
|||
|
|
$mm = ps_es($dbMime);
|
|||
|
|
$ttl = ps_es($origName);
|
|||
|
|
|
|||
|
|
$sql = "INSERT INTO {$filesTable} (agency_id, category_id, title, doc_type, file_path, file_name, file_mime, file_size, link_url, text_content)
|
|||
|
|
VALUES ({$agencyId}, {$categoryId}, '{$ttl}', 'file', '{$fp}', '{$on}', '{$mm}', {$fsize}, '', NULL)";
|
|||
|
|
|
|||
|
|
$ok = mysql_query($sql);
|
|||
|
|
|
|||
|
|
if ($ok) {
|
|||
|
|
$id = (int)mysql_insert_id();
|
|||
|
|
$created[] = array(
|
|||
|
|
'id' => $id,
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'file_size' => $fsize,
|
|||
|
|
'file_url' => $publicUrl,
|
|||
|
|
'file_path' => $publicUrl
|
|||
|
|
);
|
|||
|
|
} else {
|
|||
|
|
ps_selectel_delete_any($objectName);
|
|||
|
|
$errorsOut[] = array(
|
|||
|
|
'file_name' => $origName,
|
|||
|
|
'message' => 'Ошибка сохранения в базе'
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$i++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_json(array(
|
|||
|
|
'ok' => true,
|
|||
|
|
'created' => $created,
|
|||
|
|
'errors' => $errorsOut
|
|||
|
|
));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'materials_file_delete') {
|
|||
|
|
$fileId = ps_post_int('file_id');
|
|||
|
|
if ($fileId <= 0) ps_json(array('ok' => false, 'error' => 'Файл не выбран'));
|
|||
|
|
|
|||
|
|
$p = '';
|
|||
|
|
$res = mysql_query("SELECT file_path FROM {$filesTable} WHERE agency_id={$agencyId} AND id={$fileId} AND doc_type='file' LIMIT 1");
|
|||
|
|
if ($res && mysql_num_rows($res)) {
|
|||
|
|
$r = mysql_fetch_assoc($res);
|
|||
|
|
$p = (string)$r['file_path'];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$ok = mysql_query("DELETE FROM {$filesTable} WHERE agency_id={$agencyId} AND id={$fileId} AND doc_type='file' LIMIT 1");
|
|||
|
|
if (!$ok) ps_json(array('ok' => false, 'error' => 'Ошибка удаления'));
|
|||
|
|
|
|||
|
|
if ($p !== '') ps_selectel_delete_any($p);
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'news_list') {
|
|||
|
|
$newsItems = array();
|
|||
|
|
|
|||
|
|
$sql = "SELECT id, title, body_html, is_important, created_at
|
|||
|
|
FROM partner_news
|
|||
|
|
WHERE agency_id={$agencyId}
|
|||
|
|
ORDER BY is_important DESC, id DESC";
|
|||
|
|
|
|||
|
|
$res = mysql_query($sql);
|
|||
|
|
if (!$res) ps_json(array('ok' => false, 'error' => 'SQL ошибка: ' . mysql_error()));
|
|||
|
|
|
|||
|
|
while ($row = mysql_fetch_assoc($res)) {
|
|||
|
|
$newsItems[] = array(
|
|||
|
|
'id' => (int)$row['id'],
|
|||
|
|
'title' => (string)$row['title'],
|
|||
|
|
'body_html' => (string)$row['body_html'],
|
|||
|
|
'is_important' => (int)$row['is_important'],
|
|||
|
|
'created_at' => (string)$row['created_at']
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'items' => $newsItems));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'news_create') {
|
|||
|
|
$newsTitle = trim(ps_post_str('title', ''));
|
|||
|
|
$newsBodyHtml = (string)ps_post_str('body_html', '');
|
|||
|
|
$isImportant = ps_post_int('is_important') ? 1 : 0;
|
|||
|
|
|
|||
|
|
if ($newsTitle === '') ps_json(array('ok' => false, 'error' => 'Введите заголовок'));
|
|||
|
|
|
|||
|
|
$newsBodyHtml = str_replace("\0", '', $newsBodyHtml);
|
|||
|
|
|
|||
|
|
$newsTitleSql = ps_es($newsTitle);
|
|||
|
|
$newsBodySql = ps_es($newsBodyHtml);
|
|||
|
|
|
|||
|
|
$insertSql = "INSERT INTO partner_news (`agency_id`, `title`, `body_html`, `is_important`, `created_at`, `updated_at`)
|
|||
|
|
VALUES ({$agencyId}, '{$newsTitleSql}', '{$newsBodySql}', {$isImportant}, NOW(), NOW())";
|
|||
|
|
|
|||
|
|
$insertOk = mysql_query($insertSql);
|
|||
|
|
if (!$insertOk) ps_json(array('ok' => false, 'error' => 'Ошибка создания новости: ' . mysql_error()));
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'id' => (int)mysql_insert_id()));
|
|||
|
|
}
|
|||
|
|
if ($action === 'news_update') {
|
|||
|
|
$newsId = ps_post_int('news_id');
|
|||
|
|
$newsTitle = trim(ps_post_str('title', ''));
|
|||
|
|
$newsBodyHtml = (string)ps_post_str('body_html', '');
|
|||
|
|
$isImportant = ps_post_int('is_important') ? 1 : 0;
|
|||
|
|
|
|||
|
|
if ($newsId <= 0) ps_json(array('ok' => false, 'error' => 'Некорректный ID новости'));
|
|||
|
|
if ($newsTitle === '') ps_json(array('ok' => false, 'error' => 'Введите заголовок'));
|
|||
|
|
|
|||
|
|
$newsBodyHtml = str_replace("\0", '', $newsBodyHtml);
|
|||
|
|
|
|||
|
|
$newsTitleSql = ps_es($newsTitle);
|
|||
|
|
$newsBodySql = ps_es($newsBodyHtml);
|
|||
|
|
|
|||
|
|
$updateSql = "UPDATE partner_news
|
|||
|
|
SET `title` = '{$newsTitleSql}',
|
|||
|
|
`body_html` = '{$newsBodySql}',
|
|||
|
|
`is_important` = {$isImportant},
|
|||
|
|
`updated_at` = NOW()
|
|||
|
|
WHERE `id` = {$newsId} AND `agency_id` = {$agencyId}
|
|||
|
|
LIMIT 1";
|
|||
|
|
|
|||
|
|
$updateOk = mysql_query($updateSql);
|
|||
|
|
if (!$updateOk) ps_json(array('ok' => false, 'error' => 'Ошибка обновления новости: ' . mysql_error()));
|
|||
|
|
|
|||
|
|
if (function_exists('mysql_affected_rows') && mysql_affected_rows() < 0) {
|
|||
|
|
ps_json(array('ok' => false, 'error' => 'Не удалось обновить новость'));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true, 'id' => (int)$newsId));
|
|||
|
|
}
|
|||
|
|
if ($action === 'news_delete') {
|
|||
|
|
$newsId = ps_post_int('news_id');
|
|||
|
|
if ($newsId <= 0) ps_json(array('ok' => false, 'error' => 'Новость не выбрана'));
|
|||
|
|
|
|||
|
|
$ok = mysql_query("DELETE FROM partner_news WHERE agency_id={$agencyId} AND id={$newsId} LIMIT 1");
|
|||
|
|
if (!$ok) ps_json(array('ok' => false, 'error' => 'Ошибка удаления новости: ' . mysql_error()));
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => true));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($action === 'ckeditor_exportpdf_token') {
|
|||
|
|
header('Content-Type: application/json; charset=utf-8');
|
|||
|
|
echo json_encode(array('token' => ''));
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
if ($action === 'materials_file_download') {
|
|||
|
|
$fileId = 0;
|
|||
|
|
if (isset($_GET['file_id'])) $fileId = (int)$_GET['file_id'];
|
|||
|
|
if ($fileId <= 0) {
|
|||
|
|
header('HTTP/1.1 400 Bad Request');
|
|||
|
|
echo 'file_id missing';
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$res = mysql_query("SELECT file_path, file_name, file_mime, file_size FROM {$filesTable} WHERE agency_id={$agencyId} AND id={$fileId} AND doc_type='file' LIMIT 1");
|
|||
|
|
if (!$res || !mysql_num_rows($res)) {
|
|||
|
|
header('HTTP/1.1 404 Not Found');
|
|||
|
|
echo 'not found';
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$r = mysql_fetch_assoc($res);
|
|||
|
|
|
|||
|
|
$url = (string)($r['file_path']);
|
|||
|
|
if ($url !== '' && strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) {
|
|||
|
|
$url = ps_public_prefix_url() . '/' . ltrim($url, '/');
|
|||
|
|
}
|
|||
|
|
if ($url === '') {
|
|||
|
|
header('HTTP/1.1 404 Not Found');
|
|||
|
|
echo 'empty path';
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$fname = (string)($r['file_name']);
|
|||
|
|
if ($fname === '') $fname = 'file';
|
|||
|
|
$fname = preg_replace('/[\r\n]+/', ' ', $fname);
|
|||
|
|
$fname = str_replace(array('"', '\\'), array("'", ''), $fname);
|
|||
|
|
|
|||
|
|
$mime = (string)($r['file_mime']);
|
|||
|
|
if ($mime === '') $mime = 'application/octet-stream';
|
|||
|
|
|
|||
|
|
$size = (int)($r['file_size'] );
|
|||
|
|
|
|||
|
|
header('Content-Type: ' . $mime);
|
|||
|
|
header('Content-Disposition: attachment; filename="' . $fname . '"');
|
|||
|
|
header('X-Content-Type-Options: nosniff');
|
|||
|
|
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
|||
|
|
header('Pragma: no-cache');
|
|||
|
|
if ($size > 0) header('Content-Length: ' . $size);
|
|||
|
|
|
|||
|
|
$out = fopen('php://output', 'wb');
|
|||
|
|
if (!$out) {
|
|||
|
|
header('HTTP/1.1 500 Internal Server Error');
|
|||
|
|
echo 'output error';
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$ch = curl_init();
|
|||
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|||
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
|
|||
|
|
curl_setopt($ch, CURLOPT_FILE, $out);
|
|||
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|||
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
|
|||
|
|
|
|||
|
|
curl_exec($ch);
|
|||
|
|
curl_close($ch);
|
|||
|
|
fclose($out);
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ps_json(array('ok' => false, 'error' => 'Неизвестное действие'));
|