Pārlūkot izejas kodu

import api from feature-api

Piotr Labudda 10 gadi atpakaļ
vecāks
revīzija
9c535c0426

+ 75 - 0
SE/api.php

@@ -0,0 +1,75 @@
+<?php
+
+if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
+	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
+	exit();
+}
+
+define('DS', DIRECTORY_SEPARATOR);
+define('APP_PATH_ROOT', dirname(__FILE__));
+define('APP_PATH_LIB', APP_PATH_ROOT . '/se-lib');
+define('APP_PATH_WWW', APP_PATH_ROOT);
+define('APP_PATH_CONFIG', APP_PATH_ROOT . DS . 'config');
+define('APP_PATH_SCHEMA', APP_PATH_ROOT . DS . 'schema');
+
+date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
+
+$errorReportingLevel = E_ALL & ~E_NOTICE;
+error_reporting($errorReportingLevel);
+ini_set('error_reporting', $errorReportingLevel);
+
+if (file_exists(APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php")) {
+	require APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php";
+}
+if (file_exists(APP_PATH_ROOT . "/.config.php")) include APP_PATH_ROOT . "/.config.php";
+
+require_once APP_PATH_ROOT . "/superedit-SEF.php";
+SEF('DEBUG_S');
+
+require_once APP_PATH_LIB . '/' . 'Lib.php';
+Lib::loadClass('V');
+Lib::loadClass('DB');
+Lib::loadClass('User');
+Lib::loadClass('SE_Layout');
+Lib::loadClass('S');
+Lib::loadClass('Http');
+Lib::loadClass('HttpException');
+Lib::loadClass('ApiUser');
+Lib::loadClass('Api');
+
+session_start();
+session_write_close();
+
+$apiUser = new ApiUser();
+// ?LOGIN=LOGOUT
+if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
+	$apiUser->logout();
+} else {
+	$apiUser->auth();
+}
+
+$reqUri = V::get('REQUEST_URI', '', $_SERVER);
+$reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
+$taskPath = str_replace($reqScript, '', $reqUri);
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+
+$api = new Api();
+$api->setUser($apiUser);
+try {
+	$api->execute($taskPath);
+}
+catch (HttpException $e) {
+	Http::sendHeaderByCode($e->getCode());
+	echo $e->getMessage();
+}
+catch (Exception $e) {
+	Http::sendHeaderByCode(500);
+	echo $e->getMessage();
+}
+
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">PHP_AUTH_USER (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['PHP_AUTH_USER']);echo'</pre>';}
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">REQUEST_URI (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['REQUEST_URI']);echo'</pre>';}
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">SCRIPT_NAME (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['SCRIPT_NAME']);echo'</pre>';}
+IF(V::get('DBG','',$_GET)){die("\nEOF L." . __LINE__);}
+
+?>

+ 188 - 0
SE/se-lib/Api.php

