Compare commits

...

84 Commits

Author SHA1 Message Date
roshelrao
945724ae3c invoice changes 2021-07-19 13:46:12 +05:30
ddave
72c8b4774c Adding the action manager for the extension 2021-07-16 08:17:30 +02:00
roshelrao
9a1ee350c3 Invoice PDF builder 2021-07-14 13:10:39 +05:30
ddave
7228bb2922 Pdf builder for invoices 2021-07-09 11:24:04 +02:00
roshelrao
5416bdb840 added missing fields 2021-07-08 15:03:32 +05:30
roshelrao
1332448d72 invoice module 2021-07-01 15:51:04 +05:30
Thilina
9f47df5613 Ability to compile extensions 2021-06-29 11:37:46 +02:00
Thilina
731073a133 Merge tag 'v30.0.0.OS' into develop
v30.0.0.OS
2021-06-28 11:48:07 +02:00
Thilina
f44b9ec8dd Merge branch 'release/v30.0.0.OS' 2021-06-28 11:48:05 +02:00
Thilina
ad4fe1cc29 Update release notes 2021-06-28 11:46:49 +02:00
Thilina
8fbf8f2152 Update S3 settings 2021-06-28 10:58:39 +02:00
Thilina
74309fc922 compiled assets and connection module 2021-06-28 08:14:48 +02:00
Thilina
a042ee67ec Add missing classes 2021-06-28 08:14:01 +02:00
Thilina
41ebd61c8e Updates to package json 2021-06-27 18:13:40 +02:00
Thilina
111781b327 Improve naming in custom fields 2021-06-27 18:12:26 +02:00
Thilina
74e448bf5d Add clientBaseUrl and download PDF 2021-06-27 18:12:01 +02:00
Thilina
66b3f006e6 Improve naming in custom fields 2021-06-27 18:07:18 +02:00
Thilina
40df433580 Show viewable files based on extension 2021-06-27 18:06:24 +02:00
Thilina
499c52516e Add connection module to gulp 2021-06-27 18:05:05 +02:00
Thilina
e94a365d71 Just empty spaces 2021-06-27 18:03:57 +02:00
Thilina
e88f5f8a1a Deny access to data directory in development environment 2021-06-27 18:03:23 +02:00
Thilina
c0ce41ed2f Fix typo 2021-06-27 18:01:09 +02:00
Thilina
944d5f1f88 Fix code style issue 2021-06-27 17:49:24 +02:00
Thilina
47871d9551 Add connection module 2021-06-27 17:49:05 +02:00
Thilina
46e3bf439e Fix type in setting 2021-06-27 17:45:45 +02:00
Thilina
b858a62d42 Module builder improvements 2021-06-27 17:45:09 +02:00
Thilina
6da42b4842 Fix issue with non UTF employee names and allow secure file downloads 2021-06-27 17:44:24 +02:00
Thilina
b7b128f9a7 Getting sysdata and checking subordinates 2021-06-27 17:42:39 +02:00
Thilina
7a9f7ec36e Fix usort warning 2021-06-27 17:41:27 +02:00
Thilina
a7218a6666 Update migration list 2021-06-27 17:40:18 +02:00
Thilina
87dc692faa Migration for adding system data table 2021-06-27 17:40:05 +02:00
Thilina
042180b805 Migration for setting AWS region via settings 2021-06-27 17:39:45 +02:00
Thilina
49a22ebdf0 Add migration for S3 settings 2021-06-27 17:39:22 +02:00
Thilina
f1d4b3915e Fix SAML user redirection issue 2021-06-27 17:36:31 +02:00
Thilina
b4bec17934 Update lib files 2021-06-27 17:35:35 +02:00
Thilina
24db01729d Define client base url for each module adapter 2021-06-27 17:10:42 +02:00
Thilina
b4fc0db4de Get AWS region from settings 2021-06-27 17:09:25 +02:00
Thilina
c00fb95319 Download files securely 2021-06-27 17:09:00 +02:00
Thilina
142395591e Generated PDF download action and the data file download wrapper 2021-06-27 17:08:16 +02:00
Thilina
235924f80b Remove unwanted log 2021-06-27 17:02:53 +02:00
Thilina
8f8034556a Fix showing leave tab when its not needed 2021-06-27 17:01:55 +02:00
Thilina
f12a467099 Deny calls to icehrm/core (for nginx need to set location rules) 2021-06-27 16:59:13 +02:00
Thilina
91c2c32c0c File upload fix from react components 2021-06-27 16:58:18 +02:00
Thilina
aacff040bb During the installation set directory permission of data directory to 755 2021-06-27 16:56:04 +02:00
Thilina
e889b856bc Fix extensions loading issue 2021-06-27 16:51:53 +02:00
Thilina
548df6f408 Add eslintrc 2021-06-27 16:50:34 +02:00
Thilina
2ca9eaa083 Soft fix to prevent directory listing 2021-06-27 16:48:38 +02:00
Alan Cell
3eaf290a58 Fix employee filed not loading issue 2021-05-07 08:16:06 +02:00
Alan Cell
c276009bd8 Update release notes 2021-05-07 08:11:21 +02:00
Alan Cell
ea93d4604c Release notes 2021-04-05 20:36:47 +02:00
Alan Cell
caf41de755 Merge tag 'v29.0.0.OS' into develop
v29.0.0.OS
2021-04-05 19:12:59 +02:00
Alan Cell
45d80e9440 Merge branch 'release/v29.0.0.OS' 2021-04-05 19:12:59 +02:00
Alan Cell
bb8f11963a Fix code style 2021-04-05 19:01:58 +02:00
Alan Cell
6581d1424e Merge tag 'v29.0.0.OS' into develop
v29.0.0.OS
2021-04-05 18:53:55 +02:00
Alan Cell
253b298b0d Merge branch 'release/v29.0.0.OS' 2021-04-05 18:53:54 +02:00
Alan Cell
df554680c4 Sync changes v29.0.0 from IceHrmPro (https://icehrm.com/purchase-icehrmpro) 2021-04-05 18:52:23 +02:00
Gamonoid
92032cf1eb Update readme.md 2021-01-12 19:55:00 +01:00
Gamonoid
22cd81611d Add applity 2020-12-20 20:32:30 +01:00
Alan Cell
1a3e468458 Fix displaying wring generated profile image for in staff directory 2020-11-14 19:37:18 +01:00
Alan Cell
88962d4380 Merge branch 'release/v28.2.0.OS' 2020-11-13 02:46:51 +01:00
Alan Cell
3b1285aeaf Merge tag 'v28.2.0.OS' into develop
v28.2.0.OS
2020-11-13 02:46:51 +01:00
Alan Cell
b73e244865 Production build, release notes and version update for v28.2.0 2020-11-13 02:45:48 +01:00
Alan Cell
5f050282f0 Update readme and change delete label for employees 2020-11-13 02:43:40 +01:00
Alan Cell
f1dcc6b6a0 Merge branch 'release/v28.1.1.OS' 2020-11-07 12:52:02 +01:00
Alan Cell
e5eccf32a7 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 12:52:02 +01:00
Alan Cell
b6c0256b49 Update production build 2020-11-07 12:37:11 +01:00
Alan Cell
e31bf5a4b9 Fix api issues and production build 2020-11-07 12:25:12 +01:00
Alan Cell
06a3172a38 Merge branch 'release/v28.1.1.OS' 2020-11-07 11:46:23 +01:00
Alan Cell
e74ca00902 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 11:46:23 +01:00
Alan Cell
28aa16f35c Update version 2020-11-07 11:45:05 +01:00
Alan Cell
fb3b5b562e Merge branch 'release/v28.1.1.OS' 2020-11-07 11:41:24 +01:00
Alan Cell
8663a7aff1 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 11:41:24 +01:00
Alan Cell
e9baf45d7c Production build + fixing code style issues 2020-11-06 20:08:07 +01:00
Alan Cell
2abe52963f Imitate the REST api using url parameter based implementation
Reason for this implementation is some clients having trouble configuring the rest api either due to not having proper access to the webserver in a shared hosting environment or security restrictions. But still from icehrm frontend we need to consume the backend rest api.
2020-11-06 20:00:53 +01:00
Alan Cell
da55c7a2d2 Ability to delete files from S3 2020-11-06 19:41:56 +01:00
Alan Cell
5cd7963f6f Implement password change for employee profile 2020-11-06 19:38:48 +01:00
Alan Cell
d986a2b5bb Fix issue: employee not be selected when filtering employee documents 2020-11-06 19:32:52 +01:00
Alan Cell
1ee4fb4ba1 Update vagrant file 2020-11-06 19:23:05 +01:00
Alan Cell
b06780c466 Fix issue with time-sheets module nit being able to load projects 2020-11-06 18:51:46 +01:00
Alan Cell
5ec497e11d Upgrade vagrant config 2020-11-06 18:41:39 +01:00
Alan Cell
df3b6e968a Update vagrant 2020-11-06 09:46:20 +01:00
Thilina Pituwala
3ceb427479 Fix ci build 2020-11-01 10:17:04 +01:00
Thilina Pituwala
d3b4748cba Remove in lage in readme 2020-11-01 02:37:33 +01:00
Thilina Pituwala
2a9e65d8a8 Remove php5.6 from travis 2020-11-01 02:31:57 +01:00
260 changed files with 409396 additions and 38875 deletions

5
.eslintrc Normal file
View File

@@ -0,0 +1,5 @@
// Use this file as a starting point for your project's .eslintrc.
// Copy this file, and add rule overrides as needed.
{
"extends": "airbnb"
}

2
.gitignore vendored
View File

@@ -13,6 +13,8 @@ keys.dev.pub
/app/icehrm.key /app/icehrm.key
/app/data/*.* /app/data/*.*
/app/data/keys/* /app/data/keys/*
!/app/data/index.php
!/app/data/.htaccess
icehrm.key icehrm.key
cache.properties cache.properties
node_modules/* node_modules/*

View File

@@ -14,7 +14,6 @@ install:
script: ant build-ci script: ant build-ci
language: php language: php
php: php:
- '5.6'
- '7.0' - '7.0'
- '7.1' - '7.1'
- '7.2' - '7.2'

49
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,49 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 0,
"runtimeArgs": [
"-dxdebug.start_with_request=yes"
],
"env": {
"XDEBUG_MODE": "debug,develop",
"XDEBUG_CONFIG": "client_port=${port}"
}
},
{
"name": "Launch Built-in web server",
"type": "php",
"request": "launch",
"runtimeArgs": [
"-dxdebug.mode=debug",
"-dxdebug.start_with_request=yes",
"-S",
"localhost:0"
],
"program": "",
"cwd": "${workspaceRoot}",
"port": 9003,
"serverReadyAction": {
"pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
"uriFormat": "http://localhost:%s",
"action": "openExternally"
}
}
]
}

12
Vagrantfile vendored
View File

@@ -3,8 +3,6 @@ Vagrant.configure("2") do |config|
config.vm.box_version = "1.0.0" config.vm.box_version = "1.0.0"
config.vm.network "private_network", ip: "192.168.10.12" config.vm.network "private_network", ip: "192.168.10.12"
config.vm.synced_folder ".", "/vagrant", type: "nfs" config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.synced_folder "./deployment/vagrant/sites-available", "/etc/nginx/sites-enabled", type: "nfs"
config.vm.synced_folder "./deployment/vagrant/ssl", "/etc/nginx/ssl", type: "nfs"
config.vm.provider "virtualbox" do |vb| config.vm.provider "virtualbox" do |vb|
vb.memory = "1024" vb.memory = "1024"
@@ -13,9 +11,17 @@ Vagrant.configure("2") do |config|
end end
config.vm.provision "shell", inline: <<-SHELL config.vm.provision "shell", inline: <<-SHELL
sudo rm /etc/nginx/ssl/icehrm.*
sudo ln -s /vagrant/deployment/vagrant/ssl/icehrm.crt /etc/nginx/ssl/icehrm.crt
sudo ln -s /vagrant/deployment/vagrant/ssl/icehrm.key /etc/nginx/ssl/icehrm.key
sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /vagrant/deployment/vagrant/sites-available/default /etc/nginx/sites-enabled/default
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
systemctl restart sshd.service
sudo service nginx restart sudo service nginx restart
sudo chmod 755 -R /var/log
SHELL SHELL
config.vm.hostname = "icehrm.os" config.vm.hostname = "icehrm.os"

2
app/data/.htaccess Normal file
View File

@@ -0,0 +1,2 @@
order deny,allow
deny from all

1
app/data/index.php Normal file
View File

@@ -0,0 +1 @@
<?php

3
app/fileupload-new.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
include ('config.php');
include (APP_BASE_PATH.'fileupload-new.php');

View File

@@ -17,6 +17,13 @@ if($group == 'admin' || $group == 'modules'){
$name = str_replace("..","",$name); $name = str_replace("..","",$name);
$name = str_replace("/","",$name); $name = str_replace("/","",$name);
include APP_BASE_PATH.'/'.$group.'/'.$name.'/index.php'; include APP_BASE_PATH.'/'.$group.'/'.$name.'/index.php';
}else if ($group == 'extension'){
$name = str_replace("..","",$name);
$name = str_replace("/","",$name);
$moduleName = $name;
$moduleGroup = 'extensions';
$extensionIndex = APP_BASE_PATH.'/../extensions/'.$name.'/web/index.php';
include APP_BASE_PATH.'extensions/wrapper.php';
}else{ }else{
exit(); exit();
} }

View File

@@ -19,7 +19,10 @@ $isConfigFileWriteable = is_writable(CLIENT_APP_PATH."config.php");
error_log("Config writable ".$isConfigFileWriteable); error_log("Config writable ".$isConfigFileWriteable);
error_log("Config exists ".file_exists(CLIENT_APP_PATH."config.php")); error_log("Config exists ".file_exists(CLIENT_APP_PATH."config.php"));
if(!$isConfigFileWriteable){ if(!$isConfigFileWriteable){
$errorMap[] = array("important","Configuration file [".CLIENT_APP_PATH."config.php] is not writable","Make this file writable",array("sudo touch ".CLIENT_APP_PATH."config.php","sudo chmod 777 ".CLIENT_APP_PATH."config.php")); $errorMap[] = array("important","Configuration file [".CLIENT_APP_PATH."config.php] is not writable","Make this file writable",array(
"sudo touch ".CLIENT_APP_PATH."config.php","sudo chmod 755 ".CLIENT_APP_PATH."config.php",
"sudo chown -R ".shell_exec('whoami')." ".CLIENT_APP_PATH,
));
} }
$isConfigSampleFileExists = file_exists(CLIENT_APP_PATH."config.sample.php"); $isConfigSampleFileExists = file_exists(CLIENT_APP_PATH."config.sample.php");
@@ -48,7 +51,7 @@ if(!$isDataFolderExists){
unlink(CLIENT_APP_PATH."data/test.txt"); unlink(CLIENT_APP_PATH."data/test.txt");
} }
if(!$isDataFolderWritable){ if(!$isDataFolderWritable){
$errorMap[] = array("important","Data folder is not writable","Provide wirte permission to the web server user to ".CLIENT_APP_PATH."data",array("sudo chmod 777 ".CLIENT_APP_PATH."data")); $errorMap[] = array("important","Data folder is not writable","Provide wirte permission to the web server user to ".CLIENT_APP_PATH."data",array("sudo chmod 755 ".CLIENT_APP_PATH."data"));
} }
} }

1
bin/export-plural-rules Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/gettext/languages/bin/export-plural-rules

1
bin/markdown Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/cebe/markdown/bin/markdown

1
bin/pdepend Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/pdepend/pdepend/src/bin/pdepend

1
bin/phpcb Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/mayflower/php-codebrowser/bin/phpcb

1
bin/phpcbf Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcbf

1
bin/phpcpd Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/sebastian/phpcpd/composer/bin/phpcpd

1
bin/phpcs Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcs

1
bin/phploc Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phploc/phploc/phploc

1
bin/phpmd Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phpmd/phpmd/src/bin/phpmd

1
bin/phpunit Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phpunit/phpunit/phpunit

1
bin/release Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/consolidation/self-update/scripts/release

1
bin/robo Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/consolidation/robo/robo

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project name="icehrm" default="build"> <project name="icehrm" default="build">
<!-- By default, we assume all tools to be on the $PATH --> <!-- By default, we assume all tools to be on the $PATH -->
<property name="toolsdir" value="${basedir}/tools/"/> <property name="toolsdir" value="${basedir}/bin/"/>
<property name="destination" value="${basedir}/build/app"/> <property name="destination" value="${basedir}/build/app"/>
<property name="testdir" value="${basedir}/build/test"/> <property name="testdir" value="${basedir}/build/test"/>
<property name="origin" value="${basedir}"/> <property name="origin" value="${basedir}"/>

2
core/.htaccess Normal file
View File

@@ -0,0 +1,2 @@
order deny,allow
deny from all

View File

@@ -4,6 +4,9 @@
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah) Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/ */
use Classes\PermissionManager;
use Clients\Common\Model\Client;
$moduleName = 'clients'; $moduleName = 'clients';
$moduleGroup = 'admin'; $moduleGroup = 'admin';
define('MODULE_PATH', dirname(__FILE__)); define('MODULE_PATH', dirname(__FILE__));
@@ -17,35 +20,32 @@ include APP_BASE_PATH.'modulejslibs.inc.php';
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" id="tabPageClient"> <div class="tab-pane active" id="tabPageClient">
<div id="Client" class="reviewBlock" data-content="List" style="padding-left:5px;"> <div id="ClientTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
<div id="ClientForm"></div>
</div> <div id="ClientFilterForm"></div>
<div id="ClientForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
</div>
</div> </div>
</div> </div>
</div> </div>
<?php
$moduleData = [
'user_level' => $user->user_level,
'permissions' => [
'Client' => PermissionManager::checkGeneralAccess(new Client()),
]
];
?>
<script> <script>
var data = <?= json_encode($moduleData) ?>;
var modJsList = []; var modJsList = [];
modJsList['tabClient'] = new ClientAdapter('Client','Client'); modJsList['tabClient'] = new ClientAdapter('Client');
<?php if(isset($modulePermissions['perm']['Add Clients']) && $modulePermissions['perm']['Add Clients'] == "No"){?>
modJsList['tabClient'].setShowAddNew(false);
<?php }?>
<?php if(isset($modulePermissions['perm']['Delete Clients']) && $modulePermissions['perm']['Delete Clients'] == "No"){?>
modJsList['tabClient'].setShowDelete(false);
<?php }?>
<?php if(isset($modulePermissions['perm']['Edit Clients']) && $modulePermissions['perm']['Edit Clients'] == "No"){?>
modJsList['tabClient'].setShowSave(false);
<?php }?>
modJsList.tabClient.setObjectTypeName('Client');
modJsList.tabClient.setAccess(data.permissions.Client);
modJsList.tabClient.setDataPipe(new IceDataPipe(modJsList.tabClient));
modJsList.tabClient.setRemoteTable(true);
var modJs = modJsList['tabClient']; var modJs = modJsList['tabClient'];
</script> </script>
<?php include APP_BASE_PATH . 'footer.php'; ?> <?php include APP_BASE_PATH . 'footer.php'; ?>

View File

@@ -4,6 +4,7 @@
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah) Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/ */
use Classes\BaseService;
use Classes\PermissionManager; use Classes\PermissionManager;
use Company\Common\Model\CompanyStructure; use Company\Common\Model\CompanyStructure;
@@ -60,6 +61,7 @@ path.link {
<?php <?php
$moduleData = [ $moduleData = [
'user_level' => $user->user_level, 'user_level' => $user->user_level,
'customFields' => BaseService::getInstance()->getCustomFields("CompanyStructure"),
'permissions' => [ 'permissions' => [
'CompanyStructure' => PermissionManager::checkGeneralAccess(new CompanyStructure()), 'CompanyStructure' => PermissionManager::checkGeneralAccess(new CompanyStructure()),
] ]

View File

@@ -0,0 +1,59 @@
<?php
use Classes\StatsHelper;
use Connection\Common\ConnectionService;
$moduleName = 'connection';
$moduleGroup = 'admin';
define('MODULE_PATH',dirname(__FILE__));
include APP_BASE_PATH.'header.php';
include APP_BASE_PATH.'modulejslibs.inc.php';
$isIceHrmPro = false;
if (class_exists('\\Classes\\ProVersion')) {
$data = \Classes\ProVersion::$data;
$isIceHrmPro = true;
$data = json_decode($data, true);
}
$employeeCount = StatsHelper::getEmployeeCount();
$userCount = StatsHelper::getUserCount();
$connectionService = new ConnectionService();
?><div class="span9">
<ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
<li class="active"><a id="tabConnection" href="#tabConnection"><?=t('Connection')?></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tabConnection">
<div class="reviewBlock" data-content="List">
<div id="connectionData"></div>
</div>
</div>
</div>
</div>
<div id="dataGroup"></div>
<?php
$moduleData = [
'user_level' => $user->user_level,
'components' => [
'employeeCount' => [
'isIceHrmPro' => $isIceHrmPro,
'count' => $employeeCount,
'allowed' => $isIceHrmPro ? intval($data['employees']) : 'N/A',
'validUntil' => $data['licenseActivated'],
'licenseId' => $data['key'],
],
'systemData' => [
'data' => $connectionService->getSystemReport(),
'issues' => $connectionService->getSystemErrors(),
],
]
];
?>
<script>
initAdminConnection(<?=json_encode($moduleData)?>);
</script>
<?php include APP_BASE_PATH.'footer.php';?>

View File

@@ -0,0 +1,12 @@
{
"label": "Ice Connect",
"menu": "System",
"order": "9",
"icon": "fa-wifi",
"user_levels": [
"Admin"
],
"permissions": [],
"model_namespace": "\\Connection\\Common\\Model",
"manager": "\\Connection\\Admin\\Api\\ConnectionAdminManager"
}

View File

@@ -0,0 +1,42 @@
<?php
use Classes\BaseService;
use Classes\PermissionManager;
use FieldNames\Common\Model\CustomField;
$moduleName = 'assets';
$moduleGroup = 'admin';
define('MODULE_PATH',dirname(__FILE__));
include APP_BASE_PATH.'header.php';
include APP_BASE_PATH.'modulejslibs.inc.php';
$modelClasses = BaseService::getInstance()->getCustomFieldClassMap();
?><div class="span9">
<ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
<li class="active"><a id="tabCustomField" href="#tabPageCustomField"><?=t('Custom Fields')?></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tabPageCustomField">
<div id="CustomFieldTable" class="reviewBlock" data-content="List"></div>
<div id="CustomFieldForm"></div>
<div id="CustomFieldFilterForm"></div>
</div>
</div>
</div>
<div id="dataGroup"></div>
<?php
$moduleData = [
'user_level' => $user->user_level,
'types' => $modelClasses,
'permissions' => [
'CustomField' => PermissionManager::checkGeneralAccess(new CustomField()),
]
];
?>
<script>
initAdminCustomFields(<?=json_encode($moduleData)?>);
</script>
<?php include APP_BASE_PATH.'footer.php';?>

View File

@@ -0,0 +1,12 @@
{
"label": "Custom Fields",
"menu": "Admin",
"order": "892",
"icon": "fa-code",
"user_levels": [
"Admin"
],
"permissions": [],
"model_namespace": "\\FieldNames\\Common\\Model",
"manager": "\\CustomField\\Admin\\Api\\CustomFieldAdminManager"
}

View File

@@ -13,7 +13,6 @@ include APP_BASE_PATH.'modulejslibs.inc.php';
<ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;"> <ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
<li class="active"><a id="tabEmployeeFieldName" href="#tabPageEmployeeFieldName"><?=t('Employee Field Names')?></a></li> <li class="active"><a id="tabEmployeeFieldName" href="#tabPageEmployeeFieldName"><?=t('Employee Field Names')?></a></li>
<li><a id="tabEmployeeCustomField" href="#tabPageEmployeeCustomField"><?=t('Employee Custom Fields')?></a></li>
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
@@ -25,29 +24,17 @@ include APP_BASE_PATH.'modulejslibs.inc.php';
</div> </div>
</div> </div>
<div class="tab-pane" id="tabPageEmployeeCustomField">
<div id="EmployeeCustomField" class="reviewBlock" data-content="List" style="padding-left:5px;">
</div>
<div id="EmployeeCustomFieldForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
</div>
</div>
</div> </div>
</div> </div>
<script> <script>
var modJsList = new Array(); var modJsList = [];
modJsList['tabEmployeeFieldName'] = new FieldNameAdapter('FieldNameMapping','EmployeeFieldName',{"type":"Employee"}); modJsList['tabEmployeeFieldName'] = new FieldNameAdapter('FieldNameMapping','EmployeeFieldName',{"type":"Employee"});
modJsList['tabEmployeeFieldName'].setRemoteTable(true); modJsList['tabEmployeeFieldName'].setRemoteTable(true);
modJsList['tabEmployeeFieldName'].setShowDelete(false); modJsList['tabEmployeeFieldName'].setShowDelete(false);
modJsList['tabEmployeeFieldName'].setShowAddNew(false); modJsList['tabEmployeeFieldName'].setShowAddNew(false);
modJsList['tabEmployeeCustomField'] = new CustomFieldAdapter('CustomField','EmployeeCustomField',{"type":"Employee"},"display_order desc");
modJsList['tabEmployeeCustomField'].setRemoteTable(true);
modJsList['tabEmployeeCustomField'].setTableType("Employee");
var modJs = modJsList['tabEmployeeFieldName']; var modJs = modJsList['tabEmployeeFieldName'];

View File

@@ -4,13 +4,19 @@
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah) Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/ */
use Classes\PermissionManager;
use Projects\Common\Model\Project;
use Projects\Common\Model\EmployeeProject;
$moduleName = 'projects'; $moduleName = 'projects';
$moduleGroup = 'admin'; $moduleGroup = 'admin';
define('MODULE_PATH', dirname(__FILE__)); define('MODULE_PATH', dirname(__FILE__));
include APP_BASE_PATH . 'header.php'; include APP_BASE_PATH . 'header.php';
include APP_BASE_PATH . 'modulejslibs.inc.php'; include APP_BASE_PATH . 'modulejslibs.inc.php';
?><div class="span9"> ?><div class="span9">
<ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;"> <ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
<li class="active"><a id="tabProject" href="#tabPageProject"><?= t('Projects') ?></a></li> <li class="active"><a id="tabProject" href="#tabPageProject"><?= t('Projects') ?></a></li>
<li><a id="tabEmployeeProject" href="#tabPageEmployeeProject"><?= t('Employee Projects') ?></a></li> <li><a id="tabEmployeeProject" href="#tabPageEmployeeProject"><?= t('Employee Projects') ?></a></li>
@@ -18,55 +24,43 @@ include APP_BASE_PATH.'modulejslibs.inc.php';
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" id="tabPageProject"> <div class="tab-pane active" id="tabPageProject">
<div id="Project" class="reviewBlock" data-content="List" style="padding-left:5px;"> <div id="ProjectTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
<div id="ProjectForm"></div>
</div> <div id="ProjectFilterForm"></div>
<div id="ProjectForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
</div>
</div> </div>
<div class="tab-pane" id="tabPageEmployeeProject"> <div class="tab-pane" id="tabPageEmployeeProject">
<div id="EmployeeProject" class="reviewBlock" data-content="List" style="padding-left:5px;"> <div id="EmployeeProjectTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
<div id="EmployeeProjectForm"></div>
</div> <div id="EmployeeProjectFilterForm"></div>
<div id="EmployeeProjectForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
</div>
</div> </div>
</div> </div>
</div> </div>
<?php
$moduleData = [
'user_level' => $user->user_level,
'permissions' => [
'Project' => PermissionManager::checkGeneralAccess(new Project()),
'EmployeeProject' => PermissionManager::checkGeneralAccess(new EmployeeProject()),
]
];
?>
<script> <script>
var modJsList = []; var modJsList = [];
var data = <?= json_encode($moduleData) ?>;
modJsList['tabProject'] = new ProjectAdapter('Project', 'Project'); modJsList['tabProject'] = new ProjectAdapter('Project', 'Project');
modJsList.tabProject.setObjectTypeName('Project');
<?php if(isset($modulePermissions['perm']['Add Projects']) && $modulePermissions['perm']['Add Projects'] == "No"){?> modJsList.tabProject.setAccess(data.permissions.Project);
modJsList['tabProject'].setShowAddNew(false); modJsList.tabProject.setDataPipe(new IceDataPipe(modJsList.tabProject));
<?php }?> modJsList.tabProject.setRemoteTable(true);
<?php if(isset($modulePermissions['perm']['Delete Projects']) && $modulePermissions['perm']['Delete Projects'] == "No"){?>
modJsList['tabProject'].setShowDelete(false);
<?php }?>
<?php if(isset($modulePermissions['perm']['Edit Projects']) && $modulePermissions['perm']['Edit Projects'] == "No"){?>
modJsList['tabProject'].setShowSave(false);
<?php }?>
modJsList['tabEmployeeProject'] = new EmployeeProjectAdapter('EmployeeProject', 'EmployeeProject'); modJsList['tabEmployeeProject'] = new EmployeeProjectAdapter('EmployeeProject', 'EmployeeProject');
modJsList['tabEmployeeProject'].setRemoteTable(true);
<?php if(isset($modulePermissions['perm']['Add Projects']) && $modulePermissions['perm']['Add Projects'] == "No"){?>
modJsList['tabEmployeeProject'].setShowAddNew(false);
<?php }?>
<?php if(isset($modulePermissions['perm']['Delete Projects']) && $modulePermissions['perm']['Delete Projects'] == "No"){?>
modJsList['tabEmployeeProject'].setShowDelete(false);
<?php }?>
<?php if(isset($modulePermissions['perm']['Edit Projects']) && $modulePermissions['perm']['Edit Projects'] == "No"){?>
modJsList['tabEmployeeProject'].setShowEdit(false);
<?php }?>
modJsList.tabEmployeeProject.setObjectTypeName('Employee Project');
modJsList.tabEmployeeProject.setAccess(data.permissions.EmployeeProject);
modJsList.tabEmployeeProject.setDataPipe(new IceDataPipe(modJsList.tabEmployeeProject));
modJsList.tabEmployeeProject.setRemoteTable(true);
var modJs = modJsList['tabProject']; var modJs = modJsList['tabProject'];

View File

@@ -6,6 +6,7 @@
use Classes\ModuleBuilder\ModuleBuilder; use Classes\ModuleBuilder\ModuleBuilder;
use Classes\ModuleBuilder\ModuleTab; use Classes\ModuleBuilder\ModuleTab;
use Classes\UIManager;
$moduleName = 'settings'; $moduleName = 'settings';
$moduleGroup = 'admin'; $moduleGroup = 'admin';
@@ -19,32 +20,46 @@ $options1 = array();
$options1['setShowAddNew'] = 'false'; $options1['setShowAddNew'] = 'false';
$options1['setRemoteTable'] = 'true'; $options1['setRemoteTable'] = 'true';
$notCloud = !defined('IS_CLOUD') || IS_CLOUD == false;
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'CompanySetting','Setting','Company','SettingAdapter','{"category":"Company"}','name',true,$options1 'CompanySetting','Setting','Company','SettingAdapter','{"category":"Company"}','name',true,$options1
)); ));
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'SystemSetting','Setting','System','SettingAdapter','{"category":"System"}','name',false,$options1 'SystemSetting','Setting','System','SettingAdapter','{"category":"System"}','name',false,$options1
)); ));
if (!defined('CLOUD_INSTALLATION')) { if ( $notCloud ) {
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'EmailSetting', 'Setting', 'Email', 'SettingAdapter', '{"category":"Email"}', 'name', false, $options1 'EmailSetting', 'Setting', 'Email', 'SettingAdapter', '{"category":"Email"}', 'name', false, $options1
)); ));
} }
if(defined('LEAVE_ENABLED') && LEAVE_ENABLED == true) {
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'LeaveSetting','Setting','Leave / PTO','SettingAdapter','{"category":"Leave"}','name',false,$options1 'LeaveSetting', 'Setting', 'Leave', 'SettingAdapter', '{"category":"Leave"}', 'name', false, $options1
)); ));
}
$moduleBuilder->addModuleOrGroup(new ModuleTab(
'AttendanceSetting','Setting','Attendance','SettingAdapter','{"category":"Attendance"}','name',false,$options1
));
if(!defined('LDAP_ENABLED') || LDAP_ENABLED == true){ if(!defined('LDAP_ENABLED') || LDAP_ENABLED == true){
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'LDAPSetting','Setting','LDAP','SettingAdapter','{"category":"LDAP"}','name',false,$options1 'LDAPSetting','Setting','LDAP','SettingAdapter','{"category":"LDAP"}','name',false,$options1
)); ));
} }
if(!defined('SAML_ENABLED') || SAML_ENABLED == true){
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'AttendanceSetting','Setting','Attendance','SettingAdapter','{"category":"Attendance"}','name',false,$options1 'SAMLSetting','Setting','SAML','SettingAdapter','{"category":"SAML"}','name',false,$options1
)); ));
}
$moduleBuilder->addModuleOrGroup(new ModuleTab( $moduleBuilder->addModuleOrGroup(new ModuleTab(
'OtherSetting','Setting','Other','SettingAdapter','{"category":["Projects","Recruitment","Notifications","Expense","Travel","Api","Overtime"]}','name',false,$options1 'OtherSetting','Setting','Other','SettingAdapter','{"category":["Projects","Recruitment","Notifications","Expense","Travel","Api","Overtime"]}','name',false,$options1
)); ));
echo \Classes\UIManager::getInstance()->renderModule($moduleBuilder); echo UIManager::getInstance()->renderModule($moduleBuilder);
?> ?>
</div> </div>
<script> <script>

