Browse Source

Added Ping - Change HP Legend - Fix Sab issue - LayerCake intergration

causefx 8 years ago
parent
commit
f39162cdba
8 changed files with 614 additions and 113 deletions
  1. 0 2
      ajax.php
  2. 1 1
      auth.php
  3. 43 3
      css/style.css
  4. 478 35
      functions.php
  5. 40 30
      homepage.php
  6. 12 36
      index.php
  7. 1 1
      js/custom.js
  8. 39 5
      settings.php

+ 0 - 2
ajax.php

@@ -107,8 +107,6 @@ switch ($_SERVER['REQUEST_METHOD']) {
 				$response['notify'] = sendResult($response, "check", $_POST['checkurl'], "CODE_SUCCESS", "CODE_ERROR");
 				break;
 			case 'use-invite':
-				//$response = inviteCodes("check", $_POST['invitecode']);
-				//$response = inviteCodes("use", $_POST['invitecode']);
 				if(inviteCodes("check", $_POST['invitecode'])){
 					$response = inviteCodes("use", $_POST['invitecode'], $_POST['inviteuser']);
 					$response['notify'] = sendResult(plexUserShare($_POST['inviteuser']), "check", $_POST['checkurl'], "INVITE_SUCCESS", "INVITE_ERROR");

+ 1 - 1
auth.php

@@ -1,5 +1,5 @@
 <?php
-$debug = false;
+$debug = false; //CAREFUL WHEN SETTING TO TRUE AS THIS OPENS AUTH UP
 require_once("user.php");
 $USER = new User("registration_callback");
 $ban = isset($_GET['ban']) ? strtoupper($_GET['ban']) : "";

+ 43 - 3
css/style.css

@@ -6,10 +6,50 @@
  *
 */
 /*@import url(https://fonts.googleapis.com/css?family=Roboto:100,400,500,300,700);*/
+.splash-item {
+	max-width: 100%;
+	-moz-transition: all 0.3s;
+	-webkit-transition: all 0.3s;
+	transition: all 0.3s;
+	opacity: .8 !important;
+}
+.splash-item:hover {
+	-moz-transform: scale(1.1);
+	-webkit-transform: scale(1.1);
+	transform: scale(1.1);
+	z-index: 10000000;
+	border-radius: 10px;
+	opacity: 1 !important;
+	box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+}
+.gn-menu i {
+	height: 18px;
+	width: 52px;
+}
+.active {
+	display: block;
+}
+.hidden {
+	display: none;
+}
+.errorz {
+	background-image: linear-gradient(red, red), linear-gradient(#d2d2d2, #d2d2d2);
+	outline: none;
+	animation: input-highlight .5s forwards;
+	box-shadow: none;
+	padding-left: 0;
+	border: 0;
+	border-radius: 0;
+	background-size: 0 2px,100% 1px;
+	background-repeat: no-repeat;
+	background-position: center bottom,center calc(100% - 1px);
+	background: transparent;
+	box-shadow: none;
+}
 .loop-animation {
-    animation-iteration-count: infinite;
-    -webkit-animation-iteration-count: infinite;
-    -moz-animation-iteration-count: infinite;
+	animation-iteration-count: infinite;
+	-webkit-animation-iteration-count: infinite;
+	-moz-animation-iteration-count: infinite;
     -o-animation-iteration-count: infinite;
 }
 .elip{

+ 478 - 35
functions.php

@@ -2,7 +2,7 @@
 
 // ===================================
 // Define Version
- define('INSTALLEDVERSION', '1.44');
+ define('INSTALLEDVERSION', '1.50');
 // ===================================
 use Kryptonit3\Sonarr\Sonarr;
 use Kryptonit3\SickRage\SickRage;
@@ -1460,6 +1460,19 @@ function upgradeCheck() {
 		$createConfigSuccess = createConfig($config);
 		unset($config);
 	}
+
+	// Upgrade to 1.50
+	$config = loadConfig();
+	if (isset($config['database_Location']) && (!isset($config['CONFIG_VERSION']) || $config['CONFIG_VERSION'] < '1.50')) {
+		// Upgrade database to latest version
+		updateSQLiteDB($config['database_Location'],'1.40');
+		
+		// Update Version and Commit
+		$config['CONFIG_VERSION'] = '1.50';
+		copy('config/config.php', 'config/config['.date('Y-m-d_H-i-s').'][1.40].bak.php');
+		$createConfigSuccess = createConfig($config);
+		unset($config);
+	}
 	
 	return true;
 }
@@ -1934,6 +1947,9 @@ function printTabRow($data) {
 			'user' => 'true',
 			'guest' => 'true',
 			'window' => 'false',
+			'splash' => 'true',
+			'ping' => 'false',
+			'ping_url' => '',
 			'defaultz' => '',
 		);
 	}
@@ -1986,6 +2002,35 @@ function printTabRow($data) {
 						'html' => '- '.translate('OR').' - <div class="input-group"><input data-placement="bottomRight" class="form-control material icp-auto'.($hidden?'-pend':'').'" id="$id" name="$name" value="$val" type="text" /><span class="input-group-addon"></span></div>',
 						'value' => $data['icon'],
 					),12,1,1).'
+					'.buildField(array(
+						'type' => 'text',
+						'id' => 'tab-'.$data['id'].'-ping_url',
+						'name' => 'ping_url['.$data['id'].']',
+						'placeholder' => 'host:port',
+						'labelTranslate' => 'PING_URL',
+						'value' => $data['ping_url'],
+					),12,2,1).'
+					'.buildField(array(
+						'type' => 'radio',
+						'labelTranslate' => 'DEFAULT',
+						'name' => 'defaultz['.$data['id'].']',
+						'value' => $data['defaultz'],
+						'onclick' => "$('[type=radio][id!=\''+this.id+'\']').each(function() { this.checked=false; });",
+					),12,1,1).'
+					'.buildField(array(
+						'type' => 'button',
+						'icon' => 'caret-square-o-down',
+                        'buttonType' => 'success',
+						'labelTranslate' => 'MORE',
+						'onclick' => "$('#tab-".$data['id']."-row').toggle();$(this).html($(this).html() == '<span class=\'btn-label\'><i class=\'fa fa-caret-square-o-down\'></i></span>More' ? '<span class=\'btn-label\'><i class=\'fa fa-caret-square-o-up\'></i></span>Less' : '<span class=\'btn-label\'><i class=\'fa fa-caret-square-o-down\'></i></span>More');",
+					),12,1,1).'
+					'.buildField(array(
+						'type' => 'button',
+						'icon' => 'trash',
+                        'buttonType' => 'danger',
+						'labelTranslate' => 'REMOVE',
+						'onclick' => "$(this).parents('li').remove();",
+					),12,1,1).'</div><div id = "tab-'.$data['id'].'-row" class = "row animated slideInUp" style = "display:none;" ><div></div>
 					'.buildField(array(
 						'type' => 'checkbox',
 						'labelTranslate' => 'ACTIVE',