@@ -0,0 +1,188 @@
+<?php
+
+class Api {
+
+	private $_apiUser;
+	private $_request;
+
+	public function setUser($user) {
+		$this->_apiUser = $user;
+	}
+
+	public function execute($url) {
+		$request = $this->parseUrl($url);
+
+		$apiRouterName = $request->apiRouterName;
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">apiRouterName (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($apiRouterName);echo'</pre>';}
+		$apiRouterName = ucfirst(strtolower($apiRouterName));
+		$apiRouterClassName = "Api_{$apiRouterName}";
+		if (!Lib::tryLoadClass($apiRouterClassName)) {
+			throw new HttpException("Route not exists", 404);
+		}
+		$apiRouter = new $apiRouterClassName();
+		$apiRouter->setUser($this->_apiUser);
+		$responseDocument = $apiRouter->execute($request);
+		if (empty($responseDocument)) {
+			throw new HttpException("No result", 404);
+		}
+		$this->response($responseDocument);
+	}
+
+	private function parseUrl($url) {
+		$request = new stdClass();
+		$request->url = trim($url, '/ ');
+		$urlParts = explode('?', $request->url);
+		$request->path = $urlParts[0];
+		$request->query = (count($urlParts) > 1)? $urlParts[1] : '';
+		$request->args = $_REQUEST;
+		$request->segments = array();
+		$urlPathParts = explode('/', $request->path);
+		foreach ($urlPathParts as $part) {
+			if (!empty($part)) $request->segments[] = $part;
+		}
+
+		IF(V::get('DBG','',$_GET)>1){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">url (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($request);echo'</pre>';}
+		$request->format = array_shift($request->segments);
+		if (empty($request->segments)) return null;
+
+		IF(V::get('DBG','',$_GET)>1){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">responseFormat (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($request->format);echo'</pre>';}
+		if (!$this->checkResponseFormat($request->format)) {
+			throw new HttpException("Response format not allowed", 400);
+		}
+		IF(V::get('DBG','',$_GET)>1){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">u (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($request);echo'</pre>';}
+
+		$request->apiRouterName = array_shift($request->segments);
+		IF(V::get('DBG','',$_GET)>1){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">u (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($request);echo'</pre>';}
+
+		if (!empty($request->query)) {
+			$queryArgs = array();
+			parse_str($request->query, $queryArgs);
+			$request->query = $queryArgs;
+		}
+
+		$this->_request = $request;
+		return $this->_request;
+	}
+
+	private function checkResponseFormat($format) {
+		$allowedTypes = array();
+		$allowedTypes[] = 'xml';
+		$allowedTypes[] = 'json';
+		$allowedTypes[] = 'csv';
+		$allowedTypes[] = 'csv_file';
+		$allowedTypes[] = 'raw';
+		//$allowedTypes[] = 'xml-ns';// xml with namespace
+		return in_array($format, $allowedTypes);
+	}
+
+	private function response($document) {
+		if ('xml' == $this->_request->format) {
+			$this->responseXml($document);
+		}
+		else if ('json' == $this->_request->format) {
+			$this->responseJson($document);
+		}
+		else if ('csv' == $this->_request->format) {
+			$this->responseCsv($document);
+		}
+		else if ('csv_file' == $this->_request->format) {
+			$this->responseCsvFile($document);
+		}
+		else if ('raw' == $this->_request->format) {
+			echo $document;
+		}
+	}
+
+	private function responseXml($document) {
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">document (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($document);echo'</pre>';}
+
+		$xml = new DOMDocument('1.0', 'utf-8');
+		$xml->formatOutput = true;
+		$data = $xml->createElement('data');
+		$xml->appendChild($data);
+		$this->_xmlAddChildRec($document, $data, $xml);
+
+		header('Content-type: application/xml; charset="utf-8"');
+		echo $xml->saveXML();
+	}
+
+	private function _xmlAddChildRec($node, $parentNode, $dom) {
+		if (!$node) return;
+		if (is_object($node)) {
+			foreach ($node as $childNodeName => $childNode) {
+				$n = $dom->createElement($childNodeName);
+				$parentNode->appendChild($n);
+				$this->_xmlAddChildRec($childNode, $n, $dom);
+			}
+		}
+		else if (is_array($node)) {
+			foreach ($node as $childNodeIndeks => $childNode) {
+				$this->_xmlAddChildRec($childNode, $parentNode, $dom);
+			}
+		}
+		else if (false !== strpos($node, '&')) {
+			$n = $dom->createCDATASection($node);
+			$parentNode->appendChild($n);
+		}
+		else {
+			$n = $dom->createTextNode($node);
+			$parentNode->appendChild($n);
+		}
+	}
+
+	private function responseJson($document) {
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">document (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($document);echo'</pre>';}
+		header('Content-type: application/json; charset="utf-8"');
+		echo json_encode($document);
+	}
+
+	private function responseCsv($document) {
+		header('Content-Type: text/csv; charset=utf-8');
+
+		if (empty($document)) return;
+
+		$csvSeparator = ';';
+		$this->_printCsvDocument($document, $csvSeparator);
+	}
+
+	private function responseCsvFile($document) {
+		$csvFileName = 'output';//$this->_request
+		if ('table' === $this->_request->apiRouterName) {
+			$pathEx = explode('/', $this->_request->path);
+			if (count($pathEx) > 3) {
+				$csvFileName = $pathEx[3];
+			}
+		}
+
+		header('Content-Type: text/csv; charset=utf-8');
+		header("Content-Disposition: attachment; filename={$csvFileName}.csv");
+
+		if (empty($document)) return;
+
+		$csvSeparator = ';';
+		$this->_printCsvDocument($document, $csvSeparator);
+	}
+
+	private function _printCsvDocument($document, $csvSeparator = ';') {
+		if (empty($document)) return;
+
+		$fldList = array();
+		$labelsLine = array();
+		foreach ($document->items[0]->item as $fldName => $value) {
+			$fldList[] = $fldName;
+			$labelsLine[] = '"' . addslashes($fldName) . '"';
+		}
+		echo implode($csvSeparator, $labelsLine) . "\n";
+
+		foreach ($document->items as $itemsList) {
+			foreach ($itemsList as $item) {
+				$itemLine = array();
+				foreach ($fldList as $fldName) {
+					$itemLine[] = '"' . addslashes($item->{$fldName}) . '"';
+				}
+				echo implode($csvSeparator, $itemLine) . "\n";
+			}
+		}
+	}
+
+}

+ 131 - 0
SE/se-lib/Api/TransactionHelper.php

@@ -0,0 +1,131 @@
+<?php
+
+/**
+* usage:
+*		$actionId = $apiTransactionHelper->createAction($transactionKey, $actionType, $tblName, $requestBodyXml);
+*		...
+*		$apiTransactionHelper->setActionObject($actionId, $item);
+*		...
+*		$newItemId = $dataSource->createItem($item);
+*		...
+*		$apiTransactionHelper->setActionResult($actionId, $newItemId);
+*/
+class Api_TransactionHelper {
+
+	public function createAction($transactionKey, $actionType, $tblName, $requestBodyXml) {
+		$userLogin = User::getLogin();
+		$db = DB::getDB();
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$sqlCreateAction = "insert into `_API_XML_TASKS` (
+				`A_RECORD_CREATE_DATE`
+				, `A_RECORD_CREATE_AUTHOR`
+				, `TRANSACTION_ID`
+				, `TASK`
+				, `DB_TABLE`
+				, `XML_OBJ`
+			)
+			values (
+				NOW()
+				, '{$userLogin}'
+				, '{$transactionKey}'
+				, '{$actionType}'
+				, '{$tblName}'
+				, '{$requestBodyXml}'
+			)
+		";
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$sqlCreateAction (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlCreateAction);echo'</pre>';}
+		$db->query($sqlCreateAction);
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$actionId = $db->insert_id();
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$actionId (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($actionId);echo'</pre>';}
+		return $actionId;
+	}
+
+	public function setActionObject($actionId, $item) {
+		$userLogin = User::getLogin();
+		$db = DB::getDB();
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$itemJson = json_encode($item);
+		$sqlUpdate = "update `_API_XML_TASKS` set
+				`A_RECORD_UPDATE_DATE`=NOW()
+				, `A_RECORD_UPDATE_AUTHOR`='{$userLogin}'
+				, `ITEM_OBJ`='{$itemJson}'
+			where `ID`={$actionId}
+		";
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$sqlUpdate (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlUpdate);echo'</pre>';}
+		$db->query($sqlUpdate);
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+	}
+
+	public function setActionResult($actionId, $newItemId) {
+		$userLogin = User::getLogin();
+		$db = DB::getDB();
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$sqlUpdate = "update `_API_XML_TASKS` set
+				`A_RECORD_UPDATE_DATE`=NOW()
+				, `A_RECORD_UPDATE_AUTHOR`='{$userLogin}'
+				, `RESULT_ID`='{$newItemId}'
+			where `ID`={$actionId}
+		";
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$sqlUpdate (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlUpdate);echo'</pre>';}
+		$db->query($sqlUpdate);
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+	}
+
+	public function getLastActionInfo($transactionKey) {
+		$db = DB::getDB();
+		if ($db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$sqlSelect = "select *
+			from `_API_XML_TASKS`
+			where `TRANSACTION_ID`='{$transactionKey}'
+			order by `ID` desc
+			limit 1
+		";
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$sqlSelect (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sqlSelect);echo'</pre>';}
+		$res = $db->query($sqlSelect);
+		if (!$res || $db->has_errors()) {
+			throw new HttpException("DB Errors: " . implode("\n", $db->get_errors()), 500);
+		}
+		$item = $db->fetch_assoc($res);
+		if (!$item) {
+			throw new HttpException("Item not found", 404);
+		}
+		return $item;
+	}
+
+	private function _installTable() {
+		$sqlCreateTable = "
+			CREATE TABLE IF NOT EXISTS `_API_XML_TASKS` (
+				`ID` int(11) NOT NULL AUTO_INCREMENT,
+				`A_RECORD_CREATE_DATE` varchar(30) NOT NULL,
+				`A_RECORD_CREATE_AUTHOR` varchar(40) NOT NULL,
+				`A_RECORD_UPDATE_DATE` varchar(30) NOT NULL,
+				`A_RECORD_UPDATE_AUTHOR` varchar(40) NOT NULL,
+				`TRANSACTION_ID` varchar(255) NOT NULL,
+				`TASK` varchar(32) NOT NULL,
+				`DB_TABLE` varchar(255) NOT NULL,
+				`XML_OBJ` text NOT NULL,
+				`ITEM_OBJ` text NOT NULL,
+				`PARAMS` text NOT NULL,
+				`RESULT_ID` int(11) NOT NULL DEFAULT '0',
+				`TASK_DONE` int(11) NOT NULL DEFAULT '0',
+				PRIMARY KEY (`ID`)
+			) ENGINE=MyISAM DEFAULT CHARSET=latin2 ;
+		";
+	}
+
+}

