causefx 9 лет назад
Родитель
Сommit
0e36837650
12 измененных файлов с 840 добавлено и 45 удалено
  1. 16 0
      ajax.php
  2. 332 22
      functions.php
  3. 134 4
      index.php
  4. 24 1
      lang/de.ini
  5. 24 1
      lang/en.ini
  6. 24 1
      lang/es.ini
  7. 24 1
      lang/fr.ini
  8. 24 1
      lang/it.ini
  9. 24 1
      lang/nl.ini
  10. 24 1
      lang/pl.ini
  11. 130 2
      settings.php
  12. 60 10
      user.php

+ 16 - 0
ajax.php

@@ -77,6 +77,22 @@ switch ($_SERVER['REQUEST_METHOD']) {
             case 'search-plex':
 			 	$response = searchPlex($_POST['searchtitle']);
 			 	break;
+			case 'validate-invite':
+				$response = inviteCodes("check", $_POST['invitecode']);
+				$response['notify'] = sendResult($response, "check", $_POST['checkurl'], "CODE_SUCCESS", "CODE_ERROR");
+				break;
+			case 'use-invite':
+				//$response = inviteCodes("check", $_POST['invitecode']);
+				//$response = inviteCodes("use", $_POST['invitecode']);
+				if(inviteCodes("check", $_POST['invitecode'])){
+					$response = inviteCodes("use", $_POST['invitecode'], $_POST['inviteuser']);
+					$response['notify'] = sendResult(plexUserShare($_POST['inviteuser']), "check", $_POST['checkurl'], "INVITE_SUCCESS", "INVITE_ERROR");
+				}
+				break;
+			case 'join-plex':
+				$response = plexJoin($_POST['joinuser'], $_POST['joinemail'], $_POST['joinpassword']);
+				$response['notify'] = sendResult($response, "check", $_POST['checkurl'], "JOIN_SUCCESS", "JOIN_ERROR");
+				break;
             default: // Stuff that you need admin for
                 qualifyUser('admin', true);
                 switch ($action) {

+ 332 - 22
functions.php

@@ -2,7 +2,7 @@
 
 // ===================================
 // Define Version
- define('INSTALLEDVERSION', '1.39');
+ define('INSTALLEDVERSION', '1.40');
 // ===================================
 
 // Debugging output functions
@@ -31,13 +31,13 @@ if (function_exists('ldap_connect')) :
 		// returns true or false
 		$ldap = ldap_connect(implode(' ',$ldapServers));
 		if ($bind = ldap_bind($ldap, AUTHBACKENDDOMAIN.'\\'.$username, $password)) {
-   writeLog("success", "LDAP authentication success"); 
+   			writeLog("success", "LDAP authentication success"); 
 			return true;
 		} else {
-   writeLog("error", "LDPA could not authenticate"); 
+   			writeLog("error", "LDPA could not authenticate"); 
 			return false;
 		}
-  writeLog("error", "LDPA could not authenticate");      
+  		writeLog("error", "LDPA could not authenticate");      
 		return false;
 	}
 else :
@@ -62,7 +62,7 @@ function plugin_auth_ftp($username, $password) {
 		$conn_id = ftp_connect($host, $port, 20);
 	} else {
 		debug_out('Invalid FTP scheme. Use ftp or ftps');
-  writeLog("error", "invalid FTP scheme"); 
+  		writeLog("error", "invalid FTP scheme"); 
 		return false;
 	}
 	
@@ -74,10 +74,10 @@ function plugin_auth_ftp($username, $password) {
 		
 		// Return Result
 		if ($login_result) {
-   writeLog("success", "$username authenticated");       
+   			writeLog("success", "$username authenticated");       
 			return true;
 		} else {
-   writeLog("error", "$username could not authenticate");      
+   			writeLog("error", "$username could not authenticate");      
 			return false;
 		}
 	} else {
@@ -340,10 +340,11 @@ if (function_exists('curl_version')) :
 		}
 		// Execute
 		$result = curl_exec($curlReq);
+		$httpcode = curl_getinfo($curlReq);
 		// Close
 		curl_close($curlReq);
 		// Return
-		return array('content'=>$result);
+		return array('content'=>$result, 'http_code'=>$httpcode);
 	}
 
 	//Curl Get Function
@@ -369,6 +370,31 @@ if (function_exists('curl_version')) :
 		// Return
 		return $result;
 	}
+	
+	//Curl Delete Function
+	function curl_delete($url, $headers = array()) {
+		// Initiate cURL
+		$curlReq = curl_init($url);
+		// As post request
+		curl_setopt($curlReq, CURLOPT_CUSTOMREQUEST, "DELETE"); 
+		curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
+  		curl_setopt($curlReq, CURLOPT_CONNECTTIMEOUT, 5);
+		// Format Headers
+		$cHeaders = array();
+		foreach ($headers as $k => $v) {
+			$cHeaders[] = $k.': '.$v;
+		}
+		if (count($cHeaders)) {
+			curl_setopt($curlReq, CURLOPT_HTTPHEADER, $cHeaders);
+		}
+		// Execute
+		$result = curl_exec($curlReq);
+		$httpcode = curl_getinfo($curlReq);
+		// Close
+		curl_close($curlReq);
+		// Return
+		return array('content'=>$result, 'http_code'=>$httpcode);
+	}
 endif;
 
 //Case-Insensitive Function
