1451 lines
63 KiB
PHP
1451 lines
63 KiB
PHP
<?php
|
||
use lfkeitel\phptotp\{Base32,Totp};
|
||
//sleep(1);
|
||
|
||
//ini_set('display_errors','Off'); //Чтоб ошибки не отправлялись клиентам
|
||
//ini_set("error_log", "php_error.log"); //Чтоб ошибки сохранялись в локальную папку
|
||
|
||
$host = $_SERVER['HTTP_HOST'];
|
||
$host = '.'.cutAfterLast($host,'.',2);
|
||
ini_set('session.cookie_domain', $host);
|
||
|
||
//if(isset($_GET[session_name()]) && $_GET[session_name()]!='') //Чтоб сессия переданная гетом была главней
|
||
// session_id($_GET[session_name()]);
|
||
|
||
startSession(true); //Для ручного определения времени жизни сесии
|
||
|
||
if(isset($_SESSION['REMOTE_ADDR']) && $_SESSION['REMOTE_ADDR'] != $_SERVER['REMOTE_ADDR']) unset($_SESSION['USER_ID']); //Делаемся не авторизованным если зашли с другого ip адреса
|
||
if(!isset($_SESSION['USER_ID'])) { $_SESSION['USER_ID']=null; }
|
||
if(!isset($_COOKIE['GUID'])) { $_COOKIE['GUID']=null; }
|
||
|
||
//include("../include/xmltools.php");
|
||
//include("../include/toExcell.php");
|
||
//require_once("config.php");
|
||
|
||
function getCurrentDirectory() {
|
||
$path = dirname($_SERVER['PHP_SELF']);
|
||
$position = strrpos($path,'/') + 1;
|
||
return substr($path,$position);
|
||
}
|
||
|
||
//Полный путь к скрипту включая протокол без названия файла на конце "/"
|
||
function getFullPath()
|
||
{
|
||
$pro="http";
|
||
if (isset( $_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') $pro="https";
|
||
$path = $pro.'://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
|
||
$position = strrpos($path,'/') + 1;
|
||
return substr($path,0,$position);
|
||
}
|
||
|
||
function sendError($code, $error)
|
||
{
|
||
$obj = new StdClass();
|
||
$obj->errorCode=$code;
|
||
$obj->errorMessage=$error;
|
||
header('Content-Type: application/json');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo json_encode($obj);
|
||
exit();
|
||
}
|
||
|
||
function getSQLValue($t,$v)
|
||
{
|
||
global $db_connection;
|
||
|
||
if($t=='object' && gettype($v)=='string'){
|
||
$t='string'; //Если id шники uuid
|
||
}
|
||
|
||
if($t=='object'){
|
||
if ($v=='-1'||$v=='' || $v==null) $v='NULL';
|
||
}else
|
||
if($t=='i1' || $t=='i2' || $t=='i4' || $t=='integer'){
|
||
if($v=='') $v='NULL';
|
||
}else
|
||
if($t=='f8' || $t=='f4' || $t=='real' || $t=='double'){
|
||
if($v=='')$v='NULL';
|
||
$v=str_replace(',','.',$v); //Разделитель целой и дробной части точка
|
||
}else
|
||
if($t=='b'){
|
||
if($v=='') $v='NULL'; else
|
||
if($v=='1') $v='true'; else
|
||
if($v=='0') $v='false';
|
||
}else
|
||
if($t=='string' || $t=='html' || $t=='text' || $t=='dateTime' || $t=='time' || $t=='date' || $t=='file') {
|
||
if ($v == '') {
|
||
$v = 'NULL';
|
||
} else {
|
||
if (strpos($db_connection, 'pgsql') !== false)
|
||
$v = str_replace("'", "''", $v); //так как в SQL строку вставляется
|
||
else
|
||
$v = str_replace('\'', '\\\'', $v); //так как в SQL строку вставляется
|
||
$v = '\'' . $v . '\'';
|
||
}
|
||
}else if($t=="NULL" || $t==null){
|
||
if ($v == '') {
|
||
$v = 'NULL';
|
||
} else {
|
||
$v='\''.$v.'\'';
|
||
}
|
||
}else{
|
||
$v='\''.$v.'\'';
|
||
}
|
||
return $v;
|
||
}
|
||
|
||
function getValue($t,$v)
|
||
{
|
||
if($t=='object' && gettype($v)=='string'){
|
||
$t='string'; //Если id шники uuid
|
||
}
|
||
|
||
if($t=='object'){
|
||
if (($v=='-1')||($v=='')) $v=null;
|
||
}else
|
||
if($t=='i4' || $t=='integer'){
|
||
if($v=='') $v=null;
|
||
}else
|
||
if($t=='f8'){
|
||
if($v=='')$v=null;
|
||
$v=str_replace(',','.',$v); //Разделитель целой и дробной части точка
|
||
}else
|
||
if($t=='b'){
|
||
if($v=='') $v=null; else
|
||
if($v=='1') $v=true; else
|
||
if($v=='0') $v=false;
|
||
}else
|
||
if($t=='string' || $t=='dateTime' || $t=='date'){
|
||
if($v=='') $v=null;
|
||
}
|
||
return $v;
|
||
}
|
||
|
||
function getPDOTypeParam($t)
|
||
{
|
||
//if($t=='object' && gettype($v)=='string') $t='string'; //Если id шники uuid
|
||
|
||
if($t=='object')
|
||
{ //return PDO::PARAM_INT;
|
||
return PDO::PARAM_STR;
|
||
}else
|
||
if($t=='i4' || $t=='integer')
|
||
{ return PDO::PARAM_INT;
|
||
}else
|
||
if($t=='f8')
|
||
{ return PDO::PARAM_STR;
|
||
}else
|
||
if($t=='b')
|
||
{ return PDO::PARAM_BOOL;
|
||
}else
|
||
if($t=='string' || $t=='dateTime' || $t=='date')
|
||
{ return PDO::PARAM_STR;
|
||
}else
|
||
if($t=='blob')
|
||
{ return PDO::PARAM_LOB;
|
||
}else
|
||
return PDO::PARAM_STR;
|
||
}
|
||
|
||
//Заменить все значения первого фильтра значениями из второго
|
||
function setFilter($n1,$n2)
|
||
{
|
||
if($n1==null || $n2==null) return;
|
||
$nc1=$n1->firstChild;
|
||
while ($nc1)
|
||
{
|
||
if ($nc1->nodeName=='column')
|
||
{
|
||
$nc2=findNodeOnAttribute($n2, 'column', 'n', $nc1->getAttribute("n"));
|
||
if($nc2) getCdata($nc1)->nodeValue=getCdata($nc2)->nodeValue;
|
||
}
|
||
$nc1 = $nc1->nextSibling;
|
||
}
|
||
}
|
||
|
||
//Получить узел метаданных из базы данных
|
||
function getMetadataNode($name)
|
||
{
|
||
global $db,$Schema;
|
||
|
||
$xmls='';
|
||
$sql='select xml from '.$Schema.'_metadata where del=false and name=\''.$name.'\';';
|
||
$resX = $db->query($sql);
|
||
while ($rowX = $resX->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{
|
||
$xmls='<?xml version="1.0" encoding="UTF-8"?><metadata>'.trts($rowX['xml']).'</metadata>';
|
||
}
|
||
if($xmls!='')
|
||
{
|
||
//sendError(1,"Metadata node \"".$name."\" not find in database!");
|
||
$objXMLDocument = new DOMDocument();
|
||
try
|
||
{
|
||
$objXMLDocument->loadXML($xmls);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
$currNode=findNodeOnAttribute($objXMLDocument->documentElement, "type","n",$name);
|
||
return $currNode;
|
||
}else{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
function special_handler($exception)
|
||
{
|
||
sendError(1,$exception->getMessage());
|
||
}
|
||
set_exception_handler('special_handler'); //чтоб не пойманные исключения посылались в виде XML
|
||
|
||
//Схема базы по умолчанияю
|
||
if(!isset($Schema)) {
|
||
$Schema="";
|
||
}
|
||
//Тип идентификаторов
|
||
$idType="object";
|
||
if(!isset($idType)) {
|
||
$idType="object";
|
||
}
|
||
|
||
$db = connectToDB();
|
||
if($db==null)
|
||
sendError(1,trt('Error_connection_to_DB'));
|
||
|
||
//Пытаемся автоматически залогинется по GUID из COOKIE (TODO авторизация должна быть в отдельном файле! Смотри директорию password )
|
||
/*if($_SESSION['USER_ID']==null && $_COOKIE['GUID']!=null)
|
||
{
|
||
$res = $db->query("select * from ".$Schema."p__Login(null,null,null,'".$_COOKIE['GUID']."');");
|
||
//$res = $db->query("select * from p__Login_1(null,null,null,'".$_COOKIE['GUID']."');");
|
||
if($res->rowCount()>0)
|
||
{
|
||
$result = $res->fetch(PDO::FETCH_ASSOC);
|
||
$_SESSION['USER_ID']=$result['id'];
|
||
}
|
||
}*/
|
||
|
||
$fn=filter_input(INPUT_GET, 'fn', FILTER_VALIDATE_INT, array('options'=>array('default'=>-1)));
|
||
|
||
$HTTP_INPUT=file_get_contents("php://input");
|
||
if($HTTP_INPUT)
|
||
{
|
||
$doc = new DOMDocument();
|
||
try
|
||
{
|
||
$doc->loadXML($HTTP_INPUT);
|
||
} catch (Exception $e)
|
||
{
|
||
sendError(1,$e->getMessage());
|
||
}
|
||
$reqNode = $doc->documentElement;
|
||
|
||
if ($reqNode)
|
||
{
|
||
$fn = $reqNode->getAttribute("fn"); //Номер функции
|
||
}
|
||
}
|
||
|
||
//описание
|
||
//(fn==0) - отправить метаданные клиенту по запрошенному узлу
|
||
//(fn==1) - вставить одну запись в базу данных (результат id записи)
|
||
//(fn==2) - обновить запись
|
||
//(fn==3) - удалить запись
|
||
//(fn==4 || fn==11) - отправить данные клиенту соответствии с значением фильтра
|
||
//(fn==5) - взять данные для редактирования 1й записи по id
|
||
//(fn==6) - вернуть клиенту данные для заполнения обьекта SELECT выделенно в отдельную функцию для экономии трафика здесь могут также использоваться фильтры
|
||
//(fn==7) - залогинеться
|
||
//(fn==8) - отчёты почти тоже самое что и функция 4
|
||
//(fn==9) - Сохранить двоичные данные в базу
|
||
//(fn==10) - Получить двоичные данные из базы
|
||
|
||
if ($fn==0) //отправить метаданные клиенту по запрошенному узлу
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$typename=findFirstNode($reqNode, "type")->getAttribute("n");
|
||
$currNode=getMetadataNode($typename);
|
||
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
//Вернём значение прав доступа для запрошенного объекта
|
||
$allow_ins=false;
|
||
$allow_upd=false;
|
||
$allow_del=false;
|
||
$sql_query='select '.$Schema.'p_getaccess(:user_id1,:action_insert) as ins,'.$Schema.'p_getaccess(:user_id2,:action_update) as upd,'.$Schema.'p_getaccess(:user_id3,:action_delete) as del;';
|
||
$stmt = $db->prepare($sql_query);
|
||
$stmt->bindValue(':user_id1', $_SESSION['USER_ID'], PDO::PARAM_INT); //getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID'])
|
||
$stmt->bindValue(':user_id2', $_SESSION['USER_ID'], PDO::PARAM_INT); //getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID'])
|
||
$stmt->bindValue(':user_id3', $_SESSION['USER_ID'], PDO::PARAM_INT); //getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID'])
|
||
$stmt->bindValue(':action_insert', 'Insert_'.$typename, PDO::PARAM_STR);
|
||
$stmt->bindValue(':action_update', 'Update_'.$typename, PDO::PARAM_STR);
|
||
$stmt->bindValue(':action_delete', 'Delete_'.$typename, PDO::PARAM_STR);
|
||
$res=$stmt->execute();
|
||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
|
||
{
|
||
$allow_ins=$row['ins'] == 't';
|
||
$allow_upd=$row['upd'] == 't';
|
||
$allow_del=$row['del'] == 't';
|
||
}
|
||
$xmlAttr = $objXMLDocument->createAttribute("ins"); //insert
|
||
$xmlAttr->nodeValue = $allow_ins ? "1" : "0";
|
||
$currNode->setAttributeNode($xmlAttr);
|
||
$xmlAttr = $objXMLDocument->createAttribute("upd"); //update
|
||
$xmlAttr->nodeValue = $allow_upd ? "1" : "0";
|
||
$currNode->setAttributeNode($xmlAttr);
|
||
$xmlAttr = $objXMLDocument->createAttribute("del"); //delete
|
||
$xmlAttr->nodeValue = $allow_del ? "1" : "0";
|
||
$currNode->setAttributeNode($xmlAttr);
|
||
|
||
$allow=true;
|
||
$xmlAttr = $objXMLDocument->createAttribute("sel"); //select
|
||
$xmlAttr->nodeValue = $allow ? "1" : "0";
|
||
$currNode->setAttributeNode($xmlAttr);
|
||
|
||
//Удаляем все запросы из узла
|
||
for($i=0;$i<5;$i++)
|
||
{ $nsql=findFirstNode($currNode, "sql-query");
|
||
if($nsql!=NULL) $nsql->parentNode->removeChild($nsql);
|
||
}
|
||
|
||
$xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="0">'.$objXMLDocument->saveXML($currNode).'</metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xmlstring;
|
||
Exit();
|
||
}else
|
||
{
|
||
sendError(1,'Не найден запрошенный узел: "'.$typename.'"!');
|
||
}
|
||
}else
|
||
if ($fn==1) //вставка записи (результат id записи)
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$typename=findFirstNode($reqNode,"type")->getAttribute("n");
|
||
$currNode=getMetadataNode($typename);
|
||
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$sql_query=getCdataValue(findFirstNodeOnAttribute($currNode, "sql-query", "t", "i"));
|
||
|
||
$nodeProp=findFirstNode($reqNode,"properties");
|
||
//Представляем SQL в виде параметров
|
||
$nodePropData=$nodeProp->firstChild;
|
||
while($nodePropData != null)
|
||
{
|
||
if (($nodePropData->nodeName=="prop"))
|
||
{
|
||
//$vt=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("vt");
|
||
$nPropR = findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"));
|
||
if($nPropR!=NULL) { $vt=$nPropR->getAttribute("vt"); } else { $vt=''; }
|
||
|
||
if($vt=='blob')
|
||
{ $sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',':'.$nodePropData->getAttribute("n"),$sql_query);
|
||
//Название файла запишем в указаное поле
|
||
$val=getCdataValue($nodePropData);
|
||
$cd=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("cd");
|
||
$nd=findFirstNodeOnAttribute($nodeProp,'prop','n',$cd);
|
||
if($nd!=null) { getCdata($nd)->nodeValue=$val; }
|
||
}else if($vt=='file')
|
||
{
|
||
$val=getCdataValue($nodePropData);
|
||
$valSql=getSQLValue($vt, $val);
|
||
$sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',$valSql,$sql_query);
|
||
//Копируем файл из './temp/' в указанную папку относительно корня сайта
|
||
$flnm = afterLast($val,'_');
|
||
$dir = "./temp/";
|
||
if($val!='' && file_exists($dir.$flnm))
|
||
{
|
||
$path= $_SERVER['DOCUMENT_ROOT'].'/'.findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("path");
|
||
@mkdir($path); //Создаём папку если её нет
|
||
if(!rename($dir.$flnm, $path.$flnm))
|
||
sendError(1,'Can\'t rename to "'.$path.$v.'"!');
|
||
}
|
||
}else
|
||
{ $v=getSQLValue($vt, getCdataValue($nodePropData));
|
||
$sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',$v,$sql_query);
|
||
}
|
||
}
|
||
$nodePropData=$nodePropData->nextSibling;
|
||
}
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query); //Потому что PostgreSQL не может хранить id пользователя привязаного к сесии
|
||
|
||
$stmt = $db->prepare($sql_query);
|
||
if($stmt === false) sendError(1,'Error preparing Statement');
|
||
|
||
//присваеваем параметрам значения (В записи может быть только 1 двоичное поля см bindParam или сделать несколько переменных)
|
||
$nodePropData=$nodeProp->firstChild;
|
||
while($nodePropData != null)
|
||
{
|
||
if (($nodePropData->nodeName=="prop"))
|
||
{
|
||
//$vt=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("vt");
|
||
$nPropR = findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"));
|
||
if($nPropR!=NULL) { $vt=$nPropR->getAttribute("vt"); } else { $vt=''; }
|
||
|
||
//Если тип blob то в качастве параметра приходит название файла переданого на сервер заранее
|
||
if($vt=='blob')
|
||
{ $v=getCdataValue($nodePropData);
|
||
if($v!='' && file_exists('./temp/'.afterLast($v,'_')))
|
||
{ $v = fopen('./temp/'.afterLast($v,'_'), 'rb');
|
||
} else $v=null;
|
||
$stmt->bindParam(':'.$nodePropData->getAttribute("n"), $v, PDO::PARAM_LOB);
|
||
}
|
||
}
|
||
$nodePropData=$nodePropData->nextSibling;
|
||
}
|
||
try
|
||
{
|
||
$res = $stmt->execute();
|
||
} catch (Exception $e)
|
||
{
|
||
if(str_contains($e->getMessage(), ']]'))
|
||
sendError(1, $e->getMessage());
|
||
else
|
||
sendError(1, '[['.trt("SQL_query_error").']]'.$e->getMessage());
|
||
}
|
||
$result = $stmt->fetch(PDO::FETCH_NUM);
|
||
if($result[0]=='')
|
||
{
|
||
if(strpos($db_connection, 'sqlite')!==false) {
|
||
$result[0] = $db->lastInsertId(); //Для SQLite
|
||
}else{
|
||
sendError(1,trt('Failed_to_insert_record').'!');
|
||
}
|
||
}
|
||
|
||
$xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="1"><type n="'.$typename.'" id="'.$result[0].'"></type></metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xmlstring;
|
||
Exit();
|
||
}else
|
||
{
|
||
sendError(1,'Не найден запрошенный узел: "'.$typename.'"!');
|
||
}
|
||
}else
|
||
if ($fn==2) //редактирование (результат id записи)
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$nodeType=findFirstNode($reqNode,"type");
|
||
$typename=$nodeType->getAttribute("n");
|
||
$obj_id=$nodeType->getAttribute("id");
|
||
$node_properties=findFirstNode($nodeType,"properties");
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$sql_query=getCdataValue(findFirstNodeOnAttribute($currNode, "sql-query", "t", "u"));
|
||
//Представляем blob поля в SQL запросе в виде параметров
|
||
$nodeProps=findFirstNode($reqNode,"properties");
|
||
$nodePropData=$nodeProps->firstChild;
|
||
while($nodePropData != null)
|
||
{
|
||
if (($nodePropData->nodeName=="prop"))
|
||
{
|
||
//$vt=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("vt");
|
||
$nPropR = findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"));
|
||
if($nPropR!=NULL) { $vt=$nPropR->getAttribute("vt"); } else { $vt=''; }
|
||
|
||
if($vt=='blob')
|
||
{ $sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',':'.$nodePropData->getAttribute("n"),$sql_query);
|
||
//Название файла запишем в указаное поле
|
||
$val=getCdataValue($nodePropData);
|
||
$cd=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("cd"); //Имя поля с которого нужно брать название файла
|
||
$nd=findFirstNodeOnAttribute($nodeProps,'prop','n',$cd);
|
||
if($nd!=null) getCdata($nd)->nodeValue=$val;
|
||
}else if($vt=='file') //Файл который не загружается в базу а храниться в файловой системе
|
||
{
|
||
$val=getCdataValue($nodePropData);
|
||
$valSql=getSQLValue($vt, $val);
|
||
$sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',$valSql,$sql_query);
|
||
//Копируем файл в указанную папку относительно корня сайта
|
||
$flnm = afterLast($val,'_');
|
||
$dir = "./temp/";
|
||
if($val!='' && file_exists($dir.$flnm))
|
||
{
|
||
$path= $_SERVER['DOCUMENT_ROOT'].'/'.findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("path");
|
||
@mkdir($path);//Создаём папку если её нет
|
||
if(!rename($dir.$flnm, $path.$flnm))
|
||
sendError(1,'Can\'t rename to "'.$path.$v.'"!');
|
||
}
|
||
}else
|
||
{
|
||
$val=getSQLValue($vt, getCdataValue($nodePropData));
|
||
$sql_query=str_replace('${'.$nodePropData->getAttribute("n").'}',$val,$sql_query);
|
||
}
|
||
}
|
||
$nodePropData=$nodePropData->nextSibling;
|
||
}
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query); //Потому что PostgreSQL не может хранить id пользователя привязаного к сесии
|
||
$sql_query=str_replace('${'.$currNode->getAttribute("ObjectID").'}',getSQLValue(gettype($obj_id),$obj_id),$sql_query); //Так как пока идентификатор базы отдельно передаётся
|
||
|
||
//sendError(1,$sql_query);
|
||
$stmt = $db->prepare($sql_query);
|
||
if($stmt === false) sendError(1,'Error preparing Statement');
|
||
|
||
//Присваеваем параметру двоичную информацию (Внимание! Только 1 параметр может быть в 1 записи (почему?))
|
||
$pos_v = 0;
|
||
$mas_v[$pos_v]=null; //Чтобы данные не перекрывали друг друга при вставке
|
||
$nodePropData=$nodeProps->firstChild;
|
||
while($nodePropData != null)
|
||
{
|
||
if (($nodePropData->nodeName=="prop"))
|
||
{
|
||
//$vt=findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"))->getAttribute("vt");
|
||
$nPropR = findFirstNodeOnAttribute($currNode,"prop","n",$nodePropData->getAttribute("n"));
|
||
if($nPropR!=NULL) { $vt=$nPropR->getAttribute("vt"); } else { $vt=''; }
|
||
|
||
if($vt=='blob')
|
||
{
|
||
$path_v=getCdataValue($nodePropData);
|
||
if($path_v!='' && file_exists('./temp/'.afterLast($path_v,'_')))
|
||
{ $v = fopen('./temp/'.afterLast($path_v,'_'), 'rb');
|
||
}else
|
||
{ $v=null;
|
||
}
|
||
$mas_v[$pos_v]=$v;
|
||
$stmt->bindParam(':'.$nodePropData->getAttribute("n"), $mas_v[$pos_v], PDO::PARAM_LOB);
|
||
$pos_v++;
|
||
}
|
||
}
|
||
$nodePropData=$nodePropData->nextSibling;
|
||
}
|
||
|
||
try
|
||
{ $res = $stmt->execute();
|
||
} catch (Exception $e)
|
||
{
|
||
if(str_contains($e->getMessage(), ']]')) //If already sending short error text.
|
||
sendError(1, $e->getMessage());
|
||
else
|
||
sendError(1, '[['.trt("SQL_query_error").']]'.$e->getMessage()."\n".$sql_query);
|
||
}
|
||
$result = $stmt->fetch(PDO::FETCH_NUM); //$obj_id
|
||
if($result[0]==''){ $result[0]=$obj_id; }
|
||
$xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2"><type n="'.$typename.'" id="'.$result[0].'"></type></metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xmlstring;
|
||
Exit();
|
||
}else
|
||
{
|
||
sendError(1,'Не найден запрошенный узел: "'.$typename.'"!');
|
||
}
|
||
}else
|
||
if ($fn==3) //удаление (результат id записи)
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$nodeType=findFirstNode($reqNode,"type");
|
||
$typename=$nodeType->getAttribute("n");
|
||
$obj_id=$nodeType->getAttribute("id");
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$sql_query=getCdataValue(findFirstNodeOnAttribute($currNode, "sql-query", "t", "d"));
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query); //Потому что PostgreSQL не может хранить id пользователя привязаного к сесии
|
||
$sql_query=str_replace('${'.$currNode->getAttribute("ObjectID").'}',getSQLValue(gettype($obj_id),$obj_id),$sql_query);
|
||
|
||
//Выполняем
|
||
try
|
||
{ $res = $db->query($sql_query);
|
||
}catch (Exception $e)
|
||
{
|
||
if(str_contains($e->getMessage(), ']]')) //If already sending short error text.
|
||
sendError(1, $e->getMessage());
|
||
else
|
||
sendError(1, '[['.trt("SQL_query_error").']]'.$e->getMessage()."\n".$sql_query);
|
||
}
|
||
//записываем id удалённой записи для удаления без перезагрузки страницы через javascript
|
||
$xmlstring="";
|
||
$xmlstring.="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
|
||
$xmlstring.='<metadata fn="3">';
|
||
$xmlstring.=" <type n=\"".$typename."\" id=\"".$obj_id."\"></type>\n";
|
||
$xmlstring.="</metadata>\n";
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xmlstring;
|
||
Exit();
|
||
}else
|
||
{
|
||
sendError(1,'Не найден запрошенный узел: "'.$typename.'"!');
|
||
}
|
||
}else
|
||
if ($fn==4 || $fn==11) //взять данные из базы по переданным значениям фильтра ($fn==11 для обновления записи у клиента после вставки или редактировании)
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$rowspagecount = 100; //записей на страницу
|
||
$nTypeR=findFirstNode($reqNode,'type');
|
||
$typename=$nTypeR->getAttribute("n");
|
||
$pagepos=$nTypeR->getAttribute("pp"); //текущяя страница page pos
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$objListR = findFirstNode($nTypeR,'objects-list');
|
||
//В переданном запросе может быть не полный фильтр заполняем серверный значениями из переданного
|
||
$f1=findNodeOnPath($currNode,'objects-list/filter');
|
||
$f2=findNodeOnPath($nTypeR,'objects-list/filter');
|
||
setFilter($f1,$f2);//заменить все значения первого фильтра значениями из второго
|
||
|
||
$sql_query=getCdataValue(findNodeOnPath($currNode, "objects-list/sql-query"));
|
||
|
||
if($f1!=null)
|
||
{
|
||
$nextnode=$f1->firstChild;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ $vt=$nextnode->getAttribute("vt");
|
||
$val=getCdataValue($nextnode);
|
||
$val=getSQLValue($vt,$val);
|
||
$sql_query=str_replace('${'.$nextnode->getAttribute("n").'}',$val,$sql_query);
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
}
|
||
$vType=gettype($_SESSION['USER_ID']);
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
if($objListR!=null && $objListR->getAttribute('order')!='' && $objListR->getAttribute('order')!=null && $objListR->getAttribute('order')!='null')
|
||
{
|
||
$sql_query=str_replace('${_order}',getSQLValue('i4',findNodeOnAttribute(findFirstNode($currNode,'objects-list'), "column","n",$objListR->getAttribute("order"))->getAttribute("order")),$sql_query);
|
||
}else $sql_query=str_replace('${_order}','1',$sql_query);
|
||
|
||
//sendError(1,$sql_query);
|
||
//Выполняем запрос
|
||
try
|
||
{ $res = $db->query($sql_query);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage().' '.$sql_query);
|
||
}
|
||
//Формируем ответ
|
||
$pagecount=ceil($res->rowCount()/$rowspagecount); //Кол-во страниц
|
||
|
||
//В месте с фильтром может прити и название полей которые нужно выбрать если есть хоть 1 поле то выберать только его
|
||
$columns = array();
|
||
$nextnode=findNode($nTypeR,'objects-list');
|
||
if($nextnode)
|
||
{ $nextnode=$nextnode->firstChild;//Пытаемся заполнить из запроса
|
||
$i=0;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ $columns[$i]=$nextnode->getAttribute("n");
|
||
$i++;
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
}
|
||
if(count($columns)==0)//Если нет ни одного столбца заполняем массив из серверного XML
|
||
{
|
||
$nextnode=findNode($currNode,'objects-list');
|
||
if($nextnode)
|
||
{ $nextnode=$nextnode->firstChild;//Пытаемся заполнить из запроса
|
||
$i=0;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ $columns[$i]=$nextnode->getAttribute("n");
|
||
$i++;
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
}
|
||
}
|
||
|
||
//перебираем RS и строим XML только из тех столбцов которые записанны в секци objects-list поля column в не зависимости от их видимости
|
||
$obj = new StdClass();
|
||
$obj->errorCode=0;
|
||
$obj->errorMessage = '';
|
||
$obj->fn=$fn;
|
||
$obj->n=$typename;
|
||
$obj->pc=$pagecount;
|
||
$obj->pp=$pagepos;
|
||
//Перечисляю название выбираемых столбцов через запятую (почему в JAVA версии этого куска кода нет?)
|
||
$obj->objects_list=[];
|
||
$nextnode=findNode($currNode,'objects-list')->firstChild;
|
||
while ($nextnode)
|
||
{
|
||
if ($nextnode->nodeName=='column')
|
||
{
|
||
array_push($obj->objects_list,$nextnode->getAttribute("n"));
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
$obj->data=[];
|
||
|
||
$node=findFirstNode($reqNode,'objects-list');
|
||
$pos=-1;
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{
|
||
$pos++;
|
||
if (($pagepos!=-1)&&(($pos<($pagepos*$rowspagecount))||($pos>=$pagepos*$rowspagecount+$rowspagecount))) { continue; }
|
||
|
||
array_push($obj->data,new StdClass());
|
||
|
||
//разрешать или запрещять редактировать запись надо проверять в хранимке а также запрещять либо разрешать редактировать колонку
|
||
//для каждой записи формируеться строка настроек со значениями что нужно запретить в таком виде "iuds"
|
||
$access=''; //u = enable update field, d = enable delete field
|
||
if(!array_key_exists("_u",$row)) { $access.="u"; } else { $access.=$row["_u"]; }
|
||
if(!array_key_exists("_d",$row)) { $access.="d"; } else { $access.=$row["_d"]; }
|
||
|
||
if(array_key_exists($currNode->getAttribute("ObjectID"),$row)) {
|
||
end($obj->data)->id=$row[$currNode->getAttribute("ObjectID")];
|
||
end($obj->data)->a=$access;
|
||
}else {
|
||
end($obj->data)->id="";
|
||
end($obj->data)->a=$access;
|
||
}
|
||
|
||
end($obj->data)->row=[];
|
||
|
||
$nextnode=findNode($currNode,'objects-list')->firstChild;
|
||
while ($nextnode)
|
||
{
|
||
if ($nextnode->nodeName=='column')
|
||
{
|
||
if(array_key_exists($nextnode->getAttribute("n"),$row))
|
||
{
|
||
$field = $nextnode->getAttribute("n");
|
||
array_push(end($obj->data)->row,$row[$field]);
|
||
}else
|
||
{
|
||
sendError(1,"Column \"".$nextnode->getAttribute("n")."\" not exists in \"$typename\" for select!");
|
||
}
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
}
|
||
$res->closeCursor();
|
||
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo json_encode($obj);
|
||
exit;
|
||
}else
|
||
{
|
||
sendError(1,"Не найден запрошеный узел!");
|
||
}
|
||
}else
|
||
if ($fn==5) //вернуть клиенту данные по id для редактирования одной записи
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$sql_query='';
|
||
$node=findFirstNode($reqNode,'type');
|
||
$typename=$node->getAttribute("n");
|
||
$idval=$node->getAttribute("id"); //Значение идентификатора
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
//Тип поля с ObjectID
|
||
$nField=findFirstNodeOnAttribute(findNode($currNode, 'properties'), "prop", "n", $node->getAttribute('ObjectID'));
|
||
$csql=findNode(findFirstNodeOnAttribute($currNode, "sql-query", "t", "s"), "#cdata-section");
|
||
if($csql!=NULL && $csql->nodeValue!="") //Есть ли SQL запрос
|
||
{
|
||
$sql_query=$csql->nodeValue;
|
||
$sql_query=str_replace('${'.$node->getAttribute("ObjectID").'}',getSQLValue($nField->getAttribute('vt'),$idval),$sql_query);
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
}
|
||
}
|
||
//sendError(1,$sql_query);
|
||
try
|
||
{
|
||
$res = $db->query($sql_query);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
if(strpos($db_connection, 'sqlite')===false) //Для SQLite не работает rowCount()
|
||
{
|
||
if($res->rowCount()!=1) sendError(1,"Количество записей не равно одному!");
|
||
}
|
||
|
||
$xmls='';
|
||
$resX = $db->query('select xml from '.$Schema.'_metadata where del=false and name=\''.$typename.'\';');
|
||
while ($rowX = $resX->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{
|
||
$xmls='<?xml version="1.0" encoding="UTF-8"?><metadata>'.trts($rowX['xml']).'</metadata>';
|
||
}
|
||
if($xmls=='')
|
||
{
|
||
sendError(1,"Metadata node \"".$name."\" is empty!");
|
||
}
|
||
|
||
//загружаем мета данные и смотрим какие поля должны передать клиенту
|
||
$mdoc = new DOMDocument();
|
||
try
|
||
{
|
||
$mdoc->loadXML($xmls);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
//находим нужный узел
|
||
$node=findNodeOnAttribute($mdoc->documentElement, "type","n",$typename);
|
||
$node=findFirstNode($node,'properties');
|
||
|
||
$xmlstring='<?xml version="1.0" encoding="utf-8"?>'."\n";
|
||
$xmlstring.='<metadata fn="5">'."\n";
|
||
$xmlstring.='<type n="'.$typename.'" id="'.$idval.'">'."\n";
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{ $xmlstring.='<properties>';
|
||
$nextnode=$node->firstChild;
|
||
while($nextnode)
|
||
{
|
||
if($nextnode->nodeName=='prop')
|
||
{
|
||
try
|
||
{
|
||
if(array_key_exists ( $nextnode->getAttribute("n"), $row) || ($nextnode->getAttribute("vt")=="file" && array_key_exists ( $nextnode->getAttribute("cd"), $row)))
|
||
{
|
||
if($nextnode->getAttribute("vt")=="b")
|
||
{
|
||
if($row[$nextnode->getAttribute("n")]===false)
|
||
{
|
||
$row[$nextnode->getAttribute("n")]="0";
|
||
} else if($row[$nextnode->getAttribute("n")]===true)
|
||
{
|
||
$row[$nextnode->getAttribute("n")]="1";
|
||
}
|
||
}
|
||
|
||
if($nextnode->getAttribute("vt")=="blob") { //Только blob не file так как file как обычная текстовая строка (100 символов)
|
||
if(array_key_exists($nextnode->getAttribute("cd"), $row)) {
|
||
$xmlstring .= '<prop n="' . $nextnode->getAttribute("n") . '"><![CDATA[' . $row[$nextnode->getAttribute("cd")] . ']]></prop>' . "\n";
|
||
}else{
|
||
sendError(1,'Поле "'.$nextnode->getAttribute("cd").'" не найдено в результирующем наборе!');
|
||
}
|
||
}
|
||
else {
|
||
$xmlstring.='<prop n="'.$nextnode->getAttribute("n").'"><![CDATA['.$row[$nextnode->getAttribute("n")].']]></prop>'."\n";
|
||
}
|
||
}else
|
||
{
|
||
sendError(1,'Поле "'.$nextnode->getAttribute("n").'" не найдено в результирующем наборе!');
|
||
}
|
||
|
||
} catch (Exception $e) { sendError(1,$e->getMessage()); }
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
$xmlstring.='</properties>';
|
||
}
|
||
$xmlstring.='</type>';
|
||
$xmlstring.='</metadata>';
|
||
|
||
header('Content-type: text/xml');
|
||
echo $xmlstring;
|
||
}else
|
||
if ($fn==6) //вернуть клиенту данные колонки таблицы для заполнения выпадающего списка SELECT либо выборка названия поля типа object
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
$tNodeR=findFirstNode($reqNode,'type');
|
||
$typename=$tNodeR->getAttribute("n"); //Название принятого узла
|
||
$columnname=$tNodeR->getAttribute("c"); //Столбец для выбора (через , могут перечислятся)
|
||
$columns=explode(",",$columnname);
|
||
$propName=$tNodeR->getAttribute("pn"); //Название поля <prop> нигде не используется передаётся обратно в результат
|
||
//Теперь а нутри фильтра передаётся поэтому ненужно $propid=$tNodeR->getAttribute("id"); //-1 или '' то много записей иначе 1 должна вернуться
|
||
//if($propid==-1 || $propid=='') $propid='NULL';
|
||
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
if($currNode==null) sendError(1,"Not find \"".$typename."\"!");
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$objListR = findFirstNode($tNodeR,'objects-list'); //Из запроса
|
||
$f1=findNodeOnPath($currNode, 'objects-list/filter');
|
||
$f2=findNodeOnPath($tNodeR,'objects-list/filter');
|
||
|
||
setFilter($f1,$f2);//заменить все значения первого фильтра значениями из второго
|
||
|
||
$sql_query=getCdataValue(findNodeOnPath($currNode, "objects-list/sql-query"));
|
||
if($f1!=NULL)
|
||
{
|
||
$nextnode=$f1->firstChild;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ $val=getSQLValue($nextnode->getAttribute("vt"),getCdata($nextnode)->nodeValue);
|
||
$sql_query=str_replace('${'.$nextnode->getAttribute("n").'}',$val,$sql_query);
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
}
|
||
//$sql_query=str_replace('${'.$currNode->getAttribute("ObjectID").'}',getSQLValue(gettype($propid),$propid),$sql_query); //Чтоб вернулась 1 запись если это не выпадающий
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
if($objListR!=null && $objListR->getAttribute('order')!='' && $objListR->getAttribute('order')!=null && $objListR->getAttribute('order')!='null')
|
||
{
|
||
$sql_query=str_replace('${_order}',findNodeOnAttribute(findFirstNode($currNode,'objects-list'), "column","n",$objListR->getAttribute("order"))->getAttribute("order"),$sql_query);
|
||
}else $sql_query=str_replace('${_order}','1',$sql_query);
|
||
|
||
try
|
||
{ $res = $db->query($sql_query);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
|
||
//выбираем данные из базы и отправляем клиенту
|
||
$xmlstring='<?xml version="1.0" encoding="utf-8"?>'."\n";
|
||
$xmlstring.='<metadata fn="6">'."\n";
|
||
$xmlstring.='<type n="'.$typename.'" pn="'.$propName.'">'."\n";
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{
|
||
$xmlstring.='<record id="'.$row[$currNode->getAttribute("ObjectID")].'">';
|
||
$val="";
|
||
for($i=0;$i<count($columns);$i++)
|
||
{
|
||
if ($val!="") $val.=" ";
|
||
if(array_key_exists($columns[$i],$row))
|
||
{
|
||
$val.=$row[$columns[$i]];
|
||
}else
|
||
{
|
||
sendError(1,"Column \"$columns[$i]\" not exists in \"$typename\" for select to drop down list!");
|
||
}
|
||
}
|
||
$xmlstring.='<![CDATA['.$val.']]>';
|
||
$xmlstring.='</record>'."\n";
|
||
}
|
||
$xmlstring.='</type>'."\n";;
|
||
$xmlstring.='</metadata>'."\n";;
|
||
header('Content-type: text/xml');
|
||
echo $xmlstring;
|
||
}else
|
||
if ($fn==7)//Залогинеться
|
||
{
|
||
$cmd=getCdataValue(findFirstNode($reqNode,"cmd"));
|
||
$login=getCdataValue(findFirstNode($reqNode,"login"));
|
||
$password=getCdataValue(findFirstNode($reqNode,"password"));
|
||
$key=getCdataValue(findFirstNode($reqNode,"key"));
|
||
$time=getCdataValue(findFirstNode($reqNode,"time"));
|
||
$guid=getCdataValue(findFirstNode($reqNode,"guid")); //Зачем коментил?
|
||
|
||
if($cmd==0) //Restore password by email
|
||
{
|
||
$recovery=false;
|
||
$res = $db->query("select email from ".$Schema."_Users where del=false and (email = '$login' or login = '$login');");
|
||
if($res->rowCount()>0)
|
||
{
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
|
||
/*$pos++;
|
||
if (($pagepos!=-1)&&(($pos<($pagepos*$rowspagecount))||($pos>=$pagepos*$rowspagecount+$rowspagecount))) { continue; }
|
||
|
||
//разрешать или запрещять редактировать запись надо проверять в хранимке а также запрещять либо разрешать редактировать колонку
|
||
//для каждой записи формируеться строка настроек со значениями что нужно запретить в таком виде "iuds"
|
||
//$access=$row["access"];
|
||
$access=''; //u = enable update field, d = enable delete field
|
||
if(!array_key_exists("_u",$row)) { $access.="u"; } else { $access.=$row["email"]; }*/
|
||
|
||
$password = getPassword(6);
|
||
$sql = 'update ' . $Schema . '_users set password=md5(:password) where email=:email';
|
||
$stmt = $db->prepare($sql);
|
||
$stmt->bindValue(':password', $password, PDO::PARAM_STR);
|
||
$stmt->bindValue(':email', $row["email"], PDO::PARAM_STR);
|
||
try {
|
||
$stmt->execute();
|
||
if ($stmt->rowCount() > 0) {
|
||
//$result = $stmt->fetch(PDO::FETCH_NUM);
|
||
$recovery = true;
|
||
}
|
||
} catch (Exception $e) {
|
||
$db->rollBack();
|
||
sendError(1, $e->getMessage());
|
||
}
|
||
|
||
$html = '<html><head><title>Message</title></head><body>';
|
||
$html .= '<h1>New password:</h1>';
|
||
$html .= '<b>' . $password . '</b>';
|
||
$html .= '</body></html>';
|
||
//mail($login,'rigor.kz','Not implement',"Content-type: text/html; charset=utf-8\r\nFrom: rigor Site <info@rigor.kz>");
|
||
if (!mail($login, 'Password for monitoring', $html, "Content-type: text/html; charset=utf-8\r\nFrom: Transit Site <no-reply@istt.kz>")) {
|
||
sendError(1,"Failed to send mail to: " . $row["email"]);
|
||
}
|
||
}
|
||
}
|
||
if($recovery) {
|
||
$xs = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
||
$xs .= '<metadata fn="7"><![CDATA[OK]]></metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xs;
|
||
exit();
|
||
}else{
|
||
$xs = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
||
$xs .= '<metadata fn="7"><![CDATA[ERROR]]></metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xs;
|
||
exit();
|
||
}
|
||
|
||
}elseif($cmd==1) //Logout
|
||
{
|
||
$sql='delete from '.$Schema.'_Logins where sessionid='.getSQLValue('string',$_COOKIE['GUID']).' and user_id='.getSQLValue('object',$_SESSION['USER_ID']).';';
|
||
try
|
||
{ $db->exec($sql);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
unset($_SESSION['USER_ID']);
|
||
|
||
$xs='<?xml version="1.0" encoding="utf-8"?>'."\n";
|
||
$xs.='<metadata fn="7">'."\n";
|
||
$xs.=' <cmd><![CDATA['.$cmd.']]></cmd><login><![CDATA[0]]></login><sesid><![CDATA['.session_id().']]></sesid><sesname><![CDATA['.session_name().']]></sesname>'."\n";
|
||
$xs.='</metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xs;
|
||
exit();
|
||
|
||
}elseif($cmd==2) //Проверить залогинен ли пользователь
|
||
{
|
||
$xs='<?xml version="1.0" encoding="utf-8"?>'."\n";
|
||
$xs.='<metadata fn="7">'."\n";
|
||
if(!isset($_SESSION['USER_ID']) || $_SESSION['USER_ID']=='')
|
||
{
|
||
$xs.=' <![CDATA[0]]><cmd><![CDATA['.$cmd.']]></cmd>'."\n";
|
||
}else
|
||
{
|
||
$xs.=' <![CDATA[1]]><cmd><![CDATA['.$cmd.']]></cmd>'."\n";
|
||
$res = $db->query('select * from '.$Schema.'p__Login('.getSQLValue($idType,$_SESSION['USER_ID']).',null,null,null,null,null);');
|
||
if($row = $res->fetch(PDO::FETCH_ASSOC))
|
||
{
|
||
$xs.=' <name><![CDATA['.$row['name'].']]></name>'."\n";
|
||
$xs.=' <surname><![CDATA['.$row['surname'].']]></surname>'."\n";
|
||
$xs.=' <patronymic><![CDATA['.$row['patronymic'].']]></patronymic>'."\n";
|
||
$xs.=' <company_id><![CDATA['.$row['company_id'].']]></company_id>'."\n";
|
||
$xs.=' <expiration><![CDATA['.$row['expiration'].']]></expiration>'."\n";
|
||
$xs.=' <overdue><![CDATA['.$row['overdue'].']]></overdue>'."\n";
|
||
}
|
||
}
|
||
$xs.='</metadata>';
|
||
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xs;
|
||
exit();
|
||
|
||
}elseif ($cmd==3) //Авторизация по логину и паролю
|
||
{
|
||
//По идентификатору выбираем информацию о пользователе
|
||
$ans='0';
|
||
$name='';
|
||
$surname='';
|
||
$patronymic='';
|
||
$expiration=false;
|
||
$overdue=false;
|
||
$sql="select * from ".$Schema."p__Login(".getSQLValue($idType,$_SESSION['USER_ID']).",'$login','$password',null,null,null);";
|
||
try
|
||
{
|
||
$res = $db->query($sql);
|
||
} catch (Exception $e)
|
||
{
|
||
if(str_contains($e->getMessage(), ']]'))
|
||
sendError(1, $e->getMessage());
|
||
else
|
||
sendError(1, '[['.trt("SQL_query_error").']]'.$e->getMessage());
|
||
}
|
||
if($res->rowCount()>0)
|
||
{
|
||
$result = $res->fetch(PDO::FETCH_ASSOC);
|
||
$ans='1';
|
||
$_SESSION['USER_ID']=$result['id'];
|
||
$name=$result['name'];
|
||
$surname=$result['surname'];
|
||
$patronymic=$result['patronymic'];
|
||
$expiration=$result['expiration']; //Дата смены пароля
|
||
$overdue=$result['overdue']; //Просрочен ли пароль
|
||
//Проверяю на соответствие токену TOPT если секретный ключ задан
|
||
if($result['secret']){
|
||
$secret = Base32::decode($result['secret']);
|
||
$genkey = (new Totp('sha1',0,60))->GenerateToken($secret,$time);
|
||
if($key != $genkey) {
|
||
$ans = '0';
|
||
$_SESSION['USER_ID'] = '';
|
||
}
|
||
}
|
||
}
|
||
$xs='<?xml version="1.0" encoding="utf-8"?>'."\n";
|
||
$xs.='<metadata fn="7">'."\n";
|
||
$xs.='<![CDATA['.$ans.']]>';
|
||
$xs.=' <cmd><![CDATA['.$cmd.']]></cmd>'."\n";
|
||
$xs.=' <login><![CDATA['.$ans.']]></login>'."\n";
|
||
$xs.=' <name><![CDATA['.$name.' '.$surname.' '.$patronymic.']]></name>'."\n";
|
||
$xs.=' <sesid><![CDATA['.session_id().']]></sesid>'."\n";
|
||
$xs.=' <sesname><![CDATA['.session_name().']]></sesname>'."\n";
|
||
$xs.=' <expiration><![CDATA['.$expiration.']]></expiration>'."\n";
|
||
$xs.=' <overdue><![CDATA['.$overdue.']]></overdue>'."\n";
|
||
$xs.='</metadata>';
|
||
header('Content-type: text/xml');
|
||
header("Cache-Control: no-cache, must-revalidate");
|
||
echo $xs;
|
||
exit();
|
||
}else{
|
||
sendError(1,'Command "'.$cmd.'" not find!');
|
||
}
|
||
|
||
}else
|
||
if ($fn==8)//Получить отчёт как Excel.xls файл (почти тоже самое что и функция 4)
|
||
{
|
||
$dir='./temp/'; //$tmpfname = tempnam($dir, "");
|
||
// отправка файла в отдельном файле download.php для совместимости с java версией
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
|
||
//Выбираем информацию о текущем пользователе
|
||
$name='';
|
||
$sql="select Coalesce(surname,'') || ' ' || Coalesce(name,'') || ' ' || Coalesce(patronymic,'') as name from ".$Schema."_users where id=:user_id;";
|
||
$stmt = $db->prepare($sql);
|
||
$stmt->bindValue(':user_id', $_SESSION['USER_ID'], PDO::PARAM_INT);
|
||
$res=$stmt->execute();
|
||
if($res && $stmt->rowCount()>0)
|
||
{ $result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
$name='<i>'.$result['name'].'</i><br>';
|
||
}
|
||
$res=null; //Чтоб сработал сборщик мусора, а то вываливается ошибка: "Cannot execute queries while other unbuffered queries are active".
|
||
|
||
$nTypeR=findFirstNode($reqNode,'type');
|
||
$typename=$nTypeR->getAttribute("n");
|
||
$ext=$nTypeR->getAttribute("ext");
|
||
|
||
$currNode=getMetadataNode($typename);
|
||
if ($currNode!=null)
|
||
{
|
||
$objXMLDocument=$currNode->ownerDocument;
|
||
|
||
$objListR = findFirstNode($nTypeR,'objects-list');
|
||
//В переданном запросе может быть не полный фильтр заполняем серверный значениями из переданного
|
||
$f1=findNodeOnPath($currNode,'objects-list/filter');
|
||
$f2=findNodeOnPath($nTypeR,'objects-list/filter');
|
||
setFilter($f1,$f2);//заменить все значения первого фильтра значениями из второго
|
||
|
||
//Текстовые данные заполняются в поле caption и они вставляются в поля для информации что было заполнено
|
||
//Выбираем параметры фильтра (Для информирования что было заполнено)
|
||
$filter='<b>'.trt('Filter_options').'</b><br>';
|
||
$nextnode=$f1->firstChild;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{
|
||
if($nextnode->getAttribute('visible')!='0')
|
||
{
|
||
$filter.='<i>'.$nextnode->getAttribute("d").': </i>';
|
||
if($nextnode->getAttribute("vt")=='object')
|
||
{
|
||
if(getCdataValue($nextnode)=='')
|
||
{ $filter.='';
|
||
}else
|
||
{
|
||
//Ищем нужный узел и выполняем запрос
|
||
$nTypeO=getMetadataNode($nextnode->getAttribute("object"));
|
||
//$nTypeO=findNodeOnAttribute($objXMLDocument->documentElement,"type","n",$nextnode->getAttribute("object"));
|
||
$sql_query=getCdataValue(findNodeOnPath($nTypeO, "objects-list/sql-query"));
|
||
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
|
||
$nOID=findNodeOnAttribute(findNodeOnPath($nTypeO, "objects-list/filter"), 'column', 'n', $nTypeO->getAttribute('ObjectID'));
|
||
$sql_query=str_replace('${'.$nOID->getAttribute('n').'}',getSQLValue($nOID->getAttribute('vt'), getCdataValue($nextnode)),$sql_query);
|
||
|
||
//Обнуляем остальные значения фильтра
|
||
$nCol=findNodeOnPath($nTypeO, "objects-list/filter")->firstChild;
|
||
while ($nCol)
|
||
{ if ($nCol->nodeName=='column')
|
||
{ $sql_query=str_replace('${'.$nCol->getAttribute("n").'}','NULL',$sql_query);
|
||
}
|
||
$nCol = $nCol->nextSibling;
|
||
}
|
||
|
||
$res=null;
|
||
try
|
||
{ $res = $db->query($sql_query);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage());
|
||
}
|
||
if($res->rowCount()!=1) sendError(1,trt('The number of records is not equal to one!').' '.$sql_query);
|
||
|
||
|
||
$columns=explode(",",$nextnode->getAttribute('FieldCaption'));
|
||
if($res->rowCount()>0)
|
||
{
|
||
$row = $res->fetch(PDO::FETCH_ASSOC);
|
||
for($i=0;$i<count($columns);$i++)
|
||
{
|
||
$filter.=$row[$columns[$i]].' ';
|
||
}
|
||
}
|
||
|
||
$res=null; //Чтоб сработал сборщик мусора, а то вываливается ошибка: "Cannot execute queries while other unbuffered queries are active".
|
||
}
|
||
}else if($nextnode->getAttribute("vt")=='b')
|
||
{
|
||
if(getCdataValue($nextnode)=='1') $filter.='Да';
|
||
if(getCdataValue($nextnode)=='0') $filter.='Нет';
|
||
}else
|
||
{
|
||
$filter.=getCdataValue($nextnode);
|
||
}
|
||
$filter.='<br>';
|
||
}
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
|
||
$sql_query=getCdataValue(findNodeOnPath($currNode, "objects-list/sql-query"));
|
||
$nextnode=$f1->firstChild;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ $vt=$nextnode->getAttribute("vt");
|
||
$val=getCdataValue($nextnode);
|
||
$val=getSQLValue($vt,$val);
|
||
$sql_query=str_replace('${'.$nextnode->getAttribute("n").'}',$val,$sql_query);
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
if($objListR!=null && $objListR->getAttribute('order')!='' && $objListR->getAttribute('order')!=null && $objListR->getAttribute('order')!='null')
|
||
{
|
||
$sql_query=str_replace('${_order}',findNodeOnAttribute(findFirstNode($currNode,'objects-list'), "column","n",$objListR->getAttribute("order"))->getAttribute("order"),$sql_query);
|
||
}else $sql_query=str_replace('${_order}','1',$sql_query);
|
||
|
||
//Выполняем запрос
|
||
try
|
||
{ $res = $db->query($sql_query);
|
||
} catch (Exception $e)
|
||
{ sendError(1,$e->getMessage().$sql_query);
|
||
}
|
||
|
||
//Сохраняем результсет в файл в виде HTML с расширением XLS
|
||
$num=rand(0,1000);
|
||
$file='file_'.$num.'.xls';
|
||
$myFile = $dir.$file;
|
||
|
||
if(($fh = @fopen($myFile, 'w')) !== FALSE){
|
||
fwrite($fh, '<html>'."\n");
|
||
fwrite($fh, ' <head>'."\n");
|
||
fwrite($fh, ' <title>'.$currNode->getAttribute("d").'</title>'."\n");
|
||
fwrite($fh, ' <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'."\n");
|
||
fwrite($fh, '<style>td {mso-number-format: "\@";}</style>');
|
||
fwrite($fh, ' </head>'."\n");
|
||
fwrite($fh, ' <body>'."\n");
|
||
|
||
fwrite($fh, '<b>'.trt('Time_and_date_of_generation').': </b><i>'.date('H:i:s m.d.Y').'</i><br>');
|
||
fwrite($fh, '<b>'.trt('Creator').': </b>'.$name);
|
||
fwrite($fh, $filter);
|
||
|
||
fwrite($fh, ' <table border="1" cellspacing="0">'."\n");
|
||
fwrite($fh, ' <caption><b>'.findNode($currNode,'objects-list')->getAttribute("d").'</b></caption>'."\n");
|
||
fwrite($fh, ' <thead>'."\n");
|
||
fwrite($fh, ' <tr>');
|
||
fwrite($fh, '<td bgcolor="#d1d1d1">№</td>');
|
||
$nextnode=findNode($currNode,'objects-list')->firstChild;
|
||
$col=0;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{ fwrite($fh, '<td bgcolor="#d1d1d1" width="'.$nextnode->getAttribute("width").'px"><b>'.$nextnode->getAttribute("d")."</b></td>");
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
fwrite($fh, ' </tr>'."\n");
|
||
fwrite($fh, ' </thead>'."\n");
|
||
fwrite($fh, ' <tbody>'."\n");
|
||
$pos=0;
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC))
|
||
{
|
||
fwrite($fh, ' <tr>');
|
||
fwrite($fh, '<td>'.(++$pos).'</td>');
|
||
$nextnode=findNode($currNode,'objects-list')->firstChild;
|
||
while ($nextnode)
|
||
{ if ($nextnode->nodeName=='column')
|
||
{
|
||
fwrite($fh, '<td>'.$row[$nextnode->getAttribute("n")].'</td>');
|
||
}
|
||
$nextnode = $nextnode->nextSibling;
|
||
}
|
||
fwrite($fh, '</tr>'."\n");
|
||
}
|
||
$res->closeCursor(); //Мож поможет избавиться от ошибки: "Cannot execute queries while other unbuffered queries are active."
|
||
|
||
fwrite($fh, ' </tbody>'."\n");
|
||
fwrite($fh, ' </table>'."\n");
|
||
|
||
fwrite($fh, ' </body>'."\n");
|
||
fwrite($fh, '</html>'."\n");
|
||
|
||
fclose($fh);
|
||
}else{
|
||
sendError(1,trt('Failed_to_generate_report'));
|
||
}
|
||
|
||
/*if($ext=="pdf")
|
||
{
|
||
//Если в виде PDF
|
||
$mpdf = new mPDF('utf-8', 'A4', '8', '', 10, 10, 7, 7, 10, 10); // задаем формат, отступы и.т.д.
|
||
$mpdf->list_indent_first_level = 0;
|
||
$mpdf->WriteHTML(file_get_contents($myFile)); // формируем pdf
|
||
|
||
$dir='./temp/';
|
||
$file='file_'.$num.'.pdf';
|
||
$myFile = $dir.$file;
|
||
|
||
$mpdf->Output($myFile, 'F');
|
||
}*/
|
||
//$myFile=getFullPath().'temp/'.$file;
|
||
|
||
//отправляем ссылку на файл TODO переделать в JSON
|
||
header('Content-type: text/xml');
|
||
echo '<?xml version="1.0" encoding="utf-8"?><metadata fn="8"><file><![CDATA['.$num.']]></file></metadata>';
|
||
|
||
}else
|
||
{
|
||
sendError(1,trt('Not found the requested node:').' "'.$typename.'"!');
|
||
}
|
||
|
||
}else
|
||
if ($fn==9) //Сохранить файл во временную папку
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
$dir = "./temp/";
|
||
if (!file_exists($dir)) {
|
||
mkdir($dir, 0777);
|
||
}
|
||
|
||
//Так как у файлов могут быть одинаковые имена считаем CRC и переименовываем файл отправля пользователю новое название файла
|
||
//В базе данных название файла будет преобразовываться так: "файл.txt" -> "файл_crc32.txt"
|
||
if(isset($_FILES['file']))
|
||
{
|
||
if(file_exists($_FILES['file']['tmp_name']))
|
||
{
|
||
$hash = hash_file( 'crc32', $_FILES['file']['tmp_name'] );
|
||
if(move_uploaded_file($_FILES['file']['tmp_name'],delPHPExt($dir.$hash.'.'.strtolower(getExtension($_FILES['file']['name'])))))
|
||
{
|
||
//Отправляем новое название файла клиенту
|
||
print "ok=".beforeLast($_FILES['file']['name'],'.').'_'.$hash.'.'.strtolower(getExtension($_FILES['file']['name']))."\n";
|
||
}
|
||
}else { print "ok=\n File \"".$_FILES['file']['tmp_name']."\" not find"; }
|
||
}
|
||
|
||
//Данный код загружается в iframe
|
||
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">';
|
||
print '<html>';
|
||
print ' <head>';
|
||
print ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
|
||
print ' </head>';
|
||
print ' <body>';
|
||
print ' <form name="form" enctype="multipart/form-data" action="records.php?fn=9" method="post">';
|
||
print ' <input type="hidden" name="state" value=""/>';
|
||
print ' <input type="file" name="file"><br/>';
|
||
print ' <input type="submit" value="Send File">';
|
||
print ' <input type="reset" value="Reset">';
|
||
print ' </form>';
|
||
print ' </body>';
|
||
print '</html>';
|
||
|
||
//Отчищяем временные файлы которые больше суток на сервере
|
||
deleteTempFiles($dir);
|
||
|
||
}else
|
||
if ($fn==10) //Отправить двоичные данные клиенту в виде файла (пока без докачки)
|
||
{
|
||
session_write_close(); //Разблокируем сессионный файл так как запросы могут быть достаточно долгими
|
||
//Клиент передаёт название таблицы, название поля, id поля
|
||
$typename = $_REQUEST['t']; //Тип
|
||
$field = $_REQUEST['f']; //Название поля с двоичными данными
|
||
$name = $_REQUEST['n']; //поле с названием файла
|
||
$idval = $_REQUEST['i']; //Идентификатор поля в базе
|
||
|
||
$xmls='';
|
||
$resX = $db->query('select xml from '.$Schema.'_metadata where del=false and name=\''.$typename.'\';');
|
||
while ($rowX = $resX->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
|
||
{
|
||
$xmls='<?xml version="1.0" encoding="UTF-8"?><metadata>'.trts($rowX['xml']).'</metadata>';
|
||
}
|
||
if($xmls=='')
|
||
{
|
||
sendError(1,"Metadata node \"".$name."\" is empty!");
|
||
}
|
||
|
||
//Ищем поле в метаданных
|
||
$objXMLDocument = new DOMDocument();
|
||
try
|
||
{
|
||
$objXMLDocument->loadXML($xmls);
|
||
} catch (Exception $e)
|
||
{ echo $e->getMessage();
|
||
}
|
||
|
||
$currNode=findNodeOnAttribute($objXMLDocument->documentElement,"type","n",$typename);
|
||
if ($currNode!=null)
|
||
{
|
||
$pnode=findFirstNode($currNode,'properties');
|
||
$fnode=findFirstNodeOnAttribute($pnode,"prop","n",$field); //Поле в metedata.xml файла
|
||
$nnode=findFirstNodeOnAttribute($pnode,"prop","n",$fnode->getAttribute("cd")); //Поле в metedata.xml с именем файла
|
||
|
||
if($fnode->getAttribute("vt")=="blob") //Отправить файл клиенту из базы данных
|
||
{
|
||
$stmt = $db->prepare("SELECT \"$field\",length(\"$field\"),substring(\"$name\", position('_' IN \"$name\")+1) as name FROM $Schema\"$typename\" WHERE id='$idval'");
|
||
$stmt->execute();
|
||
$stmt->bindColumn(1, $blob, PDO::PARAM_LOB);
|
||
$stmt->bindColumn(2, $size, PDO::PARAM_INT);
|
||
$stmt->bindColumn(3, $name, PDO::PARAM_STR);
|
||
$stmt->fetch(PDO::FETCH_BOUND);
|
||
$data = stream_get_contents($blob);
|
||
|
||
header("Content-type: application/octet-stream");
|
||
header('Content-Disposition: attachment; filename="'.$name.'"');
|
||
header('Content-Length: '.$size);
|
||
echo $data;
|
||
}else if($fnode->getAttribute("vt")=="file") //Отправить файл клиенту из файловой системы
|
||
{
|
||
//Тип поля с ObjectID
|
||
$nField=findFirstNodeOnAttribute(findNode($currNode, 'properties'), "prop", "n", $currNode->getAttribute('ObjectID'));
|
||
$csql=findNode(findFirstNodeOnAttribute($currNode, "sql-query", "t", "s"), "#cdata-section");
|
||
if($csql!=NULL && $csql->nodeValue!="") //Есть ли SQL запрос
|
||
{
|
||
$sql_query=$csql->nodeValue;
|
||
$sql_query=str_replace('${'.$currNode->getAttribute("ObjectID").'}',getSQLValue($nField->getAttribute('vt'),$idval),$sql_query);
|
||
$sql_query=str_replace('${_user_id}',getSQLValue(gettype($_SESSION['USER_ID']),$_SESSION['USER_ID']),$sql_query);
|
||
}
|
||
|
||
$res = $db->query($sql_query);
|
||
while ($row = $res->fetch(PDO::FETCH_ASSOC))
|
||
{
|
||
$fname = $row[$field];
|
||
}
|
||
$dataFName = afterLast($fname,'_');
|
||
$rezFName = beforeLast($fname,'_');
|
||
$rezFName .= '.'.afterLast($fname,'.');
|
||
|
||
if(file_exists($_SERVER['DOCUMENT_ROOT'].'/'.$fnode->getAttribute('path').$dataFName))
|
||
{
|
||
header("Content-type: application/octet-stream");
|
||
header('Content-Disposition: attachment; filename="'.$rezFName.'"');
|
||
header('Content-Length: '.filesize($_SERVER['DOCUMENT_ROOT'].'/'.$fnode->getAttribute('path').$dataFName));
|
||
readfile($_SERVER['DOCUMENT_ROOT'].'/'.$fnode->getAttribute('path').$dataFName);
|
||
exit();
|
||
}else
|
||
{
|
||
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404);
|
||
echo 'File "'.$_SERVER['DOCUMENT_ROOT'].'/'.$fnode->getAttribute('path').$dataFName.'" not found!';
|
||
exit;
|
||
}
|
||
}
|
||
}
|
||
}else
|
||
{
|
||
sendError(1,"Неизвестная функция \"$fn\"!");
|
||
}
|
||
|
||
|