View File

@@ -31,22 +31,6 @@ $moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
$travelRequestOptions $travelRequestOptions
)); ));
if ($user->user_level === 'Admin') {
$travelCustomFieldOptions = [];
$travelCustomFieldOptions['setRemoteTable'] = 'true';
$travelCustomFieldOptions['setTableType'] = '\'EmployeeTravelRecord\'';
$moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
'TravelCustomField',
'CustomField',
'Custom Fields',
'CustomFieldAdapter',
'{"type":"EmployeeTravelRecord"}',
'',
false,
$travelCustomFieldOptions
));
}
echo \Classes\UIManager::getInstance()->renderModule($moduleBuilder); echo \Classes\UIManager::getInstance()->renderModule($moduleBuilder);

47
core/api-rest.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
define('CLIENT_PATH',dirname(__FILE__));
include ("config.base.php");
include ("include.common.php");
include("server.includes.inc.php");
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
if (defined('SYM_CLIENT')) {
define('REST_API_PATH', '/'.SYM_CLIENT.'/');
} else if (!defined('REST_API_PATH')){
define('REST_API_PATH', '/');
}
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
\Utils\LogManager::getInstance()->debug('Api dispatch URI: '.$uri);
\Utils\LogManager::getInstance()->debug('Api dispatch method: '.$uri);
if (!defined('SYM_CLIENT')) {
//For hosted installations, dispatch will be done in app/index
\Classes\Macaw::dispatch();
}
}else{
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true";
}

39
core/api-url-based.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
define('CLIENT_PATH',dirname(__FILE__));
include ("config.base.php");
include ("include.common.php");
include("server.includes.inc.php");
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
define('REST_API_PATH', '/');
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$method = $_SERVER['REQUEST_METHOD'];
if (strtoupper($method) === 'GET') {
\Classes\IceRoute::dispatch($_GET['url'], $method);
} else {
$method = strtoupper($_REQUEST['method']);
\Classes\IceRoute::dispatch($_REQUEST['url'], $method);
}
}else{
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true";
}

View File

@@ -13,14 +13,13 @@ if(!defined('HOME_LINK_OTHERS')){
} }
//Version //Version
define('VERSION', '28.1.0.OS'); define('VERSION', '30.0.0.OS');
define('CACHE_VALUE', '28.1.0.OS.2020-10311445'); define('CACHE_VALUE', '30.0.0.OS.2021-06261009');
define('VERSION_NUMBER', '280100'); define('VERSION_NUMBER', '300000');
define('VERSION_DATE', '31/10/2020'); define('VERSION_DATE', '26/06/2021');
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');} if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');} if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}
if(!defined('APP_SEC')){define('APP_SEC','dbcs234d2saaqw');}
define('UI_SHOW_SWITCH_PROFILE', true); define('UI_SHOW_SWITCH_PROFILE', true);
define('CRON_LOG', ini_get('error_log')); define('CRON_LOG', ini_get('error_log'));
@@ -33,6 +32,13 @@ if(!defined('WK_HTML_PATH')){
} }
define('ALL_CLIENT_BASE_PATH', '/var/www/icehrm.app/icehrmapp/'); define('ALL_CLIENT_BASE_PATH', '/var/www/icehrm.app/icehrmapp/');
define('IS_CLOUD', false);
define('LDAP_ENABLED', true); define('LDAP_ENABLED', true);
define('SAML_ENABLED', true);
define('LEAVE_ENABLED', true);
define('RECRUITMENT_ENABLED', false); define('RECRUITMENT_ENABLED', false);
define('APP_WEB_URL', 'https://icehrm.com'); define('APP_WEB_URL', 'https://icehrm.com');
if (!defined('EXTENSIONS_URL')) {
define('EXTENSIONS_URL', str_replace('/web/', '/extensions/', BASE_URL));
}

View File

@@ -0,0 +1,31 @@
<?php
use Classes\ExtensionManager;
use Utils\LogManager;
if (!isset($extensionIndex)) {
exit();
}
define('MODULE_PATH',APP_BASE_PATH.'extensions/'.$moduleName);
include APP_BASE_PATH.'header.php';
$extensionManager = new ExtensionManager();
$meta = $extensionManager->getExtensionMetaData($moduleName);
if (!$meta) {
LogManager::getInstance()->error("Extension metadata.json not found for $moduleName");
exit();
}
if ($meta->headless) {
LogManager::getInstance()->error("Extension running in headless mode for $moduleName");
exit();
}
?>
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorReact.js'?>?v=<?=$jsVersion?>"></script>
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntd.js'?>?v=<?=$jsVersion?>"></script>
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntdIcons.js'?>?v=<?=$jsVersion?>"></script>
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntv.js'?>?v=<?=$jsVersion?>"></script>
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorOther.js'?>?v=<?=$jsVersion?>"></script>
<script type="text/javascript" src="<?=EXTENSIONS_URL.$moduleName.'/dist/'.$moduleName.'.js'?>?v=<?=$jsVersion?>"></script>
<?php
include $extensionIndex;
include APP_BASE_PATH.'footer.php';
?>

View File

