فهرست منبع

Merge pull request #578 from causefx/develop

Develop
causefx 8 سال پیش
والد
کامیت
455809d4eb
18فایلهای تغییر یافته به همراه2723 افزوده شده و 1144 حذف شده
  1. 1 1
      .gitignore
  2. 46 0
      CODE_OF_CONDUCT.md
  3. 1 0
      README.md
  4. 28 3
      ajax.php
  5. 3 3
      error.php
  6. 1455 193
      functions.php
  7. 141 113
      homepage.php
  8. BIN
      images/backup.png
  9. 736 830
      index.php
  10. 4 0
      lang/en.ini
  11. 4 0
      lang/es.ini
  12. 4 0
      lang/fr.ini
  13. 4 0
      lang/it.ini
  14. 4 0
      lang/nl.ini
  15. 4 0
      lang/pl.ini
  16. 242 0
      logs.php
  17. 38 1
      settings.php
  18. 8 0
      user.php

+ 1 - 1
.gitignore

@@ -63,4 +63,4 @@ config/users
 config/users*.db
 config/users*.bak.db
 config/tmp/*
-
+images/cache/*

+ 46 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at causefx@me.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/

+ 1 - 0
README.md

@@ -2,6 +2,7 @@
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/causefx/Organizr.svg)](http://isitmaintained.com/project/causefx/Organizr "Average time to resolve an issue")
 [![GitHub stars](https://img.shields.io/github/stars/causefx/Organizr.svg)](https://github.com/causefx/Organizr/stargazers)
 [![GitHub forks](https://img.shields.io/github/forks/causefx/Organizr.svg)](https://github.com/causefx/Organizr/network)
+[![Docker pulls](https://img.shields.io/docker/pulls/lsiocommunity/organizr.svg)](https://hub.docker.com/r/lsiocommunity/organizr)
 [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/causefx)
 
 <p align="center"><img src="https://cloud.githubusercontent.com/assets/16184466/24440636/1e5e2002-140a-11e7-8da1-1cd68745cedd.png"></p>

+ 28 - 3
ajax.php

@@ -16,7 +16,6 @@ if (isset($_POST['action'])) { $action = $_POST['action']; }
 if (isset($_GET['action'])) { $action = $_GET['action']; }
 if (isset($_GET['a'])) { $action = $_GET['a']; }
 unset($_POST['action']);
-
 // No Action
 if (!isset($action)) {
 	sendNotification(false, 'No Action Specified!');
@@ -27,6 +26,20 @@ $response = array();
 switch ($_SERVER['REQUEST_METHOD']) {
 	case 'GET':
 		switch ($action) {
+			case 'get-backups':
+				qualifyUser("admin", true);
+				$response = implode("\n",getBackups());
+				break;
+			case 'get-calendar':
+				echo json_encode(getCalendar());
+				die();
+				break;
+			case 'show-file':
+				$auth = ($_SERVER['HTTP_REFERER'] ? true : false);
+				if ($auth === false) { die("WTF? Bro!  This is an internal function only"); }
+				showFile();
+				die();
+				break;
 			case 'emby-image':
 				qualifyUser(EMBYHOMEAUTH, true);
 				getEmbyImage();
@@ -83,6 +96,9 @@ switch ($_SERVER['REQUEST_METHOD']) {
             case 'tvdb-get':
 			 	$response = tvdbGet($_POST['id']);
 			 	break;
+			case 'tvdb-search':
+			 	$response = tvdbSearch($_POST['name'], $_POST['type']);
+			 	break;
 			case 'search-plex':
 			 	$response = searchPlex($_POST['searchtitle']);
 			 	break;
@@ -110,10 +126,17 @@ switch ($_SERVER['REQUEST_METHOD']) {
                         break;
 					case 'check-url':
                         sendResult(frameTest($_POST['checkurl']), "flask", $_POST['checkurl'], "IFRAME_CAN_BE_FRAMED", "IFRAME_CANNOT_BE_FRAMED");
+                        break;
+					case 'backup-now':
+                        sendResult(backupDB(), "database", "Backup", "BACKUP_CREATED", "BACKUP_ERROR");
                         break;
                     case 'upload-images':
                         uploadFiles('images/', array('jpg', 'png', 'svg', 'jpeg', 'bmp', 'gif'));
                         sendNotification(true);
+                        break;
+					case 'upload-avatar':
+                        uploadAvatar(USER_HOME.$GLOBALS['USER']->username.'/', array('jpg', 'png', 'svg', 'jpeg', 'bmp', 'gif'));
+                        sendNotification(true);
                         break;
                     case 'remove-images':
                         removeFiles('images/'.(isset($_POST['file'])?$_POST['file']:''));
@@ -130,11 +153,13 @@ switch ($_SERVER['REQUEST_METHOD']) {
                             } else {
                                 unlink('custom.css');
                             }
-                            $response['parent']['reload'] = true;
+                            $response['show_apply'] = true;
                         }
                         unset($_POST['customCSS']);
                         // Custom CSS Special Case END
-                        $response['notify'] = sendNotification(updateDBOptions($_POST),false,false);
+						if (!empty($_POST)) {
+                        	$response['notify'] = sendNotification(updateDBOptions($_POST),false,false);
+						}
                         break;
                     case 'deleteDB':
                         deleteDatabase();

+ 3 - 3
error.php

@@ -40,9 +40,9 @@ $codes = array(
        999 => array('Not Logged In', 'You need to be logged in to access this page.', 'confused'),
 );
 
-$errorTitle = $codes[$status][0];
-$message = $codes[$status][1];
-$errorImage = $codes[$status][2];
+$errorTitle = ($codes[$status][0]) ? $codes[$status][0] : "Error";
+$message = ($codes[$status][1]) ? $codes[$status][1] : "An Error Occured";
+$errorImage = ($codes[$status][2]) ? $codes[$status][2] : "confused";
 
 ?>
 

+ 1455 - 193
functions.php

@@ -2,8 +2,10 @@
 
 // ===================================
 // Define Version
- define('INSTALLEDVERSION', '1.42');
+ define('INSTALLEDVERSION', '1.44');
 // ===================================
+use Kryptonit3\Sonarr\Sonarr;
+use Kryptonit3\SickRage\SickRage;
 
 // Debugging output functions
 function debug_out($variable, $die = false) {
@@ -321,6 +323,10 @@ if (function_exists('curl_version')) :
 		curl_setopt($curlReq, CURLOPT_CUSTOMREQUEST, "POST"); 
 		curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
 		curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
+		if(localURL($url)){
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYHOST, 0);
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYPEER, 0);
+		}
 		// Format Data
 		switch (isset($headers['Content-Type'])?$headers['Content-Type']:'') {
 			case 'application/json': 
@@ -359,6 +365,10 @@ if (function_exists('curl_version')) :
 		curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
 		curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
   		curl_setopt($curlReq, CURLOPT_CONNECTTIMEOUT, 5);
+		if(localURL($url)){
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYHOST, 0);
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYPEER, 0);
+		}
 		// Format Headers
 		$cHeaders = array();
 		foreach ($headers as $k => $v) {
@@ -384,6 +394,10 @@ if (function_exists('curl_version')) :
 		curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
   		curl_setopt($curlReq, CURLOPT_CONNECTTIMEOUT, 5);
 		curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
+		if(localURL($url)){
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYHOST, 0);
+			curl_setopt($curlReq, CURLOPT_SSL_VERIFYPEER, 0);
+		}
 		// Format Headers
 		$cHeaders = array();
 		foreach ($headers as $k => $v) {
@@ -500,141 +514,141 @@ function resolveEmbyItem($address, $token, $item, $nowPlaying = false, $showName
 	}
 	//$URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
 	switch ($itemDetails['Type']) {
-    case 'Episode':
-        $title = (isset($itemDetails['SeriesName'])?$itemDetails['SeriesName']:"");
-        $imageId = (isset($itemDetails['SeriesId'])?$itemDetails['SeriesId']:$itemDetails['Id']);
-        $width = 300;
-        $style = '';
-        $image = 'slick-image-tall';
-        if(!$nowPlaying){ 
-            $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
-            $key = $itemDetails['Id'] . "-list";
-        }else{
-            $height = 281;
-            $width = 500;
-            $imageId = isset($itemDetails['ParentThumbItemId']) ?	$itemDetails['ParentThumbItemId'] : (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
-            $imageType = isset($itemDetails['ParentThumbItemId']) ?	"Thumb" : (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
-            $key = (isset($itemDetails['ParentThumbItemId']) ? $itemDetails['ParentThumbItemId']."-np" : "none-np");
-            $elapsed = $moreInfo['PlayState']['PositionTicks'];
-            $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
-            $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
-            //$transcoded = floor($item->TranscodeSession['progress']- $watched);
-            $stream = $moreInfo['PlayState']['PlayMethod'];
-            $user = $role == "admin" ? $moreInfo['UserName'] : "";
-            $id = $moreInfo['DeviceId'];
-            $streamInfo = buildStream(array(
-                'platform' => (string) $moreInfo['Client'],
-                'device' => (string) $moreInfo['DeviceName'],
-                'stream' => "&nbsp;".streamType($stream),
-                'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
-                'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
-            ));
-            $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
-            $topTitle = '<h5 class="text-center zero-m elip">'.$title.' - '.$itemDetails['Name'].'</h5>';
-            $bottomTitle = '<small class="zero-m">S'.$itemDetails['ParentIndexNumber'].' · E'.$itemDetails['IndexNumber'].'</small>';
-            if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
-        }
-    break;
+		case 'Episode':
+			$title = (isset($itemDetails['SeriesName'])?$itemDetails['SeriesName']:"");
+			$imageId = (isset($itemDetails['SeriesId'])?$itemDetails['SeriesId']:$itemDetails['Id']);
+			$width = 300;
+			$style = '';
+			$image = 'slick-image-tall';
+			if(!$nowPlaying){ 
+				$imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+				$key = $itemDetails['Id'] . "-list";
+			}else{
+				$height = 281;
+				$width = 500;
+				$imageId = isset($itemDetails['ParentThumbItemId']) ?	$itemDetails['ParentThumbItemId'] : (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
+				$imageType = isset($itemDetails['ParentThumbItemId']) ?	"Thumb" : (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
+				$key = (isset($itemDetails['ParentThumbItemId']) ? $itemDetails['ParentThumbItemId']."-np" : "none-np");
+				$elapsed = $moreInfo['PlayState']['PositionTicks'];
+				$duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+				$watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+				//$transcoded = floor($item->TranscodeSession['progress']- $watched);
+				$stream = $moreInfo['PlayState']['PlayMethod'];
+				$user = $role == "admin" ? $moreInfo['UserName'] : "";
+				$id = $moreInfo['DeviceId'];
+				$streamInfo = buildStream(array(
+					'platform' => (string) $moreInfo['Client'],
+					'device' => (string) $moreInfo['DeviceName'],
+					'stream' => "&nbsp;".streamType($stream),
+					'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+					'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+				));
+				$state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+				$topTitle = '<h5 class="text-center zero-m elip">'.$title.' - '.$itemDetails['Name'].'</h5>';
+				$bottomTitle = '<small class="zero-m">S'.$itemDetails['ParentIndexNumber'].' · E'.$itemDetails['IndexNumber'].'</small>';
+				if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
+			}
+			break;
 		case 'MusicAlbum':
 		case 'Audio':
 			$title = $itemDetails['Name'];
 			$imageId = $itemDetails['Id'];
 			$width = 444;
-    $style = '';
-    $image = 'slick-image-short';
-    if(!$nowPlaying){ 
-        $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
-        $key = $itemDetails['Id'] . "-list";
-    }else{
-        $height = 281;
-        $width = 500;
-        $imageId = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
-        $imageType = (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
-        $key = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : "no-np") . "-np";
-        $elapsed = $moreInfo['PlayState']['PositionTicks'];
-        $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
-        $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
-        //$transcoded = floor($item->TranscodeSession['progress']- $watched);
-        $stream = $moreInfo['PlayState']['PlayMethod'];
-        $user = $role == "admin" ? $moreInfo['UserName'] : "";
-        $id = $moreInfo['DeviceId'];
-        $streamInfo = buildStream(array(
-            'platform' => (string) $moreInfo['Client'],
-            'device' => (string) $moreInfo['DeviceName'],
-            'stream' => "&nbsp;".streamType($stream),
-            'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
-        ));
-        $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
-        $topTitle = '<h5 class="text-center zero-m elip">'.$itemDetails['AlbumArtist'].' - '.$itemDetails['Album'].'</h5>';
-        $bottomTitle = '<small class="zero-m">'.$title.'</small>';
-        if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
-    }
+    		$style = '';
+    		$image = 'slick-image-short';
+			if(!$nowPlaying){ 
+				$imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+				$key = $itemDetails['Id'] . "-list";
+			}else{
+				$height = 281;
+				$width = 500;
+				$imageId = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
+				$imageType = (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
+				$key = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : "no-np") . "-np";
+				$elapsed = $moreInfo['PlayState']['PositionTicks'];
+				$duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+				$watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+				//$transcoded = floor($item->TranscodeSession['progress']- $watched);
+				$stream = $moreInfo['PlayState']['PlayMethod'];
+				$user = $role == "admin" ? $moreInfo['UserName'] : "";
+				$id = $moreInfo['DeviceId'];
+				$streamInfo = buildStream(array(
+					'platform' => (string) $moreInfo['Client'],
+					'device' => (string) $moreInfo['DeviceName'],
+					'stream' => "&nbsp;".streamType($stream),
+					'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+				));
+				$state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+				$topTitle = '<h5 class="text-center zero-m elip">'.$itemDetails['AlbumArtist'].' - '.$itemDetails['Album'].'</h5>';
+				$bottomTitle = '<small class="zero-m">'.$title.'</small>';
+				if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
+			}
 			break;
-  case 'TvChannel':
+  		case 'TvChannel':
 			$title = $itemDetails['CurrentProgram']['Name'];
 			$imageId = $itemDetails['Id'];
 			$width = 300;
-    $style = '';
-    $image = 'slick-image-tall';
-    if(!$nowPlaying){ 
-        $imageType = "Primary";
-        $key = $itemDetails['Id'] . "-list";
-    }else{
-        $height = 281;
-        $width = 500;
-        $imageType = "Thumb";
-        $key = $itemDetails['Id'] . "-np";
-        $useImage = "images/livetv.png";
-        $watched = "0";
-        $stream = $moreInfo['PlayState']['PlayMethod'];
-        $user = $role == "admin" ? $moreInfo['UserName'] : "";
-        $id = $moreInfo['DeviceId'];
-        $streamInfo = buildStream(array(
-            'platform' => (string) $moreInfo['Client'],
-            'device' => (string) $moreInfo['DeviceName'],
-            'stream' => "&nbsp;".streamType($stream),
-            'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
-            'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
-        ));
-        $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
-        $topTitle = '<h5 class="text-center zero-m elip">'.$title.'</h5>';
-        $bottomTitle = '<small class="zero-m">'.$itemDetails['Name'].' - '.$itemDetails['ChannelNumber'].'</small>';
-        if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
-    }
-   break;
+			$style = '';
+			$image = 'slick-image-tall';
+			if(!$nowPlaying){ 
+				$imageType = "Primary";
+				$key = $itemDetails['Id'] . "-list";
+			}else{
+				$height = 281;
+				$width = 500;
+				$imageType = "Thumb";
+				$key = $itemDetails['Id'] . "-np";
+				$useImage = "images/livetv.png";
+				$watched = "0";
+				$stream = $moreInfo['PlayState']['PlayMethod'];
+				$user = $role == "admin" ? $moreInfo['UserName'] : "";
+				$id = $moreInfo['DeviceId'];
+				$streamInfo = buildStream(array(
+					'platform' => (string) $moreInfo['Client'],
+					'device' => (string) $moreInfo['DeviceName'],
+					'stream' => "&nbsp;".streamType($stream),
+					'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+					'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+				));
+				$state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+				$topTitle = '<h5 class="text-center zero-m elip">'.$title.'</h5>';
+				$bottomTitle = '<small class="zero-m">'.$itemDetails['Name'].' - '.$itemDetails['ChannelNumber'].'</small>';
+				if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
+			}
+			break;
 		default:
 			$title = $itemDetails['Name'];
 			$imageId = $itemDetails['Id'];
 			$width = 300;
-    $style = '';
-    $image = 'slick-image-tall';
-    if(!$nowPlaying){ 
-        $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
-        $key = $itemDetails['Id'] . "-list";
-    }else{
-        $height = 281;
-        $width = 500;
-        $imageType = isset($itemDetails['ImageTags']['Thumb']) ? "Thumb" : (isset($itemDetails['BackdropImageTags']) ? "Backdrop" : false);
-        $key = $itemDetails['Id'] . "-np";
-        $elapsed = $moreInfo['PlayState']['PositionTicks'];
-        $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
-        $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
-        //$transcoded = floor($item->TranscodeSession['progress']- $watched);
-        $stream = $moreInfo['PlayState']['PlayMethod'];
-        $user = $role == "admin" ? $moreInfo['UserName'] : "";
-        $id = $moreInfo['DeviceId'];
-        $streamInfo = buildStream(array(
-            'platform' => (string) $moreInfo['Client'],
-            'device' => (string) $moreInfo['DeviceName'],
-            'stream' => "&nbsp;".streamType($stream),
-            'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
-            'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
-        ));
-        $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
-        $topTitle = '<h5 class="text-center zero-m elip">'.$title.'</h5>';
-        $bottomTitle = '<small class="zero-m">'.$moreInfo['NowPlayingItem']['ProductionYear'].'</small>';
-        if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
-    }
+			$style = '';
+			$image = 'slick-image-tall';
+			if(!$nowPlaying){ 
+				$imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+				$key = $itemDetails['Id'] . "-list";
+			}else{
+				$height = 281;
+				$width = 500;
+				$imageType = isset($itemDetails['ImageTags']['Thumb']) ? "Thumb" : (isset($itemDetails['BackdropImageTags']) ? "Backdrop" : false);
+				$key = $itemDetails['Id'] . "-np";
+				$elapsed = $moreInfo['PlayState']['PositionTicks'];
+				$duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+				$watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+				//$transcoded = floor($item->TranscodeSession['progress']- $watched);
+				$stream = $moreInfo['PlayState']['PlayMethod'];
+				$user = $role == "admin" ? $moreInfo['UserName'] : "";
+				$id = $moreInfo['DeviceId'];
+				$streamInfo = buildStream(array(
+					'platform' => (string) $moreInfo['Client'],
+					'device' => (string) $moreInfo['DeviceName'],
+					'stream' => "&nbsp;".streamType($stream),
+					'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+					'audio' => "&nbsp;".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+				));
+				$state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+				$topTitle = '<h5 class="text-center zero-m elip">'.$title.'</h5>';
+				$bottomTitle = '<small class="zero-m">'.$moreInfo['NowPlayingItem']['ProductionYear'].'</small>';
+				if($showNames == "true"){ $bottomTitle .= '</small><small class="zero-m pull-right">'.$user.'</small>'; }
+			}
 	}
 	
 	// If No Overview
@@ -659,7 +673,7 @@ function resolveEmbyItem($address, $token, $item, $nowPlaying = false, $showName
 	// Assemble Item And Cache Into Array     
 	if($nowPlaying){
     	//prettyPrint($itemDetails);
-    	return '<div class="col-sm-6 col-md-3"><div class="thumbnail ultra-widget"><div style="display: none;" np="'.$id.'" class="overlay content-box small-box gray-bg">'.$streamInfo.'</div><span class="w-refresh w-p-icon gray" link="'.$id.'"><span class="fa-stack fa-lg" style="font-size: .5em"><i class="fa fa-square fa-stack-2x"></i><i class="fa fa-info-circle fa-stack-1x fa-inverse"></i></span></span><a href="'.$URL.'" target="_blank"><img style="width: 500px; display:inherit;" src="'.$image_url.'" alt="'.$itemDetails['Name'].'"></a><div class="progress progress-bar-sm zero-m"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="'.$watched.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$watched.'%"></div><div class="progress-bar palette-Grey-500 bg" style="width: 0%"></div></div><div class="caption"><i style="float:left" class="fa fa-'.$state.'"></i>'.$topTitle.''.$bottomTitle.'</div></div></div>';
+    	return '<div class="col-sm-6 col-md-3"><div class="thumbnail ultra-widget"><div style="display: none;" np="'.$id.'" class="overlay content-box small-box gray-bg">'.$streamInfo.'</div><span class="w-refresh w-p-icon gray" link="'.$id.'"><span class="fa-stack fa-lg" style="font-size: .5em"><i class="fa fa-square fa-stack-2x"></i><i class="fa fa-info-circle fa-stack-1x fa-inverse"></i></span></span><a href="'.$URL.'" target="_blank"><img style="width: 100%; display:inherit;" src="'.$image_url.'" alt="'.$itemDetails['Name'].'"></a><div class="progress progress-bar-sm zero-m"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="'.$watched.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$watched.'%"></div><div class="progress-bar palette-Grey-500 bg" style="width: 0%"></div></div><div class="caption"><i style="float:left" class="fa fa-'.$state.'"></i>'.$topTitle.''.$bottomTitle.'</div></div></div>';
     }else{
 		 return '<div class="item-'.$itemDetails['Type'].'"><a href="'.$URL.'" target="_blank"><img alt="'.$itemDetails['Name'].'" class="'.$image.'" data-lazy="'.$image_url.'"></a><small style="margin-right: 13px" class="elip">'.$title.'</small></div>';
 	}
@@ -865,31 +879,32 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
 	$openTab = (PLEXTABNAME) ? "true" : "false";
     // Assemble Item And Cache Into Array 
     if($nowPlaying){
-        return '<div class="col-sm-6 col-md-3"><div class="thumbnail ultra-widget"><div style="display: none;" np="'.$id.'" class="overlay content-box small-box gray-bg">'.$streamInfo.'</div><span class="w-refresh w-p-icon gray" link="'.$id.'"><span class="fa-stack fa-lg" style="font-size: .5em"><i class="fa fa-square fa-stack-2x"></i><i class="fa fa-info-circle fa-stack-1x fa-inverse"></i></span></span><a class="openTab" openTab="'.$openTab.'" href="'.$address.'" target="_blank"><img style="width: 500px; display:inherit;" src="'.$image_url.'" alt="'.$item['Name'].'"></a><div class="progress progress-bar-sm zero-m"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="'.$watched.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$watched.'%"></div><div class="progress-bar palette-Grey-500 bg" style="width: '.$transcoded.'%"></div></div><div class="caption"><i style="float:left" class="fa fa-'.$state.'"></i>'.$topTitle.''.$bottomTitle.'</div></div></div>';
+        return '<div class="col-sm-6 col-md-3"><div class="thumbnail ultra-widget"><div style="display: none;" np="'.$id.'" class="overlay content-box small-box gray-bg">'.$streamInfo.'</div><span class="w-refresh w-p-icon gray" link="'.$id.'"><span class="fa-stack fa-lg" style="font-size: .5em"><i class="fa fa-square fa-stack-2x"></i><i class="fa fa-info-circle fa-stack-1x fa-inverse"></i></span></span><a class="openTab" extraTitle="'.$title.'" extraType="'.$item['type'].'" openTab="'.$openTab.'" href="'.$address.'" target="_blank"><img style="width: 100%; display:inherit;" src="'.$image_url.'" alt="'.$item['Name'].'"></a><div class="progress progress-bar-sm zero-m"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="'.$watched.'" aria-valuemin="0" aria-valuemax="100" style="width: '.$watched.'%"></div><div class="progress-bar palette-Grey-500 bg" style="width: '.$transcoded.'%"></div></div><div class="caption"><i style="float:left" class="fa fa-'.$state.'"></i>'.$topTitle.''.$bottomTitle.'</div></div></div>';
     }else{
-        return '<div class="item-'.$item['type'].$playlist.'"><a class="openTab" openTab="'.$openTab.'" href="'.$address.'" target="_blank"><img alt="'.$item['Name'].'" class="'.$image.'" data-lazy="'.$image_url.'"></a><small style="margin-right: 13px" class="elip">'.$title.'</small></div>';
+        return '<div class="item-'.$item['type'].$playlist.'"><a class="openTab" extraTitle="'.$title.'" extraType="'.$item['type'].'" openTab="'.$openTab.'" href="'.$address.'" target="_blank"><img alt="'.$item['Name'].'" class="'.$image.'" data-lazy="'.$image_url.'"></a><small style="margin-right: 13px" class="elip">'.$title.'</small></div>';
     }
 }
-
+//$hideMenu .= '<li data-filter="playlist-'.$className.'" data-name="'.$api['title'].'"><a class="js-filter-'.$className.'" href="javascript:void(0)">'.$api['title'].'</a></li>';
 //Recent Added
 function outputRecentAdded($header, $items, $script = false, $array) {
-    $hideMenu = '<div class="pull-right"><div class="btn-group" role="group"><button type="button" class="btn waves btn-default btn-sm dropdown-toggle waves-effect waves-float" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Filter<span class="caret"></span></button><ul style="right:0; left: auto" class="dropdown-menu filter-recent-event">';
-    if($array["movie"] == "true"){
-        $hideMenu .= '<li data-filter="item-movie" data-filter-on="false"><a class="js-filter-movie" href="javascript:void(0)">Movies</a></li>';
+    $hideMenu = '<div class="pull-right"><div class="btn-group" role="group"><button type="button" class="btn waves btn-default btn-sm dropdown-toggle waves-effect waves-float" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Filter &nbsp;<span class="caret"></span></button><ul style="right:0; left: auto" class="dropdown-menu filter-recent-event">';
+    if(preg_grep("/item-movie/", $items)){
+        $hideMenu .= '<li data-filter="item-movie" data-name="Movies" data-filter-on="false"><a class="js-filter-movie" href="javascript:void(0)">Movies</a></li>';
     }
-    if($array["season"] == "true"){
-        $hideMenu .= '<li data-filter="item-season" data-filter-on="false"><a class="js-filter-season" href="javascript:void(0)">Shows</a></li>';
+	if(preg_grep("/item-season/", $items)){
+        $hideMenu .= '<li data-filter="item-season" data-name="TV Shows" data-filter-on="false"><a class="js-filter-season" href="javascript:void(0)">Shows</a></li>';
     }
-    if($array["album"] == "true"){
-        $hideMenu .= '<li data-filter="item-album" data-filter-on="false"><a class="js-filter-album" href="javascript:void(0)">Music</a></li>';
+    if(preg_grep("/item-album/", $items)){
+        $hideMenu .= '<li data-filter="item-album" data-name="Music Albums" data-filter-on="false"><a class="js-filter-album" href="javascript:void(0)">Music</a></li>';
     }
+	$hideMenu .= '<li data-filter="item-all" data-name="Content" data-filter-on="false"><a class="js-filter-all" href="javascript:void(0)">All</a></li>';
     $hideMenu .= '</ul></div></div>';
     // If None Populate Empty Item
     if (!count($items)) {
         return '<div id="recentMedia" class="content-box box-shadow big-box"><h5 class="text-center">'.$header.'</h5><p class="text-center">No Media Found</p></div>';
     }else{
 		$className = str_replace(' ', '', $header);
-        return '<div id="recentMedia" class="content-box box-shadow big-box"><h5 style="margin-bottom: -20px" class="text-center">'.$header.'</h5><div class="recentHeader inbox-pagination '.$className.'">'.$hideMenu.'</div><br/><br/><div class="recentItems-recent" data-name="'.$className.'">'.implode('',$items).'</div></div>'.($script?'<script>'.$script.'</script>':'');
+        return '<div id="recentMedia" class="content-box box-shadow big-box"><h5 id="recentContent-title" style="margin-bottom: -20px" class="text-center">'.$header.'</h5><div class="recentHeader inbox-pagination '.$className.'">'.$hideMenu.'</div><br/><br/><div class="recentItems-recent" data-name="'.$className.'">'.implode('',$items).'</div></div>'.($script?'<script>'.$script.'</script>':'');
     }
     
 }
@@ -1021,7 +1036,7 @@ function getEmbyRecent($array) {
 // Get Recent Content From Plex
 function getPlexRecent($array){
     $address = qualifyURL(PLEXURL);
-			 $header = translate('RECENT_CONTENT');
+	$header = translate('RECENT_CONTENT');
 	
 	// Perform Requests
     $api = @curl_get($address."/library/recentlyAdded?limit=".PLEXRECENTITEMS."&X-Plex-Token=".PLEXTOKEN);
@@ -1044,10 +1059,10 @@ function getPlexRecent($array){
 
 			return outputRecentAdded($header, $items, "", $array);
 		}else{
-			writeLog("error", "PLEX STREAM ERROR: could not connect - check token - if HTTPS, is cert valid");
+			writeLog("error", "PLEX RECENT-ITEMS ERROR: could not connect - check token - if HTTPS, is cert valid");
 		}
 	}else{
-		writeLog("error", "PLEX STREAM ERROR: could not connect - check URL - if HTTPS, is cert valid");
+		writeLog("error", "PLEX RECENT-ITEMS ERROR: could not connect - check URL - if HTTPS, is cert valid");
 	}
 }
 
@@ -1473,7 +1488,7 @@ function getError($os, $error){
 		),
 		'curl' => array(
 			'win' => '<b>cURL</b> not enabled, uncomment ;extension=php_curl.dll in the file php.ini | '.$ext,
-			'nix' => '<b>cURL</b> not enabled, PHP7 -> sudo apt-get install php-curl | PHP5 -> run sudo apt-get install php5.6-curl',
+			'nix' => '<b>cURL</b> not enabled, PHP7 -> sudo apt-get install php-curl or sudo apt-get install php7.0-curl | PHP5 -> run sudo apt-get install php5.6-curl',
 		),
 		'zip' => array(
 			'win' => '<b>PHP Zip</b> not enabled, uncomment ;extension=php_zip.dll in the file php.ini, if that doesn\'t work remove that line',
@@ -1534,6 +1549,39 @@ function uploadFiles($path, $ext_mask = null) {
 		echo json_encode('No files submitted!');
 	}
 }
+// Process file uploads
+function uploadAvatar($path, $ext_mask = null) {
+	if (isset($_FILES) && count($_FILES)) {
+		require_once('class.uploader.php');
+
+		$uploader = new Uploader();
+		$data = $uploader->upload($_FILES['files'], array(
+			'limit' => 10,
+			'maxSize' => 10,
+			'extensions' => $ext_mask,
+			'required' => false,
+			'uploadDir' => str_replace('//','/',$path.'/'),
+			'title' => array('name'),
+			'removeFiles' => true,
+			'replace' => true,
+		));
+
+		if($data['isComplete']){
+			$files = $data['data'];
+   			writeLog("success", $files['metas'][0]['name']." was uploaded");
+			echo json_encode($files['metas'][0]['name']);
+		}
+
+		if($data['hasErrors']){
+			$errors = $data['errors'];
+   			writeLog("error", $files['metas'][0]['name']." was not able to upload");
+			echo json_encode($errors);
+		}
+	} else { 
+  		writeLog("error", "image was not uploaded");
+		echo json_encode('No files submitted!');
+	}
+}
 
 // Remove file
 function removeFiles($path) {
@@ -1596,11 +1644,11 @@ function qualifyUser($type, $errOnFail = false) {
 	
 	if (!$authorized && $errOnFail) {
 		if ($GLOBALS['USER']->authenticated) {
-			header('Location: error.php?error=401');
-			echo '<script>window.location.href = \''.dirname($_SERVER['SCRIPT_NAME']).'/error.php?error=401\'</script>';
+			header('Location: '.dirname($_SERVER['SCRIPT_NAME']).'error.php?error=401');
+			echo '<script>window.location.href = \''.dirname($_SERVER['SCRIPT_NAME']).'error.php?error=401\'</script>';
 		} else {
-			header('Location: error.php?error=999');
-			echo '<script>window.location.href = \''.dirname($_SERVER['SCRIPT_NAME']).'/error.php?error=999\'</script>';
+			header('Location: '.dirname($_SERVER['SCRIPT_NAME']).'error.php?error=999');
+			echo '<script>window.location.href = \''.dirname($_SERVER['SCRIPT_NAME']).'error.php?error=999\'</script>';
 		}
 
 		debug_out('Not Authorized' ,1);
@@ -2731,7 +2779,8 @@ function get_browser_name() {
 function getSickrageCalendarWanted($array){
     
     $array = json_decode($array, true);
-    $gotCalendar = "";
+    //$gotCalendar = "";
+    $gotCalendar = array();
     $i = 0;
 
     foreach($array['data']['missed'] AS $child) {
@@ -2747,7 +2796,14 @@ function getSickrageCalendarWanted($array){
             if (new DateTime() < new DateTime($episodeAirDate)) { $unaired = true; }
             $downloaded = "0";
             if($downloaded == "0" && isset($unaired)){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg";}else{ $downloaded = "red-bg"; }
-            $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+            //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+			array_push($gotCalendar, array(
+				"id" => "Sick-Miss-".$i,
+				"title" => $seriesName, 
+				"start" => $episodeAirDate, 
+				"className" => $downloaded." tvID--".$episodeID, 
+				"imagetype" => "tv",
+			));
         
     }
     
@@ -2764,8 +2820,14 @@ function getSickrageCalendarWanted($array){
             if (new DateTime() < new DateTime($episodeAirDate)) { $unaired = true; }
             $downloaded = "0";
             if($downloaded == "0" && isset($unaired)){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg";}else{ $downloaded = "red-bg"; }
-            $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
-        
+            //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+			array_push($gotCalendar, array(
+				"id" => "Sick-Today-".$i,
+				"title" => $seriesName, 
+				"start" => $episodeAirDate, 
+				"className" => $downloaded." tvID--".$episodeID, 
+				"imagetype" => "tv",
+			));
     }
     
     foreach($array['data']['soon'] AS $child) {
@@ -2781,8 +2843,14 @@ function getSickrageCalendarWanted($array){
             if (new DateTime() < new DateTime($episodeAirDate)) { $unaired = true; }
             $downloaded = "0";
             if($downloaded == "0" && isset($unaired)){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg";}else{ $downloaded = "red-bg"; }
-            $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
-        
+            //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+			array_push($gotCalendar, array(
+				"id" => "Sick-Soon-".$i,
+				"title" => $seriesName, 
+				"start" => $episodeAirDate, 
+				"className" => $downloaded." tvID--".$episodeID, 
+				"imagetype" => "tv",
+			));
     }
     
     foreach($array['data']['later'] AS $child) {
@@ -2798,7 +2866,14 @@ function getSickrageCalendarWanted($array){
             if (new DateTime() < new DateTime($episodeAirDate)) { $unaired = true; }
             $downloaded = "0";
             if($downloaded == "0" && isset($unaired)){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg";}else{ $downloaded = "red-bg"; }
-            $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+            //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+			array_push($gotCalendar, array(
+				"id" => "Sick-Later-".$i,
+				"title" => $seriesName, 
+				"start" => $episodeAirDate, 
+				"className" => $downloaded." tvID--".$episodeID, 
+				"imagetype" => "tv",
+			));
         
     }
 
@@ -2809,7 +2884,8 @@ function getSickrageCalendarWanted($array){
 function getSickrageCalendarHistory($array){
     
     $array = json_decode($array, true);
-    $gotCalendar = "";
+    //$gotCalendar = "";
+    $gotCalendar = array();
     $i = 0;
 
     foreach($array['data'] AS $child) {
@@ -2819,7 +2895,14 @@ function getSickrageCalendarHistory($array){
             $episodeID = $child['tvdbid'];
             $episodeAirDate = $child['date'];
             $downloaded = "green-bg";
-            $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+            //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+			array_push($gotCalendar, array(
+				"id" => "Sick-History-".$i,
+				"title" => $seriesName, 
+				"start" => $episodeAirDate, 
+				"className" => $downloaded." tvID--".$episodeID, 
+				"imagetype" => "tv",
+			));
         
     }
 
@@ -2830,7 +2913,8 @@ function getSickrageCalendarHistory($array){
 function getSonarrCalendar($array){
     
     $array = json_decode($array, true);
-    $gotCalendar = "";
+    //$gotCalendar = "";
+    $gotCalendar = array();
     $i = 0;
     foreach($array AS $child) {
 
@@ -2849,53 +2933,47 @@ function getSonarrCalendar($array){
         $downloaded = $child['hasFile'];
         if($downloaded == "0" && isset($unaired) && $episodePremier == "true"){ $downloaded = "light-blue-bg"; }elseif($downloaded == "0" && isset($unaired)){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg";}else{ $downloaded = "red-bg"; }
         
-        $gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
-        
+        //$gotCalendar .= "{ title: \"$seriesName\", start: \"$episodeAirDate\", className: \"$downloaded tvID--$episodeID\", imagetype: \"tv\" }, \n";
+		array_push($gotCalendar, array(
+			"id" => "Sonarr-".$i,
+			"title" => $seriesName, 
+			"start" => $episodeAirDate, 
+			"className" => $downloaded." tvID--".$episodeID, 
+			"imagetype" => "tv",
+		));
+
     }
 
     if ($i != 0){ return $gotCalendar; }
 
 }
 
-function getRadarrCalendar($array){
-    
+function getRadarrCalendar($array){  
     $array = json_decode($array, true);
-    $gotCalendar = "";
+    $gotCalendar = array();
     $i = 0;
     foreach($array AS $child) {
-        
-        if(isset($child['inCinemas'])){
-            
+        if(isset($child['physicalRelease'])){
             $i++;
             $movieName = $child['title'];
             $movieID = $child['tmdbId'];
             if(!isset($movieID)){ $movieID = ""; }
-            
-            if(isset($child['inCinemas']) && isset($child['physicalRelease'])){ 
-                
-                $physicalRelease = $child['physicalRelease']; 
-                $physicalRelease = strtotime($physicalRelease);
-                $physicalRelease = date("Y-m-d", $physicalRelease);
-
-                if (new DateTime() < new DateTime($physicalRelease)) { $notReleased = "true"; }else{ $notReleased = "false"; }
-
-                $downloaded = $child['hasFile'];
-                if($downloaded == "0" && $notReleased == "true"){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg"; }else{ $downloaded = "red-bg"; }
-            
-            }else{ 
-                
-                $physicalRelease = $child['inCinemas']; 
-                $downloaded = "light-blue-bg";
-            
-            }
-                        
-            $gotCalendar .= "{ title: \"$movieName\", start: \"$physicalRelease\", className: \"$downloaded movieID--$movieID\", imagetype: \"film\" }, \n";
+			$physicalRelease = $child['physicalRelease']; 
+			$physicalRelease = strtotime($physicalRelease);
+			$physicalRelease = date("Y-m-d", $physicalRelease);
+			if (new DateTime() < new DateTime($physicalRelease)) { $notReleased = "true"; }else{ $notReleased = "false"; }
+			$downloaded = $child['hasFile'];
+			if($downloaded == "0" && $notReleased == "true"){ $downloaded = "indigo-bg"; }elseif($downloaded == "1"){ $downloaded = "green-bg"; }else{ $downloaded = "red-bg"; }
+			array_push($gotCalendar, array(
+				"id" => "Radarr-".$i,
+				"title" => $movieName, 
+				"start" => $physicalRelease, 
+				"className" => $downloaded." movieID--".$movieID, 
+				"imagetype" => "film",
+			));
         }
-        
     }
-
     if ($i != 0){ return $gotCalendar; }
-
 }
 
 function getHeadphonesCalendar($url, $key, $list){
@@ -2903,7 +2981,8 @@ function getHeadphonesCalendar($url, $key, $list){
     $api = curl_get($url."/api?apikey=".$key."&cmd=$list");
     $api = json_decode($api, true);
     $i = 0;
-    $gotCalendar = "";
+    //$gotCalendar = "";
+    $gotCalendar = array();;
 	if (is_array($api) || is_object($api)){
 		foreach($api AS $child) {
 			if($child['Status'] == "Wanted" && $list == "getWanted" && $child['ReleaseDate']){
@@ -2920,7 +2999,15 @@ function getHeadphonesCalendar($url, $key, $list){
 
 				if($albumStatus == "Wanted" && $notReleased == "true"){ $albumStatusColor = "indigo-bg"; }elseif($albumStatus == "Downloaded"){ $albumStatusColor = "green-bg"; }else{ $albumStatusColor = "red-bg"; }
 
-				$gotCalendar .= "{ title: \"$albumArtist - $albumName\", start: \"$albumDate\", className: \"$albumStatusColor\", imagetype: \"music\", url: \"https://musicbrainz.org/release-group/$albumID\" }, \n";
+				//$gotCalendar .= "{ title: \"$albumArtist - $albumName\", start: \"$albumDate\", className: \"$albumStatusColor\", imagetype: \"music\", url: \"https://musicbrainz.org/release-group/$albumID\" }, \n";
+				array_push($gotCalendar, array(
+					"id" => "Headphones-".$i,
+					"title" => $albumArtist.' - '.$albumName, 
+					"start" => $albumDate, 
+					"className" => $albumStatusColor,
+					"imagetype" => "music",
+					'url' => "https://musicbrainz.org/release-group/".$albumID,
+				));
 			}
 			if($child['Status'] == "Processed" && $list == "getHistory"){
 				$i++;
@@ -2934,7 +3021,15 @@ function getHeadphonesCalendar($url, $key, $list){
 				$albumStatusColor = "green-bg";
 				if (new DateTime() < new DateTime($albumDate)) {  $notReleased = "true"; }else{ $notReleased = "false"; }
 
-				$gotCalendar .= "{ title: \"$albumName\", start: \"$albumDate\", className: \"$albumStatusColor\", imagetype: \"music\", url: \"https://musicbrainz.org/release-group/$albumID\" }, \n";
+				//$gotCalendar .= "{ title: \"$albumName\", start: \"$albumDate\", className: \"$albumStatusColor\", imagetype: \"music\", url: \"https://musicbrainz.org/release-group/$albumID\" }, \n";
+				array_push($gotCalendar, array(
+					"id" => "Headphones-".$i,
+					"title" => $albumName, 
+					"start" => $albumDate, 
+					"className" => $albumStatusColor,
+					"imagetype" => "music",
+					'url' => "https://musicbrainz.org/release-group/".$albumID,
+				));
 			}
 		}
     	if ($i != 0){ return $gotCalendar; }
@@ -2952,11 +3047,12 @@ function checkRootPath($string){
 }
 
 function strip($string){
-	return str_replace(array("\r","\n","\t"),"",$string);
+	$string = strip_tags($string);
+	return preg_replace('/[ \t]+/', ' ', preg_replace('/\s*$^\s*/m', "\n", $string));
 }
 
 function writeLog($type, $message){
-    $message = date("Y-m-d H:i:s")."|".$type."|".$message."\n";
+    $message = date("Y-m-d H:i:s")."|".$type."|".strip($message)."\n";
     file_put_contents("org.log", $message, FILE_APPEND | LOCK_EX);
 }
 
