Subversion Repositories oidplus

Compare Revisions

Regard whitespace Rev 1115 → Rev 1116

/trunk/includes/classes/OIDplus.class.php
24,29 → 24,86
// phpcs:enable PSR1.Files.SideEffects
 
class OIDplus extends OIDplusBaseClass {
/**
* @var OIDplusPagePlugin[]
*/
private static /*OIDplusPagePlugin[]*/ $pagePlugins = array();
/**
* @var OIDplusAuthPlugin[]
*/
private static /*OIDplusAuthPlugin[]*/ $authPlugins = array();
/**
* @var OIDplusLoggerPlugin[]
*/
private static /*OIDplusLoggerPlugin[]*/ $loggerPlugins = array();
/**
* @var OIDplusObjectTypePlugin[]
*/
private static /*OIDplusObjectTypePlugin[]*/ $objectTypePlugins = array();
/**
* @var string[]|OIDplusObject[] Classnames of OIDplusObject classes
*/
private static /*string[]*/ $enabledObjectTypes = array();
/**
* @var string[]|OIDplusObject[] Classnames of OIDplusObject classes
*/
private static /*string[]*/ $disabledObjectTypes = array();
/**
* @var OIDplusDatabasePlugin[]
*/
private static /*OIDplusDatabasePlugin[]*/ $dbPlugins = array();
/**
* @var OIDplusCaptchaPlugin[]
*/
private static /*OIDplusCaptchaPlugin[]*/ $captchaPlugins = array();
/**
* @var OIDplusSqlSlangPlugin[]
*/
private static /*OIDplusSqlSlangPlugin[]*/ $sqlSlangPlugins = array();
/**
* @var OIDplusLanguagePlugin[]
*/
private static /*OIDplusLanguagePlugin[]*/ $languagePlugins = array();
/**
* @var OIDplusDesignPlugin[]
*/
private static /*OIDplusDesignPlugin[]*/ $designPlugins = array();
 
/**
* @var bool
*/
protected static $html = true;
 
/*public*/ const PATH_RELATIVE = 1; // e.g. "../"
/*public*/ const PATH_ABSOLUTE = 2; // e.g. "http://www.example.com/oidplus/"
/*public*/ const PATH_ABSOLUTE_CANONICAL = 3; // e.g. "http://www.example.org/oidplus/" (if baseconfig CANONICAL_SYSTEM_URL is set)
/*public*/ const PATH_RELATIVE_TO_ROOT = 4; // e.g. "/oidplus/"
/*public*/ const PATH_RELATIVE_TO_ROOT_CANONICAL = 5; // e.g. "/oidplus/" (if baseconfig CANONICAL_SYSTEM_URL is set)
/**
* e.g. "../"
*/
/*public*/ const PATH_RELATIVE = 1;
 
// These plugin types can contain HTML code and therefore may
// emit (non-setup) CSS/JS code via their manifest.
// Note that design plugins may only output CSS, not JS.
/**
* e.g. "http://www.example.com/oidplus/"
*/
/*public*/ const PATH_ABSOLUTE = 2;
 
/**
* e.g. "http://www.example.org/oidplus/" (if baseconfig CANONICAL_SYSTEM_URL is set)
*/
/*public*/ const PATH_ABSOLUTE_CANONICAL = 3;
 
/**
* e.g. "/oidplus/"
*/
/*public*/ const PATH_RELATIVE_TO_ROOT = 4;
 
/**
* e.g. "/oidplus/" (if baseconfig CANONICAL_SYSTEM_URL is set)
*/
/*public*/ const PATH_RELATIVE_TO_ROOT_CANONICAL = 5;
 
/**
* These plugin types can contain HTML code and therefore may
* emit (non-setup) CSS/JS code via their manifest.
* Note that design plugins may only output CSS, not JS.
*/
/*public*/ const INTERACTIVE_PLUGIN_TYPES = array(
'publicPages',
'raPages',
57,9 → 114,16
 
const UUID_NAMEBASED_NS_Base64PubKey = 'fd16965c-8bab-11ed-8744-3c4a92df8582';
 
/**
* Private constructor (Singleton)
*/
private function __construct() {
}
 
/**
* @return bool
* @throws OIDplusException
*/
private static function insideSetup(): bool {
if (PHP_SAPI == 'cli') return false;
if (!isset($_SERVER['REQUEST_URI'])) return false;
70,9 → 134,12
 
private static $baseConfig = null;
private static $oldConfigFormatLoaded = false;
public static function baseConfig() {
$first_init = false;
 
/**
* @return OIDplusBaseConfig
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function baseConfig(): OIDplusBaseConfig {
if ($first_init = is_null(self::$baseConfig)) {
self::$baseConfig = new OIDplusBaseConfig();
}
200,7 → 267,12
}
 
private static $config = null;
public static function config() {
 
/**
* @return OIDplusConfig
* @throws OIDplusException
*/
public static function config(): OIDplusConfig {
if ($first_init = is_null(self::$config)) {
self::$config = new OIDplusConfig();
}
302,7 → 374,11
}
 
private static $gui = null;
public static function gui() {
 
/**
* @return OIDplusGui
*/
public static function gui(): OIDplusGui {
if (is_null(self::$gui)) {
self::$gui = new OIDplusGui();
}
310,7 → 386,11
}
 
private static $authUtils = null;
public static function authUtils() {
 
/**
* @return OIDplusAuthUtils
*/
public static function authUtils(): OIDplusAuthUtils {
if (is_null(self::$authUtils)) {
self::$authUtils = new OIDplusAuthUtils();
}
318,7 → 398,11
}
 
private static $mailUtils = null;
public static function mailUtils() {
 
/**
* @return OIDplusMailUtils
*/
public static function mailUtils(): OIDplusMailUtils {
if (is_null(self::$mailUtils)) {
self::$mailUtils = new OIDplusMailUtils();
}
326,7 → 410,11
}
 
private static $cookieUtils = null;
public static function cookieUtils() {
 
/**
* @return OIDplusCookieUtils
*/
public static function cookieUtils(): OIDplusCookieUtils {
if (is_null(self::$cookieUtils)) {
self::$cookieUtils = new OIDplusCookieUtils();
}
334,7 → 422,11
}
 
private static $menuUtils = null;
public static function menuUtils() {
 
/**
* @return OIDplusMenuUtils
*/
public static function menuUtils(): OIDplusMenuUtils {
if (is_null(self::$menuUtils)) {
self::$menuUtils = new OIDplusMenuUtils();
}
342,7 → 434,11
}
 
private static $logger = null;
public static function logger() {
 
/**
* @return OIDplusLogger
*/
public static function logger(): OIDplusLogger {
if (is_null(self::$logger)) {
self::$logger = new OIDplusLogger();
}
352,7 → 448,9
// --- SQL slang plugin
 
/**
* @param OIDplusSqlSlangPlugin $plugin
* @return void
* @throws OIDplusException
*/
private static function registerSqlSlangPlugin(OIDplusSqlSlangPlugin $plugin) {
$name = $plugin::id();
369,11 → 467,18
self::$sqlSlangPlugins[$name] = $plugin;
}
 
public static function getSqlSlangPlugins() {
/**
* @return OIDplusSqlSlangPlugin[]
*/
public static function getSqlSlangPlugins(): array {
return self::$sqlSlangPlugins;
}
 
public static function getSqlSlangPlugin($id)/*: ?OIDplusSqlSlangPlugin*/ {
/**
* @param string $id
* @return OIDplusSqlSlangPlugin|null
*/
public static function getSqlSlangPlugin(string $id)/*: ?OIDplusSqlSlangPlugin*/ {
if (isset(self::$sqlSlangPlugins[$id])) {
return self::$sqlSlangPlugins[$id];
} else {
384,7 → 489,9
// --- Database plugin
 
/**
* @param OIDplusDatabasePlugin $plugin
* @return void
* @throws OIDplusException
*/
private static function registerDatabasePlugin(OIDplusDatabasePlugin $plugin) {
$name = $plugin::id();
401,11 → 508,18
self::$dbPlugins[$name] = $plugin;
}
 
public static function getDatabasePlugins() {
/**
* @return OIDplusDatabasePlugin[]
*/
public static function getDatabasePlugins(): array {
return self::$dbPlugins;
}
 
public static function getActiveDatabasePlugin() {
/**
* @return OIDplusDatabasePlugin
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function getActiveDatabasePlugin(): OIDplusDatabasePlugin {
$db_plugin_name = OIDplus::baseConfig()->getValue('DATABASE_PLUGIN','');
if ($db_plugin_name === '') {
throw new OIDplusConfigInitializationException(_L('No database plugin selected in config file'));
418,8 → 532,16
throw new OIDplusConfigInitializationException(_L('Database plugin "%1" not found',$db_plugin_name));
}
 
/**
* @var OIDplusDatabaseConnection|null
*/
private static $dbMainSession = null;
public static function db() {
 
/**
* @return OIDplusDatabaseConnection
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function db(): OIDplusDatabaseConnection {
if (is_null(self::$dbMainSession)) {
self::$dbMainSession = self::getActiveDatabasePlugin()->newConnection();
}
427,8 → 549,16
return self::$dbMainSession;
}
 
/**
* @var OIDplusDatabaseConnection|null
*/
private static $dbIsolatedSession = null;
public static function dbIsolated() {
 
/**
* @return OIDplusDatabaseConnection
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function dbIsolated(): OIDplusDatabaseConnection {
if (is_null(self::$dbIsolatedSession)) {
self::$dbIsolatedSession = self::getActiveDatabasePlugin()->newConnection();
}
439,7 → 569,9
// --- CAPTCHA plugin
 
/**
* @param OIDplusCaptchaPlugin $plugin
* @return void
* @throws OIDplusException
*/
private static function registerCaptchaPlugin(OIDplusCaptchaPlugin $plugin) {
$name = $plugin::id();
456,11 → 588,18
self::$captchaPlugins[$name] = $plugin;
}
 
public static function getCaptchaPlugins() {
/**
* @return OIDplusCaptchaPlugin[]
*/
public static function getCaptchaPlugins(): array {
return self::$captchaPlugins;
}
 
public static function getActiveCaptchaPluginId() {
/**
* @return string
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function getActiveCaptchaPluginId(): string {
$captcha_plugin_name = OIDplus::baseConfig()->getValue('CAPTCHA_PLUGIN', '');
 
if (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false) && ($captcha_plugin_name === '')) {
473,7 → 612,11
return $captcha_plugin_name;
}
 
public static function getActiveCaptchaPlugin() {
/**
* @return OIDplusCaptchaPlugin
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function getActiveCaptchaPlugin(): OIDplusCaptchaPlugin {
$captcha_plugin_name = OIDplus::getActiveCaptchaPluginId();
foreach (self::$captchaPlugins as $name => $plugin) {
if (strtolower($name) == strtolower($captcha_plugin_name)) {
486,6 → 629,7
// --- Page plugin
 
/**
* @param OIDplusPagePlugin $plugin
* @return void
*/
private static function registerPagePlugin(OIDplusPagePlugin $plugin) {
492,13 → 636,20
self::$pagePlugins[] = $plugin;
}
 
public static function getPagePlugins() {
/**
* @return OIDplusPagePlugin[]
*/
public static function getPagePlugins(): array {
return self::$pagePlugins;
}
 
// --- Auth plugin
 
public static function getAuthPluginByFoldername($foldername)/*: ?OIDplusAuthPlugin*/ {
/**
* @param string $foldername
* @return OIDplusAuthPlugin|null
*/
public static function getAuthPluginByFoldername(string $foldername)/*: ?OIDplusAuthPlugin*/ {
$plugins = OIDplus::getAuthPlugins();
foreach ($plugins as $plugin) {
if (basename($plugin->getPluginDirectory()) === $foldername) {
508,7 → 659,13
return null;
}
 
private static function checkRaAuthPluginAvailable($plugin_foldername, $must_hash) {
/**
* @param string $plugin_foldername
* @param bool $must_hash
* @return void
* @throws OIDplusException
*/
private static function checkRaAuthPluginAvailable(string $plugin_foldername, bool $must_hash) {
// if (!wildcard_is_dir(OIDplus::localpath().'plugins/'.'*'.'/auth/'.$plugin_foldername)) {
$plugin = OIDplus::getAuthPluginByFoldername($plugin_foldername);
if (is_null($plugin)) {
524,13 → 681,17
}
}
 
public static function getDefaultRaAuthPlugin($must_hash)/*: OIDplusAuthPlugin*/ {
/**
* @param bool $must_hash
* @return OIDplusAuthPlugin|null
* @throws OIDplusException
*/
public static function getDefaultRaAuthPlugin(bool $must_hash)/*: OIDplusAuthPlugin*/ {
// 1. Priority: Use the auth plugin the user prefers
$def_plugin_foldername = OIDplus::config()->getValue('default_ra_auth_method');
if (trim($def_plugin_foldername) !== '') {
OIDplus::checkRaAuthPluginAvailable($def_plugin_foldername, $must_hash);
$plugin = OIDplus::getAuthPluginByFoldername($def_plugin_foldername);
return $plugin;
return OIDplus::getAuthPluginByFoldername($def_plugin_foldername);
}
 
// 2. Priority: If empty (i.e. OIDplus may decide), choose the best ViaThinkSoft plugin that is supported on this system
565,7 → 726,10
}
 
/**
* @param OIDplusAuthPlugin $plugin
* @return void
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
private static function registerAuthPlugin(OIDplusAuthPlugin $plugin) {
$reason = '';
580,8 → 744,6
throw new OIDplusException(_L('Auth plugin "%1" is erroneous: %2',basename($plugin->getPluginDirectory()),$e->getMessage()));
}
 
$authKey = $authInfo->getAuthKey();
 
$authInfo_AuthKeyDiff = clone $authInfo;
$authInfo_AuthKeyDiff->setAuthKey(strrev($authInfo_AuthKeyDiff->getAuthKey()));
 
595,7 → 757,10
self::$authPlugins[] = $plugin;
}
 
public static function getAuthPlugins() {
/**
* @return OIDplusAuthPlugin[]
*/
public static function getAuthPlugins(): array {
return self::$authPlugins;
}
 
602,6 → 767,7
// --- Language plugin
 
/**
* @param OIDplusLanguagePlugin $plugin
* @return void
*/
private static function registerLanguagePlugin(OIDplusLanguagePlugin $plugin) {
608,7 → 774,10
self::$languagePlugins[] = $plugin;
}
 
public static function getLanguagePlugins() {
/**
* @return OIDplusLanguagePlugin[]
*/
public static function getLanguagePlugins(): array {
return self::$languagePlugins;
}
 
615,6 → 784,7
// --- Design plugin
 
/**
* @param OIDplusDesignPlugin $plugin
* @return void
*/
private static function registerDesignPlugin(OIDplusDesignPlugin $plugin) {
621,11 → 791,18
self::$designPlugins[] = $plugin;
}
 
public static function getDesignPlugins() {
/**
* @return OIDplusDesignPlugin[]
*/
public static function getDesignPlugins(): array {
return self::$designPlugins;
}
 
public static function getActiveDesignPlugin() {
/**
* @return OIDplusDesignPlugin|null
* @throws OIDplusException
*/
public static function getActiveDesignPlugin()/*: ?OIDplusDesignPlugin*/ {
$plugins = OIDplus::getDesignPlugins();
foreach ($plugins as $plugin) {
if ((basename($plugin->getPluginDirectory())) == OIDplus::config()->getValue('design','default')) {
638,6 → 815,7
// --- Logger plugin
 
/**
* @param OIDplusLoggerPlugin $plugin
* @return void
*/
private static function registerLoggerPlugin(OIDplusLoggerPlugin $plugin) {
644,7 → 822,10
self::$loggerPlugins[] = $plugin;
}
 
public static function getLoggerPlugins() {
/**
* @return OIDplusLoggerPlugin[]
*/
public static function getLoggerPlugins(): array {
return self::$loggerPlugins;
}
 
651,7 → 832,9
// --- Object type plugin
 
/**
* @param OIDplusObjectTypePlugin $plugin
* @return void
* @throws OIDplusException
*/
private static function registerObjectTypePlugin(OIDplusObjectTypePlugin $plugin) {
self::$objectTypePlugins[] = $plugin;
661,7 → 844,9
}
 
/**
* @param string|OIDplusObject $ot Object type class name (OIDplusObject)
* @return void
* @throws OIDplusException
*/
private static function registerObjectType($ot) {
$ns = $ot::ns();
692,7 → 877,6
$enabled_ary = empty($enabled) ? array() : explode(';', $enabled);
$enabled_ary = array_map('trim', $enabled_ary);
 
$do_enable = false;
if (in_array($ns, $enabled_ary)) {
// If it is in the list of enabled object types, it is enabled (obviously)
$do_enable = true;
738,11 → 922,17
}
}
 
public static function getObjectTypePlugins() {
/**
* @return OIDplusObjectTypePlugin[]
*/
public static function getObjectTypePlugins(): array {
return self::$objectTypePlugins;
}
 
public static function getObjectTypePluginsEnabled() {
/**
* @return OIDplusObjectTypePlugin[]
*/
public static function getObjectTypePluginsEnabled(): array {
$res = array();
foreach (self::$objectTypePlugins as $plugin) {
$ot = $plugin::getObjectTypeClassName();
751,7 → 941,10
return $res;
}
 
public static function getObjectTypePluginsDisabled() {
/**
* @return OIDplusObjectTypePlugin[]
*/
public static function getObjectTypePluginsDisabled(): array {
$res = array();
foreach (self::$objectTypePlugins as $plugin) {
$ot = $plugin::getObjectTypeClassName();
760,17 → 953,26
return $res;
}
 
public static function getEnabledObjectTypes() {
/**
* @return string[]|OIDplusObject[] Classname of a OIDplusObject class
*/
public static function getEnabledObjectTypes(): array {
return self::$enabledObjectTypes;
}
 
public static function getDisabledObjectTypes() {
/**
* @return string[]|OIDplusObject[] Classname of a OIDplusObject class
*/
public static function getDisabledObjectTypes(): array {
return self::$disabledObjectTypes;
}
 
// --- Plugin handling functions
 
public static function getAllPlugins()/*: array*/ {
/**
* @return OIDplusPlugin[]
*/
public static function getAllPlugins(): array {
$res = array();
$res = array_merge($res, self::$pagePlugins);
$res = array_merge($res, self::$authPlugins);
780,11 → 982,14
$res = array_merge($res, self::$captchaPlugins);
$res = array_merge($res, self::$sqlSlangPlugins);
$res = array_merge($res, self::$languagePlugins);
$res = array_merge($res, self::$designPlugins);
return $res;
return array_merge($res, self::$designPlugins);
}
 
public static function getPluginByOid($oid)/*: ?OIDplusPlugin*/ {
/**
* @param string $oid
* @return OIDplusPlugin|null
*/
public static function getPluginByOid(string $oid)/*: ?OIDplusPlugin*/ {
$plugins = self::getAllPlugins();
foreach ($plugins as $plugin) {
if (oid_dotnotation_equal($plugin->getManifest()->getOid(), $oid)) {
794,7 → 999,11
return null;
}
 
public static function getPluginByClassName($classname)/*: ?OIDplusPlugin*/ {
/**
* @param string $classname
* @return OIDplusPlugin|null
*/
public static function getPluginByClassName(string $classname)/*: ?OIDplusPlugin*/ {
$plugins = self::getAllPlugins();
foreach ($plugins as $plugin) {
if (get_class($plugin) === $classname) {
806,7 → 1015,7
 
/**
* Checks if the plugin is disabled
* @return boolean true if plugin is enabled, false if plugin is disabled
* @return bool true if plugin is enabled, false if plugin is disabled
* @throws OIDplusException if the class name or config file (disabled setting) does not contain a namespace
*/
private static function pluginCheckDisabled($class_name): bool {
829,9 → 1038,12
}
 
/**
* @return array<OIDplusPluginManifest>|array<string,array<string,OIDplusPluginManifest>>
* @param string $pluginFolderMasks
* @param bool $flat
* @return OIDplusPluginManifest[]|array<string,array<string,OIDplusPluginManifest>>
* @throws OIDplusException
*/
public static function getAllPluginManifests($pluginFolderMasks='*', $flat=true): array {
public static function getAllPluginManifests(string $pluginFolderMasks='*', bool $flat=true): array {
$out = array();
// Note: glob() will sort by default, so we do not need a page priority attribute.
// So you just need to use a numeric plugin directory prefix (padded).
879,7 → 1091,7
if ($flat) {
$out[] = $manifest;
} else {
$plugintype_folder = basename(dirname(dirname($ini)));
$plugintype_folder = basename(dirname($ini, 2));
$pluginname_folder = basename(dirname($ini));
 
if (!isset($out[$plugintype_folder])) $out[$plugintype_folder] = array();
891,7 → 1103,13
}
 
/**
* @return array<string>
* @param $pluginDirName
* @param $expectedPluginClass
* @param $registerCallback
* @return string[]
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
* @throws \ReflectionException
*/
public static function registerAllPlugins($pluginDirName, $expectedPluginClass, $registerCallback): array {
$out = array();
1027,7 → 1245,14
 
// --- Initialization of OIDplus
 
public static function init($html=true, $keepBaseConfig=true) {
/**
* @param bool $html
* @param bool $keepBaseConfig
* @return void
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function init(bool $html=true, bool $keepBaseConfig=true) {
self::$html = $html;
 
// Reset internal state, so we can re-init verything if required
1260,7 → 1485,7
foreach ($http_headers as $name => $val) {
 
// Plugins can remove standard OIDplus headers by setting the value to null.
if (is_null($val)) continue; /** @phpstan-ignore-line */
if (is_null($val)) continue;
 
// Some headers can be written as arrays to make it easier for plugin authors
// to manipulate/extend the contents.
1297,6 → 1522,9
 
// --- System URL, System ID, PKI, and other functions
 
/**
* @return void
*/
private static function recognizeSystemUrl() {
try {
$url = OIDplus::webpath(null,self::PATH_ABSOLUTE_CANONICAL);
1305,6 → 1533,9
}
}
 
/**
* @return false|int
*/
private static function getExecutingScriptPathDepth() {
if (PHP_SAPI == 'cli') {
global $argv;
1323,7 → 1554,10
return $steps_up;
}
 
public static function isSSL() {
/**
* @return bool
*/
public static function isSSL(): bool {
return isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on');
}
 
1334,8 → 1568,9
* results in an absolute URL. OIDplus::PATH_ABSOLUTE_CANONICAL is an absolute URL,
* but a canonical path (set by base config setting CANONICAL_SYSTEM_URL) is preferred.
* @return string|false The URL, with guaranteed trailing path delimiter for directories
* @throws OIDplusException
*/
private static function getSystemUrl($mode) {
private static function getSystemUrl(int $mode) {
if ($mode === self::PATH_RELATIVE) {
$steps_up = self::getExecutingScriptPathDepth();
if ($steps_up === false) {
1379,6 → 1614,10
}
}
 
/**
* @param $pubKey
* @return false|string
*/
private static function pubKeyToRaw($pubKey) {
$m = array();
if (preg_match('@BEGIN PUBLIC KEY\\-+([^\\-]+)\\-+END PUBLIC KEY@ismU', $pubKey, $m)) {
1387,6 → 1626,10
return false;
}
 
/**
* @param $pubKey
* @return false|int
*/
private static function getSystemIdFromPubKey($pubKey) {
$rawData = self::pubKeyToRaw($pubKey);
if ($rawData === false) return false;
1393,6 → 1636,10
return smallhash($rawData);
}
 
/**
* @param $pubKey
* @return false|string
*/
private static function getSystemGuidFromPubKey($pubKey) {
$rawData = self::pubKeyToRaw($pubKey);
if ($rawData === false) return false;
1401,7 → 1648,13
}
 
private static $system_id_cache = null;
public static function getSystemId($oid=false) {
 
/**
* @param bool $oid
* @return false|string
* @throws OIDplusException
*/
public static function getSystemId(bool $oid=false) {
if (!is_null(self::$system_id_cache)) {
$out = self::$system_id_cache;
} else {
1418,6 → 1671,11
}
 
private static $system_guid_cache = null;
 
/**
* @return false|string
* @throws OIDplusException
*/
public static function getSystemGuid() {
if (!is_null(self::$system_guid_cache)) {
$out = self::$system_guid_cache;
1434,6 → 1692,9
return $out;
}
 
/**
* @return array|string
*/
public static function getOpenSslCnf() {
// The following functions need a config file, otherway they don't work
// - openssl_csr_new
1451,10 → 1712,16
return __DIR__.'/../../vendor/phpseclib/phpseclib/phpseclib/openssl.cnf';
}
 
private static function getPrivKeyPassphraseFilename() {
/**
* @return string
*/
private static function getPrivKeyPassphraseFilename(): string {
return OIDplus::localpath() . 'userdata/privkey_secret.php';
}
 
/**
* @return void
*/
private static function tryCreatePrivKeyPassphrase() {
$file = self::getPrivKeyPassphraseFilename();
 
1471,6 → 1738,9
@file_put_contents($file, $cont);
}
 
/**
* @return string|false
*/
private static function getPrivKeyPassphrase() {
$file = self::getPrivKeyPassphraseFilename();
if (!file_exists($file)) return false;
1480,6 → 1750,10
return $m[1];
}
 
/**
* @return string|false
* @throws OIDplusException
*/
public static function getSystemPrivateKey() {
$privKey = OIDplus::config()->getValue('oidplus_private_key');
if ($privKey == '') return false;
1497,6 → 1771,10
return $privKey;
}
 
/**
* @return string|false
* @throws OIDplusException
*/
public static function getSystemPublicKey() {
$pubKey = OIDplus::config()->getValue('oidplus_public_key');
if ($pubKey == '') return false;
1503,7 → 1781,12
return $pubKey;
}
 
public static function getPkiStatus($try_generate=false) {
/**
* @param bool $try_generate
* @return bool
* @throws OIDplusException
*/
public static function getPkiStatus(bool $try_generate=false): bool {
if (!function_exists('openssl_pkey_new')) return false;
 
if ($try_generate) {
1574,6 → 1857,9
return verify_private_public_key($privKey, $pubKey);
}
 
/**
* @return string|void
*/
public static function getInstallType() {
$counter = 0;
 
1610,6 → 1896,9
}
}
 
/**
* @return void
*/
private static function recognizeVersion() {
try {
$ver_prev = OIDplus::config()->getValue("last_known_version");
1626,6 → 1915,9
}
}
 
/**
* @return false|string|null
*/
public static function getVersion() {
static $cachedVersion = null;
if (!is_null($cachedVersion)) {
1644,7 → 1936,7
}
 
if ($installType === 'git-wc') {
$ver = OIDplus::getGitsvnRevision(OIDplus::localpath());
$ver = OIDplus::getGitsvnRevision();
if ($ver)
return ($cachedVersion = 'svn-'.$ver);
}
1667,6 → 1959,11
const ENFORCE_SSL_YES = 1;
const ENFORCE_SSL_AUTO = 2;
private static $sslAvailableCache = null;
 
/**
* @return bool|void|null
* @throws OIDplusException, OIDplusConfigInitializationException
*/
public static function isSslAvailable() {
if (!is_null(self::$sslAvailableCache)) return self::$sslAvailableCache;
 
1749,11 → 2046,11
 
/**
* Gets a local path pointing to a resource
* @param string $target Target resource (file or directory must exist), or null to get the OIDplus base directory
* @param boolean $relative If true, the returning path is relative to the currently executed PHP file (not the CLI working directory)
* @param string|null $target Target resource (file or directory must exist), or null to get the OIDplus base directory
* @param bool $relative If true, the returning path is relative to the currently executed PHP file (not the CLI working directory)
* @return string|false The local path, with guaranteed trailing path delimiter for directories
*/
public static function localpath($target=null, $relative=false) {
public static function localpath(string $target=null, bool $relative=false) {
if (is_null($target)) {
$target = __DIR__.'/../../';
}
1778,21 → 2075,20
 
if (is_dir($target)) $res .= '/';
 
$res = str_replace('/', DIRECTORY_SEPARATOR, $res);
 
return $res;
return str_replace('/', DIRECTORY_SEPARATOR, $res);
}
 
/**
* Gets a URL pointing to a resource
* @param string $target Target resource (file or directory must exist), or null to get the OIDplus base directory
* @param int|boolean $mode If true or OIDplus::PATH_RELATIVE, the returning path is relative to the currently executed
* @param string|null $target Target resource (file or directory must exist), or null to get the OIDplus base directory
* @param int|bool $mode If true or OIDplus::PATH_RELATIVE, the returning path is relative to the currently executed
* PHP script (i.e. index.php , not the plugin PHP script!). False or OIDplus::PATH_ABSOLUTE is
* results in an absolute URL. OIDplus::PATH_ABSOLUTE_CANONICAL is an absolute URL,
* but a canonical path (set by base config setting CANONICAL_SYSTEM_URL) is preferred.
* @return string|false The URL, with guaranteed trailing path delimiter for directories
* @throws OIDplusException
*/
public static function webpath($target=null, $mode=self::PATH_ABSOLUTE_CANONICAL) {
public static function webpath(string $target=null, $mode=self::PATH_ABSOLUTE_CANONICAL) {
// backwards compatibility
if ($mode === true) $mode = self::PATH_RELATIVE;
if ($mode === false) $mode = self::PATH_ABSOLUTE;
1830,6 → 2126,10
return $res;
}
 
/**
* @return false|string
* @throws OIDplusException
*/
public static function canonicalURL() {
// First part: OIDplus system URL (or canonical system URL)
$sysurl = OIDplus::getSystemUrl(self::PATH_ABSOLUTE_CANONICAL);
1854,10 → 2154,18
}
 
private static $shutdown_functions = array();
 
/**
* @param $func
* @return void
*/
public static function register_shutdown_function($func) {
self::$shutdown_functions[] = $func;
}
 
/**
* @return void
*/
public static function invoke_shutdown() {
foreach (self::$shutdown_functions as $func) {
$func();
1864,7 → 2172,11
}
}
 
public static function getAvailableLangs() {
/**
* @return string[]
* @throws OIDplusException
*/
public static function getAvailableLangs(): array {
$langs = array();
foreach (OIDplus::getAllPluginManifests('language') as $pluginManifest) {
$code = $pluginManifest->getLanguageCode();
1873,7 → 2185,12
return $langs;
}
 
public static function getDefaultLang() {
/**
* @return string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function getDefaultLang(): string {
static $thrownOnce = false; // avoid endless loop inside OIDplusConfigInitializationException
 
$lang = self::baseConfig()->getValue('DEFAULT_LANGUAGE', 'enus');
1890,6 → 2207,11
return $lang;
}
 
/**
* @return false|string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function getCurrentLang() {
if (isset($_GET['lang'])) {
$lang = $_GET['lang'];
1900,10 → 2222,13
} else {
$lang = self::getDefaultLang();
}
$lang = substr(preg_replace('@[^a-z]@ismU', '', $lang),0,4); // sanitize
return $lang;
return substr(preg_replace('@[^a-z]@ismU', '', $lang),0,4); // sanitize
}
 
/**
* @return void
* @throws OIDplusException
*/
public static function handleLangArgument() {
if (isset($_GET['lang'])) {
// The "?lang=" argument is only for NoScript-Browsers/SearchEngines
1918,6 → 2243,11
}
 
private static $translationArray = array();
 
/**
* @param $translation_file
* @return array|mixed
*/
protected static function getTranslationFileContents($translation_file) {
// First, try the cache
$cache_file = __DIR__ . '/../../userdata/cache/translation_'.md5($translation_file).'.ser';
1939,7 → 2269,13
@touch($cache_file,filemtime($translation_file));
return $cac;
}
public static function getTranslationArray($requested_lang='*') {
 
/**
* @param string $requested_lang
* @return array
* @throws OIDplusException
*/
public static function getTranslationArray(string $requested_lang='*'): array {
foreach (OIDplus::getAllPluginManifests('language') as $pluginManifest) {
$lang = $pluginManifest->getLanguageCode();
if (strpos($lang,'/') !== false) continue; // just to be sure
1970,10 → 2306,16
return self::$translationArray;
}
 
/**
* @return mixed
*/
public static function getEditionInfo() {
return @parse_ini_file(__DIR__.'/../edition.ini', true)['Edition'];
}
 
/**
* @return false|string
*/
public static function findGitFolder() {
// Git command line saves git information in folder ".git"
// Plesk git saves git information in folder "../../../git/oidplus/" (or similar)
1995,7 → 2337,10
return false;
}
 
public static function getGitsvnRevision($dir='') {
/**
* @return false|string
*/
public static function getGitsvnRevision() {
try {
// tries command line and binary parsing
// requires vendor/danielmarschall/git_utils.inc.php
2014,7 → 2359,12
}
}
 
public static function prefilterQuery($static_node_id, $throw_exception) {
/**
* @param string $static_node_id
* @param bool $throw_exception
* @return string
*/
public static function prefilterQuery(string $static_node_id, bool $throw_exception): string {
// Let namespace be case-insensitive
$ary = explode(':', $static_node_id, 2);
$ary[0] = strtolower($ary[0]);
2028,18 → 2378,23
return $static_node_id;
}
 
public static function isCronjob() {
/**
* @return bool
*/
public static function isCronjob(): bool {
return explode('.',basename($_SERVER['SCRIPT_NAME']))[0] === 'cron';
}
 
/**
* Since OIDplus svn-184, entries in the database need to have a canonical ID
* If the ID is not canonical (e.g. GUIDs missing hyphens), the object cannot be opened in OIDplus
* This script re-canonizes the object IDs if required.
* In SVN Rev 856, the canonization for GUID, IPv4 and IPv6 have changed, requiring another
* re-canonization
* @return void
* @throws OIDplusException
*/
private static function recanonizeObjects() {
//
// Since OIDplus svn-184, entries in the database need to have a canonical ID
// If the ID is not canonical (e.g. GUIDs missing hyphens), the object cannot be opened in OIDplus
// This script re-canonizes the object IDs if required.
// In SVN Rev 856, the canonization for GUID, IPv4 and IPv6 have changed, requiring another
// re-canonization
//
$res = OIDplus::db()->query("select id from ###objects");
while ($row = $res->fetch_array()) {
$ida = $row['id'];
/trunk/includes/classes/OIDplusAltId.class.php
30,7 → 30,13
private $desc;
private $suffix;
 
function __construct($ns, $id, $desc, $suffix='') {
/**
* @param string $ns
* @param string $id
* @param string $desc
* @param string $suffix
*/
function __construct(string $ns, string $id, string $desc, string $suffix='') {
$this->ns = $ns;
$this->id = $id;
$this->desc = $desc;
37,19 → 43,31
$this->suffix = $suffix;
}
 
function getNamespace() {
/**
* @return string
*/
function getNamespace(): string {
return $this->ns;
}
 
function getId() {
/**
* @return string
*/
function getId(): string {
return $this->id;
}
 
function getDescription() {
/**
* @return string
*/
function getDescription(): string {
return $this->desc;
}
 
function getSuffix() {
/**
* @return string
*/
function getSuffix(): string {
return $this->suffix;
}
 
/trunk/includes/classes/OIDplusAuthContentStore.class.php
27,31 → 27,81
 
// Getter / Setter
 
public abstract function getValue($name, $default = NULL);
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
*/
public abstract function getValue(string $name, $default = NULL);
 
public abstract function setValue($name, $value);
/**
* @param string $name
* @param mixed $value
* @return void
*/
public abstract function setValue(string $name, $value);
 
public abstract function exists($name);
/**
* @param string $name
* @return bool
*/
public abstract function exists(string $name): bool;
 
public abstract function delete($name);
/**
* @param string $name
* @return void
*/
public abstract function delete(string $name);
 
public abstract static function getActiveProvider();
/**
* @return OIDplusAuthContentStore|null
* @throws OIDplusException
*/
public abstract static function getActiveProvider()/*: ?OIDplusAuthContentStore*/;
 
/**
* @return mixed
*/
public abstract function destroySession();
 
/**
* @return mixed
*/
public abstract function activate();
 
public abstract function raLoginEx($email, &$loginfo);
/**
* @param string $email
* @param string $loginfo
* @return void
*/
public abstract function raLoginEx(string $email, string &$loginfo);
 
public abstract function raLogoutEx($email, &$loginfo);
/**
* @param string $email
* @param string $loginfo
* @return void
*/
public abstract function raLogoutEx(string $email, string &$loginfo);
 
public abstract function adminLoginEx(&$loginfo);
/**
* @param string $loginfo
* @return void
*/
public abstract function adminLoginEx(string &$loginfo);
 
public abstract function adminLogoutEx(&$loginfo);
/**
* @param string $loginfo
* @return void
*/
public abstract function adminLogoutEx(string &$loginfo);
 
// RA authentication functions (low-level)
 
public function raLogin($email) {
/**
* @param string $email
* @return void
*/
public function raLogin(string $email) {
if (strpos($email, '|') !== false) return;
 
$list = $this->getValue('oidplus_ra_logged_in');
64,7 → 114,11
$this->setValue('oidplus_ra_logged_in', $list);
}
 
public function raLogout($email) {
/**
* @param string $email
* @return void
*/
public function raLogout(string $email) {
$list = $this->getValue('oidplus_ra_logged_in');
if (is_null($list)) $list = '';
 
76,11 → 130,17
$this->setValue('oidplus_ra_logged_in', $list);
}
 
public function raNumLoggedIn() {
/**
* @return int
*/
public function raNumLoggedIn(): int {
return count($this->loggedInRaList());
}
 
public function loggedInRaList() {
/**
* @return OIDplusRA[]
*/
public function loggedInRaList(): array {
$list = $this->getValue('oidplus_ra_logged_in');
if (is_null($list)) $list = '';
 
92,7 → 152,11
return $res;
}
 
public function isRaLoggedIn($email) {
/**
* @param string $email
* @return bool
*/
public function isRaLoggedIn(string $email) {
foreach ($this->loggedInRaList() as $ra) {
if ($email == $ra->raEmail()) return true;
}
101,15 → 165,24
 
// Admin authentication functions (low-level)
 
/**
* @return void
*/
public function adminLogin() {
$this->setValue('oidplus_admin_logged_in', 1);
}
 
/**
* @return void
*/
public function adminLogout() {
$this->setValue('oidplus_admin_logged_in', 0);
}
 
public function isAdminLoggedIn() {
/**
* @return bool
*/
public function isAdminLoggedIn(): bool {
return $this->getValue('oidplus_admin_logged_in') == 1;
}
 
/trunk/includes/classes/OIDplusAuthContentStoreDummy.class.php
30,19 → 30,37
 
// Override some abstract functions
 
public function getValue($name, $default = NULL) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
*/
public function getValue(string $name, $default = NULL) {
return isset($this->content[$name]) ? $this->content[$name] : $default;
}
 
public function setValue($name, $value) {
/**
* @param string $name
* @param mixed $value
* @return void
*/
public function setValue(string $name, $value) {
$this->content[$name] = $value;
}
 
public function exists($name) {
/**
* @param string $name
* @return bool
*/
public function exists(string $name): bool {
return isset($this->content[$name]);
}
 
public function delete($name) {
/**
* @param string $name
* @return void
*/
public function delete(string $name) {
unset($this->content[$name]);
}
 
/trunk/includes/classes/OIDplusAuthContentStoreJWT.class.php
31,12 → 31,23
const JWT_GENERATOR_LOGIN = 1; // "Remember me" login method
const JWT_GENERATOR_MANUAL = 2; // "Manually crafted" JWT tokens
 
private static function jwtGetBlacklistConfigKey($gen, $sub) {
/**
* @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_...
* @param string $sub
* @return string
*/
private static function jwtGetBlacklistConfigKey(int $gen, string $sub): string {
// Note: Needs to be <= 50 characters!
return 'jwt_blacklist_gen('.$gen.')_sub('.trim(base64_encode(md5($sub,true)),'=').')';
}
 
public static function jwtBlacklist($gen, $sub) {
/**
* @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_...
* @param string $sub
* @return void
* @throws OIDplusException
*/
public static function jwtBlacklist(int $gen, string $sub) {
$cfg = self::jwtGetBlacklistConfigKey($gen, $sub);
$bl_time = time()-1;
 
45,16 → 56,27
if ($gen === self::JWT_GENERATOR_LOGIN) $gen_desc = 'Login ("Remember me")';
if ($gen === self::JWT_GENERATOR_MANUAL) $gen_desc = 'Manually created';
 
OIDplus::config()->prepareConfigKey($cfg, 'Revoke timestamp of all JWT tokens for $sub with generator $gen ($gen_desc)', $bl_time, OIDplusConfig::PROTECTION_HIDDEN, function($value) {});
OIDplus::config()->prepareConfigKey($cfg, 'Revoke timestamp of all JWT tokens for $sub with generator $gen ($gen_desc)', "$bl_time", OIDplusConfig::PROTECTION_HIDDEN, function($value) {});
OIDplus::config()->setValue($cfg, $bl_time);
}
 
public static function jwtGetBlacklistTime($gen, $sub) {
/**
* @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_...
* @param string $sub
* @return int
* @throws OIDplusException
*/
public static function jwtGetBlacklistTime(int $gen, string $sub): int {
$cfg = self::jwtGetBlacklistConfigKey($gen, $sub);
return OIDplus::config()->getValue($cfg,0);
return (int)OIDplus::config()->getValue($cfg,0);
}
 
private static function jwtSecurityCheck($contentProvider) {
/**
* @param OIDplusAuthContentStore $contentProvider
* @return void
* @throws OIDplusException
*/
private static function jwtSecurityCheck(OIDplusAuthContentStore $contentProvider) {
// Check if the token is intended for us
if ($contentProvider->getValue('aud','') !== OIDplus::getEditionInfo()['jwtaud']) {
throw new OIDplusException(_L('Token has wrong audience'));
140,11 → 162,18
 
// Override abstract functions
 
/**
* @return void
*/
public function activate() {
// Send cookie at the end of the HTTP request, in case there are multiple activate() calls
OIDplus::register_shutdown_function(array($this,'activateNow'));
}
 
/**
* @return void
* @throws OIDplusException
*/
public function activateNow() {
$token = $this->getJWTToken();
$exp = $this->getValue('exp',0);
151,21 → 180,40
OIDplus::cookieUtils()->setcookie(self::COOKIE_NAME, $token, $exp, false);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function destroySession() {
OIDplus::cookieUtils()->unsetcookie(self::COOKIE_NAME);
}
 
public function raLogout($email) {
/**
* @param string $email
* @return void
* @throws OIDplusException
*/
public function raLogout(string $email) {
$gen = $this->getValue('oidplus_generator', -1);
if ($gen >= 0) self::jwtBlacklist($gen, $email);
parent::raLogout($email);
}
 
public function raLogoutEx($email, &$loginfo) {
/**
* @param string $email
* @param string $loginfo
* @return void
* @throws OIDplusException
*/
public function raLogoutEx(string $email, string &$loginfo) {
$this->raLogout($email);
$loginfo = 'from JWT session';
}
 
/**
* @return void
* @throws OIDplusException
*/
public function adminLogout() {
$gen = $this->getValue('oidplus_generator', -1);
if ($gen >= 0) self::jwtBlacklist($gen, 'admin');
172,13 → 220,23
parent::adminLogout();
}
 
public function adminLogoutEx(&$loginfo) {
/**
* @param string $loginfo
* @return void
* @throws OIDplusException
*/
public function adminLogoutEx(string &$loginfo) {
$this->adminLogout();
$loginfo = 'from JWT session';
}
 
private static $contentProvider = null;
public static function getActiveProvider() {
 
/**
* @return OIDplusAuthContentStore|null
* @throws OIDplusException
*/
public static function getActiveProvider()/*: ?OIDplusAuthContentStore*/ {
if (!self::$contentProvider) {
$jwt = '';
if (isset($_COOKIE[self::COOKIE_NAME])) $jwt = $_COOKIE[self::COOKIE_NAME];
212,7 → 270,13
return self::$contentProvider;
}
 
public function raLoginEx($email, &$loginfo) {
/**
* @param string $email
* @param string $loginfo
* @return void
* @throws OIDplusException
*/
public function raLoginEx(string $email, string &$loginfo) {
if (is_null(self::getActiveProvider())) {
$this->raLogin($email);
$loginfo = 'into new JWT session';
237,7 → 301,12
}
}
 
public function adminLoginEx(&$loginfo) {
/**
* @param string $loginfo
* @return void
* @throws OIDplusException
*/
public function adminLoginEx(string &$loginfo) {
if (is_null(self::getActiveProvider())) {
$this->adminLogin();
$loginfo = 'into new JWT session';
264,7 → 333,12
 
// Individual functions
 
public function loadJWT($jwt) {
/**
* @param string $jwt
* @return void
* @throws OIDplusException
*/
public function loadJWT(string $jwt) {
\Firebase\JWT\JWT::$leeway = 60; // leeway in seconds
if (OIDplus::getPkiStatus()) {
$pubKey = OIDplus::getSystemPublicKey();
278,7 → 352,11
}
}
 
public function getJWTToken() {
/**
* @return string
* @throws OIDplusException
*/
public function getJWTToken(): string {
$payload = $this->content;
$payload["iss"] = OIDplus::getEditionInfo()['jwtaud'];
$payload["aud"] = OIDplus::getEditionInfo()['jwtaud'];
/trunk/includes/classes/OIDplusAuthContentStoreSession.class.php
25,7 → 25,10
 
class OIDplusAuthContentStoreSession extends OIDplusAuthContentStore {
 
protected static function getSessionHandler() {
/**
* @return OIDplusSessionHandler
*/
protected static function getSessionHandler(): OIDplusSessionHandler {
static $sesHandler = null;
if (is_null($sesHandler)) {
$sesHandler = new OIDplusSessionHandler();
36,7 → 39,13
// Override abstract functions
# TODO: shouldn't we just include OIDplusSessionHandler in this class?
 
public function getValue($name, $default = NULL) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
* @throws OIDplusException
*/
public function getValue(string $name, $default = NULL) {
try {
return self::getSessionHandler()->getValue($name, $default);
} catch (\Exception $e) {
46,23 → 55,46
}
}
 
public function setValue($name, $value) {
return self::getSessionHandler()->setValue($name, $value);
/**
* @param string $name
* @param mixed $value
* @return void
* @throws OIDplusException
*/
public function setValue(string $name, $value) {
self::getSessionHandler()->setValue($name, $value);
}
 
public function exists($name) {
/**
* @param string $name
* @return bool
* @throws OIDplusException
*/
public function exists(string $name): bool {
return self::getSessionHandler()->exists($name);
}
 
public function delete($name) {
return self::getSessionHandler()->delete($name);
/**
* @param string $name
* @return void
* @throws OIDplusException
*/
public function delete(string $name) {
self::getSessionHandler()->delete($name);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function destroySession() {
return self::getSessionHandler()->destroySession();
self::getSessionHandler()->destroySession();
}
 
public static function getActiveProvider() {
/**
* @return OIDplusAuthContentStoreSession|null
*/
public static function getActiveProvider()/*: ?OIDplusAuthContentStore*/ {
static $contentProvider = null;
 
if (!$contentProvider) {
74,7 → 106,12
return $contentProvider;
}
 
public function raLoginEx($email, &$loginfo) {
/**
* @param string $email
* @param string $loginfo
* @return void
*/
public function raLoginEx(string $email, string &$loginfo) {
$this->raLogin($email);
if (is_null(self::getActiveProvider())) {
$loginfo = 'into new PHP session';
83,7 → 120,11
}
}
 
public function adminLoginEx(&$loginfo) {
/**
* @param string $loginfo
* @return void
*/
public function adminLoginEx(string &$loginfo) {
$this->adminLogin();
if (is_null(self::getActiveProvider())) {
$loginfo = 'into new PHP session';
92,19 → 133,30
}
}
 
public function raLogoutEx($email, &$loginfo) {
/**
* @param string $email
* @param string $loginfo
* @return void
*/
public function raLogoutEx(string $email, string &$loginfo) {
$this->raLogout($email);
$loginfo = 'from PHP session';
}
 
public function adminLogoutEx(&$loginfo) {
/**
* @param string $loginfo
* @return void
*/
public function adminLogoutEx(string &$loginfo) {
$this->adminLogout();
$loginfo = 'from PHP session';
}
 
/**
* @return void
*/
public function activate() {
# Sessions automatically activate during setValue()
return;
}
 
}
/trunk/includes/classes/OIDplusAuthPlugin.class.php
24,8 → 24,28
// phpcs:enable PSR1.Files.SideEffects
 
abstract class OIDplusAuthPlugin extends OIDplusPlugin {
public abstract function verify(OIDplusRAAuthInfo $authKey, $check_password);
public abstract function generate($password): OIDplusRAAuthInfo;
public abstract function availableForHash(&$reason): bool;
public abstract function availableForVerify(&$reason): bool;
/**
* @param OIDplusRAAuthInfo $authInfo
* @param string $check_password
* @return bool
*/
public abstract function verify(OIDplusRAAuthInfo $authInfo, string $check_password): bool;
 
/**
* @param string $password
* @return OIDplusRAAuthInfo
*/
public abstract function generate(string $password): OIDplusRAAuthInfo;
 
/**
* @param string $reason
* @return bool
*/
public abstract function availableForHash(string &$reason): bool;
 
/**
* @param string $reason
* @return bool
*/
public abstract function availableForVerify(string &$reason): bool;
}
/trunk/includes/classes/OIDplusAuthUtils.class.php
27,6 → 27,11
 
// Useful functions
 
/**
* @param string $password
* @return string
* @throws OIDplusException
*/
private static function raPepperProcessing(string $password): string {
// Additional feature: Pepper
// The pepper is stored inside the base configuration file
43,7 → 48,7
} else {
$hmac = hash_hmac($algo, $password, $pepper);
}
if ($hmac === false) throw new OIDplusException(_L('HMAC failed'));
if ($hmac === "") throw new OIDplusException(_L('HMAC failed'));
return $hmac;
} else {
return $password;
52,6 → 57,10
 
// Content provider
 
/**
* @return string
* @throws OIDplusException
*/
public function getAuthMethod() {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return 'null';
58,7 → 67,11
return get_class($acs);
}
 
protected function getAuthContentStore() {
/**
* @return OIDplusAuthContentStore|null
* @throws OIDplusException
*/
protected function getAuthContentStore()/*: ?OIDplusAuthContentStore*/ {
// Logged in via JWT
$tmp = OIDplusAuthContentStoreJWT::getActiveProvider();
if ($tmp) return $tmp;
72,7 → 85,13
return null;
}
 
public function getExtendedAttribute($name, $default=NULL) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed
* @throws OIDplusException
*/
public function getExtendedAttribute(string $name, $default=NULL) {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return $default;
return $acs->getValue($name, $default);
80,19 → 99,35
 
// RA authentication functions
 
public function raLogin($email) {
/**
* @param string $email
* @return void
* @throws OIDplusException
*/
public function raLogin(string $email) {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
return $acs->raLogin($email);
$acs->raLogin($email);
}
 
public function raLogout($email) {
/**
* @param string $email
* @return void
* @throws OIDplusException
*/
public function raLogout(string $email) {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
return $acs->raLogout($email);
$acs->raLogout($email);
}
 
public function raCheckPassword($ra_email, $password) {
/**
* @param string $ra_email
* @param string $password
* @return bool
* @throws OIDplusException
*/
public function raCheckPassword(string $ra_email, string $password): bool {
$ra = new OIDplusRA($ra_email);
 
// Get RA info from RA
111,13 → 146,21
return false;
}
 
public function raNumLoggedIn() {
/**
* @return int
* @throws OIDplusException
*/
public function raNumLoggedIn(): int {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return 0;
return $acs->raNumLoggedIn();
}
 
public function loggedInRaList() {
/**
* @return OIDplusRA[]
* @throws OIDplusException
*/
public function loggedInRaList(): array {
if ($this->forceAllLoggedOut()) {
return array();
} else {
127,7 → 170,12
}
}
 
public function isRaLoggedIn($email) {
/**
* @param string $email
* @return bool
* @throws OIDplusException
*/
public function isRaLoggedIn(string $email): bool {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return false;
return $acs->isRaLoggedIn($email);
134,7 → 182,15
}
 
// "High level" function including logging and checking for valid JWT alternations
public function raLoginEx($email, $remember_me, $origin='') {
 
/**
* @param string $email
* @param bool $remember_me
* @param string $origin
* @return void
* @throws OIDplusException
*/
public function raLoginEx(string $email, bool $remember_me, string $origin='') {
$loginfo = '';
$acs = $this->getAuthContentStore();
if (!is_null($acs)) {
163,12 → 219,17
OIDplus::logger()->log("[OK]RA($email)!", $logmsg);
}
 
public function raLogoutEx($email) {
/**
* @param string $email
* @return void
* @throws OIDplusException
*/
public function raLogoutEx(string $email) {
$loginfo = '';
 
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
$res = $acs->raLogoutEx($email, $loginfo);
$acs->raLogoutEx($email, $loginfo);
 
OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged out ($loginfo)");
 
179,25 → 240,36
// Get a new token for the remaining users
$acs->activate();
}
 
return $res;
}
 
// Admin authentication functions
 
/**
* @return void
* @throws OIDplusException
*/
public function adminLogin() {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
return $acs->adminLogin();
$acs->adminLogin();
}
 
/**
* @return void
* @throws OIDplusException
*/
public function adminLogout() {
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
return $acs->adminLogout();
$acs->adminLogout();
}
 
public function adminCheckPassword($password) {
/**
* @param string $password
* @return bool
* @throws OIDplusException
*/
public function adminCheckPassword(string $password): bool {
$cfgData = OIDplus::baseConfig()->getValue('ADMIN_PASSWORD', '');
if (empty($cfgData)) {
throw new OIDplusException(_L('No admin password set in %1','userdata/baseconfig/config.inc.php'));
227,7 → 299,11
return false;
}
 
public function isAdminLoggedIn() {
/**
* @return bool
* @throws OIDplusException
*/
public function isAdminLoggedIn(): bool {
if ($this->forceAllLoggedOut()) {
return false;
} else {
237,8 → 313,14
}
}
 
// "High level" function including logging and checking for valid JWT alternations
public function adminLoginEx($remember_me, $origin='') {
/**
* "High level" function including logging and checking for valid JWT alternations
* @param bool $remember_me
* @param string $origin
* @return void
* @throws OIDplusException
*/
public function adminLoginEx(bool $remember_me, string $origin='') {
$loginfo = '';
$acs = $this->getAuthContentStore();
if (!is_null($acs)) {
267,12 → 349,16
OIDplus::logger()->log("[OK]A!", $logmsg);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function adminLogoutEx() {
$loginfo = '';
 
$acs = $this->getAuthContentStore();
if (is_null($acs)) return;
$res = $acs->adminLogoutEx($loginfo);
$acs->adminLogoutEx($loginfo);
 
if ($this->raNumLoggedIn() == 0) {
// Nobody here anymore. Destroy the cookie to make GDPR people happy
283,22 → 369,35
}
 
OIDplus::logger()->log("[OK]A!", "Admin logged out ($loginfo)");
return $res;
}
 
// Authentication keys for validating arguments (e.g. sent by mail)
 
public static function makeAuthKey($data) {
/**
* @param string $data
* @return string
* @throws OIDplusException
*/
public static function makeAuthKey(string $data): string {
return sha3_512_hmac($data, 'authkey:'.OIDplus::baseConfig()->getValue('SERVER_SECRET'), false);
}
 
public static function validateAuthKey($data, $auth_key) {
/**
* @param string $data
* @param string $auth_key
* @return bool
* @throws OIDplusException
*/
public static function validateAuthKey(string $data, string $auth_key): bool {
return hash_equals(self::makeAuthKey($data), $auth_key);
}
 
// "Veto" functions to force logout state
 
protected function forceAllLoggedOut() {
/**
* @return bool
*/
protected function forceAllLoggedOut(): bool {
if (isset($_SERVER['SCRIPT_FILENAME']) && (basename($_SERVER['SCRIPT_FILENAME']) == 'sitemap.php')) {
// The sitemap may not contain any confidential information,
// even if the user is logged in, because the admin could
314,18 → 413,32
 
private $enable_csrf = true;
 
/**
* @return void
*/
public function enableCSRF() {
$this->enable_csrf = true;
}
 
/**
* @return void
*/
public function disableCSRF() {
$this->enable_csrf = false;
}
 
public function genCSRFToken() {
/**
* @return string
* @throws \Random\RandomException
*/
public function genCSRFToken(): string {
return random_bytes_ex(64, false, false);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function checkCSRF() {
if (!$this->enable_csrf) return;
 
346,7 → 459,12
 
// Generate RA passwords
 
public static function raGeneratePassword($password): OIDplusRAAuthInfo {
/**
* @param string $password
* @return OIDplusRAAuthInfo
* @throws OIDplusException
*/
public static function raGeneratePassword(string $password): OIDplusRAAuthInfo {
$plugin = OIDplus::getDefaultRaAuthPlugin(true);
return $plugin->generate(self::raPepperProcessing($password));
}
/trunk/includes/classes/OIDplusBaseClass.class.php
25,13 → 25,15
 
abstract class OIDplusBaseClass {
 
public function implementsFeature($id) {
 
// Use this function to query the plugin if it supports some specific interface
// Usually, you would use PHP Interfaces. However, the problem with PHP interfaces
// is, that there will be a fatal error if the interface can't be found (e.g. because
// the OIDplus plugin is not installed). So we need an "optional" interface.
 
/**
* Use this function to query the plugin if it supports some specific interface
* Usually, you would use PHP Interfaces. However, the problem with PHP interfaces
* is, that there will be a fatal error if the interface can't be found (e.g. because
* the OIDplus plugin is not installed). So we need an "optional" interface.
* @param string $id
* @return bool
*/
public function implementsFeature(string $id): bool {
return false;
}
 
/trunk/includes/classes/OIDplusBaseConfig.class.php
30,23 → 30,41
 
protected $data = array();
 
public function getValue($name, $default=null) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
*/
public function getValue(string $name, $default=null) {
return $this->exists($name) ? $this->data[$name] : $default;
}
 
public function setValue($name, $value) {
/**
* @param string $name
* @param mixed $value
* @return void
*/
public function setValue(string $name, $value) {
// Note: The value is only set at run time level!
// This function will NOT change the userdata/baseconfig/config.inc.php file!
$this->data[$name] = $value;
}
 
public function delete($name) {
/**
* @param string $name
* @return void
*/
public function delete(string $name) {
// Note: The value is only deleted at run time level!
// This function will NOT change the userdata/baseconfig/config.inc.php file!
unset($this->data[$name]);
}
 
public function exists($name) {
/**
* @param string $name
* @return bool
*/
public function exists(string $name): bool {
return isset($this->data[$name]);
}
 
/trunk/includes/classes/OIDplusCaptchaPlugin.class.php
25,14 → 25,33
 
abstract class OIDplusCaptchaPlugin extends OIDplusPlugin {
 
/**
* @return string
*/
public abstract static function id(): string; // this is the name that is set to the configuration value OIDplus::baseConfig()->getValue('CAPTCHA_PLUGIN') to identify the CAPTCHA plugin
 
/**
* @return bool
*/
public abstract function isVisible(): bool;
 
public abstract function captchaGenerate($header_text=null, $footer_text=null);
/**
* @param string|null $header_text
* @param string|null $footer_text
* @return string
*/
public abstract function captchaGenerate(string $header_text=null, string $footer_text=null): string;
 
public abstract function captchaVerify($params, $fieldname=null);
/**
* @param string[] $params
* @param string|null $fieldname
* @return void
*/
public abstract function captchaVerify(array $params, string $fieldname=null);
 
/**
* @return string
*/
public abstract static function setupHTML(): string;
 
}
/trunk/includes/classes/OIDplusConfig.class.php
41,7 → 41,16
protected $visibleSettings = array();
protected $validateCallbacks = array();
 
public function prepareConfigKey($name, $description, $init_value, $protection, $validateCallback) {
/**
* @param string $name
* @param string $description
* @param string $init_value
* @param int $protection
* @param $validateCallback
* @return void
* @throws OIDplusException
*/
public function prepareConfigKey(string $name, string $description, string $init_value, int $protection, $validateCallback) {
// Check if the protection flag is valid
switch ($protection) {
case OIDplusConfig::PROTECTION_EDITABLE:
111,11 → 120,19
}
}
 
/**
* @return void
* @throws OIDplusException
*/
public function clearCache() {
$this->configTableReadOnce = false;
$this->buildConfigArray();
}
 
/**
* @return void
* @throws OIDplusException
*/
protected function buildConfigArray() {
if ($this->configTableReadOnce) return;
 
134,7 → 151,13
$this->configTableReadOnce = true;
}
 
public function getValue($name, $default=null) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
* @throws OIDplusException
*/
public function getValue(string $name, $default=null) {
// Read all config settings once and write them in array $this->values
$this->buildConfigArray();
 
146,11 → 169,22
}
}
 
public function exists($name) {
/**
* @param string $name
* @return bool
* @throws OIDplusException
*/
public function exists(string $name): bool {
return !is_null($this->getValue($name, null));
}
 
public function setValue($name, $value) {
/**
* @param string $name
* @param mixed $value
* @return void
* @throws OIDplusException
*/
public function setValue(string $name, $value) {
// Read all config settings once and write them in array $this->values
$this->buildConfigArray();
 
172,7 → 206,13
$this->values[$name] = $value;
}
 
public function setValueNoCallback($name, $value) {
/**
* @param string $name
* @param string $value
* @return void
* @throws OIDplusException
*/
public function setValueNoCallback(string $name, string $value) {
// Read all config settings once and write them in array $this->values
$this->buildConfigArray();
 
188,7 → 228,12
$this->values[$name] = $value;
}
 
public function delete($name) {
/**
* @param string $name
* @return void
* @throws OIDplusException
*/
public function delete(string $name) {
if ($this->configTableReadOnce) {
if (isset($this->values[$name])) {
OIDplus::db()->query("delete from ###config where name = ?", array($name));
/trunk/includes/classes/OIDplusCookieUtils.class.php
25,11 → 25,20
 
class OIDplusCookieUtils extends OIDplusBaseClass {
 
public function unsetcookie($name) {
/**
* @param string $name
* @return void
* @throws OIDplusException
*/
public function unsetcookie(string $name) {
$this->setcookie($name, '', time()-9999, true);
}
 
private function getCookieDomain() {
/**
* @return string
* @throws OIDplusException
*/
private function getCookieDomain(): string {
$default_domain = ''; // ini_get('session.cookie_domain');
$domain = OIDplus::baseConfig()->getValue('COOKIE_DOMAIN', $default_domain);
if ($domain === '(auto)') {
43,7 → 52,11
return $domain;
}
 
private function getCookiePath() {
/**
* @return string
* @throws OIDplusException
*/
private function getCookiePath(): string {
$default_path = '/'; // ini_get('session.cookie_path');
$path = OIDplus::baseConfig()->getValue('COOKIE_PATH', $default_path);
if ($path === '(auto)') {
62,7 → 75,17
}
 
// TODO: There are several PHPSESSID cookies set. That's not very nice. We should collect the cookies and then at script ending only send the last definition one time.
public function setcookie($name, $value, $expires=0, $allowJS=false, $samesite=null, $forceInsecure=false) {
/**
* @param string $name
* @param string $value
* @param int $expires
* @param bool $allowJS
* @param string|null $samesite
* @param bool $forceInsecure
* @return void
* @throws OIDplusException
*/
public function setcookie(string $name, string $value, int $expires=0, bool $allowJS=false, /*?string*/ $samesite=null, bool $forceInsecure=false) {
$domain = $this->getCookieDomain();
$path = $this->getCookiePath();
$secure = $forceInsecure ? false : OIDplus::isSSL();
/trunk/includes/classes/OIDplusDatabaseConnection.class.php
29,21 → 29,62
protected /*?string*/ $last_query = null;
protected /*bool*/ $slangDetectionDone = false;
 
protected abstract function doQuery(string $sql, /*?array*/ $prepared_args=null): OIDplusQueryResult;
/**
* @param string $sql
* @param array|null $prepared_args
* @return OIDplusQueryResult
* @throws OIDplusException
*/
protected abstract function doQuery(string $sql, array $prepared_args=null): OIDplusQueryResult;
 
/**
* @return string
*/
public abstract function error(): string;
 
/**
* @return void
*/
public abstract function transaction_begin()/*: void*/;
 
/**
* @return void
*/
public abstract function transaction_commit()/*: void*/;
 
/**
* @return void
*/
public abstract function transaction_rollback()/*: void*/;
 
/**
* @return bool
*/
public abstract function transaction_supported(): bool;
 
/**
* @return int
*/
public abstract function transaction_level(): int;
 
/**
* @return void
*/
protected abstract function doConnect()/*: void*/;
 
/**
* @return void
*/
protected abstract function doDisconnect()/*: void*/;
 
/**
* @return OIDplusDatabasePlugin|null
*/
public function getPlugin()/*: ?OIDplusDatabasePlugin*/ {
$res = null;
$plugins = OIDplus::getDatabasePlugins();
foreach ($plugins as $plugin) {
if (get_class($this) == get_class($plugin::newConnection($this))) {
if (get_class($this) == get_class($plugin::newConnection())) {
return $plugin;
}
}
50,6 → 91,10
return $res;
}
 
/**
* @return int
* @throws OIDplusException
*/
public function insert_id(): int {
// This is the "fallback" variant. If your database provider (e.g. PDO) supports
// a function to detect the last inserted id, please override this
58,7 → 103,12
return $this->getSlang()->insert_id($this);
}
 
public final function getTable(string $sql) {
/**
* @param string $sql
* @return array[]
* @throws OIDplusException
*/
public final function getTable(string $sql): array {
$out = array();
$res = $this->query($sql);
while ($row = $res->fetch_array()) {
67,6 → 117,11
return $out;
}
 
/**
* @param string $sql
* @return mixed|null
* @throws OIDplusException
*/
public final function getScalar(string $sql) {
$res = $this->query($sql);
$row = $res->fetch_array();
73,6 → 128,12
return $row ? reset($row) : null;
}
 
/**
* @param string $sql
* @param array|null $prepared_args
* @return OIDplusQueryResult
* @throws OIDplusException
*/
public final function query(string $sql, /*?array*/ $prepared_args=null): OIDplusQueryResult {
 
$query_logfile = OIDplus::baseConfig()->getValue('QUERY_LOGFILE', '');
100,6 → 161,10
return $this->doQuery($sql, $prepared_args);
}
 
/**
* @return void
* @throws OIDplusException
*/
public final function connect()/*: void*/ {
if ($this->connected) return;
$this->beforeConnect();
110,6 → 175,9
$this->afterConnect();
}
 
/**
* @return void
*/
public final function disconnect()/*: void*/ {
if (!$this->connected) return;
$this->beforeDisconnect();
118,7 → 186,13
$this->afterDisconnect();
}
 
public function natOrder($fieldname, $order='asc'): string {
/**
* @param string $fieldname
* @param string $order
* @return string
* @throws OIDplusException
*/
public function natOrder(string $fieldname, string $order='asc'): string {
$slang = $this->getSlang();
if (!is_null($slang)) {
return $slang->natOrder($fieldname, $order);
133,14 → 207,31
}
}
 
/**
* @return void
*/
protected function beforeDisconnect()/*: void*/ {}
 
/**
* @return void
*/
protected function afterDisconnect()/*: void*/ {}
 
/**
* @return void
*/
protected function beforeConnect()/*: void*/ {}
 
/**
* @return void
*/
protected function afterConnect()/*: void*/ {}
 
/**
* @return void
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
private function afterConnectMandatory()/*: void*/ {
// Check if the config table exists. This is important because the database version is stored in it
$this->initRequireTables(array('config'));
163,7 → 254,13
$this->getSlang();
}
 
private function initRequireTables($tableNames)/*: void*/ {
/**
* @param string[] $tableNames
* @return void
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
private function initRequireTables(array $tableNames)/*: void*/ {
$msgs = array();
foreach ($tableNames as $tableName) {
$prefix = OIDplus::baseConfig()->getValue('TABLENAME_PREFIX', '');
176,7 → 273,11
}
}
 
public function tableExists($tableName): bool {
/**
* @param string $tableName
* @return bool
*/
public function tableExists(string $tableName): bool {
try {
// Attention: This query could interrupt transactions if Rollback-On-Error is enabled
$this->query("select 0 from ".$tableName." where 1=0");
186,14 → 287,25
}
}
 
/**
* @return bool
*/
public function isConnected(): bool {
return $this->connected;
}
 
public function init($html = true)/*: void*/ {
/**
* @param bool $html
* @return void
*/
public function init(bool $html = true)/*: void*/ {
$this->html = $html;
}
 
/**
* @return string
* @throws OIDplusException
*/
public function sqlDate(): string {
$slang = $this->getSlang();
if (!is_null($slang)) {
203,6 → 315,12
}
}
 
/**
* @param bool $mustExist
* @return OIDplusSqlSlangPlugin|null
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
protected function doGetSlang(bool $mustExist=true)/*: ?OIDplusSqlSlangPlugin*/ {
$res = null;
 
234,6 → 352,12
return $res;
}
 
/**
* @param bool $mustExist
* @return OIDplusSqlSlangPlugin|null
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public final function getSlang(bool $mustExist=true)/*: ?OIDplusSqlSlangPlugin*/ {
static /*?OIDplusSqlSlangPlugin*/ $slangCache = null;
 
/trunk/includes/classes/OIDplusDatabasePlugin.class.php
25,10 → 25,19
 
abstract class OIDplusDatabasePlugin extends OIDplusPlugin {
 
/**
* @return string
*/
public abstract static function id(): string; // this is the name that is set to the configuration value OIDplus::baseConfig()->getValue('DATABASE_PLUGIN') to identify the database plugin
 
/**
* @return OIDplusDatabaseConnection
*/
public abstract static function newConnection(): OIDplusDatabaseConnection;
 
/**
* @return string
*/
public abstract static function setupHTML(): string;
 
}
/trunk/includes/classes/OIDplusDesignPlugin.class.php
25,7 → 25,10
 
abstract class OIDplusDesignPlugin extends OIDplusPlugin {
 
function getThemeColor() {
/**
* @return string
*/
function getThemeColor(): string {
return ''; // no theme color
}
 
/trunk/includes/classes/OIDplusGetterSetterInterface.class.php
25,9 → 25,30
 
interface OIDplusGetterSetterInterface {
 
public function getValue($name, $default=null);
public function setValue($name, $value);
public function exists($name);
public function delete($name);
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
*/
public function getValue(string $name, $default=null);
 
/**
* @param string $name
* @param mixed $value
* @return void
*/
public function setValue(string $name, $value);
 
/**
* @param string $name
* @return bool
*/
public function exists(string $name): bool;
 
/**
* @param string $name
* @return void
*/
public function delete(string $name);
 
}
/trunk/includes/classes/OIDplusGui.class.php
25,7 → 25,11
 
class OIDplusGui extends OIDplusBaseClass {
 
public static function generateContentPage($id) {
/**
* @param string $id
* @return array
*/
public static function generateContentPage(string $id): array {
$out = array();
 
$handled = false;
56,7 → 60,12
return $out;
}
 
public static function link($goto, $new_window=false): string {
/**
* @param string $goto
* @param bool $new_window
* @return string
*/
public static function link(string $goto, bool $new_window=false): string {
if ($new_window) {
return 'href="?goto='.urlencode($goto).'" target="_blank"';
} else {
69,9 → 78,15
}
}
 
public static function getLanguageBox($goto, $useJs) {
$out = '';
$out .= '<div id="languageBox">';
/**
* @param string $goto
* @param bool $useJs
* @return string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function getLanguageBox(string $goto, bool $useJs) {
$out = '<div id="languageBox">';
$langbox_entries = array();
$non_default_languages = 0;
foreach (OIDplus::getAllPluginManifests('language') as $pluginManifest) {
83,7 → 98,7
} else {
$class = 'lng_flag picture_ghost';
}
$add = (!is_null($goto)) ? '&amp;goto='.urlencode($goto) : '';
$add = ($goto != '') ? '&amp;goto='.urlencode($goto) : '';
 
$dirs = glob(OIDplus::localpath().'plugins/'.'*'.'/language/'.$code.'/');
 
101,7 → 116,12
return $out;
}
 
public static function html_exception_handler($exception) {
/**
* @param \Throwable $exception
* @return void
* @throws OIDplusException
*/
public static function html_exception_handler(\Throwable $exception) {
if ($exception instanceof OIDplusConfigInitializationException) {
echo '<!DOCTYPE HTML>';
echo '<html><head><title>'.htmlentities(_L('OIDplus initialization error')).'</title></head><body>';
125,9 → 145,12
}
}
 
private static function getExceptionTechInfo($exception) {
$out = '';
$out .= '<p><b>'.htmlentities(_L('Technical information about the problem')).':</b></p>';
/**
* @param \Throwable $exception
* @return string
*/
private static function getExceptionTechInfo(\Throwable $exception) {
$out = '<p><b>'.htmlentities(_L('Technical information about the problem')).':</b></p>';
$out .= '<pre>';
$out .= get_class($exception)."\n";
$out .= _L('at file %1 (line %2)',$exception->getFile(),"".$exception->getLine())."\n\n";
137,33 → 160,62
return $out;
}
 
/**
* @return string
*/
public function tabBarStart() {
return '<ul class="nav nav-tabs" id="myTab" role="tablist">';
}
 
/**
* @return string
*/
public function tabBarEnd() {
return '</ul>';
}
 
public function tabBarElement($id, $title, $active) {
/**
* @param string $id
* @param string $title
* @param bool $active
* @return string
*/
public function tabBarElement(string $id, string $title, bool $active) {
// data-bs-toggle is for Bootstrap 5
// data-toggle is for Bootstrap 4 (InternetExplorer compatibility)
return '<li class="nav-item"><a class="nav-link'.($active ? ' active' : '').'" id="'.$id.'-tab" data-bs-toggle="tab" data-toggle="tab" href="#'.$id.'" role="tab" aria-controls="'.$id.'" aria-selected="'.($active ? 'true' : 'false').'">'.$title.'</a></li>';
}
 
/**
* @return string
*/
public function tabContentStart() {
return '<div class="tab-content" id="myTabContent">';
}
 
/**
* @return string
*/
public function tabContentEnd() {
return '</div>';
}
 
public function tabContentPage($id, $content, $active) {
/**
* @param string $id
* @param string $content
* @param bool $active
* @return string
*/
public function tabContentPage(string $id, string $content, bool $active) {
return '<div class="tab-pane fade'.($active ? ' show active' : '').'" id="'.$id.'" role="tabpanel" aria-labelledby="'.$id.'-tab">'.$content.'</div>';
}
 
public function combine_systemtitle_and_pagetitle($systemtitle, $pagetitle) {
/**
* @param string $systemtitle
* @param string $pagetitle
* @return string
*/
public function combine_systemtitle_and_pagetitle(string $systemtitle, string $pagetitle) {
// Please also change the function in oidplus_base.js
if ($systemtitle == $pagetitle) {
return $systemtitle;
172,7 → 224,12
}
}
 
private function getCommonHeadElems($title) {
/**
* @param string $title
* @return string[]
* @throws OIDplusException
*/
private function getCommonHeadElems(string $title): array {
// Get theme color (color of title bar)
$design_plugin = OIDplus::getActiveDesignPlugin();
$theme_color = is_null($design_plugin) ? '' : $design_plugin->getThemeColor();
198,11 → 255,22
return $head_elems;
}
 
public function showMainPage($page_title_1, $page_title_2, $static_icon, $static_content, $extra_head_tags=array(), $static_node_id='') {
/**
* @param string $page_title_1
* @param string $page_title_2
* @param string $static_icon
* @param string $static_content
* @param array $extra_head_tags
* @param string $static_node_id
* @return string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public function showMainPage(string $page_title_1, string $page_title_2, string $static_icon, string $static_content, array $extra_head_tags=array(), string $static_node_id='') {
$head_elems = $this->getCommonHeadElems($page_title_1);
$head_elems = array_merge($head_elems, $extra_head_tags);
 
$plugins = OIDplus::getPagePlugins();
$plugins = OIDplus::getAllPlugins();
foreach ($plugins as $plugin) {
$plugin->htmlHeaderUpdate($head_elems);
}
274,7 → 342,7
 
# ---
 
$plugins = OIDplus::getPagePlugins();
$plugins = OIDplus::getAllPlugins();
foreach ($plugins as $plugin) {
$plugin->htmlPostprocess($out);
}
282,7 → 350,17
return $out;
}
 
public function showSimplePage($page_title_1, $page_title_2, $static_icon, $static_content, $extra_head_tags=array()) {
/**
* @param string $page_title_1
* @param string $page_title_2
* @param string $static_icon
* @param string $static_content
* @param string[] $extra_head_tags
* @return string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public function showSimplePage(string $page_title_1, string $page_title_2, string $static_icon, string $static_content, array $extra_head_tags=array()) {
$head_elems = $this->getCommonHeadElems($page_title_1);
$head_elems = array_merge($head_elems, $extra_head_tags);
 
320,7 → 398,7
 
$out .= '</div>';
 
$out .= OIDplus::gui()->getLanguageBox(null, true);
$out .= OIDplus::gui()->getLanguageBox('', true);
 
$out .= '</div>';
 
/trunk/includes/classes/OIDplusLanguagePlugin.class.php
25,7 → 25,10
 
abstract class OIDplusLanguagePlugin extends OIDplusPlugin {
 
public function getLanguageCode() {
/**
* @return string
*/
public function getLanguageCode(): string {
return $this->getManifest()->getLanguageCode();
}
 
/trunk/includes/classes/OIDplusLogger.class.php
25,29 → 25,32
 
class OIDplusLogger extends OIDplusBaseClass {
 
private static function split_maskcodes($maskcodes) {
// This function splits a mask code containing multiple components
// (delimited by '+' or '/') in single components
// It takes care that '+' and '/' inside brackets won't be used to split the codes
// Also, brackets can be escaped.
// The severity block (optional, must be standing in front of a component)
// is handled too. Inside the severity block, you may only use '/' to split components.
// The severity block will be implicitly repeated from the previous components if a component
// does not feature one.
//
// "[S]AAA(BBB)+CCC(DDD)" ==> array(
// array(array("S"),"AAA(BBB)"),
// array(array("S"),"CCC(DDD)")
// )
// "[S]AAA(B+BB)+CCC(DDD)" ==> array(
// array(array("S"),"AAA(B+BB)"),
// array(array("S"),"CCC(DDD)")
// )
// "[S]AAA(B\)BB)+CCC(DDD)" ==> array(
// array(array("S"),"AAA(B\)BB)"),
// array(array("S"),"CCC(DDD)")
// )
 
/**
* This function splits a mask code containing multiple components
* (delimited by '+' or '/') in single components
* It takes care that '+' and '/' inside brackets won't be used to split the codes
* Also, brackets can be escaped.
* The severity block (optional, must be standing in front of a component)
* is handled too. Inside the severity block, you may only use '/' to split components.
* The severity block will be implicitly repeated from the previous components if a component
* does not feature one.
*
* "[S]AAA(BBB)+CCC(DDD)" ==> array(
* array(array("S"),"AAA(BBB)"),
* array(array("S"),"CCC(DDD)")
* )
* "[S]AAA(B+BB)+CCC(DDD)" ==> array(
* array(array("S"),"AAA(B+BB)"),
* array(array("S"),"CCC(DDD)")
* )
* "[S]AAA(B\)BB)+CCC(DDD)" ==> array(
* array(array("S"),"AAA(B\)BB)"),
* array(array("S"),"CCC(DDD)")
* )
* @param string $maskcodes
* @return array|false
*/
private static function split_maskcodes(string $maskcodes) {
$out = array();
$sevs = array(); // Note: The severity block will repeat for the next components if not changed explicitly
 
170,7 → 173,11
 
private static $missing_plugin_queue = array();
 
public static function reLogMissing() {
/**
* @return bool
* @throws OIDplusException
*/
public static function reLogMissing(): bool {
while (count(self::$missing_plugin_queue) > 0) {
$item = self::$missing_plugin_queue[0];
if (!self::log_internal($item[0], $item[1], false)) return false;
179,12 → 186,25
return true;
}
 
public static function log($maskcodes, $event) {
/**
* @param string $maskcodes
* @param string $event
* @return bool
* @throws OIDplusException
*/
public static function log(string $maskcodes, string $event): bool {
self::reLogMissing(); // try to re-log failed requests
return self::log_internal($maskcodes, $event, true);
}
 
private static function log_internal($maskcodes, $event, $allow_delayed_log) {
/**
* @param string $maskcodes
* @param string $event
* @param bool $allow_delayed_log
* @return bool
* @throws OIDplusException
*/
private static function log_internal(string $maskcodes, string $event, bool $allow_delayed_log): bool {
$loggerPlugins = OIDplus::getLoggerPlugins();
if (count($loggerPlugins) == 0) {
// The plugin might not be initialized in OIDplus::init()
205,7 → 225,7
// so, instead of logging into 3 logbooks separately,
// you would create a mask code that tells the system
// to put the message into the logbooks of person X,
// house A and house B.
// house A, and house B.
 
$users = array();
$objects = array();
/trunk/includes/classes/OIDplusLoggerPlugin.class.php
25,7 → 25,18
 
abstract class OIDplusLoggerPlugin extends OIDplusPlugin {
 
public abstract static function log($event, $users, $objects)/*: bool*/;
public abstract static function available(&$reason)/*: bool*/;
/**
* @param string $event
* @param array<int,string>[] $users Array of "Severity => username"
* @param array<int,string>[] $objects Array of "Severity => objectname"
* @return bool
*/
public abstract static function log(string $event, array $users, array $objects): bool;
 
/**
* @param string $reason
* @return bool
*/
public abstract static function available(string &$reason): bool;
 
}
/trunk/includes/classes/OIDplusMailUtils.class.php
25,11 → 25,21
 
class OIDplusMailUtils extends OIDplusBaseClass {
 
public static function validMailAddress($email) {
/**
* @param string $email
* @return bool
*/
public static function validMailAddress(string $email): bool {
return !empty(filter_var($email, FILTER_VALIDATE_EMAIL));
}
 
public static function secureEmailAddress($email, $linktext, $level=1) {
/**
* @param string $email
* @param string $linktext
* @param int $level
* @return string|null
*/
public static function secureEmailAddress(string $email, string $linktext, int $level=1)/*: ?string*/ {
 
// see http://www.spamspan.de/
 
137,7 → 147,17
*/
}
 
public static function sendMail($to, $title, $msg, $cc='', $bcc='') {
/**
* @param string $to
* @param string $title
* @param string $msg
* @param string $cc
* @param string $bcc
* @return void
* @throws OIDplusException
* @throws OIDplusMailException
*/
public static function sendMail(string $to, string $title, string $msg, string $cc='', string $bcc='') {
$h = new \SecureMailer();
 
// DM 14.04.2022: Added Reply-To, because some servers might change the 'From' attribute (Anti-Spoof?)
/trunk/includes/classes/OIDplusMenuUtils.class.php
25,7 → 25,12
 
class OIDplusMenuUtils extends OIDplusBaseClass {
 
public static function nonjs_menu() {
/**
* @return string
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function nonjs_menu(): string {
$json = array();
 
$static_node_id = isset($_REQUEST['goto']) ? $_REQUEST['goto'] : 'oidplus:system';
56,12 → 61,15
return $out;
}
 
// req_id comes from jsTree via AJAX
// req_goto comes from the user (GET argument)
public static function json_tree($req_id, $req_goto) {
/**
* @param string $req_id comes from jsTree via AJAX
* @param string $req_goto comes from the user (GET argument)
* @return string[]
*/
public static function json_tree(string $req_id, string $req_goto): array {
$json = array();
 
if (!isset($req_id) || ($req_id == '#')) {
if ($req_id === '#') {
foreach (OIDplus::getPagePlugins() as $plugin) {
// Note: The system (OIDplusMenuUtils) does only show the menu of
// publicPage plugins. Menu entries for RAs and Admins are
74,13 → 82,16
$json = self::tree_populate($req_id);
}
 
self::addHrefIfRequired($json);
if (is_array($json)) self::addHrefIfRequired($json);
 
return $json;
}
 
protected static function addHrefIfRequired(&$json) {
if (!is_array($json)) return;
/**
* @param array $json
* @return void
*/
protected static function addHrefIfRequired(array &$json) {
foreach ($json as &$item) {
if (isset($item['id'])) {
if (!isset($item['conditionalselect']) || ($item['conditionalselect'] != 'false')) {
93,7 → 104,7
}
 
if (isset($item['children'])) {
self::addHrefIfRequired($item['children']);
if (is_array($item['children'])) self::addHrefIfRequired($item['children']);
}
}
}
/trunk/includes/classes/OIDplusObject.class.php
26,7 → 26,12
abstract class OIDplusObject extends OIDplusBaseClass {
const UUID_NAMEBASED_NS_OidPlusMisc = 'ad1654e6-7e15-11e4-9ef6-78e3b5fc7f22';
 
public static function parse($node_id) { // please overwrite this function!
/**
* Please overwrite this function!
* @param string $node_id
* @return OIDplusObject|null
*/
public static function parse(string $node_id)/*: ?OIDplusObject*/ {
foreach (OIDplus::getEnabledObjectTypes() as $ot) {
try {
$good = false;
45,7 → 50,11
return null;
}
 
public function /*OIDplusAltId[]*/ getAltIds() {
/**
* @return OIDplusAltId[]
* @throws OIDplusException
*/
public function getAltIds(): array {
if ($this->isRoot()) return array();
 
$ids = array();
82,7 → 91,7
// ... but not for OIDs below oid:1.3.6.1.4.1.37476.30.9, because these are the definition of these Information Object AIDs (which will be decoded in the OID object type plugin)
if (($this->ns() != 'aid') && !str_starts_with($this->nodeId(true), 'oid:1.3.6.1.4.1.37476.30.9.')) {
$sid = OIDplus::getSystemId(false);
if (!empty($sid)) {
if ($sid !== false) {
$ns_oid = $this->getPlugin()->getManifest()->getOid();
if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
// Official ViaThinkSoft object type plugins
95,7 → 104,7
$hash_payload = $ns_oid.':'.$this->nodeId(false);
}
 
$sid_hex = strtoupper(str_pad(dechex($sid),8,'0',STR_PAD_LEFT));
$sid_hex = strtoupper(str_pad(dechex((int)$sid),8,'0',STR_PAD_LEFT));
$obj_hex = strtoupper(str_pad(dechex(smallhash($hash_payload)),8,'0',STR_PAD_LEFT));
$aid = 'D276000186B20005'.$sid_hex.$obj_hex;
$ids[] = new OIDplusAltId('aid', $aid, _L('OIDplus Information Object Application Identifier (ISO/IEC 7816)'), ' ('._L('No PIX allowed').')');
105,56 → 114,114
return $ids;
}
 
public abstract static function objectTypeTitle();
/**
* @return string
*/
public abstract static function objectTypeTitle(): string;
 
public abstract static function objectTypeTitleShort();
/**
* @return string
*/
public abstract static function objectTypeTitleShort(): string;
 
/**
* @return OIDplusObjectTypePlugin|null
*/
public function getPlugin()/*: ?OIDplusObjectTypePlugin */ {
$res = null;
$plugins = OIDplus::getObjectTypePlugins();
foreach ($plugins as $plugin) {
if (get_class($this) == $plugin::getObjectTypeClassName($this)) {
if (get_class($this) == $plugin::getObjectTypeClassName()) {
return $plugin;
}
}
return $res;
return null;
}
 
public abstract static function ns();
/**
* @return string
*/
public abstract static function ns(): string;
 
public abstract static function root();
/**
* @return string
*/
public abstract static function root(): string;
 
public abstract function isRoot();
/**
* @return bool
*/
public abstract function isRoot(): bool;
 
public abstract function nodeId($with_ns=true);
/**
* @param bool $with_ns
* @return string
*/
public abstract function nodeId(bool $with_ns=true): string;
 
public abstract function addString($str);
/**
* @param string $str
* @return string mixed
* @throws OIDplusException
*/
public abstract function addString(string $str): string;
 
public abstract function crudShowId(OIDplusObject $parent);
/**
* @param OIDplusObject $parent
* @return string
*/
public abstract function crudShowId(OIDplusObject $parent): string;
 
public function crudInsertPrefix() {
/**
* @return string
*/
public function crudInsertPrefix(): string {
return '';
}
 
public function crudInsertSuffix() {
/**
* @return string
*/
public function crudInsertSuffix(): string {
return '';
}
 
public abstract function jsTreeNodeName(OIDplusObject $parent = null);
/**
* @param OIDplusObject|null $parent
* @return string
*/
public abstract function jsTreeNodeName(OIDplusObject $parent = null): string;
 
public abstract function defaultTitle();
/**
* @return string
*/
public abstract function defaultTitle(): string;
 
public abstract function isLeafNode();
/**
* @return bool
*/
public abstract function isLeafNode(): bool;
 
public abstract function getContentPage(&$title, &$content, &$icon);
/**
* @param string $title
* @param string $content
* @param string $icon
* @return void
*/
public abstract function getContentPage(string &$title, string &$content, string &$icon);
 
public static function getRaRoots($ra_email=null) {
if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
/**
* @param OIDplusRA|string|null $ra
* @return array
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public static function getRaRoots($ra=null) : array{
if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
 
$out = array();
 
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
if (!$ra_email) {
if (!$ra) {
$res = OIDplus::db()->query("select oChild.id as id, oChild.ra_email as child_mail, oParent.ra_email as parent_mail from ###objects as oChild ".
"left join ###objects as oParent on oChild.parent = oParent.id ".
"order by ".OIDplus::db()->natOrder('oChild.id'));
170,7 → 237,7
"where (".OIDplus::db()->getSlang()->isNullFunction('oParent.ra_email',"''")." <> ? and ".
OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) or ".
" (oParent.ra_email is null and ".OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) ".
"order by ".OIDplus::db()->natOrder('oChild.id'), array($ra_email, $ra_email, $ra_email));
"order by ".OIDplus::db()->natOrder('oChild.id'), array($ra, $ra, $ra));
while ($row = $res->fetch_array()) {
$x = self::parse($row['id']); // can be FALSE if namespace was disabled
if ($x) $out[] = $x;
177,11 → 244,11
}
}
} else {
if (!$ra_email) {
if (!$ra) {
$ra_mails_to_check = OIDplus::authUtils()->loggedInRaList();
if (count($ra_mails_to_check) == 0) return $out;
} else {
$ra_mails_to_check = array($ra_email);
$ra_mails_to_check = array($ra);
}
 
self::buildObjectInformationCache();
210,7 → 277,11
return $out;
}
 
public static function getAllNonConfidential() {
/**
* @return array
* @throws OIDplusException
*/
public static function getAllNonConfidential(): array {
$out = array();
 
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
239,7 → 310,11
return $out;
}
 
public function isConfidential() {
/**
* @return bool
* @throws OIDplusException
*/
public function isConfidential(): bool {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
//static $confidential_cache = array();
$curid = $this->nodeId();
277,7 → 352,12
}
}
 
public function isChildOf(OIDplusObject $obj) {
/**
* @param OIDplusObject $obj
* @return bool
* @throws OIDplusException
*/
public function isChildOf(OIDplusObject $obj): bool {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$curid = $this->nodeId();
while (($res = OIDplus::db()->query("select parent from ###objects where id = ?", array($curid)))->any()) {
298,7 → 378,11
}
}
 
public function getChildren() {
/**
* @return array
* @throws OIDplusException
*/
public function getChildren(): array {
$out = array();
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select id from ###objects where parent = ?", array($this->nodeId()));
322,18 → 406,28
return $out;
}
 
public function getRa() {
/**
* @return OIDplusRA
* @throws OIDplusException
*/
public function getRa(): OIDplusRA {
return new OIDplusRA($this->getRaMail());
}
 
public function userHasReadRights($ra_email=null) {
if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
/**
* @param OIDplusRA|string|null $ra
* @return bool
* @throws OIDplusConfigInitializationException
* @throws OIDplusException
*/
public function userHasReadRights($ra=null): bool {
if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
 
// If it is not confidential, everybody can read/see it.
// Note: This also checks if superior OIDs are confidential.
if (!$this->isConfidential()) return true;
 
if (!$ra_email) {
if (!$ra) {
// Admin may do everything
if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
 
341,13 → 435,13
if (OIDplus::authUtils()->isRaLoggedIn($this->getRaMail())) return true;
} else {
// If this OID belongs to the requested RA, then they may see it.
if ($this->getRaMail() == $ra_email) return true;
if ($this->getRaMail() == $ra) return true;
}
 
// If someone has rights to an object below our confidential node,
// we let him see the confidential node,
// Otherwise he could not browse through to his own node.
$roots = $this->getRaRoots($ra_email);
$roots = $this->getRaRoots($ra);
foreach ($roots as $root) {
if ($root->isChildOf($this)) return true;
}
355,7 → 449,12
return false;
}
 
public function getIcon($row=null) {
/**
* @param array|null $row
* @return string|null
* @throws OIDplusException
*/
public function getIcon(array $row=null) {
$namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
 
if (is_null($row)) {
383,7 → 482,12
return $icon;
}
 
public static function exists(string $id) {
/**
* @param string $id
* @return bool
* @throws OIDplusException
*/
public static function exists(string $id): bool {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select id from ###objects where id = ?", array($id));
return $res->any();
393,8 → 497,12
}
}
 
// Get parent gives the next possible parent which is EXISTING in OIDplus
// It does not give the immediate parent
/**
* Get parent gives the next possible parent which is EXISTING in OIDplus
* It does not give the immediate parent
* @return OIDplusObject|null
* @throws OIDplusException
*/
public function getParent()/*: ?OIDplusObject*/ {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select parent from ###objects where id = ?", array($this->nodeId()));
422,11 → 530,15
$prev = $cur;
$cur = $cur->one_up();
if (!$cur) return null;
} while ($prev != $cur);
} while ($prev !== $cur);
}
return null;
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getRaMail() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select ra_email from ###objects where id = ?", array($this->nodeId()));
442,6 → 554,10
}
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getTitle() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select title from ###objects where id = ?", array($this->nodeId()));
457,6 → 573,10
}
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getDescription() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select description from ###objects where id = ?", array($this->nodeId()));
472,6 → 592,10
}
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getComment() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select comment from ###objects where id = ?", array($this->nodeId()));
487,6 → 611,10
}
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getCreatedTime() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select created from ###objects where id = ?", array($this->nodeId()));
502,6 → 630,10
}
}
 
/**
* @return false|string|null
* @throws OIDplusException
*/
public function getUpdatedTime() {
if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
$res = OIDplus::db()->query("select updated from ###objects where id = ?", array($this->nodeId()));
517,34 → 649,52
}
}
 
public function userHasParentalWriteRights($ra_email=null) {
if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
/**
* @param OIDplusRA|string|null $ra
* @return bool
* @throws OIDplusException
*/
public function userHasParentalWriteRights($ra=null) {
if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
 
if (!$ra_email) {
if (!$ra) {
if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
}
 
$objParent = $this->getParent();
if (!$objParent) return false;
return $objParent->userHasWriteRights($ra_email);
return $objParent->userHasWriteRights($ra);
}
 
public function userHasWriteRights($ra_email=null) {
if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
/**
* @param OIDplusRA|string|null $ra
* @return bool
* @throws OIDplusException
*/
public function userHasWriteRights($ra=null): bool {
if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
 
if (!$ra_email) {
if (!$ra) {
if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
return OIDplus::authUtils()->isRaLoggedIn($this->getRaMail());
} else {
return $this->getRaMail() == $ra_email;
return $this->getRaMail() == $ra;
}
}
 
public function distance($to) {
/**
* @param string|OIDplusObject $to
* @return int|null
*/
public function distance($to)/*: ?int*/ {
return null; // not implemented
}
 
public function equals($obj) {
/**
* @param OIDplusObject $obj
* @return bool
*/
public function equals(OIDplusObject $obj): bool {
if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
if (!($obj instanceof $this)) return false;
 
554,6 → 704,11
return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
}
 
/**
* @param string $id
* @return OIDplusObject|false
* @throws OIDplusException
*/
public static function findFitting(string $id) {
$obj = OIDplusObject::parse($id);
if (!$obj) return false; // e.g. if ObjectType plugin is disabled
577,7 → 732,10
}
}
 
public function one_up() {
/**
* @return OIDplusObject|null
*/
public function one_up()/*: ?OIDplusObject*/ {
return null; // not implemented
}
 
585,6 → 743,9
 
protected static $object_info_cache = null;
 
/**
* @return void
*/
public static function resetObjectInformationCache() {
self::$object_info_cache = null;
}
599,6 → 760,10
const CACHE_UPDATED = 'updated';
const CACHE_COMMENT = 'comment';
 
/**
* @return void
* @throws OIDplusException
*/
private static function buildObjectInformationCache() {
if (is_null(self::$object_info_cache)) {
self::$object_info_cache = array();
609,15 → 774,23
}
}
 
// override this function if you want your object type to save
// attachments in directories with easy names.
// Take care that your custom directory name will not allow jailbreaks (../) !
public function getDirectoryName() {
/**
* override this function if you want your object type to save
* attachments in directories with easy names.
* Take care that your custom directory name will not allow jailbreaks (../) !
* @return string
* @throws OIDplusException
*/
public function getDirectoryName(): string {
if ($this->isRoot()) return $this->ns();
return $this->getLegacyDirectoryName();
}
 
public final function getLegacyDirectoryName() {
/**
* @return string
* @throws OIDplusException
*/
public final function getLegacyDirectoryName(): string {
if ($this::ns() == 'oid') {
$oid = $this->nodeId(false);
} else {
641,7 → 814,11
}
}
 
public static function treeIconFilename($mode) {
/**
* @param string $mode
* @return string
*/
public static function treeIconFilename(string $mode): string {
// for backwards-compatibility with older plugins
return 'img/treeicon_'.$mode.'.png';
}
/trunk/includes/classes/OIDplusObjectTypePlugin.class.php
25,9 → 25,17
 
abstract class OIDplusObjectTypePlugin extends OIDplusPlugin {
 
public static abstract function getObjectTypeClassName();
/**
* @return string
*/
public static abstract function getObjectTypeClassName(): string;
 
public static function prefilterQuery($static_node_id, $throw_exception) {
/**
* @param string $static_node_id
* @param bool $throw_exception
* @return string
*/
public static function prefilterQuery(string $static_node_id, bool $throw_exception): string {
return $static_node_id;
}
 
/trunk/includes/classes/OIDplusPagePlugin.class.php
24,18 → 24,32
// phpcs:enable PSR1.Files.SideEffects
 
abstract class OIDplusPagePlugin extends OIDplusPlugin {
public function htmlHeaderUpdate(&$head_elems) {}
public function htmlPostprocess(&$html) {}
public function action($actionID, $params) {}
public function gui($id, &$out, &$handled) {}
public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {}
public function tree_search($request) {}
public function handle404($request) { return false; }
 
public function csrfUnlock($actionID) {
// override this method if you want that your plugin
// can accept ajax.php requests from outside, without CSRF check
/**
* @param string $id
* @param array $out
* @param bool $handled
* @return void
*/
public function gui(string $id, array &$out, bool &$handled) {}
 
/**
* @param array $json
* @param string|null $ra_email
* @param bool $nonjs
* @param string $req_goto To which node should be auto-expanded to? (Special values: ""=no auto expand. "*"=expand all.)
* @return bool
*/
public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool {
return false;
}
 
/**
* @param string $request
* @return array|false
*/
public function tree_search(string $request) {
return false;
}
 
}
/trunk/includes/classes/OIDplusPagePluginPublic.class.php
25,6 → 25,10
 
abstract class OIDplusPagePluginPublic extends OIDplusPagePlugin {
 
public function publicSitemap(&$out) {}
/**
* @param string[] $out
* @return void
*/
public function publicSitemap(array &$out) {}
 
}
/trunk/includes/classes/OIDplusPlugin.class.php
25,13 → 25,19
 
abstract class OIDplusPlugin extends OIDplusBaseClass {
 
public final function getPluginDirectory() {
/**
* @return string
*/
public final function getPluginDirectory(): string {
$reflector = new \ReflectionClass(get_called_class());
$path = dirname($reflector->getFilename());
return $path;
}
 
public function getManifest() {
/**
* @return OIDplusPluginManifest|null
*/
public function getManifest()/*: ?OIDplusPluginManifest*/ {
$dir = $this->getPluginDirectory();
$ini = $dir.DIRECTORY_SEPARATOR.'manifest.xml';
$manifest = new OIDplusPluginManifest();
38,8 → 44,56
return $manifest->loadManifest($ini) ? $manifest : null;
}
 
public function init($html=true) {}
/**
* @param bool $html
* @return void
*/
public function init(bool $html=true) {}
 
public function httpHeaderCheck(&$http_headers) {}
/**
* @param string $actionID
* @param array $params
* @return array
* @throws OIDplusException
*/
public function action(string $actionID, array $params): array {
throw new OIDplusException(_L('Invalid action ID'));
}
 
/**
* override this method if you want that your plugin
* can accept ajax.php requests from outside, without CSRF check
* @param string $actionID
* @return bool
*/
public function csrfUnlock(string $actionID): bool {
return false;
}
 
/**
* @param string $request
* @return bool Handled?
*/
public function handle404(string $request): bool {
return false;
}
 
/**
* @param string $html
* @return void
*/
public function htmlPostprocess(string &$html) {}
 
/**
* @param array $head_elems
* @return void
*/
public function htmlHeaderUpdate(array &$head_elems) {}
 
/**
* @param string[] $http_headers
* @return void
*/
public function httpHeaderCheck(array &$http_headers) {}
 
}
/trunk/includes/classes/OIDplusPluginManifest.class.php
54,22 → 54,37
private $languageFlag = '';
private $languageMessages = '';
 
/**
* @return string
*/
public function getTypeClass(): string {
return $this->type;
}
 
/**
* @return string
*/
public function getName(): string {
return $this->name;
}
 
/**
* @return string
*/
public function getAuthor(): string {
return $this->author;
}
 
/**
* @return string
*/
public function getLicense(): string {
return $this->license;
}
 
/**
* @return string
*/
public function getVersion(): string {
if (str_starts_with($this->oid,'1.3.6.1.4.1.37476.2.5.2.4.') && ($this->version == '')) {
$sysver = OIDplus::getVersion();
85,20 → 100,29
}
}
 
/**
* @return string
*/
public function getHtmlDescription(): string {
return $this->htmlDescription;
}
 
/**
* @return string
*/
public function getOid(): string {
return $this->oid;
}
 
/**
* @return string
*/
public function getPhpMainClass(): string {
return $this->phpMainClass;
}
 
/**
* @return array<string>
* @return string[]
*/
public function getCSSFiles(): array {
return $this->cssFiles;
105,7 → 129,7
}
 
/**
* @return array<string>
* @return string[]
*/
public function getJSFiles(): array {
return $this->jsFiles;
112,7 → 136,7
}
 
/**
* @return array<string>
* @return string[]
*/
public function getCSSFilesSetup(): array {
return $this->cssFilesSetup;
119,28 → 143,43
}
 
/**
* @return array<string>
* @return string[]
*/
public function getJSFilesSetup(): array {
return $this->jsFilesSetup;
}
 
/**
* @return string
*/
public function getManifestFile(): string {
return $this->manifestFile;
}
 
/**
* @return \SimpleXMLElement
*/
public function getRawXml(): \SimpleXMLElement {
return $this->rawXML;
}
 
/**
* @return string
*/
public function getLanguageCode(): string {
return $this->languageCode;
}
 
/**
* @return string
*/
public function getLanguageFlag(): string {
return $this->languageFlag;
}
 
/**
* @return string
*/
public function getLanguageMessages(): string {
return $this->languageMessages;
}
148,7 → 187,8
/**
* Lists all files referenced by the manifest files
* Not included are other files like menu images or other PHP classes
* @return array<string>
* @return string[]
* @throws \ReflectionException
*/
public function getManifestLinkedFiles(): array {
$files = array_merge(
163,10 → 203,14
return $files;
}
 
public function loadManifest($filename) {
/**
* @param string $filename
* @return bool
*/
public function loadManifest(string $filename) {
if (!file_exists($filename)) return false;
$xmldata = @simplexml_load_file($filename);
if ($xmldata === false) return false;
if ($xmldata === false) return false; // TODO: rather throw an Exception and let the method return void only
 
$this->manifestFile = $filename;
$this->rawXML = $xmldata;
195,8 → 239,10
$this->cssFiles[] = $file;
}
 
// The following functionalities are only available for page plugins
// The following functionalities are only available for page plugins, captcha plugins, and object type plugins
// XML Schema urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1
// XML Schema urn:oid:1.3.6.1.4.1.37476.2.5.2.5.10.1
// XML Schema urn:oid:1.3.6.1.4.1.37476.2.5.2.5.12.1
foreach ((array)$xmldata->js->file as $js_file) {
$file = dirname($filename).DIRECTORY_SEPARATOR.$js_file;
//if (!file_exists($file)) continue;
/trunk/includes/classes/OIDplusQueryResult.class.php
24,16 → 24,35
// phpcs:enable PSR1.Files.SideEffects
 
abstract class OIDplusQueryResult extends OIDplusBaseClass {
 
/**
* @return bool
*/
abstract public function containsResultSet(): bool;
 
/**
* @return int
*/
abstract public function num_rows(): int;
 
/**
* @return array|null
*/
abstract public function fetch_array()/*: ?array*/;
 
/**
* @return object|null
*/
abstract public function fetch_object()/*: ?object*/;
 
/**
* The any() function returns true if there is at least one
* row in the section. By default, num_rows() will be used.
* Plugins can override this method if they have a possibility
* of making this functionality more efficient.
* @return bool
*/
public function any(): bool {
// The any() function returns true if there is at least one
// row in the section. By default, num_rows() will be used.
// Plugins can override this method if they have a possibility
// of making this functionality more efficient.
return $this->num_rows() > 0;
}
}
/trunk/includes/classes/OIDplusRA.class.php
26,20 → 26,34
class OIDplusRA extends OIDplusBaseClass {
private $email = null;
 
public function __construct($email) {
/**
* @param string $email
*/
public function __construct(string $email) {
$this->email = $email;
}
 
public function raEmail() {
/**
* @return string
*/
public function raEmail(): string {
return $this->email;
}
 
public function existing() {
/**
* @return bool
* @throws OIDplusException
*/
public function existing(): bool {
$res = OIDplus::db()->query("select email from ###ra where email = ?", array($this->email));
return ($res->any());
}
 
public function raName() {
/**
* @return string
* @throws OIDplusException
*/
public function raName(): string {
$res = OIDplus::db()->query("select ra_name from ###ra where email = ?", array($this->email));
if (!$res->any()) return _L('(RA not in database)');
$row = $res->fetch_array();
46,7 → 60,11
return $row['ra_name'];
}
 
public static function getAllRAs() {
/**
* @return OIDplusRA[]
* @throws OIDplusException
*/
public static function getAllRAs(): array {
$out = array();
$res = OIDplus::db()->query("select email from ###ra");
while ($row = $res->fetch_array()) {
55,17 → 73,32
return $out;
}
 
public function change_password($new_password) {
/**
* @param string $new_password
* @return void
* @throws OIDplusException
*/
public function change_password(string $new_password) {
$authInfo = OIDplus::authUtils()->raGeneratePassword($new_password);
$calc_authkey = $authInfo->getAuthKey();
OIDplus::db()->query("update ###ra set authkey=? where email = ?", array($calc_authkey, $this->email));
}
 
public function change_email($new_email) {
/**
* @param string $new_email
* @return void
* @throws OIDplusException
*/
public function change_email(string $new_email) {
OIDplus::db()->query("update ###ra set email = ? where email = ?", array($new_email, $this->email));
}
 
public function register_ra($new_password) {
/**
* @param string|null $new_password
* @return void
* @throws OIDplusException
*/
public function register_ra(/*?string*/ $new_password) {
if (is_null($new_password)) {
// Invalid password (used for LDAP/OAuth)
$calc_authkey = '';
77,6 → 110,10
OIDplus::db()->query("insert into ###ra (authkey, email, registered, ra_name, personal_name, organization, office, street, zip_town, country, phone, mobile, fax) values (?, ?, ".OIDplus::db()->sqlDate().", ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", array($calc_authkey, $this->email, "", "", "", "", "", "", "", "", "", ""));
}
 
/**
* @return OIDplusRAAuthInfo|null
* @throws OIDplusException
*/
public function getAuthInfo()/*: ?OIDplusRAAuthInfo*/ {
$ra_res = OIDplus::db()->query("select authkey from ###ra where email = ?", array($this->email));
if (!$ra_res->any()) return null; // User not found
85,19 → 122,37
return new OIDplusRAAuthInfo($ra_row['authkey']);
}
 
public function checkPassword($password) {
/**
* @param string $password
* @return bool
* @throws OIDplusException
*/
public function checkPassword(string $password): bool {
return OIDplus::authUtils()->raCheckPassword($this->email, $password);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function delete() {
OIDplus::db()->query("delete from ###ra where email = ?", array($this->email));
}
 
public function setRaName($ra_name) {
/**
* @param string $ra_name
* @return void
* @throws OIDplusException
*/
public function setRaName(string $ra_name) {
OIDplus::db()->query("update ###ra set ra_name = ? where email = ?", array($ra_name, $this->email));
}
 
public function isPasswordLess() {
/**
* @return bool|null
* @throws OIDplusException
*/
public function isPasswordLess()/*: ?bool*/ {
$authInfo = $this->getAuthInfo();
if (!$authInfo) return null; // user not found
return $authInfo->isPasswordLess();
/trunk/includes/classes/OIDplusRAAuthInfo.class.php
27,22 → 27,36
 
private $authKey;
 
public function setAuthKey($authKey) {
/**
* @param string $authKey
* @return void
* @throws OIDplusException
*/
public function setAuthKey(string $authKey) {
// 250 is the length of the database field
if (strlen($authKey) > 250) throw new OIDplusException(_L('Field %1 is too long. Max allowed %2','Auth key',250));
if (is_null($authKey) || ($authKey === false)) throw new OIDplusException(_L('Field %1 is invalid','Auth key'));
$this->authKey = $authKey;
}
 
public function getAuthKey() {
/**
* @return string
*/
public function getAuthKey(): string {
return $this->authKey;
}
 
public function __construct($authKey) {
/**
* @param string $authKey
* @throws OIDplusException
*/
public function __construct(string $authKey) {
$this->setAuthKey($authKey);
}
 
public function isPasswordLess() {
/**
* @return bool
*/
public function isPasswordLess(): bool {
return empty($this->authKey);
}
 
/trunk/includes/classes/OIDplusRAAuthInfo.class.php.bak
0,0 → 1,69
<?php
 
/*
* OIDplus 2.0
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
namespace ViaThinkSoft\OIDplus;
 
// phpcs:disable PSR1.Files.SideEffects
\defined('INSIDE_OIDPLUS') or die;
// phpcs:enable PSR1.Files.SideEffects
 
class OIDplusRAAuthInfo extends OIDplusBaseClass {
 
private $authKey;
 
/**
* @param string $authKey
* @return void
* @throws OIDplusException
*/
public function setAuthKey(string $authKey) {
// 250 is the length of the database field
if (strlen($authKey) > 250) throw new OIDplusException(_L('Field %1 is too long. Max allowed %2','Auth key',250));
<<<<<<< .mine
||||||| .r1112
if (is_null($authKey) || ($authKey === false)) throw new OIDplusException(_L('Field %1 is too invalid','Auth key'));
=======
if (is_null($authKey) || ($authKey === false)) throw new OIDplusException(_L('Field %1 is invalid','Auth key'));
>>>>>>> .r1115
$this->authKey = $authKey;
}
 
/**
* @return string
*/
public function getAuthKey(): string {
return $this->authKey;
}
 
/**
* @param string $authKey
* @throws OIDplusException
*/
public function __construct(string $authKey) {
$this->setAuthKey($authKey);
}
 
/**
* @return bool
*/
public function isPasswordLess(): bool {
return empty($this->authKey);
}
 
}
/trunk/includes/classes/OIDplusSQLException.class.php
25,7 → 25,11
 
class OIDplusSQLException extends OIDplusException {
 
public function __construct($sql, $message) {
/**
* @param string $sql
* @param string $message
*/
public function __construct(string $sql, string $message) {
parent::__construct(_L('%1 at query "%2"',$message,$sql));
}
 
/trunk/includes/classes/OIDplusSessionHandler.class.php
28,6 → 28,9
private $secret = '';
protected $sessionLifetime = 0;
 
/**
* @throws OIDplusException
*/
public function __construct() {
$this->sessionLifetime = OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60);
$this->secret = OIDplus::baseConfig()->getValue('SERVER_SECRET');
56,6 → 59,10
@ini_set('session.gc_maxlifetime', $this->sessionLifetime);
}
 
/**
* @return void
* @throws OIDplusException
*/
protected function sessionSafeStart() {
if (!isset($_SESSION)) {
// TODO: session_name() makes some problems. Leave it away for now.
83,6 → 90,9
}
}
 
/**
* @return void
*/
function __destruct() {
session_write_close();
}
89,7 → 99,13
 
private $cacheSetValues = array(); // Important if you do a setValue() followed by an getValue()
 
public function setValue($name, $value) {
/**
* @param string $name
* @param mixed $value
* @return void
* @throws OIDplusException
*/
public function setValue(string $name, $value) {
$enc_data = self::encrypt($value, $this->secret);
 
$this->cacheSetValues[$name] = $enc_data;
100,7 → 116,13
$_SESSION[$name] = $enc_data;
}
 
public function getValue($name, $default = NULL) {
/**
* @param string $name
* @param mixed|null $default
* @return mixed|null
* @throws OIDplusException
*/
public function getValue(string $name, $default = NULL) {
if (isset($this->cacheSetValues[$name])) return self::decrypt($this->cacheSetValues[$name], $this->secret);
 
if (!$this->isActive()) return $default; // GDPR: Only start a session when we really need one
111,7 → 133,12
return self::decrypt($_SESSION[$name], $this->secret);
}
 
public function exists($name) {
/**
* @param string $name
* @return bool
* @throws OIDplusException
*/
public function exists(string $name): bool {
if (isset($this->cacheSetValues[$name])) return true;
 
if (!$this->isActive()) return false; // GDPR: Only start a session when we really need one
118,10 → 145,15
$this->sessionSafeStart();
OIDplus::cookieUtils()->setcookie(session_name(),session_id(),time()+$this->sessionLifetime);
 
if (!isset($_SESSION[$name])) return false;
return isset($_SESSION[$name]);
}
 
public function delete($name) {
/**
* @param string $name
* @return void
* @throws OIDplusException
*/
public function delete(string $name) {
if (isset($this->cacheSetValues[$name])) unset($this->cacheSetValues[$name]);
 
if (!$this->isActive()) return; // GDPR: Only start a session when we really need one
131,6 → 163,10
unset($_SESSION[$name]);
}
 
/**
* @return void
* @throws OIDplusException
*/
public function destroySession() {
if (!$this->isActive()) return;
 
143,11 → 179,20
OIDplus::cookieUtils()->unsetcookie(session_name()); // remove cookie, so GDPR people are happy
}
 
public function isActive() {
/**
* @return bool
*/
public function isActive(): bool {
return isset($_COOKIE[session_name()]);
}
 
protected static function encrypt($data, $key) {
/**
* @param string $data
* @param string $key
* @return string
* @throws \Exception
*/
protected static function encrypt(string $data, string $key): string {
if (function_exists('openssl_encrypt')) {
$iv = random_bytes(16); // AES block size in CBC mode
// Encryption
168,7 → 213,13
}
}
 
protected static function decrypt($data, $key) {
/**
* @param string $data
* @param string $key
* @return string
* @throws OIDplusException
*/
protected static function decrypt(string $data, string $key): string {
if (function_exists('openssl_decrypt')) {
$hmac = mb_substr($data, 0, 64, '8bit');
$iv = mb_substr($data, 64, 16, '8bit');
/trunk/includes/classes/OIDplusSqlSlangPlugin.class.php
25,33 → 25,85
 
abstract class OIDplusSqlSlangPlugin extends OIDplusPlugin {
 
/**
* @return string
*/
public abstract static function id(): string;
 
public abstract function natOrder($fieldname, $order='asc'): string;
/**
* @param string $fieldname
* @param string $order
* @return string
*/
public abstract function natOrder(string $fieldname, string $order='asc'): string;
 
/**
* @return string
*/
public abstract function sqlDate(): string;
 
/**
* @param OIDplusDatabaseConnection $db
* @return bool
*/
public abstract function detect(OIDplusDatabaseConnection $db): bool;
 
// Please note: This insert_id() function should use SQL to receive
// the last inserted ID. If the database connection provider (e.g. PDO)
// offers a way to fetch the last inserted ID, please use this instead!
// So, please do NOT use OIDplus::db()->getSlang()->insert_id()
// but instead use OIDplus::db()->insert_id()
// This way, the database connection provider can override that function
// with their own method of fetching the last inserted ID.
/**
* Please note: This insert_id() function should use SQL to receive
* the last inserted ID. If the database connection provider (e.g. PDO)
* offers a way to fetch the last inserted ID, please use this instead!
* So, please do NOT use OIDplus::db()->getSlang()->insert_id()
* but instead use OIDplus::db()->insert_id()
* This way, the database connection provider can override that function
* with their own method of fetching the last inserted ID.
* @param OIDplusDatabaseConnection $db
* @return int 0 on failure.
*/
public abstract function insert_id(OIDplusDatabaseConnection $db): int;
 
public abstract function setupSetTablePrefix($cont, $table, $prefix): string;
/**
* @param string $cont
* @param string $table
* @param string $prefix
* @return string
*/
public abstract function setupSetTablePrefix(string $cont, string $table, string $prefix): string;
 
public abstract function setupCreateDbIfNotExists($database): string;
/**
* @param string $database
* @return string
*/
public abstract function setupCreateDbIfNotExists(string $database): string;
 
public abstract function setupUseDatabase($database): string;
/**
* @param string $database
* @return string
*/
public abstract function setupUseDatabase(string $database): string;
 
public abstract function filterQuery($sql): string;
/**
* @param string $sql
* @return string
*/
public abstract function filterQuery(string $sql): string;
 
public abstract function getSQLBool($bool): string;
/**
* @param bool $bool
* @return string
*/
public abstract function getSQLBool(bool $bool): string;
 
public abstract function escapeString($str): string;
/**
* @param string $str
* @return string
*/
public abstract function escapeString(string $str): string;
 
/**
* @param string $expr1
* @param string $expr2
* @return string
*/
public abstract function isNullFunction(string $expr1, string $expr2): string;
 
}
/trunk/includes/db_updates/update1002.inc.php
18,11 → 18,13
*/
 
use ViaThinkSoft\OIDplus\OIDplusDatabaseConnection;
use ViaThinkSoft\OIDplus\OIDplusException;
 
/**
* This function is internally called by oidplus_dbupdate_1002().
* It changes the auth keys A1*# and A2# to VTS-MCF and A3# to BCrypt-MCF.
* @param OIDplusDatabaseConnection $db is the OIDplusDatabaseConnection class
* @throws OIDplusException
*/
function oidplus_dbupdate_1002_migrate_ra_passwords(OIDplusDatabaseConnection $db) {
$res = $db->query("select * from ###ra ");
/trunk/includes/functions.inc.php
48,9 → 48,9
);
$privKeyNew = @openssl_pkey_get_private($privKeyOld, $passphrase_old);
if ($privKeyNew === false) return false;
@openssl_pkey_export($privKeyNew, $privKeyNewExport, $passphrase_new, $pkey_config);
if ($privKeyNewExport === false) return false;
return $privKeyNewExport."";
if (!@openssl_pkey_export($privKeyNew, $privKeyNewExport, $passphrase_new, $pkey_config)) return false;
if ($privKeyNewExport === "") return false;
return "$privKeyNewExport";
}
 
function decrypt_private_key($privKey, $passphrase) {
/trunk/includes/oidplus.inc.php
23,7 → 23,7
// will get a compilation error and then they won't see our friendly error message.
// More information about the required PHP version: doc/developer_notes/php7_compat.txt
 
define('INSIDE_OIDPLUS', true);
const INSIDE_OIDPLUS = true;
 
if (version_compare(PHP_VERSION, $oidplus_min_version='7.0.0') < 0) {
// Note: These strings are not translated, because in case of an incompatible
52,7 → 52,7
if (count($missing_dependencies) >= 1) {
// Note that there are no translations _L() because if we get an error at this
// stage, then we have no language plugins anyways.
$message = '<p>'.sprintf('The following PHP extensions need to be installed in order to run OIDplus:').'</p>';
$message = '<p>The following PHP extensions need to be installed in order to run OIDplus:</p>';
$message .= '<p><ul>';
foreach ($missing_dependencies as $dependency) {
$message .= '<li>'.$dependency.'<br><br></li>';
85,7 → 85,7
// Functions
 
function oidplus_dependency_panic($message)/*: never*/ {
$title = sprintf('OIDplus startup error');
$title = 'OIDplus startup error';
if (PHP_SAPI === 'cli') {
$message = str_replace('<li>', "- ", $message);
$message = str_replace('<br>', "\n", $message);
/trunk/includes/oidplus_autoloader.inc.php
51,7 → 51,7
if (!isset($class_refs[$cn])) {
$class_refs[$cn] = array($filename);
} else {
$class_refs[$cn][] = $filename;;
$class_refs[$cn][] = $filename;
}
}
};
/trunk/includes/oidplus_dependency.inc.php
69,7 → 69,7
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$install_hint1 = sprintf('On Windows, install it by enabling the line %s in your PHP.ini',
'extension=php_gmp.dll');
$install_hint2 = sprintf('On Windows, it should be installed by default');
$install_hint2 = 'On Windows, it should be installed by default';
} else {
$install_hint1 = sprintf('On Linux, install it by running e.g. %s, and then restart your webserver service, e.g. by running %s',
'<code>sudo apt-get update && sudo apt-get install php-gmp</code>',
79,7 → 79,7
'<code>sudo service apache2 restart</code>');
}
$missing_dependencies[] = 'GMP ('.$install_hint1.')'.
'<br>'.sprintf('or alternatively').'<br>' .
'<br>or alternatively<br>' .
'BCMath ('.$install_hint2.')';
}
 
94,15 → 94,15
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$install_hint1 = sprintf('On Windows, install it by enabling the line %s in your PHP.ini',
'extension=php_mbstring.dll');
$install_hint2 = sprintf('On Windows, it should be installed by default');
$install_hint2 = 'On Windows, it should be installed by default';
} else {
$install_hint1 = sprintf('On Linux, install it by running e.g. %s, and then restart your webserver service, e.g. by running %s',
'<code>sudo apt-get update && sudo apt-get install php-mbstring</code>',
'<code>sudo service apache2 restart</code>');
$install_hint2 = sprintf('On Linux, it should be installed by default'); // Alpine Linux: apk add php-iconv
$install_hint2 = 'On Linux, it should be installed by default'; // Alpine Linux: apk add php-iconv
}
$missing_dependencies[] = 'MBString ('.$install_hint1.')'.
'<br>'.sprintf('or alternatively').'<br>' .
'<br>or alternatively<br>' .
'iconv ('.$install_hint2.')';
}
 
113,7 → 113,7
// dev/translation/*.phps (only for developers)
// Note: This should not happen because of vendor/danielmarschall/php_utils/simplexml_supplement.inc.php
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$install_hint = sprintf('On Windows, it should be installed by default');
$install_hint = 'On Windows, it should be installed by default';
} else {
$install_hint = sprintf('On Linux, install it by running e.g. %s, and then restart your webserver service, e.g. by running %s',
'<code>sudo apt-get update && sudo apt-get install php-xml</code>',