/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)) ? '&goto='.urlencode($goto) : ''; |
$add = ($goto != '') ? '&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>', |