@@ -2964,7 +3060,7 @@ function readLog(){
     $log = file("org.log");
     $log = array_reverse($log);
     foreach($log as $line){
-        $line = explode("|", $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>";
     }
@@ -3251,7 +3347,7 @@ function searchPlex($query){
 				$link = PLEXURL."/web/index.html#!/server/$server/details?key=/library/metadata/".$results['ratingkey'];
 			}
 			
-            $items .= '<tr style="cursor: pointer;" class="openTab" openTab="'.$openTab.'" href="'.$link.'">
+            $items .= '<tr style="cursor: pointer;" class="openTab" extraTitle="'.$results['title'].'" extraType="'.$child['type'].'" openTab="'.$openTab.'" href="'.$link.'">
             <th scope="row"><img src="'.$image_url.'"></th>
             <td class="col-xs-2 nzbtable nzbtable-row"'.$style.'>'.$results['title'].'</td>
             <td class="col-xs-3 nzbtable nzbtable-row"'.$style.'>'.$results['genre'].'</td>
@@ -3534,6 +3630,13 @@ function inviteCodes($action, $code = null, $usedBy = null) {
 		case "use":
 			$currentIP = get_client_ip();
 			$invites = $GLOBALS['file_db']->query('UPDATE invites SET valid = "No", usedby = "'.$usedBy.'", dateused = "'.$now.'", ip = "'.$currentIP.'" WHERE code = "'.$code.'"');
+			if(ENABLEMAIL){
+				if (!isset($GLOBALS['USER'])) {
+					require_once("user.php");
+					$GLOBALS['USER'] = new User('registration_callback');
+				}
+				sendEmail($GLOBALS['USER']->adminEmail, "Admin", "Plex Invite Used", orgEmail("PLEX Invite Used", "Look who joined the cool club", "Admin", "Hey, The User: $usedBy has redeemd their invite code: [$code], their IP Address was: $currentIP", null, null, "What Next?", "Well, That is up to you.  You can go check on them if you like."));
+			}
 			return (!empty($invites) ? true : false );
 			break;
 	}
@@ -3599,6 +3702,7 @@ function getCert(){
     	file_put_contents( $file, fopen($url, 'r'));
 		writeLog("success", "CERT PEM: pem file created");
 	}elseif (file_exists($file) && time() - 2592000 > filemtime($file)) {
+		file_put_contents( $file, fopen($url, 'r'));
 		writeLog("success", "CERT PEM: downloaded new pem file");
 	}
 	return $file;
@@ -3651,6 +3755,21 @@ function tvdbGet($id){
 	return $api;
 }
 
+function tvdbSearch($name, $type){
+	$name = rawurlencode(preg_replace("/\(([^()]*+|(?R))*\)/","", $name));
+	$headers = array(
+		"Accept" => "application/json", 
+		"Authorization" => "Bearer ".tvdbToken(),
+		"trakt-api-key" => "4502cfdf8f7282fe454878ff8583f5636392cdc5fcac30d0cc4565f7173bf443",
+		"trakt-api-version" => "2"
+	);
+
+	$trakt = curl_get("https://api.trakt.tv/search/$type?query=$name", $headers);
+	@$api['trakt'] = json_decode($trakt, true)[0][$type]['ids'];
+
+	return $api;
+}
+
 function getPlexPlaylists(){
     $address = qualifyURL(PLEXURL);
     
@@ -3664,9 +3783,9 @@ function getPlexPlaylists(){
 			// Identify the local machine
 			$gotServer = $getServer['machineIdentifier'];
 			$output = "";
-			$hideMenu = '<div class="pull-right"><div class="btn-group" role="group"><button type="button" id="playlist-Name" class="btn waves btn-default btn-sm dropdown-toggle waves-effect waves-float" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Choose A Playlist<span class="caret"></span></button><ul style="right:0; left: auto" class="dropdown-menu filter-recent-playlist">';
+			$hideMenu = '<div class="pull-right"><div class="btn-group" role="group"><button type="button" id="playlist-Name" class="btn waves btn-default btn-sm dropdown-toggle waves-effect waves-float" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Choose A Playlist &nbsp;<span class="caret"></span></button><ul style="right:0; left: auto; height: 200px;" class="dropdown-menu filter-recent-playlist playlist-listing">';
 			foreach($api AS $child) {
-				$items = "";
+				$items = array();
 				if ($child['playlistType'] == "video" && strpos(strtolower($child['title']) , 'private') === false){
 					$api = @curl_get($address.$child['key']."?X-Plex-Token=".PLEXTOKEN);
 					$api = simplexml_load_string($api);
@@ -3694,6 +3813,160 @@ function getPlexPlaylists(){
 	}
 }
 
+function readExternalLog($type,$filename,$name = null){
+    $log = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+    $log = array_reverse($log);
+    foreach($log as $line){
+		if(!empty($line) && $line[0] != " "){
+			$line = strip($line);
+			if($type == "single"){
+				if( strpos( strtolower($line), "ror" ) !== false ) {
+					echo "<tr><td class='red-bg'>".$line."</td></tr>";
+				}else{
+					echo "<tr><td>".$line."</td></tr>";
+				}
+			}elseif($type == "all"){
+				if( strpos( strtolower($line), "ror" ) !== false ) {
+					echo "<tr><td class='red-bg'>".$name."</td>";
+					echo "<td class='red-bg'>".$line."</td></tr>";
+				}else{
+					echo "<tr><td>".$name."</td>";
+					echo "<td>".$line."</td></tr>";
+				}
+			}
+		}
+    }
+}
+
+function getLogs(){
+    $path = __DIR__ ."/logs/";
+	@mkdir($path, 0770, true);
+    $logs = array();
+    $files = array_diff(scandir($path), array('.', '..'));
+    foreach($files as $v){
+        $title = explode(".", $v)[0];
+        $logs[$title] = $path.$v;
+    }
+    return $logs;
+}
+
+function getBackups(){
+    $path = DATABASE_LOCATION ."backups/";
+	@mkdir($path, 0770, true);
+    $backups = array();
+    $files = array_diff(scandir($path), array('.', '..'));
+    return array_reverse($files);
+}
+
+function getExtension($string) {
+    return preg_replace("#(.+)?\.(\w+)(\?.+)?#", "$2", $string);
+}
+
+function showFile(){
+	$file = $_GET['file'];
+	$fileType = getExtension($file);
+	if($fileType != 'php'){
+		header("Content-type: ".mimeTypes()[$fileType]);
+		@readfile($file);
+	}
+}
+
+function getCalendar(){
+	$sonarr = new Sonarr(SONARRURL, SONARRKEY);
+	$radarr = new Sonarr(RADARRURL, RADARRKEY);
+	$sickrage = new SickRage(SICKRAGEURL, SICKRAGEKEY);
+	$startDate = date('Y-m-d',strtotime("-".CALENDARSTARTDAY." days"));
+	$endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days")); 
+	$calendarItems = array();
+	if (SONARRURL != "" && qualifyUser(SONARRHOMEAUTH)){
+		try {
+			$sonarrCalendar = getSonarrCalendar($sonarr->getCalendar($startDate, $endDate));
+			if(!empty($sonarrCalendar)) { $calendarItems = array_merge($calendarItems, $sonarrCalendar); }
+		} catch (Exception $e) { 
+			writeLog("error", "SONARR ERROR: ".strip($e->getMessage())); 
+		}
+	}
+	if (RADARRURL != "" && qualifyUser(RADARRHOMEAUTH)){ 
+		try { 
+			$radarrCalendar = getRadarrCalendar($radarr->getCalendar($startDate, $endDate));
+			if(!empty($radarrCalendar)) { $calendarItems = array_merge($calendarItems, $radarrCalendar); } 
+		} catch (Exception $e) { 
+			writeLog("error", "RADARR ERROR: ".strip($e->getMessage())); 
+		}
+	}
+	if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
+		$headphonesHistory = getHeadphonesCalendar(HEADPHONESURL, HEADPHONESKEY, "getHistory"); 
+		$headphonesWanted = getHeadphonesCalendar(HEADPHONESURL, HEADPHONESKEY, "getWanted"); 
+		if(!empty($headphonesHistory)) { $calendarItems = array_merge($calendarItems, $headphonesHistory); }
+		if(!empty($headphonesWanted)) { $calendarItems = array_merge($calendarItems, $headphonesWanted); }
+
+	}
+	if (SICKRAGEURL != "" && qualifyUser(SICKRAGEHOMEAUTH)){
+		try { 
+			$sickrageFuture = getSickrageCalendarWanted($sickrage->future());
+			if(!empty($sickrageFuture)) { $calendarItems = array_merge($calendarItems, $sickrageFuture); }
+		} catch (Exception $e) { 
+			writeLog("error", "SICKRAGE/BEARD ERROR: ".strip($e->getMessage())); 
+		} try { 
+			$sickrageHistory = getSickrageCalendarHistory($sickrage->history("100","downloaded"));
+			if(!empty($sickrageHistory)) { $calendarItems = array_merge($calendarItems, $sickrageHistory); }
+		} catch (Exception $e) { 
+			writeLog("error", "SICKRAGE/BEARD ERROR: ".strip($e->getMessage())); 
+		}
+	}
+	return $calendarItems;
+}
+
+function localURL($url){
+	if (strpos($url, 'https') !== false) {
+		preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/", $url, $result);
+		$result = (!empty($result) ? true : false);
+		return $result;
+	}
+}
+
+function fileArray($files){
+	foreach($files as $file){
+		if(file_exists($file)){
+			$list[] = $file;
+		}
+	}
+	if(!empty($list)){ return $list; } 
+}
+
+function backupDB(){
+	if (extension_loaded('ZIP')) {
+		$directory = DATABASE_LOCATION."backups/";
+		@mkdir($directory, 0770, true);
+		$orgFiles = array(
+			'css' => 'custom.css', 
+			'temp' => 'cus.sd', 
+			'orgLog' => 'org.log', 
+			'loginLog' => 'loginLog.json', 
+			'chatDB' => 'chatpack.db', 
+			'config' => 'config/config.php', 
+			'database' => DATABASE_LOCATION.'users.db'
+		);
+		$files = fileArray($orgFiles);
+		if(!empty($files)){
+			writeLog("success", "BACKUP: backup process started");
+			$zipname = $directory.'backup['.date('Y-m-d_H-i').']['.INSTALLEDVERSION.'].zip';
+			$zip = new ZipArchive;
+			$zip->open($zipname, ZipArchive::CREATE);
+			foreach ($files as $file) {
+				$zip->addFile($file);
+			}
+			$zip->close();
+			writeLog("success", "BACKUP: backup process finished");
+			return true;
+		}else{
+			return false;
+		}
+	}else{
+		return false;
+	}
+}
+
 function orgEmail($header = "Message From Admin", $title = "Important Message", $user = "Organizr User", $mainMessage = "", $button = null, $buttonURL = null, $subTitle = "", $subMessage = ""){
 	$path = getServerPath();
 	return '
@@ -4085,5 +4358,994 @@ function orgEmail($header = "Message From Admin", $title = "Important Message",
 	';
 }
 
+function mimeTypes(){
+	return array(
+		'123' => 'application/vnd.lotus-1-2-3',
+		'3dml' => 'text/vnd.in3d.3dml',
+		'3ds' => 'image/x-3ds',
+		'3g2' => 'video/3gpp2',
+		'3gp' => 'video/3gpp',
+		'7z' => 'application/x-7z-compressed',
+		'aab' => 'application/x-authorware-bin',
+		'aac' => 'audio/x-aac',
+		'aam' => 'application/x-authorware-map',
+		'aas' => 'application/x-authorware-seg',
+		'abw' => 'application/x-abiword',
+		'ac' => 'application/pkix-attr-cert',
+		'acc' => 'application/vnd.americandynamics.acc',
+		'ace' => 'application/x-ace-compressed',
+		'acu' => 'application/vnd.acucobol',
+		'acutc' => 'application/vnd.acucorp',
+		'adp' => 'audio/adpcm',
+		'aep' => 'application/vnd.audiograph',
+		'afm' => 'application/x-font-type1',
+		'afp' => 'application/vnd.ibm.modcap',
+		'ahead' => 'application/vnd.ahead.space',
+		'ai' => 'application/postscript',
+		'aif' => 'audio/x-aiff',
+		'aifc' => 'audio/x-aiff',
+		'aiff' => 'audio/x-aiff',
+		'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+		'ait' => 'application/vnd.dvb.ait',
+		'ami' => 'application/vnd.amiga.ami',
+		'apk' => 'application/vnd.android.package-archive',
+		'appcache' => 'text/cache-manifest',
+		'application' => 'application/x-ms-application',
+		'apr' => 'application/vnd.lotus-approach',
+		'arc' => 'application/x-freearc',
+		'asc' => 'application/pgp-signature',
+		'asf' => 'video/x-ms-asf',
+		'asm' => 'text/x-asm',
+		'aso' => 'application/vnd.accpac.simply.aso',
+		'asx' => 'video/x-ms-asf',
+		'atc' => 'application/vnd.acucorp',
+		'atom' => 'application/atom+xml',
+		'atomcat' => 'application/atomcat+xml',
+		'atomsvc' => 'application/atomsvc+xml',
+		'atx' => 'application/vnd.antix.game-component',
+		'au' => 'audio/basic',
+		'avi' => 'video/x-msvideo',
+		'aw' => 'application/applixware',
+		'azf' => 'application/vnd.airzip.filesecure.azf',
+		'azs' => 'application/vnd.airzip.filesecure.azs',
+		'azw' => 'application/vnd.amazon.ebook',
+		'bat' => 'application/x-msdownload',
+		'bcpio' => 'application/x-bcpio',
+		'bdf' => 'application/x-font-bdf',
+		'bdm' => 'application/vnd.syncml.dm+wbxml',
+		'bed' => 'application/vnd.realvnc.bed',
+		'bh2' => 'application/vnd.fujitsu.oasysprs',
+		'bin' => 'application/octet-stream',
+		'blb' => 'application/x-blorb',
+		'blorb' => 'application/x-blorb',
+		'bmi' => 'application/vnd.bmi',
+		'bmp' => 'image/bmp',
+		'book' => 'application/vnd.framemaker',
+		'box' => 'application/vnd.previewsystems.box',
+		'boz' => 'application/x-bzip2',
+		'bpk' => 'application/octet-stream',
+		'btif' => 'image/prs.btif',
+		'bz' => 'application/x-bzip',
+		'bz2' => 'application/x-bzip2',
+		'c' => 'text/x-c',
+		'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+		'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+		'c4d' => 'application/vnd.clonk.c4group',
+		'c4f' => 'application/vnd.clonk.c4group',
+		'c4g' => 'application/vnd.clonk.c4group',
+		'c4p' => 'application/vnd.clonk.c4group',
+		'c4u' => 'application/vnd.clonk.c4group',
+		'cab' => 'application/vnd.ms-cab-compressed',
+		'caf' => 'audio/x-caf',
+		'cap' => 'application/vnd.tcpdump.pcap',
+		'car' => 'application/vnd.curl.car',
+		'cat' => 'application/vnd.ms-pki.seccat',
+		'cb7' => 'application/x-cbr',
+		'cba' => 'application/x-cbr',
+		'cbr' => 'application/x-cbr',
+		'cbt' => 'application/x-cbr',
+		'cbz' => 'application/x-cbr',
+		'cc' => 'text/x-c',
+		'cct' => 'application/x-director',
+		'ccxml' => 'application/ccxml+xml',
+		'cdbcmsg' => 'application/vnd.contact.cmsg',
+		'cdf' => 'application/x-netcdf',
+		'cdkey' => 'application/vnd.mediastation.cdkey',
+		'cdmia' => 'application/cdmi-capability',
+		'cdmic' => 'application/cdmi-container',
+		'cdmid' => 'application/cdmi-domain',
+		'cdmio' => 'application/cdmi-object',
+		'cdmiq' => 'application/cdmi-queue',
+		'cdx' => 'chemical/x-cdx',
+		'cdxml' => 'application/vnd.chemdraw+xml',
+		'cdy' => 'application/vnd.cinderella',
+		'cer' => 'application/pkix-cert',
+		'cfs' => 'application/x-cfs-compressed',
+		'cgm' => 'image/cgm',
+		'chat' => 'application/x-chat',
+		'chm' => 'application/vnd.ms-htmlhelp',
+		'chrt' => 'application/vnd.kde.kchart',
+		'cif' => 'chemical/x-cif',
+		'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+		'cil' => 'application/vnd.ms-artgalry',
+		'cla' => 'application/vnd.claymore',
+		'class' => 'application/java-vm',
+		'clkk' => 'application/vnd.crick.clicker.keyboard',
+		'clkp' => 'application/vnd.crick.clicker.palette',
+		'clkt' => 'application/vnd.crick.clicker.template',
+		'clkw' => 'application/vnd.crick.clicker.wordbank',
+		'clkx' => 'application/vnd.crick.clicker',
+		'clp' => 'application/x-msclip',
+		'cmc' => 'application/vnd.cosmocaller',
+		'cmdf' => 'chemical/x-cmdf',
+		'cml' => 'chemical/x-cml',
+		'cmp' => 'application/vnd.yellowriver-custom-menu',
+		'cmx' => 'image/x-cmx',
+		'cod' => 'application/vnd.rim.cod',
+		'com' => 'application/x-msdownload',
+		'conf' => 'text/plain',
+		'cpio' => 'application/x-cpio',
+		'cpp' => 'text/x-c',
+		'cpt' => 'application/mac-compactpro',
+		'crd' => 'application/x-mscardfile',
+		'crl' => 'application/pkix-crl',
+		'crt' => 'application/x-x509-ca-cert',
+		'cryptonote' => 'application/vnd.rig.cryptonote',
+		'csh' => 'application/x-csh',
+		'csml' => 'chemical/x-csml',
+		'csp' => 'application/vnd.commonspace',
+		'css' => 'text/css',
+		'cst' => 'application/x-director',
+		'csv' => 'text/csv',
+		'cu' => 'application/cu-seeme',
+		'curl' => 'text/vnd.curl',
+		'cww' => 'application/prs.cww',
+		'cxt' => 'application/x-director',
+		'cxx' => 'text/x-c',
+		'dae' => 'model/vnd.collada+xml',
+		'daf' => 'application/vnd.mobius.daf',
+		'dart' => 'application/vnd.dart',
+		'dataless' => 'application/vnd.fdsn.seed',
+		'davmount' => 'application/davmount+xml',
+		'dbk' => 'application/docbook+xml',
+		'dcr' => 'application/x-director',
+		'dcurl' => 'text/vnd.curl.dcurl',
+		'dd2' => 'application/vnd.oma.dd2+xml',
+		'ddd' => 'application/vnd.fujixerox.ddd',
+		'deb' => 'application/x-debian-package',
+		'def' => 'text/plain',
+		'deploy' => 'application/octet-stream',
+		'der' => 'application/x-x509-ca-cert',
+		'dfac' => 'application/vnd.dreamfactory',
+		'dgc' => 'application/x-dgc-compressed',
+		'dic' => 'text/x-c',
+		'dir' => 'application/x-director',
+		'dis' => 'application/vnd.mobius.dis',
+		'dist' => 'application/octet-stream',
+		'distz' => 'application/octet-stream',
+		'djv' => 'image/vnd.djvu',
+		'djvu' => 'image/vnd.djvu',
+		'dll' => 'application/x-msdownload',
+		'dmg' => 'application/x-apple-diskimage',
+		'dmp' => 'application/vnd.tcpdump.pcap',
+		'dms' => 'application/octet-stream',
+		'dna' => 'application/vnd.dna',
+		'doc' => 'application/msword',
+		'docm' => 'application/vnd.ms-word.document.macroenabled.12',
+		'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+		'dot' => 'application/msword',
+		'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
+		'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+		'dp' => 'application/vnd.osgi.dp',
+		'dpg' => 'application/vnd.dpgraph',
+		'dra' => 'audio/vnd.dra',
+		'dsc' => 'text/prs.lines.tag',
+		'dssc' => 'application/dssc+der',
+		'dtb' => 'application/x-dtbook+xml',
+		'dtd' => 'application/xml-dtd',
+		'dts' => 'audio/vnd.dts',
+		'dtshd' => 'audio/vnd.dts.hd',
+		'dump' => 'application/octet-stream',
+		'dvb' => 'video/vnd.dvb.file',
+		'dvi' => 'application/x-dvi',
+		'dwf' => 'model/vnd.dwf',
+		'dwg' => 'image/vnd.dwg',
+		'dxf' => 'image/vnd.dxf',
+		'dxp' => 'application/vnd.spotfire.dxp',
+		'dxr' => 'application/x-director',
+		'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+		'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+		'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+		'ecma' => 'application/ecmascript',
+		'edm' => 'application/vnd.novadigm.edm',
+		'edx' => 'application/vnd.novadigm.edx',
+		'efif' => 'application/vnd.picsel',
+		'ei6' => 'application/vnd.pg.osasli',
+		'elc' => 'application/octet-stream',
+		'emf' => 'application/x-msmetafile',
+		'eml' => 'message/rfc822',
+		'emma' => 'application/emma+xml',
+		'emz' => 'application/x-msmetafile',
+		'eol' => 'audio/vnd.digital-winds',
+		'eot' => 'application/vnd.ms-fontobject',
+		'eps' => 'application/postscript',
+		'epub' => 'application/epub+zip',
+		'es3' => 'application/vnd.eszigno3+xml',
+		'esa' => 'application/vnd.osgi.subsystem',
+		'esf' => 'application/vnd.epson.esf',
+		'et3' => 'application/vnd.eszigno3+xml',
+		'etx' => 'text/x-setext',
+		'eva' => 'application/x-eva',
+		'evy' => 'application/x-envoy',
+		'exe' => 'application/x-msdownload',
+		'exi' => 'application/exi',
+		'ext' => 'application/vnd.novadigm.ext',
+		'ez' => 'application/andrew-inset',
+		'ez2' => 'application/vnd.ezpix-album',
+		'ez3' => 'application/vnd.ezpix-package',
+		'f' => 'text/x-fortran',
+		'f4v' => 'video/x-f4v',
+		'f77' => 'text/x-fortran',
+		'f90' => 'text/x-fortran',
+		'fbs' => 'image/vnd.fastbidsheet',
+		'fcdt' => 'application/vnd.adobe.formscentral.fcdt',
+		'fcs' => 'application/vnd.isac.fcs',
+		'fdf' => 'application/vnd.fdf',
+		'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+		'fg5' => 'application/vnd.fujitsu.oasysgp',
+		'fgd' => 'application/x-director',
+		'fh' => 'image/x-freehand',
+		'fh4' => 'image/x-freehand',
+		'fh5' => 'image/x-freehand',
+		'fh7' => 'image/x-freehand',
+		'fhc' => 'image/x-freehand',
+		'fig' => 'application/x-xfig',
+		'flac' => 'audio/x-flac',
+		'fli' => 'video/x-fli',
+		'flo' => 'application/vnd.micrografx.flo',
+		'flv' => 'video/x-flv',
+		'flw' => 'application/vnd.kde.kivio',
+		'flx' => 'text/vnd.fmi.flexstor',
+		'fly' => 'text/vnd.fly',
+		'fm' => 'application/vnd.framemaker',
+		'fnc' => 'application/vnd.frogans.fnc',
+		'for' => 'text/x-fortran',
+		'fpx' => 'image/vnd.fpx',
+		'frame' => 'application/vnd.framemaker',
+		'fsc' => 'application/vnd.fsc.weblaunch',
+		'fst' => 'image/vnd.fst',
+		'ftc' => 'application/vnd.fluxtime.clip',
+		'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+		'fvt' => 'video/vnd.fvt',
+		'fxp' => 'application/vnd.adobe.fxp',
+		'fxpl' => 'application/vnd.adobe.fxp',
+		'fzs' => 'application/vnd.fuzzysheet',
+		'g2w' => 'application/vnd.geoplan',
+		'g3' => 'image/g3fax',
+		'g3w' => 'application/vnd.geospace',
+		'gac' => 'application/vnd.groove-account',
+		'gam' => 'application/x-tads',
+		'gbr' => 'application/rpki-ghostbusters',
+		'gca' => 'application/x-gca-compressed',
+		'gdl' => 'model/vnd.gdl',
+		'geo' => 'application/vnd.dynageo',
+		'gex' => 'application/vnd.geometry-explorer',
+		'ggb' => 'application/vnd.geogebra.file',
+		'ggt' => 'application/vnd.geogebra.tool',
+		'ghf' => 'application/vnd.groove-help',
+		'gif' => 'image/gif',
+		'gim' => 'application/vnd.groove-identity-message',
+		'gml' => 'application/gml+xml',
+		'gmx' => 'application/vnd.gmx',
+		'gnumeric' => 'application/x-gnumeric',
+		'gph' => 'application/vnd.flographit',
+		'gpx' => 'application/gpx+xml',
+		'gqf' => 'application/vnd.grafeq',
+		'gqs' => 'application/vnd.grafeq',
+		'gram' => 'application/srgs',
+		'gramps' => 'application/x-gramps-xml',
+		'gre' => 'application/vnd.geometry-explorer',
+		'grv' => 'application/vnd.groove-injector',
+		'grxml' => 'application/srgs+xml',
+		'gsf' => 'application/x-font-ghostscript',
+		'gtar' => 'application/x-gtar',
+		'gtm' => 'application/vnd.groove-tool-message',
+		'gtw' => 'model/vnd.gtw',
+		'gv' => 'text/vnd.graphviz',
+		'gxf' => 'application/gxf',
+		'gxt' => 'application/vnd.geonext',
+		'h' => 'text/x-c',
+		'h261' => 'video/h261',
+		'h263' => 'video/h263',
+		'h264' => 'video/h264',
+		'hal' => 'application/vnd.hal+xml',
+		'hbci' => 'application/vnd.hbci',
+		'hdf' => 'application/x-hdf',
+		'hh' => 'text/x-c',
+		'hlp' => 'application/winhlp',
+		'hpgl' => 'application/vnd.hp-hpgl',
+		'hpid' => 'application/vnd.hp-hpid',
+		'hps' => 'application/vnd.hp-hps',
+		'hqx' => 'application/mac-binhex40',
+		'htke' => 'application/vnd.kenameaapp',
+		'htm' => 'text/html',
+		'html' => 'text/html',
+		'hvd' => 'application/vnd.yamaha.hv-dic',
+		'hvp' => 'application/vnd.yamaha.hv-voice',
+		'hvs' => 'application/vnd.yamaha.hv-script',
+		'i2g' => 'application/vnd.intergeo',
+		'icc' => 'application/vnd.iccprofile',
+		'ice' => 'x-conference/x-cooltalk',
+		'icm' => 'application/vnd.iccprofile',
+		'ico' => 'image/x-icon',
+		'ics' => 'text/calendar',
+		'ief' => 'image/ief',
+		'ifb' => 'text/calendar',
+		'ifm' => 'application/vnd.shana.informed.formdata',
+		'iges' => 'model/iges',
+		'igl' => 'application/vnd.igloader',
+		'igm' => 'application/vnd.insors.igm',
+		'igs' => 'model/iges',
+		'igx' => 'application/vnd.micrografx.igx',
+		'iif' => 'application/vnd.shana.informed.interchange',
+		'imp' => 'application/vnd.accpac.simply.imp',
+		'ims' => 'application/vnd.ms-ims',
+		'in' => 'text/plain',
+		'ink' => 'application/inkml+xml',
+		'inkml' => 'application/inkml+xml',
+		'install' => 'application/x-install-instructions',
+		'iota' => 'application/vnd.astraea-software.iota',
+		'ipfix' => 'application/ipfix',
+		'ipk' => 'application/vnd.shana.informed.package',
+		'irm' => 'application/vnd.ibm.rights-management',
+		'irp' => 'application/vnd.irepository.package+xml',
+		'iso' => 'application/x-iso9660-image',
+		'itp' => 'application/vnd.shana.informed.formtemplate',
+		'ivp' => 'application/vnd.immervision-ivp',
+		'ivu' => 'application/vnd.immervision-ivu',
+		'jad' => 'text/vnd.sun.j2me.app-descriptor',
+		'jam' => 'application/vnd.jam',
+		'jar' => 'application/java-archive',
+		'java' => 'text/x-java-source',
+		'jisp' => 'application/vnd.jisp',
+		'jlt' => 'application/vnd.hp-jlyt',
+		'jnlp' => 'application/x-java-jnlp-file',
+		'joda' => 'application/vnd.joost.joda-archive',
+		'jpe' => 'image/jpeg',
+		'jpeg' => 'image/jpeg',
+		'jpg' => 'image/jpeg',
+		'jpgm' => 'video/jpm',
+		'jpgv' => 'video/jpeg',
+		'jpm' => 'video/jpm',
+		'js' => 'application/javascript',
+		'json' => 'application/json',
+		'jsonml' => 'application/jsonml+json',
+		'kar' => 'audio/midi',
+		'karbon' => 'application/vnd.kde.karbon',
+		'kfo' => 'application/vnd.kde.kformula',
+		'kia' => 'application/vnd.kidspiration',
+		'kml' => 'application/vnd.google-earth.kml+xml',
+		'kmz' => 'application/vnd.google-earth.kmz',
+		'kne' => 'application/vnd.kinar',
+		'knp' => 'application/vnd.kinar',
+		'kon' => 'application/vnd.kde.kontour',
+		'kpr' => 'application/vnd.kde.kpresenter',
+		'kpt' => 'application/vnd.kde.kpresenter',
+		'kpxx' => 'application/vnd.ds-keypoint',
+		'ksp' => 'application/vnd.kde.kspread',
+		'ktr' => 'application/vnd.kahootz',
+		'ktx' => 'image/ktx',
+		'ktz' => 'application/vnd.kahootz',
+		'kwd' => 'application/vnd.kde.kword',
+		'kwt' => 'application/vnd.kde.kword',
+		'lasxml' => 'application/vnd.las.las+xml',
+		'latex' => 'application/x-latex',
+		'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+		'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+		'les' => 'application/vnd.hhe.lesson-player',
+		'lha' => 'application/x-lzh-compressed',
+		'link66' => 'application/vnd.route66.link66+xml',
+		'list' => 'text/plain',
+		'list3820' => 'application/vnd.ibm.modcap',
+		'listafp' => 'application/vnd.ibm.modcap',
+		'lnk' => 'application/x-ms-shortcut',
+		'log' => 'text/plain',
+		'lostxml' => 'application/lost+xml',
+		'lrf' => 'application/octet-stream',
+		'lrm' => 'application/vnd.ms-lrm',
+		'ltf' => 'application/vnd.frogans.ltf',
+		'lvp' => 'audio/vnd.lucent.voice',
+		'lwp' => 'application/vnd.lotus-wordpro',
+		'lzh' => 'application/x-lzh-compressed',
+		'm13' => 'application/x-msmediaview',
+		'm14' => 'application/x-msmediaview',
+		'm1v' => 'video/mpeg',
+		'm21' => 'application/mp21',
+		'm2a' => 'audio/mpeg',
+		'm2v' => 'video/mpeg',
+		'm3a' => 'audio/mpeg',
+		'm3u' => 'audio/x-mpegurl',
+		'm3u8' => 'application/vnd.apple.mpegurl',
+		'm4a' => 'audio/mp4',
+		'm4u' => 'video/vnd.mpegurl',
+		'm4v' => 'video/x-m4v',
+		'ma' => 'application/mathematica',
+		'mads' => 'application/mads+xml',
+		'mag' => 'application/vnd.ecowin.chart',
+		'maker' => 'application/vnd.framemaker',
+		'man' => 'text/troff',
+		'mar' => 'application/octet-stream',
+		'mathml' => 'application/mathml+xml',
+		'mb' => 'application/mathematica',
+		'mbk' => 'application/vnd.mobius.mbk',
+		'mbox' => 'application/mbox',
+		'mc1' => 'application/vnd.medcalcdata',
+		'mcd' => 'application/vnd.mcd',
+		'mcurl' => 'text/vnd.curl.mcurl',
+		'mdb' => 'application/x-msaccess',
+		'mdi' => 'image/vnd.ms-modi',
+		'me' => 'text/troff',
+		'mesh' => 'model/mesh',
+		'meta4' => 'application/metalink4+xml',
+		'metalink' => 'application/metalink+xml',
+		'mets' => 'application/mets+xml',
+		'mfm' => 'application/vnd.mfmp',
+		'mft' => 'application/rpki-manifest',
+		'mgp' => 'application/vnd.osgeo.mapguide.package',
+		'mgz' => 'application/vnd.proteus.magazine',
+		'mid' => 'audio/midi',
+		'midi' => 'audio/midi',
+		'mie' => 'application/x-mie',
+		'mif' => 'application/vnd.mif',
+		'mime' => 'message/rfc822',
+		'mj2' => 'video/mj2',
+		'mjp2' => 'video/mj2',
+		'mk3d' => 'video/x-matroska',
+		'mka' => 'audio/x-matroska',
+		'mks' => 'video/x-matroska',
+		'mkv' => 'video/x-matroska',
+		'mlp' => 'application/vnd.dolby.mlp',
+		'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+		'mmf' => 'application/vnd.smaf',
+		'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+		'mng' => 'video/x-mng',
+		'mny' => 'application/x-msmoney',
+		'mobi' => 'application/x-mobipocket-ebook',
+		'mods' => 'application/mods+xml',
+		'mov' => 'video/quicktime',
+		'movie' => 'video/x-sgi-movie',
+		'mp2' => 'audio/mpeg',
+		'mp21' => 'application/mp21',
+		'mp2a' => 'audio/mpeg',
+		'mp3' => 'audio/mpeg',
+		'mp4' => 'video/mp4',
+		'mp4a' => 'audio/mp4',
+		'mp4s' => 'application/mp4',
+		'mp4v' => 'video/mp4',
+		'mpc' => 'application/vnd.mophun.certificate',
+		'mpe' => 'video/mpeg',
+		'mpeg' => 'video/mpeg',
+		'mpg' => 'video/mpeg',
+		'mpg4' => 'video/mp4',
+		'mpga' => 'audio/mpeg',
+		'mpkg' => 'application/vnd.apple.installer+xml',
+		'mpm' => 'application/vnd.blueice.multipass',
+		'mpn' => 'application/vnd.mophun.application',
+		'mpp' => 'application/vnd.ms-project',
+		'mpt' => 'application/vnd.ms-project',
+		'mpy' => 'application/vnd.ibm.minipay',
+		'mqy' => 'application/vnd.mobius.mqy',
+		'mrc' => 'application/marc',
+		'mrcx' => 'application/marcxml+xml',
+		'ms' => 'text/troff',
+		'mscml' => 'application/mediaservercontrol+xml',
+		'mseed' => 'application/vnd.fdsn.mseed',
+		'mseq' => 'application/vnd.mseq',
+		'msf' => 'application/vnd.epson.msf',
+		'msh' => 'model/mesh',
+		'msi' => 'application/x-msdownload',
+		'msl' => 'application/vnd.mobius.msl',
+		'msty' => 'application/vnd.muvee.style',
+		'mts' => 'model/vnd.mts',
+		'mus' => 'application/vnd.musician',
+		'musicxml' => 'application/vnd.recordare.musicxml+xml',
+		'mvb' => 'application/x-msmediaview',
+		'mwf' => 'application/vnd.mfer',
+		'mxf' => 'application/mxf',
+		'mxl' => 'application/vnd.recordare.musicxml',
+		'mxml' => 'application/xv+xml',
+		'mxs' => 'application/vnd.triscape.mxs',
+		'mxu' => 'video/vnd.mpegurl',
+		'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+		'n3' => 'text/n3',
+		'nb' => 'application/mathematica',
+		'nbp' => 'application/vnd.wolfram.player',
+		'nc' => 'application/x-netcdf',
+		'ncx' => 'application/x-dtbncx+xml',
+		'nfo' => 'text/x-nfo',
+		'ngdat' => 'application/vnd.nokia.n-gage.data',
+		'nitf' => 'application/vnd.nitf',
+		'nlu' => 'application/vnd.neurolanguage.nlu',
+		'nml' => 'application/vnd.enliven',
+		'nnd' => 'application/vnd.noblenet-directory',
+		'nns' => 'application/vnd.noblenet-sealer',
+		'nnw' => 'application/vnd.noblenet-web',
+		'npx' => 'image/vnd.net-fpx',
+		'nsc' => 'application/x-conference',
+		'nsf' => 'application/vnd.lotus-notes',
+		'ntf' => 'application/vnd.nitf',
+		'nzb' => 'application/x-nzb',
+		'oa2' => 'application/vnd.fujitsu.oasys2',
+		'oa3' => 'application/vnd.fujitsu.oasys3',
+		'oas' => 'application/vnd.fujitsu.oasys',
+		'obd' => 'application/x-msbinder',
+		'obj' => 'application/x-tgif',
+		'oda' => 'application/oda',
+		'odb' => 'application/vnd.oasis.opendocument.database',
+		'odc' => 'application/vnd.oasis.opendocument.chart',
+		'odf' => 'application/vnd.oasis.opendocument.formula',
+		'odft' => 'application/vnd.oasis.opendocument.formula-template',
+		'odg' => 'application/vnd.oasis.opendocument.graphics',
+		'odi' => 'application/vnd.oasis.opendocument.image',
+		'odm' => 'application/vnd.oasis.opendocument.text-master',
+		'odp' => 'application/vnd.oasis.opendocument.presentation',
+		'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+		'odt' => 'application/vnd.oasis.opendocument.text',
+		'oga' => 'audio/ogg',
+		'ogg' => 'audio/ogg',
+		'ogv' => 'video/ogg',
+		'ogx' => 'application/ogg',
+		'omdoc' => 'application/omdoc+xml',
+		'onepkg' => 'application/onenote',
+		'onetmp' => 'application/onenote',
+		'onetoc' => 'application/onenote',
+		'onetoc2' => 'application/onenote',
+		'opf' => 'application/oebps-package+xml',
+		'opml' => 'text/x-opml',
+		'oprc' => 'application/vnd.palm',
+		'org' => 'application/vnd.lotus-organizer',
+		'osf' => 'application/vnd.yamaha.openscoreformat',
+		'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+		'otc' => 'application/vnd.oasis.opendocument.chart-template',
+		'otf' => 'application/x-font-otf',
+		'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+		'oth' => 'application/vnd.oasis.opendocument.text-web',
+		'oti' => 'application/vnd.oasis.opendocument.image-template',
+		'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+		'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+		'ott' => 'application/vnd.oasis.opendocument.text-template',
+		'oxps' => 'application/oxps',
+		'oxt' => 'application/vnd.openofficeorg.extension',
+		'p' => 'text/x-pascal',
+		'p10' => 'application/pkcs10',
+		'p12' => 'application/x-pkcs12',
+		'p7b' => 'application/x-pkcs7-certificates',
+		'p7c' => 'application/pkcs7-mime',
+		'p7m' => 'application/pkcs7-mime',
+		'p7r' => 'application/x-pkcs7-certreqresp',
+		'p7s' => 'application/pkcs7-signature',
+		'p8' => 'application/pkcs8',
+		'pas' => 'text/x-pascal',
+		'paw' => 'application/vnd.pawaafile',
+		'pbd' => 'application/vnd.powerbuilder6',
+		'pbm' => 'image/x-portable-bitmap',
+		'pcap' => 'application/vnd.tcpdump.pcap',
+		'pcf' => 'application/x-font-pcf',
+		'pcl' => 'application/vnd.hp-pcl',
+		'pclxl' => 'application/vnd.hp-pclxl',
+		'pct' => 'image/x-pict',
+		'pcurl' => 'application/vnd.curl.pcurl',
+		'pcx' => 'image/x-pcx',
+		'pdb' => 'application/vnd.palm',
+		'pdf' => 'application/pdf',
+		'pfa' => 'application/x-font-type1',
+		'pfb' => 'application/x-font-type1',
+		'pfm' => 'application/x-font-type1',
+		'pfr' => 'application/font-tdpfr',
+		'pfx' => 'application/x-pkcs12',
+		'pgm' => 'image/x-portable-graymap',
+		'pgn' => 'application/x-chess-pgn',
+		'pgp' => 'application/pgp-encrypted',
+		'pic' => 'image/x-pict',
+		'pkg' => 'application/octet-stream',
+		'pki' => 'application/pkixcmp',
+		'pkipath' => 'application/pkix-pkipath',
+		'plb' => 'application/vnd.3gpp.pic-bw-large',
+		'plc' => 'application/vnd.mobius.plc',
+		'plf' => 'application/vnd.pocketlearn',
+		'pls' => 'application/pls+xml',
+		'pml' => 'application/vnd.ctc-posml',
+		'png' => 'image/png',
+		'pnm' => 'image/x-portable-anymap',
+		'portpkg' => 'application/vnd.macports.portpkg',
+		'pot' => 'application/vnd.ms-powerpoint',
+		'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
+		'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+		'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
+		'ppd' => 'application/vnd.cups-ppd',
+		'ppm' => 'image/x-portable-pixmap',
+		'pps' => 'application/vnd.ms-powerpoint',
+		'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+		'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+		'ppt' => 'application/vnd.ms-powerpoint',
+		'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+		'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+		'pqa' => 'application/vnd.palm',
+		'prc' => 'application/x-mobipocket-ebook',
+		'pre' => 'application/vnd.lotus-freelance',
+		'prf' => 'application/pics-rules',
+		'ps' => 'application/postscript',
+		'psb' => 'application/vnd.3gpp.pic-bw-small',
+		'psd' => 'image/vnd.adobe.photoshop',
+		'psf' => 'application/x-font-linux-psf',
+		'pskcxml' => 'application/pskc+xml',
+		'ptid' => 'application/vnd.pvi.ptid1',
+		'pub' => 'application/x-mspublisher',
+		'pvb' => 'application/vnd.3gpp.pic-bw-var',
+		'pwn' => 'application/vnd.3m.post-it-notes',
+		'pya' => 'audio/vnd.ms-playready.media.pya',
+		'pyv' => 'video/vnd.ms-playready.media.pyv',
+		'qam' => 'application/vnd.epson.quickanime',
+		'qbo' => 'application/vnd.intu.qbo',
+		'qfx' => 'application/vnd.intu.qfx',
+		'qps' => 'application/vnd.publishare-delta-tree',
+		'qt' => 'video/quicktime',
+		'qwd' => 'application/vnd.quark.quarkxpress',
+		'qwt' => 'application/vnd.quark.quarkxpress',
+		'qxb' => 'application/vnd.quark.quarkxpress',
+		'qxd' => 'application/vnd.quark.quarkxpress',
+		'qxl' => 'application/vnd.quark.quarkxpress',
+		'qxt' => 'application/vnd.quark.quarkxpress',
+		'ra' => 'audio/x-pn-realaudio',
+		'ram' => 'audio/x-pn-realaudio',
+		'rar' => 'application/x-rar-compressed',
+		'ras' => 'image/x-cmu-raster',
+		'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+		'rdf' => 'application/rdf+xml',
+		'rdz' => 'application/vnd.data-vision.rdz',
+		'rep' => 'application/vnd.businessobjects',
+		'res' => 'application/x-dtbresource+xml',
+		'rgb' => 'image/x-rgb',
+		'rif' => 'application/reginfo+xml',
+		'rip' => 'audio/vnd.rip',
+		'ris' => 'application/x-research-info-systems',
+		'rl' => 'application/resource-lists+xml',
+		'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+		'rld' => 'application/resource-lists-diff+xml',
+		'rm' => 'application/vnd.rn-realmedia',
+		'rmi' => 'audio/midi',
+		'rmp' => 'audio/x-pn-realaudio-plugin',
+		'rms' => 'application/vnd.jcp.javame.midlet-rms',
+		'rmvb' => 'application/vnd.rn-realmedia-vbr',
+		'rnc' => 'application/relax-ng-compact-syntax',
+		'roa' => 'application/rpki-roa',
+		'roff' => 'text/troff',
+		'rp9' => 'application/vnd.cloanto.rp9',
+		'rpss' => 'application/vnd.nokia.radio-presets',
+		'rpst' => 'application/vnd.nokia.radio-preset',
+		'rq' => 'application/sparql-query',
+		'rs' => 'application/rls-services+xml',
+		'rsd' => 'application/rsd+xml',
+		'rss' => 'application/rss+xml',
+		'rtf' => 'application/rtf',
+		'rtx' => 'text/richtext',
+		's' => 'text/x-asm',
+		's3m' => 'audio/s3m',
+		'saf' => 'application/vnd.yamaha.smaf-audio',
+		'sbml' => 'application/sbml+xml',
+		'sc' => 'application/vnd.ibm.secure-container',
+		'scd' => 'application/x-msschedule',
+		'scm' => 'application/vnd.lotus-screencam',
+		'scq' => 'application/scvp-cv-request',
+		'scs' => 'application/scvp-cv-response',
+		'scurl' => 'text/vnd.curl.scurl',
+		'sda' => 'application/vnd.stardivision.draw',
+		'sdc' => 'application/vnd.stardivision.calc',
+		'sdd' => 'application/vnd.stardivision.impress',
+		'sdkd' => 'application/vnd.solent.sdkm+xml',
+		'sdkm' => 'application/vnd.solent.sdkm+xml',
+		'sdp' => 'application/sdp',
+		'sdw' => 'application/vnd.stardivision.writer',
+		'see' => 'application/vnd.seemail',
+		'seed' => 'application/vnd.fdsn.seed',
+		'sema' => 'application/vnd.sema',
+		'semd' => 'application/vnd.semd',
+		'semf' => 'application/vnd.semf',
+		'ser' => 'application/java-serialized-object',
+		'setpay' => 'application/set-payment-initiation',
+		'setreg' => 'application/set-registration-initiation',
+		'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+		'sfs' => 'application/vnd.spotfire.sfs',
+		'sfv' => 'text/x-sfv',
+		'sgi' => 'image/sgi',
+		'sgl' => 'application/vnd.stardivision.writer-global',
+		'sgm' => 'text/sgml',
+		'sgml' => 'text/sgml',
+		'sh' => 'application/x-sh',
+		'shar' => 'application/x-shar',
+		'shf' => 'application/shf+xml',
+		'sid' => 'image/x-mrsid-image',
+		'sig' => 'application/pgp-signature',
+		'sil' => 'audio/silk',
+		'silo' => 'model/mesh',
+		'sis' => 'application/vnd.symbian.install',
+		'sisx' => 'application/vnd.symbian.install',
+		'sit' => 'application/x-stuffit',
+		'sitx' => 'application/x-stuffitx',
+		'skd' => 'application/vnd.koan',
+		'skm' => 'application/vnd.koan',
+		'skp' => 'application/vnd.koan',
+		'skt' => 'application/vnd.koan',
+		'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+		'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+		'slt' => 'application/vnd.epson.salt',
+		'sm' => 'application/vnd.stepmania.stepchart',
+		'smf' => 'application/vnd.stardivision.math',
+		'smi' => 'application/smil+xml',
+		'smil' => 'application/smil+xml',
+		'smv' => 'video/x-smv',
+		'smzip' => 'application/vnd.stepmania.package',
+		'snd' => 'audio/basic',
+		'snf' => 'application/x-font-snf',
+		'so' => 'application/octet-stream',
+		'spc' => 'application/x-pkcs7-certificates',
+		'spf' => 'application/vnd.yamaha.smaf-phrase',
+		'spl' => 'application/x-futuresplash',
+		'spot' => 'text/vnd.in3d.spot',
+		'spp' => 'application/scvp-vp-response',
+		'spq' => 'application/scvp-vp-request',
+		'spx' => 'audio/ogg',
+		'sql' => 'application/x-sql',
+		'src' => 'application/x-wais-source',
+		'srt' => 'application/x-subrip',
+		'sru' => 'application/sru+xml',
+		'srx' => 'application/sparql-results+xml',
+		'ssdl' => 'application/ssdl+xml',
+		'sse' => 'application/vnd.kodak-descriptor',
+		'ssf' => 'application/vnd.epson.ssf',
+		'ssml' => 'application/ssml+xml',
+		'st' => 'application/vnd.sailingtracker.track',
+		'stc' => 'application/vnd.sun.xml.calc.template',
+		'std' => 'application/vnd.sun.xml.draw.template',
+		'stf' => 'application/vnd.wt.stf',
+		'sti' => 'application/vnd.sun.xml.impress.template',
+		'stk' => 'application/hyperstudio',
+		'stl' => 'application/vnd.ms-pki.stl',
+		'str' => 'application/vnd.pg.format',
+		'stw' => 'application/vnd.sun.xml.writer.template',
+		'sub' => 'image/vnd.dvb.subtitle',
+		'sub' => 'text/vnd.dvb.subtitle',
+		'sus' => 'application/vnd.sus-calendar',
+		'susp' => 'application/vnd.sus-calendar',
+		'sv4cpio' => 'application/x-sv4cpio',
+		'sv4crc' => 'application/x-sv4crc',
+		'svc' => 'application/vnd.dvb.service',
+		'svd' => 'application/vnd.svd',
+		'svg' => 'image/svg+xml',
+		'svgz' => 'image/svg+xml',
+		'swa' => 'application/x-director',
+		'swf' => 'application/x-shockwave-flash',
+		'swi' => 'application/vnd.aristanetworks.swi',
+		'sxc' => 'application/vnd.sun.xml.calc',
+		'sxd' => 'application/vnd.sun.xml.draw',
+		'sxg' => 'application/vnd.sun.xml.writer.global',
+		'sxi' => 'application/vnd.sun.xml.impress',
+		'sxm' => 'application/vnd.sun.xml.math',
+		'sxw' => 'application/vnd.sun.xml.writer',
+		't' => 'text/troff',
+		't3' => 'application/x-t3vm-image',
+		'taglet' => 'application/vnd.mynfc',
+		'tao' => 'application/vnd.tao.intent-module-archive',
+		'tar' => 'application/x-tar',
+		'tcap' => 'application/vnd.3gpp2.tcap',
+		'tcl' => 'application/x-tcl',
+		'teacher' => 'application/vnd.smart.teacher',
+		'tei' => 'application/tei+xml',
+		'teicorpus' => 'application/tei+xml',
+		'tex' => 'application/x-tex',
+		'texi' => 'application/x-texinfo',
+		'texinfo' => 'application/x-texinfo',
+		'text' => 'text/plain',
+		'tfi' => 'application/thraud+xml',
+		'tfm' => 'application/x-tex-tfm',
+		'tga' => 'image/x-tga',
+		'thmx' => 'application/vnd.ms-officetheme',
+		'tif' => 'image/tiff',
+		'tiff' => 'image/tiff',
+		'tmo' => 'application/vnd.tmobile-livetv',
+		'torrent' => 'application/x-bittorrent',
+		'tpl' => 'application/vnd.groove-tool-template',
+		'tpt' => 'application/vnd.trid.tpt',
+		'tr' => 'text/troff',
+		'tra' => 'application/vnd.trueapp',
+		'trm' => 'application/x-msterminal',
+		'tsd' => 'application/timestamped-data',
+		'tsv' => 'text/tab-separated-values',
+		'ttc' => 'application/x-font-ttf',
+		'ttf' => 'application/x-font-ttf',
+		'ttl' => 'text/turtle',
+		'twd' => 'application/vnd.simtech-mindmapper',
+		'twds' => 'application/vnd.simtech-mindmapper',
+		'txd' => 'application/vnd.genomatix.tuxedo',
+		'txf' => 'application/vnd.mobius.txf',
+		'txt' => 'text/plain',
+		'u32' => 'application/x-authorware-bin',
+		'udeb' => 'application/x-debian-package',
+		'ufd' => 'application/vnd.ufdl',
+		'ufdl' => 'application/vnd.ufdl',
+		'ulx' => 'application/x-glulx',
+		'umj' => 'application/vnd.umajin',
+		'unityweb' => 'application/vnd.unity',
+		'uoml' => 'application/vnd.uoml+xml',
+		'uri' => 'text/uri-list',
+		'uris' => 'text/uri-list',
+		'urls' => 'text/uri-list',
+		'ustar' => 'application/x-ustar',
+		'utz' => 'application/vnd.uiq.theme',
+		'uu' => 'text/x-uuencode',
+		'uva' => 'audio/vnd.dece.audio',
+		'uvd' => 'application/vnd.dece.data',
+		'uvf' => 'application/vnd.dece.data',
+		'uvg' => 'image/vnd.dece.graphic',
+		'uvh' => 'video/vnd.dece.hd',
+		'uvi' => 'image/vnd.dece.graphic',
+		'uvm' => 'video/vnd.dece.mobile',
+		'uvp' => 'video/vnd.dece.pd',
+		'uvs' => 'video/vnd.dece.sd',
+		'uvt' => 'application/vnd.dece.ttml+xml',
+		'uvu' => 'video/vnd.uvvu.mp4',
+		'uvv' => 'video/vnd.dece.video',
+		'uvva' => 'audio/vnd.dece.audio',
+		'uvvd' => 'application/vnd.dece.data',
+		'uvvf' => 'application/vnd.dece.data',
+		'uvvg' => 'image/vnd.dece.graphic',
+		'uvvh' => 'video/vnd.dece.hd',
+		'uvvi' => 'image/vnd.dece.graphic',
+		'uvvm' => 'video/vnd.dece.mobile',
+		'uvvp' => 'video/vnd.dece.pd',
+		'uvvs' => 'video/vnd.dece.sd',
+		'uvvt' => 'application/vnd.dece.ttml+xml',
+		'uvvu' => 'video/vnd.uvvu.mp4',
+		'uvvv' => 'video/vnd.dece.video',
+		'uvvx' => 'application/vnd.dece.unspecified',
+		'uvvz' => 'application/vnd.dece.zip',
+		'uvx' => 'application/vnd.dece.unspecified',
+		'uvz' => 'application/vnd.dece.zip',
+		'vcard' => 'text/vcard',
+		'vcd' => 'application/x-cdlink',
+		'vcf' => 'text/x-vcard',
+		'vcg' => 'application/vnd.groove-vcard',
+		'vcs' => 'text/x-vcalendar',
+		'vcx' => 'application/vnd.vcx',
+		'vis' => 'application/vnd.visionary',
+		'viv' => 'video/vnd.vivo',
+		'vob' => 'video/x-ms-vob',
+		'vor' => 'application/vnd.stardivision.writer',
+		'vox' => 'application/x-authorware-bin',
+		'vrml' => 'model/vrml',
+		'vsd' => 'application/vnd.visio',
+		'vsf' => 'application/vnd.vsf',
+		'vss' => 'application/vnd.visio',
+		'vst' => 'application/vnd.visio',
+		'vsw' => 'application/vnd.visio',
+		'vtu' => 'model/vnd.vtu',
+		'vxml' => 'application/voicexml+xml',
+		'w3d' => 'application/x-director',
+		'wad' => 'application/x-doom',
+		'wav' => 'audio/x-wav',
+		'wax' => 'audio/x-ms-wax',
+		'wbmp' => 'image/vnd.wap.wbmp',
+		'wbs' => 'application/vnd.criticaltools.wbs+xml',
+		'wbxml' => 'application/vnd.wap.wbxml',
+		'wcm' => 'application/vnd.ms-works',
+		'wdb' => 'application/vnd.ms-works',
+		'wdp' => 'image/vnd.ms-photo',
+		'weba' => 'audio/webm',
+		'webm' => 'video/webm',
+		'webp' => 'image/webp',
+		'wg' => 'application/vnd.pmi.widget',
+		'wgt' => 'application/widget',
+		'wks' => 'application/vnd.ms-works',
+		'wm' => 'video/x-ms-wm',
+		'wma' => 'audio/x-ms-wma',
+		'wmd' => 'application/x-ms-wmd',
+		'wmf' => 'application/x-msmetafile',
+		'wml' => 'text/vnd.wap.wml',
+		'wmlc' => 'application/vnd.wap.wmlc',
+		'wmls' => 'text/vnd.wap.wmlscript',
+		'wmlsc' => 'application/vnd.wap.wmlscriptc',
+		'wmv' => 'video/x-ms-wmv',
+		'wmx' => 'video/x-ms-wmx',
+		'wmz' => 'application/x-ms-wmz',
+		'wmz' => 'application/x-msmetafile',
+		'woff' => 'application/font-woff',
+		'wpd' => 'application/vnd.wordperfect',
+		'wpl' => 'application/vnd.ms-wpl',
+		'wps' => 'application/vnd.ms-works',
+		'wqd' => 'application/vnd.wqd',
+		'wri' => 'application/x-mswrite',
+		'wrl' => 'model/vrml',
+		'wsdl' => 'application/wsdl+xml',
+		'wspolicy' => 'application/wspolicy+xml',
+		'wtb' => 'application/vnd.webturbo',
+		'wvx' => 'video/x-ms-wvx',
+		'x32' => 'application/x-authorware-bin',
+		'x3d' => 'model/x3d+xml',
+		'x3db' => 'model/x3d+binary',
+		'x3dbz' => 'model/x3d+binary',
+		'x3dv' => 'model/x3d+vrml',
+		'x3dvz' => 'model/x3d+vrml',
+		'x3dz' => 'model/x3d+xml',
+		'xaml' => 'application/xaml+xml',
+		'xap' => 'application/x-silverlight-app',
+		'xar' => 'application/vnd.xara',
+		'xbap' => 'application/x-ms-xbap',
+		'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+		'xbm' => 'image/x-xbitmap',
+		'xdf' => 'application/xcap-diff+xml',
+		'xdm' => 'application/vnd.syncml.dm+xml',
+		'xdp' => 'application/vnd.adobe.xdp+xml',
+		'xdssc' => 'application/dssc+xml',
+		'xdw' => 'application/vnd.fujixerox.docuworks',
+		'xenc' => 'application/xenc+xml',
+		'xer' => 'application/patch-ops-error+xml',
+		'xfdf' => 'application/vnd.adobe.xfdf',
+		'xfdl' => 'application/vnd.xfdl',
+		'xht' => 'application/xhtml+xml',
+		'xhtml' => 'application/xhtml+xml',
+		'xhvml' => 'application/xv+xml',
+		'xif' => 'image/vnd.xiff',
+		'xla' => 'application/vnd.ms-excel',
+		'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
+		'xlc' => 'application/vnd.ms-excel',
+		'xlf' => 'application/x-xliff+xml',
+		'xlm' => 'application/vnd.ms-excel',
+		'xls' => 'application/vnd.ms-excel',
+		'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+		'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
+		'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+		'xlt' => 'application/vnd.ms-excel',
+		'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
+		'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+		'xlw' => 'application/vnd.ms-excel',
+		'xm' => 'audio/xm',
+		'xml' => 'application/xml',
+		'xo' => 'application/vnd.olpc-sugar',
+		'xop' => 'application/xop+xml',
+		'xpi' => 'application/x-xpinstall',
+		'xpl' => 'application/xproc+xml',
+		'xpm' => 'image/x-xpixmap',
+		'xpr' => 'application/vnd.is-xpr',
+		'xps' => 'application/vnd.ms-xpsdocument',
+		'xpw' => 'application/vnd.intercon.formnet',
+		'xpx' => 'application/vnd.intercon.formnet',
+		'xsl' => 'application/xml',
+		'xslt' => 'application/xslt+xml',
+		'xsm' => 'application/vnd.syncml+xml',
+		'xspf' => 'application/xspf+xml',
+		'xul' => 'application/vnd.mozilla.xul+xml',
+		'xvm' => 'application/xv+xml',
+		'xvml' => 'application/xv+xml',
+		'xwd' => 'image/x-xwindowdump',
+		'xyz' => 'chemical/x-xyz',
+		'xz' => 'application/x-xz',
+		'yang' => 'application/yang',
+		'yin' => 'application/yin+xml',
+		'z1' => 'application/x-zmachine',
+		'z2' => 'application/x-zmachine',
+		'z3' => 'application/x-zmachine',
+		'z4' => 'application/x-zmachine',
+		'z5' => 'application/x-zmachine',
+		'z6' => 'application/x-zmachine',
+		'z7' => 'application/x-zmachine',
+		'z8' => 'application/x-zmachine',
+		'zaz' => 'application/vnd.zzazz.deck+xml',
+		'zip' => 'application/zip',
+		'zir' => 'application/vnd.zul',
+		'zirz' => 'application/vnd.zul',
+		'zmm' => 'application/vnd.handheld-entertainment+xml'
+	);	
+}
+
 // Always run this
 dependCheck();

+ 141 - 113
homepage.php

@@ -7,11 +7,7 @@ ini_set("error_reporting", E_ALL | E_STRICT);
 
 require_once("user.php");
 require_once("functions.php");
-use Kryptonit3\Sonarr\Sonarr;
-use Kryptonit3\SickRage\SickRage;
-$sonarr = new Sonarr(SONARRURL, SONARRKEY);
-$radarr = new Sonarr(RADARRURL, RADARRKEY);
-$sickrage = new SickRage(SICKRAGEURL, SICKRAGEKEY);
+
 $USER = new User("registration_callback");
 
 // Check if connection to homepage is allowed
@@ -22,9 +18,6 @@ foreach(loadAppearance() as $key => $value) {
 	${$key} = $value;
 }
 
-$startDate = date('Y-m-d',strtotime("-".CALENDARSTARTDAY." days"));
-$endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days")); 
-
 ?>
 
 <!DOCTYPE html>
@@ -370,17 +363,6 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                                         <a id="getDownloader" class="repeat-btn">
                                             <i class="fa fa-repeat"></i>
                                         </a>
-                                        <a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
-                                            <i class="fa fa-chevron-down"></i>
-                                        </a>
-										<!-- Lets Move This To Homepage Settings
-                                        <ul id="downloaderSeconds" class="dropdown-menu" style="top: 32px !important">
-                                            <li data-value="5000"><a>Refresh every 5 seconds</a></li>
-                                            <li data-value="10000"><a>Refresh every 10 seconds</a></li>
-                                            <li data-value="30000"><a>Refresh every 30 seconds</a></li>
-                                            <li data-value="60000"><a>Refresh every 60 seconds</a></li>
-                                        </ul>
-										-->
                                     </div>
                                     <h3 class="pull-left"><?php if(NZBGETURL != ""){ echo "NZBGet "; } if(SABNZBDURL != ""){ echo "SABnzbd "; } ?></h3>
                                     <ul class="nav nav-tabs pull-right">
@@ -446,11 +428,7 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                 </div>
                 <div id="plexPlaylists" class="row">
                     <div class="col-lg-12">
-                    <?php
-                    if(PLEXPLAYLISTS == "true"){  
-                        echo getPlexPlaylists($plexArray);
-                    } 
-                    ?>
+                    <?php if(PLEXPLAYLISTS == "true"){ echo getPlexPlaylists($plexArray); } ?>
                     </div>
                 </div>
                 <?php } ?>
@@ -465,8 +443,7 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                     if(EMBYRECENTMOVIE == "true" || EMBYRECENTTV == "true" || EMBYRECENTMUSIC == "true"){  
                         $embyArray = array("Movie" => EMBYRECENTMOVIE, "Episode" => EMBYRECENTTV, "MusicAlbum" => EMBYRECENTMUSIC, "Series" => EMBYRECENTTV);
                         echo getEmbyRecent($embyArray);
-                    } 
-    
+                    }
                     ?>
                     </div>
 
@@ -523,7 +500,96 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
         });
         
 		$(document).on("click", ".openTab", function(e) {
-			if($(this).attr("openTab") === "true") {
+            var Title = $(this).attr("extraTitle");
+            var Type = $(this).attr("extraType");
+            var openTab = $(this).attr("openTab");
+            var location = $(this).attr("href");
+            if( Type === 'season' || Type === 'episode' || Type === 'show'){
+                Type = "tv";
+                SearchType = "show";
+            }else if( Type === 'movie'){
+                Type = "movie";
+                SearchType = "movie";            
+            }
+            if( Type === 'tv' || Type === 'movie' ){
+                $('#calendarExtra').modal('show');
+                var refreshBox = $('#calendarMainID');
+                $("<div class='refresh-preloader'><div class='la-timer la-dark'><div></div></div></div>").appendTo(refreshBox).fadeIn(300);
+                setTimeout(function(){
+                    var refreshPreloader = refreshBox.find('.refresh-preloader'),
+                    deletedRefreshBox = refreshPreloader.fadeOut(300, function(){
+                        refreshPreloader.remove();
+                    });
+                },600);
+                ajax_request('POST', 'tvdb-search', {
+                    name: Title,
+                    type: SearchType,
+                }).done(function(data){ 
+                    if( data.trakt ) {               
+                        $.ajax({
+                            type: 'GET',
+                            url: 'https://api.themoviedb.org/3/'+Type+'/'+data.trakt.tmdb+'?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&append_to_response=videos,credits',
+                            cache: true,
+                            async: true,
+                            complete: function(xhr, status) {
+                                var result = $.parseJSON(xhr.responseText);
+                                if (xhr.statusText === "OK") {
+                                    if( Type === "movie"){ 
+                                        $('#calendarTitle').html(result.title);
+                                        $('#calendarRating').html('<span class="label label-gray"><i class="fa fa-thumbs-up white"></i> '+result.vote_average+'</span>&nbsp;');
+                                        $('#calendarRuntime').html('<span class="label label-gray"><i class="fa fa-clock-o white"></i> '+convertTime(result.runtime)+'</span>&nbsp;');
+                                        $('#calendarSummary').text(result.overview);
+                                        $('#calendarTagline').text(result.tagline);
+                                        $('#calendarTrailer').html(convertTrailer(result.videos)+'&nbsp;<span class="label openPlex palette-Amber-600 bg" openTab="'+openTab+'" location="'+location+'" style="width:100%;display:block;cursor:pointer;"><i style="vertical-align:sub;" class="fa fa-play white"></i><text style="vertical-align:sub;"> Watch Now on PLEX</text></span>');
+                                        $('#calendarCast').html(convertCast(result.credits));
+                                        $('#calendarGenres').html(convertArray(result.genres, "MOVIE"));
+                                        $('#calendarLang').html(convertArray(result.spoken_languages, "MOVIE"));
+                                        $('#calendarPoster').attr("src","https://image.tmdb.org/t/p/w300"+result.poster_path);
+                                        $('#calendarMain').attr("style","background-size: cover; background: linear-gradient(rgba(25,27,29,.75),rgba(25,27,29,.75)),url(https://image.tmdb.org/t/p/w1000"+result.backdrop_path+");top: 0;left: 0;width: 100%;height: 100%;position: fixed;");
+                                        $('#calendarExtra').modal('show');
+                                    }else if (Type === "tv"){
+                                        $('#calendarTitle').html(result.name);
+                                        $('#calendarRating').html('<span class="label label-gray"><i class="fa fa-thumbs-up white"></i> '+result.vote_average+'</span>&nbsp;');
+                                        $('#calendarRuntime').html('<span class="label label-gray"><i class="fa fa-clock-o white"></i> '+convertTime(whatWasIt(result.episode_run_time))+'</span>&nbsp;');
+                                        $('#calendarSummary').text(result.overview);
+                                        $('#calendarTagline').text("");
+                                        $('#calendarTrailer').html(convertTrailer(result.videos)+'&nbsp;<span class="label openPlex palette-Amber-600 bg" openTab="'+openTab+'" location="'+location+'" style="width:100%;display:block;cursor:pointer;"><i style="vertical-align:sub;" class="fa fa-play white"></i><text style="vertical-align:sub;"> Watch Now on PLEX</text></span>');
+                                        $('#calendarCast').html(convertCast(result.credits));
+                                        $('#calendarGenres').html(convertArray(result.genres, "MOVIE"));
+                                        $('#calendarLang').html(convertArray(result.languages, "TV"));
+                                        $('#calendarPoster').attr("src","https://image.tmdb.org/t/p/w300"+result.poster_path);
+                                        $('#calendarMain').attr("style","background-size: cover; background: linear-gradient(rgba(25,27,29,.75),rgba(25,27,29,.75)),url(https://image.tmdb.org/t/p/w1000"+result.backdrop_path+");top: 0;left: 0;width: 100%;height: 100%;position: fixed;");
+                                        $('#calendarExtra').modal('show');
+                                    }
+                                }
+                            }
+                        });
+                    }
+                });
+                e.preventDefault();
+            }else{
+
+                if($(this).attr("openTab") === "true") {
+                    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"));
+                        parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
+                    }else{
+                        parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
+                        parent.$("div[data-content-name^='<?php echo strtolower(PLEXTABNAME);?>']").children('iframe').attr("src", $(this).attr("href"));
+                    }
+                    e.preventDefault();
+                }else{
+                    var source = $(this).attr("href");
+                    window.open(source, '_blank');
+                }
+            }
+
+        });
+
+        $(document).on("click", ".openPlex", function(e) {
+            if($(this).attr("openTab") === "true") {
 				var isActive = parent.$("div[data-content-name^='<?php echo strtolower(PLEXTABNAME);?>']");
 				var activeFrame = isActive.children('iframe');
 				if(isActive.length === 1){
@@ -531,13 +597,12 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
 					parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
 				}else{
 					parent.$("li[name='<?php echo strtolower(PLEXTABNAME);?>']").trigger("click");
-					parent.$("div[data-content-name^='<?php echo strtolower(PLEXTABNAME);?>']").children('iframe').attr("src", $(this).attr("href"));
+					parent.$("div[data-content-name^='<?php echo strtolower(PLEXTABNAME);?>']").children('iframe').attr("src", $(this).attr("location"));
 				}
-				e.preventDefault();
 			}else{
-				console.log("nope");
+                var source = $(this).attr("location");
+				window.open(source, '_blank');
 			}
-
         });
         
             
@@ -668,51 +733,18 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
             //RECENT ITEMS
             // each filter we click on
             $(".filter-recent-event > li").on("click", function() {
-                    
-                // toggle the filter on/off
-                $(this).data( "filter-on" , !$(this).data("filter-on") );
-                
-                // set all the filter strings to empty
-                var filtersOn = "";
-                var filtersOff = "";
-                var allFilters = "";
-                
-                // loop through each filter
-                $(".filter-recent-event > li").each(function() {
-                    
-                    // set a variable to hold the value of the filter class
-                    // and also if the filter is on/off
-                    var filter = $(this).data("filter");
-                    var isOn = $(this).data("filter-on");
-
-                    // add the filter to the filtersOn / filtersOff collection
-                    if( isOn ) {
-                        filtersOn += "." + filter + ", ";
-                    } else {
-                        filtersOff += "." + filter + ", ";
-                    }
-
-                });
-                
-                // remove the last ", " from each filter collection.
-                filtersOn = filtersOn.replace(/, $/, "");
-                filtersOff = filtersOff.replace(/, $/, "");
-                
-                // remove all filters if none are on.
-                if( filtersOn === "" ) {
-                    filtersOn = "*";
-                    filtersOff = "";
-                }
-                
-                // combine the filters together ( on + off )
-                allFilters = filtersOn + ":not(" + filtersOff + ")";
-                console.log( allFilters );
-                
+                var name = $(this).attr('data-name');
+                var filter = $(this).attr('data-filter');
+                $('#recentContent-title').text('Recently Added '+name);
                 // now filter the slides.
-                $('.recentItems-recent')
-                    .slick('slickUnfilter')
-                    .slick('slickFilter' , allFilters );
-
+                if(filter !== 'item-all'){
+                    $('.recentItems-recent')
+                        .slick('slickUnfilter')
+                        .slick('slickFilter' , '.'+filter );
+                }else{
+                    $('.recentItems-recent')
+                        .slick('slickUnfilter')
+                }
             });
             //PLAYLIST SHIT
              // each filter we click on
@@ -725,7 +757,6 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                 $('.recentItems-playlists')
                     .slick('slickUnfilter')
                     .slick('slickFilter' , '.'+filter );
-
             });
 
             $("body").niceScroll({
@@ -738,6 +769,11 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                 scrollspeed: 30,
                 mousescrollstep: 60
             });