@@ -462,7 +488,12 @@ function resolveEmbyItem($address, $token, $item, $nowPlaying = false, $showName
 	
 	// Get Item Details
 	$itemDetails = json_decode(file_get_contents($address.'/Items?Ids='.$item['Id'].'&api_key='.$token),true)['Items'][0];
-	$URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
+	if (substr_count(EMBYURL, ':') == 2) {
+		$URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
+	}else{
+		$URL = EMBYURL."/web/itemdetails.html?id=".$itemDetails['Id'];
+	}
+	//$URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
 	switch ($itemDetails['Type']) {
     case 'Episode':
         $title = (isset($itemDetails['SeriesName'])?$itemDetails['SeriesName']:"");
@@ -998,7 +1029,7 @@ function getEmbyImage() {
     }
 
 	$itemId = $_GET['img'];
- $key = $_GET['key'];
+ 	$key = $_GET['key'];
 	$itemType = $_GET['type'];
 	$imgParams = array();
 	if (isset($_GET['height'])) { $imgParams['height'] = 'maxHeight='.$_GET['height']; }
@@ -1372,6 +1403,19 @@ function upgradeCheck() {
 		unset($config);
 	}
 	
+	// Upgrade to 1.40
+	$config = loadConfig();
+	if (isset($config['database_Location']) && (!isset($config['CONFIG_VERSION']) || $config['CONFIG_VERSION'] < '1.40')) {
+		// Upgrade database to latest version
+		updateSQLiteDB($config['database_Location'],'1.38');
+		
+		// Update Version and Commit
+		$config['CONFIG_VERSION'] = '1.40';
+		copy('config/config.php', 'config/config['.date('Y-m-d_H-i-s').'][1.38].bak.php');
+		$createConfigSuccess = createConfig($config);
+		unset($config);
+	}
+	
 	return true;
 }
 
@@ -1406,17 +1450,17 @@ function uploadFiles($path, $ext_mask = null) {
 
 		if($data['isComplete']){
 			$files = $data['data'];
-   writeLog("success", $files['metas'][0]['name']." was uploaded");
+   			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");
+   			writeLog("error", $files['metas'][0]['name']." was not able to upload");
 			echo json_encode($errors);
 		}
 	} else { 
-  writeLog("error", "image was not uploaded");
+  		writeLog("error", "image was not uploaded");
 		echo json_encode('No files submitted!');
 	}
 }
@@ -1427,7 +1471,7 @@ function removeFiles($path) {
         writeLog("success", "image was removed");
         unlink($path);
     } else {
-  writeLog("error", "image was not removed");
+  		writeLog("error", "image was not removed");
 		echo json_encode('No file specified for removal!');
 	}
 }
@@ -1965,10 +2009,24 @@ function createSQLiteDB($path = false) {
 			`loading`	TEXT,
 			`hovertext`	TEXT
 		);');
+		
+		// Create Invites
+		$invites = $GLOBALS['file_db']->query('CREATE TABLE `invites` (
+			`id`	INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
+			`code`	TEXT UNIQUE,
+			`date`	TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+			`email`	TEXT,
+			`username`	TEXT,
+			`dateused`	TIMESTAMP,
+			`usedby`	TEXT,
+			`ip`	TEXT,
+			`valid`	TEXT
+		);');
+		
 		writeLog("success", "database created/saved");
-		return $users && $tabs && $options;
+		return $users && $tabs && $options && $invites;
 	} else {
-  writeLog("error", "database was unable to be created/saved");
+  		writeLog("error", "database was unable to be created/saved");
 		return false;
 	}
 }
@@ -2345,13 +2403,13 @@ function updateTabs($tabs) {
 			}
 			$GLOBALS['file_db']->query('INSERT INTO tabs (`'.implode('`,`',array_keys($fields)).'`) VALUES (\''.implode("','",$fields).'\');');
 		}
-  writeLog("success", "tabs successfully saved");     
+  		writeLog("success", "tabs successfully saved");     
 		return $totalValid;
 	} else {
-  writeLog("error", "tabs could not save");     
+  		writeLog("error", "tabs could not save");     
 		return false;
 	}
- writeLog("error", "tabs could not save");     
+ 	writeLog("error", "tabs could not save");     
 	return false;
 }
 