@@ -2014,18 +2059,18 @@ function printTabRow($data) {
 						'value' => $data['window'],
 					),12,1,1).'
 					'.buildField(array(
-						'type' => 'radio',
-						'labelTranslate' => 'DEFAULT',
-						'name' => 'defaultz['.$data['id'].']',
-						'value' => $data['defaultz'],
-						'onclick' => "$('[type=radio][id!=\''+this.id+'\']').each(function() { this.checked=false; });",
+						'type' => 'checkbox',
+						'labelTranslate' => 'SPLASH',
+						'colour' => 'success',
+						'name' => 'splash['.$data['id'].']',
+						'value' => $data['splash'],
 					),12,1,1).'
 					'.buildField(array(
-						'type' => 'button',
-						'icon' => 'trash',
-                        'buttonType' => 'danger',
-						'labelTranslate' => 'REMOVE',
-						'onclick' => "$(this).parents('li').remove();",
+						'type' => 'checkbox',
+						'labelTranslate' => 'PING',
+						'colour' => 'success',
+						'name' => 'ping['.$data['id'].']',
+						'value' => $data['ping'],
 					),12,1,1).'
 				</div>
 			</tab>
@@ -2106,7 +2151,10 @@ function createSQLiteDB($path = false) {
 			`guest`	TEXT,
 			`icon`	TEXT,
 			`iconurl`	TEXT,
-			`window`	TEXT
+			`window`	TEXT,
+			`splash`	TEXT,
+			`ping`		TEXT,
+			`ping_url`	TEXT
 		);');
 		
 		// Create Options
