0
1
Fork 0

EDI update bugs solved, PHP linting

This commit is contained in:
Juan 2018-05-23 12:14:20 +02:00
parent 063d9b92e8
commit a57498548f
60 changed files with 1121 additions and 1431 deletions

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
hedera-web (1.406.02) stable; urgency=low hedera-web (1.406.03) stable; urgency=low
* Initial Release. * Initial Release.

View File

@ -2,7 +2,7 @@
require_once __DIR__.'/../php-vn-lib/env.php'; require_once __DIR__.'/../php-vn-lib/env.php';
set_include_path (__DIR__.PATH_SEPARATOR.get_include_path ()); set_include_path(__DIR__.PATH_SEPARATOR.get_include_path());
$vnAutoloadMap['vn/web'] = __DIR__.'/web'; $vnAutoloadMap['vn/web'] = __DIR__.'/web';

View File

@ -4,5 +4,5 @@
@include_once __DIR__.'/env.php'; @include_once __DIR__.'/env.php';
require_once 'vn-autoload.php'; require_once 'vn-autoload.php';
$cliApp = new Vn\Lib\CliApp ('hedera-web', __DIR__.'/rest'); $cliApp = new Vn\Lib\CliApp('hedera-web', __DIR__.'/rest');
$cliApp->run (); $cliApp->run();

View File

@ -3,5 +3,5 @@
@include_once __DIR__.'/env.php'; @include_once __DIR__.'/env.php';
require_once 'vn-autoload.php'; require_once 'vn-autoload.php';
$webApp = new Vn\Web\App ('hedera-web'); $webApp = new Vn\Web\App('hedera-web');
$webApp->run (); $webApp->run();

View File