+            $(".playlist-listing").niceScroll({
+                railpadding: {top:0,right:0,left:0,bottom:0},
+                scrollspeed: 30,
+                mousescrollstep: 60
+            });
 
             <?php if((NZBGETURL != "" && qualifyUser(NZBGETHOMEAUTH)) || (SABNZBDURL != "" && qualifyUser(SABNZBDHOMEAUTH))){ ?>
             var queueRefresh = <?php echo DOWNLOADREFRESH; ?>;
@@ -799,39 +835,7 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
                         month: { buttonText: '<?php echo $language->translate("MONTH");?>', eventLimit: false },
                         today: { buttonText: '<?php echo $language->translate("TODAY");?>' },
                     },
-                    events: [
-<?php 
-if (SICKRAGEURL != "" && qualifyUser(SICKRAGEHOMEAUTH)){
-	try { 
-		echo getSickrageCalendarWanted($sickrage->future());
-	} catch (Exception $e) { 
-		writeLog("error", "SICKRAGE/BEARD ERROR: ".strip($e->getMessage())); 
-	} try { 
-		echo getSickrageCalendarHistory($sickrage->history("100","downloaded"));
-	} catch (Exception $e) { 
-		writeLog("error", "SICKRAGE/BEARD ERROR: ".strip($e->getMessage())); 
-	}
-}
-if (SONARRURL != "" && qualifyUser(SONARRHOMEAUTH)){
-	try {
-		echo getSonarrCalendar($sonarr->getCalendar($startDate, $endDate)); 
-	} catch (Exception $e) { 
-		writeLog("error", "SONARR ERROR: ".strip($e->getMessage())); 
-	}
-}
-if (RADARRURL != "" && qualifyUser(RADARRHOMEAUTH)){ 
-	try { 
-		echo getRadarrCalendar($radarr->getCalendar($startDate, $endDate)); 
-	} catch (Exception $e) { 
-		writeLog("error", "RADARR ERROR: ".strip($e->getMessage())); 
-	}
-}
-if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
-	echo getHeadphonesCalendar(HEADPHONESURL, HEADPHONESKEY, "getHistory"); 
-	echo getHeadphonesCalendar(HEADPHONESURL, HEADPHONESKEY, "getWanted"); 
-
-}?>                                
-                    ],
+                    //events: [ <?php //echo getCalendar(); ?> ],
                     eventRender: function eventRender( event, element, view ) {
                         return ['all', event.imagetype].indexOf($('#imagetype_selector').val()) >= 0
                     },