@@ -2479,18 +2527,18 @@ function sabnzbdConnect($list = 'queue') {
         $downloadStatus = $child['status'];
         
         $gotNZB[] = '<tr>
-                        <td>'.$downloadName.'</td>
-                        <td>'.$downloadStatus.'</td>
-                        <td>'.$downloadCategory.'</td>
-                        <td>
-                            <div class="progress">
-                                <div class="progress-bar progress-bar-success '.$progressBar.'" role="progressbar" aria-valuenow="'.$downloadPercent.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$downloadPercent.'%">
-                                    <p class="text-center">'.round($downloadPercent).'%</p>
-                                    <span class="sr-only">'.$downloadPercent.'% Complete</span>
-                                </div>
-                            </div>
-                        </td>
-                    </tr>';
+						<td class="col-xs-7 nzbtable-file-row">'.$downloadName.'</td>
+						<td class="col-xs-2 nzbtable nzbtable-row">'.$downloadStatus.'</td>
+						<td class="col-xs-1 nzbtable nzbtable-row">'.$downloadCategory.'</td>
+						<td class="col-xs-2 nzbtable nzbtable-row">
+							<div class="progress">
+								<div class="progress-bar progress-bar-success '.$progressBar.'" role="progressbar" aria-valuenow="'.$downloadPercent.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$downloadPercent.'%">
+									<p class="text-center">'.round($downloadPercent).'%</p>
+									<span class="sr-only">'.$downloadPercent.'% Complete</span>
+								</div>
+							</div>
+						</td>
+					</tr>';
     }
     
 	if ($gotNZB) {
@@ -2518,10 +2566,10 @@ function updateTabs($tabs) {
 			if (!$value || !isset($tabs['url']) || !$tabs['url'][$key]) { continue; }
 			$totalValid++;
 			$fields = array();
-			foreach(array('id','name','url','icon','iconurl','order') as $v) {
+			foreach(array('id','name','url','icon','iconurl','order','ping_url') as $v) {
 				if (isset($tabs[$v]) && isset($tabs[$v][$key])) { $fields[$v] = $tabs[$v][$key]; }
 			}
-			foreach(array('active','user','guest','defaultz','window') as $v) {
+			foreach(array('active','user','guest','defaultz','window','splash','ping') as $v) {
 				if (isset($tabs[$v]) && isset($tabs[$v][$key])) { $fields[$v] = ($tabs[$v][$key]!=='false'?'true':'false'); }
 			}
 			$GLOBALS['file_db']->query('INSERT INTO tabs (`'.implode('`,`',array_keys($fields)).'`) VALUES (\''.implode("','",$fields).'\');');
@@ -3052,17 +3100,25 @@ function strip($string){
 }
 
 function writeLog($type, $message){
+	if(filesize("org.log") > 500000){
+		rename('org.log','org['.date('Y-m-d').'].log');
+		$message2 = date("Y-m-d H:i:s")."|".$type."|".strip("ORG LOG: Creating backup of org.log to org[".date('Y-m-d')."].log ")."\n";
+		file_put_contents("org.log", $message2, FILE_APPEND | LOCK_EX);
+
+	}
     $message = date("Y-m-d H:i:s")."|".$type."|".strip($message)."\n";
     file_put_contents("org.log", $message, FILE_APPEND | LOCK_EX);
 }
 
 function readLog(){
-    $log = file("org.log");
+    $log = file("org.log",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
     $log = array_reverse($log);
     foreach($log as $line){
-        $line = explode("|", strip($line));
-        $line[1] = ($line[1] == "error") ? '<span class="label label-danger">Error</span>' : '<span class="label label-primary">Success</span>';
-        echo "<tr><td>".$line[0]."</td><td>".$line[2]."</td><td>".$line[1]."</td></tr>";
+		if(substr_count($line, '|') == 2){
+			$line = explode("|", strip($line));
+			$line[1] = ($line[1] == "error") ? '<span class="label label-danger">Error</span>' : '<span class="label label-primary">Success</span>';
+			echo "<tr><td>".$line[0]."</td><td>".$line[2]."</td><td>".$line[1]."</td></tr>";
+		}
     }
 }
 
@@ -3666,26 +3722,32 @@ function plexJoin($username, $email, $password){
 	$usernameError = (!empty($json['errors']['username']) ? $json['errors']['username'][0] : false);
 	$emailError = (!empty($json['errors']['email']) ? $json['errors']['email'][0] : false);
 	$passwordError = (!empty($json['errors']['password']) ? $json['errors']['password'][0] : false);
+	$errorMessage = "";
+	if($errors){
+		if($usernameError){ $errorMessage .= "[Username Error: ". $usernameError ."]"; }
+		if($emailError){ $errorMessage .= "[Email Error: ". $emailError ."]"; }
+		if($passwordError){ $errorMessage .= "[Password Error: ". $passwordError ."]"; }
+	}
 	
 	switch ($api['http_code']['http_code']){
 		case 400:
-			writeLog("error", "PLEX JOIN: $username already has access to the shared libraries");
+			writeLog("error", "PLEX JOIN: Error: ".$api['http_code']['http_code']." $username already has access to the shared libraries $errorMessage");
 			break;
 		case 401:
-			writeLog("error", "PLEX JOIN: invalid Plex Token");
+			writeLog("error", "PLEX JOIN: Error: ".$api['http_code']['http_code']." invalid Plex Token $errorMessage");
 			break;
 		case 422:
-			writeLog("error", "PLEX JOIN: user info error");
+			writeLog("error", "PLEX JOIN: Error: ".$api['http_code']['http_code']." user info error $errorMessage");
 			break;
 		case 429:
-			writeLog("error", "PLEX JOIN: too many requests to plex.tv please try later");
+			writeLog("error", "PLEX JOIN: Error: ".$api['http_code']['http_code']." too many requests to plex.tv please try later $errorMessage");
 			break;
 		case 200:
 		case 201:
 			writeLog("success", "PLEX JOIN: $username now has access to your Plex Library");
 			break;
 		default:
-			writeLog("error", "PLEX JOIN: unknown error, Error: ".$api['http_code']['http_code']);
+			writeLog("error", "PLEX JOIN: unknown error, $errorMessage Error: ".$api['http_code']['http_code']);
 	}
 	//prettyPrint($api);
 	//prettyPrint(json_decode($api['content'], true));
@@ -3967,6 +4029,387 @@ function backupDB(){
 	}
 }
 
+class Ping {
+
+	private $host;
+	private $ttl;
+	private $timeout;
+	private $port = 80;
+	private $data = 'Ping';
+	private $commandOutput;
+
+	/**
+	* Called when the Ping object is created.
+	*
+	* @param string $host
+	*   The host to be pinged.
+	* @param int $ttl
+	*   Time-to-live (TTL) (You may get a 'Time to live exceeded' error if this
+	*   value is set too low. The TTL value indicates the scope or range in which
+	*   a packet may be forwarded. By convention:
+	*     - 0 = same host
+	*     - 1 = same subnet
+	*     - 32 = same site
+	*     - 64 = same region
+	*     - 128 = same continent
+	*     - 255 = unrestricted
+	* @param int $timeout
+	*   Timeout (in seconds) used for ping and fsockopen().
+	* @throws \Exception if the host is not set.
+	*/
+	public function __construct($host, $ttl = 255, $timeout = 10) {
+	if (!isset($host)) {
+		throw new \Exception("Error: Host name not supplied.");
+	}
+
+	$this->host = $host;
+	$this->ttl = $ttl;
+	$this->timeout = $timeout;
+	}
+
+	/**
+	* Set the ttl (in hops).
+	*
+	* @param int $ttl
+	*   TTL in hops.
+	*/
+	public function setTtl($ttl) {
+	$this->ttl = $ttl;
+	}
+
+	/**
+	* Get the ttl.
+	*
+	* @return int
+	*   The current ttl for Ping.
+	*/
+	public function getTtl() {
+	return $this->ttl;
+	}
+
+	/**
+	* Set the timeout.
+	*
+	* @param int $timeout
+	*   Time to wait in seconds.
+	*/
+	public function setTimeout($timeout) {
+	$this->timeout = $timeout;
+	}
+
+	/**
+	* Get the timeout.
+	*
+	* @return int
+	*   Current timeout for Ping.
+	*/
+	public function getTimeout() {
+	return $this->timeout;
+	}
+
+	/**
+	* Set the host.
+	*
+	* @param string $host
+	*   Host name or IP address.
+	*/
+	public function setHost($host) {
+	$this->host = $host;
+	}
+
+	/**
+	* Get the host.
+	*
+	* @return string
+	*   The current hostname for Ping.
+	*/
+	public function getHost() {
+	return $this->host;
+	}
+
+	/**
+	* Set the port (only used for fsockopen method).
+	*
+	* Since regular pings use ICMP and don't need to worry about the concept of
+	* 'ports', this is only used for the fsockopen method, which pings servers by
+	* checking port 80 (by default).
+	*
+	* @param int $port
+	*   Port to use for fsockopen ping (defaults to 80 if not set).
+	*/
+	public function setPort($port) {
+	$this->port = $port;
+	}
+
+	/**
+	* Get the port (only used for fsockopen method).
+	*
+	* @return int
+	*   The port used by fsockopen pings.
+	*/
+	public function getPort() {
+	return $this->port;
+	}
+
+	/**
+	* Return the command output when method=exec.
+	* @return string
+	*/
+	public function getCommandOutput(){
+	return $this->commandOutput;
+	}
+
+	/**
+	* Matches an IP on command output and returns.
+	* @return string
+	*/
+	public function getIpAddress() {
+	$out = array();
+	if (preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $this->commandOutput, $out)){
+		return $out[0];
+	}
+	return null;
+	}
+
+	/**
+	* Ping a host.
+	*
+	* @param string $method
+	*   Method to use when pinging:
+	*     - exec (default): Pings through the system ping command. Fast and
+	*       robust, but a security risk if you pass through user-submitted data.
+	*     - fsockopen: Pings a server on port 80.
+	*     - socket: Creates a RAW network socket. Only usable in some
+	*       environments, as creating a SOCK_RAW socket requires root privileges.
+	*
+	* @throws InvalidArgumentException if $method is not supported.
+	*
+	* @return mixed
+	*   Latency as integer, in ms, if host is reachable or FALSE if host is down.
+	*/
+	public function ping($method = 'exec') {
+	$latency = false;
+
+	switch ($method) {
+		case 'exec':
+		$latency = $this->pingExec();
+		break;
+
+		case 'fsockopen':
+		$latency = $this->pingFsockopen();
+		break;
+
+		case 'socket':
+		$latency = $this->pingSocket();
+		break;
+
+		default:
+		throw new \InvalidArgumentException('Unsupported ping method.');
+	}
+
+	// Return the latency.
+	return $latency;
+	}
+
+	/**
+	* The exec method uses the possibly insecure exec() function, which passes
+	* the input to the system. This is potentially VERY dangerous if you pass in
+	* any user-submitted data. Be SURE you sanitize your inputs!
+	*
+	* @return int
+	*   Latency, in ms.
+	*/
+	private function pingExec() {
+	$latency = false;
+
+	$ttl = escapeshellcmd($this->ttl);
+	$timeout = escapeshellcmd($this->timeout);
+	$host = escapeshellcmd($this->host);
+
+	// Exec string for Windows-based systems.
+	if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+		// -n = number of pings; -i = ttl; -w = timeout (in milliseconds).
+		$exec_string = 'ping -n 1 -i ' . $ttl . ' -w ' . ($timeout * 1000) . ' ' . $host;
+	}
+	// Exec string for Darwin based systems (OS X).
+	else if(strtoupper(PHP_OS) === 'DARWIN') {
+		// -n = numeric output; -c = number of pings; -m = ttl; -t = timeout.
+		$exec_string = 'ping -n -c 1 -m ' . $ttl . ' -t ' . $timeout . ' ' . $host;
+	}
+	// Exec string for other UNIX-based systems (Linux).
+	else {
+		// -n = numeric output; -c = number of pings; -t = ttl; -W = timeout
+		$exec_string = 'ping -n -c 1 -t ' . $ttl . ' -W ' . $timeout . ' ' . $host . ' 2>&1';
+	}
+
+	exec($exec_string, $output, $return);
+
+	// Strip empty lines and reorder the indexes from 0 (to make results more
+	// uniform across OS versions).
+	$this->commandOutput = implode($output, '');
+	$output = array_values(array_filter($output));
+
+	// If the result line in the output is not empty, parse it.
+	if (!empty($output[1])) {
+		// Search for a 'time' value in the result line.
+		$response = preg_match("/time(?:=|<)(?<time>[\.0-9]+)(?:|\s)ms/", $output[1], $matches);
+
+		// If there's a result and it's greater than 0, return the latency.
+		if ($response > 0 && isset($matches['time'])) {
+		$latency = round($matches['time'], 2);
+		}
+	}
+
+	return $latency;
+	}
+
+	/**
+	* The fsockopen method simply tries to reach the host on a port. This method
+	* is often the fastest, but not necessarily the most reliable. Even if a host
+	* doesn't respond, fsockopen may still make a connection.
+	*
+	* @return int
+	*   Latency, in ms.
+	*/
+	private function pingFsockopen() {
+	$start = microtime(true);
+	// fsockopen prints a bunch of errors if a host is unreachable. Hide those
+	// irrelevant errors and deal with the results instead.
+	$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
+	if (!$fp) {
+		$latency = false;
+	}
+	else {
+		$latency = microtime(true) - $start;
+		$latency = round($latency * 1000, 2);
+	}
+	return $latency;
+	}
+
+	/**
+	* The socket method uses raw network packet data to try sending an ICMP ping
+	* packet to a server, then measures the response time. Using this method
+	* requires the script to be run with root privileges, though, so this method
+	* only works reliably on Windows systems and on Linux servers where the
+	* script is not being run as a web user.
+	*
+	* @return int
+	*   Latency, in ms.
+	*/
+	private function pingSocket() {
+	// Create a package.
+	$type = "\x08";
+	$code = "\x00";
+	$checksum = "\x00\x00";
+	$identifier = "\x00\x00";
+	$seq_number = "\x00\x00";
+	$package = $type . $code . $checksum . $identifier . $seq_number . $this->data;
+
+	// Calculate the checksum.
+	$checksum = $this->calculateChecksum($package);
+
+	// Finalize the package.
+	$package = $type . $code . $checksum . $identifier . $seq_number . $this->data;
+
+	// Create a socket, connect to server, then read socket and calculate.
+	if ($socket = socket_create(AF_INET, SOCK_RAW, 1)) {
+		socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array(
+		'sec' => 10,
+		'usec' => 0,
+		));
+		// Prevent errors from being printed when host is unreachable.
+		@socket_connect($socket, $this->host, null);
+		$start = microtime(true);
+		// Send the package.
+		@socket_send($socket, $package, strlen($package), 0);
+		if (socket_read($socket, 255) !== false) {
+		$latency = microtime(true) - $start;
+		$latency = round($latency * 1000, 2);
+		}
+		else {
+		$latency = false;
+		}
+	}
+	else {
+		$latency = false;
+	}
+	// Close the socket.
+	socket_close($socket);
+	return $latency;
+	}
+
+	/**
+	* Calculate a checksum.
+	*
+	* @param string $data
+	*   Data for which checksum will be calculated.
+	*
+	* @return string
+	*   Binary string checksum of $data.
+	*/
+	private function calculateChecksum($data) {
+	if (strlen($data) % 2) {
+		$data .= "\x00";
+	}
+
+	$bit = unpack('n*', $data);
+	$sum = array_sum($bit);
+
+	while ($sum >> 16) {
+		$sum = ($sum >> 16) + ($sum & 0xffff);
+	}
+
+	return pack('n*', ~$sum);
+	}
+}
+
+function ping($pings, $type = "string") {
+	$ping = new Ping("");
+	$ping->setTtl(128);
+	$ping->setTimeout(2);
+	switch ($type){
+		case "array":
+			$results = [];
+			foreach ($pings as $k => $v) {
+				if(strpos($v, ':') !== false){
+					$domain = explode(':', $v)[0];
+					$port = explode(':', $v)[1];
+					$ping->setHost($domain);
+					$ping->setPort($port);
+					$latency = $ping->ping('fsockopen');
+				}else{
+					$ping->setHost($v);
+					$latency = $ping->ping();
+				}
+				if ($latency || $latency === 0) {
+					$results[$k] = $latency;
+				} else {
+					$results[$k] = 0;
+				}
+			}
+			break;
+		case "string":
+			if(strpos($pings, ':') !== false){
+				$domain = explode(':', $pings)[0];
+				$port = explode(':', $pings)[1];
+				$ping->setHost($domain);
+				$ping->setPort($port);
+				$latency = $ping->ping('fsockopen');
+			}else{
+				$ping->setHost($pings);
+				$latency = $ping->ping();
+			}
+			if ($latency || $latency === 0) {
+				$results = $latency;
+			} else {
+				$results = 0;
+			}
+			break;
+	}
+
+	return $results;
+}
+
 function orgEmail($header = "Message From Admin", $title = "Important Message", $user = "Organizr User", $mainMessage = "", $button = null, $buttonURL = null, $subTitle = "", $subMessage = ""){
 	$path = getServerPath();
 	return '

+ 40 - 30
homepage.php

@@ -45,6 +45,7 @@ foreach(loadAppearance() as $key => $value) {
         <link rel="stylesheet" href="bower_components/mdi/css/materialdesignicons.min.css?v=<?php echo INSTALLEDVERSION; ?>">
         <link rel="stylesheet" href="bower_components/google-material-color/dist/palette.css?v=<?php echo INSTALLEDVERSION; ?>">
         <link rel="stylesheet" type="text/css" href="bower_components/slick/slick.css?v=<?php echo INSTALLEDVERSION; ?>">
+        <link rel="stylesheet" href="bower_components/sweetalert/dist/sweetalert.css"
         <!-- Add the slick-theme.css if you want default styling -->
        
 
@@ -65,6 +66,7 @@ foreach(loadAppearance() as $key => $value) {
 		
 		<!--Other-->
 		<script src="js/ajax.js?v=<?php echo INSTALLEDVERSION; ?>"></script>
+        <script src="bower_components/sweetalert/dist/sweetalert.min.js"></script>
 		
         <!--[if lt IE 9]>
         <script src="bower_components/html5shiv/dist/html5shiv.min.js"></script>
@@ -192,9 +194,27 @@ foreach(loadAppearance() as $key => $value) {
         <div class="main-wrapper" style="position: initial;">
             <div id="content" class="container-fluid">
                 <br/>
- 
-                <?php if (qualifyUser(HOMEPAGENOTICEAUTH) && HOMEPAGENOTICETITLE && HOMEPAGENOTICETYPE && HOMEPAGENOTICEMESSAGE && HOMEPAGENOTICELAYOUT) { echo buildHomepageNotice(HOMEPAGENOTICELAYOUT, HOMEPAGENOTICETYPE, HOMEPAGENOTICETITLE, HOMEPAGENOTICEMESSAGE); } ?>
                 
+                <?php if (qualifyUser(HOMEPAGENOTICEAUTH) && HOMEPAGENOTICETITLE && HOMEPAGENOTICETYPE && HOMEPAGENOTICEMESSAGE && HOMEPAGENOTICELAYOUT) { echo buildHomepageNotice(HOMEPAGENOTICELAYOUT, HOMEPAGENOTICETYPE, HOMEPAGENOTICETITLE, HOMEPAGENOTICEMESSAGE); } ?>
+                <?php if((PLEXSEARCH == "true" && qualifyUser(PLEXHOMEAUTH))) { ?>
+                <div id="searchPlexRow" class="row">
+                    <div class="col-lg-12">
+                        <div class="content-box box-shadow big-box todo-list">                        
+                            <form id="plexSearchForm" onsubmit="return false;" autocomplete="off">
+                                <div class="">
+                                    <div class="input-group">
+                                        <div style="border-radius: 25px 0 0 25px; border:0" class="input-group-addon gray-bg"><i class="fa fa-search white"></i></div>
+                                        <input id="searchInput" type="text" style="border-radius: 0;" autocomplete="off" name="search-title" class="form-control input-group-addon gray-bg" placeholder="Media Search">
+										<div id="clearSearch" style="border-radius: 0 25px 25px 0;border:0; cursor: pointer;" class="input-group-addon gray-bg"><i class="fa fa-close white"></i></div>
+                                        <button style="display:none" id="plexSearchForm_submit" class="btn btn-primary waves"></button>
+                                    </div>
+                                </div>
+                            </form>
+                            <div id="resultshere" class="table-responsive"></div>
+                        </div>
+                    </div>
+                </div>
+                <?php } ?>
                 <?php if (qualifyUser(HOMEPAGECUSTOMHTML1AUTH) && HOMEPAGECUSTOMHTML1) { echo "<div>" . HOMEPAGECUSTOMHTML1 . "</div>"; } ?>
 
                 <?php if(SPEEDTEST == "true"){ ?>
@@ -333,26 +353,7 @@ foreach(loadAppearance() as $key => $value) {
                     </div>
                 </div>
                 <?php } ?>
-                <?php if((PLEXSEARCH == "true" && qualifyUser(PLEXHOMEAUTH))) { ?>
-                <div id="searchPlexRow" class="row">
-                    <div class="col-lg-12">
-                        <div class="content-box box-shadow big-box todo-list">                        
-                            <form id="plexSearchForm" onsubmit="return false;" autocomplete="off">
-                                <div class="">
-                                    <div class="input-group">
-                                        <div style="border-radius: 25px 0 0 25px; border:0" class="input-group-addon gray-bg"><i class="fa fa-search white"></i></div>
-                                        <input id="searchInput" type="text" style="border-radius: 0;" autocomplete="off" name="search-title" class="form-control input-group-addon gray-bg" placeholder="Media Search">
-										<div id="clearSearch" style="border-radius: 0 25px 25px 0;border:0; cursor: pointer;" class="input-group-addon gray-bg"><i class="fa fa-close white"></i></div>
-                                        <button style="display:none" id="plexSearchForm_submit" class="btn btn-primary waves"></button>
-                                    </div>
-                                </div>
-                            </form>
-                            <div id="resultshere" class="table-responsive"></div>
-                        </div>
-                    </div>
-                </div>
-                <?php } ?>
-                
+                                
                 <?php if((NZBGETURL != "" && qualifyUser(NZBGETHOMEAUTH)) || (SABNZBDURL != "" && qualifyUser(SABNZBDHOMEAUTH))) { ?>
                 <div id="downloadClientRow" class="row">
                     <div class="col-xs-12 col-md-12">
@@ -458,12 +459,8 @@ foreach(loadAppearance() as $key => $value) {
                                 <?php if(RADARRURL != ""){ echo '<option value="film">Movies</option>'; }?>
                                 <?php if(SONARRURL != "" || SICKRAGEURL != ""){ echo '<option value="tv">TV Shows</option>'; }?>
                                 <?php if(HEADPHONESURL != ""){ echo '<option value="music">Music</option>'; }?>
-                            </select>
-
-                            <span class="label label-primary well-sm">Available</span>
-                            <span class="label label-danger well-sm">Unavailable</span>
-                            <span class="label indigo-bg well-sm">Unreleased</span>
-                            <span class="label light-blue-bg well-sm">Premier</span>
+                            </select>&nbsp;
+                            <span class="swal-legend label label-primary well-sm">Legend</span>
                         </div>
                         <!--
                         <div class="pull-right">
@@ -488,6 +485,14 @@ foreach(loadAppearance() as $key => $value) {
             </div>    
         </div>
         <script>
+        $(".swal-legend").click(function () {
+            swal({
+                title: "Calendar Legend",
+                text: '<span class="label label-primary well-sm">Available</span>&nbsp;<span class="label label-danger well-sm">Unavailable</span>&nbsp;<span class="label indigo-bg well-sm">Unreleased</span>&nbsp;<span class="label light-blue-bg well-sm">Premier</span>',
+                html: true,
+                confirmButtonColor: "#63A8EB"
+            });
+        });
         $('.close-btn').click(function(e){
             var closedBox = $(this).closest('div.content-box').remove();
             e.preventDefault();
@@ -593,7 +598,7 @@ foreach(loadAppearance() as $key => $value) {
 				var isActive = parent.$("div[data-content-name^='<?php echo strtolower(PLEXTABNAME);?>']");
 				var activeFrame = isActive.children('iframe');
 				if(isActive.length === 1){
-					activeFrame.attr("src", $(this).attr("href"));
+					activeFrame.attr("src", $(this).attr("location"));
 					parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
 				}else{
 					parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
@@ -759,10 +764,15 @@ foreach(loadAppearance() as $key => $value) {
                     .slick('slickFilter' , '.'+filter );
             });
 
-            $("body").niceScroll({
+            /*$("body").niceScroll({
                 railpadding: {top:0,right:0,left:0,bottom:0},
                 scrollspeed: 30,
                 mousescrollstep: 60
+            });*/
+            $("body").niceScroll({
+                //cursorwidth: "12px"
+                scrollspeed: 30,
+                mousescrollstep: 60
             });
             $(".table-responsive").niceScroll({
                 railpadding: {top:0,right:0,left:0,bottom:0},

+ 12 - 36
index.php

@@ -245,27 +245,17 @@ if(file_exists("images/settings2.png")) : $iconRotate = "false"; $settingsIcon =
 		<script src="js/push.js"></script>
 		<!--Other-->
 		<script src="js/ajax.js?v=<?php echo INSTALLEDVERSION; ?>"></script>
+		<!--<script src="js/piwik.js?v=<?php echo INSTALLEDVERSION; ?>"></script>-->
 		<!--[if lt IE 9]>
 		<script src="bower_components/html5shiv/dist/html5shiv.min.js"></script>
 		<script src="bower_components/respondJs/dest/respond.min.js"></script>
 		<![endif]-->
 	</head>
 	<style>
-		.splash-item {
-			max-width: 100%;
-			-moz-transition: all 0.3s;
-			-webkit-transition: all 0.3s;
-			transition: all 0.3s;
-			opacity: .8 !important;
-		}
-		.splash-item:hover {
-			-moz-transform: scale(1.1);
-			-webkit-transform: scale(1.1);
-			transform: scale(1.1);
-			z-index: 10000000;
-			border-radius: 10px;
-			opacity: 1 !important;
-			box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+		.ping-success {
+			background: green !important;
+		}.ping-warning {
+			background: red !important;
 		}
 		.TabOpened {
 			-webkit-filter: drop-shadow(0px 0px 5px <?=$topbartext;?>);
@@ -281,9 +271,6 @@ if(file_exists("images/settings2.png")) : $iconRotate = "false"; $settingsIcon =
 			background: <?=$sidebar;?>;
 		}.gn-menu-wrapper {
 			background: <?=$sidebar;?>;
-		}.gn-menu i {
-			height: 18px;
-			width: 52px;
 		}.la-timer.la-dark {
 			color: <?=$topbartext;?>
 		}.refresh-preloader {
@@ -308,23 +295,6 @@ if(file_exists("images/settings2.png")) : $iconRotate = "false"; $settingsIcon =
 		}.gn-menu li.rightActive > a {
 			background: <?=$hoverbg;?>;
 			border-radius: 100px 0 0 100px;
-		}.active {
-			display: block;
-		}.hidden {
-			display: none;
-		}.errorz {
-			background-image: linear-gradient(red, red), linear-gradient(#d2d2d2, #d2d2d2);
-			outline: none;
-			animation: input-highlight .5s forwards;
-			box-shadow: none;
-			padding-left: 0;
-			border: 0;
-			border-radius: 0;
-			background-size: 0 2px,100% 1px;
-			background-repeat: no-repeat;
-			background-position: center bottom,center calc(100% - 1px);
-			background: transparent;
-			box-shadow: none;
 		}.gn-menu li.active i.fa {
 			color: <?=$activetabicon;?>;
 		}.gn-menu li i.fa {
@@ -486,9 +456,15 @@ if(file_exists("images/settings2.png")) : $iconRotate = "false"; $settingsIcon =
 											<i style="font-size: 19px; padding: 0 10px; font-size: 19px;">
 												<span id="<?=$row['url'];?>s" class="badge badge-success" style="position: absolute;z-index: 100;right: 0px;"></span>
 												<img src="<?=$row['iconurl'];?>" style="height: 30px; width: 30px; margin-top: -2px;">
+												<?php if($row['ping'] == "true" && $row['ping_url']){
+													if(ping($row['ping_url']) !== 0){ $class = 'success'; }else{ $class = "warning"; }
+													echo '<span id="ping-'.$row['url'].'" class="badge ping-'.$class.' '.ping($row['ping_url']).'" style="position: absolute;z-index: 100;right: 0px; padding: 0px 0px;margin-top: 30px;font-size: 10px;">&nbsp;</span>';
+												}?>
 											</i>
 										<?php else : ?>
-											<i class="fa <?=$row['icon'];?> fa-lg"><span id="<?=$row['url'];?>s" class="badge badge-success" style="position: absolute;z-index: 100;right: 0px;"></span></i>
+											<i class="fa <?=$row['icon'];?> fa-lg">
+												<span id="<?=$row['url'];?>s" class="badge badge-success" style="position: absolute;z-index: 100;right: 0px;"></span>
+											</i>
 										<?php endif; ?>
 										<?=$row['name'];?>
 									</a>

+ 1 - 1
js/custom.js

@@ -81,7 +81,7 @@ $(document).ready(function(){
 		},
 		uploadFile: {
 			url: "./ajax.php?a=upload-images",
-			data: null,
+			data: {},
 			type: 'POST',
 			enctype: 'multipart/form-data',
 			synchron: true,

+ 39 - 5
settings.php

@@ -114,6 +114,7 @@ if(SLIMBAR == "true") {
 		
         <!--Other-->
         <script src="js/ajax.js?v=<?php echo INSTALLEDVERSION; ?>"></script>
+        <!--<script src="js/piwik.js?v=<?php echo INSTALLEDVERSION; ?>"></script>-->
 
         <!--Notification-->
         <script src="js/notifications/notificationFx.js"></script>
@@ -470,6 +471,21 @@ echo buildSettings(
 			<li class="chooseTheme" id="monokaiTheme" style="border: 1px #AD80FD; border-style: groove; background: #333333; border-radius: 5px; margin: 5px;"><a style="color: #66D9EF !important;" href="#">Monokai<span><img class="themeImage" src="images/themes/monokai.png"></span></a></li>
 			<li class="chooseTheme" id="thejokerTheme" style="border: 1px #CCC6CC; border-style: groove; background: #000000; border-radius: 5px; margin: 5px;"><a style="color: #CCCCCC !important;" href="#">The Joker<span><img class="themeImage" src="images/themes/joker.png"></span></a></li>
 			<li class="chooseTheme" id="redTheme" style="border: 1px #eb6363; border-style: groove; background: #eb6363; border-radius: 5px; margin: 5px;"><a style="color: #FFFFFF !important;" href="#">Original Red<span><img class="themeImage" src="images/themes/original.png"></span></a></li>
+		</ul>
+							',
+                        ),
+                        array(
+							'type' => 'button',
+							'labelTranslate' => 'LAYER#CAKE',
+							'icon' => 'birthday-cake',
+							'id' => 'layerCake',
+							'buttonType' => 'dark',
+							'buttonDrop' => '
+        <ul class="dropdown-menu gray-bg">
+        <p class="text-center">Powered by Leram</p>
+			<li id="layerCakeDefault" data-toggle="tooltip" data-placement="top" title="" data-original-title="listen to the story im about to tell you it stated liek this"  style="border: 1px #FFFFFF; border-style: groove; background: #000000; border-radius: 5px; margin: 5px;"><a style="color: #E49F0C !important;" onclick="layerCake(\'Default\',\'Live\');$(\'#customCSS_id\').attr(\'data-changed\', \'true\');" href="#">Default</a></li>
+			<li id="layerCakeCustom" data-toggle="tooltip" data-placement="top" title="" data-original-title="listen to the story im about to tell you it stated liek this" style="border: 1px #E5A00D; border-style: groove; background: #282A2D; border-radius: 5px; margin: 5px;"><a style="color: #E5A00D !important;" onclick="layerCake(\'Custom\',\'Live\');$(\'#customCSS_id\').attr(\'data-changed\', \'true\');" href="#">Custom</a></li>
+			<li id="layerCakeStatic" style="border: 1px #E5A00D; border-style: groove; background: #282A2D; border-radius: 5px; margin: 5px;"><a style="color: #E5A00D !important;" onclick="layerCake(\'Static\',\'CSS\');$(\'#customCSS_id\').attr(\'data-changed\', \'true\');" href="#">Static</a></li>
 		</ul>
 							',
 						),
@@ -1482,7 +1498,8 @@ echo buildSettings(
 						'value' => SMTPHOSTTYPE,
 						'options' => array(
 							'ssl' => 'ssl',
-							'tls' => 'tls',
+                            'tls' => 'tls',
+                            'off' => 'false',
 						),
 					),
 					array(
@@ -2497,6 +2514,8 @@ echo buildSettings(
         <?php endif; ?>
 
 		<script>
+            //Tooltips
+            $('[data-toggle="tooltip"]').tooltip();
             //IP INFO
             $(".ipInfo").click(function(){
                 $.getJSON("https://ipinfo.io/"+$(this).text()+"/?token=<?php echo IPINFOTOKEN;?>", function (response) {
@@ -3117,8 +3136,6 @@ echo buildSettings(
                 }
             });
 
-        
-     
             $("#open-info, #open-users, #open-logs, #open-advanced, #open-homepage, #open-colors, #open-tabs, #open-donate, #open-invites ").on("click",function (e) {
                 $(".email-content").removeClass("email-active");
                 $('html').removeClass("overhid");
@@ -3143,8 +3160,6 @@ echo buildSettings(
                 e.preventDefault();
             });
           
-         
-			
             function checkGithub() {
                 $.ajax({
                     type: "GET",
@@ -3189,6 +3204,25 @@ echo buildSettings(
                     }
                 });
             }
+
+            function layerCake(type, path) {
+                $.ajax({
+                    type: "GET",
+                    url: "ajax.php?a=show-file&file=https://raw.githubusercontent.com/leram84/layer.Cake/master/"+path+"/"+type+".css",
+                    dataType: "text",
+                    success: function(github) {
+                        cssTab = $("a[href^='#tab-theme_css']");
+                        cssTab.trigger("click");
+                        $('#customCSS_id').text(github);
+                        swal({
+                            title: "Loaded Layer#Cake "+type,
+                            text: '<h2>Awesome Sauce!</h2><p>Now that you have enabled Layer#Cake, edit the colors here and then hit Save at the top right.<blockquote class="blockquote-reverse"><p>Layer#Cake is powered and brought to you by:</p><footer>Hackerman - <cite title="Source Title">Leram</cite></footer></blockquote>',
+                            html: true,
+                            confirmButtonColor: "#63A8EB"
+                        });
+                    }
+                });
+            }
         </script>
         <script>
         $( document ).ready(function() {