+ 175 - 0
SE/se-lib/ApiDataSourceTodo.php

@@ -0,0 +1,175 @@
+<?php
+
+class ApiDataSourceTodo {
+
+	private $_dataSourceName;
+	private $_sourceConnection;
+	private $_tblName;
+	private $_primaryKey;
+	private $_fields = array();
+
+	public function __construct($dataSourceName) {
+		$this->_dataSourceName = $dataSourceName;
+	}
+
+	public function getSchema() {
+		// TODO: read from schema files xml/ini
+		// TODO: build data source by name $this->_dataSourceName (Mysql|SchemaFile)
+
+		if (empty($this->_fields)) {
+			$db = $this->getConnection();
+			$sql = "show fields from `{$this->_tblName}` ";
+			$res = $db->query($sql);
+			if (!$res) {
+				IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">sql (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'</pre>';}
+				IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">db errors (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($db->get_errors());echo'</pre>';}
+				throw new HttpException("Read schema errors", 404);
+			}
+			while ($h = $db->fetch_row($res)) {
+				$fieldName = $h[0];
+				$fieldType = $h[1];
+				$this->_fields[$fieldName] = array('type'=>$h[1], 'null'=>('YES' == $h[2]), 'default'=>$h[4]);
+				if ('PRI' == $h[3]) {
+					$this->_primaryKey = $fieldName;
+				}
+			}
+			IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">_fields (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_fields);echo'</pre>';}
+			if (empty($this->_fields)) {
+				throw new HttpException("Fields list empty", 404);
+			}
+		}
+	}
+
+	private function getConnection() {
+		$this->_sourceConnection = DB::getDB($this->_dataSourceName);
+		if (!$this->_sourceConnection) {
+			throw new HttpException("Connect to data source error", 404);
+		}
+		return $this->_sourceConnection;
+	}
+
+	public function getItems($args) {
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">args (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($args);echo'</pre>';}
+		$items = array();
+		$db = $this->getConnection();
+		$fields = $this->getFields();
+		$sqlFields = array();
+		foreach ($fields as $fieldName => $field) {
+			$sqlFields[] = "t.`{$fieldName}`";
+		}
+		$sqlFields = implode(", ", $sqlFields);
+		if (!empty($args['limit']) && is_numeric($args['limit'])) {
+			$sqlLimit = "limit {$args['limit']}";
+			if (!empty($args['offset']) && is_numeric($args['offset'])) {
+				$sqlLimit .= " offset {$args['offset']}";
+			}
+		}
+
+		$sqlWhere = "1=1";
+		$sqlQueryArgs = array();
+		foreach ($fields as $fieldName => $field) {
+			$queryValue = V::get("f_{$fieldName}", null, $_GET);
+			if (!empty($queryValue)) {
+				$sqlQueryValue = $db->_($queryValue);
+				$sqlQueryArgs[] = "t.`{$fieldName}` like '{$sqlQueryValue}'";
+			}
+		}
+		if (!empty($sqlQueryArgs)) {
+			$sqlWhere .= " and " . implode(" and ", $sqlQueryArgs);
+		}
+
+		$sql = "select {$sqlFields}
+			from `{$this->_tblName}` as t
+			where {$sqlWhere}
+			{$sqlLimit}
+			-- order by
+		";
+		IF(V::get('DBG','',$_GET)>2){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">sql (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'</pre>';}
+		IF(V::get('DBG','',$_GET)>2){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">this->_primaryKey (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_primaryKey);echo'</pre>';}
+		$res = $db->query($sql);
+		while ($r = $db->fetch($res)) {
+			if (!$this->_primaryKey) {
+				$items[] = $r;
+			} else {
+				$items[$r->{$this->_primaryKey}] = $r;
+			}
+		}
+		return $items;
+	}
+
+	public function getItem($id) {
+		$items = array();
+		$db = $this->getConnection();
+		$fields = $this->getFields();
+		$sqlFields = array();
+		foreach ($fields as $fieldName => $field) {
+			$sqlFields[] = "t.`{$fieldName}`";
+		}
+		$sqlFields = implode(", ", $sqlFields);
+
+		$sqlWhere = "t.`{$this->_primaryKey}`='{$id}'";
+
+		$sql = "select {$sqlFields}
+			from `{$this->_tblName}` as t
+			where {$sqlWhere}
+		";
+		$res = $db->query($sql);
+		if ($r = $db->fetch($res)) {
+			$item = $r;
+		}
+		return $item;
+	}
+
+	public function createItem($itemRaw) {
+		$item = array();
+		$db = $this->getConnection();
+		$fields = $this->getFields();
+		foreach ($fields as $fieldName => $field) {
+			if (array_key_exists($fieldName, $itemRaw)) {
+				$item[$fieldName] = $itemRaw[$fieldName];
+			}
+		}
+		if (array_key_exists($this->_primaryKey, $item)) {
+			if (!empty($item[$this->_primaryKey])) {
+				$item[$this->_primaryKey] = null;
+			}
+		}
+//echo "itemRaw:\n";print_r($itemRaw);
+//echo "fields:\n";print_r($fields);
+//echo "item:\n";var_dump($item);
+//exit;
+		foreach ($item as $k => $v) {
+			if ($k == $this->_primaryKey) {
+				$v = 'NULL';
+			} else if (strtoupper($v) == 'NOW()') {
+				$v = 'NOW()';
+			} else if (strtoupper($v) == 'NULL') {
+				$v = 'NULL';
+			} else if (substr($v, 0, strlen('GeomFromText')) == 'GeomFromText') {
+
+			} else {
+				$v = $db->_($v);
+				$v = "'{$v}'";
+			}
+			$sql_arr ["`{$k}`"] = $v;
+		}
+		$sql = "insert into `{$this->_tblName}` (".implode(",", array_keys($sql_arr)).") values (".implode(",", array_values($sql_arr))."); ";
+//echo "sql:{$sql}\n";
+//exit;
+		$db->query($sql);
+		if ($db->has_errors()) {
+			throw new Exception("Database Errors: " . implode("\n", $db->get_errors()));
+		}
+		return $db->insert_id();
+	}
+
+	public function getFields() {
+		$this->getSchema();
+		return $this->_fields;
+	}
+
+	public function setTable($tblName) {
+		$this->_tblName = $tblName;
+	}
+
+}

+ 100 - 0
SE/se-lib/ApiUser.php

@@ -0,0 +1,100 @@
+<?php
+
+Lib::loadClass('User');
+Lib::loadClass('LDAP');
+
+class ApiUser {
+
+	public $_user;
+
+	public function auth() {
+		if (User::logged()) {
+			$this->_user = User::getCurrentUserObject();
+		}
+		else {
+			$login = V::get('PHP_AUTH_USER', '', $_SERVER);
+			$pass = V::get('PHP_AUTH_PW', '', $_SERVER);
+
+			if (!$login) {
+				$this->exitUnauthorized();
+			}
+
+			$errors = array();
+			$ldap = LDAP::getInstance();
+			if ($ldap != null && $ldap->isConnected()) {
+				$this->_user = User::loginByLDAP($login, $pass, $errors);
+			} else {
+				$this->_user = User::loginByDB($login, $pass, $errors);
+			}
+
+			if (!$this->_user) {
+				$this->exitUnauthorized();
+			}
+
+			$this->_saveToSession();
+		}
+	}
+
+	private function _saveToSession() {
+			$_SESSION['ADM_ID'] = $this->_user->ID;
+			$_SESSION['AUTHORIZE_USER'] = $this->_user->ADM_ACCOUNT;
+			$_SESSION['ADM_ACCOUNT'] = $this->_user->ADM_ACCOUNT;
+			//$_SESSION['ADM_AREA'] = $this->_user->ADM_AREA;
+			$_SESSION['ADM_NAME'] = $this->_user->ADM_NAME;
+			$_SESSION['ADM_TECH_WORKER'] = $this->_user->ADM_TECH_WORKER;
+			$_SESSION['ADM_COMPANY'] = $this->_user->ADM_COMPANY;
+			$_SESSION['ADM_ADMIN_LEVEL'] = $this->_user->ADM_ADMIN_LEVEL;
+			$_SESSION['ADM_PHONE'] = $this->_user->ADM_PHONE;
+			$_SESSION['ADM_ADMIN_EXPIRE'] = $this->_user->ADM_ADMIN_EXPIRE;
+			$_SESSION['ADM_ADMIN_DESC'] = $this->_user->ADM_ADMIN_DESC;
+			$_SESSION['EMPLOYEE_TYPE'] = $this->_user->EMPLOYEE_TYPE;
+
+			// save user pass in encrypted form
+			//Lib::loadClass('Crypt');
+			//$_SESSION['ADM_PASS_HASH'] = Crypt::encrypt($pass);
+			//$_SESSION['EMAIL_IMAP_IMPORT_PASSWD_HASH'] = Crypt::encrypt($this->_user->EMAIL_IMAP_IMPORT_PASSWD);
+			//$_SESSION['EMAIL_IMAP_IMPORT_HOST'] = $this->_user->EMAIL_IMAP_IMPORT_HOST;
+			//$_SESSION['EMAIL_IMAP_IMPORT_USERNAME'] = $this->_user->EMAIL_IMAP_IMPORT_USERNAME;
+	}
+
+	public function logout() {
+		header('WWW-Authenticate: Basic realm="API"');
+		header('HTTP/1.0 401 Unauthorized');
+		$apiUrl = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['SCRIPT_NAME']}";
+		// $_SERVER[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+		$httpAccept = V::get('HTTP_ACCEPT', '', $_SERVER);
+		if (false !== strpos($httpAccept, 'text/html')) {
+			?><!DOCTYPE html>
+<html>
+<head>
+	<meta http-equiv="refresh" content="0; url=<?php echo $apiUrl; ?>" />
+</head>
+<body>
+	Unauthorized - Go to <a href="<?php echo $apiUrl; ?>"><?php echo $apiUrl; ?></a>
+</body>
+</html>
+			<?php
+		} else {
+			echo "Unauthorized - Go to {$apiUrl}";
+		}
+		exit;
+	}
+
+	public function exitUnauthorized() {
+		header('WWW-Authenticate: Basic realm="API"');
+		header('HTTP/1.0 401 Unauthorized');
+		echo 'Unauthorized';
+		exit;
+	}
+
+	public function isAdmin() {
+		if (isset($this->_user->ADM_ADMIN_LEVEL) && in_array($this->_user->ADM_ADMIN_LEVEL, array(0, 1))) {
+			return true;
+		}
+		return false;
+	}
+
+	public function getID() {
+		return $this->_user->ID;
+	}
+}

+ 18 - 0
SE/se-lib/User.php

@@ -142,6 +142,24 @@ class User {
 		return $ret;
 	}
 
+	public static function getCurrentUserObject() {
+		$user = new stdClass();
+		if (self::logged()) {
+			$user->ID = $_SESSION['ADM_ID'];
+			$user->ADM_ACCOUNT = $_SESSION['AUTHORIZE_USER'];
+			$user->ADM_ACCOUNT = $_SESSION['ADM_ACCOUNT'];
+			$user->ADM_NAME = $_SESSION['ADM_NAME'];
+			$user->ADM_TECH_WORKER = $_SESSION['ADM_TECH_WORKER'];
+			$user->ADM_COMPANY = $_SESSION['ADM_COMPANY'];
+			$user->ADM_ADMIN_LEVEL = $_SESSION['ADM_ADMIN_LEVEL'];
+			$user->ADM_PHONE = $_SESSION['ADM_PHONE'];
+			$user->ADM_ADMIN_EXPIRE = $_SESSION['ADM_ADMIN_EXPIRE'];
+			$user->ADM_ADMIN_DESC = $_SESSION['ADM_ADMIN_DESC'];
+			$user->EMPLOYEE_TYPE = $_SESSION['EMPLOYEE_TYPE'];
+		}
+		return $user;
+	}
+
 	public static function getAcl() {
 		static $_acl;
 		if (!$_acl) {