@@ -844,6 +848,30 @@ if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
             $('#imagetype_selector').on('change',function(){
                 $('#calendar').fullCalendar('rerenderEvents');
             })
+            $.ajax({
+                type: 'GET',
+                url: 'ajax.php?a=get-calendar',
+                success: function(data)
+                {
+                    newData =  $.parseJSON(data);
+                    $('#calendar').fullCalendar('removeEvents');
+                    $('#calendar').fullCalendar('addEventSource', newData);   
+                    console.log('Calendar Entries Added');      
+                }
+            });
+            setInterval(function() {
+                $.ajax({
+                    type: 'GET',
+                    url: 'ajax.php?a=get-calendar',
+                    success: function(data)
+                    {
+                        newData =  $.parseJSON(data);
+                        $('#calendar').fullCalendar('removeEvents');
+                        $('#calendar').fullCalendar('addEventSource', newData);  
+                        console.log('Calendar refreshed');       
+                    }
+                });
+            }, 60000);
         </script>
         <?php } ?>
         <script>
@@ -876,7 +904,7 @@ if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
                 var count = 1;
                 $.each( a.results, function( key, value ) {
                     if (count == 1){
-                        result += '<span id="openTrailer" style="cursor:pointer;width: 100%;display: block;" data-key="'+value['key']+'" data-name="'+value['name']+'" data-site="'+value['site']+'" class="label label-danger"><i class="fa fa-youtube-play" aria-hidden="true"></i> &nbsp;Watch Trailer</span>&nbsp;';
+                        result += '<span id="openTrailer" style="cursor:pointer;width: 100%;display: block;" data-key="'+value['key']+'" data-name="'+value['name']+'" data-site="'+value['site']+'" class="label label-danger"><i style="vertical-align:sub;" class="fa fa-youtube-play" aria-hidden="true"></i><text style="vertical-align:sub;"> Watch Trailer</text></span>&nbsp;';
                     }
                     count++;
                 });