@@ -139,7 +139,7 @@ $result = $uploader->handleUpload(CLIENT_BASE_PATH.'data/',$saveFileName);
$uploadFilesToS3 = \Classes\SettingsManager::getInstance()->getSetting("Files: Upload Files to S3"); $uploadFilesToS3 = \Classes\SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
$uploadFilesToS3Key = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload"); $uploadFilesToS3Key = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
$uploadFilesToS3Secret = \Classes\SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = \Classes\SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3Bucket = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Bucket"); $s3Bucket = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
$s3WebUrl = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Web Url"); $s3WebUrl = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
@@ -188,7 +188,7 @@ if($result['success'] == 1){
if($uploadedToS3){ if($uploadedToS3){
$result['data'] = $file_url; $result['data'] = $file_url;
}else{ }else{
$result['data'] = CLIENT_BASE_URL.'data/'.$result['filename']; $result['data'] = \Classes\FileService::getInstance()->getLocalSecureUrl($result['filename']);
} }
$result['data'] .= "|".$saveFileName; $result['data'] .= "|".$saveFileName;
$result['data'] .= "|".$file->id; $result['data'] .= "|".$file->id;

View File

@@ -18,6 +18,7 @@
modJsList[prop].setUser(<?=json_encode(\Classes\BaseService::getInstance()->cleanUpUser($user))?>); modJsList[prop].setUser(<?=json_encode(\Classes\BaseService::getInstance()->cleanUpUser($user))?>);
modJsList[prop].initSourceMappings(); modJsList[prop].initSourceMappings();
modJsList[prop].setBaseUrl('<?=BASE_URL?>'); modJsList[prop].setBaseUrl('<?=BASE_URL?>');
modJsList[prop].setClientUrl('<?=CLIENT_BASE_URL?>');
modJsList[prop].setCurrentProfile(<?=json_encode($activeProfile)?>); modJsList[prop].setCurrentProfile(<?=json_encode($activeProfile)?>);
modJsList[prop].setInstanceId('<?=\Classes\BaseService::getInstance()->getInstanceId()?>'); modJsList[prop].setInstanceId('<?=\Classes\BaseService::getInstance()->getInstanceId()?>');
modJsList[prop].setGoogleAnalytics(ga); modJsList[prop].setGoogleAnalytics(ga);
@@ -146,7 +147,9 @@
</script> </script>
<?php include 'popups.php';?> <?php
include 'popups.php';
?>
<script src="<?=BASE_URL?>js/bootstrap-datatable.js"></script> <script src="<?=BASE_URL?>js/bootstrap-datatable.js"></script>
<div id="jt" t="<?=$jwtService->create(3600)?>"></div> <div id="jt" t="<?=$jwtService->create(3600)?>"></div>
</body> </body>

View File

@@ -215,6 +215,26 @@ if (defined('SYM_CLIENT')) {
<?php }?> <?php }?>
<?php foreach($extensions as $menu){?>
<?php if(count($menu['menu']) == 0){continue;}?>
<li class="treeview" ref="<?="extension_".str_replace(" ", "_", $menu['name'])?>">
<a href="#">
<i class="fa <?=!isset($mainIcons[$menu['name']])?"fa-th":$mainIcons[$menu['name']];?>"></i></i> <span><?=\Classes\LanguageManager::tran($menu['name'])?></span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu" id="<?="extension_".str_replace(" ", "_", $menu['name'])?>">
<?php foreach ($menu['menu'] as $item){?>
<li>
<a data-turbolinks="true" href="<?=CLIENT_BASE_URL?>?g=extension&n=<?=$item['name']?>&m=<?="extension_".str_replace(" ", "_", $menu['name'])?>">
<i class="fa <?=!isset($item['icon'])?"fa-angle-double-right":$item['icon']?>"></i> <?=\Classes\LanguageManager::tran($item['label'])?>
</a>
</li>
<?php }?>
</ul>
</li>
<?php }?>
<?php <?php
if(file_exists(CLIENT_PATH.'/third_party_meta.json')){ if(file_exists(CLIENT_PATH.'/third_party_meta.json')){
$tpModules = json_decode(file_get_contents(CLIENT_PATH.'/third_party_meta.json'),true); $tpModules = json_decode(file_get_contents(CLIENT_PATH.'/third_party_meta.json'),true);

171
core/lib/fpdf/changelog.htm Normal file
View File

@@ -0,0 +1,171 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Changelog</title>
<link type="text/css" rel="stylesheet" href="fpdf.css">
<style type="text/css">
dd {margin:1em 0 1em 1em}
</style>
</head>
<body>
<h1>Changelog</h1>
<dl>
<dt><strong>v1.83</strong> (2021-04-18)</dt>
<dd>
- Fixed an issue related to annotations.<br>
</dd>
<dt><strong>v1.82</strong> (2019-12-07)</dt>
<dd>
- Removed a deprecation notice under PHP 7.4.<br>
</dd>
<dt><strong>v1.81</strong> (2015-12-20)</dt>
<dd>
- Added GetPageWidth() and GetPageHeight().<br>
- Fixed a bug in SetXY().<br>
</dd>
<dt><strong>v1.8</strong> (2015-11-29)</dt>
<dd>
- PHP 5.1.0 or higher is now required.<br>
- The MakeFont utility now subsets fonts, which can greatly reduce font sizes.<br>
- Added ToUnicode CMaps to improve text extraction.<br>
- Added a parameter to AddPage() to rotate the page.<br>
- Added a parameter to SetY() to indicate whether the x position should be reset or not.<br>
- Added a parameter to Output() to specify the encoding of the name, and special characters are now properly encoded. Additionally the order of the first two parameters was reversed to be more logical (however the old order is still supported for compatibility).<br>
- The Error() method now throws an exception.<br>
- Adding contents before the first AddPage() or after Close() now raises an error.<br>
- Outputting text with no font selected now raises an error.<br>
</dd>
<dt><strong>v1.7</strong> (2011-06-18)</dt>
<dd>
- The MakeFont utility has been completely rewritten and doesn't depend on ttf2pt1 anymore.<br>
- Alpha channel is now supported for PNGs.<br>
- When inserting an image, it's now possible to specify its resolution.<br>
- Default resolution for images was increased from 72 to 96 dpi.<br>
- When inserting a GIF image, no temporary file is used anymore if the PHP version is 5.1 or higher.<br>
- When output buffering is enabled and the PDF is about to be sent, the buffer is now cleared if it contains only a UTF-8 BOM and/or whitespace (instead of throwing an error).<br>
- Symbol and ZapfDingbats fonts now support underline style.<br>
- Custom page sizes are now checked to ensure that width is smaller than height.<br>
- Standard font files were changed to use the same format as user fonts.<br>
- A bug in the embedding of Type1 fonts was fixed.<br>
- A bug related to SetDisplayMode() and the current locale was fixed.<br>
- A display issue occurring with the Adobe Reader X plug-in was fixed.<br>
- An issue related to transparency with some versions of Adobe Reader was fixed.<br>
- The Content-Length header was removed because it caused an issue when the HTTP server applies compression.<br>
</dd>
<dt><strong>v1.6</strong> (2008-08-03)</dt>
<dd>
- PHP 4.3.10 or higher is now required.<br>
- GIF image support.<br>
- Images can now trigger page breaks.<br>
- Possibility to have different page formats in a single document.<br>
- Document properties (author, creator, keywords, subject and title) can now be specified in UTF-8.<br>
- Fixed a bug: when a PNG was inserted through a URL, an error sometimes occurred.<br>
- An automatic page break in Header() doesn't cause an infinite loop any more.<br>
- Removed some warning messages appearing with recent PHP versions.<br>
- Added HTTP headers to reduce problems with IE.<br>
</dd>
<dt><strong>v1.53</strong> (2004-12-31)</dt>
<dd>
- When the font subdirectory is in the same directory as fpdf.php, it's no longer necessary to define the FPDF_FONTPATH constant.<br>
- The array $HTTP_SERVER_VARS is no longer used. It could cause trouble on PHP5-based configurations with the register_long_arrays option disabled.<br>
- Fixed a problem related to Type1 font embedding which caused trouble to some PDF processors.<br>
- The file name sent to the browser could not contain a space character.<br>
- The Cell() method could not print the number 0 (you had to pass the string '0').<br>
</dd>
<dt><strong>v1.52</strong> (2003-12-30)</dt>
<dd>
- Image() now displays the image at 72 dpi if no dimension is given.<br>
- Output() takes a string as second parameter to indicate destination.<br>
- Open() is now called automatically by AddPage().<br>
- Inserting remote JPEG images doesn't generate an error any longer.<br>
- Decimal separator is forced to dot in the constructor.<br>
- Added several encodings (Turkish, Thai, Hebrew, Ukrainian and Vietnamese).<br>
- The last line of a right-aligned MultiCell() was not correctly aligned if it was terminated by a carriage return.<br>
- No more error message about already sent headers when outputting the PDF to the standard output from the command line.<br>
- The underlining was going too far for text containing characters \, ( or ).<br>
- $HTTP_ENV_VARS has been replaced by $HTTP_SERVER_VARS.<br>
</dd>
<dt><strong>v1.51</strong> (2002-08-03)</dt>
<dd>
- Type1 font support.<br>
- Added Baltic encoding.<br>
- The class now works internally in points with the origin at the bottom in order to avoid two bugs occurring with Acrobat 5:<br>&nbsp;&nbsp;* The line thickness was too large when printed under Windows 98 SE and ME.<br>&nbsp;&nbsp;* TrueType fonts didn't appear immediately inside the plug-in (a substitution font was used), one had to cause a window refresh to make them show up.<br>
- It's no longer necessary to set the decimal separator as dot to produce valid documents.<br>
- The clickable area in a cell was always on the left independently from the text alignment.<br>
- JPEG images in CMYK mode appeared in inverted colors.<br>
- Transparent PNG images in grayscale or true color mode were incorrectly handled.<br>
- Adding new fonts now works correctly even with the magic_quotes_runtime option set to on.<br>
</dd>
<dt><strong>v1.5</strong> (2002-05-28)</dt>
<dd>
- TrueType font (AddFont()) and encoding support (Western and Eastern Europe, Cyrillic and Greek).<br>
- Added Write() method.<br>
- Added underlined style.<br>
- Internal and external link support (AddLink(), SetLink(), Link()).<br>
- Added right margin management and methods SetRightMargin(), SetTopMargin().<br>
- Modification of SetDisplayMode() to select page layout.<br>
- The border parameter of MultiCell() now lets choose borders to draw as Cell().<br>
- When a document contains no page, Close() now calls AddPage() instead of causing a fatal error.<br>
</dd>
<dt><strong>v1.41</strong> (2002-03-13)</dt>
<dd>
- Fixed SetDisplayMode() which no longer worked (the PDF viewer used its default display).<br>
</dd>
<dt><strong>v1.4</strong> (2002-03-02)</dt>
<dd>
- PHP3 is no longer supported.<br>
- Page compression (SetCompression()).<br>
- Choice of page format and possibility to change orientation inside document.<br>
- Added AcceptPageBreak() method.<br>
- Ability to print the total number of pages (AliasNbPages()).<br>
- Choice of cell borders to draw.<br>
- New mode for Cell(): the current position can now move under the cell.<br>
- Ability to include an image by specifying height only (width is calculated automatically).<br>
- Fixed a bug: when a justified line triggered a page break, the footer inherited the corresponding word spacing.<br>
</dd>
<dt><strong>v1.31</strong> (2002-01-12)</dt>
<dd>
- Fixed a bug in drawing frame with MultiCell(): the last line always started from the left margin.<br>
- Removed Expires HTTP header (gives trouble in some situations).<br>
- Added Content-disposition HTTP header (seems to help in some situations).<br>
</dd>
<dt><strong>v1.3</strong> (2001-12-03)</dt>
<dd>
- Line break and text justification support (MultiCell()).<br>
- Color support (SetDrawColor(), SetFillColor(), SetTextColor()). Possibility to draw filled rectangles and paint cell background.<br>
- A cell whose width is declared null extends up to the right margin of the page.<br>
- Line width is now retained from page to page and defaults to 0.2 mm.<br>
- Added SetXY() method.<br>
- Fixed a passing by reference done in a deprecated manner for PHP4.<br>
</dd>
<dt><strong>v1.2</strong> (2001-11-11)</dt>
<dd>
- Added font metric files and GetStringWidth() method.<br>
- Centering and right-aligning text in cells.<br>
- Display mode control (SetDisplayMode()).<br>
- Added methods to set document properties (SetAuthor(), SetCreator(), SetKeywords(), SetSubject(), SetTitle()).<br>
- Possibility to force PDF download by browser.<br>
- Added SetX() and GetX() methods.<br>
- During automatic page break, current abscissa is now retained.<br>
</dd>
<dt><strong>v1.11</strong> (2001-10-20)</dt>
<dd>
- PNG support doesn't require PHP4/zlib any more. Data are now put directly into PDF without any decompression/recompression stage.<br>
- Image insertion now works correctly even with magic_quotes_runtime option set to on.<br>
</dd>
<dt><strong>v1.1</strong> (2001-10-07)</dt>
<dd>
- JPEG and PNG image support.<br>
</dd>
<dt><strong>v1.01</strong> (2001-10-03)</dt>
<dd>
- Fixed a bug involving page break: in case when Header() doesn't specify a font, the one from previous page was not restored and produced an incorrect document.<br>
</dd>
<dt><strong>v1.0</strong> (2001-09-17)</dt>
<dd>
- First version.<br>
</dd>
</dl>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<?php
$type = 'Core';
$name = 'Courier';
$up = -100;
$ut = 50;
for($i=0;$i<=255;$i++)
$cw[chr($i)] = 600;
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,10 @@
<?php
$type = 'Core';
$name = 'Courier-Bold';
$up = -100;
$ut = 50;
for($i=0;$i<=255;$i++)
$cw[chr($i)] = 600;
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,10 @@
<?php
$type = 'Core';
$name = 'Courier-BoldOblique';
$up = -100;
$ut = 50;
for($i=0;$i<=255;$i++)
$cw[chr($i)] = 600;
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,10 @@
<?php
$type = 'Core';
$name = 'Courier-Oblique';
$up = -100;
$ut = 50;
for($i=0;$i<=255;$i++)
$cw[chr($i)] = 600;
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Helvetica';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Helvetica-Bold';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Helvetica-BoldOblique';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Helvetica-Oblique';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,20 @@
<?php
$type = 'Core';
$name = 'Symbol';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>713,'#'=>500,'$'=>549,'%'=>833,'&'=>778,'\''=>439,'('=>333,')'=>333,'*'=>500,'+'=>549,
','=>250,'-'=>549,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>549,'='=>549,'>'=>549,'?'=>444,'@'=>549,'A'=>722,
'B'=>667,'C'=>722,'D'=>612,'E'=>611,'F'=>763,'G'=>603,'H'=>722,'I'=>333,'J'=>631,'K'=>722,'L'=>686,'M'=>889,'N'=>722,'O'=>722,'P'=>768,'Q'=>741,'R'=>556,'S'=>592,'T'=>611,'U'=>690,'V'=>439,'W'=>768,
'X'=>645,'Y'=>795,'Z'=>611,'['=>333,'\\'=>863,']'=>333,'^'=>658,'_'=>500,'`'=>500,'a'=>631,'b'=>549,'c'=>549,'d'=>494,'e'=>439,'f'=>521,'g'=>411,'h'=>603,'i'=>329,'j'=>603,'k'=>549,'l'=>549,'m'=>576,
'n'=>521,'o'=>549,'p'=>549,'q'=>521,'r'=>549,'s'=>603,'t'=>439,'u'=>576,'v'=>713,'w'=>686,'x'=>493,'y'=>686,'z'=>494,'{'=>480,'|'=>200,'}'=>480,'~'=>549,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0,
chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>750,chr(161)=>620,chr(162)=>247,chr(163)=>549,chr(164)=>167,chr(165)=>713,chr(166)=>500,chr(167)=>753,chr(168)=>753,chr(169)=>753,chr(170)=>753,chr(171)=>1042,chr(172)=>987,chr(173)=>603,chr(174)=>987,chr(175)=>603,
chr(176)=>400,chr(177)=>549,chr(178)=>411,chr(179)=>549,chr(180)=>549,chr(181)=>713,chr(182)=>494,chr(183)=>460,chr(184)=>549,chr(185)=>549,chr(186)=>549,chr(187)=>549,chr(188)=>1000,chr(189)=>603,chr(190)=>1000,chr(191)=>658,chr(192)=>823,chr(193)=>686,chr(194)=>795,chr(195)=>987,chr(196)=>768,chr(197)=>768,
chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042,
chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329,
chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0);
$uv = array(32=>160,33=>33,34=>8704,35=>35,36=>8707,37=>array(37,2),39=>8715,40=>array(40,2),42=>8727,43=>array(43,2),45=>8722,46=>array(46,18),64=>8773,65=>array(913,2),67=>935,68=>array(916,2),70=>934,71=>915,72=>919,73=>921,74=>977,75=>array(922,4),79=>array(927,2),81=>920,82=>929,83=>array(931,3),86=>962,87=>937,88=>926,89=>936,90=>918,91=>91,92=>8756,93=>93,94=>8869,95=>95,96=>63717,97=>array(945,2),99=>967,100=>array(948,2),102=>966,103=>947,104=>951,105=>953,106=>981,107=>array(954,4),111=>array(959,2),113=>952,114=>961,115=>array(963,3),118=>982,119=>969,120=>958,121=>968,122=>950,123=>array(123,3),126=>8764,160=>8364,161=>978,162=>8242,163=>8804,164=>8725,165=>8734,166=>402,167=>9827,168=>9830,169=>9829,170=>9824,171=>8596,172=>array(8592,4),176=>array(176,2),178=>8243,179=>8805,180=>215,181=>8733,182=>8706,183=>8226,184=>247,185=>array(8800,2),187=>8776,188=>8230,189=>array(63718,2),191=>8629,192=>8501,193=>8465,194=>8476,195=>8472,196=>8855,197=>8853,198=>8709,199=>array(8745,2),201=>8835,202=>8839,203=>8836,204=>8834,205=>8838,206=>array(8712,2),208=>8736,209=>8711,210=>63194,211=>63193,212=>63195,213=>8719,214=>8730,215=>8901,216=>172,217=>array(8743,2),219=>8660,220=>array(8656,4),224=>9674,225=>9001,226=>array(63720,3),229=>8721,230=>array(63723,10),241=>9002,242=>8747,243=>8992,244=>63733,245=>8993,246=>array(63734,9));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Times-Roman';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>408,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>180,'('=>333,')'=>333,'*'=>500,'+'=>564,
','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>564,'='=>564,'>'=>564,'?'=>444,'@'=>921,'A'=>722,
'B'=>667,'C'=>667,'D'=>722,'E'=>611,'F'=>556,'G'=>722,'H'=>722,'I'=>333,'J'=>389,'K'=>722,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>556,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>722,'W'=>944,
'X'=>722,'Y'=>722,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>469,'_'=>500,'`'=>333,'a'=>444,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>333,'s'=>389,'t'=>278,'u'=>500,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>480,'|'=>200,'}'=>480,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
chr(132)=>444,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>889,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>444,chr(148)=>444,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>980,
chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>200,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>564,chr(173)=>333,chr(174)=>760,chr(175)=>333,
chr(176)=>400,chr(177)=>564,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>453,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>444,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Times-Bold';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>555,'#'=>500,'$'=>500,'%'=>1000,'&'=>833,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>930,'A'=>722,
'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>778,'I'=>389,'J'=>500,'K'=>778,'L'=>667,'M'=>944,'N'=>722,'O'=>778,'P'=>611,'Q'=>778,'R'=>722,'S'=>556,'T'=>667,'U'=>722,'V'=>722,'W'=>1000,
'X'=>722,'Y'=>722,'Z'=>667,'['=>333,'\\'=>278,']'=>333,'^'=>581,'_'=>500,'`'=>333,'a'=>500,'b'=>556,'c'=>444,'d'=>556,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>333,'k'=>556,'l'=>278,'m'=>833,
'n'=>556,'o'=>500,'p'=>556,'q'=>556,'r'=>444,'s'=>389,'t'=>333,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>394,'|'=>220,'}'=>394,'~'=>520,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>667,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>300,chr(171)=>500,chr(172)=>570,chr(173)=>333,chr(174)=>747,chr(175)=>333,
chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>556,chr(182)=>540,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>330,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Times-BoldItalic';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>389,'"'=>555,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>832,'A'=>667,
'B'=>667,'C'=>667,'D'=>722,'E'=>667,'F'=>667,'G'=>722,'H'=>778,'I'=>389,'J'=>500,'K'=>667,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>611,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>667,'W'=>889,
'X'=>667,'Y'=>611,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>570,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
'n'=>556,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>556,'v'=>444,'w'=>667,'x'=>500,'y'=>444,'z'=>389,'{'=>348,'|'=>220,'}'=>348,'~'=>570,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>389,chr(159)=>611,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>266,chr(171)=>500,chr(172)=>606,chr(173)=>333,chr(174)=>747,chr(175)=>333,
chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>576,chr(182)=>500,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>300,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,21 @@
<?php
$type = 'Core';
$name = 'Times-Italic';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>420,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>214,'('=>333,')'=>333,'*'=>500,'+'=>675,
','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>675,'='=>675,'>'=>675,'?'=>500,'@'=>920,'A'=>611,
'B'=>611,'C'=>667,'D'=>722,'E'=>611,'F'=>611,'G'=>722,'H'=>722,'I'=>333,'J'=>444,'K'=>667,'L'=>556,'M'=>833,'N'=>667,'O'=>722,'P'=>611,'Q'=>722,'R'=>611,'S'=>500,'T'=>556,'U'=>722,'V'=>611,'W'=>833,
'X'=>611,'Y'=>556,'Z'=>556,'['=>389,'\\'=>278,']'=>389,'^'=>422,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>278,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>444,'l'=>278,'m'=>722,
'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>500,'v'=>444,'w'=>667,'x'=>444,'y'=>444,'z'=>389,'{'=>400,'|'=>275,'}'=>400,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
chr(132)=>556,chr(133)=>889,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>500,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>556,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>556,chr(148)=>556,chr(149)=>350,chr(150)=>500,chr(151)=>889,chr(152)=>333,chr(153)=>980,
chr(154)=>389,chr(155)=>333,chr(156)=>667,chr(157)=>350,chr(158)=>389,chr(159)=>556,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>275,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>675,chr(173)=>333,chr(174)=>760,chr(175)=>333,
chr(176)=>400,chr(177)=>675,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>523,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>611,chr(193)=>611,chr(194)=>611,chr(195)=>611,chr(196)=>611,chr(197)=>611,
chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
?>

View File

@@ -0,0 +1,20 @@
<?php
$type = 'Core';
$name = 'ZapfDingbats';
$up = -100;
$ut = 50;
$cw = array(
chr(0)=>0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0,
chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939,
','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692,
'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776,
'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873,
'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,chr(127)=>0,chr(128)=>390,chr(129)=>390,chr(130)=>317,chr(131)=>317,
chr(132)=>276,chr(133)=>276,chr(134)=>509,chr(135)=>509,chr(136)=>410,chr(137)=>410,chr(138)=>234,chr(139)=>234,chr(140)=>334,chr(141)=>334,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>732,chr(162)=>544,chr(163)=>544,chr(164)=>910,chr(165)=>667,chr(166)=>760,chr(167)=>760,chr(168)=>776,chr(169)=>595,chr(170)=>694,chr(171)=>626,chr(172)=>788,chr(173)=>788,chr(174)=>788,chr(175)=>788,
chr(176)=>788,chr(177)=>788,chr(178)=>788,chr(179)=>788,chr(180)=>788,chr(181)=>788,chr(182)=>788,chr(183)=>788,chr(184)=>788,chr(185)=>788,chr(186)=>788,chr(187)=>788,chr(188)=>788,chr(189)=>788,chr(190)=>788,chr(191)=>788,chr(192)=>788,chr(193)=>788,chr(194)=>788,chr(195)=>788,chr(196)=>788,chr(197)=>788,
chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918,
chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874,
chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0);
$uv = array(32=>32,33=>array(9985,4),37=>9742,38=>array(9990,4),42=>9755,43=>9758,44=>array(9996,28),72=>9733,73=>array(10025,35),108=>9679,109=>10061,110=>9632,111=>array(10063,4),115=>9650,116=>9660,117=>9670,118=>10070,119=>9687,120=>array(10072,7),128=>array(10088,14),161=>array(10081,7),168=>9827,169=>9830,170=>9829,171=>9824,172=>array(9312,10),182=>array(10102,31),213=>8594,214=>array(8596,2),216=>array(10136,24),241=>array(10161,14));
?>

1910
core/lib/fpdf/fpdf.php Normal file

File diff suppressed because it is too large Load Diff

1354
core/lib/saml2/Assertion.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
<?php
include_once 'Utilities.php';
class IDPMetadataReader{
private $identityProviders;
private $serviceProviders;
public function __construct(DOMNode $xml = NULL){
$this->identityProviders = array();
$this->serviceProviders = array();
$entitiesDescriptor = Utilities::xpQuery($xml, './saml_metadata:EntitiesDescriptor');
if(!empty($entitiesDescriptor))
$entityDescriptors = Utilities::xpQuery($entitiesDescriptor[0], './saml_metadata:EntityDescriptor');
else
$entityDescriptors = Utilities::xpQuery($xml, './saml_metadata:EntityDescriptor');
foreach ($entityDescriptors as $entityDescriptor) {
$idpSSODescriptor = Utilities::xpQuery($entityDescriptor, './saml_metadata:IDPSSODescriptor');
if(isset($idpSSODescriptor) && !empty($idpSSODescriptor)){
array_push($this->identityProviders,new IdentityProviders($entityDescriptor));
}
//TODO: add sp descriptor
}
}
public function getIdentityProviders(){
return $this->identityProviders;
}
public function getServiceProviders(){
return $this->serviceProviders;
}
}
class IdentityProviders{
private $idpName;
private $entityID;
private $loginDetails;
private $logoutDetails;
private $signingCertificate;
private $encryptionCertificate;
private $signedRequest;
public function __construct(DOMElement $xml = NULL){
$this->idpName = '';
$this->loginDetails = array();
$this->logoutDetails = array();
$this->signingCertificate = array();
$this->encryptionCertificate = array();
if ($xml->hasAttribute('entityID')) {
$this->entityID = $xml->getAttribute('entityID');
}
if($xml->hasAttribute('WantAuthnRequestsSigned')){
$this->signedRequest = $xml->getAttribute('WantAuthnRequestsSigned');
}
$idpSSODescriptor = Utilities::xpQuery($xml, './saml_metadata:IDPSSODescriptor');
if (count($idpSSODescriptor) > 1) {
throw new Exception('More than one <IDPSSODescriptor> in <EntityDescriptor>.');
} elseif (empty($idpSSODescriptor)) {
throw new Exception('Missing required <IDPSSODescriptor> in <EntityDescriptor>.');
}
$idpSSODescriptorEL = $idpSSODescriptor[0];
$info = Utilities::xpQuery($xml, './saml_metadata:Extensions');
if($info)
$this->parseInfo($idpSSODescriptorEL);
$this->parseSSOService($idpSSODescriptorEL);
$this->parseSLOService($idpSSODescriptorEL);
$this->parsex509Certificate($idpSSODescriptorEL);
}
private function parseInfo($xml){
$displayNames = Utilities::xpQuery($xml, './mdui:UIInfo/mdui:DisplayName');
foreach ($displayNames as $name) {
if($name->hasAttribute('xml:lang') && $name->getAttribute('xml:lang')=="en"){
$this->idpName = $name->textContent;
}
}
}
private function parseSSOService($xml){
$ssoServices = Utilities::xpQuery($xml, './saml_metadata:SingleSignOnService');
foreach ($ssoServices as $ssoService) {
$binding = str_replace("urn:oasis:names:tc:SAML:2.0:bindings:","",$ssoService->getAttribute('Binding'));
$this->loginDetails = array_merge(
$this->loginDetails,
array($binding => $ssoService->getAttribute('Location'))
);
}
}
private function parseSLOService($xml){
$sloServices = Utilities::xpQuery($xml, './saml_metadata:SingleLogoutService');
foreach ($sloServices as $sloService) {
$binding = str_replace("urn:oasis:names:tc:SAML:2.0:bindings:","",$sloService->getAttribute('Binding'));
$this->logoutDetails = array_merge(
$this->logoutDetails,
array($binding => $sloService->getAttribute('Location'))
);
}
}
private function parsex509Certificate($xml){
foreach ( Utilities::xpQuery($xml, './saml_metadata:KeyDescriptor') as $KeyDescriptorNode ) {
if($KeyDescriptorNode->hasAttribute('use')){
if($KeyDescriptorNode->getAttribute('use')=='encryption'){
$this->parseEncryptionCertificate($KeyDescriptorNode);
}else{
$this->parseSigningCertificate($KeyDescriptorNode);
}
}else{
$this->parseSigningCertificate($KeyDescriptorNode);
}
}
}
private function parseSigningCertificate($xml){
$certNode = Utilities::xpQuery($xml, './ds:KeyInfo/ds:X509Data/ds:X509Certificate');
$certData = trim($certNode[0]->textContent);
$certData = str_replace(array ( "\r", "\n", "\t", ' '), '', $certData);
if(!empty($certNode))
array_push($this->signingCertificate, Utilities::sanitize_certificate( $certData ));
}
private function parseEncryptionCertificate($xml){
$certNode = Utilities::xpQuery($xml, './ds:KeyInfo/ds:X509Data/ds:X509Certificate');
$certData = trim($certNode[0]->textContent);
$certData = str_replace(array ( "\r", "\n", "\t", ' '), '', $certData);
if(!empty($certNode))
array_push($this->encryptionCertificate, $certData);
}
public function getIdpName(){
return "";
}
public function getEntityID(){
return $this->entityID;
}
public function getLoginURL($binding){
return $this->loginDetails[$binding];
}
public function getLogoutURL($binding){
return $this->logoutDetails[$binding];
}
public function getLoginDetails(){
return $this->loginDetails;
}
public function getLogoutDetails(){
return $this->logoutDetails;
}
public function getSigningCertificate(){
return $this->signingCertificate;
}
public function getEncryptionCertificate(){
return $this->encryptionCertificate[0];
}
public function isRequestSigned(){
return $this->signedRequest;
}
}

View File

@@ -0,0 +1,33 @@
<?php
abstract class MoSAMLBasicEnum {
private static $constCacheArray = NULL;
public static function getConstants() {
if (self::$constCacheArray == NULL) {
self::$constCacheArray = array();
}
$calledClass = get_called_class();
if (!array_key_exists($calledClass, self::$constCacheArray)) {
$reflect = new ReflectionClass($calledClass);
self::$constCacheArray[$calledClass] = $reflect->getConstants();
}
return self::$constCacheArray[$calledClass];
}
public static function isValidName($name, $strict = false) {
$constants = self::getConstants();
if ($strict) {
return array_key_exists($name, $constants);
}
$keys = array_map('strtolower', array_keys($constants));
return in_array(strtolower($name), $keys);
}
public static function isValidValue($value, $strict = true) {
$values = array_values(self::getConstants());
return in_array($value, $values, $strict);
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* Created by PhpStorm.
* User: HP
* Date: 9/11/2018
* Time: 9:48 AM
*/
class MoSAMLPointer
{
private $content,$anchor_id,$edge,$align,$active,$pointer_name;
function __construct($header,$body,$anchor_id,$edge,$align,$active,$prefix){
$this->content = '<h3>'.$header.'</h3>';
$this->content .= '<p id="'.$prefix.'" style="font-size: initial;">' .$body . '</p>';
$this-> anchor_id = $anchor_id;
$this->edge = $edge;
$this->align = $align;
$this->active = $active;
$this->pointer_name = 'miniorange_admin_pointer_'.$prefix;
}
function return_array(){
return array(
// The content needs to point to what we created above in the $new_pointer_content variable
'content' => $this->content,
// In order for the custom pointer to appear in the right location we need to specify the ID
// of the element we want it to appear next to
'anchor_id' => $this->anchor_id,
// On what edge do we want the pointer to appear. Options are 'top', 'left', 'right', 'bottom'
'edge' => $this->edge,
// How do we want out custom pointer to align to the element it is attached to. Options are
// 'left', 'right', 'center'
'align' => $this->align,
// This is how we tell the pointer to be dismissed or not. Make sure that the 'new_items'
// string matches the string at the beginning of the array item
'active' => $this->active
);
}
/**
* @return mixed
*/
public function getContent()
{
return $this->content;
}
/**
* @param mixed $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
* @return mixed
*/
public function getAnchorId()
{
return $this->anchor_id;
}
/**
* @return mixed
*/
public function getEdge()
{
return $this->edge;
}
/**
* @return mixed
*/
public function getActive()
{
return $this->active;
}
/**
* @param mixed $active
*/
public function setActive($active)
{
$this->active = $active;
}
/**
* @return mixed
*/
public function getPointerName()
{
return $this->pointer_name;
}
}

View File

@@ -0,0 +1,51 @@
<?php
class MoSAMLPointersManager {
private $pfile;
private $version;
private $prefix;
private $pointers = array();
public function __construct( $file, $version, $prefix ) {
$this->pfile = file_exists( $file ) ? $file : FALSE;
$this->version = str_replace( '.', '_', $version );
$this->prefix = $prefix;
}
public function parse() {
if ( empty( $this->pfile ) ) return;
$pointers = (array) require_once $this->pfile;
if ( empty($pointers) ) return;
foreach ( $pointers as $i => $pointer ) {
if(is_array($pointer)){
$pointer['id'] = "{$this->prefix}{$this->version}_{$i}";
$this->pointers[$pointer['id']] = (object) $pointer;
}
}
}
public function filter( $page ) {
if ( empty( $this->pointers ) ) return array();
$uid = get_current_user_id();
$no = explode( ',', (string) get_user_meta( $uid, 'dismissed_wp_pointers', TRUE ) );
$active_ids = array_diff( array_keys( $this->pointers ), $no );
$good = array();
foreach( $this->pointers as $i => $pointer ) {
if (
in_array( $i, $active_ids, TRUE ) // is active
&& isset( $pointer->where ) // has where
&& in_array( $page, (array) $pointer->where, TRUE ) // current page is in where
) {
$good[] = $pointer;
}
}
$count = count( $good );
if ( $good === 0 ) return array();
foreach( array_values( $good ) as $i => $pointer ) {
$good[$i]->next = $i+1 < $count ? $good[$i+1]->id : '';
}
return $good;
}
}

114
core/lib/saml2/Response.php Normal file
View File

@@ -0,0 +1,114 @@
<?php
/**
* This file is part of miniOrange SAML plugin.
*
* miniOrange SAML plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* miniOrange SAML plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with miniOrange SAML plugin. If not, see <http://www.gnu.org/licenses/>.
*/
include 'Assertion.php';
/**
* Class for SAML2 Response messages.
*
*/
class SAML2_Response
{
/**
* The assertions in this response.
*/
private $assertions;
/**
* The destination URL in this response.
*/
private $destination;
private $certificates;
private $signatureData;
/**
* Constructor for SAML 2 response messages.
*
* @param DOMElement|NULL $xml The input message.
*/
public function __construct(DOMElement $xml = NULL)
{
//parent::__construct('Response', $xml);
$this->assertions = array();
$this->certificates = array();
if ($xml === NULL) {
return;
}
$sig = Utilities::validateElement($xml);
if ($sig !== FALSE) {
$this->certificates = $sig['Certificates'];
$this->signatureData = $sig;
}
/* set the destination from saml response */
if ($xml->hasAttribute('Destination')) {
$this->destination = $xml->getAttribute('Destination');
}
for ($node = $xml->firstChild; $node !== NULL; $node = $node->nextSibling) {
if ($node->namespaceURI !== 'urn:oasis:names:tc:SAML:2.0:assertion') {
continue;
}
if ($node->localName === 'Assertion' || $node->localName === 'EncryptedAssertion') {
$this->assertions[] = new SAML2_Assertion($node);
}
}
}
/**
* Retrieve the assertions in this response.
*
* @return SAML2_Assertion[]|SAML2_EncryptedAssertion[]
*/
public function getAssertions()
{
return $this->assertions;
}
/**
* Set the assertions that should be included in this response.
*
* @param SAML2_Assertion[]|SAML2_EncryptedAssertion[] The assertions.
*/
public function setAssertions(array $assertions)
{
$this->assertions = $assertions;
}
public function getDestination()
{
return $this->destination;
}
public function getCertificates()
{
return $this->certificates;
}
public function getSignatureData()
{
return $this->signatureData;
}
}

View File

@@ -0,0 +1,511 @@
<?php
namespace RobRichards\XMLSecLibs;
use DOMDocument;
use DOMElement;
use DOMNode;
use DOMXPath;
use Exception;
use RobRichards\XMLSecLibs\Utils\MoXPath as XPath;
/**
* xmlseclibs.php
*
* Copyright (c) 2007-2020, Robert Richards <rrichards@cdatazone.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Robert Richards nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @author Robert Richards <rrichards@cdatazone.org>
* @copyright 2007-2020 Robert Richards <rrichards@cdatazone.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class MoXMLSecEnc
{
const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
<xenc:CipherData>
<xenc:CipherValue></xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>";
const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
const URI = 3;
const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
/** @var null|DOMDocument */
private $encdoc = null;
/** @var null|DOMNode */
private $rawNode = null;
/** @var null|string */
public $type = null;
/** @var null|DOMElement */
public $encKey = null;
/** @var array */
private $references = array();
public function __construct()
{
$this->_resetTemplate();
}
private function _resetTemplate()
{
$this->encdoc = new DOMDocument();
$this->encdoc->loadXML(self::template);
}
/**
* @param string $name
* @param DOMNode $node
* @param string $type
* @throws Exception
*/
public function addReference($name, $node, $type)
{
if (! $node instanceOf DOMNode) {
throw new Exception('$node is not of type DOMNode');
}
$curencdoc = $this->encdoc;
$this->_resetTemplate();
$encdoc = $this->encdoc;
$this->encdoc = $curencdoc;
$refuri = MoXMLSecurityDSig::generateGUID();
$element = $encdoc->documentElement;
$element->setAttribute("Id", $refuri);
$this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
}
/**
* @param DOMNode $node
*/
public function setNode($node)
{
$this->rawNode = $node;
}
/**
* Encrypt the selected node with the given key.
*
* @param MoXMLSecurityKey $objKey The encryption key and algorithm.
* @param bool $replace Whether the encrypted node should be replaced in the original tree. Default is true.
* @return DOMElement The <xenc:EncryptedData>-element.
*@throws Exception
*
*/
public function encryptNode($objKey, $replace = true)
{
$data = '';
if (empty($this->rawNode)) {
throw new Exception('Node to encrypt has not been set');
}
if (! $objKey instanceof MoXMLSecurityKey) {
throw new Exception('Invalid Key');
}
$doc = $this->rawNode->ownerDocument;
$xPath = new DOMXPath($this->encdoc);
$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
$cipherValue = $objList->item(0);
if ($cipherValue == null) {
throw new Exception('Error locating CipherValue element within template');
}
switch ($this->type) {
case (self::Element):
$data = $doc->saveXML($this->rawNode);
$this->encdoc->documentElement->setAttribute('Type', self::Element);
break;
case (self::Content):
$children = $this->rawNode->childNodes;
foreach ($children AS $child) {
$data .= $doc->saveXML($child);
}
$this->encdoc->documentElement->setAttribute('Type', self::Content);
break;
default:
throw new Exception('Type is currently not supported');
}
$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
$encMethod->setAttribute('Algorithm', $objKey->getAlgorithm());
$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
$strEncrypt = base64_encode($objKey->encryptData($data));
$value = $this->encdoc->createTextNode($strEncrypt);
$cipherValue->appendChild($value);
if ($replace) {
switch ($this->type) {
case (self::Element):
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
return $this->encdoc;
}
$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
return $importEnc;
case (self::Content):
$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
while ($this->rawNode->firstChild) {
$this->rawNode->removeChild($this->rawNode->firstChild);
}
$this->rawNode->appendChild($importEnc);
return $importEnc;
}
} else {
return $this->encdoc->documentElement;
}
}
/**
* @param MoXMLSecurityKey $objKey
* @throws Exception
*/
public function encryptReferences($objKey)
{
$curRawNode = $this->rawNode;
$curType = $this->type;
foreach ($this->references AS $name => $reference) {
$this->encdoc = $reference["encnode"];
$this->rawNode = $reference["node"];
$this->type = $reference["type"];
try {
$encNode = $this->encryptNode($objKey);
$this->references[$name]["encnode"] = $encNode;
} catch (Exception $e) {
$this->rawNode = $curRawNode;
$this->type = $curType;
throw $e;
}
}
$this->rawNode = $curRawNode;
$this->type = $curType;
}
/**
* Retrieve the CipherValue text from this encrypted node.
*
* @throws Exception
* @return string|null The Ciphervalue text, or null if no CipherValue is found.
*/
public function getCipherValue()
{
if (empty($this->rawNode)) {
throw new Exception('Node to decrypt has not been set');
}
$doc = $this->rawNode->ownerDocument;
$xPath = new DOMXPath($doc);
$xPath->registerNamespace('xmlencr', self::XMLENCNS);
/* Only handles embedded content right now and not a reference */
$query = "./xmlencr:CipherData/xmlencr:CipherValue";
$nodeset = $xPath->query($query, $this->rawNode);
$node = $nodeset->item(0);
if (!$node) {
return null;
}
return base64_decode($node->nodeValue);
}
/**
* Decrypt this encrypted node.
*
* The behaviour of this function depends on the value of $replace.
* If $replace is false, we will return the decrypted data as a string.
* If $replace is true, we will insert the decrypted element(s) into the
* document, and return the decrypted element(s).
*
* @param MoXMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
* @param boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
*
* @return string|DOMElement The decrypted data.
*/
public function decryptNode($objKey, $replace=true)
{
if (! $objKey instanceof MoXMLSecurityKey) {
throw new Exception('Invalid Key');
}
$encryptedData = $this->getCipherValue();
if ($encryptedData) {
$decrypted = $objKey->decryptData($encryptedData);
if ($replace) {
switch ($this->type) {
case (self::Element):
$newdoc = new DOMDocument();
$newdoc->loadXML($decrypted);
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
return $newdoc;
}
$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, true);
$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
return $importEnc;
case (self::Content):
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
$doc = $this->rawNode;
} else {
$doc = $this->rawNode->ownerDocument;
}
$newFrag = $doc->createDocumentFragment();
$newFrag->appendXML($decrypted);
$parent = $this->rawNode->parentNode;
$parent->replaceChild($newFrag, $this->rawNode);
return $parent;
default:
return $decrypted;
}
} else {
return $decrypted;
}
} else {
throw new Exception("Cannot locate encrypted data");
}
}
/**
* Encrypt the XMLSecurityKey
*
* @param MoXMLSecurityKey $srcKey
* @param MoXMLSecurityKey $rawKey
* @param bool $append
* @throws Exception
*/
public function encryptKey($srcKey, $rawKey, $append=true)
{
if ((! $srcKey instanceof MoXMLSecurityKey) || (! $rawKey instanceof MoXMLSecurityKey)) {
throw new Exception('Invalid Key');
}
$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
$root = $this->encdoc->documentElement;
$encKey = $this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptedKey');
if ($append) {
$keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
$keyInfo->appendChild($encKey);
} else {
$this->encKey = $encKey;
}
$encMethod = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
if (! empty($srcKey->name)) {
$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
}
$cipherData = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherData'));
$cipherData->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherValue', $strEncKey));
if (is_array($this->references) && count($this->references) > 0) {
$refList = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:ReferenceList'));
foreach ($this->references AS $name => $reference) {
$refuri = $reference["refuri"];
$dataRef = $refList->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:DataReference'));
$dataRef->setAttribute("URI", '#' . $refuri);
}
}
return;
}
/**
* @param MoXMLSecurityKey $encKey
* @return DOMElement|string
* @throws Exception
*/
public function decryptKey($encKey)
{
if (! $encKey->isEncrypted) {
throw new Exception("Key is not Encrypted");
}
if (empty($encKey->key)) {
throw new Exception("Key is missing data to perform the decryption");
}
return $this->decryptNode($encKey, false);
}
/**
* @param DOMDocument $element
* @return DOMNode|null
*/
public function locateEncryptedData($element)
{
if ($element instanceof DOMDocument) {
$doc = $element;
} else {
$doc = $element->ownerDocument;
}
if ($doc) {
$xpath = new DOMXPath($doc);
$query = "//*[local-name()='EncryptedData' and namespace-uri()='".self::XMLENCNS."']";
$nodeset = $xpath->query($query);
return $nodeset->item(0);
}
return null;
}
/**
* Returns the key from the DOM
* @param null|DOMNode $node
* @return null|MoXMLSecurityKey
*/
public function locateKey($node=null)
{
if (empty($node)) {
$node = $this->rawNode;
}
if (! $node instanceof DOMNode) {
return null;
}
if ($doc = $node->ownerDocument) {
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
$query = ".//xmlsecenc:EncryptionMethod";
$nodeset = $xpath->query($query, $node);
if ($encmeth = $nodeset->item(0)) {
$attrAlgorithm = $encmeth->getAttribute("Algorithm");
try {
$objKey = new MoXMLSecurityKey($attrAlgorithm, array('type' => 'private'));
} catch (Exception $e) {
return null;
}
return $objKey;
}
}
return null;
}
/**
* @param null|MoXMLSecurityKey $objBaseKey
* @param null|DOMNode $node
* @return null|MoXMLSecurityKey
* @throws Exception
*/
public static function staticLocateKeyInfo($objBaseKey=null, $node=null)
{
if (empty($node) || (! $node instanceof DOMNode)) {
return null;
}
$doc = $node->ownerDocument;
if (!$doc) {
return null;
}
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
$xpath->registerNamespace('xmlsecdsig', MoXMLSecurityDSig::XMLDSIGNS);
$query = "./xmlsecdsig:KeyInfo";
$nodeset = $xpath->query($query, $node);
$encmeth = $nodeset->item(0);
if (!$encmeth) {
/* No KeyInfo in EncryptedData / EncryptedKey. */
return $objBaseKey;
}
foreach ($encmeth->childNodes AS $child) {
switch ($child->localName) {
case 'KeyName':
if (! empty($objBaseKey)) {
$objBaseKey->name = $child->nodeValue;
}
break;
case 'KeyValue':
foreach ($child->childNodes AS $keyval) {
switch ($keyval->localName) {
case 'DSAKeyValue':
throw new Exception("DSAKeyValue currently not supported");
case 'RSAKeyValue':
$modulus = null;
$exponent = null;
if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
$modulus = base64_decode($modulusNode->nodeValue);
}
if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
$exponent = base64_decode($exponentNode->nodeValue);
}
if (empty($modulus) || empty($exponent)) {
throw new Exception("Missing Modulus or Exponent");
}
$publicKey = MoXMLSecurityKey::convertRSA($modulus, $exponent);
$objBaseKey->loadKey($publicKey);
break;
}
}
break;
case 'RetrievalMethod':
$type = $child->getAttribute('Type');
if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
/* Unsupported key type. */
break;
}
$uri = $child->getAttribute('URI');
if ($uri[0] !== '#') {
/* URI not a reference - unsupported. */
break;
}
$id = substr($uri, 1);
$query = '//xmlsecenc:EncryptedKey[@Id="'.MoXPath::filterAttrValue($id, MoXPath::DOUBLE_QUOTE).'"]';
$keyElement = $xpath->query($query)->item(0);
if (!$keyElement) {
throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
}
return MoXMLSecurityKey::fromEncryptedKeyElement($keyElement);
case 'EncryptedKey':
return MoXMLSecurityKey::fromEncryptedKeyElement($child);
case 'X509Data':
if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
if ($x509certNodes->length > 0) {
$x509cert = $x509certNodes->item(0)->textContent;
$x509cert = str_replace(array("\r", "\n", " "), "", $x509cert);
$x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
$objBaseKey->loadKey($x509cert, false, true);
}
}
break;
}
}
return $objBaseKey;
}
/**
* @param null|MoXMLSecurityKey $objBaseKey
* @param null|DOMNode $node
* @return null|MoXMLSecurityKey
*/
public function locateKeyInfo($objBaseKey=null, $node=null)
{
if (empty($node)) {
$node = $this->rawNode;
}
return self::staticLocateKeyInfo($objBaseKey, $node);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,800 @@
<?php
namespace RobRichards\XMLSecLibs;
use DOMElement;
use Exception;
/**
* xmlseclibs.php
*
* Copyright (c) 2007-2020, Robert Richards <rrichards@cdatazone.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Robert Richards nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @author Robert Richards <rrichards@cdatazone.org>
* @copyright 2007-2020 Robert Richards <rrichards@cdatazone.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class MoXMLSecurityKey
{
const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
const AES128_GCM = 'http://www.w3.org/2009/xmlenc11#aes128-gcm';
const AES192_GCM = 'http://www.w3.org/2009/xmlenc11#aes192-gcm';
const AES256_GCM = 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
const RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
const RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
const HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
const AUTHTAG_LENGTH = 16;
/** @var array */
private $cryptParams = array();
/** @var int|string */
public $type = 0;
/** @var mixed|null */
public $key = null;
/** @var string */
public $passphrase = "";
/** @var string|null */
public $iv = null;
/** @var string|null */
public $name = null;
/** @var mixed|null */
public $keyChain = null;
/** @var bool */
public $isEncrypted = false;
/** @var MoXMLSecEnc|null */
public $encryptedCtx = null;
/** @var mixed|null */
public $guid = null;
/**
* This variable contains the certificate as a string if this key represents an X509-certificate.
* If this key doesn't represent a certificate, this will be null.
* @var string|null
*/
private $x509Certificate = null;
/**
* This variable contains the certificate thumbprint if we have loaded an X509-certificate.
* @var string|null
*/
private $X509Thumbprint = null;
/**
* @param string $type
* @param null|array $params
* @throws Exception
*/
public function __construct($type, $params=null)
{
switch ($type) {
case (self::TRIPLEDES_CBC):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'des-ede3-cbc';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
$this->cryptParams['keysize'] = 24;
$this->cryptParams['blocksize'] = 8;
break;
case (self::AES128_CBC):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-128-cbc';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
$this->cryptParams['keysize'] = 16;
$this->cryptParams['blocksize'] = 16;
break;
case (self::AES192_CBC):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-192-cbc';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
$this->cryptParams['keysize'] = 24;
$this->cryptParams['blocksize'] = 16;
break;
case (self::AES256_CBC):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-256-cbc';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
$this->cryptParams['keysize'] = 32;
$this->cryptParams['blocksize'] = 16;
break;
case (self::AES128_GCM):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-128-gcm';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes128-gcm';
$this->cryptParams['keysize'] = 32;
$this->cryptParams['blocksize'] = 16;
break;
case (self::AES192_GCM):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-192-gcm';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes192-gcm';
$this->cryptParams['keysize'] = 32;
$this->cryptParams['blocksize'] = 16;
break;
case (self::AES256_GCM):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['cipher'] = 'aes-256-gcm';
$this->cryptParams['type'] = 'symmetric';
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
$this->cryptParams['keysize'] = 32;
$this->cryptParams['blocksize'] = 16;
break;
case (self::RSA_1_5):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::RSA_OAEP_MGF1P):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
$this->cryptParams['hash'] = null;
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::RSA_SHA1):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::RSA_SHA256):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
$this->cryptParams['digest'] = 'SHA256';
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::RSA_SHA384):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
$this->cryptParams['digest'] = 'SHA384';
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::RSA_SHA512):
$this->cryptParams['library'] = 'openssl';
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
$this->cryptParams['digest'] = 'SHA512';
if (is_array($params) && ! empty($params['type'])) {
if ($params['type'] == 'public' || $params['type'] == 'private') {
$this->cryptParams['type'] = $params['type'];
break;
}
}
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
case (self::HMAC_SHA1):
$this->cryptParams['library'] = $type;
$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
break;
default:
throw new Exception('Invalid Key Type');
}
$this->type = $type;
}
/**
* Retrieve the key size for the symmetric encryption algorithm..
*
* If the key size is unknown, or this isn't a symmetric encryption algorithm,
* null is returned.
*
* @return int|null The number of bytes in the key.
*/
public function getSymmetricKeySize()
{
if (! isset($this->cryptParams['keysize'])) {
return null;
}
return $this->cryptParams['keysize'];
}
/**
* Generates a session key using the openssl-extension.
* In case of using DES3-CBC the key is checked for a proper parity bits set.
* @return string
* @throws Exception
*/
public function generateSessionKey()
{
if (!isset($this->cryptParams['keysize'])) {
throw new Exception('Unknown key size for type "' . $this->type . '".');
}
$keysize = $this->cryptParams['keysize'];
$key = openssl_random_pseudo_bytes($keysize);
if ($this->type === self::TRIPLEDES_CBC) {
/* Make sure that the generated key has the proper parity bits set.
* Mcrypt doesn't care about the parity bits, but others may care.
*/
for ($i = 0; $i < strlen($key); $i++) {
$byte = ord($key[$i]) & 0xfe;
$parity = 1;
for ($j = 1; $j < 8; $j++) {
$parity ^= ($byte >> $j) & 1;
}
$byte |= $parity;
$key[$i] = chr($byte);
}
}
$this->key = $key;
return $key;
}
/**
* Get the raw thumbprint of a certificate
*
* @param string $cert
* @return null|string
*/
public static function getRawThumbprint($cert)
{
$arCert = explode("\n", $cert);
$data = '';
$inData = false;
foreach ($arCert AS $curData) {
if (! $inData) {
if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
$inData = true;
}
} else {
if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
break;
}
$data .= trim($curData);
}
}
if (! empty($data)) {
return strtolower(sha1(base64_decode($data)));
}
return null;
}
/**
* Loads the given key, or - with isFile set true - the key from the keyfile.
*
* @param string $key
* @param bool $isFile
* @param bool $isCert
* @throws Exception
*/
public function loadKey($key, $isFile=false, $isCert = false)
{
if ($isFile) {
$this->key = file_get_contents($key);
} else {
$this->key = $key;
}
if ($isCert) {
$this->key = openssl_x509_read($this->key);
openssl_x509_export($this->key, $str_cert);
$this->x509Certificate = $str_cert;
$this->key = $str_cert;
} else {
$this->x509Certificate = null;
}
if ($this->cryptParams['library'] == 'openssl') {
switch ($this->cryptParams['type']) {
case 'public':
if ($isCert) {
/* Load the thumbprint if this is an X509 certificate. */
$this->X509Thumbprint = self::getRawThumbprint($this->key);
}
$this->key = openssl_get_publickey($this->key);
if (! $this->key) {
throw new Exception('Unable to extract public key');
}
break;
case 'private':
$this->key = openssl_get_privatekey($this->key, $this->passphrase);
break;
case'symmetric':
if (strlen($this->key) < $this->cryptParams['keysize']) {
throw new Exception('Key must contain at least 25 characters for this cipher');
}
break;
default:
throw new Exception('Unknown type');
}
}
}
/**
* ISO 10126 Padding
*
* @param string $data
* @param integer $blockSize
* @throws Exception
* @return string
*/
private function padISO10126($data, $blockSize)
{
if ($blockSize > 256) {
throw new Exception('Block size higher than 256 not allowed');
}
$padChr = $blockSize - (strlen($data) % $blockSize);
$pattern = chr($padChr);
return $data . str_repeat($pattern, $padChr);
}
/**
* Remove ISO 10126 Padding
*
* @param string $data
* @return string
*/
private function unpadISO10126($data)
{
$padChr = substr($data, -1);
$padLen = ord($padChr);
return substr($data, 0, -$padLen);
}
/**
* Encrypts the given data (string) using the openssl-extension
*
* @param string $data
* @return string
*/
private function encryptSymmetric($data)
{
$this->iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->cryptParams['cipher']));
$authTag = null;
if(in_array($this->cryptParams['cipher'], ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])) {
if (version_compare(PHP_VERSION, '7.1.0') < 0) {
throw new Exception('PHP 7.1.0 is required to use AES GCM algorithms');
}
$authTag = openssl_random_pseudo_bytes(self::AUTHTAG_LENGTH);
$encrypted = openssl_encrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA, $this->iv, $authTag);
} else {
$data = $this->padISO10126($data, $this->cryptParams['blocksize']);
$encrypted = openssl_encrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
}
if (false === $encrypted) {
throw new Exception('Failure encrypting Data (openssl symmetric) - ' . openssl_error_string());
}
return $this->iv . $encrypted . $authTag;
}
/**
* Decrypts the given data (string) using the openssl-extension
*
* @param string $data
* @return string
*/
private function decryptSymmetric($data)
{
$iv_length = openssl_cipher_iv_length($this->cryptParams['cipher']);
$this->iv = substr($data, 0, $iv_length);
$data = substr($data, $iv_length);
$authTag = null;
if(in_array($this->cryptParams['cipher'], ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])) {
if (version_compare(PHP_VERSION, '7.1.0') < 0) {
throw new Exception('PHP 7.1.0 is required to use AES GCM algorithms');
}
// obtain and remove the authentication tag
$offset = 0 - self::AUTHTAG_LENGTH;
$authTag = substr($data, $offset);
$data = substr($data, 0, $offset);
$decrypted = openssl_decrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA, $this->iv, $authTag);
} else {
$decrypted = openssl_decrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
}
if (false === $decrypted) {
throw new Exception('Failure decrypting Data (openssl symmetric) - ' . openssl_error_string());
}
return null !== $authTag ? $decrypted : $this->unpadISO10126($decrypted);
}
/**
* Encrypts the given public data (string) using the openssl-extension
*
* @param string $data
* @return string
* @throws Exception
*/
private function encryptPublic($data)
{
if (! openssl_public_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
throw new Exception('Failure encrypting Data (openssl public) - ' . openssl_error_string());
}
return $encrypted;
}
/**
* Decrypts the given public data (string) using the openssl-extension
*
* @param string $data
* @return string
* @throws Exception
*/
private function decryptPublic($data)
{
if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
throw new Exception('Failure decrypting Data (openssl public) - ' . openssl_error_string());
}
return $decrypted;
}
/**
* Encrypts the given private data (string) using the openssl-extension
*
* @param string $data
* @return string
* @throws Exception
*/
private function encryptPrivate($data)
{
if (! openssl_private_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
throw new Exception('Failure encrypting Data (openssl private) - ' . openssl_error_string());
}
return $encrypted;
}
/**
* Decrypts the given private data (string) using the openssl-extension
*
* @param string $data
* @return string
* @throws Exception
*/
private function decryptPrivate($data)
{
if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
throw new Exception('Failure decrypting Data (openssl private) - ' . openssl_error_string());
}
return $decrypted;
}
/**
* Signs the given data (string) using the openssl-extension
*
* @param string $data
* @return string
* @throws Exception
*/
private function signOpenSSL($data)
{
$algo = OPENSSL_ALGO_SHA1;
if (! empty($this->cryptParams['digest'])) {
$algo = $this->cryptParams['digest'];
}
if (! openssl_sign($data, $signature, $this->key, $algo)) {
throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
}
return $signature;
}
/**
* Verifies the given data (string) belonging to the given signature using the openssl-extension
*
* Returns:
* 1 on succesful signature verification,
* 0 when signature verification failed,
* -1 if an error occurred during processing.
*
* NOTE: be very careful when checking the return value, because in PHP,
* -1 will be cast to True when in boolean context. So always check the
* return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
*
* @param string $data
* @param string $signature
* @return int
*/
private function verifyOpenSSL($data, $signature)
{
$algo = OPENSSL_ALGO_SHA1;
if (! empty($this->cryptParams['digest'])) {
$algo = $this->cryptParams['digest'];
}
return openssl_verify($data, $signature, $this->key, $algo);
}
/**
* Encrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
*
* @param string $data
* @return mixed|string
*/
public function encryptData($data)
{
if ($this->cryptParams['library'] === 'openssl') {
switch ($this->cryptParams['type']) {
case 'symmetric':
return $this->encryptSymmetric($data);
case 'public':
return $this->encryptPublic($data);
case 'private':
return $this->encryptPrivate($data);
}
}
}
/**
* Decrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
*
* @param string $data
* @return mixed|string
*/
public function decryptData($data)
{
if ($this->cryptParams['library'] === 'openssl') {
switch ($this->cryptParams['type']) {
case 'symmetric':
return $this->decryptSymmetric($data);
case 'public':
return $this->decryptPublic($data);
case 'private':
return $this->decryptPrivate($data);
}
}
}
/**
* Signs the data (string) using the extension assigned to the type in the constructor.
*
* @param string $data
* @return mixed|string
*/
public function signData($data)
{
switch ($this->cryptParams['library']) {
case 'openssl':
return $this->signOpenSSL($data);
case (self::HMAC_SHA1):
return hash_hmac("sha1", $data, $this->key, true);
}
}
/**
* Verifies the data (string) against the given signature using the extension assigned to the type in the constructor.
*
* Returns in case of openSSL:
* 1 on succesful signature verification,
* 0 when signature verification failed,
* -1 if an error occurred during processing.
*
* NOTE: be very careful when checking the return value, because in PHP,
* -1 will be cast to True when in boolean context. So always check the
* return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
*
* @param string $data
* @param string $signature
* @return bool|int
*/
public function verifySignature($data, $signature)
{
switch ($this->cryptParams['library']) {
case 'openssl':
return $this->verifyOpenSSL($data, $signature);
case (self::HMAC_SHA1):
$expectedSignature = hash_hmac("sha1", $data, $this->key, true);
return strcmp($signature, $expectedSignature) == 0;
}
}
/**
* @deprecated
* @see getAlgorithm()
* @return mixed
*/
public function getAlgorith()
{
return $this->getAlgorithm();
}
/**
* @return mixed
*/
public function getAlgorithm()
{
return $this->cryptParams['method'];
}
/**
*
* @param int $type
* @param string $string
* @return null|string
*/
public static function makeAsnSegment($type, $string)
{
switch ($type) {
case 0x02:
if (ord($string) > 0x7f)
$string = chr(0).$string;
break;
case 0x03:
$string = chr(0).$string;
break;
}
$length = strlen($string);
if ($length < 128) {
$output = sprintf("%c%c%s", $type, $length, $string);
} else if ($length < 0x0100) {
$output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
} else if ($length < 0x010000) {
$output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
} else {
$output = null;
}
return $output;
}
/**
*
* Hint: Modulus and Exponent must already be base64 decoded
* @param string $modulus
* @param string $exponent
* @return string
*/
public static function convertRSA($modulus, $exponent)
{
/* make an ASN publicKeyInfo */
$exponentEncoding = self::makeAsnSegment(0x02, $exponent);
$modulusEncoding = self::makeAsnSegment(0x02, $modulus);
$sequenceEncoding = self::makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
$bitstringEncoding = self::makeAsnSegment(0x03, $sequenceEncoding);
$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
$publicKeyInfo = self::makeAsnSegment(0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
/* encode the publicKeyInfo in base64 and add PEM brackets */
$publicKeyInfoBase64 = base64_encode($publicKeyInfo);
$encoding = "-----BEGIN PUBLIC KEY-----\n";
$offset = 0;
while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
$encoding = $encoding.$segment."\n";
$offset += 64;
}
return $encoding."-----END PUBLIC KEY-----\n";
}
/**
* @param mixed $parent
*/
public function serializeKey($parent)
{
}
/**
* Retrieve the X509 certificate this key represents.
*
* Will return the X509 certificate in PEM-format if this key represents
* an X509 certificate.
*
* @return string The X509 certificate or null if this key doesn't represent an X509-certificate.
*/
public function getX509Certificate()
{
return $this->x509Certificate;
}
/**
* Get the thumbprint of this X509 certificate.
*
* Returns:
* The thumbprint as a lowercase 40-character hexadecimal number, or null
* if this isn't a X509 certificate.
*
* @return string Lowercase 40-character hexadecimal number of thumbprint
*/
public function getX509Thumbprint()
{
return $this->X509Thumbprint;
}
/**
* Create key from an EncryptedKey-element.
*
* @param DOMElement $element The EncryptedKey-element.
* @return MoXMLSecurityKey The new key.
* @throws Exception
*
*/
public static function fromEncryptedKeyElement(DOMElement $element)
{
$objenc = new MoXMLSecEnc();
$objenc->setNode($element);
if (! $objKey = $objenc->locateKey()) {
throw new Exception("Unable to locate algorithm for this Encrypted Key");
}
$objKey->isEncrypted = true;
$objKey->encryptedCtx = $objenc;
MoXMLSecEnc::staticLocateKeyInfo($objKey, $element);
return $objKey;
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace RobRichards\XMLSecLibs\Utils;
class MoXPath
{
const ALPHANUMERIC = '\w\d';
const NUMERIC = '\d';
const LETTERS = '\w';
const EXTENDED_ALPHANUMERIC = '\w\d\s\-_:\.';
const SINGLE_QUOTE = '\'';
const DOUBLE_QUOTE = '"';
const ALL_QUOTES = '[\'"]';
/**
* Filter an attribute value for save inclusion in an XPath query.
*
* @param string $value The value to filter.
* @param string $quotes The quotes used to delimit the value in the XPath query.
*
* @return string The filtered attribute value.
*/
public static function filterAttrValue($value, $quotes = self::ALL_QUOTES)
{
return preg_replace('#'.$quotes.'#', '', $value);
}
/**
* Filter an attribute name for save inclusion in an XPath query.
*
* @param string $name The attribute name to filter.
* @param mixed $allow The set of characters to allow. Can be one of the constants provided by this class, or a
* custom regex excluding the '#' character (used as delimiter).
*
* @return string The filtered attribute name.
*/
public static function filterAttrName($name, $allow = self::EXTENDED_ALPHANUMERIC)
{
return preg_replace('#[^'.$allow.']#', '', $name);
}
}

View File

@@ -0,0 +1,830 @@
<?php
/**
* This file is part of miniOrange SAML plugin.
*
* miniOrange SAML plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* miniOrange SAML plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with miniOrange SAML plugin. If not, see <http://www.gnu.org/licenses/>.
*/
include_once 'xmlseclibs.php';
use \RobRichards\XMLSecLibs\MoXMLSecurityKey;
use \RobRichards\XMLSecLibs\MoXMLSecurityDSig;
use \RobRichards\XMLSecLibs\MoXMLSecEnc;
class Utilities {
public static function generateID() {
return '_' . self::stringToHex(self::generateRandomBytes(21));
}
public static function stringToHex($bytes) {
$ret = '';
for($i = 0; $i < strlen($bytes); $i++) {
$ret .= sprintf('%02x', ord($bytes[$i]));
}
return $ret;
}
public static function generateRandomBytes($length, $fallback = TRUE) {
return openssl_random_pseudo_bytes($length);
}
public static function createAuthnRequest($acsUrl, $issuer, $force_authn = 'false') {
$requestXmlStr = '<?xml version="1.0" encoding="UTF-8"?>' .
'<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="' . self::generateID() .
'" Version="2.0" IssueInstant="' . self::generateTimestamp() . '"';
if( $force_authn == 'true') {
$requestXmlStr .= ' ForceAuthn="true"';
}
$requestXmlStr .= ' ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="' . $acsUrl .
'" ><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer></samlp:AuthnRequest>';
$deflatedStr = gzdeflate($requestXmlStr);
$base64EncodedStr = base64_encode($deflatedStr);
$urlEncoded = urlencode($base64EncodedStr);
update_option('MO_SAML_REQUEST',$base64EncodedStr);
return $urlEncoded;
}
public static function createSAMLRequest($acsUrl, $issuer, $destination, $force_authn = 'false') {
$requestXmlStr = '<?xml version="1.0" encoding="UTF-8"?>' .
'<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="' . self::generateID() .
'" Version="2.0" IssueInstant="' . self::generateTimestamp() . '"';
if( $force_authn == 'true') {
$requestXmlStr .= ' ForceAuthn="true"';
}
$requestXmlStr .= ' ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="' . $acsUrl .
'" Destination="' . htmlspecialchars($destination) . '"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer><samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
/></samlp:AuthnRequest>';
$samlRequest = base64_encode($requestXmlStr);
update_option('MO_SAML_REQUEST',$samlRequest);
return $requestXmlStr;
}
public static function generateTimestamp($instant = NULL) {
if($instant === NULL) {
$instant = time();
}
return gmdate('Y-m-d\TH:i:s\Z', $instant);
}
public static function xpQuery(DOMNode $node, $query)
{
static $xpCache = NULL;
if ($node instanceof DOMDocument) {
$doc = $node;
} else {
$doc = $node->ownerDocument;
}
if ($xpCache === NULL || !$xpCache->document->isSameNode($doc)) {
$xpCache = new DOMXPath($doc);
$xpCache->registerNamespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/');
$xpCache->registerNamespace('saml_protocol', 'urn:oasis:names:tc:SAML:2.0:protocol');
$xpCache->registerNamespace('saml_assertion', 'urn:oasis:names:tc:SAML:2.0:assertion');
$xpCache->registerNamespace('saml_metadata', 'urn:oasis:names:tc:SAML:2.0:metadata');
$xpCache->registerNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#');
$xpCache->registerNamespace('xenc', 'http://www.w3.org/2001/04/xmlenc#');
}
$results = $xpCache->query($query, $node);
$ret = array();
for ($i = 0; $i < $results->length; $i++) {
$ret[$i] = $results->item($i);
}
return $ret;
}
public static function parseNameId(DOMElement $xml)
{
$ret = array('Value' => trim($xml->textContent));
foreach (array('NameQualifier', 'SPNameQualifier', 'Format') as $attr) {
if ($xml->hasAttribute($attr)) {
$ret[$attr] = $xml->getAttribute($attr);
}
}
return $ret;
}
public static function xsDateTimeToTimestamp($time)
{
$matches = array();
// We use a very strict regex to parse the timestamp.
$regex = '/^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(?:\\.\\d+)?Z$/D';
if (preg_match($regex, $time, $matches) == 0) {
echo sprintf("Invalid SAML2 timestamp passed to xsDateTimeToTimestamp: ". htmlspecialchars($time));
exit;
}
// Extract the different components of the time from the matches in the regex.
// intval will ignore leading zeroes in the string.
$year = intval($matches[1]);
$month = intval($matches[2]);
$day = intval($matches[3]);
$hour = intval($matches[4]);
$minute = intval($matches[5]);
$second = intval($matches[6]);
// We use gmmktime because the timestamp will always be given
//in UTC.
$ts = gmmktime($hour, $minute, $second, $month, $day, $year);
return $ts;
}
public static function extractStrings(DOMElement $parent, $namespaceURI, $localName)
{
$ret = array();
for ($node = $parent->firstChild; $node !== NULL; $node = $node->nextSibling) {
if ($node->namespaceURI !== $namespaceURI || $node->localName !== $localName) {
continue;
}
$ret[] = trim($node->textContent);
}
return $ret;
}
public static function validateElement(DOMElement $root)
{
//$data = $root->ownerDocument->saveXML($root);
//echo htmlspecialchars($data);
/* Create an XML security object. */
$objXMLSecDSig = new MoXMLSecurityDSig();
/* Both SAML messages and SAML assertions use the 'ID' attribute. */
$objXMLSecDSig->idKeys[] = 'ID';
/* Locate the XMLDSig Signature element to be used. */
$signatureElement = self::xpQuery($root, './ds:Signature');
//print_r($signatureElement);
if (count($signatureElement) === 0) {
/* We don't have a signature element to validate. */
return FALSE;
} elseif (count($signatureElement) > 1) {
echo sprintf("XMLSec: more than one signature element in root.");
exit;
}/* elseif ((in_array('Response', $signatureElement) && $ocurrence['Response'] > 1) ||
(in_array('Assertion', $signatureElement) && $ocurrence['Assertion'] > 1) ||
!in_array('Response', $signatureElement) && !in_array('Assertion', $signatureElement)
) {
return false;
} */
$signatureElement = $signatureElement[0];
$objXMLSecDSig->sigNode = $signatureElement;
/* Canonicalize the XMLDSig SignedInfo element in the message. */
$objXMLSecDSig->canonicalizeSignedInfo();
/* Validate referenced xml nodes. */
if (!$objXMLSecDSig->validateReference()) {
echo sprintf("XMLSec: digest validation failed");
exit;
}
/* Check that $root is one of the signed nodes. */
$rootSigned = FALSE;
/** @var DOMNode $signedNode */
foreach ($objXMLSecDSig->getValidatedNodes() as $signedNode) {
if ($signedNode->isSameNode($root)) {
$rootSigned = TRUE;
break;
} elseif ($root->parentNode instanceof DOMDocument && $signedNode->isSameNode($root->ownerDocument)) {
/* $root is the root element of a signed document. */
$rootSigned = TRUE;
break;
}
}
if (!$rootSigned) {
echo sprintf("XMLSec: The root element is not signed.");
exit;
}
/* Now we extract all available X509 certificates in the signature element. */
$certificates = array();
foreach (self::xpQuery($signatureElement, './ds:KeyInfo/ds:X509Data/ds:X509Certificate') as $certNode) {
$certData = trim($certNode->textContent);
$certData = str_replace(array("\r", "\n", "\t", ' '), '', $certData);
$certificates[] = $certData;
//echo "CertDate: " . $certData . "<br />";
}
$ret = array(
'Signature' => $objXMLSecDSig,
'Certificates' => $certificates,
);
//echo "Signature validated";
return $ret;
}
public static function validateSignature(array $info, MoXMLSecurityKey $key)
{
/** @var MoXMLSecurityDSig $objXMLSecDSig */
$objXMLSecDSig = $info['Signature'];
$sigMethod = self::xpQuery($objXMLSecDSig->sigNode, './ds:SignedInfo/ds:SignatureMethod');
if (empty($sigMethod)) {
echo sprintf('Missing SignatureMethod element');
exit();
}
$sigMethod = $sigMethod[0];
if (!$sigMethod->hasAttribute('Algorithm')) {
echo sprintf('Missing Algorithm-attribute on SignatureMethod element.');
exit;
}
$algo = $sigMethod->getAttribute('Algorithm');
if ($key->type === MoXMLSecurityKey::RSA_SHA1 && $algo !== $key->type) {
$key = self::castKey($key, $algo);
}
/* Check the signature. */
if (! $objXMLSecDSig->verify($key)) {
echo sprintf('Unable to validate Signature');
exit;
}
}
public static function castKey(MoXMLSecurityKey $key, $algorithm, $type = 'public')
{
// do nothing if algorithm is already the type of the key
if ($key->type === $algorithm) {
return $key;
}
$keyInfo = openssl_pkey_get_details($key->key);
if ($keyInfo === FALSE) {
echo sprintf('Unable to get key details from XMLSecurityKey.');
exit;
}
if (!isset($keyInfo['key'])) {
echo sprintf('Missing key in public key details.');
exit;
}
$newKey = new MoXMLSecurityKey($algorithm, array('type'=>$type));
$newKey->loadKey($keyInfo['key']);
return $newKey;
}
public static function processResponse($currentURL, $certFingerprint, $signatureData,
SAML2_Response $response, $certNumber,$relayState) {
$assertion = current($response->getAssertions());
$notBefore = $assertion->getNotBefore();
if ($notBefore !== NULL && $notBefore > time() + 60) {
error_log('Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.');
return false;
}
$notOnOrAfter = $assertion->getNotOnOrAfter();
if ($notOnOrAfter !== NULL && $notOnOrAfter <= time() - 60) {
error_log('Received an assertion that has expired. Check clock synchronization on IdP and SP.');
return false;
}
$sessionNotOnOrAfter = $assertion->getSessionNotOnOrAfter();
if ($sessionNotOnOrAfter !== NULL && $sessionNotOnOrAfter <= time() - 60) {
error_log('Received an assertion with a session that has expired. Check clock synchronization on IdP and SP.');
return false;
}
/* Validate Response-element destination. */
$msgDestination = $response->getDestination();
if(substr($msgDestination, -1) == '/') {
$msgDestination = substr($msgDestination, 0, -1);
}
if(substr($currentURL, -1) == '/') {
$currentURL = substr($currentURL, 0, -1);
}
if ($msgDestination !== NULL && $msgDestination !== $currentURL) {
echo sprintf('Destination in response doesn\'t match the current URL. Destination is "' .
htmlspecialchars($msgDestination) . '", current URL is "' . htmlspecialchars($currentURL) . '".');
exit;
}
$responseSigned = self::checkSign($certFingerprint, $signatureData, $certNumber,$relayState);
if (!$responseSigned) {
error_log('SAML: Responses is not signed');
}
/* Returning boolean $responseSigned */
return $responseSigned;
}
public static function checkSign($certFingerprint, $signatureData, $certNumber, $relayState) {
$certificates = $signatureData['Certificates'];
error_log('SAML: certificate count = '.count($certificates));
if (count($certificates) === 0) {
$storedCerts = maybe_unserialize(get_option('saml_x509_certificate'));
$pemCert = $storedCerts[$certNumber];
}else{
$fpArray = array();
$fpArray[] = $certFingerprint;
$pemCert = self::findCertificate($fpArray, $certificates, $relayState);
if($pemCert==false)
return false;
}
$lastException = NULL;
$key = new MoXMLSecurityKey(MoXMLSecurityKey::RSA_SHA1, array('type'=>'public'));
$key->loadKey($pemCert);
try {
/*
* Make sure that we have a valid signature
*/
self::validateSignature($signatureData, $key);
return TRUE;
} catch (Exception $e) {
$lastException = $e;
}
/* We were unable to validate the signature with any of our keys. */
if ($lastException !== NULL) {
throw $lastException;
} else {
return FALSE;
}
}
public static function validateIssuerAndAudience($samlResponse, $spEntityId, $issuerToValidateAgainst, $relayState) {
$issuer = current($samlResponse->getAssertions())->getIssuer();
$assertion = current($samlResponse->getAssertions());
$audiences = $assertion->getValidAudiences();
if(strcmp($issuerToValidateAgainst, $issuer) === 0) {
if(!empty($audiences)) {
if(in_array($spEntityId, $audiences, TRUE)) {
return TRUE;
} else {
if($relayState=='testValidate'){
$Error_message=mo_saml_options_error_constants::Error_invalid_audience;
$Cause_message = mo_saml_options_error_constants::Cause_invalid_audience;
echo '<div style="font-family:Calibri;padding:0 3%;">';
echo '<div style="color: #a94442;background-color: #f2dede;padding: 15px;margin-bottom: 20px;text-align:center;border:1px solid #E6B3B2;font-size:18pt;"> ' . __('ERROR','miniorange-saml-20-single-sign-on') . '</div>
<div style="color: #a94442;font-size:14pt; margin-bottom:20px;"><p><strong>' . __('Error','miniorange-saml-20-single-sign-on') . ': </strong>'.$Error_message.'</p>
<p><strong>' . __('Possible Cause','miniorange-saml-20-single-sign-on'). ': </strong>'.$Cause_message.'</p>
<p>' . __('Expected one of the Audiences to be','miniorange-saml-20-single-sign-on'). ': '.$spEntityId.'<p>
</div>';
mo_saml_download_logs($Error_message,$Cause_message);
exit;
}
else
{
wp_die(__("We could not sign you in. Please contact your administrator",'miniorange-saml-20-single-sign-on'),"Error: Invalid Audience URI");
}
}
}
} else {
if($relayState=='testValidate'){
$Error_message=mo_saml_options_error_constants::Error_issuer_not_verfied;
$Cause_message = mo_saml_options_error_constants::Cause_issuer_not_verfied;
update_option('mo_saml_required_issuer',$issuer);
echo '<div style="font-family:Calibri;padding:0 3%;">';
echo '<div style="color: #a94442;background-color: #f2dede;padding: 15px;margin-bottom: 20px;text-align:center;border:1px solid #E6B3B2;font-size:18pt;">' . __('ERROR','miniorange-saml-20-single-sign-on') . '</div>
<div style="color: #a94442;font-size:14pt; margin-bottom:20px;text-align: justify"><p><strong>' . __('Error','miniorange-saml-20-single-sign-on'). ':'.$Error_message.' </strong></p>
<p><strong>' . __('Possible Cause','miniorange-saml-20-single-sign-on') . ':'.$Cause_message.' </strong></p>
<div>
<ol style="text-align: center">
<form method="post" action="" name="mo_fix_entityid" id="mo_fix_certificate">';
wp_nonce_field('mo_fix_entity_id');
echo '<input type="hidden" name="option" value="mo_fix_entity_id" />
<input type="submit" class="miniorange-button" style="width: 55%" value="' . __('Fix Issue','miniorange-saml-20-single-sign-on' ) .'">
</form>
</ol>
</div>
</div>
</div>';
mo_saml_download_logs($Error_message,$Cause_message);
exit;
}
else
{
wp_die(__("We could not sign you in. Please contact your administrator",'miniorange-saml-20-single-sign-on'),"Error: Issuer cannot be verified");
}
}
}
private static function findCertificate(array $certFingerprints, array $certificates, $relayState) {
$candidates = array();
//foreach ($certificates as $cert) {
$fp = strtolower(sha1(base64_decode($certificates[0])));
if (!in_array($fp, $certFingerprints, TRUE)) {
$candidates[] = $fp;
return false;
//continue;
}
/* We have found a matching fingerprint. */
$pem = "-----BEGIN CERTIFICATE-----\n" .
chunk_split($certificates[0], 64) .
"-----END CERTIFICATE-----\n";
return $pem;
// }
// if($relayState=='testValidate'){
// $pem = "-----BEGIN CERTIFICATE-----<br>" .
// chunk_split($cert, 64) .
// "<br>-----END CERTIFICATE-----";
// echo '<div style="font-family:Calibri;padding:0 3%;">';
// echo '<div style="color: #a94442;background-color: #f2dede;padding: 15px;margin-bottom: 20px;text-align:center;border:1px solid #E6B3B2;font-size:18pt;"> ERROR</div>
// <div style="color: #a94442;font-size:14pt; margin-bottom:20px;"><p><strong>Error: </strong>Unable to find a certificate matching the configured fingerprint.</p>
// <p>Please contact your administrator and report the following error:</p>
// <p><strong>Possible Cause: </strong>Content of \'X.509 Certificate\' field in Service Provider Settings is incorrect. Please replace it with certificate given below.</p>
// <p><strong>Certificate found in SAML Response: </strong><br><br>'.$pem.'</p>
// </div>
// <div style="margin:3%;display:block;text-align:center;">
// <form action="index.php">
// <div style="margin:3%;display:block;text-align:center;"><input style="padding:1%;width:100px;background: #0091CD none repeat scroll 0% 0%;cursor: pointer;font-size:15px;border-width: 1px;border-style: solid;border-radius: 3px;white-space: nowrap;box-sizing: border-box;border-color: #0073AA;box-shadow: 0px 1px 0px rgba(120, 200, 230, 0.6) inset;color: #FFF;"type="button" value="Done" onClick="self.close();"></div>';
// exit;
// }
// else{
// wp_die("We could not sign you in. Please contact your administrator","Error: Invalid Certificate");
// }
}
/**
* Decrypt an encrypted element.
*
* This is an internal helper function.
*
* @param DOMElement $encryptedData The encrypted data.
* @param MoXMLSecurityKey $inputKey The decryption key.
* @param array &$blacklist Blacklisted decryption algorithms.
* @return DOMElement The decrypted element.
* @throws Exception
*/
private static function doDecryptElement(DOMElement $encryptedData, MoXMLSecurityKey $inputKey, array &$blacklist)
{
$enc = new MoXMLSecEnc();
$enc->setNode($encryptedData);
$enc->type = $encryptedData->getAttribute("Type");
$symmetricKey = $enc->locateKey($encryptedData);
if (!$symmetricKey) {
echo sprintf(__('Could not locate key algorithm in encrypted data.','miniorange-saml-20-single-sign-on'));
exit;
}
$symmetricKeyInfo = $enc->locateKeyInfo($symmetricKey);
if (!$symmetricKeyInfo) {
echo sprintf(__('Could not locate <dsig:KeyInfo> for the encrypted key.','miniorange-saml-20-single-sign-on'));
exit;
}
$inputKeyAlgo = $inputKey->getAlgorith();
if ($symmetricKeyInfo->isEncrypted) {
$symKeyInfoAlgo = $symmetricKeyInfo->getAlgorith();
if (in_array($symKeyInfoAlgo, $blacklist, TRUE)) {
echo sprintf('Algorithm disabled: ' . var_export($symKeyInfoAlgo, TRUE));
exit;
}
if ($symKeyInfoAlgo === MoXMLSecurityKey::RSA_OAEP_MGF1P && $inputKeyAlgo === MoXMLSecurityKey::RSA_1_5) {
/*
* The RSA key formats are equal, so loading an RSA_1_5 key
* into an RSA_OAEP_MGF1P key can be done without problems.
* We therefore pretend that the input key is an
* RSA_OAEP_MGF1P key.
*/
$inputKeyAlgo = MoXMLSecurityKey::RSA_OAEP_MGF1P;
}
/* Make sure that the input key format is the same as the one used to encrypt the key. */
if ($inputKeyAlgo !== $symKeyInfoAlgo) {
echo sprintf( 'Algorithm mismatch between input key and key used to encrypt ' .
' the symmetric key for the message. Key was: ' .
var_export($inputKeyAlgo, TRUE) . '; message was: ' .
var_export($symKeyInfoAlgo, TRUE));
exit;
}
/** @var MoXMLSecEnc $encKey */
$encKey = $symmetricKeyInfo->encryptedCtx;
$symmetricKeyInfo->key = $inputKey->key;
$keySize = $symmetricKey->getSymmetricKeySize();
if ($keySize === NULL) {
/* To protect against "key oracle" attacks, we need to be able to create a
* symmetric key, and for that we need to know the key size.
*/
echo sprintf('Unknown key size for encryption algorithm: ' . var_export($symmetricKey->type, TRUE));
exit;
}
try {
$key = $encKey->decryptKey($symmetricKeyInfo);
if (strlen($key) != $keySize) {
echo sprintf('Unexpected key size (' . strlen($key) * 8 . 'bits) for encryption algorithm: ' .
var_export($symmetricKey->type, TRUE));
exit;
}
} catch (Exception $e) {
/* We failed to decrypt this key. Log it, and substitute a "random" key. */
/* Create a replacement key, so that it looks like we fail in the same way as if the key was correctly padded. */
/* We base the symmetric key on the encrypted key and private key, so that we always behave the
* same way for a given input key.
*/
$encryptedKey = $encKey->getCipherValue();
$pkey = openssl_pkey_get_details($symmetricKeyInfo->key);
$pkey = sha1(serialize($pkey), TRUE);
$key = sha1($encryptedKey . $pkey, TRUE);
/* Make sure that the key has the correct length. */
if (strlen($key) > $keySize) {
$key = substr($key, 0, $keySize);
} elseif (strlen($key) < $keySize) {
$key = str_pad($key, $keySize);
}
}
$symmetricKey->loadkey($key);
} else {
$symKeyAlgo = $symmetricKey->getAlgorith();
/* Make sure that the input key has the correct format. */
if ($inputKeyAlgo !== $symKeyAlgo) {
echo sprintf( 'Algorithm mismatch between input key and key in message. ' .
'Key was: ' . var_export($inputKeyAlgo, TRUE) . '; message was: ' .
var_export($symKeyAlgo, TRUE));
exit;
}
$symmetricKey = $inputKey;
}
$algorithm = $symmetricKey->getAlgorith();
if (in_array($algorithm, $blacklist, TRUE)) {
echo sprintf('Algorithm disabled: ' . var_export($algorithm, TRUE));
exit;
}
/** @var string $decrypted */
$decrypted = $enc->decryptNode($symmetricKey, FALSE);
/*
* This is a workaround for the case where only a subset of the XML
* tree was serialized for encryption. In that case, we may miss the
* namespaces needed to parse the XML.
*/
$xml = '<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" '.
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' .
$decrypted .
'</root>';
$newDoc = new DOMDocument();
if (!@$newDoc->loadXML($xml)) {
echo sprintf('Failed to parse decrypted XML. Maybe the wrong sharedkey was used?');
throw new Exception('Failed to parse decrypted XML. Maybe the wrong sharedkey was used?');
}
$decryptedElement = $newDoc->firstChild->firstChild;
if ($decryptedElement === NULL) {
echo sprintf('Missing encrypted element.');
throw new Exception('Missing encrypted element.');
}
if (!($decryptedElement instanceof DOMElement)) {
echo sprintf('Decrypted element was not actually a DOMElement.');
}
return $decryptedElement;
}
/**
* Decrypt an encrypted element.
*
* @param DOMElement $encryptedData The encrypted data.
* @param MoXMLSecurityKey $inputKey The decryption key.
* @param array $blacklist Blacklisted decryption algorithms.
* @return DOMElement The decrypted element.
* @throws Exception
*/
public static function decryptElement(DOMElement $encryptedData, MoXMLSecurityKey $inputKey, array $blacklist = array(), MoXMLSecurityKey $alternateKey = NULL)
{
try {
return self::doDecryptElement($encryptedData, $inputKey, $blacklist);
} catch (Exception $e) {
//Try with alternate key
try {
return self::doDecryptElement($encryptedData, $alternateKey, $blacklist);
} catch(Exception $t) {
}
/*
* Something went wrong during decryption, but for security
* reasons we cannot tell the user what failed.
*/
//print_r($e->getMessage());
echo sprintf('Failed to decrypt XML element.');
exit;
}
}
/**
* Generates the metadata of the SP based on the settings
*
* @param string $sp The SP data
* @param string $authnsign authnRequestsSigned attribute
* @param string $wsign wantAssertionsSigned attribute
* @param DateTime $validUntil Metadata's valid time
* @param Timestamp $cacheDuration Duration of the cache in seconds
* @param array $contacts Contacts info
* @param array $organization Organization ingo
*
* @return string SAML Metadata XML
*/
public static function metadata_builder($siteUrl)
{
$xml = new DOMDocument();
$url = plugins_url().'/miniorange-saml-20-single-sign-on/sp-metadata.xml';
$xml->load($url);
$xpath = new DOMXPath($xml);
$elements = $xpath->query('//md:EntityDescriptor[@entityID="http://{path-to-your-site}/wp-content/plugins/miniorange-saml-20-single-sign-on/"]');
if ($elements->length >= 1) {
$element = $elements->item(0);
$element->setAttribute('entityID', $siteUrl.'/wp-content/plugins/miniorange-saml-20-single-sign-on/');
}
$elements = $xpath->query('//md:AssertionConsumerService[@Location="http://{path-to-your-site}"]');
if ($elements->length >= 1) {
$element = $elements->item(0);
$element->setAttribute('Location', $siteUrl.'/');
}
//re-save
$xml->save(plugins_url()."/miniorange-saml-20-single-sign-on/sp-metadata.xml");
}
public static function get_mapped_groups($saml_params, $saml_groups)
{
$groups = array();
if (!empty($saml_groups)) {
$saml_mapped_groups = array();
$i=1;
while ($i < 10) {
$saml_mapped_groups_value = $saml_params->get('group'.$i.'_map');
$saml_mapped_groups[$i] = explode(';', $saml_mapped_groups_value);
$i++;
}
}
foreach ($saml_groups as $saml_group) {
if (!empty($saml_group)) {
$i = 0;
$found = false;
while ($i < 9 && !$found) {
if (!empty($saml_mapped_groups[$i]) && in_array($saml_group, $saml_mapped_groups[$i], TRUE)) {
$groups[] = $saml_params->get('group'.$i);
$found = true;
}
$i++;
}
}
}
return array_unique($groups);
}
public static function getEncryptionAlgorithm($method){
switch($method){
case 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc':
return MoXMLSecurityKey::TRIPLEDES_CBC;
break;
case 'http://www.w3.org/2001/04/xmlenc#aes128-cbc':
return MoXMLSecurityKey::AES128_CBC;
case 'http://www.w3.org/2001/04/xmlenc#aes192-cbc':
return MoXMLSecurityKey::AES192_CBC;
break;
case 'http://www.w3.org/2001/04/xmlenc#aes256-cbc':
return MoXMLSecurityKey::AES256_CBC;
break;
case 'http://www.w3.org/2001/04/xmlenc#rsa-1_5':
return MoXMLSecurityKey::RSA_1_5;
break;
case 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p':
return MoXMLSecurityKey::RSA_OAEP_MGF1P;
break;
case 'http://www.w3.org/2000/09/xmldsig#dsa-sha1':
return MoXMLSecurityKey::DSA_SHA1;
break;
case 'http://www.w3.org/2000/09/xmldsig#rsa-sha1':
return MoXMLSecurityKey::RSA_SHA1;
break;
case 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256':
return MoXMLSecurityKey::RSA_SHA256;
break;
case 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384':
return MoXMLSecurityKey::RSA_SHA384;
break;
case 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512':
return MoXMLSecurityKey::RSA_SHA512;
break;
default:
echo sprintf('Invalid Encryption Method: '. htmlspecialchars($method));
exit;
break;
}
}
public static function sanitize_certificate( $certificate ) {
$certificate = preg_replace("/[\r\n]+/", "", $certificate);
$certificate = str_replace( "-", "", $certificate );
$certificate = str_replace( "BEGIN CERTIFICATE", "", $certificate );
$certificate = str_replace( "END CERTIFICATE", "", $certificate );
$certificate = str_replace( " ", "", $certificate );
$certificate = chunk_split($certificate, 64, "\r\n");
$certificate = "-----BEGIN CERTIFICATE-----\r\n" . $certificate . "-----END CERTIFICATE-----";
return $certificate;
}
public static function desanitize_certificate( $certificate ) {
$certificate = preg_replace("/[\r\n]+/", "", $certificate);
//$certificate = str_replace( "-", "", $certificate );
$certificate = str_replace( "-----BEGIN CERTIFICATE-----", "", $certificate );
$certificate = str_replace( "-----END CERTIFICATE-----", "", $certificate );
$certificate = str_replace( " ", "", $certificate );
//$certificate = chunk_split($certificate, 64, "\r\n");
//$certificate = "-----BEGIN CERTIFICATE-----\r\n" . $certificate . "-----END CERTIFICATE-----";
return $certificate;
}
public static function mo_saml_wp_remote_post($url, $args = array()){
$response = wp_remote_post($url, $args);
if(!is_wp_error($response)){
return $response;
} else {
$show_message = new saml_mo_login();
update_option('mo_saml_message', __('Unable to connect to the Internet. Please try again.','miniorange-saml-20-single-sign-on'));
$show_message->mo_saml_show_error_message();
}
}
public static function mo_saml_wp_remote_get($url, $args = array()){
$response = wp_remote_get($url, $args);
if(!is_wp_error($response)){
return $response;
} else {
$show_message = new saml_mo_login();
update_option('mo_saml_message', __('Unable to connect to the Internet. Please try again.','miniorange-saml-20-single-sign-on'));
$show_message->mo_saml_show_error_message();
}
}
}
?>

View File

@@ -0,0 +1,44 @@
<?php
/**
* @package miniOrange
* @author miniOrange Security Software Pvt. Ltd.
* @license GNU/GPLv3
* @copyright Copyright 2015 miniOrange. All Rights Reserved.
*
*
* This file is part of miniOrange SAML plugin.
*/
class AESEncryption {
/**
* @param string $data - the key=value pairs separated with &
* @return string
*/
public static function encrypt_data($data, $key) {
$key = openssl_digest($key, 'sha256');
$method = 'AES-128-ECB';
$ivSize = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($ivSize);
$strCrypt = openssl_encrypt ($data, $method, $key,OPENSSL_RAW_DATA||OPENSSL_ZERO_PADDING, $iv);
return base64_encode($iv.$strCrypt);
}
/**
* @param string $data - crypt response from Sagepay
* @return string
*/
public static function decrypt_data($data, $key) {
$strIn = base64_decode($data);
$key = openssl_digest($key, 'sha256');
$method = 'AES-128-ECB';
$ivSize = openssl_cipher_iv_length($method);
$iv = substr($strIn,0,$ivSize);
$data = substr($strIn,$ivSize);
$clear = openssl_decrypt ($data, $method, $key, OPENSSL_RAW_DATA||OPENSSL_ZERO_PADDING, $iv);
return $clear;
}
}
?>

View File

@@ -0,0 +1,640 @@
<?php
include "MoSAMLBasicEnum.php";
class mo_saml_options_enum_sso_loginMoSAML extends MoSAMLBasicEnum {
const Relay_state = 'mo_saml_relay_state';
const Redirect_Idp = 'mo_saml_registered_only_access';
const Force_authentication = 'mo_saml_force_authentication';
const Enable_access_RSS = 'mo_saml_enable_rss_access';
const Auto_redirect = 'mo_saml_enable_login_redirect';
}
class mo_saml_options_enum_identity_providerMoSAML extends MoSAMLBasicEnum{
const Broker_service ='mo_saml_enable_cloud_broker';
const SP_Base_Url='mo_saml_sp_base_url';
const SP_Entity_ID = 'mo_saml_sp_entity_id';
}
class mo_saml_options_tab_names extends MoSAMLBasicEnum{
const Service_provider_settings = 'service-provider-setup';
const Identity_provider_settting = 'identity-provider-setup';
const Redirection_sso_links = 'redirection-sso-links';
const Entire_plugin_tour = 'entire-plugin-tour';
const Attribute_role_mapping = 'attribute-role-mapping';
}
class mo_saml_options_enum_pointersMoSAML extends MoSAMLBasicEnum{
public static
$DEFAULT = array(
'custom_admin_pointers4_8_52_default-miniorange-sp-metadata-url',
'custom_admin_pointers4_8_52_default-miniorange-select-your-idp',
'custom_admin_pointers4_8_52_default-miniorange-upload-metadata',
'custom_admin_pointers4_8_52_default-miniorange-test-configuration',
'custom_admin_pointers4_8_52_default-miniorange-attribute-mapping',
'custom_admin_pointers4_8_52_default-miniorange-role-mapping',
'custom_admin_pointers4_8_52_default-minorange-use-widget',
'custom_admin_pointers4_8_52_default-miniorange-addons',
'custom_admin_pointers4_8_52_default-miniorange-support-pointer'
);
public static $DEFAULT_SKIP = array(
'custom_admin_pointers4_8_52_default-miniorange-sp-metadata-url',
'custom_admin_pointers4_8_52_default-miniorange-select-your-idp',
'custom_admin_pointers4_8_52_default-miniorange-upload-metadata',
'custom_admin_pointers4_8_52_default-miniorange-test-configuration',
'custom_admin_pointers4_8_52_default-miniorange-attribute-mapping',
'custom_admin_pointers4_8_52_default-miniorange-role-mapping',
'custom_admin_pointers4_8_52_default-minorange-use-widget',
'custom_admin_pointers4_8_52_default-miniorange-addons',
);
public static $SERVICE_PROVIDER = array(
'custom_admin_pointers4_8_52_miniorange-select-your-idp',
'custom_admin_pointers4_8_52_miniorange-upload-metadata',
'custom_admin_pointers4_8_52_miniorange-test-configuration',
'custom_admin_pointers4_8_52_miniorange-import-config',
'custom_admin_pointers4_8_52_export-import-config',
'custom_admin_pointers4_8_52_configure-service-restart-tour');
public static $IDENTITY_PROVIDER = array(
'custom_admin_pointers4_8_52_metadata_manual',
'custom_admin_pointers4_8_52_miniorange-sp-metadata-url',
'custom_admin_pointers4_8_52_identity-provider-restart-tour'
);
public static $ATTRIBUTE_MAPPING = array(
'custom_admin_pointers4_8_52_miniorange-attribute-mapping',
'custom_admin_pointers4_8_52_miniorange-role-mapping',
'custom_admin_pointers4_8_52_attribute-mapping-restart-tour');
public static $REDIRECTION_LINK = array(
'custom_admin_pointers4_8_52_minorange-use-widget',
'custom_admin_pointers4_8_52_miniorange-auto-redirect',
'custom_admin_pointers4_8_52_miniorange-auto-redirect-login-page',
'custom_admin_pointers4_8_52_miniorange-short-code',
'custom_admin_pointers4_8_52_miniorange-redirection-sso-restart-tour'
);
}
class mo_saml_options_enum_service_providerMoSAML extends MoSAMLBasicEnum{
const Identity_name ='saml_identity_name';
const Login_binding_type='saml_login_binding_type';
const Login_URL = 'saml_login_url';
const Logout_binding_type = 'saml_logout_binding_type';
const Logout_URL = 'saml_logout_url';
const Issuer = 'saml_issuer';
const X509_certificate = 'saml_x509_certificate';
const Request_signed = 'saml_request_signed';
const Guide_name = 'saml_identity_provider_guide_name';
const Is_encoding_enabled = 'mo_saml_encoding_enabled';
}
class mo_saml_options_test_configuration extends MoSAMLBasicEnum{
const SAML_REQUEST = 'MO_SAML_REQUEST';
const SAML_RESPONSE = 'MO_SAML_RESPONSE';
const TEST_CONFIG_ERROR_LOG = 'MO_SAML_TEST';
}
class mo_saml_options_enum_attribute_mappingMoSAML extends MoSAMLBasicEnum{
const Attribute_Username ='saml_am_username';
const Attribute_Email = 'saml_am_email';
const Attribute_First_name ='saml_am_first_name';
const Attribute_Last_name = 'saml_am_last_name';
const Attribute_Group_name ='saml_am_group_name';
const Attribute_Custom_mapping = 'mo_saml_custom_attrs_mapping';
const Attribute_Account_matcher = 'saml_am_account_matcher';
}
class mo_saml_options_enum_role_mappingMoSAML extends MoSAMLBasicEnum{
const Role_do_not_auto_create_users = 'mo_saml_dont_create_user_if_role_not_mapped';
const Role_do_not_assign_role_unlisted = 'saml_am_dont_allow_unlisted_user_role';
const Role_do_not_update_existing_user = 'saml_am_dont_update_existing_user_role';
const Role_default_role ='saml_am_default_user_role';
}
class mo_saml_options_error_constants extends MoSAMLBasicEnum{
const Error_no_certificate = "Unable to find a certificate .";
const Cause_no_certificate = "No signature found in SAML Response or Assertion. Please sign at least one of them.";
const Error_wrong_certificate = "Unable to find a certificate matching the configured fingerprint.";
const Cause_wrong_certificate = "X.509 Certificate field in plugin does not match the certificate found in SAML Response.";
const Error_invalid_audience = "Invalid Audience URI.";
const Cause_invalid_audience = "The value of 'Audience URI' field on Identity Provider's side is incorrect";
const Error_issuer_not_verfied = "Issuer cannot be verified.";
const Cause_issuer_not_verfied = "IdP Entity ID configured and the one found in SAML Response do not match";
}
class mo_saml_options_plugin_constants extends MoSAMLBasicEnum{
const CMS_Name = "WP";
const Application_Name = "WP miniOrange SAML 2.0 SSO Plugin";
const Application_type = "SAML";
const Version = "4.9.05";
const HOSTNAME = "https://login.xecurify.com";
}
class mo_saml_options_plugin_idp extends MoSAMLBasicEnum{
public static $IDP_GUIDES = array(
"Azure AD" => "azure-ad",
"Azure B2C" => "azure-b2c",
"ADFS" => "adfs",
"Okta" => "okta",
"SalesForce" => "salesforce",
"Google Apps" => "google-apps",
"OneLogin" => "onelogin",
"MiniOrange" => "miniorange",
"Keycloak" => "jboss-keycloak",
"AbsorbLMS" => "absorb-lms",
"Degreed" => "degreed",
"JumpCloud" => "jumpcloud",
"PingFederate" => "pingfederate",
"PingOne" => "pingone",
"Centrify" => "centrify",
"Oracle" => "oracle-enterprise-manager",
"Bitium" => "bitium",
"Shibboleth 2" => "shibboleth2",
"Shibboleth 3" => "shibboleth3",
"Gluu Server" => "gluu-server",
"SimpleSAMLphp" => "simplesaml",
"OpenAM" => "openam",
"Authanvil"=>"authanvil",
"Auth0"=>"auth0",
"CA Identity"=>"ca-identity",
"WSO2"=>"wso2",
"RSA SecureID"=>"rsa-secureid",
"Custom IDP"=>"custom-idp"
);
}
class mo_saml_options_plugin_idp_videos extends MoSAMLBasicEnum{
public static $IDP_VIDEOS = array(
"azure-ad"=> "eHen4aiflFU",
"azure-b2c"=> "",
"adfs"=> "rLBHbRbrY5E",
"okta"=> "YHE8iYojUqM",
"salesforce"=> "LRQrmgr255Q",
"google-apps"=> "5BwzEjgZiu4",
"onelogin"=> "_Hsot_RG9YY",
"miniorange"=> "eamf9s6JpbA",
"jboss-keycloak"=> "Io6x1fTNWHI",
"absorb-lms"=> "",
"degreed"=> "",
"jumpcloud"=> "",
"pingfederate"=> "",
"pingone"=> "",
"centrify"=> "",
"oracle-enterprise-manager"=> "",
"bitium"=> "",
"shibboleth2"=> "",
"shibboleth3"=> "",
"gluu-server"=> "",
"simplesaml"=> "",
"openam"=> "",
"authanvil"=> "",
"auth0"=> "54pz6m5h9mk",
"ca-identity" => "",
"wso2" => "",
"rsa-secureid" => "",
"custom-idp" => "gilfhNFYsgc"
);
}
class mo_saml_options_addons extends MoSAMLBasicEnum{
public static $ADDON_URL = array(
'scim' => 'https://plugins.miniorange.com/wordpress-user-provisioning',
'page_restriction' => 'https://plugins.miniorange.com/wordpress-page-restriction',
'file_prevention' => 'https://plugins.miniorange.com/wordpress-media-restriction',
'ssologin' => 'https://plugins.miniorange.com/wordpress-sso-login-audit',
'buddypress' => 'https://plugins.miniorange.com/wordpress-buddypress-integrator',
'learndash' => 'https://plugins.miniorange.com/wordpress-learndash-integrator',
'attribute_based_redirection' => 'https://plugins.miniorange.com/wordpress-attribute-based-redirection-restriction',
'ssosession' => 'https://plugins.miniorange.com/sso-session-management',
'fsso' => 'https://plugins.miniorange.com/incommon-federation-single-sign-on-sso',
'paid_mem_pro' => 'https://plugins.miniorange.com/paid-membership-pro-integrator',
'memberpress' => 'https://plugins.miniorange.com/wordpress-memberpress-integrator',
'wp_members' => 'https://plugins.miniorange.com/wordpress-members-integrator',
'woocommerce' => 'https://plugins.miniorange.com/wordpress-woocommerce-integrator',
'guest_login' => 'https://plugins.miniorange.com/guest-user-login',
'profile_picture_add_on' => 'https://plugins.miniorange.com/wordpress-profile-picture-map'
);
public static $WP_ADDON_URL = array(
'page-restriction' => 'https://wordpress.org/plugins/page-and-post-restriction/embed/',
'scim-user-sync'=> 'https://wordpress.org/plugins/scim-user-provisioning/embed/'
);
public static $ADDON_TITLE = array(
'scim' => 'SCIM User Provisioning',
'page_restriction' => 'Page and Post Restriction',
'file_prevention' => 'Prevent File Access',
'ssologin' => 'SSO Login Audit',
'buddypress' => 'BuddyPress Integrator',
'learndash' => 'Learndash Integrator',
'attribute_based_redirection' => 'Attribute Based Redirection',
'ssosession' => 'SSO Session Management',
'fsso' => 'Federation Single Sign-On',
'memberpress' => 'MemberPress Integrator',
'wp_members' => 'WP-Members Integrator',
'woocommerce' => 'WooCommerce Integrator',
'guest_login' => 'Guest Login',
'profile_picture_add_on' => 'Profile Picture Add-on',
'paid_mem_pro' => 'PaidMembership Pro Integrator'
);
public static $RECOMMENDED_ADDONS_PATH = array(
"learndash" => "sfwd-lms/sfwd_lms.php",
"buddypress" => "buddypress/bp-loader.php",
"paid_mem_pro" => "paid-memberships-pro/paid-memberships-pro.php",
"memberpress" => "memberpress/memberpress.php",
"wp_members" => "wp-members/wp-members.php",
"woocommerce" => "woocommerce/woocommerce.php"
);
}
class mo_saml_license_plans extends MoSAMLBasicEnum {
public static $license_plans = array (
'standard' => 'WP SAML SSO Standard Plan',
'premium' => 'WP SAML SSO Premium Plan',
'enterprise' => 'WP SAML SSO Enterprise Plan',
'enterprise-multiple-idp' => 'WP SAML SSO Enterprise Multiple-IDP Plan',
'all-inclusive' => 'WP SAML SSO All Inclusive Plan',
'premium-multisite' => 'WP SAML SSO Premium Multisite Plan',
'enterprise-multisite' => 'WP SAML SSO Enterprise Multisite Plan',
'all-inclusive-multisite' => 'WP SAML SSO All Inclusive Multisite Plan',
'help' => 'Not Sure'
);
public static $license_plans_slug = array (
'standard' => '16.0.2@16.0.2',
'premium' => '12.0.2@12.0.2',
'enterprise' => '12.0.2@12.0.2',
'enterprise-multiple-idp' => '25.0.1@25.0.1',
'all-inclusive' => '25.0.1@25.0.1',
);
}
class mo_saml_time_zones extends MoSAMLBasicEnum {
public static $time_zones = array(
"(GMT-11:00) Niue Time" => "Pacific/Niue",
"(GMT-11:00) Samoa Standard Time" => "Pacific/Pago_Pago",
"(GMT-10:00) Cook Islands Standard Time" => "Pacific/Rarotonga",
"(GMT-10:00) Hawaii-Aleutian Standard Time" => "Pacific/Honolulu",
"(GMT-10:00) Tahiti Time" => "Pacific/Tahiti",
"(GMT-09:30) Marquesas Time" => "Pacific/Marquesas",
"(GMT-09:00) Gambier Time" => "Pacific/Gambier",
"(GMT-09:00) Hawaii-Aleutian Time (Adak)" => "America/Adak",
"(GMT-08:00) Alaska Time - Anchorage" => "America/Anchorage",
"(GMT-08:00) Alaska Time - Juneau" => "America/Juneau",
"(GMT-08:00) Alaska Time - Metlakatla" => "America/Metlakatla",
"(GMT-08:00) Alaska Time - Nome" => "America/Nome",
"(GMT-08:00) Alaska Time - Sitka" => "America/Sitka",
"(GMT-08:00) Alaska Time - Yakutat" => "America/Yakutat",
"(GMT-08:00) Pitcairn Time" => "Pacific/Pitcairn",
"(GMT-07:00) Mexican Pacific Standard Time" => "America/Hermosillo",
"(GMT-07:00) Mountain Standard Time - Creston" => "America/Creston",
"(GMT-07:00) Mountain Standard Time - Dawson" => "America/Dawson",
"(GMT-07:00) Mountain Standard Time - Dawson Creek" => "America/Dawson_Creek",
"(GMT-07:00) Mountain Standard Time - Fort Nelson" => "America/Fort_Nelson",
"(GMT-07:00) Mountain Standard Time - Phoenix" => "America/Phoenix",
"(GMT-07:00) Mountain Standard Time - Whitehorse" => "America/Whitehorse",
"(GMT-07:00) Pacific Time - Los Angeles" => "America/Los_Angeles",
"(GMT-07:00) Pacific Time - Tijuana" => "America/Tijuana",
"(GMT-07:00) Pacific Time - Vancouver" => "America/Vancouver",
"(GMT-06:00) Central Standard Time - Belize" => "America/Belize",
"(GMT-06:00) Central Standard Time - Costa Rica" => "America/Costa_Rica",
"(GMT-06:00) Central Standard Time - El Salvador" => "America/El_Salvador",
"(GMT-06:00) Central Standard Time - Guatemala" => "America/Guatemala",
"(GMT-06:00) Central Standard Time - Managua" => "America/Managua",
"(GMT-06:00) Central Standard Time - Regina" => "America/Regina",
"(GMT-06:00) Central Standard Time - Swift Current" => "America/Swift_Current",
"(GMT-06:00) Central Standard Time - Tegucigalpa" => "America/Tegucigalpa",
"(GMT-06:00) Easter Island Time" => "Pacific/Easter",
"(GMT-06:00) Galapagos Time" => "Pacific/Galapagos",
"(GMT-06:00) Mexican Pacific Time - Chihuahua" => "America/Chihuahua",
"(GMT-06:00) Mexican Pacific Time - Mazatlan" => "America/Mazatlan",
"(GMT-06:00) Mountain Time - Boise" => "America/Boise",
"(GMT-06:00) Mountain Time - Cambridge Bay" => "America/Cambridge_Bay",
"(GMT-06:00) Mountain Time - Denver" => "America/Denver",
"(GMT-06:00) Mountain Time - Edmonton" => "America/Edmonton",
"(GMT-06:00) Mountain Time - Inuvik" => "America/Inuvik",
"(GMT-06:00) Mountain Time - Ojinaga" => "America/Ojinaga",
"(GMT-06:00) Mountain Time - Yellowknife" => "America/Yellowknife",
"(GMT-05:00) Acre Standard Time - Eirunepe" => "America/Eirunepe",
"(GMT-05:00) Acre Standard Time - Rio Branco" => "America/Rio_Branco",
"(GMT-05:00) Central Time - Bahia Banderas" => "America/Bahia_Banderas",
"(GMT-05:00) Central Time - Beulah, North Dakota" => "America/North_Dakota/Beulah",
"(GMT-05:00) Central Time - Center, North Dakota" => "America/North_Dakota/Center",
"(GMT-05:00) Central Time - Chicago" => "America/Chicago",
"(GMT-05:00) Central Time - Knox, Indiana" => "America/Indiana/Knox",
"(GMT-05:00) Central Time - Matamoros" => "America/Matamoros",
"(GMT-05:00) Central Time - Menominee" => "America/Menominee",
"(GMT-05:00) Central Time - Merida" => "America/Merida",
"(GMT-05:00) Central Time - Mexico City" => "America/Mexico_City",
"(GMT-05:00) Central Time - Monterrey" => "America/Monterrey",
"(GMT-05:00) Central Time - New Salem, North Dakota" => "America/North_Dakota/New_Salem",
"(GMT-05:00) Central Time - Rainy River" => "America/Rainy_River",
"(GMT-05:00) Central Time - Rankin Inlet" => "America/Rankin_Inlet",
"(GMT-05:00) Central Time - Resolute" => "America/Resolute",
"(GMT-05:00) Central Time - Tell City, Indiana" => "America/Indiana/Tell_City",
"(GMT-05:00) Central Time - Winnipeg" => "America/Winnipeg",
"(GMT-05:00) Colombia Standard Time" => "America/Bogota",
"(GMT-05:00) Eastern Standard Time - Atikokan" => "America/Atikokan",
"(GMT-05:00) Eastern Standard Time - Cancun" => "America/Cancun",
"(GMT-05:00) Eastern Standard Time - Jamaica" => "America/Jamaica",
"(GMT-05:00) Eastern Standard Time - Panama" => "America/Panama",
"(GMT-05:00) Ecuador Time" => "America/Guayaquil",
"(GMT-05:00) Peru Standard Time" => "America/Lima",
"(GMT-04:00) Amazon Standard Time - Boa Vista" => "America/Boa_Vista",
"(GMT-04:00) Amazon Standard Time - Campo Grande" => "America/Campo_Grande",
"(GMT-04:00) Amazon Standard Time - Cuiaba" => "America/Cuiaba",
"(GMT-04:00) Amazon Standard Time - Manaus" => "America/Manaus",
"(GMT-04:00) Amazon Standard Time - Porto Velho" => "America/Porto_Velho",
"(GMT-04:00) Atlantic Standard Time - Barbados" => "America/Barbados",
"(GMT-04:00) Atlantic Standard Time - Blanc-Sablon" => "America/Blanc-Sablon",
"(GMT-04:00) Atlantic Standard Time - Curaçao" => "America/Curacao",
"(GMT-04:00) Atlantic Standard Time - Martinique" => "America/Martinique",
"(GMT-04:00) Atlantic Standard Time - Port of Spain" => "America/Port_of_Spain",
"(GMT-04:00) Atlantic Standard Time - Puerto Rico" => "America/Puerto_Rico",
"(GMT-04:00) Atlantic Standard Time - Santo Domingo" => "America/Santo_Domingo",
"(GMT-04:00) Bolivia Time" => "America/La_Paz",
"(GMT-04:00) Chile Time" => "America/Santiago",
"(GMT-04:00) Cuba Time" => "America/Havana",
"(GMT-04:00) Eastern Time - Detroit" => "America/Detroit",
"(GMT-04:00) Eastern Time - Grand Turk" => "America/Grand_Turk",
"(GMT-04:00) Eastern Time - Indianapolis" => "America/Indiana/Indianapolis",
"(GMT-04:00) Eastern Time - Iqaluit" => "America/Iqaluit",
"(GMT-04:00) Eastern Time - Louisville" => "America/Kentucky/Louisville",
"(GMT-04:00) Eastern Time - Marengo, Indiana" => "America/Indiana/Marengo",
"(GMT-04:00) Eastern Time - Monticello, Kentucky" => "America/Kentucky/Monticello",
"(GMT-04:00) Eastern Time - Nassau" => "America/Nassau",
"(GMT-04:00) Eastern Time - New York" => "America/New_York",
"(GMT-04:00) Eastern Time - Nipigon" => "America/Nipigon",
"(GMT-04:00) Eastern Time - Pangnirtung" => "America/Pangnirtung",
"(GMT-04:00) Eastern Time - Petersburg, Indiana" => "America/Indiana/Petersburg",
"(GMT-04:00) Eastern Time - Port-au-Prince" => "America/Port-au-Prince",
"(GMT-04:00) Eastern Time - Thunder Bay" => "America/Thunder_Bay",
"(GMT-04:00) Eastern Time - Toronto" => "America/Toronto",
"(GMT-04:00) Eastern Time - Vevay, Indiana" => "America/Indiana/Vevay",
"(GMT-04:00) Eastern Time - Vincennes, Indiana" => "America/Indiana/Vincennes",
"(GMT-04:00) Eastern Time - Winamac, Indiana" => "America/Indiana/Winamac",
"(GMT-04:00) Guyana Time" => "America/Guyana",
"(GMT-04:00) Paraguay Time" => "America/Asuncion",
"(GMT-04:00) Venezuela Time" => "America/Caracas",
"(GMT-03:00) Argentina Standard Time - Buenos Aires" => "America/Argentina/Buenos_Aires",
"(GMT-03:00) Argentina Standard Time - Catamarca" => "America/Argentina/Catamarca",
"(GMT-03:00) Argentina Standard Time - Cordoba" => "America/Argentina/Cordoba",
"(GMT-03:00) Argentina Standard Time - Jujuy" => "America/Argentina/Jujuy",
"(GMT-03:00) Argentina Standard Time - La Rioja" => "America/Argentina/La_Rioja",
"(GMT-03:00) Argentina Standard Time - Mendoza" => "America/Argentina/Mendoza",
"(GMT-03:00) Argentina Standard Time - Rio Gallegos" => "America/Argentina/Rio_Gallegos",
"(GMT-03:00) Argentina Standard Time - Salta" => "America/Argentina/Salta",
"(GMT-03:00) Argentina Standard Time - San Juan" => "America/Argentina/San_Juan",
"(GMT-03:00) Argentina Standard Time - San Luis" => "America/Argentina/San_Luis",
"(GMT-03:00) Argentina Standard Time - Tucuman" => "America/Argentina/Tucuman",
"(GMT-03:00) Argentina Standard Time - Ushuaia" => "America/Argentina/Ushuaia",
"(GMT-03:00) Atlantic Time - Bermuda" => "Atlantic/Bermuda",
"(GMT-03:00) Atlantic Time - Glace Bay" => "America/Glace_Bay",
"(GMT-03:00) Atlantic Time - Goose Bay" => "America/Goose_Bay",
"(GMT-03:00) Atlantic Time - Halifax" => "America/Halifax",
"(GMT-03:00) Atlantic Time - Moncton" => "America/Moncton",
"(GMT-03:00) Atlantic Time - Thule" => "America/Thule",
"(GMT-03:00) Brasilia Standard Time - Araguaina" => "America/Araguaina",
"(GMT-03:00) Brasilia Standard Time - Bahia" => "America/Bahia",
"(GMT-03:00) Brasilia Standard Time - Belem" => "America/Belem",
"(GMT-03:00) Brasilia Standard Time - Fortaleza" => "America/Fortaleza",
"(GMT-03:00) Brasilia Standard Time - Maceio" => "America/Maceio",
"(GMT-03:00) Brasilia Standard Time - Recife" => "America/Recife",
"(GMT-03:00) Brasilia Standard Time - Santarem" => "America/Santarem",
"(GMT-03:00) Brasilia Standard Time - Sao Paulo" => "America/Sao_Paulo",
"(GMT-03:00) Chile Time" => "America/Santiago",
"(GMT-03:00) Falkland Islands Standard Time" => "Atlantic/Stanley",
"(GMT-03:00) French Guiana Time" => "America/Cayenne",
"(GMT-03:00) Palmer Time" => "Antarctica/Palmer",
"(GMT-03:00) Punta Arenas Time" => "America/Punta_Arenas",
"(GMT-03:00) Rothera Time" => "Antarctica/Rothera",
"(GMT-03:00) Suriname Time" => "America/Paramaribo",
"(GMT-03:00) Uruguay Standard Time" => "America/Montevideo",
"(GMT-02:30) Newfoundland Time" => "America/St_Johns",
"(GMT-02:00) Fernando de Noronha Standard Time" => "America/Noronha",
"(GMT-02:00) South Georgia Time" => "Atlantic/South_Georgia",
"(GMT-02:00) St. Pierre & Miquelon Time" => "America/Miquelon",
"(GMT-02:00) West Greenland Time" => "America/Nuuk",
"(GMT-01:00) Cape Verde Standard Time" => "Atlantic/Cape_Verde",
"(GMT+00:00) Azores Time" => "Atlantic/Azores",
"(GMT+00:00) Coordinated Universal Time" => "UTC",
"(GMT+00:00) East Greenland Time" => "America/Scoresbysund",
"(GMT+00:00) Greenwich Mean Time" => "Etc/GMT",
"(GMT+00:00) Greenwich Mean Time - Abidjan" => "Africa/Abidjan",
"(GMT+00:00) Greenwich Mean Time - Accra" => "Africa/Accra",
"(GMT+00:00) Greenwich Mean Time - Bissau" => "Africa/Bissau",
"(GMT+00:00) Greenwich Mean Time - Danmarkshavn" => "America/Danmarkshavn",
"(GMT+00:00) Greenwich Mean Time - Monrovia" => "Africa/Monrovia",
"(GMT+00:00) Greenwich Mean Time - Reykjavik" => "Atlantic/Reykjavik",
"(GMT+00:00) Greenwich Mean Time - São Tomé" => "Africa/Sao_Tome",
"(GMT+01:00) Central European Standard Time - Algiers" => "Africa/Algiers",
"(GMT+01:00) Central European Standard Time - Tunis" => "Africa/Tunis",
"(GMT+01:00) Ireland Time" => "Europe/Dublin",
"(GMT+01:00) Morocco Time" => "Africa/Casablanca",
"(GMT+01:00) United Kingdom Time" => "Europe/London",
"(GMT+01:00) West Africa Standard Time - Lagos" => "Africa/Lagos",
"(GMT+01:00) West Africa Standard Time - Ndjamena" => "Africa/Ndjamena",
"(GMT+01:00) Western European Time - Canary" => "Atlantic/Canary",
"(GMT+01:00) Western European Time - Faroe" => "Atlantic/Faroe",
"(GMT+01:00) Western European Time - Lisbon" => "Europe/Lisbon",
"(GMT+01:00) Western European Time - Madeira" => "Atlantic/Madeira",
"(GMT+01:00) Western Sahara Time" => "Africa/El_Aaiun",
"(GMT+02:00) Central Africa Time - Khartoum" => "Africa/Khartoum",
"(GMT+02:00) Central Africa Time - Maputo" => "Africa/Maputo",
"(GMT+02:00) Central Africa Time - Windhoek" => "Africa/Windhoek",
"(GMT+02:00) Central European Time - Amsterdam" => "Europe/Amsterdam",
"(GMT+02:00) Central European Time - Andorra" => "Europe/Andorra",
"(GMT+02:00) Central European Time - Belgrade" => "Europe/Belgrade",
"(GMT+02:00) Central European Time - Berlin" => "Europe/Berlin",
"(GMT+02:00) Central European Time - Brussels" => "Europe/Brussels",
"(GMT+02:00) Central European Time - Budapest" => "Europe/Budapest",
"(GMT+02:00) Central European Time - Ceuta" => "Africa/Ceuta",
"(GMT+02:00) Central European Time - Copenhagen" => "Europe/Copenhagen",
"(GMT+02:00) Central European Time - Gibraltar" => "Europe/Gibraltar",
"(GMT+02:00) Central European Time - Luxembourg" => "Europe/Luxembourg",
"(GMT+02:00) Central European Time - Madrid" => "Europe/Madrid",
"(GMT+02:00) Central European Time - Malta" => "Europe/Malta",
"(GMT+02:00) Central European Time - Monaco" => "Europe/Monaco",
"(GMT+02:00) Central European Time - Oslo" => "Europe/Oslo",
"(GMT+02:00) Central European Time - Paris" => "Europe/Paris",
"(GMT+02:00) Central European Time - Prague" => "Europe/Prague",
"(GMT+02:00) Central European Time - Rome" => "Europe/Rome",
"(GMT+02:00) Central European Time - Stockholm" => "Europe/Stockholm",
"(GMT+02:00) Central European Time - Tirane" => "Europe/Tirane",
"(GMT+02:00) Central European Time - Vienna" => "Europe/Vienna",
"(GMT+02:00) Central European Time - Warsaw" => "Europe/Warsaw",
"(GMT+02:00) Central European Time - Zurich" => "Europe/Zurich",
"(GMT+02:00) Eastern European Standard Time - Cairo" => "Africa/Cairo",
"(GMT+02:00) Eastern European Standard Time - Kaliningrad" => "Europe/Kaliningrad",
"(GMT+02:00) Eastern European Standard Time - Tripoli" => "Africa/Tripoli",
"(GMT+02:00) South Africa Standard Time" => "Africa/Johannesburg",
"(GMT+02:00) Troll Time" => "Antarctica/Troll",
"(GMT+03:00) Arabian Standard Time - Baghdad" => "Asia/Baghdad",
"(GMT+03:00) Arabian Standard Time - Qatar" => "Asia/Qatar",
"(GMT+03:00) Arabian Standard Time - Riyadh" => "Asia/Riyadh",
"(GMT+03:00) East Africa Time - Juba" => "Africa/Juba",
"(GMT+03:00) East Africa Time - Nairobi" => "Africa/Nairobi",
"(GMT+03:00) Eastern European Time - Amman" => "Asia/Amman",
"(GMT+03:00) Eastern European Time - Athens" => "Europe/Athens",
"(GMT+03:00) Eastern European Time - Beirut" => "Asia/Beirut",
"(GMT+03:00) Eastern European Time - Bucharest" => "Europe/Bucharest",
"(GMT+03:00) Eastern European Time - Chisinau" => "Europe/Chisinau",
"(GMT+03:00) Eastern European Time - Damascus" => "Asia/Damascus",
"(GMT+03:00) Eastern European Time - Gaza" => "Asia/Gaza",
"(GMT+03:00) Eastern European Time - Hebron" => "Asia/Hebron",
"(GMT+03:00) Eastern European Time - Helsinki" => "Europe/Helsinki",
"(GMT+03:00) Eastern European Time - Kiev" => "Europe/Kiev",
"(GMT+03:00) Eastern European Time - Nicosia" => "Asia/Nicosia",
"(GMT+03:00) Eastern European Time - Riga" => "Europe/Riga",
"(GMT+03:00) Eastern European Time - Sofia" => "Europe/Sofia",
"(GMT+03:00) Eastern European Time - Tallinn" => "Europe/Tallinn",
"(GMT+03:00) Eastern European Time - Uzhhorod" => "Europe/Uzhgorod",
"(GMT+03:00) Eastern European Time - Vilnius" => "Europe/Vilnius",
"(GMT+03:00) Eastern European Time - Zaporozhye" => "Europe/Zaporozhye",
"(GMT+03:00) Famagusta Time" => "Asia/Famagusta",
"(GMT+03:00) Israel Time" => "Asia/Jerusalem",
"(GMT+03:00) Kirov Time" => "Europe/Kirov",
"(GMT+03:00) Moscow Standard Time - Minsk" => "Europe/Minsk",
"(GMT+03:00) Moscow Standard Time - Moscow" => "Europe/Moscow",
"(GMT+03:00) Moscow Standard Time - Simferopol" => "Europe/Simferopol",
"(GMT+03:00) Syowa Time" => "Antarctica/Syowa",
"(GMT+03:00) Turkey Time" => "Europe/Istanbul",
"(GMT+04:00) Armenia Standard Time" => "Asia/Yerevan",
"(GMT+04:00) Astrakhan Time" => "Europe/Astrakhan",
"(GMT+04:00) Azerbaijan Standard Time" => "Asia/Baku",
"(GMT+04:00) Georgia Standard Time" => "Asia/Tbilisi",
"(GMT+04:00) Gulf Standard Time" => "Asia/Dubai",
"(GMT+04:00) Mauritius Standard Time" => "Indian/Mauritius",
"(GMT+04:00) Réunion Time" => "Indian/Reunion",
"(GMT+04:00) Samara Standard Time" => "Europe/Samara",
"(GMT+04:00) Saratov Time" => "Europe/Saratov",
"(GMT+04:00) Seychelles Time" => "Indian/Mahe",
"(GMT+04:00) Ulyanovsk Time" => "Europe/Ulyanovsk",
"(GMT+04:00) Volgograd Standard Time" => "Europe/Volgograd",
"(GMT+04:30) Afghanistan Time" => "Asia/Kabul",
"(GMT+04:30) Iran Time" => "Asia/Tehran",
"(GMT+05:00) French Southern & Antarctic Time" => "Indian/Kerguelen",
"(GMT+05:00) Maldives Time" => "Indian/Maldives",
"(GMT+05:00) Mawson Time" => "Antarctica/Mawson",
"(GMT+05:00) Pakistan Standard Time" => "Asia/Karachi",
"(GMT+05:00) Tajikistan Time" => "Asia/Dushanbe",
"(GMT+05:00) Turkmenistan Standard Time" => "Asia/Ashgabat",
"(GMT+05:00) Uzbekistan Standard Time - Samarkand" => "Asia/Samarkand",
"(GMT+05:00) Uzbekistan Standard Time - Tashkent" => "Asia/Tashkent",
"(GMT+05:00) West Kazakhstan Time - Aqtau" => "Asia/Aqtau",
"(GMT+05:00) West Kazakhstan Time - Aqtobe" => "Asia/Aqtobe",
"(GMT+05:00) West Kazakhstan Time - Atyrau" => "Asia/Atyrau",
"(GMT+05:00) West Kazakhstan Time - Oral" => "Asia/Oral",
"(GMT+05:00) West Kazakhstan Time - Qyzylorda" => "Asia/Qyzylorda",
"(GMT+05:00) Yekaterinburg Standard Time" => "Asia/Yekaterinburg",
"(GMT+05:30) Indian Standard Time - Colombo" => "Asia/Colombo",
"(GMT+05:30) Indian Standard Time - Kolkata" => "Asia/Kolkata",
"(GMT+05:45) Nepal Time" => "Asia/Kathmandu",
"(GMT+06:00) Bangladesh Standard Time" => "Asia/Dhaka",
"(GMT+06:00) Bhutan Time" => "Asia/Thimphu",
"(GMT+06:00) East Kazakhstan Time - Almaty" => "Asia/Almaty",
"(GMT+06:00) East Kazakhstan Time - Kostanay" => "Asia/Qostanay",
"(GMT+06:00) Indian Ocean Time" => "Indian/Chagos",
"(GMT+06:00) Kyrgyzstan Time" => "Asia/Bishkek",
"(GMT+06:00) Omsk Standard Time" => "Asia/Omsk",
"(GMT+06:00) Urumqi Time" => "Asia/Urumqi",
"(GMT+06:00) Vostok Time" => "Antarctica/Vostok",
"(GMT+06:30) Cocos Islands Time" => "Indian/Cocos",
"(GMT+06:30) Myanmar Time" => "Asia/Yangon",
"(GMT+07:00) Barnaul Time" => "Asia/Barnaul",
"(GMT+07:00) Christmas Island Time" => "Indian/Christmas",
"(GMT+07:00) Davis Time" => "Antarctica/Davis",
"(GMT+07:00) Hovd Standard Time" => "Asia/Hovd",
"(GMT+07:00) Indochina Time - Bangkok" => "Asia/Bangkok",
"(GMT+07:00) Indochina Time - Ho Chi Minh City" => "Asia/Ho_Chi_Minh",
"(GMT+07:00) Krasnoyarsk Standard Time - Krasnoyarsk" => "Asia/Krasnoyarsk",
"(GMT+07:00) Krasnoyarsk Standard Time - Novokuznetsk" => "Asia/Novokuznetsk",
"(GMT+07:00) Novosibirsk Standard Time" => "Asia/Novosibirsk",
"(GMT+07:00) Tomsk Time" => "Asia/Tomsk",
"(GMT+07:00) Western Indonesia Time - Jakarta" => "Asia/Jakarta",
"(GMT+07:00) Western Indonesia Time - Pontianak" => "Asia/Pontianak",
"(GMT+08:00) Australian Western Standard Time - Casey" => "Antarctica/Casey",
"(GMT+08:00) Australian Western Standard Time - Perth" => "Australia/Perth",
"(GMT+08:00) Brunei Darussalam Time" => "Asia/Brunei",
"(GMT+08:00) Central Indonesia Time" => "Asia/Makassar",
"(GMT+08:00) China Standard Time - Macao" => "Asia/Macau",
"(GMT+08:00) China Standard Time - Shanghai" => "Asia/Shanghai",
"(GMT+08:00) Hong Kong Standard Time" => "Asia/Hong_Kong",
"(GMT+08:00) Irkutsk Standard Time" => "Asia/Irkutsk",
"(GMT+08:00) Malaysia Time - Kuala Lumpur" => "Asia/Kuala_Lumpur",
"(GMT+08:00) Malaysia Time - Kuching" => "Asia/Kuching",
"(GMT+08:00) Philippine Standard Time" => "Asia/Manila",
"(GMT+08:00) Singapore Standard Time" => "Asia/Singapore",
"(GMT+08:00) Taipei Standard Time" => "Asia/Taipei",
"(GMT+08:00) Ulaanbaatar Standard Time - Choibalsan" => "Asia/Choibalsan",
"(GMT+08:00) Ulaanbaatar Standard Time - Ulaanbaatar" => "Asia/Ulaanbaatar",
"(GMT+08:45) Australian Central Western Standard Time" => "Australia/Eucla",
"(GMT+09:00) East Timor Time" => "Asia/Dili",
"(GMT+09:00) Eastern Indonesia Time" => "Asia/Jayapura",
"(GMT+09:00) Japan Standard Time" => "Asia/Tokyo",
"(GMT+09:00) Korean Standard Time - Pyongyang" => "Asia/Pyongyang",
"(GMT+09:00) Korean Standard Time - Seoul" => "Asia/Seoul",
"(GMT+09:00) Palau Time" => "Pacific/Palau",
"(GMT+09:00) Yakutsk Standard Time - Chita" => "Asia/Chita",
"(GMT+09:00) Yakutsk Standard Time - Khandyga" => "Asia/Khandyga",
"(GMT+09:00) Yakutsk Standard Time - Yakutsk" => "Asia/Yakutsk",
"(GMT+09:30) Australian Central Standard Time" => "Australia/Darwin",
"(GMT+09:30) Central Australia Time - Adelaide" => "Australia/Adelaide",
"(GMT+09:30) Central Australia Time - Broken Hill" => "Australia/Broken_Hill",
"(GMT+10:00) Australian Eastern Standard Time - Brisbane" => "Australia/Brisbane",
"(GMT+10:00) Australian Eastern Standard Time - Lindeman" => "Australia/Lindeman",
"(GMT+10:00) Chamorro Standard Time" => "Pacific/Guam",
"(GMT+10:00) Chuuk Time" => "Pacific/Chuuk",
"(GMT+10:00) Dumont-dUrville Time" => "Antarctica/DumontDUrville",
"(GMT+10:00) Eastern Australia Time - Currie" => "Australia/Currie",
"(GMT+10:00) Eastern Australia Time - Hobart" => "Australia/Hobart",
"(GMT+10:00) Eastern Australia Time - Melbourne" => "Australia/Melbourne",
"(GMT+10:00) Eastern Australia Time - Sydney" => "Australia/Sydney",
"(GMT+10:00) Papua New Guinea Time" => "Pacific/Port_Moresby",
"(GMT+10:00) Vladivostok Standard Time - Ust-Nera" => "Asia/Ust-Nera",
"(GMT+10:00) Vladivostok Standard Time - Vladivostok" => "Asia/Vladivostok",
"(GMT+10:30) Lord Howe Time" => "Australia/Lord_Howe",
"(GMT+11:00) Bougainville Time" => "Pacific/Bougainville",
"(GMT+11:00) Kosrae Time" => "Pacific/Kosrae",
"(GMT+11:00) Macquarie Island Time" => "Antarctica/Macquarie",
"(GMT+11:00) Magadan Standard Time" => "Asia/Magadan",
"(GMT+11:00) New Caledonia Standard Time" => "Pacific/Noumea",
"(GMT+11:00) Norfolk Island Time" => "Pacific/Norfolk",
"(GMT+11:00) Ponape Time" => "Pacific/Pohnpei",
"(GMT+11:00) Sakhalin Standard Time" => "Asia/Sakhalin",
"(GMT+11:00) Solomon Islands Time" => "Pacific/Guadalcanal",
"(GMT+11:00) Srednekolymsk Time" => "Asia/Srednekolymsk",
"(GMT+11:00) Vanuatu Standard Time" => "Pacific/Efate",
"(GMT+12:00) Anadyr Standard Time" => "Asia/Anadyr",
"(GMT+12:00) Fiji Time" => "Pacific/Fiji",
"(GMT+12:00) Gilbert Islands Time" => "Pacific/Tarawa",
"(GMT+12:00) Marshall Islands Time - Kwajalein" => "Pacific/Kwajalein",
"(GMT+12:00) Marshall Islands Time - Majuro" => "Pacific/Majuro",
"(GMT+12:00) Nauru Time" => "Pacific/Nauru",
"(GMT+12:00) New Zealand Time" => "Pacific/Auckland",
"(GMT+12:00) Petropavlovsk-Kamchatski Standard Time" => "Asia/Kamchatka",
"(GMT+12:00) Tuvalu Time" => "Pacific/Funafuti",
"(GMT+12:00) Wake Island Time" => "Pacific/Wake",
"(GMT+12:00) Wallis & Futuna Time" => "Pacific/Wallis",
"(GMT+12:45) Chatham Time" => "Pacific/Chatham",
"(GMT+13:00) Apia Time" => "Pacific/Apia",
"(GMT+13:00) Phoenix Islands Time" => "Pacific/Enderbury",
"(GMT+13:00) Tokelau Time" => "Pacific/Fakaofo",
"(GMT+13:00) Tonga Standard Time" => "Pacific/Tongatapu",
"(GMT+14:00) Line Islands Time" => "Pacific/Kiritimati"
);
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* xmlseclibs.php
*
* Copyright (c) 2007-2016, Robert Richards <rrichards@cdatazone.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Robert Richards nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @author Robert Richards <rrichards@cdatazone.org>
* @copyright 2007-2017 Robert Richards <rrichards@cdatazone.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version 3.0.1
*/
$xmlseclibs_srcdir = dirname(__FILE__) . '/SAML2Core';
require $xmlseclibs_srcdir . '/MoXMLSecurityKey.php';
require $xmlseclibs_srcdir . '/MoXMLSecurityDSig.php';
require $xmlseclibs_srcdir . '/MoXMLSecEnc.php';
require $xmlseclibs_srcdir . '/Utils/MoXPath.php';

View File

@@ -1,11 +1,14 @@
<?php <?php
define('CLIENT_PATH', dirname(__FILE__)); use Classes\SAMLManager;use Classes\SettingsManager;use Utils\LogManager;define('CLIENT_PATH', dirname(__FILE__));
include("config.base.php"); include("config.base.php");
include("include.common.php"); include("include.common.php");
include("server.includes.inc.php"); include("server.includes.inc.php");
$companyName = \Classes\SettingsManager::getInstance()->getSetting('Company: Name'); $gsuiteEnabled = SettingsManager::getInstance()->getSetting('System: G Suite Enabled');
$gsuiteEnabled = \Classes\SettingsManager::getInstance()->getSetting('System: G Suite Enabled'); $companyName = SettingsManager::getInstance()->getSetting('Company: Name');
$SAMLAutoLogin = SettingsManager::getInstance()->getSetting('SAML: Auto Login') === "1";
$SAMLEnabled = SettingsManager::getInstance()->getSetting("SAML: Enabled") == "1";
$SAMLUserLoaded = false;
if (isset($_REQUEST['logout'])) { if (isset($_REQUEST['logout'])) {
\Utils\SessionUtils::unsetClientSession(); \Utils\SessionUtils::unsetClientSession();
@@ -14,12 +17,19 @@ if (isset($_REQUEST['logout'])) {
if (empty($user) || empty($user->email)) { if (empty($user) || empty($user->email)) {
if (!empty($_REQUEST['username']) && !empty($_REQUEST['password'])) { if (!isset($_REQUEST['logout']) && !isset($_POST['SAMLResponse']) && $SAMLAutoLogin && $SAMLEnabled && !empty(SettingsManager::getInstance()->getSetting("SAML: IDP SSO Url"))) {
header("Location:" . SettingsManager::getInstance()->getSetting("SAML: IDP SSO Url"));
exit();
}
if ((!empty($_REQUEST['username']) && !empty($_REQUEST['password']))
|| isset($_POST['SAMLResponse'])
) {
$suser = null; $suser = null;
$ssoUserLoaded = false; $ssoUserLoaded = false;
if($_REQUEST['username'] != "admin") { if($_REQUEST['username'] != "admin") {
if (\Classes\SettingsManager::getInstance()->getSetting("LDAP: Enabled") == "1") { if (SettingsManager::getInstance()->getSetting("LDAP: Enabled") === "1") {
$ldapResp = \Classes\LDAPManager::getInstance()->checkLDAPLogin($_REQUEST['username'], $_REQUEST['password']); $ldapResp = \Classes\LDAPManager::getInstance()->checkLDAPLogin($_REQUEST['username'], $_REQUEST['password']);
if ($ldapResp->getStatus() == \Classes\IceResponse::ERROR) { if ($ldapResp->getStatus() == \Classes\IceResponse::ERROR) {
header("Location:" . CLIENT_BASE_URL . "login.php?f=1"); header("Location:" . CLIENT_BASE_URL . "login.php?f=1");
@@ -36,6 +46,39 @@ if (empty($user) || empty($user->email)) {
} }
} }
if ($SAMLEnabled && isset($_POST['SAMLResponse'])) {
$samlData = $_POST['SAMLResponse'];
if(array_key_exists('RelayState', $_POST) && !empty( $_POST['RelayState'] ) && $_POST['RelayState'] !== '/') {
$relayState = htmlspecialchars($_POST['RelayState']);
} else {
$relayState = '';
}
$ssoUserEmail = (new SAMLManager())->getSSOEmail($samlData, $relayState);
LogManager::getInstance()->info('SSO SAML User Email:'.$ssoUserEmail);
if (false === $ssoUserEmail) {
header("Location:" . CLIENT_BASE_URL . "login.php?f=1");
exit();
} else {
$mapping = SettingsManager::getInstance()->getSetting('SAML: Name ID Mapping');
$suser = new \Users\Common\Model\User();
if ($mapping === 'username') {
$suser->Load("username = ?", array($ssoUserEmail));
} else {
$suser->Load("email = ?", array($ssoUserEmail));
}
LogManager::getInstance()->info('SSO SAML User:'.print_r($suser->email, true));
if (empty($suser) || empty($suser->id)) {
header("Location:" . CLIENT_BASE_URL . "logout.php");
exit();
}
$ssoUserLoaded = true;
$SAMLUserLoaded = true;
}
}
if (empty($suser)) { if (empty($suser)) {
$suser = new \Users\Common\Model\User(); $suser = new \Users\Common\Model\User();
$suser->Load( $suser->Load(
@@ -59,7 +102,7 @@ if (empty($user) || empty($user->email)) {
$loginCsrf = \Utils\SessionUtils::getSessionObject('csrf-login'); $loginCsrf = \Utils\SessionUtils::getSessionObject('csrf-login');
if ($_REQUEST['csrf'] != $loginCsrf || empty($_REQUEST['csrf'])) { if (!$SAMLUserLoaded && ($_REQUEST['csrf'] != $loginCsrf || empty($_REQUEST['csrf']))) {
$next = !empty($_REQUEST['next'])?'&next='.$_REQUEST['next']:''; $next = !empty($_REQUEST['next'])?'&next='.$_REQUEST['next']:'';
header("Location:".CLIENT_BASE_URL."login.php?f=1".$next); header("Location:".CLIENT_BASE_URL."login.php?f=1".$next);
exit(); exit();
@@ -277,7 +320,7 @@ $csrfToken = sha1(rand(4500, 100000) . time(). CLIENT_BASE_URL);
<div class="col-lg-6 col-md-8 col-xs-10"> <div class="col-lg-6 col-md-8 col-xs-10">
<div class="bg-white-2 h-100 px-11 pt-11 pb-7"> <div class="bg-white-2 h-100 px-11 pt-11 pb-7">
<div class="row d-flex justify-content-center"> <div class="row d-flex justify-content-center">
<img src="<?=$logoFileUrl?>"/> <img style="max-width: 100%;" src="<?=$logoFileUrl?>"/>
</div> </div>
<hr/> <hr/>
<?php if ($gsuiteEnabled) {?> <?php if ($gsuiteEnabled) {?>

View File

@@ -1,5 +1,13 @@
<?php <?php
$migrationList = []; $migrationList = [];
$migrationList[] = 'v20210626_290004_add_s3_settings';
$migrationList[] = 'v20210606_290003_system_meta_data';
$migrationList[] = 'v20210606_290002_add_aws_region';
$migrationList[] = 'v20210606_290001_update_s3_config';
$migrationList[] = 'v20210402_280006_modify_attendance_rep';
$migrationList[] = 'v20210327_280005_saml_settings';
$migrationList[] = 'v20210228_280003_add_share_with_employee';
$migrationList[] = 'v20210228_280004_add_visible_to_document';
$migrationList[] = 'v20201028_280002_update_gender'; $migrationList[] = 'v20201028_280002_update_gender';
$migrationList[] = 'v20201028_280001_update_module_names'; $migrationList[] = 'v20201028_280001_update_module_names';
$migrationList[] = 'v20201017_271101_switch_off_photo_att'; $migrationList[] = 'v20201017_271101_switch_off_photo_att';

View File

@@ -0,0 +1,24 @@
<?php
namespace Classes\Migration;
class v20210228_280003_add_share_with_employee extends AbstractMigration
{
public function up()
{
$sql = <<<'SQL'
ALTER TABLE `Documents`
ADD COLUMN `share_with_employee` enum('Yes','No') NULL DEFAULT 'Yes' AFTER `updated`;
SQL;
$this->executeQuery($sql);
return $this->executeQuery($sql);
}
public function down()
{
return true;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Classes\Migration;
class v20210228_280004_add_visible_to_document extends AbstractMigration
{
public function up()
{
$sql = <<<'SQL'
ALTER TABLE `EmployeeDocuments`
ADD COLUMN `visible_to` enum('Owner','Manager','Admin') NULL DEFAULT 'Owner' AFTER `expire_notification_last`;
SQL;
$this->executeQuery($sql);
return $this->executeQuery($sql);
}
public function down()
{
return true;
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Classes\Migration;
class v20210327_280005_saml_settings extends AbstractMigration {
public function up(){
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: Enabled',
'0',
'Enable SAML Login',
'["value", {"label":"Value","type":"select","source":[["1","Yes"],["0","No"]]}]',
'SAML'
);
SQL;
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: Auto Login',
'0',
'Try to login via SAML by redirecting the user to SSO Url',
'["value", {"label":"Value","type":"select","source":[["1","Yes"],["0","No"]]}]',
'SAML'
);
SQL;
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: IDP SSO Url',
'',
'Identity Provider Single Sign-On URL. Users will be redirected to this URL for authentication',
'',
'SAML'
);
SQL;
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: IDP Issuer',
'',
'Identity Provider Issuer',
'',
'SAML'
);
SQL;
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: X.509 Certificate',
'',
'X.509 Certificate provided by the Identity Provider. This certificate will be encrypted',
'["value", {"label":"Value","type":"textarea"}]',
'SAML'
);
SQL;
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'SAML: Name ID Mapping',
'email',
'SAML Name id mapped to can be mapped to icehrm user email or the username',
'["value", {"label":"Value","type":"select","source":[["email","Email"],["username","Username"]]}]',
'SAML'
);
SQL;
$result = true;
foreach ($sql as $query) {
$result = $result && $this->executeQuery($query);
}
return $result;
}
public function down(){
return true;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Classes\Migration;
use Model\Report;
class v20210402_280006_modify_attendance_rep extends AbstractMigration {
public function up(){
$report = new Report();
$report->Load('name = ?', ['Employee Time Tracking Report']);
$report->parameters = <<<'JSON'
[
[ "employee", {"label":"Employee","type":"select2","allow-null":false,"remote-source":["Employee","id","first_name+last_name"]}],
[ "date_start", {"label":"Start Date","type":"date", "validation":"none"}],
[ "date_end", {"label":"End Date","type":"date","validation":"none"}],
["period", { "label": "Period", "type": "select", "source": [["Current Month", "Current Month"], ["Last Month", "Last Month"], ["Last Week", "Last Week"], ["Last 2 Weeks", "Last 2 Weeks"]], "validation":"none" }]
]
JSON;
$report->paramOrder = <<<'JSON'
["employee","date_start","date_end","period"]
JSON;
$report->Save();
return true;
}
public function down(){
return true;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Classes\Migration;
class v20210606_290001_update_s3_config extends AbstractMigration
{
public function up()
{
$sql = <<<'SQL'
UPDATE `Settings`
SET name = 'Files: Amazon S3 Secret for File Upload'
WHERE name = 'Files: Amazone S3 Secret for File Upload';
SQL;
$this->executeQuery($sql);
$sql = <<<'SQL'
UPDATE `Settings`
SET category = 'System'
WHERE name like 'Files:%';
SQL;
return $this->executeQuery($sql);
}
public function down()
{
return true;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Classes\Migration;
class v20210606_290002_add_aws_region extends AbstractMigration {
public function up(){
$sql[] = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`)
VALUES (
'System: AWS Region',
'us-east-1',
'Amazon SWS Region used for file storage',
'',
'System'
);
SQL;
$result = true;
foreach ($sql as $query) {
$result = $result && $this->executeQuery($query);
}
return $result;
}
public function down(){
return true;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Classes\Migration;
class v20210606_290003_system_meta_data extends AbstractMigration {
public function up(){
$sql = <<<'SQL'
create table `SystemData` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) not null,
`value` text default null,
primary key (`id`),
unique key `name` (`name`)
) engine=innodb default charset=utf8;
SQL;
return $this->executeQuery($sql);
}
public function down(){
return true;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Classes\Migration;
class v20210626_290004_add_s3_settings extends AbstractMigration
{
public function up()
{
$sql = <<<'SQL'
REPLACE INTO `Settings` (`name`, `value`, `description`, `meta`, `category`) VALUES
('Files: Upload Files to S3', '0', '','["value", {"label":"Value","type":"select","source":[["1","Yes"],["0","No"]]}]', 'System'),
('Files: Amazon S3 Key for File Upload', '', 'Please provide S3 Key for uploading files','', 'System'),
('Files: Amazon S3 Secret for File Upload', '', 'Please provide S3 Secret for uploading files','', 'System'),
('Files: S3 Bucket', '', 'Please provide S3 Bucket name for uploading files','', 'System'),
('Files: S3 Web Url', '', 'Please provide Url to the s3 bucket','', 'System'),
('System: AWS Region', 'us-east-1', 'Amazon AWS Region used for file storage','', 'System');
SQL;
return $this->executeQuery($sql);
}
public function down()
{
return true;
}
}

View File

@@ -291,6 +291,12 @@ foreach ($ams as $am) {
} }
} }
$extensionManager = new \Classes\ExtensionManager();
$extensionData = $extensionManager->setupExtensions();
$extensionIcons = $extensionData[0];
$extensionTemp = $extensionData[1];
$extensionMenus = array_keys($extensionIcons);
foreach ($adminModulesTemp as $k => $v) { foreach ($adminModulesTemp as $k => $v) {
ksort($adminModulesTemp[$k]); ksort($adminModulesTemp[$k]);
} }
@@ -299,6 +305,10 @@ foreach ($userModulesTemp as $k => $v) {
ksort($userModulesTemp[$k]); ksort($userModulesTemp[$k]);
} }
foreach ($extensionTemp as $k => $v) {
ksort($extensionTemp[$k]);
}
$adminIcons = json_decode(file_get_contents(CLIENT_PATH.'/admin/meta.json'), true); $adminIcons = json_decode(file_get_contents(CLIENT_PATH.'/admin/meta.json'), true);
$adminMenus = array_keys($adminIcons); $adminMenus = array_keys($adminIcons);
@@ -332,8 +342,6 @@ foreach ($userMenus as $menu) {
} }
} }
$mainIcons = array_merge($adminIcons, $userIcons);
foreach ($userModulesTemp as $k => $v) { foreach ($userModulesTemp as $k => $v) {
if (!in_array($k, $added)) { if (!in_array($k, $added)) {
$arr = array("name"=>$k,"menu"=>$userModulesTemp[$k]); $arr = array("name"=>$k,"menu"=>$userModulesTemp[$k]);
@@ -341,6 +349,25 @@ foreach ($userModulesTemp as $k => $v) {
} }
} }
$extensions = array();
foreach ($extensionMenus as $menu) {
if (isset($extensionTemp[$menu])) {
$arr = array("name"=>$menu,"menu"=>$extensionTemp[$menu]);
$extensions[] = $arr;
$added[] = $menu;
}
}
foreach ($extensionTemp as $k => $v) {
if (!in_array($k, $added)) {
$arr = array("name"=>$k,"menu"=>$extensionTemp[$k]);
$extensions[] = $arr;
}
}
// Merge icons
$mainIcons = array_merge($adminIcons, $userIcons, $extensionIcons);
//Remove modules having no permissions //Remove modules having no permissions
if (!empty($user)) { if (!empty($user)) {
if (!empty($user->user_roles)) { if (!empty($user->user_roles)) {
@@ -393,4 +420,24 @@ if (!empty($user)) {
} }
} }
} }
foreach ($extensions as $fk => $menu) {
foreach ($menu['menu'] as $key => $item) {
// If the user's once of the user roles are blacklisted for the module
$commonRoles = array_intersect($item['user_roles_blacklist'], $userRoles);
if (!empty($commonRoles)) {
unset($extensions[$fk]['menu'][$key]);
}
if (!in_array($user->user_level, $item['user_levels'])) {
if (!empty($userRoles)) {
$commonRoles = array_intersect($item['user_roles'], $userRoles);
if (empty($commonRoles)) {
unset($extensions[$fk]['menu'][$key]);
}
} else {
unset($extensions[$fk]['menu'][$key]);
}
}
}
}
} }

View File

@@ -67,6 +67,8 @@ modJsList['tabEmployeeDocument'].setShowDelete(false);
modJsList['tabEmployeeDocument'].setShowEdit(false); modJsList['tabEmployeeDocument'].setShowEdit(false);
<?php }?> <?php }?>
modJsList['tabEmployeeDocument'].setRemoteTable(true);
modJsList['tabEmployeeCompanyDocument'] = new EmployeeCompanyDocumentAdapter('CompanyDocument','EmployeeCompanyDocument'); modJsList['tabEmployeeCompanyDocument'] = new EmployeeCompanyDocumentAdapter('CompanyDocument','EmployeeCompanyDocument');
modJsList['tabEmployeeCompanyDocument'].setLoadMoreButton($("#loadMoreEmployeeCompanyDocument")); modJsList['tabEmployeeCompanyDocument'].setLoadMoreButton($("#loadMoreEmployeeCompanyDocument"));

View File

@@ -3,49 +3,8 @@ header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: DELETE, POST, GET, OPTIONS'); header('Access-Control-Allow-Methods: DELETE, POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With'); header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
header('Content-Type: application/json'); header('Content-Type: application/json');
define('CLIENT_PATH',dirname(__FILE__)); if (isset($_REQUEST['method']) && isset($_REQUEST['url'])) {
include ("config.base.php"); include(APP_BASE_PATH . 'api-url-based.php');
include ("include.common.php");
include("server.includes.inc.php");
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
if (defined('SYM_CLIENT')) {
define('REST_API_PATH', '/'.SYM_CLIENT.'/');
} else if (!defined('REST_API_PATH')){
define('REST_API_PATH', '/');
}
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
\Utils\LogManager::getInstance()->debug('Api dispatch URI: '.$uri);
\Utils\LogManager::getInstance()->debug('Api dispatch method: '.$uri);
if (!defined('SYM_CLIENT')) {
//For hosted installations, dispatch will be done in app/index
\Classes\Macaw::dispatch();
}
} else { } else {
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true"; include(APP_BASE_PATH . 'api-rest.php');
} }

View File

@@ -3,19 +3,28 @@
use Classes\BaseService; use Classes\BaseService;
use Classes\CustomFieldManager; use Classes\CustomFieldManager;
use Classes\JwtTokenService; use Classes\JwtTokenService;
use Classes\MemoryCacheService;
use Classes\Migration\MigrationManager; use Classes\Migration\MigrationManager;
use Classes\NotificationManager; use Classes\NotificationManager;
use Classes\RedisCacheService;
use Classes\ReportHandler; use Classes\ReportHandler;
use Classes\SettingsManager; use Classes\SettingsManager;
use Model\Audit;
use Model\BaseModel;
use Model\DataEntryBackup;
use Model\File;
use Model\Notification;
use Model\Report;
use Model\RestAccessToken;
use Model\Setting;
use Utils\LogManager; use Utils\LogManager;
if (!defined("AWS_REGION")) {
define('AWS_REGION', 'us-east-1');
}
include(APP_BASE_PATH.'lib/adodb512/adodb.inc.php'); include(APP_BASE_PATH.'lib/adodb512/adodb.inc.php');
include(APP_BASE_PATH.'lib/adodb512/adodb-active-record.inc.php'); include(APP_BASE_PATH.'lib/adodb512/adodb-active-record.inc.php');
$ADODB_ASSOC_CASE = 2; $ADODB_ASSOC_CASE = 2;
include(APP_BASE_PATH.'lib/fpdf/fpdf.php');
//detect admin and user modules //detect admin and user modules
if (defined("MODULE_PATH")) { if (defined("MODULE_PATH")) {
$tArr = explode("/", MODULE_PATH); $tArr = explode("/", MODULE_PATH);
@@ -37,13 +46,13 @@ $dbLocal = NewADOConnection('mysqli');
$res = $dbLocal->Connect(APP_HOST, APP_USERNAME, APP_PASSWORD, APP_DB); $res = $dbLocal->Connect(APP_HOST, APP_USERNAME, APP_PASSWORD, APP_DB);
\Model\File::SetDatabaseAdapter($dbLocal); File::SetDatabaseAdapter($dbLocal);
\Model\Setting::SetDatabaseAdapter($dbLocal); Setting::SetDatabaseAdapter($dbLocal);
\Model\Report::SetDatabaseAdapter($dbLocal); Report::SetDatabaseAdapter($dbLocal);
\Model\DataEntryBackup::SetDatabaseAdapter($dbLocal); DataEntryBackup::SetDatabaseAdapter($dbLocal);
\Model\Audit::SetDatabaseAdapter($dbLocal); Audit::SetDatabaseAdapter($dbLocal);
\Model\Notification::SetDatabaseAdapter($dbLocal); Notification::SetDatabaseAdapter($dbLocal);
\Model\RestAccessToken::SetDatabaseAdapter($dbLocal); RestAccessToken::SetDatabaseAdapter($dbLocal);
$baseService = BaseService::getInstance(); $baseService = BaseService::getInstance();
@@ -71,14 +80,31 @@ if (defined('REDIS_SERVER_URI')
&& QUERY_CACHE_TYPE === 'redis' && QUERY_CACHE_TYPE === 'redis'
) { ) {
BaseService::getInstance()->setCacheService( BaseService::getInstance()->setCacheService(
new \Classes\RedisCacheService(REDIS_SERVER_URI, CLIENT_NAME) new RedisCacheService(REDIS_SERVER_URI, CLIENT_NAME)
); );
} else { } else {
BaseService::getInstance()->setCacheService( BaseService::getInstance()->setCacheService(
new \Classes\MemoryCacheService(CLIENT_NAME) new MemoryCacheService(CLIENT_NAME)
); );
} }
$awsRegion = SettingsManager::getInstance()->getSetting("System: AWS Region");
if (!defined("AWS_REGION")) {
define('AWS_REGION', empty($awsRegion) ? 'us-east-1' : $awsRegion);
}
$samlEnabled = SettingsManager::getInstance()->getSetting("SAML: Enabled");
if ($samlEnabled === '1') {
include APP_BASE_PATH . 'lib/saml2/Utilities.php';
include APP_BASE_PATH . 'lib/saml2/Response.php';
include APP_BASE_PATH . 'lib/saml2/encryption.php';
include APP_BASE_PATH . 'lib/saml2/mo-saml-options-enum.php';
}
$instanceId = SettingsManager::getInstance()->getSetting("Instance : ID");
$instanceKey = SettingsManager::getInstance()->getSetting("Instance: Key");
if(!defined('APP_SEC')){define('APP_SEC',sha1($instanceId.$instanceKey));}
$noJSONRequests = SettingsManager::getInstance()->getSetting("System: Do not pass JSON in request"); $noJSONRequests = SettingsManager::getInstance()->getSetting("System: Do not pass JSON in request");
$debugMode = SettingsManager::getInstance()->getSetting("System: Debug Mode"); $debugMode = SettingsManager::getInstance()->getSetting("System: Debug Mode");
@@ -123,10 +149,12 @@ if (defined('CLIENT_PATH')) {
$modelClassList = $moduleManagerObj->getModelClasses(); $modelClassList = $moduleManagerObj->getModelClasses();
$metaData = $moduleManagerObj->getModuleObject(); $metaData = $moduleManagerObj->getModuleObject();
/** @var BaseModel $modelClass */
foreach ($modelClassList as $modelClass) { foreach ($modelClassList as $modelClass) {
$modelClassWithNameSpace = $metaData['model_namespace']."\\".$modelClass; $modelClassWithNameSpace = $metaData['model_namespace']."\\".$modelClass;
$modelClassWithNameSpace::SetDatabaseAdapter($dbLocal); $modelClassWithNameSpace::SetDatabaseAdapter($dbLocal);
$baseService->addModelClass($modelClass, $modelClassWithNameSpace); $baseService->addModelClass($modelClass, $modelClassWithNameSpace);
$modelClassObject = new $modelClassWithNameSpace();
} }
} }
} }

View File

@@ -3,7 +3,10 @@
use Classes\BaseService; use Classes\BaseService;
use Classes\IceResponse; use Classes\IceResponse;
use Classes\PasswordManager; use Classes\PasswordManager;
use Classes\Pdf\PDFRegister;
use Classes\SettingsManager;
use Metadata\Common\Model\SupportedLanguage; use Metadata\Common\Model\SupportedLanguage;
use Model\File;
use Users\Common\Model\User; use Users\Common\Model\User;
use Utils\LogManager; use Utils\LogManager;
use Classes\Exception\IceHttpException; use Classes\Exception\IceHttpException;
@@ -173,19 +176,20 @@ try {// Domain aware input cleanup
$type = strtolower(substr($file->filename, strrpos($file->filename, ".") + 1)); $type = strtolower(substr($file->filename, strrpos($file->filename, ".") + 1));
if ($file->name == $name) { if ($file->name == $name) {
$ret['status'] = "SUCCESS"; $ret['status'] = "SUCCESS";
if (\Classes\SettingsManager::getInstance()->getSetting("Files: Upload Files to S3") == '1') { $file->ext = explode('.', $file->filename)[1];
$uploadFilesToS3Key = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload"); if (SettingsManager::getInstance()->getSetting("Files: Upload Files to S3") == '1') {
$uploadFilesToS3Secret = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazone S3 Secret for File Upload"); $uploadFilesToS3Key = SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting("Files: Amazon S3 Secret for File Upload");
$s3FileSys = new \Classes\S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new \Classes\S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Web Url"); $s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
$fileUrl = $s3WebUrl . CLIENT_NAME . "/" . $file->filename; $fileUrl = $s3WebUrl . CLIENT_NAME . "/" . $file->filename;
$fileUrl = $s3FileSys->generateExpiringURL($fileUrl); $fileUrl = $s3FileSys->generateExpiringURL($fileUrl);
$file->filename = $fileUrl; $file->filename = $fileUrl;
} else { } else {
$file->filename = CLIENT_BASE_URL . 'data/' . $file->filename; $file->filename = \Classes\FileService::getInstance()->getLocalSecureUrl($file->filename);
} }
$ret['data'] = $file; $ret['data'] = BaseService::getInstance()->cleanUpAll($file);
} else { } else {
$ret['status'] = "ERROR"; $ret['status'] = "ERROR";
} }
@@ -193,21 +197,49 @@ try {// Domain aware input cleanup
$fileName = $_REQUEST['file']; $fileName = $_REQUEST['file'];
$fileName = str_replace("..", "", $fileName); $fileName = str_replace("..", "", $fileName);
$fileName = str_replace("/", "", $fileName); $fileName = str_replace("/", "", $fileName);
$fileName = CLIENT_BASE_PATH . 'data/' . $fileName;
if (!file_exists($fileName)) { $file = new File();
$file->Load('name = ?', array($fileName));
if ($fileName !== $file->name) {
$file->Load('filename = ?', array($fileName));
}
if (empty($file->id)) {
exit; exit;
} }
if (!file_exists(CLIENT_BASE_PATH . 'data/' . $file->filename)) {
exit;
}
$extension = explode('.', $file->filename)[1];
header('Content-Description: File Transfer'); header('Content-Description: File Transfer');
if ('png' === $extension) {
header('Content-Type: image/png');
} elseif ('gif' === $extension) {
header('Content-Type: image/png');
} elseif ('jpg' === $extension || 'jpeg' === $extension) {
header('Content-Type: image/jpeg');
} elseif ('pdf' === $extension) {
header('Content-Type: application/pdf');
} elseif ('xml' === $extension) {
header('Content-Type: application/xml');
} else {
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($fileName));
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
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($fileName)); }
header('Content-Disposition: attachment; filename=' . basename($file->filename));
header('Content-Length: ' . filesize(CLIENT_BASE_PATH . 'data/' . $file->filename));
ob_clean(); ob_clean();
flush(); flush();
readfile($fileName); readfile(CLIENT_BASE_PATH . 'data/' . $file->filename);
exit; exit;
} else if ($action == 'rsp') { // linked clicked from password change email } else if ($action == 'rsp') { // linked clicked from password change email
@@ -305,6 +337,22 @@ try {// Domain aware input cleanup
} }
} }
} }
if ($action == 'pdf') {
$data = $_REQUEST['data'];
$hash = $_REQUEST['h'];
PDFRegister::init();
$callback = PDFRegister::get($hash);
if (empty($callback) || !$callback($data)->granted()) {
$ret['status'] = "ERROR";
$ret['message'] = "Invalid request";
} else {
$pdfBuilder = $callback($data);
$pdf = $pdfBuilder->createPdf();
$pdf->SetAuthor(SettingsManager::getInstance()->getSetting('Company: Name'));
$pdf->Output();
}
} else {
try { try {
echo BaseService::getInstance()->safeJsonEncode($ret); echo BaseService::getInstance()->safeJsonEncode($ret);
} catch (Exception $e) { } catch (Exception $e) {
@@ -312,6 +360,8 @@ try {// Domain aware input cleanup
LogManager::getInstance()->notifyException($e); LogManager::getInstance()->notifyException($e);
echo json_encode(['status' => 'Error']); echo json_encode(['status' => 'Error']);
} }
}
} catch (IceHttpException $e) { } catch (IceHttpException $e) {
http_response_code($e->getCode()); http_response_code($e->getCode());
echo json_encode(['message' => $e->getMessage()]); echo json_encode(['message' => $e->getMessage()]);

View File

@@ -109,11 +109,10 @@ class AttendanceStatus extends BaseModel
$data[] = $entry; $data[] = $entry;
} }
function cmp($a, $b)
{ usort($data, function ($a, $b) {
return $a->statusId - $b->statusId; return $a->statusId - $b->statusId;
} });
usort($data, "cmp");
return $data; return $data;
} }

View File

@@ -33,8 +33,7 @@ class AttendanceActionManager extends SubActionManager
//Find any open punch //Find any open punch
$attendance = new Attendance(); $attendance = new Attendance();
$attendance->Load( $attendance->Load(
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and (out_time is NULL "employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and out_time is NULL",
or out_time = '0000-00-00 00:00:00')",
array($employee->id,$date) array($employee->id,$date)
); );

View File

@@ -7,6 +7,7 @@
*/ */
namespace Classes; namespace Classes;
use Model\BaseModel;
use Utils\LogManager; use Utils\LogManager;
abstract class AbstractModuleManager abstract class AbstractModuleManager
@@ -254,7 +255,17 @@ abstract class AbstractModuleManager
protected function addModelClass($className) protected function addModelClass($className)
{ {
$this->modelClasses[] = $className; $this->modelClasses[] = $className;
BaseService::getInstance()->addModelClass($className, $this->moduleObject['model_namespace']."\\".$className); $classWithNamespace = $this->moduleObject['model_namespace']."\\".$className;
BaseService::getInstance()->addModelClass($className, $classWithNamespace);
/** @var BaseModel $modelClass */
$modelClass = new $classWithNamespace();
if ($modelClass->isCustomFieldsEnabled()) {
$objectName = $modelClass->getObjectName();
BaseService::getInstance()->addCustomFieldClass(
$className,
(null === $objectName)? $className : $objectName
);
}
} }
protected function addHistoryGeneric($type, $table, $refName, $refId, $field, $oldValue, $newValue) protected function addHistoryGeneric($type, $table, $refName, $refId, $field, $oldValue, $newValue)
@@ -278,4 +289,12 @@ abstract class AbstractModuleManager
{ {
BaseService::getInstance()->addCalculationHook($code, $name, $class, $method); BaseService::getInstance()->addCalculationHook($code, $name, $class, $method);
} }
public function install()
{
}
public function uninstall()
{
}
} }

View File

@@ -0,0 +1,8 @@
<?php
namespace Classes;
interface Authorizable
{
public function granted() : bool;
}

View File

@@ -19,8 +19,10 @@ use Employees\Common\Model\EmployeeApproval;
use FieldNames\Common\Model\CustomField; use FieldNames\Common\Model\CustomField;
use FieldNames\Common\Model\FieldNameMapping; use FieldNames\Common\Model\FieldNameMapping;
use Metadata\Common\Model\CalculationHook; use Metadata\Common\Model\CalculationHook;
use Model\BaseModel;
use Model\DataEntryBackup; use Model\DataEntryBackup;
use Model\Setting; use Model\Setting;
use Model\SystemData;
use Modules\Common\Model\Module; use Modules\Common\Model\Module;
use Permissions\Common\Model\Permission; use Permissions\Common\Model\Permission;
use Users\Common\Model\User; use Users\Common\Model\User;
@@ -51,7 +53,8 @@ class BaseService
public $calculationHooks = array(); public $calculationHooks = array();
public $customFieldManager = null; public $customFieldManager = null;
public $migrationManager = null; public $migrationManager = null;
public $modelClassMap = array(); public $modelClassMap = [];
public $customFieldsClassMap = [];
public $currentProfileId = false; public $currentProfileId = false;
protected $cacheService = null; protected $cacheService = null;
@@ -167,6 +170,20 @@ class BaseService
$this->modelClassMap[$modelClass] = $fullQualifiedName; $this->modelClassMap[$modelClass] = $fullQualifiedName;
} }
public function getCustomFieldClassMap()
{
$map = [];
foreach ($this->customFieldsClassMap as $key => $val) {
$map[] = [$key, $val];
}
return $map;
}
public function addCustomFieldClass($customFieldsClass, $objectName)
{
$this->customFieldsClassMap[$customFieldsClass] = $objectName;
}
public function getModelClassName($name) public function getModelClassName($name)
{ {
return $this->getFullQualifiedModelClassName($name); return $this->getFullQualifiedModelClassName($name);
@@ -637,7 +654,10 @@ class BaseService
$processedList = array(); $processedList = array();
foreach ($list as $obj) { foreach ($list as $obj) {
$processedList[] = $this->cleanUpAdoDB($obj->postProcessGetData($obj)); $processedObj = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
if (null !== $processedObj) {
$processedList[] = $processedObj;
}
} }
$list = $processedList; $list = $processedList;
@@ -749,7 +769,7 @@ class BaseService
$obj = $this->enrichObjectCustomFields($table, $obj); $obj = $this->enrichObjectCustomFields($table, $obj);
$obj = $obj->postProcessGetElement($obj); $obj = $obj->postProcessGetElement($obj);
return $this->cleanUpAdoDB($obj->postProcessGetData($obj)); return $this->cleanUpAdoDB($obj);
} }
return null; return null;
} }
@@ -928,6 +948,7 @@ class BaseService
{ {
$fileFields = $this->fileFields; $fileFields = $this->fileFields;
$nsTable = $this->getFullQualifiedModelClassName($table); $nsTable = $this->getFullQualifiedModelClassName($table);
/** @var BaseModel $ele */
$ele = new $nsTable(); $ele = new $nsTable();
$ele->Load('id = ?', array($id)); $ele->Load('id = ?', array($id));
@@ -985,7 +1006,7 @@ class BaseService
$dataEntryBackup->data = json_encode($newObj); $dataEntryBackup->data = json_encode($newObj);
$dataEntryBackup->Save(); $dataEntryBackup->Save();
} }
$ele->executePostDeleteActions($ele);
$this->audit(IceConstants::AUDIT_DELETE, "Deleted an object in ".$table." [id:".$ele->id."]"); $this->audit(IceConstants::AUDIT_DELETE, "Deleted an object in ".$table." [id:".$ele->id."]");
} }
@@ -998,6 +1019,7 @@ class BaseService
} }
$cfs = $this->customFieldManager->getCustomFields($table, $id); $cfs = $this->customFieldManager->getCustomFields($table, $id);
/** @var CustomField $cf */
foreach ($cfs as $cf) { foreach ($cfs as $cf) {
$cf->Delete(); $cf->Delete();
} }
@@ -1957,4 +1979,38 @@ END;
$dbUser = $this->getCurrentDBUser(); $dbUser = $this->getCurrentDBUser();
return RestApiManager::getInstance()->getAccessTokenForUser($dbUser); return RestApiManager::getInstance()->getAccessTokenForUser($dbUser);
} }
public function isSubordinateEmployee($supervisorId, $subordinateId)
{
$employee = new Employee();
$employee->Load('id = ? and supervisor = ?', [$subordinateId, $supervisorId]);
return ($supervisorId == $employee->supervisor && $subordinateId == $employee->id);
}
public function setSystemData($name, $value)
{
$sysData = new SystemData();
$sysData->Load('name = ?', [$name]);
if (!empty($sysData->id)) {
$sysData->value = $value;
} else {
$sysData->name = $name;
$sysData->value = $value;
}
return $sysData->Save();
}
public function getSystemData($name)
{
$sysData = new SystemData();
$sysData->Load('name = ?', [$name]);
if (!empty($sysData->id) && $sysData->name === $name) {
return $sysData->value;
}
return null;
}
} }

View File

@@ -90,6 +90,14 @@ class DomainAwareInputCleaner
private function isValidFilterValue($input) private function isValidFilterValue($input)
{ {
if (is_array($input)) {
$isValid = true;
foreach ($input as $val) {
$isValid = $isValid && !!preg_match('/^[-_: \d\p{L}]+$/u', $val);
}
return $isValid;
}
return !!preg_match('/^[-_: \d\p{L}]+$/u', $input); return !!preg_match('/^[-_: \d\p{L}]+$/u', $input);
} }
} }

View File

@@ -0,0 +1,146 @@
<?php
namespace Classes;
use Utils\LogManager;
class ExtensionManager
{
const GROUP = 'extension';
protected function processExtensionInDB()
{
$dbModule = new \Modules\Common\Model\Module();
$extensions = $dbModule->Find("mod_group = ?", array(self::GROUP));
$extensionsInDB = [];
foreach ($extensions as $dbm) {
$extensionsInDB[$dbm->name] = $dbm;
ModuleAccessService::getInstance()->setModule($dbm->name, self::GROUP, $dbm);
}
return $extensionsInDB;
}
public function getExtensionsPath()
{
return APP_BASE_PATH.'../extensions/';
}
public function getExtensionMetaData($extensionName)
{
return json_decode(file_get_contents($this->getExtensionsPath().$extensionName.'/meta.json'));
}
public function setupExtensions()
{
$menu = [];
$extensions = [];
$extensionDirs = scandir($this->getExtensionsPath());
$currentLocation = 0;
$extensionsInDB = $this->processExtensionInDB();
$needToInstall = false;
foreach ($extensionDirs as $extensionDir) {
if (is_dir($this->getExtensionsPath().$extensionDir) && $extensionDir != '.' && $extensionDir != '..') {
$meta = $this->getExtensionMetaData($extensionDir);
$arr = [];
$arr['name'] = $extensionDir;
$arr['label'] = $meta->label;
$arr['icon'] = $meta->icon;
$arr['menu'] = $meta->menu[0];
$arr['order'] = 0;
$arr['status'] = 'Enabled';
$arr['user_levels'] = $meta->user_levels;
$arr['user_roles'] = isset($meta->user_roles)?$meta->user_roles:"";
$arr['model_namespace'] = $meta->model_namespace;
$arr['manager'] = $meta->manager;
// Add menu
$menu[$meta->menu[0]] = $meta->menu[1];
//Check in admin dbmodules
if (isset($extensionsInDB[$arr['name']])) {
$dbModule = $extensionsInDB[$arr['name']];
$arr['name'] = $dbModule->name;
$arr['label'] = $dbModule->label;
$arr['icon'] = $dbModule->icon;
$arr['menu'] = $dbModule->menu;
$arr['status'] = $dbModule->status;
$arr['user_levels'] = json_decode($dbModule->user_levels);
$arr['user_roles'] = empty($dbModule->user_roles)
? [] : json_decode($dbModule->user_roles);
$arr['user_roles_blacklist'] = empty($dbModule->user_roles_blacklist)
? [] : json_decode($dbModule->user_roles_blacklist);
} else {
$dbModule = new \Modules\Common\Model\Module();
$dbModule->menu = $arr['menu'];
$dbModule->name = $arr['name'];
$dbModule->label = $arr['label'];
$dbModule->icon = $arr['icon'];
$dbModule->mod_group = self::GROUP;
$dbModule->mod_order = $arr['order'];
$dbModule->status = "Enabled";
$dbModule->version = isset($meta->version)?$meta->version:"";
$dbModule->update_path = self::GROUP.">".$extensionDir;
$dbModule->user_levels = isset($meta->user_levels)?json_encode($meta->user_levels):"";
$dbModule->user_roles = isset($meta->user_roles)?json_encode($meta->user_roles):"";
$ok = $dbModule->Save();
if (!$ok) {
LogManager::getInstance()->error('Error saving module: '.$dbModule->name);
}
$needToInstall = $ok;
}
/* @var \Classes\AbstractModuleManager */
$manager = $this->includeModuleManager($extensionDir, $arr);
if ($dbModule->status == 'Disabled') {
continue;
}
if ($needToInstall) {
$manager->install();
}
$menuName = $arr['menu'];
if (!isset($extensions[$menuName])) {
$extensions[$menuName] = array();
}
if (!$meta->headless) {
if ($arr['order'] == '0' || $arr['order'] == '') {
$extensions[$menuName]["Z".$currentLocation] = $arr;
$currentLocation++;
} else {
$extensions[$arr['menu']]["A".$arr['order']] = $arr;
}
}
$initializer = $manager->getInitializer();
if ($initializer !== null) {
$initializer->setBaseService(BaseService::getInstance());
$initializer->init();
}
}
}
return [$menu, $extensions];
}
public function includeModuleManager($name, $data)
{
include($this->getExtensionsPath().$name.'/'.$name.'.php');
$moduleManagerClass = $data['manager'];
/* @var \Classes\AbstractModuleManager $moduleManagerObj*/
$moduleManagerObj = new $moduleManagerClass();
$moduleManagerObj->setModuleObject($data);
$moduleManagerObj->setModuleType(self::GROUP);
$moduleManagerObj->setModulePath(CLIENT_PATH.'/'.self::GROUP.'/'.$name);
\Classes\BaseService::getInstance()->addModuleManager($moduleManagerObj);
return $moduleManagerObj;
}
}

View File

@@ -76,15 +76,20 @@ class FileService
if (file_exists("/tmp/".$file->filename."_orig")) { if (file_exists("/tmp/".$file->filename."_orig")) {
//Resize image to 100 //Resize image to 100
try {
$img = new \Classes\SimpleImage("/tmp/" . $file->filename . "_orig"); $img = new \Classes\SimpleImage("/tmp/" . $file->filename . "_orig");
$img->fitToWidth(140); $img->fitToWidth(140);
$img->save("/tmp/" . $file->filename); $img->save("/tmp/" . $file->filename);
} catch (\Exception $e) {
LogManager::getInstance()->error($e->getTraceAsString());
return null;
}
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload" "Files: Amazon S3 Key for File Upload"
); );
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket"); $s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
@@ -94,6 +99,8 @@ class FileService
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read'); $result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read');
$file->size = filesize($localFile);
unlink("/tmp/".$file->filename); unlink("/tmp/".$file->filename);
unlink("/tmp/".$file->filename."_orig"); unlink("/tmp/".$file->filename."_orig");
@@ -101,7 +108,6 @@ class FileService
$file->employee = $profileImage->employee; $file->employee = $profileImage->employee;
$file->file_group = 'profile_image_small'; $file->file_group = 'profile_image_small';
$file->size = filesize(CLIENT_BASE_PATH.'data/'.$file->filename);
$file->size_text = $this->getReadableSize($file->size); $file->size_text = $this->getReadableSize($file->size);
if (!empty($result)) { if (!empty($result)) {
@@ -131,11 +137,7 @@ class FileService
if (empty($file->id)) { if (empty($file->id)) {
LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found"); LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found");
$largeFileUrl = $this->getFileUrl($profileImage->name); if (file_exists(CLIENT_BASE_PATH.'data/'.$profileImage->filename)) {
file_put_contents("/tmp/".$profileImage->filename."_orig", file_get_contents($largeFileUrl));
if (file_exists("/tmp/".$profileImage->filename."_orig")) {
//Resize image to 100 //Resize image to 100
$file->name = $profileImage->name."_small"; $file->name = $profileImage->name."_small";
@@ -143,16 +145,19 @@ class FileService
$file->$signInMappingField = $profileImage->$signInMappingField; $file->$signInMappingField = $profileImage->$signInMappingField;
$file->filename = $file->name.str_replace($profileImage->name, "", $profileImage->filename); $file->filename = $file->name.str_replace($profileImage->name, "", $profileImage->filename);
$img = new \Classes\SimpleImage("/tmp/".$profileImage->filename."_orig"); try {
$img = new \Classes\SimpleImage(CLIENT_BASE_PATH . 'data/' . $profileImage->filename);
$img->fitToWidth(140); $img->fitToWidth(140);
$img->save(CLIENT_BASE_PATH . 'data/' . $file->filename); $img->save(CLIENT_BASE_PATH . 'data/' . $file->filename);
$file->employee = $profileImage->employee; $file->employee = $profileImage->employee;
$file->file_group = 'profile_image_small'; $file->file_group = 'profile_image_small';
$file->size = filesize(CLIENT_BASE_PATH . 'data/' . $file->filename); $file->size = filesize(CLIENT_BASE_PATH . 'data/' . $file->filename);
$file->size_text = $this->getReadableSize($file->size); $file->size_text = $this->getReadableSize($file->size);
$file->Save(); $file->Save();
unlink("/tmp/".$file->filename."_orig"); } catch (\Exception $e) {
LogManager::getInstance()->error($e->getTraceAsString());
return null;
}
return $file; return $file;
} }
@@ -181,7 +186,7 @@ class FileService
"Files: Amazon S3 Key for File Upload" "Files: Amazon S3 Key for File Upload"
); );
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url"); $s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
@@ -203,7 +208,7 @@ class FileService
$profile->image = $file->filename; $profile->image = $file->filename;
} else { } else {
$fileNew = $this->checkAddSmallProfileImage($file); $fileNew = $this->checkAddSmallProfileImage($file);
$profile->image = CLIENT_BASE_URL.'data/'.$fileNew->filename; $profile->image = $this->getFileUrl($fileNew->filename);
} }
} else { } else {
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name); $profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
@@ -224,7 +229,7 @@ class FileService
"Files: Amazon S3 Key for File Upload" "Files: Amazon S3 Key for File Upload"
); );
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url"); $s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
@@ -240,7 +245,7 @@ class FileService
} elseif (substr($file->filename, 0, 8) === 'https://') { } elseif (substr($file->filename, 0, 8) === 'https://') {
$profile->image = $file->filename; $profile->image = $file->filename;
} else { } else {
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename; $profile->image = $this->getLocalSecureUrl($file->filename);
} }
} else { } else {
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name); $profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
@@ -254,6 +259,10 @@ class FileService
$file = new File(); $file = new File();
$file->Load('name = ?', array($fileName)); $file->Load('name = ?', array($fileName));
if ($fileName !== $file->name) {
$file->Load('filename = ?', array($fileName));
}
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3"); $uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") { if ($uploadFilesToS3 == "1") {
@@ -261,7 +270,7 @@ class FileService
"Files: Amazon S3 Key for File Upload" "Files: Amazon S3 Key for File Upload"
); );
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url"); $s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
@@ -281,10 +290,22 @@ class FileService
return $expireUrl; return $expireUrl;
} else { } else {
return CLIENT_BASE_URL.'data/'.$file->filename; return CLIENT_BASE_URL.'service.php?a=download&file='.$file->filename;
} }
} }
public function getLocalSecureUrl($fileName)
{
$file = new File();
$file->Load('name = ?', array($fileName));
if ($fileName !== $file->name) {
$file->Load('filename = ?', array($fileName));
}
return CLIENT_BASE_URL.'service.php?a=download&file='.$file->filename;
}
public function deleteProfileImage($profileId) public function deleteProfileImage($profileId)
{ {
$file = new File(); $file = new File();
@@ -293,8 +314,7 @@ class FileService
if ($file->employee == $profileId) { if ($file->employee == $profileId) {
$ok = $file->Delete(); $ok = $file->Delete();
if ($ok) { if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename); $this->deleteFileFromDisk($file);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else { } else {
return false; return false;
} }
@@ -306,8 +326,7 @@ class FileService
if ($file->employee == $profileId) { if ($file->employee == $profileId) {
$ok = $file->Delete(); $ok = $file->Delete();
if ($ok) { if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename); $this->deleteFileFromDisk($file);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else { } else {
return false; return false;
} }
@@ -317,6 +336,30 @@ class FileService
return true; return true;
} }
public function deleteFileFromDisk($file)
{
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Secret for File Upload"
);
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
$uploadname = CLIENT_NAME."/".$file->filename;
LogManager::getInstance()->info("Delete from S3:".$uploadname);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3FileSys->deleteObject($s3Bucket, $uploadname);
} else {
LogManager::getInstance()->info("Delete:".CLIENT_BASE_PATH.'data/'.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
}
}
public function deleteFileByField($value, $field) public function deleteFileByField($value, $field)
{ {
LogManager::getInstance()->info("Delete file by field: $field / value: $value"); LogManager::getInstance()->info("Delete file by field: $field / value: $value");
@@ -332,7 +375,7 @@ class FileService
"Files: Amazon S3 Key for File Upload" "Files: Amazon S3 Key for File Upload"
); );
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting( $uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload" "Files: Amazon S3 Secret for File Upload"
); );
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket"); $s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
@@ -377,15 +420,34 @@ class FileService
{ {
$seed = substr($first, 0, 1); $seed = substr($first, 0, 1);
if (empty($last)) { if (empty($last)) {
$seed .= substr($first, -1); $seed .= utf8_encode(substr($first, -1));
} else { } else {
$seed .= substr($last, 0, 1); $seed .= utf8_encode(substr($last, 0, 1));
} }
md5($seed . $last); // TODO - remove code after chinese character issue is resolved
// if(strlen($seed) != mb_strlen($seed, 'utf-8')) {
// $char1 = substr($first, 0, 1);
// $char1 = chr($this->uniord($char1) % 26 + 65);
// if (empty($last)) {
// $char2 = substr($first, -1);
// } else {
// $char2 = substr($last, 0, 1);
// }
// $char2 = chr($this->uniord($char2) % 26 + 65);
// $seed = $char1.$char2;
// }
return sprintf( return sprintf(
'https://avatars.dicebear.com/api/initials/:%s.svg', 'https://avatars.dicebear.com/api/initials/:%s.svg',
$seed . substr(md5($first . $last), -5) $seed . substr(md5($first . $last), -5)
); );
} }
private function uniord($u)
{
$k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
$k1 = ord(substr($k, 0, 1));
$k2 = ord(substr($k, 1, 1));
return $k2 * 256 + $k1;
}
} }

View File

@@ -0,0 +1,20 @@
<?php
namespace Classes;
abstract class IceExtension extends AbstractModuleManager
{
public function initializeUserClasses()
{
// TODO: Implement initializeUserClasses() method.
}
public function initializeFieldMappings()
{
// TODO: Implement initializeFieldMappings() method.
}
public function initializeDatabaseErrorMappings()
{
// TODO: Implement initializeDatabaseErrorMappings() method.
}
}

177
core/src/Classes/IceRoute.php Executable file
View File

@@ -0,0 +1,177 @@
<?php
namespace Classes;
/**
* @method static IceRoute get(string $route, Callable $callback)
* @method static IceRoute post(string $route, Callable $callback)
* @method static IceRoute put(string $route, Callable $callback)
* @method static IceRoute delete(string $route, Callable $callback)
* @method static IceRoute options(string $route, Callable $callback)
* @method static IceRoute head(string $route, Callable $callback)
*/
class IceRoute
{
public static $halts = false;
public static $routes = array();
public static $methods = array();
public static $callbacks = array();
public static $patterns = array(
':any' => '[^/]+',
':num' => '[0-9]+',
':all' => '.*'
);
public static $error_callback;
/**
* Defines a route w/ callback and method
*/
public static function __callstatic($method, $params)
{
$uri = $params[0][0];
$callback = $params[0][1];
array_push(self::$routes, $uri);
array_push(self::$methods, strtoupper($method));
array_push(self::$callbacks, $callback);
return $uri;
}
/**
* Defines callback if route is not found
*/
public static function error($callback)
{
self::$error_callback = $callback;
}
public static function haltOnMatch($flag = true)
{
self::$halts = $flag;
}
/**
* Runs the callback for the given request
*/
public static function dispatch($uri, $method)
{
$searches = array_keys(static::$patterns);
$replaces = array_values(static::$patterns);
$found_route = false;
self::$routes = str_replace('//', '/', self::$routes);
// check if route is defined without regex
if (in_array($uri, self::$routes)) {
$route_pos = array_keys(self::$routes, $uri);
foreach ($route_pos as $route) {
//using an ANY option to match both GET and POST requests
if (self::$methods[$route] == $method || self::$methods[$route] == 'ANY') {
$found_route = true;
//if route is not an object
if (!is_object(self::$callbacks[$route])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$route]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//call method
$controller->$segments[1]();
if (self::$halts) {
return;
}
} else {
//call closure
call_user_func(self::$callbacks[$route]);
if (self::$halts) {
return;
}
}
}
}
} else {
// check if defined with regex
$pos = 0;
foreach (self::$routes as $route) {
if (strpos($route, ':') !== false) {
$route = str_replace($searches, $replaces, $route);
}
if (preg_match('#^' . $route . '$#', $uri, $matched)) {
if (self::$methods[$pos] == $method) {
$found_route = true;
array_shift($matched); //remove $matched[0] as [1] is the first parameter.
if (!is_object(self::$callbacks[$pos])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$pos]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//fix multi parameters
if (!method_exists($controller, $segments[1])) {
echo "controller and action not found";
} else {
call_user_func_array(array($controller, $segments[1]), $matched);
}
//call method and pass any extra parameters to the method
// $controller->$segments[1](implode(",", $matched));
if (self::$halts) {
return;
}
} else {
call_user_func_array(self::$callbacks[$pos], $matched);
if (self::$halts) {
return;
}
}
}
}
$pos++;
}
}
// run the error callback if the route was not found
if ($found_route == false) {
if (!self::$error_callback) {
self::$error_callback = function () {
header($_SERVER['SERVER_PROTOCOL']." 404 Not Found");
echo '404';
};
}
call_user_func(self::$error_callback);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace Classes; namespace Classes;
use Firebase\JWT\JWT; use Firebase\JWT\JWT;
use Firebase\JWT\SignatureInvalidException;
class JwtTokenService class JwtTokenService
{ {
@@ -22,7 +23,11 @@ class JwtTokenService
public function getBaseToken($jwtToken) public function getBaseToken($jwtToken)
{ {
$secret = APP_SEC.APP_PASSWORD; $secret = APP_SEC.APP_PASSWORD;
try {
$jwt = JWT::decode($jwtToken, $secret, array('HS256')); $jwt = JWT::decode($jwtToken, $secret, array('HS256'));
} catch (SignatureInvalidException $e) {
return null;
}
if (time() > intval($jwt->expire)) { if (time() > intval($jwt->expire)) {
return null; return null;

View File

@@ -42,6 +42,8 @@ class Macaw
array_push(self::$methods, strtoupper($method)); array_push(self::$methods, strtoupper($method));
array_push(self::$callbacks, $callback); array_push(self::$callbacks, $callback);
call_user_func('\Classes\IceRoute::'.$method, $params);
return $uri; return $uri;
} }

View File

@@ -15,6 +15,8 @@ class MemcacheService
public static $openConnections = array(); public static $openConnections = array();
private static $me = null; private static $me = null;
protected $inMemoryStore = [];
private function __construct() private function __construct()
{ {
} }
@@ -56,6 +58,15 @@ class MemcacheService
} }
public function set($key, $value, $expiry = 3600) public function set($key, $value, $expiry = 3600)
{
if (!$this->setInServer($key, $value, $expiry)) {
$this->inMemoryStore[$this->compressKey($key)] = $value;
}
return true;
}
public function setInServer($key, $value, $expiry = 3600)
{ {
if (!class_exists('\\Memcached')) { if (!class_exists('\\Memcached')) {
return false; return false;
@@ -74,6 +85,19 @@ class MemcacheService
} }
public function get($key) public function get($key)
{
$data = $this->getFromServer($key);
if ($data) {
return $data;
}
if (isset($this->inMemoryStore[$this->compressKey($key)])) {
return $this->inMemoryStore[$this->compressKey($key)];
}
return false;
}
public function getFromServer($key)
{ {
if (!class_exists('\\Memcached')) { if (!class_exists('\\Memcached')) {
return false; return false;

View File

@@ -8,6 +8,8 @@
namespace Classes\Migration; namespace Classes\Migration;
use Utils\LogManager;
abstract class AbstractMigration abstract class AbstractMigration
{ {
protected $file; protected $file;
@@ -16,7 +18,7 @@ abstract class AbstractMigration
protected $lastError; protected $lastError;
public function __construct($file) public function __construct($file = null)
{ {
$this->file = $file; $this->file = $file;
} }
@@ -50,6 +52,7 @@ abstract class AbstractMigration
$ret = $this->db()->Execute($sql); $ret = $this->db()->Execute($sql);
if (!$ret) { if (!$ret) {
$this->lastError = $this->db()->ErrorMsg(); $this->lastError = $this->db()->ErrorMsg();
LogManager::getInstance()->error('Error in migration: '.$this->lastError);
} }
return $ret; return $ret;
} }

Some files were not shown because too many files have changed in this diff Show More