array( 'refresh' => array_filter($GLOBALS, function ($k) use ($refreshSearch) { return stripos($k, $refreshSearch) !== false; }, ARRAY_FILTER_USE_KEY), 'search' => array( 'enabled' => (qualifyRequest($GLOBALS['mediaSearchAuth']) && $GLOBALS['mediaSearch'] == true && $GLOBALS['plexToken']) ? true : false, 'type' => $GLOBALS['mediaSearchType'], ), 'ombi' => array( 'enabled' => (qualifyRequest($GLOBALS['homepageOmbiAuth']) && qualifyRequest($GLOBALS['homepageOmbiRequestAuth']) && $GLOBALS['homepageOmbiEnabled'] == true && $GLOBALS['ssoOmbi'] && isset($_COOKIE['Auth'])) ? true : false, 'authView' => (qualifyRequest($GLOBALS['homepageOmbiAuth'])) ? true : false, 'authRequest' => (qualifyRequest($GLOBALS['homepageOmbiRequestAuth'])) ? true : false, 'sso' => ($GLOBALS['ssoOmbi']) ? true : false, 'cookie' => (isset($_COOKIE['Auth'])) ? true : false, ), 'options' => array( 'alternateHomepageHeaders' => $GLOBALS['alternateHomepageHeaders'], ) ), 'sso' => array( 'misc' => array( 'oAuthLogin' => isset($_COOKIE['oAuth']) ? true : false, 'rememberMe' => $GLOBALS['rememberMe'], 'rememberMeDays' => $GLOBALS['rememberMeDays'] ), 'plex' => array( 'enabled' => ($GLOBALS['ssoPlex']) ? true : false, 'cookie' => isset($_COOKIE['mpt']) ? true : false, 'machineID' => (strlen($GLOBALS['plexID']) == 40) ? true : false, 'token' => ($GLOBALS['plexToken'] !== '') ? true : false, 'oAuthEnabled' => ($GLOBALS['plexoAuth']) ? true : false, 'backend' => ($GLOBALS['authBackend'] == 'plex') ? true : false, ), 'ombi' => array( 'enabled' => ($GLOBALS['ssoOmbi']) ? true : false, 'cookie' => isset($_COOKIE['Auth']) ? true : false, 'url' => ($GLOBALS['ombiURL'] !== '') ? $GLOBALS['ombiURL'] : false, 'api' => ($GLOBALS['ombiToken'] !== '') ? true : false, ), 'tautulli' => array( 'enabled' => ($GLOBALS['ssoTautulli']) ? true : false, 'cookie' => !empty($tautulli) ? true : false, 'url' => ($GLOBALS['tautulliURL'] !== '') ? $GLOBALS['tautulliURL'] : false, ), ), 'ping' => array( 'onlineSound' => $GLOBALS['pingOnlineSound'], 'offlineSound' => $GLOBALS['pingOfflineSound'], 'statusSounds' => $GLOBALS['statusSounds'], 'auth' => $GLOBALS['pingAuth'], 'authMessage' => $GLOBALS['pingAuthMessage'], 'authMs' => $GLOBALS['pingAuthMs'], 'ms' => $GLOBALS['pingMs'], 'adminRefresh' => $GLOBALS['adminPingRefresh'], 'everyoneRefresh' => $GLOBALS['otherPingRefresh'], ), 'notifications' => array( 'backbone' => $GLOBALS['notificationBackbone'], 'position' => $GLOBALS['notificationPosition'] ), 'lockout' => array( 'enabled' => $GLOBALS['lockoutSystem'], 'timer' => $GLOBALS['lockoutTimeout'], 'minGroup' => $GLOBALS['lockoutMinAuth'], 'maxGroup' => $GLOBALS['lockoutMaxAuth'] ), 'user' => array( 'agent' => isset($_SERVER ['HTTP_USER_AGENT']) ? $_SERVER ['HTTP_USER_AGENT'] : null, 'oAuthLogin' => isset($_COOKIE['oAuth']) ? true : false, 'local' => (isLocal()) ? true : false ), 'login' => array( 'rememberMe' => $GLOBALS['rememberMe'], 'rememberMeDays' => $GLOBALS['rememberMeDays'], ), 'misc' => array( 'installedPlugins' => $GLOBALS['installedPlugins'], 'installedThemes' => $GLOBALS['installedThemes'], 'return' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : false, 'authDebug' => $GLOBALS['authDebug'], 'minimalLoginScreen' => $GLOBALS['minimalLoginScreen'], 'unsortedTabs' => $GLOBALS['unsortedTabs'], 'authBackend' => $GLOBALS['authBackend'], 'newMessageSound' => (isset($GLOBALS['CHAT-newMessageSound-include'])) ? $GLOBALS['CHAT-newMessageSound-include'] : '', 'uuid' => $GLOBALS['uuid'], 'docker' => $GLOBALS['docker'] ) ); } function wizardConfig($array) { foreach ($array['data'] as $items) { foreach ($items as $key => $value) { if ($key == 'name') { $newKey = $value; } if ($key == 'value') { $newValue = $value; } if (isset($newKey) && isset($newValue)) { $$newKey = $newValue; } } } $location = cleanDirectory($location); $dbName = dbExtension($dbName); $configVersion = $GLOBALS['installedVersion']; $configArray = array( 'dbName' => $dbName, 'dbLocation' => $location, 'license' => $license, 'organizrHash' => $hashKey, 'organizrAPI' => $api, 'registrationPassword' => $registrationPassword, ); // Create Config $GLOBALS['dbLocation'] = $location; $GLOBALS['dbName'] = $dbName; if (createConfig($configArray)) { // Call DB Create if (createDB($location, $dbName)) { // Add in first user if (createFirstAdmin($location, $dbName, $username, $password, $email)) { if (createToken($username, $email, gravatar($email), 'Admin', 0, $hashKey, 1)) { return true; } else { return 'token'; } } else { return 'admin'; } } else { return 'db'; } } else { return 'config'; } return false; } function register($array) { // Grab username and password from login form foreach ($array['data'] as $items) { foreach ($items as $key => $value) { if ($key == 'name') { $newKey = $value; } if ($key == 'value') { $newValue = $value; } if (isset($newKey) && isset($newValue)) { $$newKey = $newValue; } } } if ($registrationPassword == $GLOBALS['registrationPassword']) { $defaults = defaultUserGroup(); writeLog('success', 'Registration Function - Registration Password Verified', $username); if (createUser($username, $password, $defaults, $email)) { writeLog('success', 'Registration Function - A User has registered', $username); if (createToken($username, $email, gravatar($email), $defaults['group'], $defaults['group_id'], $GLOBALS['organizrHash'], $GLOBALS['rememberMeDays'])) { writeLoginLog($username, 'success'); writeLog('success', 'Login Function - A User has logged in', $username); return true; } } else { writeLog('error', 'Registration Function - An error occured', $username); return 'username taken'; } } else { writeLog('warning', 'Registration Function - Wrong Password', $username); return 'mismatch'; } } function removeFile($array) { $filePath = $array['data']['path']; $fileName = $array['data']['name']; if (file_exists($filePath)) { if (unlink($filePath)) { writeLog('success', 'Log Management Function - Log: ' . $fileName . ' has been purged/deleted', 'SYSTEM'); return true; } else { writeLog('error', 'Log Management Function - Log: ' . $fileName . ' - Error Occured', 'SYSTEM'); return false; } } else { writeLog('error', 'Log Management Function - Log: ' . $fileName . ' does not exist', 'SYSTEM'); return false; } } function recover($array) { $email = $array['data']['email']; $newPassword = randString(10); try { $connect = new Dibi\Connection([ 'driver' => 'sqlite3', 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'], ]); $isUser = $connect->fetch('SELECT * FROM users WHERE email = ? COLLATE NOCASE', $email); if ($isUser) { $connect->query(' UPDATE users SET', [ 'password' => password_hash($newPassword, PASSWORD_BCRYPT) ], ' WHERE email=? COLLATE NOCASE', $email); if ($GLOBALS['PHPMAILER-enabled']) { $emailTemplate = array( 'type' => 'reset', 'body' => $GLOBALS['PHPMAILER-emailTemplateResetPassword'], 'subject' => $GLOBALS['PHPMAILER-emailTemplateResetPasswordSubject'], 'user' => $isUser['username'], 'password' => $newPassword, 'inviteCode' => null, ); $emailTemplate = phpmEmailTemplate($emailTemplate); $sendEmail = array( 'to' => $email, 'user' => $isUser['username'], 'subject' => $emailTemplate['subject'], 'body' => phpmBuildEmail($emailTemplate), ); phpmSendEmail($sendEmail); } writeLog('success', 'User Management Function - User: ' . $isUser['username'] . '\'s password was reset', $isUser['username']); return true; } else { writeLog('error', 'User Management Function - Error - User: ' . $email . ' An error Occured', $email); return 'an error occured'; } } catch (Dibi\Exception $e) { writeLog('error', 'User Management Function - Error - User: ' . $email . ' An error Occured', $email); return 'an error occured'; } } function unlock($array) { if ($array['data']['password'] == '') { return 'Password Not Set'; } try { $connect = new Dibi\Connection([ 'driver' => 'sqlite3', 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'], ]); $result = $connect->fetch('SELECT * FROM users WHERE id = ?', $GLOBALS['organizrUser']['userID']); if (!password_verify($array['data']['password'], $result['password'])) { return 'Password Incorrect'; } $connect->query(' UPDATE users SET', [ 'locked' => '' ], ' WHERE id=?', $GLOBALS['organizrUser']['userID']); writeLog('success', 'User Lockout Function - User: ' . $GLOBALS['organizrUser']['username'] . '\'s account unlocked', $GLOBALS['organizrUser']['username']); return true; } catch (Dibi\Exception $e) { writeLog('error', 'User Management Function - Error - User: ' . $GLOBALS['organizrUser']['username'] . ' An error Occured', $GLOBALS['organizrUser']['username']); return 'an error occured'; } } function lock() { if ($GLOBALS['organizrUser']['userID'] == '999') { return 'Not Allowed on Guest'; } try { $connect = new Dibi\Connection([ 'driver' => 'sqlite3', 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'], ]); $connect->query(' UPDATE users SET', [ 'locked' => '1' ], ' WHERE id=?', $GLOBALS['organizrUser']['userID']); writeLog('success', 'User Lockout Function - User: ' . $GLOBALS['organizrUser']['username'] . '\'s account unlocked', $GLOBALS['organizrUser']['username']); return true; } catch (Dibi\Exception $e) { writeLog('error', 'User Management Function - Error - User: ' . $GLOBALS['organizrUser']['username'] . ' An error Occured', $GLOBALS['organizrUser']['username']); return 'an error occured'; } } function editUser($array) { if ($array['data']['username'] == '' && $array['data']['username'] == '') { return 'Username/email not set'; } try { $connect = new Dibi\Connection([ 'driver' => 'sqlite3', 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'], ]); if (!usernameTakenExcept($array['data']['username'], $array['data']['email'], $GLOBALS['organizrUser']['userID'])) { $connect->query(' UPDATE users SET', [ 'username' => $array['data']['username'], 'email' => $array['data']['email'], 'image' => gravatar($array['data']['email']), ], ' WHERE id=?', $GLOBALS['organizrUser']['userID']); if (!empty($array['data']['password'])) { $connect->query(' UPDATE users SET', [ 'password' => password_hash($array['data']['password'], PASSWORD_BCRYPT) ], ' WHERE id=?', $GLOBALS['organizrUser']['userID']); } writeLog('success', 'User Management Function - User: ' . $array['data']['username'] . '\'s info was changed', $GLOBALS['organizrUser']['username']); return true; } else { return 'Username/Email Already Taken'; } } catch (Dibi\Exception $e) { writeLog('error', 'User Management Function - Error - User: ' . $array['data']['username'] . ' An error Occured', $GLOBALS['organizrUser']['username']); return 'an error occured'; } } function clearTautulliTokens() { foreach (array_keys($_COOKIE) as $k => $v) { if (strpos($v, 'tautulli') !== false) { coookie('delete', $v); } } } function logout() { coookie('delete', $GLOBALS['cookieName']); coookie('delete', 'mpt'); coookie('delete', 'Auth'); coookie('delete', 'oAuth'); clearTautulliTokens(); revokeToken(array('data' => array('token' => $GLOBALS['organizrUser']['token']))); $GLOBALS['organizrUser'] = false; return true; } function qualifyRequest($accessLevelNeeded) { if (getUserLevel() <= $accessLevelNeeded && getUserLevel() !== null) { return true; } else { return false; } } function getUserLevel() { // Grab token //$requesterToken = isset(getallheaders()['Token']) ? getallheaders()['Token'] : false; $requesterToken = isset(getallheaders()['Token']) ? getallheaders()['Token'] : (isset($_GET['apikey']) ? $_GET['apikey'] : false); // Check token or API key // If API key, return 0 for admin if (strlen($requesterToken) == 20 && $requesterToken == $GLOBALS['organizrAPI']) { //DO API CHECK return 0; } elseif (isset($GLOBALS['organizrUser'])) { return $GLOBALS['organizrUser']['groupID']; } // All else fails? return guest id return 999; } function organizrStatus() { $status = array(); $dependenciesActive = array(); $dependenciesInactive = array(); $extensions = array("PDO_SQLITE", "PDO", "SQLITE3", "zip", "cURL", "openssl", "simplexml", "json", "session"); $functions = array("hash", "fopen", "fsockopen", "fwrite", "fclose", "readfile"); foreach ($extensions as $check) { if (extension_loaded($check)) { array_push($dependenciesActive, $check); } else { array_push($dependenciesInactive, $check); } } foreach ($functions as $check) { if (function_exists($check)) { array_push($dependenciesActive, $check); } else { array_push($dependenciesInactive, $check); } } if (!file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) { $status['status'] = "wizard";//wizard - ok for test } if (count($dependenciesInactive) > 0 || !is_writable(dirname(__DIR__, 2)) || !(version_compare(PHP_VERSION, $GLOBALS['minimumPHP']) >= 0)) { $status['status'] = "dependencies"; } $status['status'] = (!empty($status['status'])) ? $status['status'] : $status['status'] = "ok"; $status['writable'] = is_writable(dirname(__DIR__, 2)) ? 'yes' : 'no'; $status['minVersion'] = (version_compare(PHP_VERSION, $GLOBALS['minimumPHP']) >= 0) ? 'yes' : 'no'; $status['dependenciesActive'] = $dependenciesActive; $status['dependenciesInactive'] = $dependenciesInactive; $status['version'] = $GLOBALS['installedVersion']; $status['os'] = getOS(); $status['php'] = phpversion(); return $status; } function getSettingsMain() { return array( 'Github' => array( array( 'type' => 'select', 'name' => 'branch', 'label' => 'Branch', 'value' => $GLOBALS['branch'], 'options' => getBranches() ), array( 'type' => 'button', 'label' => 'Force Install Branch', 'class' => 'updateNow', 'icon' => 'fa fa-download', 'text' => 'Retrieve', 'attr' => ($GLOBALS['docker']) ? 'title="You can just restart your docker to update"' : '', 'help' => ($GLOBALS['docker']) ? 'Since you are using the Official Docker image, You can just restart your docker to update' : 'This will re-download all of the source files for Organizr' ) ), 'API' => array( array( 'type' => 'password-alt', 'name' => 'organizrAPI', 'label' => 'Organizr API', 'value' => $GLOBALS['organizrAPI'] ), array( 'type' => 'button', 'label' => 'Generate New API Key', 'class' => 'newAPIKey', 'icon' => 'fa fa-refresh', 'text' => 'Generate' ) ), 'Authentication' => array( array( 'type' => 'select', 'name' => 'authType', 'id' => 'authSelect', 'label' => 'Authentication Type', 'value' => $GLOBALS['authType'], 'options' => getAuthTypes() ), array( 'type' => 'select', 'name' => 'authBackend', 'id' => 'authBackendSelect', 'label' => 'Authentication Backend', 'class' => 'backendAuth switchAuth', 'value' => $GLOBALS['authBackend'], 'options' => getAuthBackends() ), array( 'type' => 'password-alt', 'name' => 'plexToken', 'class' => 'plexAuth switchAuth', 'label' => 'Plex Token', 'value' => $GLOBALS['plexToken'], 'placeholder' => 'Use Get Token Button' ), array( 'type' => 'button', 'label' => 'Get Plex Token', 'class' => 'popup-with-form getPlexTokenAuth plexAuth switchAuth', 'icon' => 'fa fa-ticket', 'text' => 'Retrieve', 'href' => '#auth-plex-token-form', 'attr' => 'data-effect="mfp-3d-unfold"' ), array( 'type' => 'password-alt', 'name' => 'plexID', 'class' => 'plexAuth switchAuth', 'label' => 'Plex Machine', 'value' => $GLOBALS['plexID'], 'placeholder' => 'Use Get Plex Machine Button' ), array( 'type' => 'button', 'label' => 'Get Plex Machine', 'class' => 'popup-with-form getPlexMachineAuth plexAuth switchAuth', 'icon' => 'fa fa-id-badge', 'text' => 'Retrieve', 'href' => '#auth-plex-machine-form', 'attr' => 'data-effect="mfp-3d-unfold"' ), array( 'type' => 'input', 'name' => 'plexAdmin', 'label' => 'Admin Username', 'class' => 'plexAuth switchAuth', 'value' => $GLOBALS['plexAdmin'], 'placeholder' => 'Admin username for Plex' ), array( 'type' => 'switch', 'name' => 'plexoAuth', 'label' => 'Enable Plex oAuth', 'class' => 'plexAuth switchAuth', 'value' => $GLOBALS['plexoAuth'] ), array( 'type' => 'switch', 'name' => 'plexStrictFriends', 'label' => 'Strict Plex Friends ', 'class' => 'plexAuth switchAuth', 'value' => $GLOBALS['plexStrictFriends'], 'help' => 'Enabling this will only allow Friends that have shares to the Machine ID entered above to login, Having this disabled will allow all Friends on your Friends list to login' ), array( 'type' => 'input', 'name' => 'authBackendHost', 'class' => 'ldapAuth ftpAuth switchAuth', 'label' => 'Host Address', 'value' => $GLOBALS['authBackendHost'], 'placeholder' => 'http{s) | ftp(s) | ldap(s)://hostname:port' ), array( 'type' => 'input', 'name' => 'authBaseDN', 'class' => 'ldapAuth switchAuth', 'label' => 'Host Base DN', 'value' => $GLOBALS['authBaseDN'], 'placeholder' => 'cn=%s,dc=sub,dc=domain,dc=com' ), array( 'type' => 'input', 'name' => 'embyURL', 'class' => 'embyAuth switchAuth', 'label' => 'Emby URL', 'value' => $GLOBALS['embyURL'], 'placeholder' => 'http(s)://hostname:port' ), array( 'type' => 'password-alt', 'name' => 'embyToken', 'class' => 'embyAuth switchAuth', 'label' => 'Emby Token', 'value' => $GLOBALS['embyToken'], 'placeholder' => '' ), /*array( 'type' => 'button', 'label' => 'Send Test', 'class' => 'phpmSendTestEmail', 'icon' => 'fa fa-paper-plane', 'text' => 'Send' )*/ ), 'Security' => array( array( 'type' => 'number', 'name' => 'lockoutTimeout', 'label' => 'Inactivity Timer [Minutes]', 'value' => $GLOBALS['lockoutTimeout'], 'placeholder' => '' ), array( 'type' => 'select', 'name' => 'lockoutMinAuth', 'label' => 'Lockout Groups From', 'value' => $GLOBALS['lockoutMinAuth'], 'options' => groupSelect() ), array( 'type' => 'select', 'name' => 'lockoutMaxAuth', 'label' => 'Lockout Groups To', 'value' => $GLOBALS['lockoutMaxAuth'], 'options' => groupSelect() ), array( 'type' => 'switch', 'name' => 'lockoutSystem', 'label' => 'Inactivity Lock', 'value' => $GLOBALS['lockoutSystem'] ), array( 'type' => 'switch', 'name' => 'authDebug', 'label' => 'Nginx Auth Debug', 'help' => 'Important! Do not keep this enabled for too long as this opens up Authentication while testing.', 'value' => $GLOBALS['authDebug'], 'class' => 'authDebug' ) ), 'Login' => array( array( 'type' => 'password-alt', 'name' => 'registrationPassword', 'label' => 'Registration Password', 'value' => $GLOBALS['registrationPassword'], ), array( 'type' => 'switch', 'name' => 'hideRegistration', 'label' => 'Hide Registration', 'value' => $GLOBALS['hideRegistration'], ), array( 'type' => 'number', 'name' => 'rememberMeDays', 'label' => 'Remember Me Length', 'help' => 'Number of days cookies and tokens will be valid for', 'value' => $GLOBALS['rememberMeDays'], 'placeholder' => '', 'attr' => 'min="1"' ), array( 'type' => 'switch', 'name' => 'rememberMe', 'label' => 'Remember Me', 'help' => 'Default status of Remember Me button on login screen', 'value' => $GLOBALS['rememberMe'], ), ), 'Ping' => array( array( 'type' => 'select', 'name' => 'pingAuth', 'label' => 'Minimum Authentication', 'value' => $GLOBALS['pingAuth'], 'options' => groupSelect() ), array( 'type' => 'select', 'name' => 'pingAuthMessage', 'label' => 'Minimum Authentication for Message and Sound', 'value' => $GLOBALS['pingAuthMessage'], 'options' => groupSelect() ), array( 'type' => 'select', 'name' => 'pingOnlineSound', 'label' => 'Online Sound', 'value' => $GLOBALS['pingOnlineSound'], 'options' => getSounds() ), array( 'type' => 'select', 'name' => 'pingOfflineSound', 'label' => 'Offline Sound', 'value' => $GLOBALS['pingOfflineSound'], 'options' => getSounds() ), array( 'type' => 'switch', 'name' => 'pingMs', 'label' => 'Show Ping Time', 'value' => $GLOBALS['pingMs'] ), array( 'type' => 'switch', 'name' => 'statusSounds', 'label' => 'Enable Notify Sounds', 'value' => $GLOBALS['statusSounds'], 'help' => 'Will play a sound if the server goes down and will play sound if comes back up.', ), array( 'type' => 'select', 'name' => 'pingAuthMs', 'label' => 'Minimum Authentication for Time Display', 'value' => $GLOBALS['pingAuthMs'], 'options' => groupSelect() ), array( 'type' => 'select', 'name' => 'adminPingRefresh', 'label' => 'Admin Refresh Seconds', 'value' => $GLOBALS['adminPingRefresh'], 'options' => optionTime() ), array( 'type' => 'select', 'name' => 'otherPingRefresh', 'label' => 'Everyone Refresh Seconds', 'value' => $GLOBALS['otherPingRefresh'], 'options' => optionTime() ), ) ); } function getSSO() { return array( 'FYI' => array( array( 'type' => 'html', 'label' => 'Important Information', 'override' => 12, 'html' => '