@@ -888,7 +916,7 @@ if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
                 $.each( a.cast, function( key, value ) {
                     if( value['profile_path'] ){
                         if (count <= 6){
-                            result += '<div class="col-lg-2 col-xs-2"><div class="zero-m"><img style="border-radius:10%;margin-left: auto;margin-right: auto;display: block;" height="50px" src="https://image.tmdb.org/t/p/w150'+value['profile_path']+'" alt="profile"><h5 class="text-center"><strong>'+value['name']+'</strong></h5><h6 class="text-center">'+value['character']+'</h6></div></div>';
+                            result += '<div class="col-lg-4 col-xs-4"><div class="zero-m"><img class="pull-left" style="border-radius:10%;margin-left: auto;margin-right: auto;display: block;" height="100px" src="https://image.tmdb.org/t/p/w150'+value['profile_path']+'" alt="profile"><h5 class="text-center"><strong>'+value['name']+'</strong></h5><h6 class="text-center">'+value['character']+'</h6></div></div>';
                             count++;
                         }
                     }
@@ -925,7 +953,7 @@ if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
                     deletedRefreshBox = refreshPreloader.fadeOut(300, function(){
                         refreshPreloader.remove();
                     });
-                },300);
+                },600);
                 var check = $(this).attr("class");
                 var ID = check.split("--")[1];
                 if (~check.indexOf("tvID")){
@@ -1027,7 +1055,7 @@ if (HEADPHONESURL != "" && qualifyUser(HEADPHONESHOMEAUTH)){
                     </div>
                    <div style="position: inherit; padding: 15px 0px 30px 0px; margin-top: -20px;">
                         <div class="col-sm-4">
-                            <span id="calendarTrailer" class="pull-left" style="width:100%"></span>
+                            <span id="calendarTrailer" class="pull-left" style="width:100%;display: flex;"></span>
                         </div> 
                         <div class="col-sm-8">   
                             <span id="calendarLang" class="pull-right"></span>

BIN
images/backup.png


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 736 - 830
index.php


+ 4 - 0
lang/en.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 4 - 0
lang/es.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 4 - 0
lang/fr.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 4 - 0
lang/it.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 4 - 0
lang/nl.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 4 - 0
lang/pl.ini

@@ -312,3 +312,7 @@ CHECK_FRAME = "Test Frame"
 GENERATE_API_KEY = "Generate API Key"
 ORGANIZR_API_KEY = "Organizr API Key"
 TEST_EMAIL = "Send Test E-Mail"
+BACKUP_CREATED = "Backup Created"
+BACKUP_ERROR = "Backup Creation Error"
+BACKUP_NOW = "Backup Now"
+BACKUP_LIST = "Backup List"

+ 242 - 0
logs.php

@@ -0,0 +1,242 @@
+<?php
+// Some PHP config stuff
+ini_set("display_errors", 1);
+ini_set("error_reporting", E_ALL | E_STRICT);
+// Include functions if not already included
+require_once('functions.php');
+
+// Upgrade environment
+upgradeCheck();
+
+// Lazyload settings
+$databaseConfig = configLazy('config/config.php');
+
+// Load USER
+require_once("user.php");
+qualifyUser("admin", true);
+$USER = new User("registration_callback");
+
+// Load Colours/Appearance
+foreach(loadAppearance() as $key => $value) {
+	$$key = $value;
+}
+
+$logs = getLogs();
+
+?>
+
+<!DOCTYPE html>
+
+<html lang="en" class="no-js">
+    <head>
+       <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="msapplication-tap-highlight" content="no" />
+
+        <title><?=$title;?> Logs</title>
+
+        <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css?v=<?php echo INSTALLEDVERSION; ?>">
+        <link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css">
+        <link rel="stylesheet" href="bower_components/mdi/css/materialdesignicons.min.css">
+        <link rel="stylesheet" href="bower_components/metisMenu/dist/metisMenu.min.css">
+        <link rel="stylesheet" href="bower_components/Waves/dist/waves.min.css"> 
+        <link rel="stylesheet" href="bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css"> 
+
+        <link rel="stylesheet" href="js/selects/cs-select.css">
+        <link rel="stylesheet" href="js/selects/cs-skin-elastic.css">
+        <link href="bower_components/iconpick/dist/css/fontawesome-iconpicker.min.css" rel="stylesheet">
+        <link rel="stylesheet" href="bower_components/google-material-color/dist/palette.css">
+        <link rel="stylesheet" href="bower_components/sweetalert/dist/sweetalert.css">
+        <link rel="stylesheet" href="bower_components/smoke/dist/css/smoke.min.css">
+
+        <script src="js/menu/modernizr.custom.js"></script>
+        <script type="text/javascript" src="js/sha1.js"></script>
+        <script type="text/javascript" src="js/user.js"></script>
+        <link rel="stylesheet" href="bower_components/animate.css/animate.min.css">
+        <link rel="stylesheet" href="bower_components/DataTables/media/css/jquery.dataTables.css">
+        <link rel="stylesheet" href="bower_components/datatables-tabletools/css/dataTables.tableTools.css">
+        <link rel="stylesheet" href="bower_components/numbered/jquery.numberedtextarea.css">
+
+        <link rel="stylesheet" href="css/style.css?v=<?php echo INSTALLEDVERSION; ?>">
+        <link rel="stylesheet" href="css/settings.css?v=<?php echo INSTALLEDVERSION; ?>">
+        <link rel="stylesheet" href="bower_components/summernote/dist/summernote.css">
+        <link href="css/jquery.filer.css" rel="stylesheet">
+	    <link href="css/jquery.filer-dragdropbox-theme.css" rel="stylesheet">
+
+        <!--[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]-->
+		
+        <!--Scripts-->
+        <script src="bower_components/jquery/dist/jquery.min.js"></script>
+        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
+        <script src="bower_components/metisMenu/dist/metisMenu.min.js"></script>
+        <script src="bower_components/Waves/dist/waves.min.js"></script>
+        <script src="bower_components/moment/min/moment.min.js"></script>
+        <script src="bower_components/jquery.nicescroll/jquery.nicescroll.min.js"></script>
+        <script src="bower_components/slimScroll/jquery.slimscroll.min.js"></script>
+        <script src="bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js"></script>
+        <script src="bower_components/cta/dist/cta.min.js"></script>
+
+        <!--Menu-->
+        <script src="js/menu/classie.js"></script>
+        <script src="bower_components/iconpick/dist/js/fontawesome-iconpicker.js"></script>
+
+
+        <!--Selects-->
+        <script src="js/selects/selectFx.js"></script>
+        <script src="js/jscolor.js"></script>
+        <script src="bower_components/sweetalert/dist/sweetalert.min.js"></script>
+
+        <script src="bower_components/smoke/dist/js/smoke.min.js"></script>
+        <script src="bower_components/numbered/jquery.numberedtextarea.js"></script>
+		
+        <!--Other-->
+        <script src="js/ajax.js?v=<?php echo INSTALLEDVERSION; ?>"></script>
+
+        <!--Notification-->
+        <script src="js/notifications/notificationFx.js"></script>
+
+        <script src="js/jqueri_ui_custom/jquery-ui.min.js"></script>
+        <script src="js/jquery.filer.min.js" type="text/javascript"></script>
+        <script src="js/custom.js?v=<?php echo INSTALLEDVERSION; ?>" type="text/javascript"></script>
+        <script src="js/jquery.mousewheel.min.js" type="text/javascript"></script>
+        <!--Data Tables-->
+        <script src="bower_components/DataTables/media/js/jquery.dataTables.js"></script>
+        <script src="bower_components/datatables.net-responsive/js/dataTables.responsive.js"></script>
+        <script src="bower_components/datatables-tabletools/js/dataTables.tableTools.js"></script>
+         <!--Summernote-->
+        <script src="bower_components/summernote/dist/summernote.min.js"></script>
+		<style><?php customCSS(); ?></style>
+    </head>
+    <body class="scroller-body" style="padding: 0; overflow: hidden">
+        <div id="main-wrapper" class="main-wrapper">
+            <!--Content-->
+            <div id="content"  style="margin:0 10px; overflow:hidden">
+                <div class="big-box">
+                    <div class="row">
+                        <div class="col-lg-12">
+                            <?php if( count($logs) < 5){?>
+                            <div class="btn-group btn-group-justified gray-bg">
+                                <?php foreach($logs as $k => $v){ ?>
+                                <div class="btn-group" role="group">
+                                    <button type="button" data-name="<?php echo $k; ?>" class="btn waves btn-info waves-effect waves-float log-link gray-bg"><?php echo $k; ?></button>
+                                </div>
+                                <?php } ?>
+                                <div class="btn-group" role="group">
+                                    <button type="button" data-name="All" class="btn waves btn-info waves-effect waves-float log-link gray-bg">Combined</button>
+                                </div>
+                                <div class="btn-group" role="group">
+                                    <button type="button" data-name="All" class="btn waves btn-info waves-effect waves-float all-link gray-bg">Show All Logs</button>
+                                </div>
+                            </div>
+                            <?php } ?>
+                            <?php if( count($logs) >= 5){?>
+                            <div class="btn-group pull-right" role="group" aria-label="...">
+                                <div class="btn-group" role="group">
+                                    <button type="button" class="btn waves btn-default dropdown-toggle waves-effect waves-float green-bg" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        Choose Log <span class="caret"></span>
+                                    </button>
+                                    <ul class="dropdown-menu pull-right" style="position: fixed;right: 20px;top: 50px;">
+                                        <?php foreach($logs as $k => $v){ ?>
+                                        <li data-name="<?php echo $k; ?>" class="log-link"><a href="#"><?php echo $k; ?></a></li>
+                                        <?php } ?>
+                                        <li class="divider"></li>
+                                        <li data-name="All" class="log-link"><a href="#">Combined</a></li>
+                                        <li data-name="All" class="all-link"><a href="#">Show All Logs</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                            <?php } ?>
+                        </div>
+                    </div>
+                    <br/>
+                    <div class="row">
+                        <div class="col-lg-12">
+
+                            <?php foreach($logs as $k => $v){ ?>
+                            <div id="<?php echo $k;?>-table" class="table-responsive content-box" style="padding: 10px; display: none">
+                            <h2><?php echo $k;?></h2>
+                                <table id="datatable" class="datatable display">
+                                    <thead>
+                                        <tr>
+                                            <th><?php echo $language->translate("LOG");?></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                            <?php readExternalLog('single',$v); ?>
+                                    </tbody>
+                                </table>
+                            </div>
+                            <?php }?>
+
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-lg-12">                            
+                            <div id="All-table" class="table-responsive" style="padding: 10px; display: none">
+                            <h2>All Logs</h2>
+                                <table id="datatable" class="datatable display">
+                                    <thead>
+                                        <tr>
+                                            <th><?php echo $language->translate("SOURCE");?></th>
+                                            <th><?php echo $language->translate("LOG");?></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                    <?php foreach($logs as $k => $v){
+                                        readExternalLog('all',$v,$k);
+                                    }?>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </body>
+    <script>
+    $(function () {
+        //Data Tables
+        $('.datatable').DataTable({
+            displayLength: 10,
+            dom: 'T<"clear">lfrtip',
+            responsive: true,
+            "order": [[ 0, 'desc' ]],
+            "language": {
+                "info": "<?php echo explosion($language->translate('SHOW_ENTRY_CURRENT'), 0);?> _START_ <?php echo explosion($language->translate('SHOW_ENTRY_CURRENT'), 1);?> _END_ <?php echo explosion($language->translate('SHOW_ENTRY_CURRENT'), 2);?> _TOTAL_ <?php echo explosion($language->translate('SHOW_ENTRY_CURRENT'), 3);?>",
+                "infoEmpty": "<?php echo $language->translate('NO_ENTRIES');?>",
+                "infoFiltered": "<?php echo explosion($language->translate('FILTERED'), 0);?> _MAX_ <?php echo explosion($language->translate('FILTERED'), 1);?>",
+                "lengthMenu": "<?php echo $language->translate('SHOW');?> _MENU_ <?php echo $language->translate('ENTRIES');?>",
+                "search": "",
+                "searchPlaceholder": "<?php echo $language->translate('SEARCH');?>",
+                "searchClass": "<?php echo $language->translate('SEARCH');?>",
+                "zeroRecords": "<?php echo $language->translate('NO_MATCHING');?>",
+                "paginate": {
+                    "next": "<?php echo $language->translate('NEXT');?>",
+                    "previous": "<?php echo $language->translate('PREVIOUS');?>",
+                }
+            }
+        });
+    });
+    $(".scroller-body").niceScroll({
+                railpadding: {top:0,right:0,left:0,bottom:0}
+    });
+    $('.log-link').click(function(e){
+        var target = $(this).attr('data-name')+'-table';
+        $('.table-responsive').hide();
+        $('#'+target).show();
+        console.log(target);
+        e.preventDefault();
+    });
+    $('.all-link').click(function(e){
+        $('.table-responsive').show();
+        $('#All-table').hide();
+        e.preventDefault();
+    });
+    $('#All-table').show();
+    </script>
+</html>

+ 38 - 1
settings.php

@@ -81,7 +81,7 @@ if(SLIMBAR == "true") {
         <link rel="stylesheet" href="css/settings.css?v=<?php echo INSTALLEDVERSION; ?>">
         <link rel="stylesheet" href="bower_components/summernote/dist/summernote.css">
         <link href="css/jquery.filer.css" rel="stylesheet">
-	       <link href="css/jquery.filer-dragdropbox-theme.css" rel="stylesheet">
+	    <link href="css/jquery.filer-dragdropbox-theme.css" rel="stylesheet">
 
         <!--[if lt IE 9]>
         <script src="bower_components/html5shiv/dist/html5shiv.min.js"></script>
@@ -1573,6 +1573,30 @@ echo buildSettings(
 					),
 				),
 			),
+            array(
+				'title' => 'Backup Settings',
+				'id' => 'backup_settings',
+				'image' => 'images/backup.png',
+				'fields' => array(
+					array(
+                        array(
+							'type' => 'button',
+							'labelTranslate' => 'BACKUP_NOW',
+							'id' => 'backupNow',
+							'icon' => 'database',
+                            'style' =>  (extension_loaded("ZIP")) ? "margin-bottom: 5px;" : "display : none",
+						),
+					),
+                    array(
+						'type' => 'textarea',
+						'labelTranslate' => 'BACKUP_LIST',
+						'name' => 'backupList',
+						'value' => (extension_loaded("ZIP")) ? implode("\n",getBackups()) : "PLEASE ENABLE PHP ZIP",
+						'rows' => 15,
+						'style' => 'background: #000; color: #FFF;pointer-events: none',
+					),
+				),
+			),
 		),
 	)
 );
