Jelajahi Sumber

Merge pull request #1334 from causefx/v2-develop

V2 develop
causefx 6 tahun lalu
induk
melakukan
e9c77f50e3

+ 1 - 1
api/composer.json

@@ -1,6 +1,6 @@
 {
   "require": {
-    "dibi/dibi": "^3.1",
+    "dibi/dibi": "^3.2",
     "lcobucci/jwt": "^3.2",
     "composer/semver": "^1.4",
     "phpmailer/phpmailer": "^6.0",

+ 6 - 6
api/composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "1473a4b919301bb2dba1f39810e12418",
+    "content-hash": "b895341ab62fbe32e131b91bf9ca2e04",
     "packages": [
         {
             "name": "adldap2/adldap2",
@@ -129,16 +129,16 @@
         },
         {
             "name": "dibi/dibi",
-            "version": "v3.2.3",
+            "version": "v3.2.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dg/dibi.git",
-                "reference": "906e1f240742124e49562cace271916e1b08c991"
+                "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dg/dibi/zipball/906e1f240742124e49562cace271916e1b08c991",
-                "reference": "906e1f240742124e49562cace271916e1b08c991",
+                "url": "https://api.github.com/repos/dg/dibi/zipball/d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
+                "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
                 "shasum": ""
             },
             "require": {
@@ -192,7 +192,7 @@
                 "sqlite",
                 "sqlsrv"
             ],
-            "time": "2018-09-17T11:47:10+00:00"
+            "time": "2020-03-26T03:05:01+00:00"
         },
         {
             "name": "guzzlehttp/guzzle",

+ 1 - 0
api/config/default.php

@@ -16,6 +16,7 @@ return array(
 	'loginWallpaper' => '',
 	'title' => 'Organizr V2',
 	'useLogo' => false,
+	'useLogoLogin' => false,
 	'headerColor' => '',
 	'headerTextColor' => '',
 	'sidebarColor' => '',

+ 18 - 18
api/functions/homepage-connect-functions.php

@@ -52,7 +52,7 @@ function homepageConnect($array)
 			return getCalendar();
 			break;
 		case 'getRequests':
-			return getOmbiRequests($GLOBALS['ombiLimit']);
+			return getOmbiRequests('both', $GLOBALS['ombiLimit']);
 			break;
 		case 'getHealthChecks':
 			return (qualifyRequest($GLOBALS['homepageHealthChecksAuth'])) ? getHealthChecks($array['data']['tags']) : false;
@@ -763,7 +763,7 @@ function jdownloaderConnect()
         $url = qualifyURL($GLOBALS['jdownloaderURL']);
 
         try {
-            $options = (localURL($url)) ? array('verify' => false) : array();
+            $options = (localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
             $response = Requests::get($url, array(), $options);
             if ($response->success) {
                 $temp = json_decode($response->body, true);
@@ -835,13 +835,13 @@ function nzbgetConnect()
 {
 	if ($GLOBALS['homepageNzbgetEnabled'] && !empty($GLOBALS['nzbgetURL']) && qualifyRequest($GLOBALS['homepageNzbgetAuth'])) {
 		$url = qualifyURL($GLOBALS['nzbgetURL']);
-		if (!empty($GLOBALS['nzbgetUsername']) && !empty($GLOBALS['nzbgetPassword'])) {
-			$url = $url . '/' . $GLOBALS['nzbgetUsername'] . ':' . decrypt($GLOBALS['nzbgetPassword']) . '/jsonrpc/listgroups';
-		} else {
-			$url = $url . '/jsonrpc/listgroups';
-		}
+		$url = $url . '/jsonrpc/listgroups';
 		try {
 			$options = (localURL($url)) ? array('verify' => false) : array();
+			if($GLOBALS['nzbgetUsername'] !== '' && decrypt($GLOBALS['nzbgetPassword']) !== ''){
+				$credentials = array('auth' => new Requests_Auth_Basic(array($GLOBALS['nzbgetUsername'], decrypt($GLOBALS['nzbgetPassword']))));
+				$options = array_merge($options, $credentials);
+			}
 			$response = Requests::get($url, array(), $options);
 			if ($response->success) {
 				$api['content']['queueItems'] = json_decode($response->body, true);
@@ -850,13 +850,13 @@ function nzbgetConnect()
 			writeLog('error', 'NZBGet Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
 		};
 		$url = qualifyURL($GLOBALS['nzbgetURL']);
-		if (!empty($GLOBALS['nzbgetUsername']) && !empty($GLOBALS['nzbgetPassword'])) {
-			$url = $url . '/' . $GLOBALS['nzbgetUsername'] . ':' . decrypt($GLOBALS['nzbgetPassword']) . '/jsonrpc/history';
-		} else {
-			$url = $url . '/jsonrpc/history';
-		}
+		$url = $url . '/jsonrpc/history';
 		try {
 			$options = (localURL($url)) ? array('verify' => false) : array();
+			if($GLOBALS['nzbgetUsername'] !== '' && decrypt($GLOBALS['nzbgetPassword']) !== ''){
+				$credentials = array('auth' => new Requests_Auth_Basic(array($GLOBALS['nzbgetUsername'], decrypt($GLOBALS['nzbgetPassword']))));
+				$options = array_merge($options, $credentials);
+			}
 			$response = Requests::get($url, array(), $options);
 			if ($response->success) {
 				$api['content']['historyItems'] = json_decode($response->body, true);
@@ -2591,7 +2591,7 @@ function testAPIConnection($array)
             if (!empty($GLOBALS['jdownloaderURL'])) {
                 $url = qualifyURL($GLOBALS['jdownloaderURL']);
                 try {
-                    $options = (localURL($url)) ? array('verify' => false) : array();
+	                $options = (localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
                     $response = Requests::get($url, array(), $options);
                     if ($response->success) {
                         return true;
@@ -2623,13 +2623,13 @@ function testAPIConnection($array)
 		case 'nzbget':
 			if (!empty($GLOBALS['nzbgetURL'])) {
 				$url = qualifyURL($GLOBALS['nzbgetURL']);
-				if (!empty($GLOBALS['nzbgetUsername']) && !empty($GLOBALS['nzbgetPassword'])) {
-					$url = $url . '/' . $GLOBALS['nzbgetUsername'] . ':' . decrypt($GLOBALS['nzbgetPassword']) . '/jsonrpc/listgroups';
-				} else {
-					$url = $url . '/jsonrpc/listgroups';
-				}
+				$url = $url . '/jsonrpc/listgroups';
 				try {
 					$options = (localURL($url)) ? array('verify' => false) : array();
+					if($GLOBALS['nzbgetUsername'] !== '' && decrypt($GLOBALS['nzbgetPassword']) !== ''){
+						$credentials = array('auth' => new Requests_Auth_Basic(array($GLOBALS['nzbgetUsername'], decrypt($GLOBALS['nzbgetPassword']))));
+						$options = array_merge($options, $credentials);
+					}
 					$response = Requests::get($url, array(), $options);
 					if ($response->success) {
 						return true;

+ 8 - 8
api/functions/normal-functions.php

@@ -101,13 +101,13 @@ function coookie($type, $name, $value = '', $days = -1, $http = true)
 			. (empty($days) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() + (86400 * $days)) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $Domain)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 		header('Set-Cookie: ' . rawurlencode($name) . '=' . rawurlencode($value)
 			. (empty($days) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() + (86400 * $days)) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $DomainTest)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 	} elseif ($type == 'delete') {
 		unset($_COOKIE[$name]);
@@ -115,13 +115,13 @@ function coookie($type, $name, $value = '', $days = -1, $http = true)
 			. (empty($days) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() - 3600) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $Domain)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 		header('Set-Cookie: ' . rawurlencode($name) . '=' . rawurlencode($value)
 			. (empty($days) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() - 3600) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $DomainTest)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 	}
 }
@@ -150,13 +150,13 @@ function coookieSeconds($type, $name, $value = '', $ms, $http = true)
 			. (empty($ms) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() + ($ms / 1000)) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $Domain)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 		header('Set-Cookie: ' . rawurlencode($name) . '=' . rawurlencode($value)
 			. (empty($ms) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() + ($ms / 1000)) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $DomainTest)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 	} elseif ($type == 'delete') {
 		unset($_COOKIE[$name]);
@@ -164,13 +164,13 @@ function coookieSeconds($type, $name, $value = '', $ms, $http = true)
 			. (empty($ms) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() - 3600) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $Domain)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 		header('Set-Cookie: ' . rawurlencode($name) . '=' . rawurlencode($value)
 			. (empty($ms) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', time() - 3600) . ' GMT')
 			. (empty($Path) ? '' : '; path=' . $Path)
 			. (empty($Domain) ? '' : '; domain=' . $DomainTest)
-			. (!$Secure ? '' : '; secure')
+			. (!$Secure ? '' : '; SameSite=None; Secure')
 			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
 	}
 }

+ 21 - 4
api/functions/organizr-functions.php

@@ -1140,6 +1140,7 @@ function loadAppearance()
 	$appearance['logo'] = $GLOBALS['logo'];
 	$appearance['title'] = $GLOBALS['title'];
 	$appearance['useLogo'] = $GLOBALS['useLogo'];
+	$appearance['useLogoLogin'] = $GLOBALS['useLogoLogin'];
 	$appearance['headerColor'] = $GLOBALS['headerColor'];
 	$appearance['headerTextColor'] = $GLOBALS['headerTextColor'];
 	$appearance['sidebarColor'] = $GLOBALS['sidebarColor'];
@@ -1206,6 +1207,12 @@ function getCustomizeAppearance()
 					'value' => $GLOBALS['loginWallpaper'],
 					'help' => 'You may enter multiple URL\'s using the CSV format.  i.e. link#1,link#2,link#3'
 				),
+				array(
+					'type' => 'switch',
+					'name' => 'useLogoLogin',
+					'label' => 'Use Logo instead of Title on Login Page',
+					'value' => $GLOBALS['useLogoLogin']
+				),
 				array(
 					'type' => 'switch',
 					'name' => 'minimalLoginScreen',
@@ -1691,7 +1698,7 @@ function auth()
 		}
 	}
 	if ($group !== null) {
-		if ($_SERVER['HTTP_X_FORWARDED_SERVER'] == 'traefik' || $GLOBALS['traefikAuthEnable']) {
+		if ((isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && $_SERVER['HTTP_X_FORWARDED_SERVER'] == 'traefik') || $GLOBALS['traefikAuthEnable']) {
 			$redirect = 'Location: ' . getServerPath();
 		}
 		if (qualifyRequest($group) && $unlocked) {
@@ -1722,7 +1729,7 @@ function getTabGroup ($tab)
 
 function logoOrText()
 {
-	if ($GLOBALS['useLogo'] == false) {
+	if ($GLOBALS['useLogoLogin'] == false) {
 		return '<h1>' . $GLOBALS['title'] . '</h1>';
 	} else {
 		return '<img class="loginLogo" src="' . $GLOBALS['loginLogo'] . '" alt="Home" />';
@@ -2025,13 +2032,23 @@ function getImage()
 		if (file_exists($cachefile) && time() - $cachetime < filemtime($cachefile) && $refresh == false) {
 			header("Content-type: image/jpeg");
 			//@readfile($cachefile);
-			echo @curl('get', $cachefile)['content'];
+			//echo @curl('get', $cachefile)['content'];
+			$options = array('verify' => false);
+			$response = Requests::get($cachefile, array(), $options);
+			if ($response->success) {
+				echo $response->body;
+			}
 			exit;
 		}
 		ob_start(); // Start the output buffer
 		header('Content-type: image/jpeg');
 		//@readfile($image_src);
-		echo @curl('get', $image_src)['content'];
+		//echo @curl('get', $image_src)['content'];
+		$options = array('verify' => false);
+		$response = Requests::get($image_src, array(), $options);
+		if ($response->success) {
+			echo $response->body;
+		}
 		// Cache the output to a file
 		$fp = fopen($cachefile, 'wb');
 		fwrite($fp, ob_get_contents());

+ 1 - 1
api/functions/static-globals.php

@@ -1,7 +1,7 @@
 <?php
 // ===================================
 // Organizr Version
-$GLOBALS['installedVersion'] = '2.0.390';
+$GLOBALS['installedVersion'] = '2.0.408';
 // ===================================
 // Quick php Version check
 $GLOBALS['minimumPHP'] = '7.1.3';

+ 8 - 5
api/functions/token-functions.php

@@ -104,8 +104,8 @@ function validateToken($token, $global = false)
 	// Validate script
 	$userInfo = jwtParse($token);
 	$validated = $userInfo ? true : false;
-	if ($validated == true) {
-		if ($global == true) {
+	if ($global == true) {
+		if ($validated == true) {
 			try {
 				$database = new Dibi\Connection([
 					'driver' => 'sqlite3',
@@ -138,12 +138,15 @@ function validateToken($token, $global = false)
 			} catch (Dibi\Exception $e) {
 				$GLOBALS['organizrUser'] = false;
 			}
+		}else{
+			// Delete cookie & reload page
+			coookie('delete', $GLOBALS['cookieName']);
+			$GLOBALS['organizrUser'] = false;
 		}
 	} else {
-		// Delete cookie & reload page
-		coookie('delete', $GLOBALS['cookieName']);
-		$GLOBALS['organizrUser'] = false;
+		return $userInfo;
 	}
+	return false;
 }
 
 function getOrganizrUserToken()

+ 23 - 0
api/index.php

@@ -1279,6 +1279,29 @@ switch ($function) {
 				break;
 		}
 		break;
+	case 'v1_token_validate':
+		switch ($method) {
+			case 'GET':
+				$token = $_GET['token'] ?? false;
+				break;
+			case 'POST':
+				$token = $_POST['token'] ?? false;
+				break;
+			default:
+				$result['status'] = 'error';
+				$result['statusText'] = 'The function requested is not defined for method: ' . $method;
+				break;
+		}
+		$token = validateToken($token);
+		if($token){
+			$result['status'] = 'success';
+			$result['statusText'] = 'success';
+			$result['data'] = $token;
+		}else{
+			$result['status'] = 'error';
+			$result['statusText'] = 'Token not validated or empty';
+		}
+		break;
 	case 'v1_update_db_manual':
 		switch ($method) {
 			case 'GET':

+ 1 - 1
api/pages/login.php

@@ -32,7 +32,7 @@ if(activeInfo.settings.login.rememberMe){
                     <div class="panel-body">
 	                    <div class="input-group" style="width: 100%;">
 	                        <div class="input-group-addon hidden-xs"><i class="ti-lock"></i></div>
-	                        <input type="text" class="form-control tfa-input" name="tfaCode" placeholder="Code" autocomplete="off" autocorrect="off" autocapitalize="off" maxlength="6" spellcheck="false" autofocus="">
+	                        <input type="text" class="form-control tfa-input" name="tfaCode" placeholder="Code" data-lpignore="true" autocomplete="off" autocorrect="off" autocapitalize="off" maxlength="6" spellcheck="false" autofocus="">
 	                    </div>
 	                    <button class="btn btn-warning btn-lg btn-block text-uppercase waves-effect waves-light login-button m-t-10" type="submit" lang="en">Login</button>
                     </div>

+ 1 - 0
api/vendor/composer/autoload_classmap.php

@@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
 
 return array(
     'Dibi\\Bridges\\Nette\\DibiExtension22' => $vendorDir . '/dibi/dibi/src/Dibi/Bridges/Nette/DibiExtension22.php',
+    'Dibi\\Bridges\\Tracy\\Panel' => $vendorDir . '/dibi/dibi/src/Dibi/Bridges/Tracy/Panel.php',
     'Dibi\\Connection' => $vendorDir . '/dibi/dibi/src/Dibi/Connection.php',
     'Dibi\\ConstraintViolationException' => $vendorDir . '/dibi/dibi/src/Dibi/exceptions.php',
     'Dibi\\DataSource' => $vendorDir . '/dibi/dibi/src/Dibi/DataSource.php',

+ 1 - 0
api/vendor/composer/autoload_static.php

@@ -191,6 +191,7 @@ class ComposerStaticInitcbdc783d76f8e7563dcce7d8af053ecb
 
     public static $classMap = array (
         'Dibi\\Bridges\\Nette\\DibiExtension22' => __DIR__ . '/..' . '/dibi/dibi/src/Dibi/Bridges/Nette/DibiExtension22.php',
+        'Dibi\\Bridges\\Tracy\\Panel' => __DIR__ . '/..' . '/dibi/dibi/src/Dibi/Bridges/Tracy/Panel.php',
         'Dibi\\Connection' => __DIR__ . '/..' . '/dibi/dibi/src/Dibi/Connection.php',
         'Dibi\\ConstraintViolationException' => __DIR__ . '/..' . '/dibi/dibi/src/Dibi/exceptions.php',
         'Dibi\\DataSource' => __DIR__ . '/..' . '/dibi/dibi/src/Dibi/DataSource.php',

+ 6 - 6
api/vendor/composer/installed.json

@@ -126,17 +126,17 @@
     },
     {
         "name": "dibi/dibi",
-        "version": "v3.2.3",
-        "version_normalized": "3.2.3.0",
+        "version": "v3.2.4",
+        "version_normalized": "3.2.4.0",
         "source": {
             "type": "git",
             "url": "https://github.com/dg/dibi.git",
-            "reference": "906e1f240742124e49562cace271916e1b08c991"
+            "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/dg/dibi/zipball/906e1f240742124e49562cace271916e1b08c991",
-            "reference": "906e1f240742124e49562cace271916e1b08c991",
+            "url": "https://api.github.com/repos/dg/dibi/zipball/d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
+            "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
             "shasum": ""
         },
         "require": {
@@ -149,7 +149,7 @@
             "nette/tester": "~1.7",
             "tracy/tracy": "~2.2"
         },
-        "time": "2018-09-17T11:47:10+00:00",
+        "time": "2020-03-26T03:05:01+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {

+ 2 - 1
api/vendor/dibi/dibi/src/Dibi/Drivers/Sqlite3Driver.php

@@ -445,11 +445,12 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
 		$columns = [];
 		static $types = [SQLITE3_INTEGER => 'int', SQLITE3_FLOAT => 'float', SQLITE3_TEXT => 'text', SQLITE3_BLOB => 'blob', SQLITE3_NULL => 'null'];
 		for ($i = 0; $i < $count; $i++) {
+			$type = $this->resultSet->columnType($i); // buggy in PHP 7.4.4 & 7.3.16, bug 79414
 			$columns[] = [
 				'name' => $this->resultSet->columnName($i),
 				'table' => null,
 				'fullname' => $this->resultSet->columnName($i),
-				'nativetype' => $types[$this->resultSet->columnType($i)],
+				'nativetype' => $type ? $types[$type] : null,
 			];
 		}
 		return $columns;

+ 7 - 1
api/vendor/dibi/dibi/src/Dibi/Result.php

@@ -498,8 +498,11 @@ class Result implements IDataSource
 			} elseif ($type === Type::FLOAT) {
 				$value = ltrim((string) $value, '0');
 				$p = strpos($value, '.');
-				if ($p !== false) {
+				$e = strpos($value, 'e');
+				if ($p !== false && $e === false) {
 					$value = rtrim(rtrim($value, '0'), '.');
+				} elseif ($p !== false && $e !== false) {
+					$value = rtrim($value, '.');
 				}
 				if ($value === '' || $value[0] === '.') {
 					$value = '0' . $value;
@@ -526,6 +529,9 @@ class Result implements IDataSource
 
 			} elseif ($type === Type::BINARY) {
 				$row[$key] = $this->getResultDriver()->unescapeBinary($value);
+
+			} else {
+				$row[$key] = $value;
 			}
 		}
 	}

+ 2 - 2
api/vendor/dibi/dibi/src/Dibi/dibi.php

@@ -21,8 +21,8 @@ class dibi
 
 	/** version */
 	const
-		VERSION = '3.2.3',
-		REVISION = 'released on 2018-09-17';
+		VERSION = '3.2.4',
+		REVISION = 'released on 2020-03-26';
 
 	/** sorting order */
 	const

+ 4 - 4
index.php

@@ -1,6 +1,6 @@
 <?php include 'api/functions/static-globals.php';?>
 <!DOCTYPE html>
-<html lang="en">
+<html lang="en" ontouchmove>
 
 <head>
     <meta charset="utf-8">
@@ -51,7 +51,7 @@
     <![endif]-->
 </head>
 
-<body class="fix-header" data-active-tab="">
+<body class="fix-header" data-active-tab="" tabIndex=0>
 <!-- ============================================================== -->
 <!-- Preloader -->
 <!-- ============================================================== -->
@@ -113,8 +113,8 @@
     <!-- ============================================================== -->
     <!-- Left Sidebar - style you can find in sidebar.scss  -->
     <!-- ============================================================== -->
-    <div class="navbar-default sidebar" role="navigation">
-        <div class="sidebar-nav slimscrollsidebar">
+    <div class="navbar-default sidebar" role="navigation" data-simplebar-direction="rtl">
+        <div class="sidebar-nav">
             <div class="sidebar-head">
                 <h3><span class="open-close m-r-5"><i class="ti-menu hidden-xs"></i><i class="ti-close visible-xs"></i></span>
                     <span class="hide-menu hidden-xs" lang="en">Navigation</span>

+ 31 - 14
js/functions.js

@@ -14,6 +14,7 @@ lang.init({
 	allowCookieOverride: true
 });
 var OAuthLoginNeeded = false;
+var pingOrg = false;
 var timeouts = {};
 var increment = 0;
 var tabInformation = {};
@@ -2638,6 +2639,7 @@ function tabProcess(arrayItems) {
 		noTabs(arrayItems);
 	}
 	$(menuExtras(arrayItems.data.user.loggedin)).appendTo($('#side-menu'));
+    new SimpleBar($('.sidebar')[0], { direction: 'rtl' });
 }
 function buildLogin(){
 	swapDisplay('login');
@@ -4335,7 +4337,7 @@ function buildRequestItem(array, extra=null){
 				var user = (activeInfo.user.groupID <= 1) ? '<span lang="en">Requested By:</span> '+v.user : '';
 				var user2 = (activeInfo.user.groupID <= 1) ? '<br>'+v.user : '';
 				items += `
-				<div class="item lazyload recent-poster request-item request-`+v.type+` `+className+` mouse" data-target="request-`+v.id+`" data-src="`+v.poster+`">
+				<div class="item lazyload recent-poster request-item request-`+v.type+` `+className+` request-`+v.request_id+`-div mouse" data-target="request-`+v.id+`" data-src="`+v.poster+`">
 					<div class="outside-request-div">
 						<div class="inside-over-request-div `+badge2+`"></div>
 						<div class="inside-request-div `+badge+`"></div>
@@ -4825,8 +4827,9 @@ function processRequest(id,type){
 function ombiActions(id,action,type){
 	//console.log(id,action,type);
 	var msg = (activeInfo.user.groupID <= 1) ? '<a href="https://github.com/tidusjar/Ombi/issues/2176" target="_blank">Not Org Fault - Ask Ombi</a>' : 'Connection Error to Request Server';
-	ajaxloader('.preloader-'+id,'in');
-    ajaxloader('.mfp-content .white-popup .col-md-8 .white-box .user-bg','in');
+	ajaxloader('.request-' + id + '-div', 'in')
+    $.magnificPopup.close();
+    message(window.lang.translate('Submitting Action to Ombi'),'',activeInfo.settings.notifications.position,"#FFF",'success',"3500");
 	organizrAPI('POST','api/?v1/ombi',{id:id, action:action, type:type}).success(function(data) {
         try {
             var response = JSON.parse(data);
@@ -4839,7 +4842,6 @@ function ombiActions(id,action,type){
 		if(response.data !== false){
             if(action == 'delete'){
                 homepageRequests();
-                $.magnificPopup.close();
                 message(window.lang.translate('Deleted Request Item'),'',activeInfo.settings.notifications.position,"#FFF",'success',"3500");
                 return true;
             }
@@ -4850,12 +4852,11 @@ function ombiActions(id,action,type){
                 orgErrorAlert('<h4>' + e + '</h4>' + formatDebug(response.data.bd));
                 return false;
             }
-            console.log(responseData);
+            //console.log(responseData);
             var responseMessage = (responseData.isError == true) ? responseData.errorMessage : 'Success';
             var responseType = (responseData.isError == true) ? 'error' : 'success';
 			homepageRequests();
 			if(action !== 'add'){
-				$.magnificPopup.close();
 				message(window.lang.translate('Updated Request Item'),responseMessage,activeInfo.settings.notifications.position,"#FFF",responseType,"3500");
 			}else{
 				ajaxloader();
@@ -5060,7 +5061,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts">`+v.filename+`</td>
-                    <td class="hidden-xs">`+v.status+`</td>
+                    <td class="hidden-xs sabnzbd-`+cleanClass(v.status)+`">`+v.status+`</td>
                     <td class="downloader mouse" data-target="`+v.nzo_id+`" data-source="sabnzbd" data-action="`+action+`"><i class="fa fa-`+actionIcon+`"></i></td>
                     <td class="hidden-xs"><span class="label label-info">`+v.cat+`</span></td>
                     <td class="hidden-xs">`+v.size+`</td>
@@ -5080,7 +5081,7 @@ function buildDownloaderItem(array, source, type='none'){
                 history += `
                 <tr>
                     <td class="max-texts">`+v.name+`</td>
-                    <td class="hidden-xs">`+v.status+`</td>
+                    <td class="hidden-xs sabnzbd-`+cleanClass(v.status)+`">`+v.status+`</td>
                     <td class="hidden-xs"><span class="label label-info">`+v.category+`</span></td>
                     <td class="hidden-xs">`+v.size+`</td>
                     <td class="text-right">
@@ -5110,7 +5111,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts">`+v.NZBName+`</td>
-                    <td class="hidden-xs">`+v.Status+`</td>
+                    <td class="hidden-xs nzbget-`+cleanClass(v.Status)+`">`+v.Status+`</td>
                     <!--<td class="downloader mouse" data-target="`+v.NZBID+`" data-source="sabnzbd" data-action="`+action+`"><i class="fa fa-`+actionIcon+`"></i></td>-->
                     <td class="hidden-xs"><span class="label label-info">`+v.Category+`</span></td>
                     <td class="hidden-xs">`+humanFileSize(size,true)+`</td>
@@ -5131,7 +5132,7 @@ function buildDownloaderItem(array, source, type='none'){
                 history += `
                 <tr>
                     <td class="max-texts">`+v.NZBName+`</td>
-                    <td class="hidden-xs">`+v.Status+`</td>
+                    <td class="hidden-xs nzbget-`+cleanClass(v.Status)+`">`+v.Status+`</td>
                     <td class="hidden-xs"><span class="label label-info">`+v.Category+`</span></td>
                     <td class="hidden-xs">`+humanFileSize(size,true)+`</td>
                     <td class="text-right">
@@ -5194,7 +5195,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts">`+v.name+`</td>
-                    <td class="hidden-xs">`+status+`</td>
+                    <td class="hidden-xs transmission-`+cleanClass(status)+`">`+status+`</td>
                     <td class="hidden-xs">`+v.downloadDir+`</td>
                     <td class="hidden-xs">`+humanFileSize(v.totalSize,true)+`</td>
                     <td class="text-right">
@@ -5229,7 +5230,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="`+date+`">`+v.name+`</span></td>
-                    <td class="hidden-xs">`+v.status+`</td>
+                    <td class="hidden-xs rtorrent-`+cleanClass(v.status)+`">`+v.status+`</td>
                     <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="`+downTotal+`"><i class="fa fa-download"></i>&nbsp;`+download+`</span></td>
                     <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="`+upTotal+`"><i class="fa fa-upload"></i>&nbsp;`+upload+`</span></td>
                     <td class="hidden-xs">`+size+`</td>
@@ -5290,7 +5291,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts">`+v.name+`</td>
-                    <td class="hidden-xs qbit-`+status+`">`+status+`</td>
+                    <td class="hidden-xs qbit-`+cleanClass(status)+`">`+status+`</td>
                     <td class="hidden-xs">`+v.save_path+`</td>
                     <td class="hidden-xs">`+size+`</td>
                     <td class="text-right">
@@ -5321,7 +5322,7 @@ function buildDownloaderItem(array, source, type='none'){
                 queue += `
                 <tr>
                     <td class="max-texts">`+v.name+`</td>
-                    <td class="hidden-xs">`+v.state+`</td>
+                    <td class="hidden-xs deluge-`+cleanClass(v.state)+`">`+v.state+`</td>
                     <td class="hidden-xs">`+size+`</td>
                     <td class="hidden-xs"><i class="fa fa-download"></i>&nbsp;`+download+`</td>
                     <td class="hidden-xs"><i class="fa fa-upload"></i>&nbsp;`+upload+`</td>
@@ -7378,6 +7379,21 @@ function oAuthLoginNeededCheck() {
 function ipInfoSpan(ip){
     return '<span class="ipInfo mouse">'+ip+'</span>';
 }
+function checkToken(activate = false){
+    if(typeof activeInfo !== 'undefined'){
+        if(typeof activeInfo.settings.misc.uuid !== 'undefined'){
+            var token = getCookie('organizr_token_' + activeInfo.settings.misc.uuid);
+            if(token){
+                setTimeout(function(){ checkToken(true); }, 5000);
+            }else{
+                if(activate){
+                    local('set','message','Token Expired|You have been logged out|error');
+                    location.reload();
+                }
+            }
+        }
+    }
+}
 function launch(){
 	organizrConnect('api/?v1/launch_organizr').success(function (data) {
         try {
@@ -7425,6 +7441,7 @@ function launch(){
 		changeStyle(activeInfo.style);
 		changeTheme(activeInfo.theme);
 		setSSO();
+		checkToken();
 		switch (json.data.status.status) {
 			case "wizard":
 				buildWizard();

+ 7 - 0
js/version.json

@@ -236,5 +236,12 @@
     "new": "Remove tab has after logout|Added ChangeLog Link (#1292)|server auth redirect for traefik (#1240)|Edit wording for rutorrent urls|add ssl options to fopen on getCert function",
     "fixed": "Fixed Radarr V2 and V3 image issue|Workaround for Organizr become unresponsive after opening Tab Editor tab (#1319)|How to Reset the \"Color and Themes\" Section? (#1085)|Attempt to fix rutorrent issues with seedboxes|Attempt to fix 2.0.370 update not working (#1316)",
     "notes": "Framework changes below|Updated PHP Mailer|Updated JWT|Updated pusher|Updated LDAP|Updated guzzle|removed TLD Extract|Please report bugs in GitHub issues page|Updated language translations"
+  },
+  "2.0.408": {
+    "date": "2020-03-27 20:35",
+    "title": "Small Update",
+    "new": "Reworked Ombi Homepage ajax loading screen - faster now|added validate token api endpoint|sidebar rtl for tabs|added org token check and logout if not valid|Add IDs to all downloader Homepage item? (#1213)|Add toggle for login image|increase jdownloader timeout",
+    "fixed": "Fix Sidebar doesn't load tabs on iPhone running iOS 13.4+ (#1328)|Attempt to fix api call for image fetch for some users|check if HTTP_X_FORWARDED_SERVER is set|rtorrent/Nzbget API homepage modules and special character in password (#1309)|fix for nzbget connection|2FA login breaks with LastPass Chrome extension (#997)Ombi homepage item \"Item limit\" setting does not change the number of items displayed on the homepage (#1324)",
+    "notes": "Updated Dibi|Please report bugs in GitHub issues page|Updated language translations"
   }
 }