Compare commits
55 Commits
feature/cu
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f44b9ec8dd | ||
|
|
ad4fe1cc29 | ||
|
|
8fbf8f2152 | ||
|
|
74309fc922 | ||
|
|
a042ee67ec | ||
|
|
41ebd61c8e | ||
|
|
111781b327 | ||
|
|
74e448bf5d | ||
|
|
66b3f006e6 | ||
|
|
40df433580 | ||
|
|
499c52516e | ||
|
|
e94a365d71 | ||
|
|
e88f5f8a1a | ||
|
|
c0ce41ed2f | ||
|
|
944d5f1f88 | ||
|
|
47871d9551 | ||
|
|
46e3bf439e | ||
|
|
b858a62d42 | ||
|
|
6da42b4842 | ||
|
|
b7b128f9a7 | ||
|
|
7a9f7ec36e | ||
|
|
a7218a6666 | ||
|
|
87dc692faa | ||
|
|
042180b805 | ||
|
|
49a22ebdf0 | ||
|
|
f1d4b3915e | ||
|
|
b4bec17934 | ||
|
|
24db01729d | ||
|
|
b4fc0db4de | ||
|
|
c00fb95319 | ||
|
|
142395591e | ||
|
|
235924f80b | ||
|
|
8f8034556a | ||
|
|
f12a467099 | ||
|
|
91c2c32c0c | ||
|
|
aacff040bb | ||
|
|
e889b856bc | ||
|
|
548df6f408 | ||
|
|
2ca9eaa083 | ||
|
|
3eaf290a58 | ||
|
|
c276009bd8 | ||
|
|
ea93d4604c | ||
|
|
caf41de755 | ||
|
|
45d80e9440 | ||
|
|
bb8f11963a | ||
|
|
6581d1424e | ||
|
|
253b298b0d | ||
|
|
df554680c4 | ||
|
|
92032cf1eb | ||
|
|
22cd81611d | ||
|
|
1a3e468458 | ||
|
|
88962d4380 | ||
|
|
3b1285aeaf | ||
|
|
b73e244865 | ||
|
|
5f050282f0 |
5
.eslintrc
Normal file
5
.eslintrc
Normal 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
2
.gitignore
vendored
@@ -13,6 +13,8 @@ keys.dev.pub
|
||||
/app/icehrm.key
|
||||
/app/data/*.*
|
||||
/app/data/keys/*
|
||||
!/app/data/index.php
|
||||
!/app/data/.htaccess
|
||||
icehrm.key
|
||||
cache.properties
|
||||
node_modules/*
|
||||
|
||||
2
app/data/.htaccess
Normal file
2
app/data/.htaccess
Normal file
@@ -0,0 +1,2 @@
|
||||
order deny,allow
|
||||
deny from all
|
||||
1
app/data/index.php
Normal file
1
app/data/index.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
3
app/fileupload-new.php
Normal file
3
app/fileupload-new.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
include ('config.php');
|
||||
include (APP_BASE_PATH.'fileupload-new.php');
|
||||
@@ -19,7 +19,10 @@ $isConfigFileWriteable = is_writable(CLIENT_APP_PATH."config.php");
|
||||
error_log("Config writable ".$isConfigFileWriteable);
|
||||
error_log("Config exists ".file_exists(CLIENT_APP_PATH."config.php"));
|
||||
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");
|
||||
@@ -48,7 +51,7 @@ if(!$isDataFolderExists){
|
||||
unlink(CLIENT_APP_PATH."data/test.txt");
|
||||
}
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
core/.htaccess
Normal file
2
core/.htaccess
Normal file
@@ -0,0 +1,2 @@
|
||||
order deny,allow
|
||||
deny from all
|
||||
@@ -4,48 +4,48 @@
|
||||
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
|
||||
*/
|
||||
|
||||
use Classes\PermissionManager;
|
||||
use Clients\Common\Model\Client;
|
||||
|
||||
$moduleName = 'clients';
|
||||
$moduleGroup = 'admin';
|
||||
define('MODULE_PATH',dirname(__FILE__));
|
||||
include APP_BASE_PATH.'header.php';
|
||||
include APP_BASE_PATH.'modulejslibs.inc.php';
|
||||
define('MODULE_PATH', dirname(__FILE__));
|
||||
include APP_BASE_PATH . 'header.php';
|
||||
include APP_BASE_PATH . 'modulejslibs.inc.php';
|
||||
?><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="tabClient" href="#tabPageClient"><?=t('Clients')?></a></li>
|
||||
<li class="active"><a id="tabClient" href="#tabPageClient"><?= t('Clients') ?></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tabPageClient">
|
||||
<div id="Client" class="reviewBlock" data-content="List" style="padding-left:5px;">
|
||||
|
||||
</div>
|
||||
<div id="ClientForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
|
||||
|
||||
</div>
|
||||
<div id="ClientTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
|
||||
<div id="ClientForm"></div>
|
||||
<div id="ClientFilterForm"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
var modJsList = [];
|
||||
<?php
|
||||
$moduleData = [
|
||||
'user_level' => $user->user_level,
|
||||
'permissions' => [
|
||||
'Client' => PermissionManager::checkGeneralAccess(new Client()),
|
||||
]
|
||||
];
|
||||
?>
|
||||
<script>
|
||||
var data = <?= json_encode($moduleData) ?>;
|
||||
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 }?>
|
||||
modJsList.tabClient.setObjectTypeName('Client');
|
||||
modJsList.tabClient.setAccess(data.permissions.Client);
|
||||
modJsList.tabClient.setDataPipe(new IceDataPipe(modJsList.tabClient));
|
||||
modJsList.tabClient.setRemoteTable(true);
|
||||
|
||||
<?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 }?>
|
||||
|
||||
|
||||
var modJs = modJsList['tabClient'];
|
||||
|
||||
</script>
|
||||
<?php include APP_BASE_PATH.'footer.php';?>
|
||||
var modJs = modJsList['tabClient'];
|
||||
</script>
|
||||
<?php include APP_BASE_PATH . 'footer.php'; ?>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
|
||||
*/
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\PermissionManager;
|
||||
use Company\Common\Model\CompanyStructure;
|
||||
|
||||
@@ -60,6 +61,7 @@ path.link {
|
||||
<?php
|
||||
$moduleData = [
|
||||
'user_level' => $user->user_level,
|
||||
'customFields' => BaseService::getInstance()->getCustomFields("CompanyStructure"),
|
||||
'permissions' => [
|
||||
'CompanyStructure' => PermissionManager::checkGeneralAccess(new CompanyStructure()),
|
||||
]
|
||||
|
||||
59
core/admin/connection/index.php
Normal file
59
core/admin/connection/index.php
Normal 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';?>
|
||||
|
||||
12
core/admin/connection/meta.json
Normal file
12
core/admin/connection/meta.json
Normal 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"
|
||||
}
|
||||
42
core/admin/custom_fields/index.php
Normal file
42
core/admin/custom_fields/index.php
Normal 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';?>
|
||||
|
||||
12
core/admin/custom_fields/meta.json
Normal file
12
core/admin/custom_fields/meta.json
Normal 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"
|
||||
}
|
||||
@@ -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;">
|
||||
<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>
|
||||
|
||||
<div class="tab-content">
|
||||
@@ -25,29 +24,17 @@ include APP_BASE_PATH.'modulejslibs.inc.php';
|
||||
|
||||
</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>
|
||||
<script>
|
||||
var modJsList = new Array();
|
||||
var modJsList = [];
|
||||
|
||||
modJsList['tabEmployeeFieldName'] = new FieldNameAdapter('FieldNameMapping','EmployeeFieldName',{"type":"Employee"});
|
||||
modJsList['tabEmployeeFieldName'].setRemoteTable(true);
|
||||
modJsList['tabEmployeeFieldName'].setShowDelete(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'];
|
||||
|
||||
|
||||
@@ -4,71 +4,65 @@
|
||||
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';
|
||||
$moduleGroup = 'admin';
|
||||
define('MODULE_PATH',dirname(__FILE__));
|
||||
include APP_BASE_PATH.'header.php';
|
||||
include APP_BASE_PATH.'modulejslibs.inc.php';
|
||||
define('MODULE_PATH', dirname(__FILE__));
|
||||
include APP_BASE_PATH . 'header.php';
|
||||
include APP_BASE_PATH . 'modulejslibs.inc.php';
|
||||
|
||||
?><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="tabProject" href="#tabPageProject"><?=t('Projects')?></a></li>
|
||||
<li><a id="tabEmployeeProject" href="#tabPageEmployeeProject"><?=t('Employee 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>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tabPageProject">
|
||||
<div id="Project" class="reviewBlock" data-content="List" style="padding-left:5px;">
|
||||
|
||||
</div>
|
||||
<div id="ProjectForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
|
||||
|
||||
</div>
|
||||
<div id="ProjectTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
|
||||
<div id="ProjectForm"></div>
|
||||
<div id="ProjectFilterForm"></div>
|
||||
</div>
|
||||
<div class="tab-pane" id="tabPageEmployeeProject">
|
||||
<div id="EmployeeProject" class="reviewBlock" data-content="List" style="padding-left:5px;">
|
||||
|
||||
</div>
|
||||
<div id="EmployeeProjectForm" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;">
|
||||
|
||||
</div>
|
||||
<div id="EmployeeProjectTable" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>
|
||||
<div id="EmployeeProjectForm"></div>
|
||||
<div id="EmployeeProjectFilterForm"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
$moduleData = [
|
||||
'user_level' => $user->user_level,
|
||||
'permissions' => [
|
||||
'Project' => PermissionManager::checkGeneralAccess(new Project()),
|
||||
'EmployeeProject' => PermissionManager::checkGeneralAccess(new EmployeeProject()),
|
||||
]
|
||||
];
|
||||
?>
|
||||
<script>
|
||||
var modJsList = [];
|
||||
var modJsList = [];
|
||||
var data = <?= json_encode($moduleData) ?>;
|
||||
modJsList['tabProject'] = new ProjectAdapter('Project', 'Project');
|
||||
modJsList.tabProject.setObjectTypeName('Project');
|
||||
modJsList.tabProject.setAccess(data.permissions.Project);
|
||||
modJsList.tabProject.setDataPipe(new IceDataPipe(modJsList.tabProject));
|
||||
modJsList.tabProject.setRemoteTable(true);
|
||||
|
||||
modJsList['tabProject'] = new ProjectAdapter('Project','Project');
|
||||
|
||||
<?php if(isset($modulePermissions['perm']['Add Projects']) && $modulePermissions['perm']['Add Projects'] == "No"){?>
|
||||
modJsList['tabProject'].setShowAddNew(false);
|
||||
<?php }?>
|
||||
|
||||
<?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);
|
||||
modJsList.tabEmployeeProject.setObjectTypeName('Employee Project');
|
||||
modJsList.tabEmployeeProject.setAccess(data.permissions.EmployeeProject);
|
||||
modJsList.tabEmployeeProject.setDataPipe(new IceDataPipe(modJsList.tabEmployeeProject));
|
||||
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 }?>
|
||||
|
||||
|
||||
var modJs = modJsList['tabProject'];
|
||||
var modJs = modJsList['tabProject'];
|
||||
|
||||
</script>
|
||||
<?php include APP_BASE_PATH.'footer.php';?>
|
||||
<?php include APP_BASE_PATH . 'footer.php'; ?>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
use Classes\ModuleBuilder\ModuleBuilder;
|
||||
use Classes\ModuleBuilder\ModuleTab;
|
||||
use Classes\UIManager;
|
||||
|
||||
$moduleName = 'settings';
|
||||
$moduleGroup = 'admin';
|
||||
@@ -19,32 +20,46 @@ $options1 = array();
|
||||
$options1['setShowAddNew'] = 'false';
|
||||
$options1['setRemoteTable'] = 'true';
|
||||
|
||||
$notCloud = !defined('IS_CLOUD') || IS_CLOUD == false;
|
||||
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'CompanySetting','Setting','Company','SettingAdapter','{"category":"Company"}','name',true,$options1
|
||||
));
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'SystemSetting','Setting','System','SettingAdapter','{"category":"System"}','name',false,$options1
|
||||
));
|
||||
if (!defined('CLOUD_INSTALLATION')) {
|
||||
if ( $notCloud ) {
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'EmailSetting', 'Setting', 'Email', 'SettingAdapter', '{"category":"Email"}', 'name', false, $options1
|
||||
));
|
||||
}
|
||||
if(defined('LEAVE_ENABLED') && LEAVE_ENABLED == true) {
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'LeaveSetting', 'Setting', 'Leave', 'SettingAdapter', '{"category":"Leave"}', 'name', false, $options1
|
||||
));
|
||||
}
|
||||
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'LeaveSetting','Setting','Leave / PTO','SettingAdapter','{"category":"Leave"}','name',false,$options1
|
||||
'AttendanceSetting','Setting','Attendance','SettingAdapter','{"category":"Attendance"}','name',false,$options1
|
||||
));
|
||||
|
||||
if(!defined('LDAP_ENABLED') || LDAP_ENABLED == true){
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'LDAPSetting','Setting','LDAP','SettingAdapter','{"category":"LDAP"}','name',false,$options1
|
||||
));
|
||||
}
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'AttendanceSetting','Setting','Attendance','SettingAdapter','{"category":"Attendance"}','name',false,$options1
|
||||
));
|
||||
|
||||
if(!defined('SAML_ENABLED') || SAML_ENABLED == true){
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'SAMLSetting','Setting','SAML','SettingAdapter','{"category":"SAML"}','name',false,$options1
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
$moduleBuilder->addModuleOrGroup(new ModuleTab(
|
||||
'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>
|
||||
<script>
|
||||
|
||||
@@ -31,22 +31,6 @@ $moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
|
||||
$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);
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ include("server.includes.inc.php");
|
||||
|
||||
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
|
||||
|
||||
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit();
|
||||
|
||||
@@ -13,14 +13,13 @@ if(!defined('HOME_LINK_OTHERS')){
|
||||
}
|
||||
|
||||
//Version
|
||||
define('VERSION', '28.1.1.OS');
|
||||
define('CACHE_VALUE', '28.1.1.OS.2020-11071143');
|
||||
define('VERSION_NUMBER', '280101');
|
||||
define('VERSION_DATE', '07/11/2020');
|
||||
define('VERSION', '30.0.0.OS');
|
||||
define('CACHE_VALUE', '30.0.0.OS.2021-06261009');
|
||||
define('VERSION_NUMBER', '300000');
|
||||
define('VERSION_DATE', '26/06/2021');
|
||||
|
||||
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
|
||||
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}
|
||||
if(!defined('APP_SEC')){define('APP_SEC','dbcs234d2saaqw');}
|
||||
|
||||
define('UI_SHOW_SWITCH_PROFILE', true);
|
||||
define('CRON_LOG', ini_get('error_log'));
|
||||
@@ -33,7 +32,10 @@ if(!defined('WK_HTML_PATH')){
|
||||
}
|
||||
define('ALL_CLIENT_BASE_PATH', '/var/www/icehrm.app/icehrmapp/');
|
||||
|
||||
define('IS_CLOUD', false);
|
||||
define('LDAP_ENABLED', true);
|
||||
define('SAML_ENABLED', true);
|
||||
define('LEAVE_ENABLED', true);
|
||||
define('RECRUITMENT_ENABLED', false);
|
||||
define('APP_WEB_URL', 'https://icehrm.com');
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<?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';
|
||||
?>
|
||||
@@ -139,7 +139,7 @@ $result = $uploader->handleUpload(CLIENT_BASE_PATH.'data/',$saveFileName);
|
||||
$uploadFilesToS3 = \Classes\SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
|
||||
$uploadFilesToS3Key = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
|
||||
$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");
|
||||
$s3WebUrl = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
@@ -188,7 +188,7 @@ if($result['success'] == 1){
|
||||
if($uploadedToS3){
|
||||
$result['data'] = $file_url;
|
||||
}else{
|
||||
$result['data'] = CLIENT_BASE_URL.'data/'.$result['filename'];
|
||||
$result['data'] = \Classes\FileService::getInstance()->getLocalSecureUrl($result['filename']);
|
||||
}
|
||||
$result['data'] .= "|".$saveFileName;
|
||||
$result['data'] .= "|".$file->id;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
modJsList[prop].setUser(<?=json_encode(\Classes\BaseService::getInstance()->cleanUpUser($user))?>);
|
||||
modJsList[prop].initSourceMappings();
|
||||
modJsList[prop].setBaseUrl('<?=BASE_URL?>');
|
||||
modJsList[prop].setClientUrl('<?=CLIENT_BASE_URL?>');
|
||||
modJsList[prop].setCurrentProfile(<?=json_encode($activeProfile)?>);
|
||||
modJsList[prop].setInstanceId('<?=\Classes\BaseService::getInstance()->getInstanceId()?>');
|
||||
modJsList[prop].setGoogleAnalytics(ga);
|
||||
@@ -146,7 +147,9 @@
|
||||
|
||||
|
||||
</script>
|
||||
<?php include 'popups.php';?>
|
||||
<?php
|
||||
include 'popups.php';
|
||||
?>
|
||||
<script src="<?=BASE_URL?>js/bootstrap-datatable.js"></script>
|
||||
<div id="jt" t="<?=$jwtService->create(3600)?>"></div>
|
||||
</body>
|
||||
|
||||
171
core/lib/fpdf/changelog.htm
Normal file
171
core/lib/fpdf/changelog.htm
Normal 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> * The line thickness was too large when printed under Windows 98 SE and ME.<br> * 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>
|
||||
10
core/lib/fpdf/font/courier.php
Normal file
10
core/lib/fpdf/font/courier.php
Normal 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));
|
||||
?>
|
||||
10
core/lib/fpdf/font/courierb.php
Normal file
10
core/lib/fpdf/font/courierb.php
Normal 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));
|
||||
?>
|
||||
10
core/lib/fpdf/font/courierbi.php
Normal file
10
core/lib/fpdf/font/courierbi.php
Normal 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));
|
||||
?>
|
||||
10
core/lib/fpdf/font/courieri.php
Normal file
10
core/lib/fpdf/font/courieri.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/helvetica.php
Normal file
21
core/lib/fpdf/font/helvetica.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/helveticab.php
Normal file
21
core/lib/fpdf/font/helveticab.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/helveticabi.php
Normal file
21
core/lib/fpdf/font/helveticabi.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/helveticai.php
Normal file
21
core/lib/fpdf/font/helveticai.php
Normal 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));
|
||||
?>
|
||||
20
core/lib/fpdf/font/symbol.php
Normal file
20
core/lib/fpdf/font/symbol.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/times.php
Normal file
21
core/lib/fpdf/font/times.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/timesb.php
Normal file
21
core/lib/fpdf/font/timesb.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/timesbi.php
Normal file
21
core/lib/fpdf/font/timesbi.php
Normal 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));
|
||||
?>
|
||||
21
core/lib/fpdf/font/timesi.php
Normal file
21
core/lib/fpdf/font/timesi.php
Normal 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));
|
||||
?>
|
||||
20
core/lib/fpdf/font/zapfdingbats.php
Normal file
20
core/lib/fpdf/font/zapfdingbats.php
Normal 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
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
1354
core/lib/saml2/Assertion.php
Normal file
File diff suppressed because it is too large
Load Diff
185
core/lib/saml2/MetadataReader.php
Normal file
185
core/lib/saml2/MetadataReader.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
33
core/lib/saml2/MoSAMLBasicEnum.php
Normal file
33
core/lib/saml2/MoSAMLBasicEnum.php
Normal 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);
|
||||
}
|
||||
}
|
||||
109
core/lib/saml2/MoSAMLPointer.php
Normal file
109
core/lib/saml2/MoSAMLPointer.php
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
51
core/lib/saml2/PointersManager.php
Normal file
51
core/lib/saml2/PointersManager.php
Normal 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
114
core/lib/saml2/Response.php
Normal 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;
|
||||
}
|
||||
}
|
||||
511
core/lib/saml2/SAML2Core/MoXMLSecEnc.php
Normal file
511
core/lib/saml2/SAML2Core/MoXMLSecEnc.php
Normal 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);
|
||||
}
|
||||
}
|
||||
1162
core/lib/saml2/SAML2Core/MoXMLSecurityDSig.php
Normal file
1162
core/lib/saml2/SAML2Core/MoXMLSecurityDSig.php
Normal file
File diff suppressed because it is too large
Load Diff
800
core/lib/saml2/SAML2Core/MoXMLSecurityKey.php
Normal file
800
core/lib/saml2/SAML2Core/MoXMLSecurityKey.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
44
core/lib/saml2/SAML2Core/Utils/MoXPath.php
Normal file
44
core/lib/saml2/SAML2Core/Utils/MoXPath.php
Normal 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);
|
||||
}
|
||||
}
|
||||
830
core/lib/saml2/Utilities.php
Normal file
830
core/lib/saml2/Utilities.php
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
44
core/lib/saml2/encryption.php
Normal file
44
core/lib/saml2/encryption.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
640
core/lib/saml2/mo-saml-options-enum.php
Normal file
640
core/lib/saml2/mo-saml-options-enum.php
Normal 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-d’Urville 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"
|
||||
);
|
||||
}
|
||||
47
core/lib/saml2/xmlseclibs.php
Normal file
47
core/lib/saml2/xmlseclibs.php
Normal 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';
|
||||
@@ -1,11 +1,14 @@
|
||||
<?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("include.common.php");
|
||||
include("server.includes.inc.php");
|
||||
|
||||
$companyName = \Classes\SettingsManager::getInstance()->getSetting('Company: Name');
|
||||
$gsuiteEnabled = \Classes\SettingsManager::getInstance()->getSetting('System: G Suite Enabled');
|
||||
$gsuiteEnabled = 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'])) {
|
||||
\Utils\SessionUtils::unsetClientSession();
|
||||
@@ -14,12 +17,19 @@ if (isset($_REQUEST['logout'])) {
|
||||
|
||||
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;
|
||||
$ssoUserLoaded = false;
|
||||
|
||||
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']);
|
||||
if ($ldapResp->getStatus() == \Classes\IceResponse::ERROR) {
|
||||
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)) {
|
||||
$suser = new \Users\Common\Model\User();
|
||||
$suser->Load(
|
||||
@@ -59,7 +102,7 @@ if (empty($user) || empty($user->email)) {
|
||||
|
||||
$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']:'';
|
||||
header("Location:".CLIENT_BASE_URL."login.php?f=1".$next);
|
||||
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="bg-white-2 h-100 px-11 pt-11 pb-7">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<img src="<?=$logoFileUrl?>" style="max-width:100%;max-height:280px;"/>
|
||||
<img style="max-width: 100%;" src="<?=$logoFileUrl?>"/>
|
||||
</div>
|
||||
<hr/>
|
||||
<?php if ($gsuiteEnabled) {?>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<?php
|
||||
$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_280001_update_module_names';
|
||||
$migrationList[] = 'v20201017_271101_switch_off_photo_att';
|
||||
|
||||
24
core/migrations/v20210228_280003_add_share_with_employee.php
Normal file
24
core/migrations/v20210228_280003_add_share_with_employee.php
Normal 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;
|
||||
}
|
||||
}
|
||||
24
core/migrations/v20210228_280004_add_visible_to_document.php
Normal file
24
core/migrations/v20210228_280004_add_visible_to_document.php
Normal 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;
|
||||
}
|
||||
}
|
||||
85
core/migrations/v20210327_280005_saml_settings.php
Normal file
85
core/migrations/v20210327_280005_saml_settings.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
32
core/migrations/v20210402_280006_modify_attendance_rep.php
Normal file
32
core/migrations/v20210402_280006_modify_attendance_rep.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
31
core/migrations/v20210606_290001_update_s3_config.php
Normal file
31
core/migrations/v20210606_290001_update_s3_config.php
Normal 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;
|
||||
}
|
||||
}
|
||||
31
core/migrations/v20210606_290002_add_aws_region.php
Normal file
31
core/migrations/v20210606_290002_add_aws_region.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
22
core/migrations/v20210606_290003_system_meta_data.php
Normal file
22
core/migrations/v20210606_290003_system_meta_data.php
Normal 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;
|
||||
}
|
||||
}
|
||||
28
core/migrations/v20210626_290004_add_s3_settings.php
Normal file
28
core/migrations/v20210626_290004_add_s3_settings.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,8 @@ modJsList['tabEmployeeDocument'].setShowDelete(false);
|
||||
modJsList['tabEmployeeDocument'].setShowEdit(false);
|
||||
<?php }?>
|
||||
|
||||
modJsList['tabEmployeeDocument'].setRemoteTable(true);
|
||||
|
||||
|
||||
modJsList['tabEmployeeCompanyDocument'] = new EmployeeCompanyDocumentAdapter('CompanyDocument','EmployeeCompanyDocument');
|
||||
modJsList['tabEmployeeCompanyDocument'].setLoadMoreButton($("#loadMoreEmployeeCompanyDocument"));
|
||||
|
||||
@@ -3,19 +3,28 @@
|
||||
use Classes\BaseService;
|
||||
use Classes\CustomFieldManager;
|
||||
use Classes\JwtTokenService;
|
||||
use Classes\MemoryCacheService;
|
||||
use Classes\Migration\MigrationManager;
|
||||
use Classes\NotificationManager;
|
||||
use Classes\RedisCacheService;
|
||||
use Classes\ReportHandler;
|
||||
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;
|
||||
|
||||
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-active-record.inc.php');
|
||||
$ADODB_ASSOC_CASE = 2;
|
||||
|
||||
include(APP_BASE_PATH.'lib/fpdf/fpdf.php');
|
||||
|
||||
//detect admin and user modules
|
||||
if (defined("MODULE_PATH")) {
|
||||
$tArr = explode("/", MODULE_PATH);
|
||||
@@ -37,13 +46,13 @@ $dbLocal = NewADOConnection('mysqli');
|
||||
$res = $dbLocal->Connect(APP_HOST, APP_USERNAME, APP_PASSWORD, APP_DB);
|
||||
|
||||
|
||||
\Model\File::SetDatabaseAdapter($dbLocal);
|
||||
\Model\Setting::SetDatabaseAdapter($dbLocal);
|
||||
\Model\Report::SetDatabaseAdapter($dbLocal);
|
||||
\Model\DataEntryBackup::SetDatabaseAdapter($dbLocal);
|
||||
\Model\Audit::SetDatabaseAdapter($dbLocal);
|
||||
\Model\Notification::SetDatabaseAdapter($dbLocal);
|
||||
\Model\RestAccessToken::SetDatabaseAdapter($dbLocal);
|
||||
File::SetDatabaseAdapter($dbLocal);
|
||||
Setting::SetDatabaseAdapter($dbLocal);
|
||||
Report::SetDatabaseAdapter($dbLocal);
|
||||
DataEntryBackup::SetDatabaseAdapter($dbLocal);
|
||||
Audit::SetDatabaseAdapter($dbLocal);
|
||||
Notification::SetDatabaseAdapter($dbLocal);
|
||||
RestAccessToken::SetDatabaseAdapter($dbLocal);
|
||||
|
||||
|
||||
$baseService = BaseService::getInstance();
|
||||
@@ -71,14 +80,31 @@ if (defined('REDIS_SERVER_URI')
|
||||
&& QUERY_CACHE_TYPE === 'redis'
|
||||
) {
|
||||
BaseService::getInstance()->setCacheService(
|
||||
new \Classes\RedisCacheService(REDIS_SERVER_URI, CLIENT_NAME)
|
||||
new RedisCacheService(REDIS_SERVER_URI, CLIENT_NAME)
|
||||
);
|
||||
} else {
|
||||
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");
|
||||
|
||||
$debugMode = SettingsManager::getInstance()->getSetting("System: Debug Mode");
|
||||
@@ -123,10 +149,12 @@ if (defined('CLIENT_PATH')) {
|
||||
|
||||
$modelClassList = $moduleManagerObj->getModelClasses();
|
||||
$metaData = $moduleManagerObj->getModuleObject();
|
||||
/** @var BaseModel $modelClass */
|
||||
foreach ($modelClassList as $modelClass) {
|
||||
$modelClassWithNameSpace = $metaData['model_namespace']."\\".$modelClass;
|
||||
$modelClassWithNameSpace::SetDatabaseAdapter($dbLocal);
|
||||
$baseService->addModelClass($modelClass, $modelClassWithNameSpace);
|
||||
$modelClassObject = new $modelClassWithNameSpace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\PasswordManager;
|
||||
use Classes\Pdf\PDFRegister;
|
||||
use Classes\SettingsManager;
|
||||
use Metadata\Common\Model\SupportedLanguage;
|
||||
use Model\File;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\LogManager;
|
||||
use Classes\Exception\IceHttpException;
|
||||
@@ -173,19 +176,20 @@ try {// Domain aware input cleanup
|
||||
$type = strtolower(substr($file->filename, strrpos($file->filename, ".") + 1));
|
||||
if ($file->name == $name) {
|
||||
$ret['status'] = "SUCCESS";
|
||||
if (\Classes\SettingsManager::getInstance()->getSetting("Files: Upload Files to S3") == '1') {
|
||||
$uploadFilesToS3Key = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
|
||||
$uploadFilesToS3Secret = \Classes\SettingsManager::getInstance()->getSetting("Files: Amazone S3 Secret for File Upload");
|
||||
$file->ext = explode('.', $file->filename)[1];
|
||||
if (SettingsManager::getInstance()->getSetting("Files: Upload Files to S3") == '1') {
|
||||
$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);
|
||||
$s3WebUrl = \Classes\SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
$fileUrl = $s3WebUrl . CLIENT_NAME . "/" . $file->filename;
|
||||
$fileUrl = $s3FileSys->generateExpiringURL($fileUrl);
|
||||
$file->filename = $fileUrl;
|
||||
|
||||
} 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 {
|
||||
$ret['status'] = "ERROR";
|
||||
}
|
||||
@@ -193,21 +197,49 @@ try {// Domain aware input cleanup
|
||||
$fileName = $_REQUEST['file'];
|
||||
$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;
|
||||
}
|
||||
|
||||
if (!file_exists(CLIENT_BASE_PATH . 'data/' . $file->filename)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$extension = explode('.', $file->filename)[1];
|
||||
|
||||
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-Disposition: attachment; filename=' . basename($fileName));
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
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();
|
||||
flush();
|
||||
readfile($fileName);
|
||||
readfile(CLIENT_BASE_PATH . 'data/' . $file->filename);
|
||||
exit;
|
||||
|
||||
} 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 {
|
||||
echo BaseService::getInstance()->safeJsonEncode($ret);
|
||||
} catch (Exception $e) {
|
||||
@@ -312,6 +360,8 @@ try {// Domain aware input cleanup
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
echo json_encode(['status' => 'Error']);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IceHttpException $e) {
|
||||
http_response_code($e->getCode());
|
||||
echo json_encode(['message' => $e->getMessage()]);
|
||||
|
||||
@@ -109,11 +109,10 @@ class AttendanceStatus extends BaseModel
|
||||
$data[] = $entry;
|
||||
}
|
||||
|
||||
function cmp($a, $b)
|
||||
{
|
||||
|
||||
usort($data, function ($a, $b) {
|
||||
return $a->statusId - $b->statusId;
|
||||
}
|
||||
usort($data, "cmp");
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ class AttendanceActionManager extends SubActionManager
|
||||
//Find any open punch
|
||||
$attendance = new Attendance();
|
||||
$attendance->Load(
|
||||
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and (out_time is NULL
|
||||
or out_time = '0000-00-00 00:00:00')",
|
||||
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and out_time is NULL",
|
||||
array($employee->id,$date)
|
||||
);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
namespace Classes;
|
||||
|
||||
use Model\BaseModel;
|
||||
use Utils\LogManager;
|
||||
|
||||
abstract class AbstractModuleManager
|
||||
@@ -254,7 +255,17 @@ abstract class AbstractModuleManager
|
||||
protected function addModelClass($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)
|
||||
@@ -279,11 +290,11 @@ abstract class AbstractModuleManager
|
||||
BaseService::getInstance()->addCalculationHook($code, $name, $class, $method);
|
||||
}
|
||||
|
||||
public function install() {
|
||||
|
||||
public function install()
|
||||
{
|
||||
}
|
||||
|
||||
public function uninstall() {
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
8
core/src/Classes/Authorizable.php
Normal file
8
core/src/Classes/Authorizable.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
interface Authorizable
|
||||
{
|
||||
public function granted() : bool;
|
||||
}
|
||||
@@ -19,8 +19,10 @@ use Employees\Common\Model\EmployeeApproval;
|
||||
use FieldNames\Common\Model\CustomField;
|
||||
use FieldNames\Common\Model\FieldNameMapping;
|
||||
use Metadata\Common\Model\CalculationHook;
|
||||
use Model\BaseModel;
|
||||
use Model\DataEntryBackup;
|
||||
use Model\Setting;
|
||||
use Model\SystemData;
|
||||
use Modules\Common\Model\Module;
|
||||
use Permissions\Common\Model\Permission;
|
||||
use Users\Common\Model\User;
|
||||
@@ -51,7 +53,8 @@ class BaseService
|
||||
public $calculationHooks = array();
|
||||
public $customFieldManager = null;
|
||||
public $migrationManager = null;
|
||||
public $modelClassMap = array();
|
||||
public $modelClassMap = [];
|
||||
public $customFieldsClassMap = [];
|
||||
public $currentProfileId = false;
|
||||
|
||||
protected $cacheService = null;
|
||||
@@ -167,6 +170,20 @@ class BaseService
|
||||
$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)
|
||||
{
|
||||
return $this->getFullQualifiedModelClassName($name);
|
||||
@@ -637,7 +654,10 @@ class BaseService
|
||||
|
||||
$processedList = array();
|
||||
foreach ($list as $obj) {
|
||||
$processedList[] = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
$processedObj = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
if (null !== $processedObj) {
|
||||
$processedList[] = $processedObj;
|
||||
}
|
||||
}
|
||||
|
||||
$list = $processedList;
|
||||
@@ -749,7 +769,7 @@ class BaseService
|
||||
$obj = $this->enrichObjectCustomFields($table, $obj);
|
||||
|
||||
$obj = $obj->postProcessGetElement($obj);
|
||||
return $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
return $this->cleanUpAdoDB($obj);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -928,6 +948,7 @@ class BaseService
|
||||
{
|
||||
$fileFields = $this->fileFields;
|
||||
$nsTable = $this->getFullQualifiedModelClassName($table);
|
||||
/** @var BaseModel $ele */
|
||||
$ele = new $nsTable();
|
||||
|
||||
$ele->Load('id = ?', array($id));
|
||||
@@ -985,7 +1006,7 @@ class BaseService
|
||||
$dataEntryBackup->data = json_encode($newObj);
|
||||
$dataEntryBackup->Save();
|
||||
}
|
||||
|
||||
$ele->executePostDeleteActions($ele);
|
||||
$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);
|
||||
/** @var CustomField $cf */
|
||||
foreach ($cfs as $cf) {
|
||||
$cf->Delete();
|
||||
}
|
||||
@@ -1957,4 +1979,38 @@ END;
|
||||
$dbUser = $this->getCurrentDBUser();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,14 @@ class DomainAwareInputCleaner
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ use Utils\LogManager;
|
||||
class ExtensionManager
|
||||
{
|
||||
const GROUP = 'extension';
|
||||
protected function processExtensionInDB() {
|
||||
protected function processExtensionInDB()
|
||||
{
|
||||
$dbModule = new \Modules\Common\Model\Module();
|
||||
$extensions = $dbModule->Find("mod_group = ?", array(self::GROUP));
|
||||
|
||||
@@ -20,7 +21,8 @@ class ExtensionManager
|
||||
return $extensionsInDB;
|
||||
}
|
||||
|
||||
public function getExtensionsPath() {
|
||||
public function getExtensionsPath()
|
||||
{
|
||||
return APP_BASE_PATH.'../extensions/';
|
||||
}
|
||||
|
||||
@@ -29,7 +31,8 @@ class ExtensionManager
|
||||
return json_decode(file_get_contents($this->getExtensionsPath().$extensionName.'/meta.json'));
|
||||
}
|
||||
|
||||
public function setupExtensions() {
|
||||
public function setupExtensions()
|
||||
{
|
||||
$menu = [];
|
||||
$extensions = [];
|
||||
$extensionDirs = scandir($this->getExtensionsPath());
|
||||
|
||||
@@ -76,15 +76,20 @@ class FileService
|
||||
if (file_exists("/tmp/".$file->filename."_orig")) {
|
||||
//Resize image to 100
|
||||
|
||||
$img = new \Classes\SimpleImage("/tmp/".$file->filename."_orig");
|
||||
try {
|
||||
$img = new \Classes\SimpleImage("/tmp/" . $file->filename . "_orig");
|
||||
$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(
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$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");
|
||||
|
||||
@@ -132,11 +137,7 @@ class FileService
|
||||
if (empty($file->id)) {
|
||||
LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found");
|
||||
|
||||
$largeFileUrl = $this->getFileUrl($profileImage->name);
|
||||
|
||||
file_put_contents("/tmp/".$profileImage->filename."_orig", file_get_contents($largeFileUrl));
|
||||
|
||||
if (file_exists("/tmp/".$profileImage->filename."_orig")) {
|
||||
if (file_exists(CLIENT_BASE_PATH.'data/'.$profileImage->filename)) {
|
||||
//Resize image to 100
|
||||
|
||||
$file->name = $profileImage->name."_small";
|
||||
@@ -144,16 +145,19 @@ class FileService
|
||||
$file->$signInMappingField = $profileImage->$signInMappingField;
|
||||
$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->save(CLIENT_BASE_PATH.'data/'.$file->filename);
|
||||
$img->save(CLIENT_BASE_PATH . 'data/' . $file->filename);
|
||||
$file->employee = $profileImage->employee;
|
||||
$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->Save();
|
||||
unlink("/tmp/".$file->filename."_orig");
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error($e->getTraceAsString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
@@ -182,7 +186,7 @@ class FileService
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
|
||||
"Files: Amazone S3 Secret for File Upload"
|
||||
"Files: Amazon S3 Secret for File Upload"
|
||||
);
|
||||
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
@@ -204,7 +208,7 @@ class FileService
|
||||
$profile->image = $file->filename;
|
||||
} else {
|
||||
$fileNew = $this->checkAddSmallProfileImage($file);
|
||||
$profile->image = CLIENT_BASE_URL.'data/'.$fileNew->filename;
|
||||
$profile->image = $this->getFileUrl($fileNew->filename);
|
||||
}
|
||||
} else {
|
||||
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
|
||||
@@ -225,7 +229,7 @@ class FileService
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
|
||||
"Files: Amazone S3 Secret for File Upload"
|
||||
"Files: Amazon S3 Secret for File Upload"
|
||||
);
|
||||
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
@@ -241,7 +245,7 @@ class FileService
|
||||
} elseif (substr($file->filename, 0, 8) === 'https://') {
|
||||
$profile->image = $file->filename;
|
||||
} else {
|
||||
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename;
|
||||
$profile->image = $this->getLocalSecureUrl($file->filename);
|
||||
}
|
||||
} else {
|
||||
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
|
||||
@@ -255,6 +259,10 @@ class FileService
|
||||
$file = new File();
|
||||
$file->Load('name = ?', array($fileName));
|
||||
|
||||
if ($fileName !== $file->name) {
|
||||
$file->Load('filename = ?', array($fileName));
|
||||
}
|
||||
|
||||
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
|
||||
|
||||
if ($uploadFilesToS3 == "1") {
|
||||
@@ -262,7 +270,7 @@ class FileService
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
|
||||
"Files: Amazone S3 Secret for File Upload"
|
||||
"Files: Amazon S3 Secret for File Upload"
|
||||
);
|
||||
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
@@ -282,10 +290,22 @@ class FileService
|
||||
|
||||
return $expireUrl;
|
||||
} 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)
|
||||
{
|
||||
$file = new File();
|
||||
@@ -325,7 +345,7 @@ class FileService
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$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");
|
||||
|
||||
@@ -355,7 +375,7 @@ class FileService
|
||||
"Files: Amazon S3 Key for File Upload"
|
||||
);
|
||||
$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");
|
||||
|
||||
@@ -400,15 +420,34 @@ class FileService
|
||||
{
|
||||
$seed = substr($first, 0, 1);
|
||||
if (empty($last)) {
|
||||
$seed .= substr($first, -1);
|
||||
$seed .= utf8_encode(substr($first, -1));
|
||||
} 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(
|
||||
'https://avatars.dicebear.com/api/initials/:%s.svg',
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Classes;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\SignatureInvalidException;
|
||||
|
||||
class JwtTokenService
|
||||
{
|
||||
@@ -22,7 +23,11 @@ class JwtTokenService
|
||||
public function getBaseToken($jwtToken)
|
||||
{
|
||||
$secret = APP_SEC.APP_PASSWORD;
|
||||
try {
|
||||
$jwt = JWT::decode($jwtToken, $secret, array('HS256'));
|
||||
} catch (SignatureInvalidException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (time() > intval($jwt->expire)) {
|
||||
return null;
|
||||
|
||||
@@ -15,6 +15,8 @@ class MemcacheService
|
||||
public static $openConnections = array();
|
||||
private static $me = null;
|
||||
|
||||
protected $inMemoryStore = [];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
@@ -56,6 +58,15 @@ class MemcacheService
|
||||
}
|
||||
|
||||
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')) {
|
||||
return false;
|
||||
@@ -74,6 +85,19 @@ class MemcacheService
|
||||
}
|
||||
|
||||
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')) {
|
||||
return false;
|
||||
|
||||
99
core/src/Classes/ModuleBuilderV2/ModuleBuilder.php
Normal file
99
core/src/Classes/ModuleBuilderV2/ModuleBuilder.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:47 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\PermissionManager;
|
||||
|
||||
class ModuleBuilder
|
||||
{
|
||||
public $modules = array();
|
||||
public $user = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->user = BaseService::getInstance()->getCurrentUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModuleTab $module
|
||||
*/
|
||||
public function addModuleOrGroup($module)
|
||||
{
|
||||
$this->modules[] = $module;
|
||||
}
|
||||
|
||||
public function getTabHeadersHTML()
|
||||
{
|
||||
$html = "";
|
||||
foreach ($this->modules as $module) {
|
||||
$html .= $module->getHTML()."\r\n";
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getTabPagesHTML()
|
||||
{
|
||||
$html = "";
|
||||
/* @var ModuleTab $module */
|
||||
foreach ($this->modules as $module) {
|
||||
if (get_class($module) === ModuleTab::class) {
|
||||
$html .= $module->getPageHTML()."\r\n";
|
||||
} else {
|
||||
/* @var ModuleTab $mod */
|
||||
foreach ($module->modules as $mod) {
|
||||
$html .= $mod->getPageHTML()."\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getModJsHTML()
|
||||
{
|
||||
$moduleData = [
|
||||
'user_level' => $this->user->user_level,
|
||||
'permissions' => [
|
||||
]
|
||||
];
|
||||
|
||||
$html = "var modJsList = new Array();\r\n";
|
||||
$activeModule = "";
|
||||
/* @var ModuleTab $module */
|
||||
foreach ($this->modules as $module) {
|
||||
if (get_class($module) == ModuleTab::class) {
|
||||
$html .= $module->getJSObjectCode()."\r\n";
|
||||
|
||||
$modelClass = $module->modelPath;
|
||||
$moduleData['permissions'][$module->name] = PermissionManager::checkGeneralAccess(new $modelClass());
|
||||
|
||||
if ($module->isActive) {
|
||||
$activeModule = $module->name;
|
||||
}
|
||||
} else {
|
||||
/* @var ModuleTab $mod */
|
||||
foreach ($module->modules as $mod) {
|
||||
$modelClass = $mod->modelPath;
|
||||
$moduleData['permissions'][$mod->name] = PermissionManager::checkGeneralAccess(new $modelClass());
|
||||
|
||||
if ($module->isActive && $activeModule == "") {
|
||||
$activeModule = $mod->name;
|
||||
}
|
||||
$html .= $mod->getJSObjectCode()."\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html .= "var modJs = modJsList['tab".$activeModule."'];\r\n";
|
||||
|
||||
$html = "var data = ".json_encode($moduleData).";\r\n".$html;
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
98
core/src/Classes/ModuleBuilderV2/ModuleTab.php
Normal file
98
core/src/Classes/ModuleBuilderV2/ModuleTab.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:47 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
class ModuleTab
|
||||
{
|
||||
public $modelPath;
|
||||
public $name;
|
||||
public $class;
|
||||
public $label;
|
||||
public $adapterName;
|
||||
public $filter;
|
||||
public $orderBy;
|
||||
public $isActive = false;
|
||||
public $isInsideGroup = false;
|
||||
public $options = array();
|
||||
|
||||
public function __construct(
|
||||
$modelPath,
|
||||
$name,
|
||||
$class,
|
||||
$label,
|
||||
$adapterName,
|
||||
$filter,
|
||||
$orderBy,
|
||||
$isActive = false,
|
||||
$options = array()
|
||||
) {
|
||||
|
||||
$this->modelPath = $modelPath;
|
||||
$this->name = $name;
|
||||
$this->class = $class;
|
||||
$this->label = $label;
|
||||
$this->adapterName = $adapterName;
|
||||
$this->filter = $filter;
|
||||
$this->orderBy = $orderBy;
|
||||
$this->isActive = $isActive;
|
||||
|
||||
$this->options = array_merge(
|
||||
$options,
|
||||
[
|
||||
"setObjectTypeName" => "'{$this->name}'",
|
||||
"setAccess" => "data.permissions.{$this->name} ? data.permissions.{$this->name} : {}",
|
||||
"setDataPipe" => 'new IceDataPipe(modJsList.tab' . $this->name . ')',
|
||||
"setRemoteTable" => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getHTML()
|
||||
{
|
||||
$active = ($this->isActive)?"active":"";
|
||||
if (!$this->isInsideGroup) {
|
||||
return '<li class="' . $active . '"><a id="tab' . $this->name
|
||||
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
|
||||
} else {
|
||||
return '<li class="' . $active . '"><a id="tab' . $this->name
|
||||
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
|
||||
}
|
||||
}
|
||||
|
||||
public function getPageHTML()
|
||||
{
|
||||
$active = ($this->isActive)?" active":"";
|
||||
$html = '<div class="tab-pane'.$active.'" id="tabPage'.$this->name.'">'.
|
||||
'<div id="'.$this->name.'Table" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>'.
|
||||
'<div id="'.$this->name.'Form"></div>'.
|
||||
'<div id="'.$this->name.'FilterForm"></div>'.
|
||||
'</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getJSObjectCode()
|
||||
{
|
||||
$js = "";
|
||||
if (empty($this->filter)) {
|
||||
$js.= "modJsList['tab" . $this->name . "'] = new " .
|
||||
$this->adapterName . "('" . $this->class . "','" . $this->name . "','','".$this->orderBy. "');\r\n";
|
||||
} else {
|
||||
$js.= "modJsList['tab" . $this->name . "'] = new " .
|
||||
$this->adapterName . "('" . $this->class . "','" . $this->name . "'," .
|
||||
$this->filter . ",'".$this->orderBy. "');\r\n";
|
||||
}
|
||||
|
||||
foreach ($this->options as $key => $val) {
|
||||
$js.= "modJsList['tab" . $this->name . "'].".$key."(".$val. ");\r\n";
|
||||
}
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
53
core/src/Classes/ModuleBuilderV2/ModuleTabGroup.php
Normal file
53
core/src/Classes/ModuleBuilderV2/ModuleTabGroup.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:48 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
class ModuleTabGroup
|
||||
{
|
||||
public $name;
|
||||
public $label;
|
||||
public $isActive = false;
|
||||
public $modules = array();
|
||||
|
||||
public function __construct($name, $label)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public function addModuleTab($moduleTab)
|
||||
{
|
||||
if ($moduleTab->isActive) {
|
||||
$this->isActive = true;
|
||||
$moduleTab->isActive = false;
|
||||
}
|
||||
$moduleTab->isInsideGroup = true;
|
||||
$this->modules[] = $moduleTab;
|
||||
}
|
||||
|
||||
public function getHTML()
|
||||
{
|
||||
$html = "";
|
||||
$active = ($this->isActive)?" active":"";
|
||||
|
||||
$html.= '<li class="dropdown'.$active.'">'."\r\n".
|
||||
'<a href="#" id="'.$this->name.
|
||||
'" class="dropdown-toggle" data-toggle="dropdown" aria-controls="'.$this->name.
|
||||
'-contents">'.$this->label.' <span class="caret"></span></a>'."\r\n".
|
||||
'<ul class="dropdown-menu" role="menu" aria-labelledby="'.$this->name.'" id="'.$this->name.'-contents">';
|
||||
|
||||
foreach ($this->modules as $module) {
|
||||
$html.= $module->getHTML();
|
||||
}
|
||||
|
||||
$html .= "</ul></li>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ class PasswordManager
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (strlen($password) > 20) {
|
||||
if (strlen($password) > 30) {
|
||||
$error = "Password too long";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
|
||||
162
core/src/Classes/Pdf/BasePdfTemplate.php
Normal file
162
core/src/Classes/Pdf/BasePdfTemplate.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
namespace Classes\Pdf;
|
||||
|
||||
use Classes\SettingsManager;
|
||||
|
||||
class BasePdfTemplate extends \FPDF
|
||||
{
|
||||
protected $title;
|
||||
protected $date;
|
||||
|
||||
const WIDTH = 210;
|
||||
|
||||
public function initialize($title)
|
||||
{
|
||||
$this->AliasNbPages();
|
||||
$this->AddPage();
|
||||
$this->SetTitle($title);
|
||||
$this->date = $date = date('c');
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
function Header()
|
||||
{
|
||||
// Logo
|
||||
try {
|
||||
$this->Image(\Classes\UIManager::getInstance()->getCompanyLogoUrl(), 10, 10, 0, 10);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
PdfColour::setTextColor($this, PdfColour::GREY_100);
|
||||
// Arial bold 15
|
||||
$this->SetFont('Arial', '', 9);
|
||||
// Company name
|
||||
$companyName = SettingsManager::getInstance()->getSetting('Company: Name');
|
||||
$this->Cell(30, 23, $companyName, 0, 0, 'L');
|
||||
PdfColour::setDrawColor($this, PdfColour::GREY_100);
|
||||
$this->Line(10, 26, self::WIDTH - 10, 26);
|
||||
// Line break
|
||||
$this->Ln(20);
|
||||
}
|
||||
|
||||
function Footer()
|
||||
{
|
||||
PdfColour::setTextColor($this, PdfColour::GREY_100);
|
||||
// Position at 1.5 cm from bottom
|
||||
$this->SetY(-15);
|
||||
// Arial italic 8
|
||||
$this->SetFont('Arial', 'I', 8);
|
||||
// Page number
|
||||
$this->Cell(0, 10, 'Page '.$this->PageNo().'/{nb}, Date:'.$this->date, 0, 0, 'C');
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function addH1($title, $style = 'B', $textAlignment = 'C')
|
||||
{
|
||||
$this->addH($title, $style, $textAlignment, 21);
|
||||
}
|
||||
|
||||
public function addH2($title, $style = 'B', $textAlignment = 'C')
|
||||
{
|
||||
$this->addH($title, $style, $textAlignment, 17);
|
||||
}
|
||||
|
||||
public function addH3($title, $style = 'B', $textAlignment = 'C')
|
||||
{
|
||||
$this->addH($title, $style, $textAlignment, 14);
|
||||
}
|
||||
|
||||
public function addH($title, $style = 'B', $textAlignment = 'C', $fontSize = 16)
|
||||
{
|
||||
PdfColour::setTextColor($this, PdfColour::BLACK_LIGHT);
|
||||
$this->SetFont('Arial', $style, $fontSize);
|
||||
$this->Cell(0, 10, $title, 0, 1, $textAlignment);
|
||||
}
|
||||
|
||||
public function addBorderedText($text)
|
||||
{
|
||||
$this->addText($text, '', 'L', 10, PdfColour::BLACK_LIGHT, 1, PdfColour::GREY_DARK);
|
||||
}
|
||||
|
||||
public function addText(
|
||||
$text,
|
||||
$style = '',
|
||||
$textAlignment = 'L',
|
||||
$fontSize = 10,
|
||||
$color = PdfColour::BLACK_LIGHT,
|
||||
$cellBorder = 0,
|
||||
$cellBorderColor = PdfColour::GREY_DARK
|
||||
) {
|
||||
PdfColour::setTextColor($this, $color);
|
||||
$this->SetFont('Arial', $style, $fontSize);
|
||||
if ($cellBorder === 1) {
|
||||
PdfColour::setDrawColor($this, $cellBorderColor);
|
||||
}
|
||||
PdfColour::setFillColor($this, PdfColour::WHITE);
|
||||
$this->MultiCell(0, 5, $text, $cellBorder, 1, $textAlignment);
|
||||
}
|
||||
|
||||
public function addKeyValue($key, $value, $type = 'text')
|
||||
{
|
||||
PdfColour::setDrawColor($this, PdfColour::GREY_DARK);
|
||||
PdfColour::setFillColor($this, PdfColour::GREY);
|
||||
|
||||
|
||||
if ($type === 'textarea') {
|
||||
$this->Cell(0, 10, $key, 1, 1, 'L', true);
|
||||
} else {
|
||||
$this->Cell(80, 10, $key, 1, 0, 'L', true);
|
||||
}
|
||||
|
||||
PdfColour::setFillColor($this, PdfColour::WHITE);
|
||||
|
||||
if ($type === 'textarea') {
|
||||
$this->MultiCell(0, 5, $value, 1, 1, 'L');
|
||||
} elseif ($type === 'date') {
|
||||
$value = date('Y-m-d', strtotime($value));
|
||||
$this->Cell(110, 10, $value, 1, 1, 'L', true);
|
||||
} elseif ($type === 'select2multi') {
|
||||
$value = json_decode($value, true);
|
||||
$value = !empty($value) ? join(',', $value) : '';
|
||||
$this->Cell(110, 10, $value, 1, 1, 'L', true);
|
||||
} else {
|
||||
$this->Cell(110, 10, $value, 1, 1, 'L', true);
|
||||
}
|
||||
}
|
||||
|
||||
public function addKeyValueObject($key, $value)
|
||||
{
|
||||
PdfColour::setDrawColor($this, PdfColour::GREY_DARK);
|
||||
PdfColour::setFillColor($this, PdfColour::GREY);
|
||||
$this->Cell(80, 10, $key, 1, 0, 'L', true);
|
||||
|
||||
PdfColour::setFillColor($this, PdfColour::WHITE);
|
||||
$this->MultiCell(110, 10, $value, 1, 1, true);
|
||||
}
|
||||
|
||||
public function addHR($width = 0)
|
||||
{
|
||||
$this->Ln(2);
|
||||
PdfColour::setDrawColor($this, PdfColour::GREY_DARK);
|
||||
PdfColour::setFillColor($this, PdfColour::GREY_DARK);
|
||||
$this->Cell($width, 0.2, '', 0, 0, '', true);
|
||||
// Line break
|
||||
$this->Ln(3);
|
||||
}
|
||||
|
||||
public function getImageFromDataURI($dataURI)
|
||||
{
|
||||
$img = explode(',', $dataURI, 2)[1];
|
||||
return 'data://text/plain;base64,'. $img;
|
||||
}
|
||||
|
||||
public function addSignature($name, $data)
|
||||
{
|
||||
$image = $this->getImageFromDataURI($data);
|
||||
$this->Ln(10);
|
||||
$this->Image($image, $this->GetX(), $this->GetY(), 30, 0, 'png');
|
||||
$this->Ln(30);
|
||||
$this->addHR(30);
|
||||
$this->addText($name);
|
||||
}
|
||||
}
|
||||
27
core/src/Classes/Pdf/PDFRegister.php
Normal file
27
core/src/Classes/Pdf/PDFRegister.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Classes\Pdf;
|
||||
|
||||
use Forms\Common\EmployeeFormPDFBuilder;
|
||||
|
||||
class PDFRegister
|
||||
{
|
||||
protected static $register = [];
|
||||
|
||||
public static function init()
|
||||
{
|
||||
self::put('empf', function ($data) {
|
||||
return new EmployeeFormPDFBuilder($data);
|
||||
});
|
||||
}
|
||||
|
||||
public static function put($key, $callback)
|
||||
{
|
||||
self::$register[$key] = $callback;
|
||||
}
|
||||
|
||||
public static function get($key)
|
||||
{
|
||||
return self::$register[$key];
|
||||
}
|
||||
}
|
||||
8
core/src/Classes/Pdf/PdfBuilder.php
Normal file
8
core/src/Classes/Pdf/PdfBuilder.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Classes\Pdf;
|
||||
|
||||
interface PdfBuilder
|
||||
{
|
||||
public function createPdf();
|
||||
}
|
||||
27
core/src/Classes/Pdf/PdfColour.php
Normal file
27
core/src/Classes/Pdf/PdfColour.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Classes\Pdf;
|
||||
|
||||
class PdfColour
|
||||
{
|
||||
const GREY = [224, 224, 224];
|
||||
const GREY_DARK = [160, 160, 160];
|
||||
const WHITE = [255, 255, 255];
|
||||
const BLACK_LIGHT = [84, 84, 84];
|
||||
const GREY_100 = [100, 100, 100];
|
||||
|
||||
public static function setFillColor(\FPDF $pdf, $color)
|
||||
{
|
||||
$pdf->SetFillColor($color[0], $color[1], $color[2]);
|
||||
}
|
||||
|
||||
public static function setTextColor(\FPDF $pdf, $color)
|
||||
{
|
||||
$pdf->SetTextColor($color[0], $color[1], $color[2]);
|
||||
}
|
||||
|
||||
public static function setDrawColor(\FPDF $pdf, $color)
|
||||
{
|
||||
$pdf->SetDrawColor($color[0], $color[1], $color[2]);
|
||||
}
|
||||
}
|
||||
@@ -424,10 +424,8 @@ class RestEndPoint
|
||||
$token = $_GET['token'];
|
||||
}
|
||||
|
||||
if (strlen($token) > 32) {
|
||||
$tokenService = new JwtTokenService();
|
||||
$token = $tokenService->getBaseToken($token);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
100
core/src/Classes/SAMLManager.php
Normal file
100
core/src/Classes/SAMLManager.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use \RobRichards\XMLSecLibs\MoXMLSecurityKey;
|
||||
use Utils\LogManager;
|
||||
|
||||
class SAMLManager
|
||||
{
|
||||
public function getSSOEmail($samlData, $relayState)
|
||||
{
|
||||
// Service Providers Assertion Consumer Service (ACS) URL
|
||||
$acsUrl = CLIENT_BASE_URL.'login.php';
|
||||
$samlResponse = htmlspecialchars($samlData);
|
||||
|
||||
$samlResponse = base64_decode($samlResponse);
|
||||
|
||||
$document = new \DOMDocument();
|
||||
$document->loadXML($samlResponse);
|
||||
$samlResponseXml = $document->firstChild;
|
||||
|
||||
$doc = $document->documentElement;
|
||||
$xpath = new \DOMXpath($document);
|
||||
$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
|
||||
$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
|
||||
|
||||
$status = $xpath->query('/samlp:Response/samlp:Status/samlp:StatusCode', $doc);
|
||||
$statusString = $status->item(0)->getAttribute('Value');
|
||||
|
||||
|
||||
$statusArray = explode(':', $statusString);
|
||||
if (array_key_exists(7, $statusArray)) {
|
||||
$status = $statusArray[7];
|
||||
}
|
||||
|
||||
if ('Success' !== $status) {
|
||||
$StatusMessage = $xpath->query('/samlp:Response/samlp:Status/samlp:StatusMessage', $doc)->item(0);
|
||||
LogManager::getInstance()->error('SAML login failed: status = '. $status);
|
||||
if (!empty($StatusMessage)) {
|
||||
$StatusMessage = $StatusMessage->nodeValue;
|
||||
LogManager::getInstance()->error('SAML login failed: status message = '. $StatusMessage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$x509cert = SettingsManager::getInstance()->getSetting('SAML: X.509 Certificate');
|
||||
|
||||
$samlResponse = new \SAML2_Response($samlResponseXml);
|
||||
$responseSignatureData = $samlResponse->getSignatureData();
|
||||
$assertionSignatureData = current($samlResponse->getAssertions())->getSignatureData();
|
||||
|
||||
$certFingerPrint = MoXMLSecurityKey::getRawThumbprint($x509cert);
|
||||
$certFingerPrint = preg_replace('/\s+/', '', $certFingerPrint);
|
||||
$validSignature = false;
|
||||
if (!empty($responseSignatureData)) {
|
||||
$validSignature = \Utilities::processResponse(
|
||||
$acsUrl,
|
||||
$certFingerPrint,
|
||||
$responseSignatureData,
|
||||
$samlResponse,
|
||||
0,
|
||||
$relayState
|
||||
);
|
||||
LogManager::getInstance()->error('SAML: response signature validity :'.$validSignature);
|
||||
}
|
||||
|
||||
if (!empty($assertionSignatureData)) {
|
||||
$validSignature = \Utilities::processResponse(
|
||||
$acsUrl,
|
||||
$certFingerPrint,
|
||||
$assertionSignatureData,
|
||||
$samlResponse,
|
||||
0,
|
||||
$relayState
|
||||
);
|
||||
LogManager::getInstance()->error('SAML: response signature validity :'.$validSignature);
|
||||
}
|
||||
|
||||
if (!$validSignature) {
|
||||
LogManager::getInstance()->error('Invalid response or assertion signature');
|
||||
return false;
|
||||
}
|
||||
|
||||
$issuer = current($samlResponse->getAssertions())->getIssuer();
|
||||
$assertion = current($samlResponse->getAssertions());
|
||||
$audiences = $assertion->getValidAudiences();
|
||||
$expectedIssuer = SettingsManager::getInstance()->getSetting('SAML: IDP Issuer');
|
||||
if ($issuer !== $expectedIssuer) {
|
||||
LogManager::getInstance()->error('SAML Invalid Issuer :'.$issuer.' expected :'.$expectedIssuer);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ssoEmail = current(current($samlResponse->getAssertions())->getNameId());
|
||||
if (!$ssoEmail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ssoEmail;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
<?php
|
||||
namespace Classes;
|
||||
|
||||
use Classes\Crypt\AesCtr;
|
||||
use Model\Setting;
|
||||
|
||||
class SettingsManager
|
||||
{
|
||||
|
||||
const ENCRYPTED_PREFIX = 'iceenc_';
|
||||
|
||||
private static $me = null;
|
||||
|
||||
private $encryptedSettings = [];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
$this->addEncryptedSetting('SAML: X.509 Certificate');
|
||||
$this->addEncryptedSetting('LDAP: Manager Password');
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
@@ -21,9 +28,67 @@ class SettingsManager
|
||||
return self::$me;
|
||||
}
|
||||
|
||||
public function addEncryptedSetting($name)
|
||||
{
|
||||
if (!$this->isEncryptedSetting($name)) {
|
||||
$this->encryptedSettings[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
public function isEncryptedSetting($name)
|
||||
{
|
||||
return in_array($name, $this->encryptedSettings);
|
||||
}
|
||||
|
||||
public function getInstanceKey()
|
||||
{
|
||||
$settings = new Setting();
|
||||
$settings->Load("name = ?", array("Instance: Key"));
|
||||
if ($settings->name != "Instance: Key") {
|
||||
return null;
|
||||
}
|
||||
return $settings->value;
|
||||
}
|
||||
|
||||
private function encrypt($value)
|
||||
{
|
||||
$id = BaseService::getInstance()->getInstanceId();
|
||||
$key = $this->getInstanceKey();
|
||||
return AesCtr::encrypt($value, $id.$key, 256);
|
||||
}
|
||||
|
||||
public function encryptSetting($name, $value)
|
||||
{
|
||||
// check the existence of prefix and encrypt only if need to avoid double encryption
|
||||
if ($this->isEncryptedSetting($name)
|
||||
&& substr($value, 0, strlen(self::ENCRYPTED_PREFIX)) !== self::ENCRYPTED_PREFIX
|
||||
) {
|
||||
$value = self::ENCRYPTED_PREFIX.$this->encrypt($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function decrypt($value)
|
||||
{
|
||||
$id = BaseService::getInstance()->getInstanceId();
|
||||
$key = $this->getInstanceKey();
|
||||
return AesCtr::decrypt($value, $id.$key, 256);
|
||||
}
|
||||
|
||||
public function decryptSetting($name, $value)
|
||||
{
|
||||
if ($this->isEncryptedSetting($name)
|
||||
&& substr($value, 0, strlen(self::ENCRYPTED_PREFIX)) === self::ENCRYPTED_PREFIX
|
||||
) {
|
||||
$value = $this->decrypt(substr($value, strlen(self::ENCRYPTED_PREFIX)));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getSetting($name)
|
||||
{
|
||||
|
||||
if (class_exists("\\Classes\\ProVersion")) {
|
||||
$pro = new ProVersion();
|
||||
$val = $pro->getSetting($name);
|
||||
@@ -34,20 +99,28 @@ class SettingsManager
|
||||
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
$value = null;
|
||||
if ($setting->name == $name) {
|
||||
return $setting->value;
|
||||
$value = $setting->value;
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->decryptSetting($name, $value);
|
||||
}
|
||||
|
||||
public function setSetting($name, $value)
|
||||
{
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
if ($setting->name == $name) {
|
||||
$setting->value = $value;
|
||||
$setting->Save();
|
||||
if ($setting->name !== $name) {
|
||||
return;
|
||||
}
|
||||
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->Save();
|
||||
}
|
||||
|
||||
public function addSetting($name, $value)
|
||||
@@ -55,14 +128,22 @@ class SettingsManager
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
if ($setting->name == $name) {
|
||||
$setting->value = $value;
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->Save();
|
||||
} else {
|
||||
$setting->name = $name;
|
||||
$setting->value = $value;
|
||||
$setting->description = $value;
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->description = '';
|
||||
$setting->meta = '';
|
||||
$setting->Save();
|
||||
}
|
||||
}
|
||||
|
||||
public function getDeprecatedSettings()
|
||||
{
|
||||
return [
|
||||
'Attendance: Work Week Start Day',
|
||||
'Attendance: Overtime Calculation Class'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
33
core/src/Classes/StatsHelper.php
Normal file
33
core/src/Classes/StatsHelper.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Employees\Common\Model\Employee;
|
||||
use Users\Common\Model\User;
|
||||
|
||||
class StatsHelper
|
||||
{
|
||||
public static function getEmployeeCount()
|
||||
{
|
||||
$employee = new Employee();
|
||||
$employeeCount = $employee->DB()->Execute("select count(id) from Employees");
|
||||
if ($employeeCount) {
|
||||
$employeeCount = intval($employeeCount->fields[0]);
|
||||
return $employeeCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getUserCount()
|
||||
{
|
||||
$user = new User();
|
||||
$userCount = $user->DB()->Execute("select count(id) from Users");
|
||||
if ($userCount) {
|
||||
$userCount = intval($userCount->fields[0]);
|
||||
return $userCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ class Uploader
|
||||
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
|
||||
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
|
||||
$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");
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
|
||||
@@ -5,9 +5,14 @@ use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
use Model\CustomFieldTrait;
|
||||
|
||||
class CompanyStructure extends BaseModel
|
||||
{
|
||||
use CustomFieldTrait;
|
||||
public $objectName = 'Company Structures';
|
||||
protected $allowCustomFields = true;
|
||||
|
||||
public $table = 'CompanyStructures';
|
||||
|
||||
public function getAdminAccess()
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace Connection\Admin\Api;
|
||||
|
||||
use Classes\SubActionManager;
|
||||
|
||||
class ConnectionActionManager extends SubActionManager
|
||||
{
|
||||
|
||||
}
|
||||
38
core/src/Connection/Admin/Api/ConnectionAdminManager.php
Normal file
38
core/src/Connection/Admin/Api/ConnectionAdminManager.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Connection\Admin\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
use Connection\Common\ConnectionService;
|
||||
|
||||
class ConnectionAdminManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
$iceConnect = new ConnectionService();
|
||||
if ($iceConnect->dispatchInstallationRequest()) {
|
||||
$iceConnect->reportInstallationData();
|
||||
}
|
||||
}
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
// TODO: Implement initializeUserClasses() method.
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
// TODO: Implement initializeFieldMappings() method.
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
// TODO: Implement initializeDatabaseErrorMappings() method.
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
// TODO: Implement setupModuleClassDefinitions() method.
|
||||
}
|
||||
}
|
||||
135
core/src/Connection/Common/ConnectionService.php
Normal file
135
core/src/Connection/Common/ConnectionService.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
namespace Connection\Common;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\SettingsManager;
|
||||
use Classes\StatsHelper;
|
||||
use GuzzleHttp\Client;
|
||||
use Users\Common\Model\User;
|
||||
|
||||
class ConnectionService
|
||||
{
|
||||
public function getInstallationData()
|
||||
{
|
||||
$proKey = '';
|
||||
if (class_exists('\\Classes\\ProVersion')) {
|
||||
$data = \Classes\ProVersion::$data;
|
||||
$data = json_decode($data, true);
|
||||
$proKey = $data['key'];
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => BaseService::getInstance()->getInstanceId(),
|
||||
'secret' => md5(BaseService::getInstance()->getInstanceKey()),
|
||||
'external_ip' => $this->getExternalIP(),
|
||||
'internal_ip' => $_SERVER['SERVER_ADDR'],
|
||||
'employees' => StatsHelper::getEmployeeCount(),
|
||||
'users' => StatsHelper::getUserCount(),
|
||||
'version' => VERSION,
|
||||
'company' => SettingsManager::getInstance()->getSetting('Company: Name'),
|
||||
'pro_key' => $proKey,
|
||||
];
|
||||
}
|
||||
|
||||
public function getSystemReport()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'name' => 'Installation ID',
|
||||
'value' => BaseService::getInstance()->getInstanceId(),
|
||||
],
|
||||
[
|
||||
'name' => 'PHP Version',
|
||||
'value' => phpversion(),
|
||||
],
|
||||
[
|
||||
'name' => 'PHP Extensions',
|
||||
'value' => join(', ', get_loaded_extensions()),
|
||||
],
|
||||
[
|
||||
'name' => 'Web Server',
|
||||
'value' => $_SERVER['SERVER_SOFTWARE'],
|
||||
],
|
||||
[
|
||||
'name' => 'MySQL Server',
|
||||
'value' => mysqli_get_server_info((new User())->DB()->_connectionID),
|
||||
],
|
||||
[
|
||||
'name' => 'Modules Loaded',
|
||||
'value' => join(', ', array_keys(BaseService::getInstance()->getModuleManagerNames())),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getSystemErrors()
|
||||
{
|
||||
$errors = [];
|
||||
$res = fopen(CLIENT_BASE_PATH.'data/connection_test.txt', "w");
|
||||
|
||||
if (false === $res) {
|
||||
$errors[] = [
|
||||
'type' => 'error',
|
||||
'message' =>
|
||||
'Data directory is not writable. Please make sure php can has write access to <icehrm>/app/data',
|
||||
];
|
||||
} else {
|
||||
fwrite($res, date('Y-m-d'));
|
||||
$file = CLIENT_BASE_URL.'data/connection_test.txt';
|
||||
$file_headers = @get_headers($file);
|
||||
if ($file_headers && $file_headers[0] !== 'HTTP/1.1 404 Not Found') {
|
||||
$errors[] = [
|
||||
'type' => 'error',
|
||||
'link' => 'https://icehrm.gitbook.io/icehrm/getting-started/securing-icehrm-installation',
|
||||
'linkText' => 'Learn how to fix',
|
||||
'message' => 'Data directory is accessible from outside.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function dispatchInstallationRequest()
|
||||
{
|
||||
$timeNow = time();
|
||||
$time = BaseService::getInstance()->getSystemData('sysDataTime');
|
||||
if (null === $time) {
|
||||
BaseService::getInstance()->setSystemData('sysDataTime', $timeNow);
|
||||
return true;
|
||||
}
|
||||
|
||||
$time = intval($time);
|
||||
if ($timeNow > $time + 3600) {
|
||||
BaseService::getInstance()->setSystemData('sysDataTime', $timeNow);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getExternalIP()
|
||||
{
|
||||
try {
|
||||
$externalContent = file_get_contents('http://checkip.dyndns.com/');
|
||||
preg_match('/Current IP Address: \[?([:.0-9a-fA-F]+)\]?/', $externalContent, $m);
|
||||
return $m[1];
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function reportInstallationData()
|
||||
{
|
||||
try {
|
||||
$client = new Client();
|
||||
$response = $client->request('POST', APP_WEB_URL . '/sapi/installtion-data', [
|
||||
'json' => $this->getInstallationData(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
25
core/src/CustomField/Admin/Api/CustomFieldAdminManager.php
Normal file
25
core/src/CustomField/Admin/Api/CustomFieldAdminManager.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace CustomField\Admin\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
|
||||
class CustomFieldAdminManager extends AbstractModuleManager
|
||||
{
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
$this->addModelClass('CustomField');
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,13 @@ class DocumentTaskCreator implements TaskCreator
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query = "select count(id) as c from EmployeeDocuments where employee = ? and valid_until < ?";
|
||||
$query = "select count(id) as c
|
||||
from EmployeeDocuments
|
||||
where employee = ? and valid_until < ? and visible_to = ?";
|
||||
|
||||
$user->DB()->SetFetchMode(ADODB_FETCH_ASSOC);
|
||||
$rs = $user->DB()->Execute($query, [$employee->id, date('Y-m-d')]);
|
||||
// TODO - sending notifications only for Owner documents, this need to be extended later
|
||||
$rs = $user->DB()->Execute($query, [$employee->id, date('Y-m-d'), 'Owner']);
|
||||
$count = $rs->fields['c'];
|
||||
|
||||
return $count;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
@@ -26,4 +27,23 @@ class Document extends BaseModel
|
||||
new ModuleAccess('documents', 'user'),
|
||||
];
|
||||
}
|
||||
|
||||
public function fieldValueMethods()
|
||||
{
|
||||
return ['getDocumentTypesForUser'];
|
||||
}
|
||||
|
||||
public function getDocumentTypesForUser()
|
||||
{
|
||||
$documents = new Document();
|
||||
if (BaseService::getInstance()->currentUser->user_level === 'Employee'
|
||||
|| BaseService::getInstance()->currentUser->user_level === 'Restricted Employee'
|
||||
) {
|
||||
$documents = $documents->Find('share_with_employee = ?', ['Yes']);
|
||||
} else {
|
||||
$documents = $documents->Find('1 = 1');
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,65 @@
|
||||
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeDocument extends BaseModel
|
||||
{
|
||||
public $table = 'EmployeeDocuments';
|
||||
|
||||
private function getHiddenDocumentTypeIds()
|
||||
{
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
|
||||
{
|
||||
$find = '';
|
||||
$user = BaseService::getInstance()->getCurrentUser();
|
||||
|
||||
if ($user->user_level == 'Employee') {
|
||||
$find = ' visible_to = \'Owner\' AND ';
|
||||
$document = new Document();
|
||||
$hiddenDocumentTypes = $document->Find(
|
||||
"share_with_employee = ?",
|
||||
['No']
|
||||
);
|
||||
|
||||
$hiddenTypeIds = [];
|
||||
foreach ($hiddenDocumentTypes as $hiddenDocumentType) {
|
||||
$hiddenTypeIds[] = $hiddenDocumentType->id;
|
||||
}
|
||||
|
||||
if(count($hiddenTypeIds) > 0) {
|
||||
$find .= ' document NOT IN (\''.implode('\',\'', $hiddenTypeIds).'\') AND ';
|
||||
}
|
||||
|
||||
return parent::Find($find.$whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
|
||||
} else if ($user->user_level == 'Manager') {
|
||||
// Original $whereOrderBy already contain employee selection
|
||||
// So here if isSubOrdinates is true if the query coming from Employee -> Document Management
|
||||
// In that case we need to show documents from sub ordinates
|
||||
// These docs can can be owner and manager both
|
||||
if (isset($isSubOrdinates) && $isSubOrdinates) {
|
||||
$find .= ' visible_to in (\'Owner\', \'Manager\') AND ';
|
||||
} else {
|
||||
// Here we are showing the documents for the manager
|
||||
// If someone upload a document for this manager and make it visible to manager,
|
||||
// that means only the manager of this manager can see the document
|
||||
// So it should not be visible to this manager
|
||||
$find .= ' visible_to in (\'Owner\') AND ';
|
||||
}
|
||||
}
|
||||
|
||||
return parent::Find($find.$whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
@@ -26,6 +77,8 @@ class EmployeeDocument extends BaseModel
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getUserAccess()
|
||||
{
|
||||
return array("get");
|
||||
|
||||
@@ -8,6 +8,7 @@ use Classes\ModuleAccess;
|
||||
use Company\Common\Model\CompanyStructure;
|
||||
use Metadata\Common\Model\Country;
|
||||
use Model\BaseModel;
|
||||
use Model\CustomFieldTrait;
|
||||
|
||||
class Employee extends BaseModel
|
||||
{
|
||||
@@ -90,6 +91,11 @@ class Employee extends BaseModel
|
||||
$this->oldObj = BaseService::getInstance()->getElement('Employee', $obj->id, $mapping, true);
|
||||
}
|
||||
|
||||
public function isCustomFieldsEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function saveHistory($obj)
|
||||
{
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
use Utils\LogManager;
|
||||
|
||||
class CustomField extends BaseModel
|
||||
{
|
||||
@@ -58,6 +59,22 @@ class CustomField extends BaseModel
|
||||
return new IceResponse(IceResponse::SUCCESS, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CustomField $obj
|
||||
*/
|
||||
public function executePostDeleteActions($obj)
|
||||
{
|
||||
$ret = $this->DB()->Execute(
|
||||
'DELETE FROM CustomFieldValues where type = ? and name = ?',
|
||||
[$obj->type, $obj->name]
|
||||
);
|
||||
|
||||
if (!$ret) {
|
||||
$this->lastError = $this->db()->ErrorMsg();
|
||||
LogManager::getInstance()->error('Error deleting custom field values: '.$this->DB()->ErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -11,6 +11,8 @@ use Utils\LogManager;
|
||||
|
||||
class BaseModel extends \ADOdb_Active_Record
|
||||
{
|
||||
public $objectName = null;
|
||||
protected $allowCustomFields = false;
|
||||
|
||||
public $keysToIgnore = array(
|
||||
"_table",
|
||||
@@ -84,7 +86,7 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
}
|
||||
|
||||
$permissions = $allowedAccessMatrix === null ? $this->getDefaultAccessLevel() : $allowedAccessMatrix;
|
||||
;
|
||||
|
||||
foreach ($userRoles as $role) {
|
||||
$userRole = new UserRole();
|
||||
$userRole->Load('id = ?', [$role]);
|
||||
@@ -195,6 +197,16 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
{
|
||||
}
|
||||
|
||||
public function executePostDeleteActions($obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* If null is returned the object wont be included in the response
|
||||
*
|
||||
* @param $obj
|
||||
* @return mixed
|
||||
*/
|
||||
public function postProcessGetData($obj)
|
||||
{
|
||||
return $obj;
|
||||
@@ -340,4 +352,14 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
return $ok;
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function getObjectName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isCustomFieldsEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
16
core/src/Model/CustomFieldTrait.php
Normal file
16
core/src/Model/CustomFieldTrait.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
trait CustomFieldTrait
|
||||
{
|
||||
public function getObjectName()
|
||||
{
|
||||
return $this->objectName;
|
||||
}
|
||||
|
||||
public function isCustomFieldsEnabled()
|
||||
{
|
||||
return $this->allowCustomFields;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user