@ -1,6 +1,6 @@
{ {
"name": "hedera-web", "name": "hedera-web",
"version": "1.406.02", "version": "1.406.03",
"description": "Verdnatura web page", "description": "Verdnatura web page",
"license": "GPL-3.0", "license": "GPL-3.0",
"repository": { "repository": {

View File

@ -1,7 +1,7 @@
<?php <?php
$lang = Vn\Lib\Locale::get (); $lang = Vn\Lib\Locale::get();
$result = $db->query ('SELECT name, content FROM metatag'); $result = $db->query('SELECT name, content FROM metatag');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -18,11 +18,11 @@ $result = $db->query ('SELECT name, content FROM metatag');
<meta name="theme-color" content="#009688"/> <meta name="theme-color" content="#009688"/>
<meta name="content-language" content="<?=$lang?>"/> <meta name="content-language" content="<?=$lang?>"/>
<?php while ($row = $result->fetch_object ()): ?> <?php while ($row = $result->fetch_object()): ?>
<meta name="<?=$row->name?>" content="<?=$row->content?>"/> <meta name="<?=$row->name?>" content="<?=$row->content?>"/>
<?php endwhile ?> <?php endwhile ?>
<?php foreach (getWebpackAssets () as $js): ?> <?php foreach(getWebpackAssets() as $js): ?>
<script type="text/javascript" src="<?=$js?>"></script> <script type="text/javascript" src="<?=$js?>"></script>
<?php endforeach ?> <?php endforeach ?>

View File

@ -1,10 +1,8 @@
<?php <?php
class Account class Account {
{ static function trySync($db, $userName, $password = NULL) {
static function trySync ($db, $userName, $password = NULL) $isSync = $db->getValue(
{
$isSync = $db->getValue (
'SELECT sync FROM account.user WHERE name = #', 'SELECT sync FROM account.user WHERE name = #',
[$userName] [$userName]
); );
@ -12,12 +10,11 @@ class Account
if ($isSync) if ($isSync)
return; return;
self::sync ($db, $userName, $password); self::sync($db, $userName, $password);
} }
static function sync ($db, $userName, $password = NULL, $force = TRUE) static function sync($db, $userName, $password = NULL, $force = TRUE) {
{ $hasAccount = $db->getValue(
$hasAccount = $db->getValue (
'SELECT COUNT(*) > 0 'SELECT COUNT(*) > 0
FROM account.user u FROM account.user u
JOIN account.account a ON u.id = a.id JOIN account.account a ON u.id = a.id
@ -25,13 +22,12 @@ class Account
[$userName] [$userName]
); );
if ($hasAccount) if ($hasAccount) {
{ self::ldapSync($db, $userName, $password);
self::ldapSync ($db, $userName, $password); self::sambaSync($db, $userName, $password);
self::sambaSync ($db, $userName, $password);
} }
$db->query ( $db->query(
'UPDATE account.user SET sync = TRUE WHERE name = #', 'UPDATE account.user SET sync = TRUE WHERE name = #',
[$userName] [$userName]
); );
@ -40,47 +36,46 @@ class Account
/** /**
* Synchronizes the user credentials in the LDAP server. * Synchronizes the user credentials in the LDAP server.
*/ */
static function ldapSync ($db, $userName, $password) static function ldapSync($db, $userName, $password) {
{
// Gets LDAP configuration parameters // Gets LDAP configuration parameters
$conf = $db->getObject ( $conf = $db->getObject(
'SELECT host, rdn, password, baseDn, filter 'SELECT host, rdn, password, baseDn, filter
FROM account.ldapConfig'); FROM account.ldapConfig');
// Connects an authenticates against server // Connects an authenticates against server
$ds = ldap_connect ($conf->host); $ds = ldap_connect($conf->host);
if (!$ds) if (!$ds)
throw new Exception ("Can't connect to LDAP server: ". ldapError ($ds)); throw new Exception("Can't connect to LDAP server: ". ldapError($ds));
try { try {
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind = ldap_bind ($ds, $conf->rdn, base64_decode ($conf->password)); $bind = ldap_bind($ds, $conf->rdn, base64_decode($conf->password));
if (!$bind) if (!$bind)
throw new Exception ("Authentication failed on LDAP server: ". ldapError ($ds)); throw new Exception("Authentication failed on LDAP server: ". ldapError($ds));
// Prepares the data // Prepares the data
$domain = $db->getValue ('SELECT domain FROM account.mailConfig'); $domain = $db->getValue('SELECT domain FROM account.mailConfig');
$user = $db->getObject ( $user = $db->getObject(
'SELECT id, nickname, lang 'SELECT id, nickname, lang
FROM account.user FROM account.user
WHERE name = #', WHERE name = #',
[$userName] [$userName]
); );
$cn = empty ($user->nickname) ? $userName : $user->nickname; $cn = empty($user->nickname) ? $userName : $user->nickname;
$nameArgs = explode (' ', $user->nickname); $nameArgs = explode(' ', $user->nickname);
$givenName = $nameArgs[0]; $givenName = $nameArgs[0];
if (count ($nameArgs) > 1) if (count($nameArgs) > 1)
$sn = $nameArgs[1]; $sn = $nameArgs[1];
if (empty ($sn)) if (empty($sn))
$sn = 'Empty'; $sn = 'Empty';
$attrs = [ $attrs = [
@ -89,7 +84,7 @@ class Account
'givenName' => $givenName, 'givenName' => $givenName,
'sn' => $sn, 'sn' => $sn,
'mail' => "$userName@{$domain}", 'mail' => "$userName@{$domain}",
'userPassword' => sshaEncode ($password), 'userPassword' => sshaEncode($password),
'preferredLanguage' => $user->lang 'preferredLanguage' => $user->lang
]; ];
@ -100,67 +95,61 @@ class Account
if (!empty($conf->filter)) if (!empty($conf->filter))
$filter = "(&($filter)($conf->filter))"; $filter = "(&($filter)($conf->filter))";
$res = ldap_search ($ds, $conf->baseDn, $filter); $res = ldap_search($ds, $conf->baseDn, $filter);
if (!$res) if (!$res)
throw new Exception ("Can't get the LDAP entry: ". ldapError ($ds)); throw new Exception("Can't get the LDAP entry: ". ldapError($ds));
$dn = "uid=$userName,{$conf->baseDn}"; $dn = "uid=$userName,{$conf->baseDn}";
$entry = ldap_first_entry ($ds, $res); $entry = ldap_first_entry($ds, $res);
$classes = ldap_get_values ($ds, $entry, 'objectClass'); $classes = ldap_get_values($ds, $entry, 'objectClass');
if (!in_array ('inetOrgPerson', $classes)) if (!in_array('inetOrgPerson', $classes)) {
{ ldap_delete($ds, $dn);
ldap_delete ($ds, $dn);
$entry = NULL; $entry = NULL;
} }
if ($entry) if ($entry) {
{
$modifs = []; $modifs = [];
$curAttrs = ldap_get_attributes ($ds, $entry); $curAttrs = ldap_get_attributes($ds, $entry);
foreach ($attrs as $attribute => $value) foreach($attrs as $attribute => $value)
if (!empty ($value)) if (!empty($value)) {
{
$modifs[] = [ $modifs[] = [
'attrib' => $attribute, 'attrib' => $attribute,
'modtype' => LDAP_MODIFY_BATCH_REPLACE, 'modtype' => LDAP_MODIFY_BATCH_REPLACE,
'values' => [$value] 'values' => [$value]
]; ];
} }
elseif (isset ($curAttrs[$attribute])) elseif (isset($curAttrs[$attribute])) {
{
$modifs[] = [ $modifs[] = [
'attrib' => $attribute, 'attrib' => $attribute,
'modtype' => LDAP_MODIFY_BATCH_REMOVE_ALL 'modtype' => LDAP_MODIFY_BATCH_REMOVE_ALL
]; ];
} }
$updated = ldap_modify_batch ($ds, $dn, $modifs); $updated = ldap_modify_batch($ds, $dn, $modifs);
} }
else else {
{
$addAttrs = []; $addAttrs = [];
foreach ($attrs as $attribute => $value) foreach($attrs as $attribute => $value)
if (!empty ($value)) if (!empty($value))
$addAttrs[$attribute] = $value; $addAttrs[$attribute] = $value;
$addAttrs = array_merge ($addAttrs, [ $addAttrs = array_merge($addAttrs, [
'objectClass' => ['inetOrgPerson'], 'objectClass' => ['inetOrgPerson'],
'uid' => $userName 'uid' => $userName
]); ]);
$updated = ldap_add ($ds, $dn, $addAttrs); $updated = ldap_add($ds, $dn, $addAttrs);
} }
if (!$updated) if (!$updated)
throw new Exception ("Can't update the LDAP entry: ". ldapError ($ds)); throw new Exception("Can't update the LDAP entry: ". ldapError($ds));
} }
catch (Exception $e) catch (Exception $e) {
{ ldap_unbind($ds);
ldap_unbind ($ds);
throw $e; throw $e;
} }
} }
@ -168,28 +157,27 @@ class Account
/** /**
* Synchronizes the user credentials in the Samba server. * Synchronizes the user credentials in the Samba server.
*/ */
static function sambaSync ($db, $userName, $password) static function sambaSync($db, $userName, $password) {
{ $conf = $db->getObject(
$conf = $db->getObject (
'SELECT host, sshUser, sshPass, uidBase 'SELECT host, sshUser, sshPass, uidBase
FROM account.sambaConfig' FROM account.sambaConfig'
); );
$domain = $db->getValue ('SELECT domain FROM account.mailConfig'); $domain = $db->getValue('SELECT domain FROM account.mailConfig');
$samba = new SshConnection ($conf->host $samba = new SshConnection($conf->host
,$conf->sshUser ,$conf->sshUser
,base64_decode ($conf->sshPass) ,base64_decode($conf->sshPass)
); );
$scriptDir = '/mnt/cluster/scripts'; $scriptDir = '/mnt/cluster/scripts';
// Creates the Samba user and initializes it's home directory // Creates the Samba user and initializes it's home directory
$userId = $db->getValue ( $userId = $db->getValue(
'SELECT id FROM account.user WHERE name = #', [$userName]); 'SELECT id FROM account.user WHERE name = #', [$userName]);
$samba->exec ("$scriptDir/create-user.sh %s %s %s" $samba->exec("$scriptDir/create-user.sh %s %s %s"
,$userName ,$userName
,$conf->uidBase + $userId ,$conf->uidBase + $userId
,"$userName@{$domain}" ,"$userName@{$domain}"
@ -197,56 +185,51 @@ class Account
// Syncronizes the Samba password // Syncronizes the Samba password
if (empty ($password)) if (empty($password))
return; return;
$samba->exec ("$scriptDir/set-password.sh %s %s" $samba->exec("$scriptDir/set-password.sh %s %s"
,$userName ,$userName
,$password ,$password
); );
} }
} }
function ldapError ($ds) function ldapError($ds) {
{ return ldap_errno($ds) .': '. ldap_error($ds);
return ldap_errno ($ds) .': '. ldap_error ($ds);
} }
function sshaEncode ($value) function sshaEncode($value) {
{ mt_srand((double) microtime() * 1000000);
mt_srand ((double) microtime () * 1000000); $salt = pack('CCCC', mt_rand(), mt_rand(), mt_rand(), mt_rand());
$salt = pack ('CCCC', mt_rand (), mt_rand (), mt_rand (), mt_rand ()); $hash = '{SSHA}' . base64_encode(pack('H*', sha1($value . $salt)) . $salt);
$hash = '{SSHA}' . base64_encode (pack ('H*', sha1 ($value . $salt)) . $salt);
return $hash; return $hash;
} }
function sshaVerify ($hash, $value) function sshaVerify($hash, $value) {
{ $ohash = base64_decode(substr($hash, 6));
$ohash = base64_decode (substr ($hash, 6)); $osalt = substr($ohash, 20);
$osalt = substr ($ohash, 20); $ohash = substr($ohash, 0, 20);
$ohash = substr ($ohash, 0, 20); $nhash = pack('H*', sha1($value . $osalt));
$nhash = pack ('H*', sha1 ($value . $osalt));
return $ohash == $nhash; return $ohash == $nhash;
} }
class SshConnection class SshConnection {
{
var $connection; var $connection;
/** /**
* Abrebiated method to make SSH connections. * Abrebiated method to make SSH connections.
*/ */
function __construct ($host, $user, $password) function __construct($host, $user, $password) {
{ $this->connection = $connection = ssh2_connect($host);
$this->connection = $connection = ssh2_connect ($host);
if (!$connection) if (!$connection)
throw new Exception ("Can't connect to SSH server $host"); throw new Exception("Can't connect to SSH server $host");
$authOk = ssh2_auth_password ($connection, $user, $password); $authOk = ssh2_auth_password($connection, $user, $password);
if (!$authOk) if (!$authOk)
throw new Exception ("SSH authentication failed on server $host"); throw new Exception("SSH authentication failed on server $host");
return $connection; return $connection;
} }
@ -254,23 +237,21 @@ class SshConnection
/** /**
* Executes a command on the host. * Executes a command on the host.
*/ */
function exec () function exec() {
{ $nargs = func_num_args();
$nargs = func_num_args (); $args = func_get_args();
$args = func_get_args ();
for ($i = 1; $i < $nargs; $i++) for ($i = 1; $i < $nargs; $i++)
$args[$i] = self::escape ($args[$i]); $args[$i] = self::escape($args[$i]);
$command = call_user_func_array ('sprintf', $args); $command = call_user_func_array('sprintf', $args);
return ssh2_exec ($this->connection, $command); return ssh2_exec($this->connection, $command);
} }
/** /**
* Escapes the double quotes from an string. * Escapes the double quotes from an string.
*/ */
static function escape ($str) static function escape($str) {
{ return '"'. str_replace('"', '\\"', $str) .'"';
return '"'. str_replace ('"', '\\"', $str) .'"';
} }
} }

View File

@ -1,12 +1,10 @@
<?php <?php
require_once ('PEAR.php'); require_once('PEAR.php');
require_once ('Text/CAPTCHA.php'); require_once('Text/CAPTCHA.php');
class Captcha extends Vn\Web\RestRequest class Captcha extends Vn\Web\RestRequest {
{ function run($db) {
function run ($db)
{
$options = $options =
[ [
'width' => 130 'width' => 130
@ -24,23 +22,23 @@ class Captcha extends Vn\Web\RestRequest
] ]
]; ];
$captcha = Text_CAPTCHA::factory ('Image'); $captcha = Text_CAPTCHA::factory('Image');
$retval = $captcha->init ($options); $retval = $captcha->init($options);
if (PEAR::isError ($retval)) if (PEAR::isError($retval))
throw new Exception ('Error initializing CAPTCHA: %s!', throw new Exception('Error initializing CAPTCHA: %s!',
$retval->getMessage()); $retval->getMessage());
$png = $captcha->getCAPTCHA (); $png = $captcha->getCAPTCHA();
if (PEAR::isError ($png)) if (PEAR::isError($png))
throw new Exception ('Error generating CAPTCHA: %s!', throw new Exception('Error generating CAPTCHA: %s!',
$png->getMessage ()); $png->getMessage());
// Get secret passphrase // Get secret passphrase
$_SESSION['captcha'] = $captcha->getPhrase (); $_SESSION['captcha'] = $captcha->getPhrase();
header ('Content-Type: image/png'); header('Content-Type: image/png');
echo $png; echo $png;
} }
} }

View File

@ -5,18 +5,16 @@ include __DIR__.'/account.php';
/** /**
* Updates the user password. * Updates the user password.
**/ **/
class ChangePassword extends Vn\Web\JsonRequest class ChangePassword extends Vn\Web\JsonRequest {
{
const PARAMS = ['newPassword']; const PARAMS = ['newPassword'];
function run ($db) function run($db) {
{
$newPassword = $_REQUEST['newPassword']; $newPassword = $_REQUEST['newPassword'];
$oldPassword = $_REQUEST['oldPassword']; $oldPassword = $_REQUEST['oldPassword'];
$db->query ('CALL account.myUserChangePassword (#, #)', $db->query('CALL account.myUserChangePassword(#, #)',
[$oldPassword, $newPassword]); [$oldPassword, $newPassword]);
Account::sync ($db, $_SESSION['user'], $newPassword); Account::sync($db, $_SESSION['user'], $newPassword);
return TRUE; return TRUE;
} }
} }

View File

@ -1,7 +1,6 @@
<?php <?php
class Log extends Vn\Web\JsonRequest class Log extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'file' 'file'
,'line' ,'line'
@ -9,10 +8,9 @@ class Log extends Vn\Web\JsonRequest
,'stack' ,'stack'
]; ];
function run ($db) function run($db) {
{ $user = isset($_SESSION['user']) ? $_SESSION['user'] : 'guest';
$user = isset ($_SESSION['user']) ? $_SESSION['user'] : 'guest'; error_log(sprintf("Javascript: User: %s: %s(%d): %s.\n%s"
error_log (sprintf ("Javascript: User: %s: %s(%d): %s.\n%s"
,$user ,$user
,$_REQUEST['file'] ,$_REQUEST['file']
,$_REQUEST['line'] ,$_REQUEST['line']

View File

@ -2,24 +2,21 @@
include __DIR__.'/account.php'; include __DIR__.'/account.php';
class Login extends Vn\Web\JsonRequest class Login extends Vn\Web\JsonRequest {
{ function run($db) {
function run ($db)
{
try { try {
Account::trySync ($db Account::trySync($db
,strtolower ($_POST['user']) ,strtolower($_POST['user'])
,$_POST['password'] ,$_POST['password']
); );
} }
catch (Exception $e) catch (Exception $e) {
{ error_log($e->getMessage());
error_log ($e->getMessage());
} }
$token = $this->service->createToken ( $token = $this->service->createToken(
$_SESSION['user'], $_SESSION['user'],
!empty ($_POST['remember']) !empty($_POST['remember'])
); );
return [ return [

View File

@ -1,10 +1,8 @@
<?php <?php
class Logout extends Vn\Web\JsonRequest class Logout extends Vn\Web\JsonRequest {
{ function run($db) {
function run ($db) $this->service->logout();
{
$this->service->logout ();
return TRUE; return TRUE;
} }
} }

View File

@ -4,63 +4,56 @@ use Vn\Lib;
use Vn\Web\Security; use Vn\Web\Security;
use Vn\Lib\Type; use Vn\Lib\Type;
class Query extends Vn\Web\JsonRequest class Query extends Vn\Web\JsonRequest {
{
const PARAMS = ['sql']; const PARAMS = ['sql'];
const SECURITY = Security::INVOKER; const SECURITY = Security::INVOKER;
function run ($db) function run($db) {
{
$results = []; $results = [];
try { try {
$db->multiQuery ($_REQUEST['sql']); $db->multiQuery($_REQUEST['sql']);
do { do {
$result = $db->storeResult (); $result = $db->storeResult();
if ($result !== FALSE) if ($result !== FALSE) {
{ $results[] = $this->transformResult($result);
$results[] = $this->transformResult ($result); $result->free();
$result->free ();
} }
else else
$results[] = TRUE; $results[] = TRUE;
} }
while ($db->moreResults () && $db->nextResult ()); while ($db->moreResults() && $db->nextResult());
// Checks for warnings // Checks for warnings
if ($db->checkWarnings () if ($db->checkWarnings()
&& ($result = $db->query ('SHOW WARNINGS'))) &&($result = $db->query('SHOW WARNINGS'))) {
{
$sql = 'SELECT `description`, @warn `code` $sql = 'SELECT `description`, @warn `code`
FROM `message` WHERE `code` = @warn'; FROM `message` WHERE `code` = @warn';
while ($row = $result->fetch_object ()) while ($row = $result->fetch_object()) {
{
if ($row->Code == 1265 if ($row->Code == 1265
&& ($warning = $db->getObject ($sql))) &&($warning = $db->getObject($sql)))
trigger_error ("{$warning->code}: {$warning->description}", E_USER_WARNING); trigger_error("{$warning->code}: {$warning->description}", E_USER_WARNING);
else else
trigger_error ("{$row->Code}: {$row->Message}", E_USER_WARNING); trigger_error("{$row->Code}: {$row->Message}", E_USER_WARNING);
} }
} }
// Checks for errors // Checks for errors
$db->checkError (); $db->checkError();
} }
catch (Vn\Db\Exception $e) catch (Vn\Db\Exception $e) {
{ if ($e->getCode() == 1644) {
if ($e->getCode () == 1644) $dbMessage = $e->getMessage();
{
$dbMessage = $e->getMessage ();
$sql = 'SELECT `description` FROM `message` WHERE `code` = #'; $sql = 'SELECT `description` FROM `message` WHERE `code` = #';
$message = $db->getValue ($sql, [$dbMessage]); $message = $db->getValue($sql, [$dbMessage]);
if ($message) if ($message)
throw new Lib\UserException ($message, $dbMessage); throw new Lib\UserException($message, $dbMessage);
} }
throw $e; throw $e;
@ -72,10 +65,9 @@ class Query extends Vn\Web\JsonRequest
/** /**
* Transforms the database result into a JSON parseable object. * Transforms the database result into a JSON parseable object.
**/ **/
function transformResult ($result) function transformResult($result) {
{
$tableMap = []; $tableMap = [];
$columns = $result->fetch_fields (); $columns = $result->fetch_fields();
$resultMap = $resultMap =
[ [
@ -84,12 +76,10 @@ class Query extends Vn\Web\JsonRequest
'tables' => [] 'tables' => []
]; ];
for ($i = 0; $i < $result->field_count; $i++) for ($i = 0; $i < $result->field_count; $i++) {
{
$column = $columns[$i]; $column = $columns[$i];
switch ($column->type) switch ($column->type) {
{
case MYSQLI_TYPE_BIT: case MYSQLI_TYPE_BIT:
$type = Type::BOOLEAN; $type = Type::BOOLEAN;
break; break;
@ -118,8 +108,7 @@ class Query extends Vn\Web\JsonRequest
$type = Type::STRING; $type = Type::STRING;
} }
if (!isset ($tableMap[$column->table])) if (!isset($tableMap[$column->table])) {
{
$resultMap['tables'][] = $resultMap['tables'][] =
[ [
'name' => $column->table, 'name' => $column->table,
@ -127,7 +116,7 @@ class Query extends Vn\Web\JsonRequest
'schema' => $column->db, 'schema' => $column->db,
'pks' => [] 'pks' => []
]; ];
$tableIndex = count ($resultMap['tables']) - 1; $tableIndex = count($resultMap['tables']) - 1;
$tableMap[$column->table] = $tableIndex; $tableMap[$column->table] = $tableIndex;
} }
else else
@ -136,7 +125,7 @@ class Query extends Vn\Web\JsonRequest
if ($column->flags & MYSQLI_PRI_KEY_FLAG) if ($column->flags & MYSQLI_PRI_KEY_FLAG)
$resultMap['tables'][$tableIndex]['pks'][] = $i; $resultMap['tables'][$tableIndex]['pks'][] = $i;
$default = $this->castValue ($column->def, $type); $default = $this->castValue($column->def, $type);
$resultMap['columns'][] = $resultMap['columns'][] =
[ [
@ -151,10 +140,9 @@ class Query extends Vn\Web\JsonRequest
$columns = $resultMap['columns']; $columns = $resultMap['columns'];
while ($row = $result->fetch_row ()) while ($row = $result->fetch_row()) {
{
for ($j = 0; $j < $result->field_count; $j++) for ($j = 0; $j < $result->field_count; $j++)
$row[$j] = $this->castValue ($row[$j], $columns[$j]['type']); $row[$j] = $this->castValue($row[$j], $columns[$j]['type']);
$resultMap['data'][] = $row; $resultMap['data'][] = $row;
} }
@ -165,11 +153,9 @@ class Query extends Vn\Web\JsonRequest
/** /**
* Transforms the database value into a JSON parseable value. * Transforms the database value into a JSON parseable value.
**/ **/
function castValue ($value, $type) function castValue($value, $type) {
{
if ($value !== NULL) if ($value !== NULL)
switch ($type) switch ($type) {
{
case Type::BOOLEAN: case Type::BOOLEAN:
return (bool) $value; return (bool) $value;
case Type::INTEGER: case Type::INTEGER:
@ -178,14 +164,13 @@ class Query extends Vn\Web\JsonRequest
return (float) $value; return (float) $value;
case Type::DATE: case Type::DATE:
case Type::DATE_TIME: case Type::DATE_TIME:
return mktime return mktime(
( substr($value, 11 , 2)
substr ($value, 11 , 2) ,substr($value, 14 , 2)
,substr ($value, 14 , 2) ,substr($value, 17 , 2)
,substr ($value, 17 , 2) ,substr($value, 5 , 2)
,substr ($value, 5 , 2) ,substr($value, 8 , 2)
,substr ($value, 8 , 2) ,substr($value, 0 , 4)
,substr ($value, 0 , 4)
); );
break; break;
} }

View File

@ -2,13 +2,11 @@
use Vn\Web; use Vn\Web;
class RecoverPassword extends Vn\Web\JsonRequest class RecoverPassword extends Vn\Web\JsonRequest {
{
const PARAMS = ['recoverUser']; const PARAMS = ['recoverUser'];
function run ($db) function run($db) {
{ $user = $db->getRow(
$user = $db->getRow (
'SELECT email, active FROM account.user WHERE name = #', 'SELECT email, active FROM account.user WHERE name = #',
[$_REQUEST['recoverUser']] [$_REQUEST['recoverUser']]
); );
@ -17,11 +15,11 @@ class RecoverPassword extends Vn\Web\JsonRequest
return TRUE; return TRUE;
$service = $this->service; $service = $this->service;
$token = $service->createToken ($_REQUEST['recoverUser'], FALSE, TRUE); $token = $service->createToken($_REQUEST['recoverUser'], FALSE, TRUE);
$url = $service->getUrl () ."#!form=account/conf&token=$token"; $url = $service->getUrl() ."#!form=account/conf&token=$token";
$report = new Vn\Web\Report ($db, 'recover-password', ['url' => $url]); $report = new Vn\Web\Report($db, 'recover-password', ['url' => $url]);
$report->sendMail ($user['email']); $report->sendMail($user['email']);
return TRUE; return TRUE;
} }
@ -31,40 +29,37 @@ class RecoverPassword extends Vn\Web\JsonRequest
const DIGITS = '1234567890'; const DIGITS = '1234567890';
const SYMBOLS = '!$%&()=.'; const SYMBOLS = '!$%&()=.';
function genPassword ($db) function genPassword($db) {
{ $restrictions = $db->getRow(
$restrictions = $db->getRow (
'SELECT length, nUpper, nDigits, nPunct FROM account.userPassword'); 'SELECT length, nUpper, nDigits, nPunct FROM account.userPassword');
$pass = []; $pass = [];
$newPass = ''; $newPass = '';
$nAlpha = $restrictions['length'] - ( $nAlpha = $restrictions['length'] -(
$restrictions['nUpper'] + $restrictions['nUpper'] +
$restrictions['nDigits'] + $restrictions['nDigits'] +
$restrictions['nPunct']); $restrictions['nPunct']);
$this->genRands ($pass, self::LOWERS, $nAlpha); $this->genRands($pass, self::LOWERS, $nAlpha);
$this->genRands ($pass, self::UPPERS, $restrictions['nUpper']); $this->genRands($pass, self::UPPERS, $restrictions['nUpper']);
$this->genRands ($pass, self::DIGITS, $restrictions['nDigits']); $this->genRands($pass, self::DIGITS, $restrictions['nDigits']);
$this->genRands ($pass, self::SYMBOLS, $restrictions['nPunct']); $this->genRands($pass, self::SYMBOLS, $restrictions['nPunct']);
for ($i = count ($pass) - 1; $i >= 0; $i--) for ($i = count($pass) - 1; $i >= 0; $i--) {
{ $rand = rand(0, $i);
$rand = rand (0, $i);
$newPass .= $pass[$rand]; $newPass .= $pass[$rand];
array_splice ($pass, $rand, 1); array_splice($pass, $rand, 1);
} }
return $newPass; return $newPass;
} }
function genRands (&$pass, $chars, $max) function genRands(&$pass, $chars, $max) {
{ $len = strlen($chars) - 1;
$len = strlen ($chars) - 1;
for ($i = 0; $i < $max; $i++) for ($i = 0; $i < $max; $i++)
$pass[] = $chars[rand (0, $len)]; $pass[] = $chars[rand(0, $len)];
} }
} }

View File

@ -5,21 +5,19 @@ include __DIR__.'/account.php';
/** /**
* Sets the user password. * Sets the user password.
**/ **/
class SetPassword extends Vn\Web\JsonRequest class SetPassword extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'setUser' 'setUser'
,'setPassword' ,'setPassword'
]; ];
function run ($db) function run($db) {
{
$setUser = $_REQUEST['setUser']; $setUser = $_REQUEST['setUser'];
$setPassword = $_REQUEST['setPassword']; $setPassword = $_REQUEST['setPassword'];
$db->query ('CALL account.userSetPassword (#, #)', $db->query('CALL account.userSetPassword(#, #)',
[$setUser, $setPassword]); [$setUser, $setPassword]);
Account::sync ($db, $setUser, $setPassword); Account::sync($db, $setUser, $setPassword);
return TRUE; return TRUE;
} }
} }

View File

@ -1,12 +1,10 @@
<?php <?php
class Supplant extends Vn\Web\JsonRequest class Supplant extends Vn\Web\JsonRequest {
{
const PARAMS = ['supplantUser']; const PARAMS = ['supplantUser'];
function run ($db) function run($db) {
{ return $this->service->createToken($_REQUEST['supplantUser']);
return $this->service->createToken ($_REQUEST['supplantUser']);
} }
} }

View File

@ -6,13 +6,11 @@ include __DIR__.'/account.php';
* Updates the user credentials on external systems like Samba, create * Updates the user credentials on external systems like Samba, create
* home directory, create mailbox, etc. * home directory, create mailbox, etc.
**/ **/
class SyncUser extends Vn\Web\JsonRequest class SyncUser extends Vn\Web\JsonRequest {
{
const PARAMS = ['syncUser']; const PARAMS = ['syncUser'];
function run ($db) function run($db) {
{ Account::sync($db, $_REQUEST['syncUser'], NULL);
Account::sync ($db, $_REQUEST['syncUser'], NULL);
return TRUE; return TRUE;
} }
} }

View File

@ -5,17 +5,15 @@ use Vn\Lib;
/** /**
* Adds a document to the Document Management System. * Adds a document to the Document Management System.
**/ **/
class Add extends Vn\Web\JsonRequest class Add extends Vn\Web\JsonRequest {
{ function run($db) {
function run ($db)
{
// XXX: Uncomment only to test the script // XXX: Uncomment only to test the script
//$_REQUEST['description'] = 'description'; //$_REQUEST['description'] = 'description';
$description = empty ($_REQUEST['description']) ? $description = empty($_REQUEST['description']) ?
NULL : $_REQUEST['description']; NULL : $_REQUEST['description'];
$baseDir = _DATA_DIR .'/'. $this->app->getName (); $baseDir = _DATA_DIR .'/'. $this->app->getName();
$docsDir = "$baseDir/dms"; $docsDir = "$baseDir/dms";
$tempDir = "$baseDir/.dms"; $tempDir = "$baseDir/.dms";
@ -27,26 +25,26 @@ class Add extends Vn\Web\JsonRequest
// Checks document restrictions // Checks document restrictions
if (empty ($_FILES['doc']['name'])) if (empty($_FILES['doc']['name']))
throw new Lib\UserException ('File not choosed'); throw new Lib\UserException('File not choosed');
$maxSize = $db->getValue ('SELECT max_size FROM dms_config'); $maxSize = $db->getValue('SELECT max_size FROM dms_config');
if ($_FILES['doc']['size'] > $maxSize * 1048576) if ($_FILES['doc']['size'] > $maxSize * 1048576)
throw new Lib\UserException (sprintf ('File size exceeds size: %d MB', $maxSize)); throw new Lib\UserException(sprintf('File size exceeds size: %d MB', $maxSize));
try { try {
// Registers the document in the database // Registers the document in the database
$db->query ('START TRANSACTION'); $db->query('START TRANSACTION');
$db->query ('INSERT INTO dms_document SET description = #', [$description]); $db->query('INSERT INTO dms_document SET description = #', [$description]);
$docId = (string) $db->getValue ('SELECT LAST_INSERT_ID()'); $docId =(string) $db->getValue('SELECT LAST_INSERT_ID()');
$len = strlen ($docId); $len = strlen($docId);
$neededLevels = ceil ($len / $digXDir) - 1; $neededLevels = ceil($len / $digXDir) - 1;
$dirLevels = $db->getValue ( $dirLevels = $db->getValue(
'SELECT dir_levels FROM dms_config LOCK IN SHARE MODE'); 'SELECT dir_levels FROM dms_config LOCK IN SHARE MODE');
if ($dirLevels > $neededLevels) if ($dirLevels > $neededLevels)
@ -55,55 +53,52 @@ class Add extends Vn\Web\JsonRequest
// Reorganizes the file repository if necessary // Reorganizes the file repository if necessary
if ($dirLevels < $neededLevels) if ($dirLevels < $neededLevels)
$dirLevels = $db->getValue ( $dirLevels = $db->getValue(
'SELECT dir_levels FROM dms_config FOR UPDATE'); 'SELECT dir_levels FROM dms_config FOR UPDATE');
if ($dirLevels < $neededLevels) if ($dirLevels < $neededLevels) {
{ if (is_dir($docsDir)) {
if (is_dir ($docsDir)) $dif =($neededLevels - $dirLevels) - 1;
{
$dif = ($neededLevels - $dirLevels) - 1;
$newDir = $docsDir; $newDir = $docsDir;
for ($i = 0; $i < $dif; $i++) for ($i = 0; $i < $dif; $i++)
$newDir .= "/$zerosDir"; $newDir .= "/$zerosDir";
$success = rename ($docsDir, $tempDir) $success = rename($docsDir, $tempDir)
&& mkdir ($newDir, 0770, TRUE) && mkdir($newDir, 0770, TRUE)
&& rename ($tempDir, "$newDir/$zerosDir"); && rename($tempDir, "$newDir/$zerosDir");
if (!$success) if (!$success)
throw new Exception ('Error while reorganizing directory tree'); throw new Exception('Error while reorganizing directory tree');
} }
$curLevels = $db->query ('UPDATE dms_config SET dir_levels = #', $curLevels = $db->query('UPDATE dms_config SET dir_levels = #',
[$neededLevels]); [$neededLevels]);
} }
// Saves the document to the repository // Saves the document to the repository
$padLen = ($neededLevels + 1) * $digXDir; $padLen =($neededLevels + 1) * $digXDir;
$paddedId = str_pad ($docId, $padLen, '0', STR_PAD_LEFT); $paddedId = str_pad($docId, $padLen, '0', STR_PAD_LEFT);
$saveDir = $docsDir; $saveDir = $docsDir;
for ($i = 0; $i < $neededLevels; $i++) for ($i = 0; $i < $neededLevels; $i++)
$saveDir .= '/'. substr ($paddedId, $i * $digXDir, $digXDir); $saveDir .= '/'. substr($paddedId, $i * $digXDir, $digXDir);
if (!file_exists ($saveDir)) if (!file_exists($saveDir))
mkdir ($saveDir, 0770, TRUE); mkdir($saveDir, 0770, TRUE);
$savePath = "$saveDir/". substr ($paddedId, -$digXDir); $savePath = "$saveDir/". substr($paddedId, -$digXDir);
move_uploaded_file ($_FILES['doc']['tmp_name'], $savePath); move_uploaded_file($_FILES['doc']['tmp_name'], $savePath);
$db->query ('COMMIT'); $db->query('COMMIT');
return $docId; return $docId;
} }
catch (Exception $e) catch (Exception $e) {
{ $db->query('ROLLBACK');
$db->query ('ROLLBACK');
throw $e; throw $e;
} }
} }

View File

@ -4,20 +4,18 @@ use Vn\Web\Security;
use Vn\Web\Util; use Vn\Web\Util;
use Vn\Lib; use Vn\Lib;
class Invoice extends Vn\Web\RestRequest class Invoice extends Vn\Web\RestRequest {
{
const PARAMS = ['invoice']; const PARAMS = ['invoice'];
const SECURITY = Security::INVOKER; const SECURITY = Security::INVOKER;
function run ($db) function run($db) {
{ $pdfPath = $db->getValueFromFile(__DIR__ .'/invoice',
$pdfPath = $db->getValueFromFile (__DIR__ .'/invoice', ['invoice' =>(int) $_GET['invoice']]);
['invoice' => (int) $_GET['invoice']]);
if (!$pdfPath) if (!$pdfPath)
throw new Lib\UserException (s('Invoice id not found')); throw new Lib\UserException(s('Invoice id not found'));
Util::printFile ($pdfPath); Util::printFile($pdfPath);
} }
} }

View File

@ -2,34 +2,30 @@
require_once __DIR__.'/lib/method.php'; require_once __DIR__.'/lib/method.php';
class Clean extends Edi\Method class Clean extends Edi\Method {
{ function ediRun($db) {
function ediRun ($db)
{
$imap = $this->imap; $imap = $this->imap;
$cleanPeriod = $db->getValue ('SELECT clean_period FROM imap_config'); $cleanPeriod = $db->getValue('SELECT clean_period FROM imap_config');
$deleted = 0; $deleted = 0;
$date = new DateTime (NULL); $date = new DateTime(NULL);
$date->sub (new DateInterval ($cleanPeriod)); $date->sub(new DateInterval($cleanPeriod));
$filter = sprintf ('BEFORE "%s"', $date->format('D, j M Y')); $filter = sprintf('BEFORE "%s"', $date->format('D, j M Y'));
$folders = [ $folders = [
$this->imapConf['success_folder'] $this->imapConf['success_folder']
,$this->imapConf['error_folder'] ,$this->imapConf['error_folder']
]; ];
foreach ($folders as $folder) foreach($folders as $folder)
if (imap_reopen ($imap, "{$this->mailbox}$folder")) if (imap_reopen($imap, "{$this->mailbox}$folder")) {
{ if ($messages = imap_search($imap, $filter)) {
if ($messages = imap_search ($imap, $filter)) foreach($messages as $message)
{ imap_delete($imap, $message);
foreach ($messages as $message)
imap_delete ($imap, $message);
imap_expunge ($imap); imap_expunge($imap);
$count = count ($messages); $count = count($messages);
$deleted += $count; $deleted += $count;
} }
else else
@ -41,7 +37,7 @@ class Clean extends Edi\Method
echo "Total $deleted mails deleted\n"; echo "Total $deleted mails deleted\n";
echo "Deleting records from database\n"; echo "Deleting records from database\n";
$db->query ('DELETE FROM message WHERE created < #', [$date]); $db->query('DELETE FROM message WHERE created < #', [$date]);
echo "Done\n"; echo "Done\n";
} }
} }

View File

@ -2,40 +2,35 @@
namespace Edi; namespace Edi;
require_once (__DIR__.'/section.php'); require_once(__DIR__.'/section.php');
class SectionInfo class SectionInfo {
{
var $schema; var $schema;
var $parentInfo; var $parentInfo;
var $section; var $section;
} }
class Message class Message {
{
var $section; var $section;
static function loadSchema ($schemaName) static function loadSchema($schemaName) {
{ $ediSchemaStr = file_get_contents(__DIR__."/$schemaName.json", TRUE);
$ediSchemaStr = file_get_contents (__DIR__."/$schemaName.json", TRUE);
if ($ediSchemaStr !== FALSE) if ($ediSchemaStr !== FALSE)
return json_decode ($ediSchemaStr, TRUE); return json_decode($ediSchemaStr, TRUE);
return NULL; return NULL;
} }
static function isEdiString (&$string) static function isEdiString(&$string) {
{ return substr($string, 0, 4) == 'UNB+';
return substr ($string, 0, 4) == 'UNB+';
} }
function parse (&$string, &$schema = NULL) function parse(&$string, &$schema = NULL) {
{
global $delimiters; global $delimiters;
if (!self::isEdiString ($string)) if (!self::isEdiString($string))
throw new \Exception ('Not an EDI string.'); throw new \Exception('Not an EDI string.');
$pos = 0; $pos = 0;
$error = FALSE; $error = FALSE;
@ -43,34 +38,30 @@ class Message
$firstLoop = TRUE; $firstLoop = TRUE;
$newSection = TRUE; $newSection = TRUE;
$info = new SectionInfo (); $info = new SectionInfo();
$info->schema = $schema; $info->schema = $schema;
$info->parentInfo = NULL; $info->parentInfo = NULL;
$info->section = NULL; $info->section = NULL;
$topInfo = $info; $topInfo = $info;
try { try {
while (TRUE) while (TRUE) {
{ $segment = $this->parseSegment($string, $pos);
$segment = $this->parseSegment ($string, $pos);
if (!$segment && (!$endTag || !$info)) if (!$segment &&(!$endTag || !$info))
break; break;
if (!$segment || ($segment && !$info)) if (!$segment ||($segment && !$info))
throw new \Exception (); throw new \Exception();
if ($firstLoop) if ($firstLoop) {
{
if ($segment->name != $info->schema['mainTag']) if ($segment->name != $info->schema['mainTag'])
throw new \Exception (); throw new \Exception();
} }
else else {
{
for ($i = $info; $i; $i = $i->parentInfo) for ($i = $info; $i; $i = $i->parentInfo)
if (isset ($i->schema['childs'][$segment->name])) if (isset($i->schema['childs'][$segment->name])) {
{ $info = new SectionInfo();
$info = new SectionInfo ();
$info->schema = $i->schema['childs'][$segment->name]; $info->schema = $i->schema['childs'][$segment->name];
$info->parentInfo = $i; $info->parentInfo = $i;
$newSection = TRUE; $newSection = TRUE;
@ -78,32 +69,28 @@ class Message
} }
} }
if ($newSection) if ($newSection) {
{ $section = new Section();
$section = new Section ();
$section->name = $segment->name; $section->name = $segment->name;
$info->section = $section; $info->section = $section;
if ($info->parentInfo) if ($info->parentInfo) {
{
$section->parent = $info->parentInfo->section; $section->parent = $info->parentInfo->section;
$section->parent->childs[$segment->name][] = $section; $section->parent->childs[$segment->name][] = $section;
} }
if (isset ($info->schema['endTag'])) if (isset($info->schema['endTag']))
$endTag = $info; $endTag = $info;
$newSection = FALSE; $newSection = FALSE;
} }
if ($endTag && $endTag->schema['endTag'] == $segment->name) if ($endTag && $endTag->schema['endTag'] == $segment->name) {
{
$endTag->section->segments[] = $segment; $endTag->section->segments[] = $segment;
$info = $endTag->parentInfo; $info = $endTag->parentInfo;
for ($i = $info; $i; $i = $i->parentInfo) for ($i = $info; $i; $i = $i->parentInfo)
if (isset ($i->schema['endTag'])) if (isset($i->schema['endTag'])) {
{
$endTag = $i; $endTag = $i;
break; break;
} }
@ -113,36 +100,30 @@ class Message
$firstLoop = FALSE; $firstLoop = FALSE;
}} }}
catch (\Exception $e) catch (\Exception $e) {
{ throw new \Exception(sprintf('Parse error, something is wrong near "%s"',
throw new \Exception (sprintf ('Parse error, something is wrong near "%s"', substr($string, $pos, 10)));
substr ($string, $pos, 10)));
} }
$this->section = $topInfo->section; $this->section = $topInfo->section;
} }
function parseSegment (&$string, &$pos) function parseSegment(&$string, &$pos) {
{
$empty = TRUE; $empty = TRUE;
$values = []; $values = [];
while (TRUE) while (TRUE) {
{ if (!isset($string{$pos}))
if (!isset ($string{$pos}))
return NULL; return NULL;
if (in_array ($string{$pos}, ['+', ':', '\''])) if (in_array($string{$pos}, ['+', ':', '\''])) {
{ if (!$empty) {
if (!$empty)
{
$values[] = $values[] =
trim (substr ($string, $start, $pos - $start)); trim(substr($string, $start, $pos - $start));
$empty = TRUE; $empty = TRUE;
} }
} }
elseif ($empty) elseif ($empty) {
{
$start = $pos; $start = $pos;
$empty = FALSE; $empty = FALSE;
} }
@ -155,7 +136,7 @@ class Message
$pos++; $pos++;
$segment = new Segment (); $segment = new Segment();
$segment->name = $values[0]; $segment->name = $values[0];
$segment->values = $values; $segment->values = $values;
return $segment; return $segment;

View File

@ -2,40 +2,37 @@
namespace Edi; namespace Edi;
abstract class Method extends \Vn\Lib\Method abstract class Method extends \Vn\Lib\Method {
{
protected $imap; protected $imap;
protected $imapConf; protected $imapConf;
protected $mailbox; protected $mailbox;
abstract function ediRun ($db); abstract function ediRun($db);
function run ($db) function run($db) {
{ $db->selectDb('edi');
$db->selectDb ('edi');
$imapConf = $db->getRow ( $imapConf = $db->getRow(
'SELECT host, user, pass, success_folder, error_folder FROM imap_config'); 'SELECT host, user, pass, success_folder, error_folder FROM imap_config');
$this->mailbox = sprintf ('{%s/imap/ssl/novalidate-cert}', $this->mailbox = sprintf('{%s/imap/ssl/novalidate-cert}',
$imapConf['host']); $imapConf['host']);
$imap = imap_open ($this->mailbox $imap = imap_open($this->mailbox
,$imapConf['user'] ,$imapConf['user']
,base64_decode ($imapConf['pass']) ,base64_decode($imapConf['pass'])
); );
$this->imap = $imap; $this->imap = $imap;
$this->imapConf = $imapConf; $this->imapConf = $imapConf;
if ($imap) if ($imap) {
{ $this->ediRun($db);
$this->ediRun ($db); imap_expunge($imap);
imap_expunge ($imap); imap_close($imap);
imap_close ($imap);
} }
else else
error_log (imap_last_error ()); error_log(imap_last_error());
} }
} }

View File

@ -2,24 +2,22 @@
namespace Edi; namespace Edi;
require_once (__DIR__.'/segment.php'); require_once(__DIR__.'/segment.php');
class Section class Section {
{
var $name; var $name;
var $parent = NULL; var $parent = NULL;
var $segments = []; var $segments = [];
var $childs = []; var $childs = [];
function getValue ($name, $key, $type = NULL, $subname = NULL) function getValue($name, $key, $type = NULL, $subname = NULL) {
{ foreach($this->segments as $segment)
foreach ($this->segments as $segment)
if ($segment->name == $name if ($segment->name == $name
&& (!$subname || $segment->values[1] == $subname)) &&(!$subname || $segment->values[1] == $subname))
return $segment->getValue ($key, $type); return $segment->getValue($key, $type);
if ($this->parent) if ($this->parent)
return $this->parent->getValue ($name, $key, $type, $subname); return $this->parent->getValue($name, $key, $type, $subname);
return NULL; return NULL;
} }

View File

@ -6,31 +6,28 @@ use Vn\Lib\Type;
use Vn\Lib\Date; use Vn\Lib\Date;
use Vn\Lib\Time; use Vn\Lib\Time;
class Segment class Segment {
{
var $name; var $name;
var $values = []; var $values = [];
function getValue ($key, $type = NULL) function getValue($key, $type = NULL) {
{ if ($key < 0 || $key >= count($this->values))
if ($key < 0 || $key >= count ($this->values))
return NULL; return NULL;
$v = $this->values[$key]; $v = $this->values[$key];
switch ($type) switch ($type) {
{
case Type::DATE: case Type::DATE:
$tmp = new Date (); $tmp = new Date();
$tmp->setDate (substr ($v, 0, 4), substr ($v, 4, 2), substr ($v, 6, 2)); $tmp->setDate(substr($v, 0, 4), substr($v, 4, 2), substr($v, 6, 2));
return $tmp; return $tmp;
case Type::TIME: case Type::TIME:
$tmp = new Time (); $tmp = new Time();
$tmp->setTime (substr ($v, 0, 2), substr ($v, 2, 2)); $tmp->setTime(substr($v, 0, 2), substr($v, 2, 2));
return $tmp; return $tmp;
case Type::DOUBLE: case Type::DOUBLE:
case Type::INTEGER: case Type::INTEGER:
Type::set ($v, $type); Type::set($v, $type);
default: default:
return $v; return $v;
} }

View File

@ -1,52 +1,48 @@
<?php <?php
require_once (__DIR__.'/lib/method.php'); require_once(__DIR__.'/lib/method.php');
require_once (__DIR__.'/lib/message.php'); require_once(__DIR__.'/lib/message.php');
use Vn\Lib\Type; use Vn\Lib\Type;
class Load extends Edi\Method class Load extends Edi\Method {
{ function ediRun($db) {
function ediRun ($db) $this->ediSchema = Edi\Message::loadSchema('CLOCKT');
{
$this->ediSchema = Edi\Message::loadSchema ('CLOCKT');
if (!$this->ediSchema) if (!$this->ediSchema)
throw new Exception ('Can not load EDI schema.'); throw new Exception('Can not load EDI schema.');
$this->params = $db->query ( $this->params = $db->query(
'SELECT code, name, subname, position, type, required FROM param'); 'SELECT code, name, subname, position, type, required FROM param');
$inbox = imap_search ($this->imap, 'ALL'); $inbox = imap_search($this->imap, 'ALL');
if ($inbox) if ($inbox) {
{ foreach($inbox as $msg)
foreach ($inbox as $msg) $this->loadMail($db, $msg);
$this->loadMail ($db, $msg);
$inboxCount = count ($inbox); $inboxCount = count($inbox);
if ($inboxCount > 0) if ($inboxCount > 0)
echo "Total $inboxCount messages readed\n"; echo "Total $inboxCount messages readed\n";
} }
} }
function loadMail ($db, $msg) function loadMail($db, $msg) {
{
$imap = $this->imap; $imap = $this->imap;
// Gets EKT messages from email // Gets EKT messages from email
$msgStructure = imap_fetchstructure ($imap, $msg); $msgStructure = imap_fetchstructure($imap, $msg);
$result = []; $result = [];
// Gets the mail sender and Message-ID // Gets the mail sender and Message-ID
$header = imap_headerinfo ($imap, $msg); $header = imap_headerinfo($imap, $msg);
$from = $header->from; $from = $header->from;
$mailId = trim ($header->message_id, '<>'); $mailId = trim($header->message_id, '<>');
if ($from && count ($from) > 0) if ($from && count($from) > 0)
$sender = $from[0]->mailbox .'@'. $from[0]->host; $sender = $from[0]->mailbox .'@'. $from[0]->host;
else else
$sender = NULL; $sender = NULL;
@ -54,37 +50,35 @@ class Load extends Edi\Method
// Searches the EDI message on mail parts // Searches the EDI message on mail parts
$matchTypes = [TYPEAPPLICATION, TYPETEXT]; $matchTypes = [TYPEAPPLICATION, TYPETEXT];
$this->imapFindParts ($msgStructure, $matchTypes, [], $result); $this->imapFindParts($msgStructure, $matchTypes, [], $result);
$count = 0; $count = 0;
$error = NULL; $error = NULL;
foreach ($result as $msgSection) foreach($result as $msgSection)
try try {
{ $part = imap_bodystruct($imap, $msg, $msgSection);
$part = imap_bodystruct ($imap, $msg, $msgSection); $ediString = imap_fetchbody($imap, $msg, $msgSection);
$ediString = imap_fetchbody ($imap, $msg, $msgSection);
switch ($part->encoding) switch ($part->encoding) {
{
case ENCBASE64: case ENCBASE64:
$ediString = imap_base64 ($ediString); $ediString = imap_base64($ediString);
break; break;
case ENCQUOTEDPRINTABLE: case ENCQUOTEDPRINTABLE:
$ediString = imap_qprint ($ediString); $ediString = imap_qprint($ediString);
break; break;
} }
if (!Edi\Message::isEdiString ($ediString)) if (!Edi\Message::isEdiString($ediString))
continue; continue;
// Creates the EDI object and loads its exchanges // Creates the EDI object and loads its exchanges
$ediMessage = new Edi\Message (); $ediMessage = new Edi\Message();
$ediMessage->parse ($ediString, $this->ediSchema); $ediMessage->parse($ediString, $this->ediSchema);
$db->query ('START TRANSACTION'); $db->query('START TRANSACTION');
$db->query ('CALL messageNew (#mailId, #sender, @message)', $db->query('CALL messageNew(#mailId, #sender, @message)',
[ [
'mailId' => $mailId, 'mailId' => $mailId,
'sender' => $sender 'sender' => $sender
@ -93,19 +87,16 @@ class Load extends Edi\Method
$unb = $ediMessage->section; $unb = $ediMessage->section;
$unhs = $unb->childs['UNH']; $unhs = $unb->childs['UNH'];
foreach ($unhs as $unh) foreach($unhs as $unh)
foreach ($lins = $unh->childs['LIN'] as $lin) foreach($lins = $unh->childs['LIN'] as $lin) {
{
$ediValues = []; $ediValues = [];
// Gets the exchange params // Gets the exchange params
$this->params->data_seek (0); $this->params->data_seek(0);
while ($row = $this->params->fetch_assoc ()) while ($row = $this->params->fetch_assoc()) {
{ switch ($row['type']) {
switch ($row['type'])
{
case 'INTEGER': case 'INTEGER':
$type = Type::INTEGER; $type = Type::INTEGER;
break; break;
@ -122,56 +113,54 @@ class Load extends Edi\Method
$type = Type::STRING; $type = Type::STRING;
} }
$value = $lin->getValue ( $value = $lin->getValue(
$row['name'], $row['position'], $type, $row['subname']); $row['name'], $row['position'], $type, $row['subname']);
if (!isset ($value) && $row['required']) if (!isset($value) && $row['required'])
throw new Exception ('Missing required parameter: '. $row['code']); throw new Exception('Missing required parameter: '. $row['code']);
$ediValues[$row['code']] = $value; $ediValues[$row['code']] = $value;
} }
// Gets the exchange features // Gets the exchange features
$res = $db->query ( $res = $db->query(
'SELECT presentation_order, feature 'SELECT presentation_order, feature
FROM item_feature FROM item_feature
WHERE item_id = #ref WHERE item_id = #ref
AND entry_date <= CURDATE() AND entry_date <= CURDATE()
AND (expiry_date IS NULL OR expiry_date >= CURDATE()) AND(expiry_date IS NULL OR expiry_date >= CURDATE())
GROUP BY presentation_order' GROUP BY presentation_order'
,$ediValues ,$ediValues
); );
if ($res) if ($res)
while ($row = $res->fetch_assoc ()) while ($row = $res->fetch_assoc()) {
{ $value = $lin->getValue('IMD', 2, Type::INTEGER, $row['feature']);
$value = $lin->getValue ('IMD', 2, Type::INTEGER, $row['feature']);
$ediValues['s'.$row['presentation_order']] = $value; $ediValues['s'.$row['presentation_order']] = $value;
} }
else else
throw new Exception ('Can\'t get the item features.'); throw new Exception('Can\'t get the item features.');
for ($i = 1; $i <= 6; $i++) for ($i = 1; $i <= 6; $i++)
if (!isset ($ediValues['s'.$i])) if (!isset($ediValues['s'.$i]))
$ediValues['s'.$i] = NULL; $ediValues['s'.$i] = NULL;
// Adds the exchange to the Database // Adds the exchange to the Database
$res = $db->queryFromFile (__DIR__.'/sql/batch-add', $ediValues); $res = $db->queryFromFile(__DIR__.'/sql/batch-add', $ediValues);
if (!$res) if (!$res)
throw new Exception ('Failed to insert the line.'); throw new Exception('Failed to insert the line.');
$count++; $count++;
} }
$db->query ('COMMIT'); $db->query('COMMIT');
} }
catch (Exception $e) catch (Exception $e) {
{ $db->query('ROLLBACK');
$db->query ('ROLLBACK'); $error = $e->getMessage();
$error = $e->getMessage ();
break; break;
} }
@ -180,43 +169,38 @@ class Load extends Edi\Method
// Logs information of realized operations // Logs information of realized operations
if (!$error) if (!$error) {
{
$folder = $this->imapConf['success_folder']; $folder = $this->imapConf['success_folder'];
echo "Mail loaded with $count lines.\n"; echo "Mail loaded with $count lines.\n";
} }
else else {
{
$folder = $this->imapConf['error_folder']; $folder = $this->imapConf['error_folder'];
echo "Mail error: $error\n"; echo "Mail error: $error\n";
} }
// Moves the mail to another folder // Moves the mail to another folder
$folder = sprintf ('%s', $folder); $folder = sprintf('%s', $folder);
if (!imap_mail_move ($imap, $msg, $folder)) if (!imap_mail_move($imap, $msg, $folder))
error_log ('Can\'t move message to %s: %s' error_log('Can\'t move message to %s: %s'
,$folder ,$folder
,imap_last_error () ,imap_last_error()
); );
} }
function imapFindParts (&$part, &$matchTypes, $section, &$result) function imapFindParts(&$part, &$matchTypes, $section, &$result) {
{ if (in_array($part->type, $matchTypes)) {
if (in_array ($part->type, $matchTypes)) if (count($section) > 0)
{ $result[] = implode('.', $section);
if (count ($section) > 0)
$result[] = implode ('.', $section);
else else
$result[] = '1'; $result[] = '1';
} }
elseif ($part->type == TYPEMULTIPART) elseif ($part->type == TYPEMULTIPART)
foreach ($part->parts as $i => $subpart) foreach($part->parts as $i => $subpart) {
{ array_push($section, $i + 1);
array_push ($section, $i + 1); $this->imapFindParts($subpart, $matchTypes, $section, $result);
$this->imapFindParts ($subpart, $matchTypes, $section, $result); array_pop($section);
array_pop ($section);
} }
} }
} }

View File

@ -1,47 +1,47 @@
<?php <?php
class Update extends Vn\Lib\Method class Update extends Vn\Lib\Method {
{ function run($db) {
function run ($db) $db->selectDb('edi');
{ //$db->options(MYSQLI_OPT_LOCAL_INFILE, TRUE);
$db->selectDb ('edi');
//$db->options (MYSQLI_OPT_LOCAL_INFILE, TRUE);
$tmpDir = '/tmp/floricode'; $tmpDir = '/tmp/floricode';
// Establece una conexi<78>n FTP // Establish the FTP connection
$ftpConf = $db->getRow ('SELECT host, user, password FROM ftp_config'); $ftpConf = $db->getRow('SELECT host, user, password FROM ftp_config');
echo "Openning FTP connection to {$ftpConf['host']}\n"; echo "Openning FTP connection to {$ftpConf['host']}\n";
$ftpConn = ftp_connect ($ftpConf['host']); $ftpConn = ftp_connect($ftpConf['host']);
if (!$ftpConn) if (!$ftpConn)
throw new Exception ('Can not connect to '. $ftpConf['host']); throw new Exception('Can not connect to '. $ftpConf['host']);
if (!ftp_login ($ftpConn, $ftpConf['user'], $ftpConf['password'])) if (!ftp_login($ftpConn, $ftpConf['user'], $ftpConf['password']))
throw new Exception ('Can not login to '. $ftpConf['user'] .'@'. $ftpConf['host']); throw new Exception('Can not login to '. $ftpConf['user'] .'@'. $ftpConf['host']);
// Obtiene el listado de tablas a actualizar // Gets the list with the tables to update
set_time_limit (0); set_time_limit(0);
$res = $db->query ( $res = $db->query(
'SELECT file_name, to_table, file, updated FROM file_config'); 'SELECT file_name, to_table, file, updated FROM file_config');
$dwFiles = []; $dwFiles = [];
if (!file_exists ($tmpDir)) if (!file_exists($tmpDir))
mkdir ($tmpDir); mkdir($tmpDir);
while ($row = $res->fetch_assoc ()) while ($row = $res->fetch_assoc())
try { try {
$file = $row['file']; $file = $row['file'];
$table = $row['to_table']; $table = $row['to_table'];
$baseName = $row['file_name']; $baseName = $row['file_name'];
if ($row['updated']) if ($row['updated']) {
$updated = DateTime::createFromFormat ('Y-m-d', $row['updated']); $updated = DateTime::createFromFormat('Y-m-d', $row['updated']);
$updated->setTime(0, 0, 0, 0);
}
else else
$updated = NULL; $updated = NULL;
@ -49,71 +49,65 @@ class Update extends Vn\Lib\Method
$zipFile = "$tmpDir/$file.zip"; $zipFile = "$tmpDir/$file.zip";
$ucDir = "$tmpDir/$file"; $ucDir = "$tmpDir/$file";
// Intenta descargar y descomprimir el fichero con los datos // Downloads and decompress the file with the data
if (!isset ($dwFiles[$file])) if (!isset($dwFiles[$file])) {
{
$dwFiles[$file] = TRUE; $dwFiles[$file] = TRUE;
echo "Downloading $remoteFile\n"; echo "Downloading $remoteFile\n";
if (!ftp_get ($ftpConn, $zipFile, $remoteFile, FTP_BINARY)) if (!ftp_get($ftpConn, $zipFile, $remoteFile, FTP_BINARY))
throw new Exception ("Error downloading $remoteFile to $zipFile"); throw new Exception("Error downloading $remoteFile to $zipFile");
$zip = new ZipArchive; $zip = new ZipArchive;
if ($zip->open ($zipFile) !== TRUE) if ($zip->open($zipFile) !== TRUE)
throw new Exception ("Can not open $zipFile"); throw new Exception("Can not open $zipFile");
@mkdir ($ucDir, 0774, TRUE); @mkdir($ucDir, 0774, TRUE);
if (!$zip->extractTo ($ucDir)) if (!$zip->extractTo($ucDir))
throw new Exception ("Can not uncompress file $zipFile"); throw new Exception("Can not uncompress file $zipFile");
$zip->close(); $zip->close();
unlink ($zipFile); unlink($zipFile);
} }
foreach (glob ("$ucDir/$baseName*.txt") as $fileName) foreach(glob("$ucDir/$baseName*.txt") as $fileName)
break; break;
if (!$fileName) if (!$fileName)
throw new Exception ("Import file for table $table does not exist"); throw new Exception("Import file for table $table does not exist");
// Si los datos están actualizados omite la tabla // If data is updated, omits the table
$lastUpdated = substr ($fileName, -10, 6); $lastUpdated = substr($fileName, -10, 6);
$lastUpdated = DateTime::createFromFormat ('dmy', $lastUpdated); $lastUpdated = DateTime::createFromFormat('dmy', $lastUpdated);
$lastUpdated->setTime(0, 0, 0, 0);
if ($updated && $lastUpdated <= $updated) if (isset($updated) && $lastUpdated <= $updated) {
echo "Table $table is updated, omitted\n";
continue; continue;
}
// Actualiza los datos de la tabla // Updates the table
echo "Dumping data to table $table\n"; echo "Dumping data to table $table\n";
$importQuery = $db->loadFromFile (__DIR__."/sql/$table", ['file' => $fileName]);
$db->multiQuery ( $db->query("START TRANSACTION");
"START TRANSACTION; $db->query("DELETE FROM {$db->quote($table)}");
DELETE FROM $table; $db->queryFromFile(__DIR__."/sql/$table", ['file' => $fileName]);
$importQuery; $db->query("UPDATE file_config SET updated = # WHERE file_name = #",
UPDATE file_config SET updated = # WHERE file_name = #;
COMMIT;",
[$lastUpdated, $baseName] [$lastUpdated, $baseName]
); );
$db->query("COMMIT");
do {
$db->storeResult ();
}
while ($db->moreResults () && $db->nextResult ());
} }
catch (Exception $e) catch (Exception $e) {
{ $db->query('ROLLBACK');
$db->query ('ROLLBACK'); error_log($e->getMessage());
error_log ($e->getMessage ());
} }
shell_exec ("rm -R $tmpDir"); shell_exec("rm -R $tmpDir");
ftp_close ($ftpConn); ftp_close($ftpConn);
echo "Update completed\n"; echo "Update completed\n";
} }

View File

@ -2,34 +2,31 @@
use Vn\Lib\UserException; use Vn\Lib\UserException;
class Image class Image {
{
/** /**
* Creates an image resource from a valid image file. * Creates an image resource from a valid image file.
* *
* @param string $srcFile The source file name * @param string $srcFile The source file name
**/ **/
static function create ($srcFile) static function create($srcFile) {
{ $imageType = exif_imagetype($srcFile);
$imageType = exif_imagetype ($srcFile);
if ($imageType !== FALSE) if ($imageType !== FALSE)
switch ($imageType) switch ($imageType) {
{
case IMAGETYPE_JPEG: case IMAGETYPE_JPEG:
$image = imagecreatefromjpeg ($srcFile); $image = imagecreatefromjpeg($srcFile);
break; break;
case IMAGETYPE_PNG: case IMAGETYPE_PNG:
$image = imagecreatefrompng ($srcFile); $image = imagecreatefrompng($srcFile);
break; break;
case IMAGETYPE_GIF: case IMAGETYPE_GIF:
$image = imagecreatefromgif ($srcFile); $image = imagecreatefromgif ($srcFile);
break; break;
default: default:
throw new UserException (s('Bad file format')); throw new UserException(s('Bad file format'));
} }
else else
throw new UserException (s('Image open error')); throw new UserException(s('Image open error'));
return $image; return $image;
} }
@ -44,23 +41,21 @@ class Image
* @param boolean $crop Wether to crop the image * @param boolean $crop Wether to crop the image
* @param boolean $symbolicSrc If it is not necessary to resize the image creates a symbolic link using the passed path as source * @param boolean $symbolicSrc If it is not necessary to resize the image creates a symbolic link using the passed path as source
**/ **/
static function resizeSave ($image, $dstFile, $maxHeight, $maxWidth, $crop = FALSE, $symbolicSrc = NULL) static function resizeSave($image, $dstFile, $maxHeight, $maxWidth, $crop = FALSE, $symbolicSrc = NULL) {
{ $width = imagesx($image);
$width = imagesx ($image); $height = imagesy($image);
$height = imagesy ($image);
$dirname = dirname ($dstFile); $dirname = dirname($dstFile);
if (!is_dir ($dirname)) if (!is_dir($dirname))
mkdir ($dirname, 0775, TRUE); mkdir($dirname, 0775, TRUE);
if (file_exists ($dstFile)) if (file_exists($dstFile))
@unlink ($dstFile); @unlink($dstFile);
// Check if it is necessary to resize the image // Check if it is necessary to resize the image
if ($height > $maxHeight || $width > $maxWidth) if ($height > $maxHeight || $width > $maxWidth) {
{
$srcX = 0; $srcX = 0;
$srcY = 0; $srcY = 0;
$srcWidth = $width; $srcWidth = $width;
@ -68,45 +63,38 @@ class Image
$dstWidth = $width; $dstWidth = $width;
$dstHeight = $height; $dstHeight = $height;
if (!$crop) // Resize if (!$crop) // Resize {
{
$ratio = NULL; $ratio = NULL;
if ($dstWidth > $maxWidth) if ($dstWidth > $maxWidth) {
{
$ratio = $dstWidth / $maxWidth; $ratio = $dstWidth / $maxWidth;
$dstWidth = $maxWidth; $dstWidth = $maxWidth;
$dstHeight = (int) ($dstHeight / $ratio); $dstHeight =(int)($dstHeight / $ratio);
} }
if ($dstHeight > $maxHeight) if ($dstHeight > $maxHeight) {
{
$ratio = $dstHeight / $maxHeight; $ratio = $dstHeight / $maxHeight;
$dstHeight = $maxHeight; $dstHeight = $maxHeight;
$dstWidth = (int) ($dstWidth / $ratio); $dstWidth =(int)($dstWidth / $ratio);
} }
} }
else // Cut & resize else // Cut & resize {
{
if ($width > $maxWidth) if ($width > $maxWidth)
$dstWidth = $maxWidth; $dstWidth = $maxWidth;
if ($height > $maxWidth) if ($height > $maxWidth)
$dstHeight = $maxHeight; $dstHeight = $maxHeight;
if ($width <= $maxWidth) if ($width <= $maxWidth) {
{
if ($height > $srcHeight) if ($height > $srcHeight)
$srcHeight = $maxHeight; $srcHeight = $maxHeight;
} }
elseif ($height <= $maxHeight) elseif ($height <= $maxHeight) {
{
if ($width > $maxWidth) if ($width > $maxWidth)
$srcWidth = $maxWidth; $srcWidth = $maxWidth;
} }
else else {
{ $srcWidth =(int)($maxWidth *($height / $maxHeight));
$srcWidth = (int) ($maxWidth * ($height / $maxHeight)); $srcHeight =(int)($maxHeight *($width / $maxWidth));
$srcHeight = (int) ($maxHeight * ($width / $maxWidth));
if ($srcWidth <= $width) if ($srcWidth <= $width)
$srcHeight = $height; $srcHeight = $height;
@ -115,32 +103,30 @@ class Image
} }
if ($width !== $srcWidth) if ($width !== $srcWidth)
$srcX = (int) (($width / 2) - ($srcWidth / 2)); $srcX =(int)(($width / 2) -($srcWidth / 2));
if ($height !== $srcHeight) if ($height !== $srcHeight)
$srcY = (int) (($height / 2) - ($srcHeight / 2)); $srcY =(int)(($height / 2) -($srcHeight / 2));
} }
$resizedImage = imagecreatetruecolor ($dstWidth, $dstHeight); $resizedImage = imagecreatetruecolor($dstWidth, $dstHeight);
imagealphablending ($resizedImage, FALSE); imagealphablending($resizedImage, FALSE);
imagesavealpha ($resizedImage, TRUE); imagesavealpha($resizedImage, TRUE);
imagecopyresampled ($resizedImage, $image, imagecopyresampled($resizedImage, $image,
0, 0, $srcX, $srcY, $dstWidth, $dstHeight, $srcWidth, $srcHeight); 0, 0, $srcX, $srcY, $dstWidth, $dstHeight, $srcWidth, $srcHeight);
$saved = imagepng ($resizedImage, $dstFile); $saved = imagepng($resizedImage, $dstFile);
imagedestroy ($resizedImage); imagedestroy($resizedImage);
} }
elseif (isset ($symbolicSrc)) elseif (isset($symbolicSrc)) {
{ $saved = symlink($symbolicSrc, $dstFile);
$saved = symlink ($symbolicSrc, $dstFile);
} }
else else {
{ imagesavealpha($image, TRUE);
imagesavealpha ($image, TRUE); $saved = imagepng($image, $dstFile);
$saved = imagepng ($image, $dstFile);
} }
if (!$saved) if (!$saved)
throw new UserException (sprintf (s('File save error: %s'), $dstFile)); throw new UserException(sprintf(s('File save error: %s'), $dstFile));
} }
} }

View File

@ -1,6 +1,6 @@
<?php <?php
require_once (__DIR__.'/lib.php'); require_once(__DIR__.'/lib.php');
/** /**
* Resizes all images allocated in a directory. * Resizes all images allocated in a directory.
@ -11,8 +11,7 @@ require_once (__DIR__.'/lib.php');
* @param integer $maxWidth The maximum width of resized image in pixels * @param integer $maxWidth The maximum width of resized image in pixels
* @param boolean $rewrite Wether to rewrite the destination file if it exits * @param boolean $rewrite Wether to rewrite the destination file if it exits
*/ */
class Resize extends Vn\Lib\Method class Resize extends Vn\Lib\Method {
{
const PARAMS = [ const PARAMS = [
'srcDir' 'srcDir'
,'dstDir' ,'dstDir'
@ -23,41 +22,38 @@ class Resize extends Vn\Lib\Method
,'symbolic' ,'symbolic'
]; ];
function run () function run() {
{ $options = getopt('', $params);
$options = getopt ('', $params);
if (!$this->checkParams ($options, self::PARAMS)) if (!$this->checkParams($options, self::PARAMS))
$this->usage (); $this->usage();
$srcDir = $options['srcDir']; $srcDir = $options['srcDir'];
$dstDir = $options['dstDir']; $dstDir = $options['dstDir'];
$maxHeight = $options['maxHeight']; $maxHeight = $options['maxHeight'];
$maxWidth = $options['maxWidth']; $maxWidth = $options['maxWidth'];
$rewrite = isset ($options['rewrite']); $rewrite = isset($options['rewrite']);
$crop = isset ($options['crop']); $crop = isset($options['crop']);
$symbolic = isset ($options['symbolic']); $symbolic = isset($options['symbolic']);
set_time_limit (0); set_time_limit(0);
$count = 0; $count = 0;
$dir = opendir ($srcDir); $dir = opendir($srcDir);
if ($dir) if ($dir)
while ($fileName = readdir ($dir)) while ($fileName = readdir($dir))
if (!in_array ($fileName, ['.', '..'])) if (!in_array($fileName, ['.', '..'])) {
{
$srcFile = "$srcDir/$fileName"; $srcFile = "$srcDir/$fileName";
$dstFile = "$dstDir/". substr ($fileName, 0, -4).'.png'; $dstFile = "$dstDir/". substr($fileName, 0, -4).'.png';
if (!file_exists ($dstFile) || $rewrite) if (!file_exists($dstFile) || $rewrite)
try try {
{ $symbolicSrc =($symbolic) ? $srcFile : NULL;
$symbolicSrc = ($symbolic) ? $srcFile : NULL;
$image = Image::create ($srcFile); $image = Image::create($srcFile);
Image::resizeSave ($image, $dstFile, $maxHeight, $maxWidth, $crop, $symbolicSrc); Image::resizeSave($image, $dstFile, $maxHeight, $maxWidth, $crop, $symbolicSrc);
imagedestroy ($image); imagedestroy($image);
$count++; $count++;
} }
catch (\Exception $e) {} catch (\Exception $e) {}

View File

@ -1,64 +1,59 @@
<?php <?php
require_once (__DIR__.'/util.php'); require_once(__DIR__.'/util.php');
/** /**
* Syncronizes the data directory with the database, this may take * Syncronizes the data directory with the database, this may take
* some time. * some time.
*/ */
class Sync extends Vn\Lib\Method class Sync extends Vn\Lib\Method {
{
private $trashSubdir; private $trashSubdir;
private $util; private $util;
function __construct ($app) function __construct($app) {
{ parent::__construct($app);
parent::__construct ($app); $this->util = new Util($app);
$this->util = new Util ($app);
$this->dataDir = $this->util->dataDir; $this->dataDir = $this->util->dataDir;
} }
function run ($db) function run($db) {
{ $db = $this->getSysConn();
$db = $this->getSysConn ();
set_time_limit (0); set_time_limit(0);
$this->trashSubdir = date ('YmdHis'); $this->trashSubdir = date('YmdHis');
$checkCount = 0; $checkCount = 0;
$query = 'SELECT DISTINCT `%3$s` FROM `%1$s`.`%2$s` $query = 'SELECT DISTINCT `%3$s` FROM `%1$s`.`%2$s`
WHERE `%3$s` IS NOT NULL AND `%3$s` != \'\''; WHERE `%3$s` IS NOT NULL AND `%3$s` != \'\'';
$dir = opendir ($this->dataDir); $dir = opendir($this->dataDir);
if ($dir) if ($dir)
while ($schema = readdir ($dir)) while ($schema = readdir($dir))
if (!in_array ($schema, ['.', '..'])) if (!in_array($schema, ['.', '..'])) {
{ $info = $this->loadInfo($schema);
$info = $this->loadInfo ($schema);
$schemaPath = "{$this->dataDir}/$schema"; $schemaPath = "{$this->dataDir}/$schema";
// Deletes unreferenced schemas. // Deletes unreferenced schemas.
if (!isset ($info)) if (!isset($info)) {
{ $this->moveTrash($schema);
$this->moveTrash ($schema);
continue; continue;
} }
// Deletes unreferenced sizes. // Deletes unreferenced sizes.
$schemaDir = opendir ($schemaPath); $schemaDir = opendir($schemaPath);
if ($schemaDir) if ($schemaDir)
while ($size = readdir ($schemaDir)) while ($size = readdir($schemaDir))
if (!in_array ($size, ['.', '..', 'full']) if (!in_array($size, ['.', '..', 'full'])
&& !isset ($info['sizes'][$size])) && !isset($info['sizes'][$size]))
$this->moveTrash ("$schema/$size"); $this->moveTrash("$schema/$size");
// Gets a list of referenced images from the database. // Gets a list of referenced images from the database.
$result = $db->query (sprintf ($query $result = $db->query(sprintf($query
,$info['schema'] ,$info['schema']
,$info['table'] ,$info['table']
,$info['column'] ,$info['column']
@ -69,41 +64,38 @@ class Sync extends Vn\Lib\Method
$map = []; $map = [];
while ($row = $result->fetch_row ()) while ($row = $result->fetch_row()) {
{
$map[$row[0]] = TRUE; $map[$row[0]] = TRUE;
$checkCount++; $checkCount++;
} }
$result->free (); $result->free();
// Deletes unreferenced images. // Deletes unreferenced images.
$this->cleanImages ($schema, 'full', $map); $this->cleanImages($schema, 'full', $map);
foreach ($info['sizes'] as $size => $i) foreach($info['sizes'] as $size => $i)
$this->cleanImages ($schema, $size, $map); $this->cleanImages($schema, $size, $map);
} }
echo "Syncronization finished.\n"; echo "Syncronization finished.\n";
} }
function cleanImages ($schema, $size, &$map) function cleanImages($schema, $size, &$map) {
{
$sizePath = "{$this->dataDir}/$schema/$size"; $sizePath = "{$this->dataDir}/$schema/$size";
if (!is_dir ($sizePath)) if (!is_dir($sizePath))
return; return;
$iter = new DirectoryIterator ($sizePath); $iter = new DirectoryIterator($sizePath);
for (; $iter->valid (); $iter->next ()) for (; $iter->valid(); $iter->next())
if (!$iter->isDir () && strripos ($iter->getFilename (), '.png', -4) !== FALSE) if (!$iter->isDir() && strripos($iter->getFilename(), '.png', -4) !== FALSE) {
{ $name = substr($iter->getFilename(), 0, -4);
$name = substr ($iter->getFilename (), 0, -4);
if (!isset ($map[$name])) if (!isset($map[$name]))
$this->moveTrash ("$schema/$size/". $iter->getFilename ()); $this->moveTrash("$schema/$size/". $iter->getFilename());
} }
} }
@ -112,15 +104,14 @@ class Sync extends Vn\Lib\Method
* *
* @param string $file The file to move to the trash * @param string $file The file to move to the trash
*/ */
function moveTrash ($file) function moveTrash($file) {
{
$trashBasedir = "{$this->dataDir}/.trash/". $this->$trashSubdir; $trashBasedir = "{$this->dataDir}/.trash/". $this->$trashSubdir;
$trashdir = "$trashBasedir/". dirname ($file); $trashdir = "$trashBasedir/". dirname($file);
if (!is_dir ($trashdir)) if (!is_dir($trashdir))
mkdir ($trashdir, 0775, TRUE); mkdir($trashdir, 0775, TRUE);
rename ( rename(
"{$this->dataDir}/$file", "{$this->dataDir}/$file",
"$trashBasedir/$file" "$trashBasedir/$file"
); );

View File

@ -1,6 +1,6 @@
<?php <?php
require_once (__DIR__.'/util.php'); require_once(__DIR__.'/util.php');
/** /**
* Creates a thumb from an existing full image. * Creates a thumb from an existing full image.
@ -10,37 +10,35 @@ require_once (__DIR__.'/util.php');
* @param integer $width The width of the thumb * @param integer $width The width of the thumb
* @param integer $height The height of the thumb * @param integer $height The height of the thumb
*/ */
class Thumb extends Vn\Web\RestRequest class Thumb extends Vn\Web\RestRequest {
{ function run() {
function run ()
{
// XXX: Uncomment only to test the script // XXX: Uncomment only to test the script
//$_SERVER['REQUEST_URI'] = 'catalog/200x200/e_cinerea.png'; //$_SERVER['REQUEST_URI'] = 'catalog/200x200/e_cinerea.png';
$db = $this->getSysConn (); $db = $this->getSysConn();
// Gets parameters from URI. // Gets parameters from URI.
$uriSplit = explode ('/', $_SERVER['REQUEST_URI']); $uriSplit = explode('/', $_SERVER['REQUEST_URI']);
$uriSplit = array_slice ($uriSplit, count ($uriSplit) - 3, 3); $uriSplit = array_slice($uriSplit, count($uriSplit) - 3, 3);
if (count ($uriSplit) < 3) if (count($uriSplit) < 3)
throw new Exception ('Bad request'); throw new Exception('Bad request');
$schema = $uriSplit[0]; $schema = $uriSplit[0];
$orgFile = $uriSplit[2]; $orgFile = $uriSplit[2];
$file = $orgFile; $file = $orgFile;
if (strrpos ($file, '.') === FALSE) if (strrpos($file, '.') === FALSE)
$file .= '.png'; $file .= '.png';
$size = explode ('x', $uriSplit[1]); $size = explode('x', $uriSplit[1]);
if (count ($size) < 2) if (count($size) < 2)
throw new Exception ('Bad request'); throw new Exception('Bad request');
$width = (int) $size[0]; $width =(int) $size[0];
$height = (int) $size[1]; $height =(int) $size[1];
// Verifies that it is an allowed size. // Verifies that it is an allowed size.
@ -50,7 +48,7 @@ class Thumb extends Vn\Web\RestRequest
,'height' => $height ,'height' => $height
]; ];
$row = $db->getValue ( $row = $db->getValue(
'SELECT crop 'SELECT crop
FROM imageCollection s FROM imageCollection s
JOIN imageCollectionSize z ON z.collectionFk = s.id JOIN imageCollectionSize z ON z.collectionFk = s.id
@ -60,37 +58,36 @@ class Thumb extends Vn\Web\RestRequest
,$params ,$params
); );
if (!isset ($row)) if (!isset($row))
throw new Exception ('Size not allowed'); throw new Exception('Size not allowed');
// Creates the thumb. // Creates the thumb.
$util = new Util ($this->app); $util = new Util($this->app);
$baseDir = "{$util->dataDir}/$schema"; $baseDir = "{$util->dataDir}/$schema";
$srcFile = "$baseDir/full/$file"; $srcFile = "$baseDir/full/$file";
$dstFile = "$baseDir/{$width}x{$height}/$file"; $dstFile = "$baseDir/{$width}x{$height}/$file";
$symbolicSrc = "../full/$file"; $symbolicSrc = "../full/$file";
if (!file_exists ($srcFile)) if (!file_exists($srcFile))
throw new Exception ('Source not exists'); throw new Exception('Source not exists');
if (file_exists ($dstFile)) if (file_exists($dstFile))
throw new Exception ('Destination already exists'); throw new Exception('Destination already exists');
$image = Image::create ($srcFile); $image = Image::create($srcFile);
Image::resizeSave ($image, $dstFile, $height, $width, $row, $symbolicSrc); Image::resizeSave($image, $dstFile, $height, $width, $row, $symbolicSrc);
imagedestroy ($image); imagedestroy($image);
// Sends the thumb to the client // Sends the thumb to the client
$useXsendfile = $db->getValue ('SELECT useXsendfile FROM imageConfig'); $useXsendfile = $db->getValue('SELECT useXsendfile FROM imageConfig');
if ($useXsendfile) if ($useXsendfile) {
{ header("X-Sendfile: $dstFile");
header ("X-Sendfile: $dstFile"); header("Content-Type: image/png");
header ("Content-Type: image/png");
} }
else else
header ("Location: {$_SERVER['REQUEST_URI']}"); header("Location: {$_SERVER['REQUEST_URI']}");
} }
} }

View File

@ -1,6 +1,6 @@
<?php <?php
require_once (__DIR__.'/util.php'); require_once(__DIR__.'/util.php');
use Vn\Lib; use Vn\Lib;
use Vn\Lib\UserException; use Vn\Lib\UserException;
@ -8,41 +8,37 @@ use Vn\Lib\UserException;
/** /**
* Uploads a file creating its corresponding sizes. * Uploads a file creating its corresponding sizes.
*/ */
class Upload extends Vn\Web\JsonRequest class Upload extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'name', 'name',
'schema' 'schema'
]; ];
function run ($db) function run($db) {
{ $util = new Util($this->app);
$util = new Util ($this->app);
$schema = $_REQUEST['schema']; $schema = $_REQUEST['schema'];
$name = $_REQUEST['name']; $name = $_REQUEST['name'];
// Checks schema // Checks schema
$info = $util->loadInfo ($schema); $info = $util->loadInfo($schema);
if (!$info) if (!$info)
throw new UserException (s('Schema not exists')); throw new UserException(s('Schema not exists'));
// Checks file name // Checks file name
if (preg_match ('/[^a-z0-9_]/', $_REQUEST['name']) !== 0) if (preg_match('/[^a-z0-9_]/', $_REQUEST['name']) !== 0)
throw new UserException (s('Bad file name')); throw new UserException(s('Bad file name'));
// Checks for file errors // Checks for file errors
if (empty ($_FILES['image']['name'])) if (empty($_FILES['image']['name']))
throw new UserException (s('File not choosed')); throw new UserException(s('File not choosed'));
if ($_FILES['image']['error'] != 0) if ($_FILES['image']['error'] != 0) {
{ switch ($_FILES['image']['error']) {
switch ($_FILES['image']['error'])
{
case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_INI_SIZE:
$message = 'ErrIniSize'; $message = 'ErrIniSize';
break; break;
@ -69,13 +65,13 @@ class Upload extends Vn\Web\JsonRequest
break; break;
} }
throw new Lib\Exception (s($message)); throw new Lib\Exception(s($message));
} }
$maxSize = $db->getValue ('SELECT maxSize FROM imageConfig'); $maxSize = $db->getValue('SELECT maxSize FROM imageConfig');
if ($_FILES['image']['size'] > $maxSize * 1048576) if ($_FILES['image']['size'] > $maxSize * 1048576)
throw new UserException (sprintf (s('File size error'), $maxSize)); throw new UserException(sprintf(s('File size error'), $maxSize));
// Resizes and saves the image // Resizes and saves the image
@ -85,17 +81,16 @@ class Upload extends Vn\Web\JsonRequest
$fullFile = "$schemaPath/full/$fileName"; $fullFile = "$schemaPath/full/$fileName";
$symbolicSrc = "../full/$fileName"; $symbolicSrc = "../full/$fileName";
$image = Image::create ($tmpName); $image = Image::create($tmpName);
Image::resizeSave ($image, $fullFile, $info['maxHeight'], $info['maxWidth']); Image::resizeSave($image, $fullFile, $info['maxHeight'], $info['maxWidth']);
foreach ($info['sizes'] as $size => $i) foreach($info['sizes'] as $size => $i) {
{
$dstFile = "$schemaPath/$size/$fileName"; $dstFile = "$schemaPath/$size/$fileName";
Image::resizeSave ($image, $dstFile, $i['height'], $i['width'], $i['crop'], $symbolicSrc); Image::resizeSave($image, $dstFile, $i['height'], $i['width'], $i['crop'], $symbolicSrc);
} }
imagedestroy ($image); imagedestroy($image);
unlink ($tmpName); unlink($tmpName);
return TRUE; return TRUE;
} }
} }

View File

@ -1,19 +1,17 @@
<?php <?php
require_once (__DIR__.'/image.php'); require_once(__DIR__.'/image.php');
/** /**
* Base class for image methods. * Base class for image methods.
*/ */
class Util class Util {
{
var $app; var $app;
var $dataDir; var $dataDir;
function __construct ($app) function __construct($app) {
{
$this->app = $app; $this->app = $app;
$this->dataDir = _DATA_DIR .'/'. $app->getName () .'/image-db'; $this->dataDir = _DATA_DIR .'/'. $app->getName() .'/image-db';
} }
/** /**
@ -21,11 +19,10 @@ class Util
* *
* @param string $schema The schema name * @param string $schema The schema name
*/ */
function loadInfo ($schema) function loadInfo($schema) {
{ $db = $this->app->getSysConn();
$db = $this->app->getSysConn ();
$info = $db->getRow ( $info = $db->getRow(
'SELECT id, maxWidth, maxHeight, `schema`, `table`, `column` 'SELECT id, maxWidth, maxHeight, `schema`, `table`, `column`
FROM imageCollection WHERE name = #schema' FROM imageCollection WHERE name = #schema'
,['schema' => $schema] ,['schema' => $schema]
@ -34,7 +31,7 @@ class Util
if (!$info) if (!$info)
return NULL; return NULL;
$res = $db->query ( $res = $db->query(
'SELECT width, height, crop 'SELECT width, height, crop
FROM imageCollectionSize WHERE collectionFk = #id' FROM imageCollectionSize WHERE collectionFk = #id'
,['id' => $info['id']] ,['id' => $info['id']]
@ -42,8 +39,7 @@ class Util
$info['sizes'] = []; $info['sizes'] = [];
while ($r = $res->fetch_assoc ()) while ($r = $res->fetch_assoc()) {
{
$size = "{$r['width']}x{$r['height']}"; $size = "{$r['width']}x{$r['height']}";
$info['sizes'][$size] = [ $info['sizes'][$size] = [
'width' => $r['width'], 'width' => $r['width'],

View File

@ -6,26 +6,22 @@ use Vn\Lib\UserException;
/** /**
* Uploads a access module. * Uploads a access module.
*/ */
class AccessVersion extends Vn\Web\JsonRequest class AccessVersion extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'appName' 'appName'
,'newVersion' ,'newVersion'
]; ];
function run ($db) function run($db) {
{
// Checks for file errors. // Checks for file errors.
$moduleFile = $_FILES['moduleFile']; $moduleFile = $_FILES['moduleFile'];
if (empty ($moduleFile['name'])) if (empty($moduleFile['name']))
throw new UserException (s('File not choosed')); throw new UserException(s('File not choosed'));
if ($moduleFile['error'] != 0) if ($moduleFile['error'] != 0) {
{ switch ($_FILES['image']['error']) {
switch ($_FILES['image']['error'])
{
case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_INI_SIZE:
$message = 'ErrIniSize'; $message = 'ErrIniSize';
break; break;
@ -52,7 +48,7 @@ class AccessVersion extends Vn\Web\JsonRequest
break; break;
} }
throw new Lib\Exception (s($message)); throw new Lib\Exception(s($message));
} }
// Defining parameters // Defining parameters
@ -67,8 +63,8 @@ class AccessVersion extends Vn\Web\JsonRequest
// Updates the application // Updates the application
copy ($moduleFile['tmp_name'], $archiveFile); copy($moduleFile['tmp_name'], $archiveFile);
rename ($moduleFile['tmp_name'], $uploadFile); rename($moduleFile['tmp_name'], $uploadFile);
return TRUE; return TRUE;
} }

View File

@ -1,11 +1,10 @@
<?php <?php
require_once ('libphp-phpmailer/PHPMailerAutoload.php'); require_once('libphp-phpmailer/PHPMailerAutoload.php');
use Vn\Lib; use Vn\Lib;
class Contact extends Vn\Web\JsonRequest class Contact extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'name' 'name'
,'pc' ,'pc'
@ -15,54 +14,51 @@ class Contact extends Vn\Web\JsonRequest
,'captcha' ,'captcha'
]; ];
function run ($db) function run($db) {
{
// Checks the antispam code // Checks the antispam code
$lastCaptcha = $_SESSION['captcha']; $lastCaptcha = $_SESSION['captcha'];
unset ($_SESSION['captcha']); unset($_SESSION['captcha']);
if ($_REQUEST['captcha'] !== $lastCaptcha) if ($_REQUEST['captcha'] !== $lastCaptcha)
throw new Lib\UserException (s('Wrong captcha'), 'wrongCaptcha'); throw new Lib\UserException (s('Wrong captcha'), 'wrongCaptcha');
// Sends the mail // Sends the mail
// TODO: Change form fields // TODO: Change form fields
//$db->queryFromFile (__DIR__.'/contact', $_REQUEST); //$db->queryFromFile(__DIR__.'/contact', $_REQUEST);
//$customerId = $db->getValue ('SELECT @id'); //$customerId = $db->getValue('SELECT @id');
$conf = $db->getObject ( $conf = $db->getObject(
'SELECT m.host, m.port, m.secure, m.sender, m.user, m.password, c.recipient 'SELECT m.host, m.port, m.secure, m.sender, m.user, m.password, c.recipient
FROM mailConfig m JOIN contact c' FROM mailConfig m JOIN contact c'
); );
$mail = new PHPMailer (); $mail = new PHPMailer();
$mail->isSMTP (); $mail->isSMTP();
$mail->Host = $conf->host; $mail->Host = $conf->host;
if (!empty ($conf->user)) if (!empty($conf->user)) {
{
$mail->SMTPAuth = TRUE; $mail->SMTPAuth = TRUE;
$mail->Username = $conf->user; $mail->Username = $conf->user;
$mail->Password = base64_decode ($conf->password); $mail->Password = base64_decode($conf->password);
} }
else else
$mail->SMTPAuth = FALSE; $mail->SMTPAuth = FALSE;
if ($conf->secure) if ($conf->secure) {
{
$mail->SMTPSecure = 'ssl'; $mail->SMTPSecure = 'ssl';
$mail->Port = 465; $mail->Port = 465;
} }
$mail->setFrom ($conf->sender, 'Web'); $mail->setFrom($conf->sender, 'Web');
$mail->addAddress ($conf->recipient); $mail->addAddress($conf->recipient);
$mail->isHTML (TRUE); $mail->isHTML(TRUE);
$mail->Subject = s('New customer request'); $mail->Subject = s('New customer request');
$mail->Body = '<pre>'. print_r ($_REQUEST, TRUE) .'</pre>'; $mail->Body = '<pre>'. print_r($_REQUEST, TRUE) .'</pre>';
if (!$mail->send ()) if (!$mail->send())
throw new Exception ($mail->ErrorInfo); throw new Exception ($mail->ErrorInfo);
return TRUE; return TRUE;
} }

View File

@ -4,42 +4,38 @@
* Ejemplo: * Ejemplo:
* <Cube><Cube time="2010-12-10"><Cube currency="USD" rate="1.3244"/> * <Cube><Cube time="2010-12-10"><Cube currency="USD" rate="1.3244"/>
*/ */
class ExchangeRate extends Vn\Lib\Method class ExchangeRate extends Vn\Lib\Method {
{ function run($db) {
function run ($db) $db->selectDb('vn2008');
{
$db->selectDb ('vn2008');
// Indica la URL del archivo // Indica la URL del archivo
$xml = new SimpleXMLElement ( $xml = new SimpleXMLElement(
'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml', 0, TRUE); 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml', 0, TRUE);
$date = $db->getValue ("SELECT MAX(date) fecha FROM reference_rate"); $date = $db->getValue("SELECT MAX(date) fecha FROM reference_rate");
$maxDate = $date ? DateTime::createFromFormat ('Y-m-d', $date) : NULL; $maxDate = $date ? DateTime::createFromFormat('Y-m-d', $date) : NULL;
foreach ($xml->Cube[0]->Cube as $cube) foreach($xml->Cube[0]->Cube as $cube) {
{ $xmlDate = new DateTime($cube['time']);
$xmlDate = new DateTime ($cube['time']);
// Si existen datos más recientes de la máxima fecha los añade // Si existen datos más recientes de la máxima fecha los añade
if ($maxDate <= $xmlDate) if ($maxDate <= $xmlDate)
foreach ($cube->Cube as $subCube) foreach($cube->Cube as $subCube)
if ($subCube['currency'] == 'USD') if ($subCube['currency'] == 'USD') {
{
$params = [ $params = [
'date' => $xmlDate, 'date' => $xmlDate,
'rate' => $subCube['rate'] 'rate' => $subCube['rate']
]; ];
$db->query ( $db->query(
'REPLACE INTO reference_rate (moneda_id, date, rate) 'REPLACE INTO reference_rate(moneda_id, date, rate)
VALUES (2, #date, #rate)', VALUES(2, #date, #rate)',
$params $params
); );
} }
} }
$db->queryFromFile (__DIR__.'/exrate-add'); $db->queryFromFile(__DIR__.'/exrate-add');
} }
} }

View File

@ -1,56 +1,51 @@
<?php <?php
require_once ('libphp-phpmailer/PHPMailerAutoload.php'); require_once('libphp-phpmailer/PHPMailerAutoload.php');
class Mail extends Vn\Lib\Method class Mail extends Vn\Lib\Method {
{ function run($db) {
function run ($db) $db->selectDb('vn2008');
{ $db->query('START TRANSACTION');
$db->selectDb ('vn2008');
$db->query ('START TRANSACTION');
$mailer = new Vn\Web\Mailer ($db); $mailer = new Vn\Web\Mailer($db);
$res = $db->query ( $res = $db->query(
'SELECT * FROM mail WHERE sent = 0 ORDER BY DATE_ODBC DESC 'SELECT * FROM mail WHERE sent = 0 ORDER BY DATE_ODBC DESC
LIMIT 20 FOR UPDATE'); LIMIT 20 FOR UPDATE');
$count = 0; $count = 0;
while ($row = $res->fetch_object ()) while ($row = $res->fetch_object()) {
{
$sent = 1; $sent = 1;
$status = 'OK'; $status = 'OK';
try { try {
$mail = $mailer->createObject ($row->to, $row->text, $row->subject); $mail = $mailer->createObject($row->to, $row->text, $row->subject);
$mail->AddReplyTo ($row->reply_to, $row->reply_to); $mail->AddReplyTo($row->reply_to, $row->reply_to);
if (!empty ($row->path)) if (!empty($row->path)) {
{
$attachment = '/mnt/cluster/pdfs/'. $row->path; $attachment = '/mnt/cluster/pdfs/'. $row->path;
if (file_exists ($attachment)) if (file_exists($attachment))
$mail->AddAttachment ($attachment, ''); $mail->AddAttachment($attachment, '');
else else
throw new Exception ("Attachment file could not be found: $attachment"); throw new Exception("Attachment file could not be found: $attachment");
} }
if (!$mail->Send ()) if (!$mail->Send())
throw new Exception ('Send error: '.$mail->ErrorInfo); throw new Exception('Send error: '.$mail->ErrorInfo);
$count++; $count++;
} }
catch (Exception $e) catch (Exception $e) {
{
$sent = 2; $sent = 2;
$status = $e->getMessage (); $status = $e->getMessage();
} }
$db->query ('UPDATE mail SET sent = #, error = # WHERE id = #', $db->query('UPDATE mail SET sent = #, error = # WHERE id = #',
[$sent, $status, $row->id]); [$sent, $status, $row->id]);
} }
$db->query ('COMMIT'); $db->query('COMMIT');
echo "Total $count mails sent\n"; echo "Total $count mails sent\n";
} }
} }

View File

@ -1,19 +1,17 @@
<?php <?php
class Production extends Vn\Web\JsonRequest class Production extends Vn\Web\JsonRequest {
{
const PARAMS = ['deviceId']; const PARAMS = ['deviceId'];
function run ($db) function run($db) {
{ $row = $db->getObject(
$row = $db->getObject (
'SELECT displayText, status 'SELECT displayText, status
FROM vn.routeGate WHERE deviceId = #', FROM vn.routeGate WHERE deviceId = #',
[$_REQUEST['deviceId']] [$_REQUEST['deviceId']]
); );
if (!isset($row)) if (!isset($row))
throw new Vn\Lib\UserException ('Device not found'); throw new Vn\Lib\UserException('Device not found');
return $row; return $row;
} }

View File

@ -2,8 +2,7 @@
use Vn\Lib; use Vn\Lib;
class Sms extends Vn\Web\JsonRequest class Sms extends Vn\Web\JsonRequest {
{
const PARAMS = [ const PARAMS = [
'destination' 'destination'
,'message' ,'message'
@ -14,22 +13,21 @@ class Sms extends Vn\Web\JsonRequest
200 // Processing 200 // Processing
]; ];
function run ($db) function run($db) {
{ $smsConfig = $db->getObject('SELECT uri, user, password, title FROM vn.smsConfig');
$smsConfig = $db->getObject ('SELECT uri, user, password, title FROM vn.smsConfig');
$sClient = new SoapClient ($smsConfig->uri); $sClient = new SoapClient($smsConfig->uri);
$xmlString = $sClient->sendSMS ( $xmlString = $sClient->sendSMS(
$smsConfig->user $smsConfig->user
,$smsConfig->password ,$smsConfig->password
,$smsConfig->title ,$smsConfig->title
,$_REQUEST['destination'] ,$_REQUEST['destination']
,$_REQUEST['message'] ,$_REQUEST['message']
); );
$xmlResponse = new SimpleXMLElement ($xmlString); $xmlResponse = new SimpleXMLElement($xmlString);
$res = $xmlResponse->sms; $res = $xmlResponse->sms;
$db->query ( $db->query(
'INSERT INTO vn.sms SET 'INSERT INTO vn.sms SET
`senderFk` = account.myUserGetId(), `senderFk` = account.myUserGetId(),
`destinationFk` = #, `destinationFk` = #,
@ -38,7 +36,7 @@ class Sms extends Vn\Web\JsonRequest
`statusCode` = #, `statusCode` = #,
`status` = #', `status` = #',
[ [
empty ($_REQUEST['destinationId']) ? NULL : $_REQUEST['destinationId'] empty($_REQUEST['destinationId']) ? NULL : $_REQUEST['destinationId']
,$_REQUEST['destination'] ,$_REQUEST['destination']
,$_REQUEST['message'] ,$_REQUEST['message']
,$res->codigo ,$res->codigo
@ -46,8 +44,8 @@ class Sms extends Vn\Web\JsonRequest
] ]
); );
if (!in_array ((int) $res->codigo, self::OK_STATES)) if (!in_array((int) $res->codigo, self::OK_STATES))
throw new Lib\UserException ($res->descripcion); throw new Lib\UserException($res->descripcion);
return TRUE; return TRUE;
} }

View File

@ -1,18 +1,15 @@
<?php <?php
class VisitsSync extends Vn\Lib\Method class VisitsSync extends Vn\Lib\Method {
{ function run($db) {
function run ($db) $result = $db->query("SELECT id, agent FROM visit_agent
{
$result = $db->query ("SELECT id, agent FROM visit_agent
WHERE version = '0.0' OR platform = 'unknown' OR cookies IS NULL ORDER BY id DESC"); WHERE version = '0.0' OR platform = 'unknown' OR cookies IS NULL ORDER BY id DESC");
$stmt = $db->prepare ('UPDATE visit_agent $stmt = $db->prepare('UPDATE visit_agent
SET platform = ?, browser = ?, version = ?, javascript = ?, cookies = ? WHERE id = ?'); SET platform = ?, browser = ?, version = ?, javascript = ?, cookies = ? WHERE id = ?');
if ($result && $stmt) if ($result && $stmt) {
{ set_time_limit(0);
set_time_limit (0);
$stmt->bind_param('sssiii' $stmt->bind_param('sssiii'
,$platform ,$platform
@ -27,16 +24,15 @@ class VisitsSync extends Vn\Lib\Method
$count = 0; $count = 0;
while ($row = $result->fetch_assoc ()) while ($row = $result->fetch_assoc()) {
{ $info = get_browser($row['agent']);
$info = get_browser ($row['agent']);
$platform = $info->platform; $platform = $info->platform;
$browser = $info->browser; $browser = $info->browser;
$version = $info->version; $version = $info->version;
$javascript = $info->javascript; $javascript = $info->javascript;
$cookies = $info->cookies; $cookies = $info->cookies;
$id = $row['id']; $id = $row['id'];
$stmt->execute (); $stmt->execute();
$count++; $count++;
} }
@ -45,8 +41,8 @@ class VisitsSync extends Vn\Lib\Method
} }
if ($stmt) if ($stmt)
$stmt->close (); $stmt->close();
if ($result) if ($result)
$result->free (); $result->free();
} }
} }

View File

@ -1,49 +1,45 @@
<?php <?php
require_once (__DIR__.'/tpv.php'); require_once(__DIR__.'/tpv.php');
/** /**
* Gets transaction confirmations from the IMAP mailbox. * Gets transaction confirmations from the IMAP mailbox.
**/ **/
class ConfirmMail extends Vn\Lib\Method class ConfirmMail extends Vn\Lib\Method {
{ function run($db) {
function run ($db)
{
$imap = NULL; $imap = NULL;
$imapConf = $db->getObject ( $imapConf = $db->getObject(
'SELECT host, user, pass, cleanPeriod, successFolder, errorFolder 'SELECT host, user, pass, cleanPeriod, successFolder, errorFolder
FROM tpvImapConfig' FROM tpvImapConfig'
); );
$mailbox = sprintf ('{%s/imap/ssl/novalidate-cert}', $mailbox = sprintf('{%s/imap/ssl/novalidate-cert}',
$imapConf->host); $imapConf->host);
$imap = imap_open ($mailbox $imap = imap_open($mailbox
,$imapConf->user ,$imapConf->user
,base64_decode ($imapConf->pass) ,base64_decode($imapConf->pass)
); );
if (!$imap) if (!$imap)
throw new Exception (imap_last_error ()); throw new Exception(imap_last_error());
// Fetchs and confirms new transaction mails // Fetchs and confirms new transaction mails
$count = 0; $count = 0;
$inbox = imap_search ($imap, 'ALL'); $inbox = imap_search($imap, 'ALL');
if ($inbox) if ($inbox)
foreach ($inbox as $msg) foreach($inbox as $msg) {
{
// Decodes the mail body // Decodes the mail body
$params = []; $params = [];
$body = imap_fetchbody ($imap, $msg, '1'); $body = imap_fetchbody($imap, $msg, '1');
$strings = explode (';', $body); $strings = explode(';', $body);
foreach ($strings as $string) foreach($strings as $string) {
{ $x = explode(':', $string);
$x = explode (':', $string); $params[trim($x[0])] = trim($x[1]);
$params[trim ($x[0])] = trim ($x[1]);
} }
// Confirms the transaction // Confirms the transaction
@ -51,11 +47,10 @@ class ConfirmMail extends Vn\Lib\Method
$success = FALSE; $success = FALSE;
try { try {
$success = Tpv::confirm ($db, $params); $success = Tpv::confirm($db, $params);
} }
catch (\Exception $e) catch (\Exception $e) {
{ trigger_error($e->getMessage(), E_USER_WARNING);
trigger_error ($e->getMessage (), E_USER_WARNING);
} }
// Moves the processed mail to another folder // Moves the processed mail to another folder
@ -65,38 +60,36 @@ class ConfirmMail extends Vn\Lib\Method
else else
$folder = $imapConf->errorFolder; $folder = $imapConf->errorFolder;
if (!imap_mail_move ($imap, $msg, "$folder")) if (!imap_mail_move($imap, $msg, "$folder"))
trigger_error (imap_last_error (), E_USER_WARNING); trigger_error(imap_last_error(), E_USER_WARNING);
$count++; $count++;
} }
imap_expunge ($imap); imap_expunge($imap);
// Cleans the old mails // Cleans the old mails
$deleted = 0; $deleted = 0;
if (rand (1, 20) == 1) if (rand(1, 20) == 1) {
{ $folders = array(
$folders = array (
$imapConf->successFolder $imapConf->successFolder
,$imapConf->errorFolder ,$imapConf->errorFolder
); );
$date = new \DateTime (NULL); $date = new \DateTime(NULL);
$date->sub (new \DateInterval ($imapConf->cleanPeriod)); $date->sub(new \DateInterval($imapConf->cleanPeriod));
$filter = sprintf ('BEFORE "%s"', $date->format('D, j M Y')); $filter = sprintf('BEFORE "%s"', $date->format('D, j M Y'));
foreach ($folders as $folder) foreach($folders as $folder)
if (imap_reopen ($imap, $mailbox.'.'.$folder)) if (imap_reopen($imap, $mailbox.'.'.$folder))
if ($messages = imap_search ($imap, $filter)) if ($messages = imap_search($imap, $filter)) {
{ foreach($messages as $message)
foreach ($messages as $message) imap_delete($imap, $message);
imap_delete ($imap, $message);
imap_expunge ($imap); imap_expunge($imap);
$deleted += count ($messages); $deleted += count($messages);
} }
} }

View File

@ -1,15 +1,13 @@
<?php <?php
require_once (__DIR__.'/tpv.php'); require_once(__DIR__.'/tpv.php');
/** /**
* Gets transaction confirmation from HTTP POST. * Gets transaction confirmation from HTTP POST.
**/ **/
class ConfirmPost extends Vn\Web\RestRequest class ConfirmPost extends Vn\Web\RestRequest {
{ function run($db) {
function run ($db) Tpv::confirm($db, $_POST);
{
Tpv::confirm ($db, $_POST);
} }
} }

View File

@ -1,31 +1,28 @@
<?php <?php
require_once ('vn/web/util.php'); require_once('vn/web/util.php');
require_once (__DIR__.'/tpv.php'); require_once(__DIR__.'/tpv.php');
/** /**
* Gets transaction confirmation from SOAP service. * Gets transaction confirmation from SOAP service.
**/ **/
class ConfirmSoap extends Vn\Web\RestRequest class ConfirmSoap extends Vn\Web\RestRequest {
{ function run($db) {
function run ($db)
{
global $tpvConfirmSoap; global $tpvConfirmSoap;
$tpvConfirmSoap = $this; $tpvConfirmSoap = $this;
ini_set ('soap.wsdl_cache_enabled', FALSE); ini_set('soap.wsdl_cache_enabled', FALSE);
$server = new SoapServer (__DIR__ .'/soap.wsdl'); $server = new SoapServer(__DIR__ .'/soap.wsdl');
$server->addFunction ('procesaNotificacionSIS'); $server->addFunction('procesaNotificacionSIS');
$server->handle (); $server->handle();
} }
} }
function procesaNotificacionSIS ($XML) function procesaNotificacionSIS($XML) {
{
global $tpvConfirmSoap; global $tpvConfirmSoap;
$db = $tpvConfirmSoap->app->getSysConn (); $db = $tpvConfirmSoap->app->getSysConn();
$status = 'OK'; $status = 'OK';
$requestString = $XML; $requestString = $XML;
@ -33,50 +30,49 @@ function procesaNotificacionSIS ($XML)
// Processes the request // Processes the request
try { try {
$xml = new SimpleXMLElement ($requestString); $xml = new SimpleXMLElement($requestString);
$params = (array) $xml->{'Request'}; $params =(array) $xml->{'Request'};
if (!(isset ($params['Ds_Amount']) if (!(isset($params['Ds_Amount'])
&& isset ($params['Ds_Order']) && isset($params['Ds_Order'])
&& isset ($params['Ds_MerchantCode']) && isset($params['Ds_MerchantCode'])
&& isset ($params['Ds_Currency']) && isset($params['Ds_Currency'])
&& isset ($params['Ds_Response']))) && isset($params['Ds_Response'])))
throw new Exception ('Missing required parameters'); throw new Exception('Missing required parameters');
// Checks the signature // Checks the signature
$start = strpos ($requestString, '<Request'); $start = strpos($requestString, '<Request');
$end = strrpos ($requestString, '</Request>'); $end = strrpos($requestString, '</Request>');
$shaString = substr ($requestString, $start, $end - $start + 10); $shaString = substr($requestString, $start, $end - $start + 10);
$key = $db->getValue ( $key = $db->getValue(
'SELECT secretKey FROM tpvMerchant WHERE id = #' 'SELECT secretKey FROM tpvMerchant WHERE id = #'
,[$params['Ds_MerchantCode']] ,[$params['Ds_MerchantCode']]
); );
if (sha1 ($shaString.$key) != $xml->{'Signature'}) if (sha1($shaString.$key) != $xml->{'Signature'})
throw new Exception ('Invalid signature'); throw new Exception('Invalid signature');
// Confirms the transaction // Confirms the transaction
Tpv::confirm ($db, $params); Tpv::confirm($db, $params);
} }
catch (Exception $e) catch (Exception $e) {
{
$status = 'KO'; $status = 'KO';
} }
// Generates the response // Generates the response
$responseString = file_get_contents (__DIR__ .'/soap-reply.xml'); $responseString = file_get_contents(__DIR__ .'/soap-reply.xml');
$xml = new SimpleXMLElement ($responseString); $xml = new SimpleXMLElement($responseString);
$response = $xml->{'Response'}; $response = $xml->{'Response'};
$response->{'Ds_Response_Merchant'} = $status; $response->{'Ds_Response_Merchant'} = $status;
$xml->{'Signature'} = sha1 ($response->asXML ().$key); $xml->{'Signature'} = sha1($response->asXML().$key);
return $xml->asXML (); return $xml->asXML();
/* /*
// Another way to generate the response // Another way to generate the response
@ -88,7 +84,7 @@ function procesaNotificacionSIS ($XML)
$xmlMessage = $xmlMessage =
'<Message> '<Message>
'. $xmlResponse .' '. $xmlResponse .'
<Signature>'. sha1 ($xmlResponse.$key) .'</Signature> <Signature>'. sha1($xmlResponse.$key) .'</Signature>
</Message>'; </Message>';
return $xmlMessage; return $xmlMessage;

View File

@ -1,29 +1,27 @@
<?php <?php
if (isset ($_POST['key'])) if (isset($_POST['key'])) {
{ ini_set('soap.wsdl_cache_enabled', FALSE);
ini_set ('soap.wsdl_cache_enabled', FALSE);
$requestString = file_get_contents (__DIR__.'/soap-request.xml'); $requestString = file_get_contents(__DIR__.'/soap-request.xml');
$client = new SoapClient (__DIR__.'/soap.wsdl'); $client = new SoapClient(__DIR__.'/soap.wsdl');
$result = $client->__soapCall ('procesaNotificacionSIS', [ $result = $client->__soapCall('procesaNotificacionSIS', [
'XML' => $requestString 'XML' => $requestString
]); ]);
$xml = new SimpleXMLElement ($result); $xml = new SimpleXMLElement($result);
$key = $_POST['key']; $key = $_POST['key'];
$start = strpos ($result, '<Response'); $start = strpos($result, '<Response');
$end = strrpos ($result, '</Response>'); $end = strrpos($result, '</Response>');
$shaString = substr ($result, $start, $end - $start + 11); $shaString = substr($result, $start, $end - $start + 11);
$shaHash = sha1 ($shaString.$key); $shaHash = sha1($shaString.$key);
$isValid = $xml->{'Signature'} == $shaHash; $isValid = $xml->{'Signature'} == $shaHash;
} }
else else {
{
$key = ''; $key = '';
$result = ''; $result = '';
$shaHash = ''; $shaHash = '';
@ -46,7 +44,7 @@ else
</form> </form>
<h2>Response</h2> <h2>Response</h2>
<p> <p>
<pre><?=htmlentities ($result)?></pre> <pre><?=htmlentities($result)?></pre>
</p> </p>
<h2>Signature</h2> <h2>Signature</h2>
<p> <p>

View File

@ -1,26 +1,24 @@
<?php <?php
class Tpv class Tpv {
{
/** /**
* Tryes to confirm a transaction with the given params. * Tryes to confirm a transaction with the given params.
**/ **/
static function confirm ($db, $params) static function confirm($db, $params) {
{ if (!(isset($params['Ds_Amount'])
if (!(isset ($params['Ds_Amount']) && isset($params['Ds_Order'])
&& isset ($params['Ds_Order']) && isset($params['Ds_MerchantCode'])
&& isset ($params['Ds_MerchantCode']) && isset($params['Ds_Currency'])
&& isset ($params['Ds_Currency']) && isset($params['Ds_Response'])))
&& isset ($params['Ds_Response'])))
return FALSE; return FALSE;
if (isset ($params['Ds_ErrorCode'])) if (isset($params['Ds_ErrorCode']))
$error = $params['Ds_ErrorCode']; $error = $params['Ds_ErrorCode'];
else else
$error = NULL; $error = NULL;
return $db->query ( return $db->query(
'CALL tpvTransactionConfirm (#, #, #, #, #, #)', 'CALL tpvTransactionConfirm(#, #, #, #, #, #)',
[ [
$params['Ds_Amount'] $params['Ds_Amount']
,$params['Ds_Order'] ,$params['Ds_Order']

View File

@ -3,24 +3,22 @@
/** /**
* Starts a new TPV transaction and returns the params. * Starts a new TPV transaction and returns the params.
*/ */
class Transaction extends Vn\Web\JsonRequest class Transaction extends Vn\Web\JsonRequest {
{
const PARAMS = ['amount']; const PARAMS = ['amount'];
function run ($db) function run($db) {
{ $amount =(int) $_REQUEST['amount'];
$amount = (int) $_REQUEST['amount']; $companyId = empty($_REQUEST['company']) ? NULL : $_REQUEST['company'];
$companyId = empty ($_REQUEST['company']) ? NULL : $_REQUEST['company'];
$row = $db->getObject ('CALL tpvTransactionStart (#, #)', $row = $db->getObject('CALL tpvTransactionStart(#, #)',
[$amount, $companyId]); [$amount, $companyId]);
if (!isset ($row)) if (!isset($row))
throw new Exception ('Transaction error'); throw new Exception('Transaction error');
$transactionId = str_pad ($row->transactionId, 12, '0', STR_PAD_LEFT); $transactionId = str_pad($row->transactionId, 12, '0', STR_PAD_LEFT);
$urlOk = empty ($_REQUEST['urlOk']) ? '' : sprintf ($_REQUEST['urlOk'], $transactionId); $urlOk = empty($_REQUEST['urlOk']) ? '' : sprintf($_REQUEST['urlOk'], $transactionId);
$urlKo = empty ($_REQUEST['urlKo']) ? '' : sprintf ($_REQUEST['urlKo'], $transactionId); $urlKo = empty($_REQUEST['urlKo']) ? '' : sprintf($_REQUEST['urlKo'], $transactionId);
$merchantUrl = $row->merchantUrl ? $row->merchantUrl : ''; $merchantUrl = $row->merchantUrl ? $row->merchantUrl : '';
$params = [ $params = [
@ -35,15 +33,15 @@ class Transaction extends Vn\Web\JsonRequest
,'Ds_Merchant_UrlKO' => $urlKo ,'Ds_Merchant_UrlKO' => $urlKo
]; ];
$encodedParams = base64_encode (json_encode ($params)); $encodedParams = base64_encode(json_encode($params));
$key = base64_decode ($row->secretKey); $key = base64_decode($row->secretKey);
$bytes = [0, 0, 0, 0, 0, 0, 0, 0]; $bytes = [0, 0, 0, 0, 0, 0, 0, 0];
$iv = implode (array_map ('chr', $bytes)); $iv = implode(array_map('chr', $bytes));
$key = mcrypt_encrypt (MCRYPT_3DES, $key, $transactionId, MCRYPT_MODE_CBC, $iv); $key = mcrypt_encrypt(MCRYPT_3DES, $key, $transactionId, MCRYPT_MODE_CBC, $iv);
$signature = base64_encode (hash_hmac ('sha256', $encodedParams, $key, TRUE)); $signature = base64_encode(hash_hmac('sha256', $encodedParams, $key, TRUE));
$url = $row->url; $url = $row->url;
$postValues = [ $postValues = [

View File

@ -8,8 +8,7 @@ namespace Vn\Web;
* Format for $_REQUEST['srv'] variable: * Format for $_REQUEST['srv'] variable:
* - [serviceName]:[requestDir]/[requestFile] * - [serviceName]:[requestDir]/[requestFile]
**/ **/
class App extends \Vn\Lib\App class App extends \Vn\Lib\App {
{
protected $conn = NULL; protected $conn = NULL;
private $allowedServices = private $allowedServices =
[ [
@ -18,34 +17,32 @@ class App extends \Vn\Lib\App
'json' 'json'
]; ];
function run () function run() {
{ $this->init();
$this->init ();
$srv = empty ($_REQUEST['srv']) ? '' : $_REQUEST['srv']; $srv = empty($_REQUEST['srv']) ? '' : $_REQUEST['srv'];
$explode = explode (':', $srv, 2); $explode = explode(':', $srv, 2);
if (count ($explode) > 0) if (count($explode) > 0)
$_REQUEST['service'] = $explode[0]; $_REQUEST['service'] = $explode[0];
if (count ($explode) > 1) if (count($explode) > 1)
$_REQUEST['method'] = $explode[1]; $_REQUEST['method'] = $explode[1];
$service = empty ($_REQUEST['service']) ? 'html' : $_REQUEST['service']; $service = empty($_REQUEST['service']) ? 'html' : $_REQUEST['service'];
if (in_array ($service, $this->allowedServices, TRUE)) if (in_array($service, $this->allowedServices, TRUE)) {
{
$includeFile = __DIR__."/$service-service.php"; $includeFile = __DIR__."/$service-service.php";
require_once ($includeFile); require_once($includeFile);
$className = __NAMESPACE__ .'\\'. hyphenToCamelCase ($service, TRUE) .'Service'; $className = __NAMESPACE__ .'\\'. hyphenToCamelCase($service, TRUE) .'Service';
$service = new $className ($this); $service = new $className($this);
$service->run (); $service->run();
} }
else else
http_response_code (400); http_response_code(400);
} }
function deinit () {} function deinit() {}
/** /**
* Gets the configuration file name associated to the current vhost * Gets the configuration file name associated to the current vhost
@ -53,23 +50,21 @@ class App extends \Vn\Lib\App
* *
* @return string The config file name * @return string The config file name
**/ **/
function getConfigFile () function getConfigFile() {
{ if (!empty($_SERVER['SERVER_NAME'])
if (!empty ($_SERVER['SERVER_NAME']) && preg_match('/^[\w\-\.]+$/', $_SERVER['SERVER_NAME'])) {
&& preg_match ('/^[\w\-\.]+$/', $_SERVER['SERVER_NAME'])) $hostSplit = explode('.', $_SERVER['SERVER_NAME']);
{ array_splice($hostSplit, -2);
$hostSplit = explode ('.', $_SERVER['SERVER_NAME']); $subdomain = implode('.', $hostSplit);
array_splice ($hostSplit, -2);
$subdomain = implode ('.', $hostSplit);
$configDir = _CONFIG_DIR .'/'. $this->name; $configDir = _CONFIG_DIR .'/'. $this->name;
$hostFile = "$configDir/config.$subdomain.php"; $hostFile = "$configDir/config.$subdomain.php";
} }
if (isset ($hostFile) && file_exists ($hostFile)) if (isset($hostFile) && file_exists($hostFile))
return $hostFile; return $hostFile;
else else
return parent::getConfigFile (); return parent::getConfigFile();
} }
} }

View File

@ -2,35 +2,29 @@
namespace Vn\Web; namespace Vn\Web;
class DbSessionHandler implements \SessionHandlerInterface class DbSessionHandler implements \SessionHandlerInterface {
{
private $db; private $db;
function __construct ($db) function __construct($db) {
{
$this->db = $db; $this->db = $db;
} }
function open ($savePath, $name) function open($savePath, $name) {
{
return TRUE; return TRUE;
} }
function close () function close() {
{
return TRUE; return TRUE;
} }
function read ($sessionId) function read($sessionId) {
{ $sessionData = $this->db->getValue(
$sessionData = $this->db->getValue (
'SELECT data FROM userSession WHERE ssid = #', [$sessionId]); 'SELECT data FROM userSession WHERE ssid = #', [$sessionId]);
return isset ($sessionData) ? $sessionData : ''; return isset($sessionData) ? $sessionData : '';
} }
function write ($sessionId, $sessionData) function write($sessionId, $sessionData) {
{ $this->db->query(
$this->db->query (
'INSERT INTO userSession SET 'INSERT INTO userSession SET
ssid = #, data = #, lastUpdate = NOW() ssid = #, data = #, lastUpdate = NOW()
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
@ -39,15 +33,13 @@ class DbSessionHandler implements \SessionHandlerInterface
return TRUE; return TRUE;
} }
function destroy ($sessionId) function destroy($sessionId) {
{ $this->db->query('DELETE FROM userSession WHERE ssid = #', [$sessionId]);
$this->db->query ('DELETE FROM userSession WHERE ssid = #', [$sessionId]);
return TRUE; return TRUE;
} }
function gc ($maxLifeTime) function gc($maxLifeTime) {
{ $this->db->query('DELETE FROM userSession
$this->db->query ('DELETE FROM userSession
WHERE lastUpdate < TIMESTAMPADD(SECOND, -#, NOW())', WHERE lastUpdate < TIMESTAMPADD(SECOND, -#, NOW())',
[$maxLifeTime] [$maxLifeTime]
); );

View File

@ -7,57 +7,51 @@ use Vn\Lib\Locale;
/** /**
* Base class for services that sends response as HTML format. * Base class for services that sends response as HTML format.
*/ */
class HtmlService extends Service class HtmlService extends Service {
{ function run() {
function run ()
{
$eFlag = $eFlag =
E_ERROR E_ERROR
| E_USER_ERROR; | E_USER_ERROR;
set_error_handler ([$this, 'errorHandler'], $eFlag); set_error_handler([$this, 'errorHandler'], $eFlag);
set_exception_handler ([$this, 'errorHandler']); set_exception_handler([$this, 'errorHandler']);
$this->init (); $this->init();
$db = $this->db; $db = $this->db;
if (!$this->isHttps () if (!$this->isHttps()
&& $db->getValue ('SELECT https FROM config') && !_DEV_MODE) && $db->getValue('SELECT https FROM config') && !_DEV_MODE) {
{ header("Location: https://{$this->getUri()}");
header ("Location: https://{$this->getUri()}"); exit(0);
exit (0);
} }
$this->startSession (); $this->startSession();
// Getting the requested page // Getting the requested page
if (!empty ($_REQUEST['method']) && isHyphen ($_REQUEST['method'])) if (!empty($_REQUEST['method']) && isHyphen($_REQUEST['method']))
$page = $_REQUEST['method']; $page = $_REQUEST['method'];
else else
$page = 'main'; $page = 'main';
// Checking the browser version // Checking the browser version
if (!isset ($_SESSION['skipBrowser']) && $page != 'update-browser') if (!isset($_SESSION['skipBrowser']) && $page != 'update-browser') {
{
$updateBrowser = FALSE; $updateBrowser = FALSE;
if (!isset ($_GET['skipBrowser']) if (!isset($_GET['skipBrowser'])
&& isset($_SERVER['HTTP_USER_AGENT']) && isset($_SERVER['HTTP_USER_AGENT'])
&& ($browser = get_browser ($_SERVER['HTTP_USER_AGENT']))) &&($browser = get_browser($_SERVER['HTTP_USER_AGENT']))) {
{ $browserVersion =(double) $browser->version;
$browserVersion = (double) $browser->version; $minVersion = $db->getValue(
$minVersion = $db->getValue (
'SELECT version FROM browser WHERE name = #', [$browser->browser]); 'SELECT version FROM browser WHERE name = #', [$browser->browser]);
$updateBrowser = $browserVersion > 0 $updateBrowser = $browserVersion > 0
&& isset ($minVersion) && $browserVersion < $minVersion; && isset($minVersion) && $browserVersion < $minVersion;
} }
if ($updateBrowser) if ($updateBrowser) {
{ header('Location: ?method=update-browser');
header ('Location: ?method=update-browser'); exit(0);
exit (0);
} }
else else
$_SESSION['skipBrowser'] = TRUE; $_SESSION['skipBrowser'] = TRUE;
@ -65,57 +59,52 @@ class HtmlService extends Service
// If enabled, requests the user to choose between two web versions // If enabled, requests the user to choose between two web versions
if (!isset ($_SESSION['skipVersionMenu']) if (!isset($_SESSION['skipVersionMenu'])
&& $db->getValue ('SELECT testDomain FROM config')) && $db->getValue('SELECT testDomain FROM config')) {
{
$_SESSION['skipVersionMenu'] = TRUE; $_SESSION['skipVersionMenu'] = TRUE;
header ('Location: ?method=version-menu'); header('Location: ?method=version-menu');
} }
// Setting the version // Setting the version
setcookie ('vnVersion', $this->getVersion ()); setcookie('vnVersion', $this->getVersion());
// Loading the requested page // Loading the requested page
$basePath = "pages/$page"; $basePath = "pages/$page";
if (file_exists ($basePath)) if (file_exists($basePath)) {
{ Locale::addPath($basePath);
Locale::addPath ($basePath);
$phpFile = "./$basePath/$page.php"; $phpFile = "./$basePath/$page.php";
if (file_exists ($phpFile)) if (file_exists($phpFile))
require ($phpFile); require($phpFile);
$this->printHeader (); $this->printHeader();
$dir = $basePath; $dir = $basePath;
include_once __DIR__.'/html.php'; include_once __DIR__.'/html.php';
include ("./$basePath/ui.php"); include("./$basePath/ui.php");
} }
else else
header ('Location: ./'); header('Location: ./');
} }
function printHeader () function printHeader() {
{ header('Content-Type: text/html; charset=UTF-8');
header ('Content-Type: text/html; charset=UTF-8'); //header("Content-Security-Policy: default-src *; img-src *;");
//header ("Content-Security-Policy: default-src *; img-src *;");
} }
function errorHandler ($err) function errorHandler($err) {
{
error_log("{$err->getMessage()} {$err->getTraceAsString()}"); error_log("{$err->getMessage()} {$err->getTraceAsString()}");
$this->printHeader (); $this->printHeader();
include (__DIR__.'/unavailable.html'); include(__DIR__.'/unavailable.html');
exit (0); exit(0);
return FALSE; return FALSE;
} }
function isMobile () function isMobile() {
{
$re = '/(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i'; $re = '/(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i';
return preg_match ($re, $_SERVER['HTTP_USER_AGENT']); return preg_match($re, $_SERVER['HTTP_USER_AGENT']);
} }
} }

View File

@ -3,66 +3,60 @@
$lang = isset($_SESSION['lang']) ? $_SESSION['lang'] : 'en'; $lang = isset($_SESSION['lang']) ? $_SESSION['lang'] : 'en';
$version = $this->getVersion(); $version = $this->getVersion();
function getUrl ($fileName) function getUrl($fileName) {
{
global $version; global $version;
if (file_exists ($fileName)) if (file_exists($fileName))
$fileVersion = strftime ('%G%m%d%H%M%S', filemtime ($fileName)); $fileVersion = strftime('%G%m%d%H%M%S', filemtime($fileName));
else else
$fileVersion = $version; $fileVersion = $version;
return "$fileName?$fileVersion"; return "$fileName?$fileVersion";
} }
function js ($fileName) function js($fileName) {
{ return '<script type="text/javascript" src="'. getUrl("$fileName.js") .'"></script>'."\n";
return '<script type="text/javascript" src="'. getUrl ("$fileName.js") .'"></script>'."\n";
} }
function css ($fileName) function css($fileName) {
{ return '<link rel="stylesheet" type="text/css" href="'. getUrl("$fileName.css") .'"/>'."\n";
return '<link rel="stylesheet" type="text/css" href="'. getUrl ("$fileName.css") .'"/>'."\n";
} }
function getWebpackAssets () function getWebpackAssets() {
{ $wpConfig = json_decode(file_get_contents('webpack.config.json'));
$wpConfig = json_decode (file_get_contents ('webpack.config.json'));
$buildDir = $wpConfig->buildDir; $buildDir = $wpConfig->buildDir;
$devServerPort = $wpConfig->devServerPort; $devServerPort = $wpConfig->devServerPort;
$host = $_SERVER['SERVER_NAME']; $host = $_SERVER['SERVER_NAME'];
$assets = new stdClass(); $assets = new stdClass();
if (!_DEV_MODE) if (!_DEV_MODE) {
{ $wpAssets = json_decode(file_get_contents("$buildDir/webpack-assets.json"));
$wpAssets = json_decode (file_get_contents ("$buildDir/webpack-assets.json"));
$manifestJs = $wpAssets->manifest->js; $manifestJs = $wpAssets->manifest->js;
$mainJs = $wpAssets->main->js; $mainJs = $wpAssets->main->js;
unset ($wpAssets->manifest); unset($wpAssets->manifest);
unset ($wpAssets->main); unset($wpAssets->main);
foreach ($wpAssets as $name => $asset) foreach($wpAssets as $name => $asset)
if (property_exists ($asset, 'js')) if (property_exists($asset, 'js'))
$assets->$name = $asset->js; $assets->$name = $asset->js;
} }
else else {
{
$devServerPath = "http://$host:$devServerPort/$buildDir"; $devServerPath = "http://$host:$devServerPort/$buildDir";
$manifestJs = "$devServerPath/manifest.js"; $manifestJs = "$devServerPath/manifest.js";
$mainJs = "$devServerPath/main.js"; $mainJs = "$devServerPath/main.js";
unset ($wpConfig->entry->main); unset($wpConfig->entry->main);
foreach ($wpConfig->entry as $asset => $files) foreach($wpConfig->entry as $asset => $files)
$assets->$asset = "$devServerPath/$asset.js"; $assets->$asset = "$devServerPath/$asset.js";
} }
$jsFiles = []; $jsFiles = [];
$jsFiles[] = $manifestJs; $jsFiles[] = $manifestJs;
foreach ($assets as $jsFile) foreach($assets as $jsFile)
$jsFiles[] = $jsFile; $jsFiles[] = $jsFile;
$jsFiles[] = $mainJs; $jsFiles[] = $mainJs;

View File

@ -9,8 +9,7 @@ namespace Vn\Web;
* @property string $message The message string * @property string $message The message string
* @property string $code The code of message * @property string $code The code of message
**/ **/
class JsonException class JsonException {
{
var $exception = NULL; var $exception = NULL;
var $message; var $message;
var $code = NULL; var $code = NULL;

View File

@ -8,8 +8,7 @@ namespace Vn\Web;
* @property Object $data The returned data * @property Object $data The returned data
* @property array $warnings Array with warning messages * @property array $warnings Array with warning messages
**/ **/
class JsonReply class JsonReply {
{
var $data = NULL; var $data = NULL;
var $warnings = NULL; var $warnings = NULL;
} }

View File

@ -7,36 +7,32 @@ use Vn\Lib;
/** /**
* Base class for JSON application. * Base class for JSON application.
*/ */
class JsonService extends RestService class JsonService extends RestService {
{
private $warnings = NULL; private $warnings = NULL;
function run () function run() {
{ ini_set('display_errors', FALSE);
ini_set ('display_errors', FALSE); set_error_handler([$this, 'errorHandler'], E_ALL);
set_error_handler ([$this, 'errorHandler'], E_ALL); set_exception_handler([$this, 'exceptionHandler']);
set_exception_handler ([$this, 'exceptionHandler']);
$this->init (); $this->init();
$this->startSession (); $this->startSession();
$this->checkVersion (); $this->checkVersion();
$json = $this->loadMethod (__NAMESPACE__.'\JsonRequest'); $json = $this->loadMethod(__NAMESPACE__.'\JsonRequest');
$this->replyJson ($json); $this->replyJson($json);
} }
function replyJson ($jsonData) function replyJson($jsonData) {
{ $reply = new JsonReply();
$reply = new JsonReply ();
$reply->data = $jsonData; $reply->data = $jsonData;
$reply->warnings = $this->warnings; $reply->warnings = $this->warnings;
header ('Content-Type: application/json; charset=UTF-8'); header('Content-Type: application/json; charset=UTF-8');
echo json_encode ($reply); echo json_encode($reply);
} }
function errorHandler ($errno, $message, $file, $line, $context) function errorHandler($errno, $message, $file, $line, $context) {
{
$eUserWarn = $eUserWarn =
E_USER_NOTICE E_USER_NOTICE
| E_USER_WARNING | E_USER_WARNING
@ -49,62 +45,55 @@ class JsonService extends RestService
$eWarn = $eUserWarn | $eCoreWarn; $eWarn = $eUserWarn | $eCoreWarn;
$eUser = $eUserWarn | E_USER_ERROR; $eUser = $eUserWarn | E_USER_ERROR;
$json = new JsonException (); $json = new JsonException();
if (_ENABLE_DEBUG || $errno & $eUser) if (_ENABLE_DEBUG || $errno & $eUser)
$json->message = $message; $json->message = $message;
else else
$json->message = s('Something went wrong'); $json->message = s('Something went wrong');
if (_ENABLE_DEBUG) if (_ENABLE_DEBUG) {
{
$json->code = $errno; $json->code = $errno;
$json->file = $file; $json->file = $file;
$json->line = $line; $json->line = $line;
} }
if ($errno & $eWarn) if ($errno & $eWarn) {
{ if (!isset($this->warnings))
if (!isset ($this->warnings))
$this->warnings = []; $this->warnings = [];
$this->warnings[] = $json; $this->warnings[] = $json;
} }
else else {
{ http_response_code(500);
http_response_code (500); $this->replyJson($json);
$this->replyJson ($json); exit();
exit ();
} }
return !($errno & $eUser); return !($errno & $eUser);
} }
function exceptionHandler ($e) function exceptionHandler($e) {
{ $json = new JsonException();
$json = new JsonException ();
if (_ENABLE_DEBUG || $e instanceof Lib\UserException) if (_ENABLE_DEBUG || $e instanceof Lib\UserException) {
{ $json->exception = get_class($e);
$json->exception = get_class ($e); $json->message = $e->getMessage();
$json->message = $e->getMessage ();
} }
else else {
{
$json->exception = 'Exception'; $json->exception = 'Exception';
$json->message = s('Something went wrong'); $json->message = s('Something went wrong');
} }
if (_ENABLE_DEBUG) if (_ENABLE_DEBUG) {
{ $json->code = $e->getCode();
$json->code = $e->getCode (); $json->file = $e->getFile();
$json->file = $e->getFile (); $json->line = $e->getLine();
$json->line = $e->getLine (); $json->trace = $e->getTrace();
$json->trace = $e->getTrace ();
} }
$this->statusFromException ($e); $this->statusFromException($e);
$this->replyJson ($json); $this->replyJson($json);
if (!($e instanceof Lib\UserException)) if (!($e instanceof Lib\UserException))
throw $e; throw $e;

View File

@ -8,8 +8,7 @@ use Exception;
* Basic class to encode, decode and verify JWT tokens. It implements the HS256 * Basic class to encode, decode and verify JWT tokens. It implements the HS256
* algorithm from the RFC 7519 standard. * algorithm from the RFC 7519 standard.
**/ **/
class Jwt class Jwt {
{
/** /**
* Creates a new JWT token with the passed $payload and $key. * Creates a new JWT token with the passed $payload and $key.
* *
@ -17,16 +16,15 @@ class Jwt
* @param {string} $key The key used to sign the token * @param {string} $key The key used to sign the token
* @return {string} The new JWT token * @return {string} The new JWT token
**/ **/
static function encode ($payload, $key) static function encode($payload, $key) {
{
$header = [ $header = [
'alg' => 'HS256', 'alg' => 'HS256',
'typ' => 'JWT' 'typ' => 'JWT'
]; ];
$b64Header = self::jsonB64Encode ($header); $b64Header = self::jsonB64Encode($header);
$b64Payload = self::jsonB64Encode ($payload); $b64Payload = self::jsonB64Encode($payload);
$b64Signature = self::getSignature ($b64Header, $b64Payload, $key); $b64Signature = self::getSignature($b64Header, $b64Payload, $key);
return "$b64Header.$b64Payload.$b64Signature"; return "$b64Header.$b64Payload.$b64Signature";
} }
@ -38,51 +36,45 @@ class Jwt
* @param {string} $key The key used to validate the token * @param {string} $key The key used to validate the token
* @return {string} The JWT validated and decoded data * @return {string} The JWT validated and decoded data
**/ **/
static function decode ($token, $key) static function decode($token, $key) {
{ $parts = explode('.', $token);
$parts = explode ('.', $token);
if (count($parts) !== 3) if (count($parts) !== 3)
throw new Exception ('Bad JWT token'); throw new Exception('Bad JWT token');
$b64Header = $parts[0]; $b64Header = $parts[0];
$b64Payload = $parts[1]; $b64Payload = $parts[1];
$b64Signature = $parts[2]; $b64Signature = $parts[2];
$header = self::jsonB64Decode ($b64Header); $header = self::jsonB64Decode($b64Header);
$payload = self::jsonB64Decode ($b64Payload); $payload = self::jsonB64Decode($b64Payload);
if ($b64Signature != self::getSignature ($b64Header, $b64Payload, $key)) if ($b64Signature != self::getSignature($b64Header, $b64Payload, $key))
throw new Exception ('Bad token signature'); throw new Exception('Bad token signature');
return $payload; return $payload;
} }
static function getSignature ($b64Header, $b64Payload, $key) static function getSignature($b64Header, $b64Payload, $key) {
{ $signature = hash_hmac('sha256', "$b64Header.$b64Payload", $key, TRUE);
$signature = hash_hmac ('sha256', "$b64Header.$b64Payload", $key, TRUE); return self::base64UrlEncode($signature);
return self::base64UrlEncode ($signature);
} }
static function jsonB64Encode ($data) static function jsonB64Encode($data) {
{ return self::base64UrlEncode(json_encode($data));
return self::base64UrlEncode (json_encode ($data));
} }
static function jsonB64Decode ($data) static function jsonB64Decode($data) {
{ return json_decode(self::base64UrlDecode($data), TRUE);
return json_decode (self::base64UrlDecode ($data), TRUE);
} }
static function base64UrlEncode ($data) static function base64UrlEncode($data) {
{ return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
return rtrim (strtr (base64_encode ($data), '+/', '-_'), '=');
} }
static function base64UrlDecode ($data) static function base64UrlDecode($data) {
{ $remainder = strlen($data) % 4;
$remainder = strlen ($data) % 4; $data = strtr($data, '-_', '+/');
$data = strtr ($data, '-_', '+/'); return base64_decode(str_pad($data, $remainder, '=', STR_PAD_RIGHT));
return base64_decode (str_pad ($data, $remainder, '=', STR_PAD_RIGHT));
} }
} }

View File

@ -6,60 +6,54 @@ require_once 'libphp-phpmailer/PHPMailerAutoload.php';
use Vn\Lib\UserException; use Vn\Lib\UserException;
class Mailer class Mailer {
{
private $conf; private $conf;
function __construct ($db) function __construct($db) {
{ $this->conf = $db->getObject(
$this->conf = $db->getObject (
'SELECT host, port, secure, sender, senderName, user, password 'SELECT host, port, secure, sender, senderName, user, password
FROM hedera.mailConfig' FROM hedera.mailConfig'
); );
} }
function createObject ($mailTo, $body, $subject) function createObject($mailTo, $body, $subject) {
{
$conf = $this->conf; $conf = $this->conf;
$mail = new \PHPMailer (); $mail = new \PHPMailer();
$mail->isSMTP (); $mail->isSMTP();
$mail->Host = $conf->host; $mail->Host = $conf->host;
if (!empty ($conf->user)) if (!empty($conf->user)) {
{
$mail->SMTPAuth = TRUE; $mail->SMTPAuth = TRUE;
$mail->Username = $conf->user; $mail->Username = $conf->user;
$mail->Password = base64_decode ($conf->password); $mail->Password = base64_decode($conf->password);
} }
else else
$mail->SMTPAuth = FALSE; $mail->SMTPAuth = FALSE;
if ($conf->secure) if ($conf->secure) {
{
$mail->SMTPSecure = 'ssl'; $mail->SMTPSecure = 'ssl';
$mail->Port = 465; $mail->Port = 465;
} }
$mail->setFrom ($conf->sender, $conf->senderName); $mail->setFrom($conf->sender, $conf->senderName);
$mail->IsHTML (TRUE); $mail->IsHTML(TRUE);
$mail->Subject = $subject; $mail->Subject = $subject;
$mail->Body = $body; $mail->Body = $body;
$mail->CharSet = 'UTF-8'; $mail->CharSet = 'UTF-8';
$mailList = explode (',', $mailTo); $mailList = explode(',', $mailTo);
foreach ($mailList as $to) foreach($mailList as $to)
$mail->AddAddress ($to); $mail->AddAddress($to);
return $mail; return $mail;
} }
function send ($mailTo, $body, $subject) function send($mailTo, $body, $subject) {
{ $mail = $this->createObject($mailTo, $body, $subject);
$mail = $this->createObject ($mailTo, $body, $subject);
if (!$mail->Send ()) if (!$mail->Send())
throw new UserException ('Send error: '.$mail->ErrorInfo); throw new UserException('Send error: '.$mail->ErrorInfo);
} }
} }

View File

@ -2,43 +2,38 @@
namespace Vn\Web; namespace Vn\Web;
class Report class Report {
{
var $db; var $db;
var $name; var $name;
var $html; var $html;
function __construct ($db, $reportName, $params) function __construct($db, $reportName, $params) {
{
$this->db = $db; $this->db = $db;
$this->name = $reportName; $this->name = $reportName;
extract ($params); extract($params);
\Vn\Lib\Locale::addPath ("reports/$reportName"); \Vn\Lib\Locale::addPath("reports/$reportName");
ob_start (); ob_start();
include __DIR__.'/report.html.php'; include __DIR__.'/report.html.php';
$this->html = ob_get_contents (); $this->html = ob_get_contents();
ob_end_clean (); ob_end_clean();
if (isset ($title)) if (isset($title))
$this->title = $title; $this->title = $title;
} }
function getTitle () function getTitle() {
{
return $this->title; return $this->title;
} }
function getHtml () function getHtml() {
{
return $this->html; return $this->html;
} }
function sendMail ($mail) function sendMail($mail) {
{ $mailer = new Mailer($this->db);
$mailer = new Mailer ($this->db); $mailer->send($mail, $this->html, $this->title);
$mailer->send ($mail, $this->html, $this->title);
} }
} }

View File

@ -2,8 +2,7 @@
namespace Vn\Web; namespace Vn\Web;
class Security class Security {
{
const DEFINER = 1; const DEFINER = 1;
const INVOKER = 2; const INVOKER = 2;
} }
@ -11,8 +10,7 @@ class Security
/** /**
* Base class for REST services. * Base class for REST services.
**/ **/
abstract class RestRequest extends \Vn\Lib\Method abstract class RestRequest extends \Vn\Lib\Method {
{
const PARAMS = NULL; const PARAMS = NULL;
const SECURITY = Security::DEFINER; const SECURITY = Security::DEFINER;

View File

@ -9,87 +9,76 @@ use Vn\Lib\UserException;
/** /**
* Base class for REST application. * Base class for REST application.
*/ */
class RestService extends Service class RestService extends Service {
{ function run() {
function run () ini_set('display_errors', _ENABLE_DEBUG);
{ set_error_handler([$this, 'errorHandler'], E_ALL);
ini_set ('display_errors', _ENABLE_DEBUG); set_exception_handler([$this, 'exceptionHandler']);
set_error_handler ([$this, 'errorHandler'], E_ALL);
set_exception_handler ([$this, 'exceptionHandler']);
$this->init (); $this->init();
$this->startSession (); $this->startSession();
$this->loadMethod (__NAMESPACE__.'\RestRequest'); $this->loadMethod(__NAMESPACE__.'\RestRequest');
} }
/** /**
* Runs a REST method. * Runs a REST method.
*/ */
function loadMethod ($class) function loadMethod($class) {
{
$db = $this->db; $db = $this->db;
$this->login (); $this->login();
$method = $this->app->loadMethod ( $method = $this->app->loadMethod(
$_REQUEST['method'], $class, './rest'); $_REQUEST['method'], $class, './rest');
$method->service = $this; $method->service = $this;
if ($method::SECURITY == Security::DEFINER) if ($method::SECURITY == Security::DEFINER) {
{ $isAuthorized = $db->getValue('SELECT userCheckRestPriv(#)',
$isAuthorized = $db->getValue ('SELECT userCheckRestPriv (#)',
[$_REQUEST['method']]); [$_REQUEST['method']]);
if (!$isAuthorized) if (!$isAuthorized)
throw new UserException (s('You don\'t have enough privileges')); throw new UserException(s('You don\'t have enough privileges'));
$methodDb = $db; $methodDb = $db;
} }
else else
$methodDb = $this->getUserDb ($_SESSION['user']); $methodDb = $this->getUserDb($_SESSION['user']);
if ($method::PARAMS !== NULL && !$method->checkParams ($_REQUEST, $method::PARAMS)) if ($method::PARAMS !== NULL && !$method->checkParams($_REQUEST, $method::PARAMS))
throw new UserException (s('Missing parameters')); throw new UserException (s('Missing parameters'));
Locale::addPath ('rest/'. dirname ($_REQUEST['method'])); Locale::addPath('rest/'. dirname($_REQUEST['method']));
$res = NULL; $res = NULL;
try { try {
$res = $method->run ($methodDb); $res = $method->run($methodDb);
} }
catch (Db\Exception $e) catch (Db\Exception $e) {
{ if ($e->getCode() == 1644)
if ($e->getCode () == 1644) throw new UserException(s($e->getMessage()));
throw new UserException (s($e->getMessage ()));
} }
if ($method::SECURITY == Security::DEFINER) if ($method::SECURITY == Security::DEFINER)
$methodDb->query ('CALL account.myUserLogout ()'); $methodDb->query('CALL account.myUserLogout()');
$db->query ('CALL account.myUserLogout ()'); $db->query('CALL account.myUserLogout()');
return $res; return $res;
} }
function statusFromException ($e) function statusFromException($e) {
{
try { try {
throw $e; throw $e;
} }
catch (SessionExpiredException $e) catch (SessionExpiredException $e) { $status = 401; }
{ $status = 401; } catch (BadLoginException $e) { $status = 401; }
catch (BadLoginException $e) catch (Lib\UserException $e) { $status = 400; }
{ $status = 401; } catch (\Exception $e) { $status = 500; }
catch (Lib\UserException $e)
{ $status = 400; }
catch (\Exception $e)
{ $status = 500; }
http_response_code ($status); http_response_code($status);
} }
function errorHandler ($errno, $message, $file, $line, $context) function errorHandler($errno, $message, $file, $line, $context) {
{
$eFlag = $eFlag =
E_USER_NOTICE E_USER_NOTICE
| E_USER_WARNING | E_USER_WARNING
@ -99,14 +88,13 @@ class RestService extends Service
| E_DEPRECATED; | E_DEPRECATED;
if (!($errno & $eFlag)) if (!($errno & $eFlag))
http_response_code (500); http_response_code(500);
return FALSE; return FALSE;
} }
function exceptionHandler ($e) function exceptionHandler($e) {
{ $this->statusFromException($e);
$this->statusFromException ($e);
throw $e; throw $e;
} }
} }

View File

@ -29,98 +29,90 @@ class OutdatedVersionException extends UserException {}
/** /**
* Main class for web applications. * Main class for web applications.
*/ */
abstract class Service abstract class Service {
{
protected $app; protected $app;
protected $db; protected $db;
protected $userDb = NULL; protected $userDb = NULL;
function __construct ($app) function __construct($app) {
{
$this->app = $app; $this->app = $app;
} }
function init () function init() {
{ $this->db = $this->app->getSysConn();
$this->db = $this->app->getSysConn ();
} }
/** /**
* Starts the user session. * Starts the user session.
*/ */
function startSession () function startSession() {
{ $db = $this->app->getSysConn();
$db = $this->app->getSysConn ();
ini_set ('session.cookie_secure', $this->isHttps ()); ini_set('session.cookie_secure', $this->isHttps());
ini_set ('session.hash_function', 'sha256'); ini_set('session.hash_function', 'sha256');
session_set_save_handler (new DbSessionHandler ($db)); session_set_save_handler(new DbSessionHandler($db));
session_start (); session_start();
// Setting the locale // Setting the locale
if (isset ($_SERVER['HTTP_ACCEPT_LANGUAGE'])) if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
if (!isset ($_SESSION['httpLanguage']) if (!isset($_SESSION['httpLanguage'])
|| $_SESSION['httpLanguage'] != $_SERVER['HTTP_ACCEPT_LANGUAGE']) || $_SESSION['httpLanguage'] != $_SERVER['HTTP_ACCEPT_LANGUAGE']) {
{
$_SESSION['httpLanguage'] = $_SERVER['HTTP_ACCEPT_LANGUAGE']; $_SESSION['httpLanguage'] = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$regexp = '/([a-z]{1,4})(?:-[a-z]{1,4})?\s*(?:;\s*q\s*=\s*(?:1|0\.[0-9]+))?,?/i'; $regexp = '/([a-z]{1,4})(?:-[a-z]{1,4})?\s*(?:;\s*q\s*=\s*(?:1|0\.[0-9]+))?,?/i';
preg_match_all ($regexp, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $languages); preg_match_all($regexp, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $languages);
foreach ($languages[1] as $lang) foreach($languages[1] as $lang)
if (TRUE || stream_resolve_include_path ("locale/$lang")) if (TRUE || stream_resolve_include_path("locale/$lang")) {
{
$_SESSION['lang'] = $lang; $_SESSION['lang'] = $lang;
break; break;
} }
} }
if (!isset ($_SESSION['lang'])) if (!isset($_SESSION['lang']))
$_SESSION['lang'] = NULL; $_SESSION['lang'] = NULL;
Locale::set ($_SESSION['lang']); Locale::set($_SESSION['lang']);
Locale::addPath ('vn/web'); Locale::addPath('vn/web');
// Registering the visit // Registering the visit
if (isset ($_COOKIE['PHPSESSID']) if (isset($_COOKIE['PHPSESSID'])
|| isset ($_SESSION['access']) || isset($_SESSION['access'])
|| isset ($_SESSION['skipVisit']) || isset($_SESSION['skipVisit'])
|| !isset ($_SERVER['HTTP_USER_AGENT'])) || !isset($_SERVER['HTTP_USER_AGENT']))
return; return;
$agent = $_SERVER['HTTP_USER_AGENT']; $agent = $_SERVER['HTTP_USER_AGENT'];
$browser = get_browser ($agent, TRUE); $browser = get_browser($agent, TRUE);
if (!empty ($browser['crawler'])) if (!empty($browser['crawler'])) {
{
$_SESSION['skipVisit'] = TRUE; $_SESSION['skipVisit'] = TRUE;
return; return;
} }
if (isset ($_SERVER['REMOTE_ADDR'])) if (isset($_SERVER['REMOTE_ADDR']))
$ip = ip2long ($_SERVER['REMOTE_ADDR']); $ip = ip2long($_SERVER['REMOTE_ADDR']);
$row = $db->getRow ( $row = $db->getRow(
'CALL visitRegister (#, #, #, #, #, #, #, #, #)', 'CALL visitRegister(#, #, #, #, #, #, #, #, #)',
[ [
nullIf ($_COOKIE, 'vnVisit') nullIf($_COOKIE, 'vnVisit')
,nullIf ($browser, 'platform') ,nullIf($browser, 'platform')
,nullIf ($browser, 'browser') ,nullIf($browser, 'browser')
,nullIf ($browser, 'version') ,nullIf($browser, 'version')
,nullIf ($browser, 'javascript') ,nullIf($browser, 'javascript')
,nullIf ($browser, 'cookies') ,nullIf($browser, 'cookies')
,isset ($agent) ? $agent : NULL ,isset($agent) ? $agent : NULL
,isset ($ip) && $ip ? $ip : NULL ,isset($ip) && $ip ? $ip : NULL
,nullIf ($_SERVER, 'HTTP_REFERER') ,nullIf($_SERVER, 'HTTP_REFERER')
] ]
); );
if (isset ($row['access'])) if (isset($row['access'])) {
{ setcookie('vnVisit', $row['visit'], time() + 31536000); // 1 Year
setcookie ('vnVisit', $row['visit'], time () + 31536000); // 1 Year
$_SESSION['access'] = $row['access']; $_SESSION['access'] = $row['access'];
} }
else else
@ -137,92 +129,83 @@ abstract class Service
* *
* return Db\Conn The database connection * return Db\Conn The database connection
*/ */
function login () function login() {
{
$db = $this->db; $db = $this->db;
$anonymousUser = FALSE; $anonymousUser = FALSE;
if (isset ($_POST['user']) && isset ($_POST['password'])) if (isset($_POST['user']) && isset($_POST['password'])) {
{ $user = strtolower($_POST['user']);
$user = strtolower ($_POST['user']);
try { try {
$db->query ('CALL account.userLogin (#, #)', $db->query('CALL account.userLogin(#, #)',
[$user, $_POST['password']]); [$user, $_POST['password']]);
} }
catch (Db\Exception $e) catch (Db\Exception $e) {
{ if ($e->getMessage() == 'INVALID_CREDENTIALS') {
if ($e->getMessage () == 'INVALID_CREDENTIALS') sleep(3);
{ throw new BadLoginException();
sleep (3);
throw new BadLoginException ();
} }
else else
throw $e; throw $e;
} }
} }
else else {
{ if (isset($_POST['token']) || isset($_GET['token'])) {
if (isset ($_POST['token']) || isset ($_GET['token'])) if (isset($_POST['token']))
{
if (isset ($_POST['token']))
$token = $_POST['token']; $token = $_POST['token'];
if (isset ($_GET['token'])) if (isset($_GET['token']))
$token = $_GET['token']; $token = $_GET['token'];
$key = $db->getValue ('SELECT jwtKey FROM config'); $key = $db->getValue('SELECT jwtKey FROM config');
try { try {
$jwtPayload = Jwt::decode ($token, $key); $jwtPayload = Jwt::decode($token, $key);
} }
catch (\Exception $e) catch (\Exception $e) {
{ throw new BadLoginException($e->getMessage());
throw new BadLoginException ($e->getMessage ());
} }
$expiration = $jwtPayload['exp']; $expiration = $jwtPayload['exp'];
if (empty ($expiration) || $expiration <= time()) if (empty($expiration) || $expiration <= time())
throw new SessionExpiredException (); throw new SessionExpiredException();
$user = $jwtPayload['sub']; $user = $jwtPayload['sub'];
if (!empty ($jwtPayload['recover'])) if (!empty($jwtPayload['recover']))
$db->query ( $db->query(
'UPDATE account.user SET recoverPass = TRUE 'UPDATE account.user SET recoverPass = TRUE
WHERE name = #', WHERE name = #',
[$user] [$user]
); );
} }
else else {
{ $user = $db->getValue('SELECT guestUser FROM config');
$user = $db->getValue ('SELECT guestUser FROM config');
$anonymousUser = TRUE; $anonymousUser = TRUE;
} }
$db->query ('CALL account.userLoginWithName (#)', [$user]); $db->query('CALL account.userLoginWithName(#)', [$user]);
} }
$userChanged = !$anonymousUser $userChanged = !$anonymousUser
&& (empty ($_SESSION['user']) || $_SESSION['user'] != $user); &&(empty($_SESSION['user']) || $_SESSION['user'] != $user);
$_SESSION['user'] = $user; $_SESSION['user'] = $user;
// Registering the user access // Registering the user access
if (isset ($_SESSION['access']) && $userChanged) if (isset($_SESSION['access']) && $userChanged)
$db->query ( $db->query(
'CALL visitUserNew (#, #)', 'CALL visitUserNew(#, #)',
[$_SESSION['access'], session_id ()] [$_SESSION['access'], session_id()]
); );
} }
/** /**
* Logouts the current user. Cleans the last saved used credentials. * Logouts the current user. Cleans the last saved used credentials.
*/ */
function logout () function logout() {
{ unset($_SESSION['user']);
unset ($_SESSION['user']);
} }
/** /**
@ -231,12 +214,11 @@ abstract class Service
* *
* @return {Db\Conn} The database connection * @return {Db\Conn} The database connection
*/ */
function getUserDb ($user) function getUserDb($user) {
{
if ($this->userDb) if ($this->userDb)
return $this->userDb; return $this->userDb;
$row = $this->db->getObject ( $row = $this->db->getObject(
'SELECT r.name, rc.mysqlPassword, uc.loginKey 'SELECT r.name, rc.mysqlPassword, uc.loginKey
FROM account.user u FROM account.user u
JOIN account.role r ON r.id = u.role JOIN account.role r ON r.id = u.role
@ -247,10 +229,10 @@ abstract class Service
); );
$userName = "z-{$row->name}"; $userName = "z-{$row->name}";
$password = base64_decode ($row->mysqlPassword); $password = base64_decode($row->mysqlPassword);
$userDb = $this->app->createConnection ($userName, $password, TRUE); $userDb = $this->app->createConnection($userName, $password, TRUE);
$userDb->query ('CALL account.userLoginWithKey (#, #)', [$user, $row->loginKey]); $userDb->query('CALL account.userLoginWithKey(#, #)', [$user, $row->loginKey]);
return $userDb; return $userDb;
} }
@ -262,8 +244,7 @@ abstract class Service
* @param {boolean} $recover Wether to enable recovery mode on login * @param {boolean} $recover Wether to enable recovery mode on login
* @return {string} The JWT generated token * @return {string} The JWT generated token
*/ */
function createToken ($user, $remember = FALSE, $recover = FALSE) function createToken($user, $remember = FALSE, $recover = FALSE) {
{
if ($remember) if ($remember)
$tokenLife = WEEK; $tokenLife = WEEK;
else else
@ -271,14 +252,14 @@ abstract class Service
$payload = [ $payload = [
'sub' => $user, 'sub' => $user,
'exp' => time () + $tokenLife 'exp' => time() + $tokenLife
]; ];
if ($recover) if ($recover)
$payload['recover'] = 'TRUE'; $payload['recover'] = 'TRUE';
$key = $this->db->getValue ('SELECT jwtKey FROM config'); $key = $this->db->getValue('SELECT jwtKey FROM config');
return Jwt::encode ($payload, $key); return Jwt::encode($payload, $key);
} }
/** /**
@ -287,22 +268,19 @@ abstract class Service
* *
* @return string The version number * @return string The version number
*/ */
function getVersion () function getVersion() {
{ $appName = $this->app->getName();
$appName = $this->app->getName ();
$version = apc_fetch("$appName.version", $success); $version = apc_fetch("$appName.version", $success);
if (!$success) if (!$success) {
{ if (file_exists('package.json')) {
if (file_exists ('package.json')) $package = json_decode(file_get_contents('package.json'));
{
$package = json_decode (file_get_contents ('package.json'));
$version = $package->version; $version = $package->version;
} }
else else
$version = '0.0.0'; $version = '0.0.0';
apc_store ("$appName.version", $version); apc_store("$appName.version", $version);
} }
return $version; return $version;
@ -311,14 +289,13 @@ abstract class Service
/** /**
* Checks the client version. * Checks the client version.
*/ */
function checkVersion () function checkVersion() {
{ if (!empty($_COOKIE['vnVersion']))
if (!empty ($_COOKIE['vnVersion']))
$clientVersion = $_COOKIE['vnVersion']; $clientVersion = $_COOKIE['vnVersion'];
if (isset ($clientVersion) if (isset($clientVersion)
&& $clientVersion < $this->getVersion ()) && $clientVersion < $this->getVersion())
throw new OutdatedVersionException (); throw new OutdatedVersionException();
} }
/** /**
@ -326,9 +303,8 @@ abstract class Service
* *
* @return boolean Return %TRUE if its secure, %FALSE otherwise * @return boolean Return %TRUE if its secure, %FALSE otherwise
*/ */
function isHttps () function isHttps() {
{ return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
return isset ($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
} }
/** /**
@ -336,8 +312,7 @@ abstract class Service
* *
* @return string The current URI * @return string The current URI
*/ */
function getUri () function getUri() {
{
return "{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}"; return "{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
} }
@ -346,9 +321,8 @@ abstract class Service
* *
* @return string The current URL * @return string The current URL
*/ */
function getUrl () function getUrl() {
{ $proto = $this->isHttps() ? 'https' : 'http';
$proto = $this->isHttps () ? 'https' : 'http';
return "$proto://{$this->getUri()}"; return "$proto://{$this->getUri()}";
} }
} }

View File

@ -5,13 +5,11 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Not available - Verdnatura</title> <title>Not available - Verdnatura</title>
<style type="text/css"> <style type="text/css">
body body {
{
font-size: 16pt; font-size: 16pt;
font-family: Sans; font-family: Sans;
} }
div div {
{
position: absolute; position: absolute;
width: 32em; width: 32em;
margin-top: -7em; margin-top: -7em;
@ -20,12 +18,10 @@
left: 50%; left: 50%;
text-align: center; text-align: center;
} }
div h2 div h2 {
{
font-weight: normal; font-weight: normal;
} }
div a div a {
{
color: #2962FF; color: #2962FF;
text-decoration: none; text-decoration: none;
} }

View File

@ -2,42 +2,37 @@
namespace Vn\Web; namespace Vn\Web;
class Util class Util {
{
/** /**
* Reads a file and writes it to the output buffer. * Reads a file and writes it to the output buffer.
* *
* @param string file The file path * @param string file The file path
* @param boolean useXsendfile Wether to use the apache module Xsendfile * @param boolean useXsendfile Wether to use the apache module Xsendfile
*/ */
static function printFile ($file, $useXsendfile = FALSE) static function printFile($file, $useXsendfile = FALSE) {
{ if (!file_exists($file)) {
if (!file_exists ($file)) http_response_code(404);
{
http_response_code (404);
return; return;
} }
$finfo = new \finfo (FILEINFO_MIME_TYPE); $finfo = new \finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file ($file); $mimeType = $finfo->file($file);
if ($useXsendfile) if ($useXsendfile) {
{ header("X-Sendfile: $file");
header ("X-Sendfile: $file"); header("Content-Type: $mimeType");
header ("Content-Type: $mimeType");
} }
else else {
{ header('Content-Description: File Transfer');
header ('Content-Description: File Transfer'); header("Content-Type: $mimeType");
header ("Content-Type: $mimeType"); header('Content-Disposition: attachment; filename="'. basename($file) .'"');
header ('Content-Disposition: attachment; filename="'. basename ($file) .'"'); header('Expires: 0');
header ('Expires: 0'); header('Cache-Control: must-revalidate');
header ('Cache-Control: must-revalidate'); header('Pragma: public');
header ('Pragma: public'); header('Content-Length: '. filesize($file));
header ('Content-Length: '. filesize ($file));
set_time_limit (0); set_time_limit(0);
readfile ($file); readfile($file);
} }
} }
} }