@@ -2830,6 +2854,19 @@ echo buildSettings(
             });
         </script>
         <script>
+            //Backup
+            $('#backupNow').on('click', function () {
+                console.log("starting backup now");
+                ajax_request('POST', 'backup-now');
+                setTimeout(function(){
+                    ajax_request('GET', 'get-backups').done(function(data){
+                        $('#backupList_id').html(data);
+                        $('#backupList_id').addClass('animated pulse');
+                    });
+                    console.log("ajax backup done")
+                }, 500);
+                ;
+            });
             //TestEmail
             function isUpperCase(str) {
                 return str === str.toUpperCase();

+ 8 - 0
user.php

@@ -118,6 +118,7 @@
 		var $userdir = false;
 		// the user's email address, if logged in.
 		var $email = "";
+		var $adminEmail = "";
 		// the user's role in the system
 		var $role = "";
 		var $group = "";
@@ -212,6 +213,7 @@
 			$this->username = $_SESSION["username"];
 			$this->userdir = ($this->username !=User::GUEST_USER? USER_HOME . $this->username : false);
 			$this->email = $this->get_user_email($this->username);
+			$this->adminEmail = $this->get_admin_email();
 			$this->role = $this->get_user_role($this->username);
 			//$this->group = $this->get_user_group($this->username);
 			// clear database
@@ -825,6 +827,12 @@
 				foreach($this->database->query($query) as $data) { return $data["email"]; }}
 			return "";
 		}
+		function get_admin_email()
+		{
+			$query = "SELECT email FROM users WHERE role = 'admin' COLLATE NOCASE LIMIT 1";
+			foreach($this->database->query($query) as $data) { return $data["email"]; }
+			return "";
+		}
 		/**
 		 * Get a user's role
 		 */

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است