@@ -2859,7 +2917,15 @@ function getPlatform($platform){
         "Emby for iOS" => "ios.png",
         "Emby Mobile" => "emby.png",
         "Emby Theater" => "emby.png",
+        "Emby Classic" => "emby.png",
         "Safari" => "safari.png",
+        "Android" => "android.png",
+        "Chromecast" => "chromecast.png",
+        "Dashboard" => "emby.png",
+        "Dlna" => "dlna.png",
+        "Windows Phone" => "wp.png",
+        "Windows RT" => "win8.png",
+        "Kodi" => "koid.png",
     );
     if (array_key_exists($platform, $allPlatforms)) {
         return $allPlatforms[$platform];
@@ -2873,9 +2939,9 @@ function getServer(){
     return $server;    
 }
 
-function prettyPrint($a) {
-    echo "HEADERS: <pre>";
-    print_r($a);
+function prettyPrint($array) {
+    echo "<pre>";
+    print_r($array);
     echo "</pre>";
     echo "<br/>";
 }
@@ -3152,5 +3218,249 @@ function get_client_ip() {
     return $ipaddress;
 }
 
+//EMAIL SHIT
+function sendEmail($email, $username = "Organizr User", $subject, $body, $cc = null){
+
+	$mail = new PHPMailer;
+	$mail->isSMTP();
+	$mail->Host = SMTPHOST;
+	$mail->SMTPAuth = SMTPHOSTAUTH;
+	$mail->Username = SMTPHOSTUSERNAME;
+	$mail->Password = SMTPHOSTPASSWORD;
+	$mail->SMTPSecure = SMTPHOSTTYPE;
+	$mail->Port = SMTPHOSTPORT;
+	$mail->setFrom(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME);
+	$mail->addReplyTo(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME);
+	$mail->isHTML(true);
+	$mail->addAddress($email, $username);
+	$mail->Subject = $subject;
+	$mail->Body    = $body;
+	//$mail->send();
+	if(!$mail->send()) {
+		writeLog("error", "mail failed to send");
+	} else {
+		writeLog("success", "mail has been sent");
+	}
+
+}
+
+function libraryList(){
+    $address = qualifyURL(PLEXURL);
+	$headers = array(
+		"Accept" => "application/json", 
+		"X-Plex-Token" => PLEXTOKEN
+	);
+	$getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+    if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+	
+	$api = simplexml_load_string(@curl_get("https://plex.tv/api/servers/$gotServer/shared_servers", $headers));
+	$libraryList = array();
+    foreach($api->SharedServer->Section AS $child) {
+		$libraryList['libraries'][(string)$child['title']] = (string)$child['id'];
+    }
+	foreach($api->SharedServer AS $child) {
+		if(!empty($child['username'])){
+			$username = (string)strtolower($child['username']);
+			$libraryList['users'][$username] = (string)$child['id'];
+		}
+    }
+    return (!empty($libraryList) ? array_change_key_case($libraryList,CASE_LOWER) : null );
+}
+
+function plexUserShare($username){
+    $address = qualifyURL(PLEXURL);
+	$headers = array(
+		"Accept" => "application/json", 
+		"Content-Type" => "application/json", 
+		"X-Plex-Token" => PLEXTOKEN
+	);
+	$getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+    if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+	
+	$json = array(
+		"server_id" => $gotServer,
+		"shared_server" => array(
+			//"library_section_ids" => "[26527637]",
+			"invited_email" => $username
+		)
+	);
+	
+	$api = curl_post("https://plex.tv/api/servers/$gotServer/shared_servers/", $json, $headers);
+	
+	switch ($api['http_code']['http_code']){
+		case 400:
+			writeLog("error", "PLEX INVITE: $username already has access to the shared libraries");
+			$result = "$username already has access to the shared libraries";
+			break;
+		case 401:
+			writeLog("error", "PLEX INVITE: Invalid Plex Token");
+			$result = "Invalid Plex Token";
+			break;
+		case 200:
+			writeLog("success", "PLEX INVITE: $username now has access to your Plex Library");
+			$result = "$username now has access to your Plex Library";
+			break;
+		default:
+			writeLog("error", "PLEX INVITE: unknown error");
+			$result = false;
+	}
+    return (!empty($result) ? $result : null );
+}
+
+function plexUserDelete($username){
+    $address = qualifyURL(PLEXURL);
+	$headers = array(
+		"Accept" => "application/json", 
+		"Content-Type" => "application/json", 
+		"X-Plex-Token" => PLEXTOKEN
+	);
+	$getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+    if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+	$id = convertPlexName($username, "id");
+	
+	$api = curl_delete("https://plex.tv/api/servers/$gotServer/shared_servers/$id", $headers);
+	
+	switch ($api['http_code']['http_code']){
+		case 401:
+			writeLog("error", "PLEX INVITE: Invalid Plex Token");
+			$result = "Invalid Plex Token";
+			break;
+		case 200:
+			writeLog("success", "PLEX INVITE: $username doesn't have access to your Plex Library anymore");
+			$result = "$username doesn't have access to your Plex Library anymore";
+			break;
+		default:
+			writeLog("error", "PLEX INVITE: unknown error");
+			$result = false;
+	}
+    return (!empty($result) ? $result : null );
+}
+
+function convertPlexName($user, $type){
+	$array = libraryList();
+	switch ($type){
+		case "username":
+			$plexUser = array_search ($user, $array['users']);
+			break;
+		case "id":
+			if (array_key_exists(strtolower($user), $array['users'])) {
+				$plexUser = $array['users'][strtolower($user)];
+			}
+			break;
+		default:
+			$plexUser = false;
+	}
+	return (!empty($plexUser) ? $plexUser : null );
+}
+
+function randomCode($length = 5, $type = null) {
+	switch ($type){
+		case "alpha":
+			$legend = array_merge(range('A', 'Z'));
+			break;
+		case "numeric":
+			$legend = array_merge(range(0,9));
+			break;
+		default:
+			$legend = array_merge(range(0,9),range('A', 'Z'));
+	}
+    $code = "";
+    for($i=0; $i < $length; $i++) {
+        $code .= $legend[mt_rand(0, count($legend) - 1)];
+    }
+    return $code;
+}
+
+function inviteCodes($action, $code = null, $usedBy = null) {
+	if (!isset($GLOBALS['file_db'])) {
+		$GLOBALS['file_db'] = new PDO('sqlite:'.DATABASE_LOCATION.'users.db');
+		$GLOBALS['file_db']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+	}
+	$now = date("Y-m-d H:i:s");
+	
+	switch ($action) {
+		case "get":
+			// Start Array
+			$result = array();
+			// Database Lookup
+			$invites = $GLOBALS['file_db']->query('SELECT * FROM invites WHERE valid = "Yes"');
+			// Get Codes
+			foreach($invites as $row) {
+				array_push($result, $row['code']);
+			}
+			// Return the Results
+			return (!empty($result) ? $result : false );
+			break;
+		case "check":
+			// Start Array
+			$result = array();
+			// Database Lookup
+			$invites = $GLOBALS['file_db']->query('SELECT * FROM invites WHERE valid = "Yes" AND code = "'.$code.'"');
+			// Get Codes
+			foreach($invites as $row) {
+				$result = $row['code'];
+			}
+			// Return the Results
+			return (!empty($result) ? $result : false );
+			break;
+		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.'"');
+			return (!empty($invites) ? true : false );
+			break;
+	}
+	
+}
+
+function plexJoin($username, $email, $password){
+	$connectURL = 'https://plex.tv/users.json';
+	$headers = array(
+		'Accept'=> 'application/json',
+		'Content-Type' => 'application/x-www-form-urlencoded',
+		'X-Plex-Product' => 'Organizr',
+		'X-Plex-Version' => '1.0',
+		'X-Plex-Client-Identifier' => '01010101-10101010',
+	);
+	$body = array(
+		'user[email]' => $email,
+		'user[username]' => $username,
+		'user[password]' => $password,
+	);
+	
+	$api = curl_post($connectURL, $body, $headers);
+	$json = json_decode($api['content'], true);
+	$errors = (!empty($json['errors']) ? true : false);
+	$success = (!empty($json['user']) ? true : false);
+	//Use This for later
+	$usernameError = (!empty($json['errors']['username']) ? $json['errors']['username'][0] : false);
+	$emailError = (!empty($json['errors']['email']) ? $json['errors']['email'][0] : false);
+	$passwordError = (!empty($json['errors']['password']) ? $json['errors']['password'][0] : false);
+	
+	switch ($api['http_code']['http_code']){
+		case 400:
+			writeLog("error", "PLEX JOIN: $username already has access to the shared libraries");
+			break;
+		case 401:
+			writeLog("error", "PLEX JOIN: invalid Plex Token");
+			break;
+		case 422:
+			writeLog("error", "PLEX JOIN: user info error");
+			break;
+		case 429:
+			writeLog("error", "PLEX JOIN: too many requests to plex.tv please try later");
+			break;
+		case 200:
+		case 201:
+			writeLog("success", "PLEX JOIN: $username now has access to your Plex Library");
+			break;
+		default:
+			writeLog("error", "PLEX JOIN: unknown error, Error: ".$api['http_code']['http_code']);
+	}
+	//prettyPrint($api);
+	//prettyPrint(json_decode($api['content'], true));
+    return (!empty($success) && empty($errors) ? true : false );
+	
+}
+
 // Always run this
 dependCheck();

+ 134 - 4
index.php

@@ -40,6 +40,8 @@ if(isset($_POST['action'])) {
     $action = $_POST['action'];
 	unset($_POST['action']);
 }
+//Get Invite Code
+$inviteCode = isset($_GET['inviteCode']) ? $_GET['inviteCode'] : null;
 
 // Check for config file
 if(!file_exists('config/config.php')) {
@@ -652,7 +654,7 @@ endif; ?>
             <!--Content-->
             <div id="content" class="content" style="">
                 <script>addToHomescreen();</script>
-
+				
                 <!--Load Framed Content-->
                 <?php if($needSetup == "Yes" && $configReady == "Yes") : ?>
                 <div class="table-wrapper" style="background:<?=$sidebar;?>;">
@@ -895,7 +897,7 @@ endif; ?>
             </div>
 
         </div>
-        <?php if($configReady == "Yes") : if(!$USER->authenticated && $configReady == "Yes") : ?>
+        <?php if($configReady == "Yes") : if(!$USER->authenticated && $configReady == "Yes") : if(!$inviteCode) : ?>
         <div class="login-modal modal fade">
             <div style="background:<?=$sidebar;?>;" class="table-wrapper">
                 <div class="table-row">
@@ -1013,7 +1015,7 @@ endif; ?>
                 </div>
             </div>
         </div>
-        <?php endif; endif;?>
+        <?php endif; endif; endif;?>
         <?php if($configReady == "Yes") : if($USER->authenticated) : ?>
         <div style="background:<?=$topbar;?>;" class="logout-modal modal fade">
             <div class="table-wrapper" style="background: <?=$sidebar;?>">
@@ -1041,6 +1043,76 @@ endif; ?>
             </div>
         </div>
         <?php endif; endif;?>
+		<?php if ($inviteCode){ ?>
+		<div id="inviteSet" class="login-modal modal fade">
+			<div style="background:<?=$sidebar;?>;" class="table-wrapper">
+				<div class="table-row">
+					<div class="table-cell text-center">
+						<button style="color:<?=$topbartext;?>;" type="button" class="close" data-dismiss="modal" aria-label="Close">
+							<span aria-hidden="true">&times;</span>
+						</button>
+						<div class="login i-block">
+							<div class="content-box">
+								<div style="background:<?=$topbar;?>;" class="biggest-box">
+
+									<h1 style="color:<?=$topbartext;?>;" class="zero-m text-uppercase"><?php echo $language->translate("WELCOME");?></h1>
+
+								</div>
+								<div class="big-box text-left login-form">
+
+									<?php if($USER->error!="") : ?>
+									<p class="error">Error: <?php echo $USER->error; ?></p>
+									<?php endif; ?>
+									<form name="checkInviteForm" id="checkInviteForm" onsubmit="return false;" data-smk-icon="glyphicon-remove-sign">
+										<h4 class="text-center"><?php echo $language->translate("CHECK_INVITE");?></h4>
+										<div class="form-group">
+											<input style="font-size: 400%; height: 100%" type="text" class="form-control yellow-bg text-center text-uppercase" name="inviteCode" placeholder="<?php echo $language->translate("CODE");?>" autocomplete="off" autocorrect="off" autocapitalize="off" value="<?=$inviteCode;?>" maxlength="6" spellcheck="false" autofocus required>
+										</div>
+
+										<button id="checkInviteForm_submit" style="background:<?=$topbar;?>;" type="submit" class="btn btn-block btn-info text-uppercase waves" value="checkInvite"><text style="color:<?=$topbartext;?>;"><?php echo $language->translate("SUBMIT_CODE");?></text></button>
+
+									</form> 
+									
+									<div style="display: none" id="chooseMethod">
+										<h4 class="text-center"><?php echo $language->translate("HAVE_ACCOUNT");?></h4>
+										<button id="yesPlexButton" style="background:<?=$topbartext;?>;" class="btn btn-block btn-info text-uppercase waves"><text style="color:<?=$topbar;?>;"><?php echo $language->translate("YES");?></text></button>
+										<button id="noPlexButton" style="background:<?=$topbartext;?>;" class="btn btn-block btn-info text-uppercase waves"><text style="color:<?=$topbar;?>;"><?php echo $language->translate("NO");?></text></button>
+									</div>
+									
+									<form style="display:none" name="useInviteForm" id="useInviteForm" onsubmit="return false;" data-smk-icon="glyphicon-remove-sign">
+										<h4 class="text-center"><?php echo $language->translate("ENTER_PLEX_NAME");?></h4>
+										<h4 id="accountMade" style="display: none" class="text-center">
+											<span class="label label-primary"><?php echo $language->translate("ACCOUNT_MADE");?></span>
+										</h4>
+										<div class="form-group">
+											<input style="font-size: 400%; height: 100%" type="hidden" class="form-control yellow-bg text-center text-uppercase" name="inviteCode" placeholder="<?php echo $language->translate("CODE");?>" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" value="<?=$inviteCode;?>" maxlength="6" required>
+											<input type="text" class="form-control material" name="inviteUser" placeholder="<?php echo $language->translate("USERNAME_EMAIL");?>" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" value="" autofocus required>
+										</div>
+
+										<button id="useInviteForm_submit" style="background:<?=$topbar;?>;" type="submit" class="btn btn-block btn-info text-uppercase waves" value="useInvite"><text style="color:<?=$topbartext;?>;"><?php echo $language->translate("JOIN");?></text></button>
+
+									</form>
+
+									<form style="display:none" name="joinPlexForm" id="joinPlexForm" onsubmit="return false;" data-smk-icon="glyphicon-remove-sign">
+										<h4 class="text-center"><?php echo $language->translate("CREATE_PLEX");?></h4>
+										<div class="form-group">
+											<input type="text" class="form-control material" name="joinUser" placeholder="<?php echo $language->translate("USERNAME");?>" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" value="" autofocus required>
+											<input type="text" class="form-control material" name="joinEmail" placeholder="<?php echo $language->translate("EMAIL");?>" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" value="" required>
+											<input type="password" class="form-control material" name="joinPassword" placeholder="<?php echo $language->translate("PASSWORD");?>" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" value="" required>
+										</div>
+
+										<button id="joinPlexForm_submit" style="background:<?=$topbar;?>;" type="submit" class="btn btn-block btn-info text-uppercase waves" value="useInvite"><text style="color:<?=$topbartext;?>;"><?php echo $language->translate("SIGN_UP");?></text></button>
+
+									</form> 
+
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<?php } ?>
 
         <!--Scripts-->
         <script src="<?=$baseURL;?>bower_components/jquery/dist/jquery.min.js"></script>
@@ -1187,12 +1259,16 @@ endif; ?>
         $(".log-in").click(function(e){
             var e1 = document.querySelector(".log-in"),
                 e2 = document.querySelector(".login-modal");
-            cta(e1, e2, {relativeToWindow: true}, function () {
+            	cta(e1, e2, {relativeToWindow: true}, function () {
                 $('.login-modal').modal("show");
             });
 
             e.preventDefault();
         });
+		//InviteCode
+		<?php if($inviteCode){ ?>
+		$('#inviteSet').modal("show");	
+		<?php } ?>
 
         //Logout
         $(".logout").click(function(e){
@@ -1222,6 +1298,60 @@ endif; ?>
         });
 
         $(document).ready(function(){
+			//PLEX INVITE SHIT
+			$('#checkInviteForm').on('submit', function () {
+                ajax_request('POST', 'validate-invite', {
+                    invitecode: $('#checkInviteForm [name=inviteCode]').val(),
+                }).done(function(data){ 
+					var result = JSON.stringify(data).includes("success");
+					if(result === true){
+						$('#checkInviteForm').hide();
+						$('#chooseMethod').show();
+						console.log(result);
+					}
+				});
+
+            });
+			$('#useInviteForm').on('submit', function () {
+                ajax_request('POST', 'use-invite', {
+                    invitecode: $('#useInviteForm [name=inviteCode]').val(),
+                    inviteuser: $('#useInviteForm [name=inviteUser]').val(),
+                }).done(function(data){ 
+					var result = JSON.stringify(data).includes("success");
+					console.log(result);
+					if(result === true){
+						//$('#checkInviteForm').hide();
+						//$('#chooseMethod').show();
+						console.log(result);
+					}
+				});
+
+            });
+			$('#joinPlexForm').on('submit', function () {
+                ajax_request('POST', 'join-plex', {
+                    joinuser: $('#joinPlexForm [name=joinUser]').val(),
+                    joinemail: $('#joinPlexForm [name=joinEmail]').val(),
+                    joinpassword: $('#joinPlexForm [name=joinPassword]').val(),
+                }).done(function(data){ 
+					var result = JSON.stringify(data).includes("success");
+					if(result === true){
+						$('#joinPlexForm').hide();
+						$('#useInviteForm').show();
+						$('#accountMade').show();
+						$('input[name=inviteUser]').val($('input[name=joinUser]').val());
+						console.log(result);
+					}
+				});
+
+            });
+			$("#yesPlexButton").click(function(){
+				$('#chooseMethod').hide();
+				$('#useInviteForm').show();
+			});
+			$("#noPlexButton").click(function(){
+				$('#chooseMethod').hide();
+				$('#joinPlexForm').show();
+			});
             $('#userCreateForm').submit(function(event) {
 
                 var formData = {

+ 24 - 1
lang/de.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/en.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/es.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/fr.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/it.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/nl.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 24 - 1
lang/pl.ini

@@ -258,4 +258,27 @@ NOTICE_MESSAGE = "Notice Message"
 SHOW_NAMES = "Show Names"
 NOTICE_LAYOUT = "Notice Layout"
 RECENT_ITEMS_LIMIT = "Recent Items Limit"
-ALLOW_SEARCH = "Allow Search"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"

+ 130 - 2
settings.php

@@ -26,6 +26,9 @@ qualifyUser('admin', true);
 // Load User List
 $gotUsers = $file_db->query('SELECT * FROM users');
 
+// Load Invite List
+$gotInvites = $file_db->query('SELECT * FROM invites');
+
 // Load Colours/Appearance
 foreach(loadAppearance() as $key => $value) {
 	$$key = $value;
@@ -361,6 +364,7 @@ endif; ?>
                                     <li><a id="open-logs" box="logs-box"><i class="fa fa-file-text-o blue pull-right"></i>View Logs</a></li>
                                     <li><a id="open-homepage" box="homepage-box"><i class=" fa fa-home yellow pull-right"></i>Edit Homepage</a></li>
                                     <li><a id="open-advanced" box="advanced-box"><i class=" fa fa-cog light-blue pull-right"></i>Advanced</a></li>
+                                    <li><a id="open-invites" box="invites-box"><i class=" fa fa-user-plus gray pull-right"></i>Plex Invites</a></li>
                                     <li><a id="open-info" box="info-box"><i class=" fa fa-info-circle orange pull-right"></i>About</a></li>
                                     <li><a id="open-donate" box="donate-box"><i class=" fa fa-money red pull-right"></i>Donate</a></li>
                                 </ul>
@@ -391,7 +395,7 @@ endif; ?>
 											<button id="iconAll" type="button" class="btn waves btn-labeled btn-info btn-sm text-uppercase waves-effect waves-float">
 												<span class="btn-label"><i class="fa fa-picture-o"></i></span><?php echo $language->translate("VIEW_ICONS");?>
 											</button>
-           <button id="checkFrame" data-toggle="modal" data-target=".checkFrame" type="button" class="btn waves btn-labeled btn-gray btn-sm text-uppercase waves-effect waves-float">
+           									<button id="checkFrame" data-toggle="modal" data-target=".checkFrame" type="button" class="btn waves btn-labeled btn-gray btn-sm text-uppercase waves-effect waves-float">
 												<span class="btn-label"><i class="fa fa-check"></i></span><?php echo $language->translate("CHECK_FRAME");?>
 											</button>
 											<button type="submit" class="btn waves btn-labeled btn-success btn btn-sm pull-right text-uppercase waves-effect waves-float">
@@ -2025,6 +2029,117 @@ echo buildSettings(
                         </div>
                     </div>
                 </div>
+				<div class="email-content invites-box white-bg">
+                    <div class="email-body">
+                        <div class="email-header gray-bg">
+                            <button type="button" class="btn btn-danger btn-sm waves close-button"><i class="fa fa-close"></i></button>
+                            <h1>Invite Management</h1>
+                        </div>
+                        <div class="email-inner small-box">
+                            <div class="email-inner-section">
+                                <div class="small-box fade in" id="useredit">
+                                    <div class="row">
+                                        <div class="col-lg-12">
+                                            <div class="small-box">
+                                                <form class="content-form form-inline" name="inviteNewUser" id="inviteNewUser" action="" method="POST">
+                                                    <input type="hidden" name="op" value="invite"/>
+                                                    <input type="hidden" name="server" value="plex"/>
+
+                                                    <div class="form-group">
+
+                                                        <input type="text" class="form-control material" name="username" placeholder="<?php echo $language->translate("USERNAME");?>" autocorrect="off" autocapitalize="off" value="">
+
+                                                    </div>
+
+                                                    <div class="form-group">
+
+                                                        <input type="email" class="form-control material" name="email" placeholder="<?php echo $language->translate("EMAIL");?>" required>
+
+                                                    </div>
+
+                                                    <button type="submit" class="btn waves btn-labeled btn-primary btn btn-sm text-uppercase waves-effect waves-float">
+
+                                                        <span class="btn-label"><i class="fa fa-user-plus"></i></span><?php echo $language->translate("SEND_INVITE");?>
+
+                                                    </button>
+
+                                                </form>               
+                                            </div>
+                                        </div>
+                                    </div>
+                                    <div class="small-box">
+                                            
+                                            <p id="inputUsername"></p>
+
+                                            <div class="table-responsive">
+
+                                                <table class="table table-striped">
+
+                                                    <thead>
+
+                                                        <tr>
+
+                                                            <th>#</th>
+
+                                                            <th><?php echo $language->translate("USERNAME");?></th>
+                                                            <th><?php echo $language->translate("EMAIL");?></th>
+                                                            <th><?php echo $language->translate("INVITE_CODE");?></th>
+                                                            <th><?php echo $language->translate("DATE_SENT");?></th>
+                                                            <th><?php echo $language->translate("DATE_USED");?></th>
+                                                            <th><?php echo $language->translate("USED_BY");?></th>
+                                                            <th><?php echo $language->translate("IP_ADDRESS");?></th>
+                                                            <th><?php echo $language->translate("VALID");?></th>
+
+                                                        </tr>
+
+                                                    </thead>
+
+                                                    <tbody>
+
+                                                        <?php
+                                                        foreach($gotInvites as $row) :
+															$validColor = ($row['valid'] == "Yes" ? "primary" : "danger");
+															$inviteUser = ($row['username'] != "" ? $row['username'] : "N/A");
+															$dateInviteUsed = ($row['dateused'] != "" ? $row['dateused'] : "Not Used");
+															$ipUsed = ($row['ip'] != "" ? $row['ip'] : "Not Used");
+															$usedBy = ($row['usedby'] != "" ? $row['usedby'] : "Not Used");
+              
+                                                        ?>
+
+                                                        <tr id="<?=$row['id'];?>">
+
+                                                            <th scope="row"><?=$row['id'];?></th>
+
+                                                            <td><?=$inviteUser;?></td>
+                                                            <td><?=$row['email'];?></td>
+
+                                                            <td><span style="font-size: 100%;" class="label label-<?=$validColor;?>"><?=$row['code'];?></span></td>
+
+                                                            <td><?=$row['date'];?></td>
+
+                                                            <td><?=$dateInviteUsed;?></td>
+                                                            <td><?=$usedBy;?></td>
+                                                            <td><?=$ipUsed;?></td>
+
+                                                            <td><span style="font-size: 100%;" class="label label-<?=$validColor;?>"><?=$row['valid'];?></span></td>
+
+                                                        </tr>
+
+                                                        <?php endforeach; ?>
+
+                                                    </tbody>
+
+                                                </table>
+
+                                            </div>
+                                        
+                                    </div>
+
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
                 <div class="email-content logs-box white-bg">
                     <div class="email-body">
                         <div class="email-header gray-bg">
@@ -2191,6 +2306,19 @@ echo buildSettings(
             <!--End Content-->
 
         </div>
+		 <?php if(isset($_POST['op'])) : ?>
+        <script>
+            
+            parent.notify("<?php echo printArray($USER->info_log); ?>","info-circle","notice","5000", "<?=$notifyExplode[0];?>", "<?=$notifyExplode[1];?>");
+            
+            <?php if(!empty($USER->error_log)) : ?>
+            
+            parent.notify("<?php echo printArray($USER->error_log); ?>","exclamation-circle ","error","5000", "<?=$notifyExplode[0];?>", "<?=$notifyExplode[1];?>");
+            
+            <?php endif; ?>
+            
+        </script>
+        <?php endif; ?>
 
 		<script>
 			function performUpdate(){
@@ -2691,7 +2819,7 @@ echo buildSettings(
 
         
      
-            $("#open-info, #open-users, #open-logs, #open-advanced, #open-homepage, #open-colors, #open-tabs, #open-donate ").on("click",function (e) {
+            $("#open-info, #open-users, #open-logs, #open-advanced, #open-homepage, #open-colors, #open-tabs, #open-donate, #open-invites ").on("click",function (e) {
                 $(".email-content").removeClass("email-active");
                 $('html').removeClass("overhid");
                 if($(window).width() < 768){

+ 60 - 10
user.php

@@ -197,6 +197,7 @@
 				// anything else won't change authentication status.
 				elseif($operation == "register") { $this->register($registration_callback); }
 				elseif($operation == "update") { $this->update(); }
+				elseif($operation == "invite") { $this->invite(); }
 				// we only allow password resetting if we can send notification mails
 				elseif($operation == "reset" && User::use_mail) { $this->reset_password(); }
 			}
@@ -334,6 +335,25 @@ EOT;
 			// step 2: if validation passed, update the user's information
 			return $this->update_user($username, $email, $sha1, $role);
 		}
+		/**
+		 * Called when the requested POST operation is "update"
+		 */
+		function invite()
+		{
+			// get relevant values
+            @$username = trim($_POST["username"]);
+			@$email = trim($_POST["email"]);
+			@$server = trim($_POST["server"]);
+			// step 1: someone could have bypassed the javascript validation, so validate again.
+			if($email !="" && preg_match(User::emailregexp, $email)==0) {
+				$this->info("<strong>invite error:</strong> email address did not pass validation");
+				writeLog("error", "$email didn't pass validation");
+				return false; 
+			}
+			// step 2: if validation passed, send the user's information for invite
+			return $this->invite_user($username, $email, $server);
+			writeLog("success", "passing invite info for $email");
+		}
 		/**
 		 * Reset a user's password
 		 */
@@ -357,7 +377,7 @@ EOT;
 			// step 2b: if there was a user to reset a password for, reset it.
 			$dbpassword = $this->token_hash_password($username, $sha1, $token);
 			$update = "UPDATE users SET password = '$dbpassword' WHERE email= '$email'";
-   writeLog("success", "$username has reset their password");
+   			writeLog("success", "$username has reset their password");
 			$this->database->exec($update);
             //$this->info("Email has been sent with new password");
 			// step 3: notify the user of the new password
@@ -564,7 +584,7 @@ EOT;
 			$query = "SELECT * FROM users WHERE username = '$username'";
 			foreach($this->database->query($query) as $data) {
 				$this->info("created user account for $username");
-    writeLog("success", "$username has just registered");
+    			writeLog("success", "$username has just registered");
 				$this->update_user_token($username, $sha1, false);
 				// make the user's data directory
 				$dir = USER_HOME . $username;
@@ -655,7 +675,7 @@ EOT;
 					file_put_contents(FAIL_LOG, $buildLog($username, "good_auth"));
 					chmod(FAIL_LOG, 0660);
 					setcookie("cookiePassword", COOKIEPASSWORD, time() + (86400 * 7), "/", DOMAIN);
-     writeLog("success", "$username has logged in");
+     				writeLog("success", "$username has logged in");
 					return true; 
 				} else if (AUTHBACKENDCREATE !== 'false' && $surface) {
 					// Create User
@@ -673,7 +693,7 @@ EOT;
 			} else if (!$authSuccess) {
 				// authentication failed
 				//$this->info("password mismatch for $username");
-    writeLog("error", "$username tried to sign-in with the wrong password");
+    			writeLog("error", "$username tried to sign-in with the wrong password");
 				file_put_contents(FAIL_LOG, $buildLog($username, "bad_auth"));
 				chmod(FAIL_LOG, 0660);
 				if(User::unsafe_reporting) { $this->error = "incorrect password for $username."; $this->error("incorrect password for $username."); }
@@ -704,9 +724,39 @@ EOT;
 				$dbpassword = $this->token_hash_password($username, $sha1, $this->get_user_token($username));
 				$update = "UPDATE users SET password = '$dbpassword' WHERE username = '$username'";
 				$this->database->exec($update); }
-   writeLog("success", "information for $username has been updated");
+   			writeLog("success", "information for $username has been updated");
 			$this->info("updated the information for <strong>$username</strong>");
 		}
+		/**
+		 * Invite using a user's information
+		 */
+		function invite_user($username = "none", $email, $server)
+		{
+			$now = date("Y-m-d H:i:s");
+			$inviteCode = randomCode(6);
+			$username = (!empty($username) ? $username : $server . " User");
+			$domain = getServerPath();
+			$link = getServerPath()."?inviteCode=".$inviteCode;
+			if($email !="") {
+				$insert = "INSERT INTO invites (username, email, code, valid, date) ";
+				$insert .= "VALUES ('".strtolower($username)."', '$email', '$inviteCode', 'Yes', '$now') ";
+				$this->database->exec($insert);
+			}
+   			writeLog("success", "$email has been invited to the $server server");
+			$this->info("$email has been invited to the $server server");
+			if($insert && User::use_mail)
+			{
+				// send email notification
+				$subject = User::DOMAIN_NAME . " $server invite!";
+				$body = <<<EOT
+	Hi $username,
+	Here is an invite to my $server server.  The code to join is $inviteCode.  You can head over to my website to join by going here: <a href="$domain">$domain</a> and clicking Join My Server.  You could also just click this <a href="$link">Link</a> to automatically fill in the info and join.
+	- the $domain_name team
+EOT;
+
+                $this->startEmail($email, $username, $subject, $body);
+			}
+		}
 		/**
 		 * Log a user out.
 		 */
@@ -725,7 +775,7 @@ EOT;
             unset($_COOKIE['cookiePassword']);
             setcookie("cookiePassword", '', time() - 3600, '/', DOMAIN);
             setcookie("cookiePassword", '', time() - 3600, '/');
-   writeLog("success", "$username has signed out");
+   			writeLog("success", "$username has signed out");
 			return true;
 		}
 		/**
@@ -737,10 +787,10 @@ EOT;
 			$this->database->exec($delete);
 			$this->info("<strong>$username</strong> has been kicked out of Organizr");
 			//$this->resetSession();
-    $dir = USER_HOME . $username;
-    if(!rmdir($dir)) { $this->error("could not delete user directory $dir"); }
-    $this->info("and we deleted user directory $dir");
-    writeLog("success", "$username has been deleted");
+    		$dir = USER_HOME . $username;
+    		if(!rmdir($dir)) { $this->error("could not delete user directory $dir"); }
+    		$this->info("and we deleted user directory $dir");
+    		writeLog("success", "$username has been deleted");
 			return true;
 		}
 		/**