Files
Metadata_PHP/metadata/dbms/records.xyz
2024-12-08 15:24:40 +06:00

1452 lines
63 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

<?php
use lfkeitel\phptotp\{Base32,Totp};
//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.xyz");
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->error_code=$code;
$obj->error_message=$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'];
}
}*/
if(!isset($fn))
$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"); //Номер функции из XML
}
}
//описание
//(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.'get_access(:user_id1,:action_insert) as ins,'.$Schema.'get_access(:user_id2,:action_update) as upd,'.$Schema.'get_access(: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->error_code=0;
$obj->error_message = '';
$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)//Залогинеться (TODO логин происходит через JWT в другом коде на java)
{
$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/';
// отправка файла в отдельном файле 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 style="background-color:#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>';
//deleteTempFiles($dir);
}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="/api/dbms/v09/upload" 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\"!");
}