$path,
'name' => $image
);
}
}
$dirname = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
$path = 'plugins/images/userTabs/';
$images = scandir($dirname);
foreach ($images as $image) {
if (!in_array($image, $ignore)) {
$allIconsPrep[$image] = array(
'path' => $path,
'name' => $image
);
}
}
ksort($allIconsPrep);
foreach ($allIconsPrep as $item) {
$allIcons[] = $item['path'] . $item['name'];
}
return $allIcons;
}
public function imageSelect($form)
{
$i = 1;
$images = $this->getImages();
$return = '';
}
public function getThemes()
{
$themes = array();
foreach (glob(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . "*.css") as $filename) {
$themes[] = array(
'name' => preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($filename)),
'value' => preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($filename))
);
}
return $themes;
}
public function getSounds()
{
$sounds = array();
foreach (glob(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'sounds' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . "*.mp3") as $filename) {
$sounds[] = array(
'name' => preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($filename)),
'value' => preg_replace('/\\.[^.\\s]{3,4}$/', '', 'plugins/sounds/default/' . basename($filename) . '.mp3')
);
}
foreach (glob(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'sounds' . DIRECTORY_SEPARATOR . 'custom' . DIRECTORY_SEPARATOR . "*.mp3") as $filename) {
$sounds[] = array(
'name' => preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($filename)),
'value' => preg_replace('/\\.[^.\\s]{3,4}$/', '', 'plugins/sounds/custom/' . basename($filename) . '.mp3')
);
}
return $sounds;
}
public function getBranches()
{
return array(
array(
'name' => 'Develop',
'value' => 'v2-develop'
),
array(
'name' => 'Master',
'value' => 'v2-master'
)
);
}
public function getAuthTypes()
{
return array(
array(
'name' => 'Organizr DB',
'value' => 'internal'
),
array(
'name' => 'Organizr DB + Backend',
'value' => 'both'
),
array(
'name' => 'Backend Only',
'value' => 'external'
)
);
}
public function getLDAPOptions()
{
return array(
array(
'name' => 'Active Directory',
'value' => '1'
),
array(
'name' => 'OpenLDAP',
'value' => '2'
),
array(
'name' => 'First IPA',
'value' => '3'
),
);
}
public function getAuthBackends()
{
$backendOptions = array();
$backendOptions[] = array(
'name' => 'Choose Backend',
'value' => false,
'disabled' => true
);
foreach (array_filter(get_class_methods('Organizr'), function ($v) {
return strpos($v, 'plugin_auth_') === 0;
}) as $value) {
$name = str_replace('plugin_auth_', '', $value);
if (strpos($name, 'disabled') === false) {
$backendOptions[] = array(
'name' => ucwords(str_replace('_', ' ', $name)),
'value' => $name
);
} else {
$backendOptions[] = array(
'name' => $this->$value(),
'value' => 'none',
'disabled' => true,
);
}
}
ksort($backendOptions);
return $backendOptions;
}
public function importUserButtons()
{
$emptyButtons = '
Currently User import is available for Plex only.
';
$buttons = '';
if (!empty($this->config['plexToken'])) {
$buttons .= '';
}
if (!empty($this->config['jellyfinURL']) && !empty($this->config['jellyfinToken'])) {
$buttons .= '';
}
if (!empty($this->config['embyURL']) && !empty($this->config['embyToken'])) {
$buttons .= '';
}
return ($buttons !== '') ? $buttons : $emptyButtons;
}
public function getHomepageMediaImage()
{
$refresh = false;
$cacheDirectory = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
if (!file_exists($cacheDirectory)) {
mkdir($cacheDirectory, 0777, true);
}
@$image_url = $_GET['img'];
@$key = $_GET['key'];
@$image_height = $_GET['height'];
@$image_width = $_GET['width'];
@$source = $_GET['source'];
@$itemType = $_GET['type'];
if (strpos($key, '$') !== false) {
$key = explode('$', $key)[0];
$refresh = true;
}
switch ($source) {
case 'plex':
$plexAddress = $this->qualifyURL($this->config['plexURL']);
$image_src = $plexAddress . '/photo/:/transcode?height=' . $image_height . '&width=' . $image_width . '&upscale=1&url=' . $image_url . '&X-Plex-Token=' . $this->config['plexToken'];
break;
case 'emby':
$embyAddress = $this->qualifyURL($this->config['embyURL']);
$imgParams = array();
if (isset($_GET['height'])) {
$imgParams['height'] = 'maxHeight=' . $_GET['height'];
}
if (isset($_GET['width'])) {
$imgParams['width'] = 'maxWidth=' . $_GET['width'];
}
$image_src = $embyAddress . '/Items/' . $image_url . '/Images/' . $itemType . '?' . implode('&', $imgParams);
break;
case 'jellyfin':
$jellyfinAddress = $this->qualifyURL($this->config['jellyfinURL']);
$imgParams = array();
if (isset($_GET['height'])) {
$imgParams['height'] = 'maxHeight=' . $_GET['height'];
}
if (isset($_GET['width'])) {
$imgParams['width'] = 'maxWidth=' . $_GET['width'];
}
$image_src = $jellyfinAddress . '/Items/' . $image_url . '/Images/' . $itemType . '?' . implode('&', $imgParams);
break;
default:
# code...
break;
}
if (isset($image_url) && isset($image_height) && isset($image_width) && isset($image_src)) {
$cachefile = $cacheDirectory . $key . '.jpg';
$cachetime = 604800;
// Serve from the cache if it is younger than $cachetime
if (file_exists($cachefile) && time() - $cachetime < filemtime($cachefile) && $refresh == false) {
header("Content-type: image/jpeg");
@readfile($cachefile);
exit;
}
ob_start(); // Start the output buffer
header('Content-type: image/jpeg');
$options = array('verify' => false);
$response = Requests::get($image_src, array(), $options);
if ($response->success) {
echo $response->body;
}
// Cache the output to a file
$fp = fopen($cachefile, 'wb');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush(); // Send the output to the browser
die();
} else {
die("Invalid Request");
}
}
public function cacheImage($url, $name, $extension = 'jpg')
{
$cacheDirectory = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
if (!file_exists($cacheDirectory)) {
mkdir($cacheDirectory, 0777, true);
}
$cacheFile = $cacheDirectory . $name . '.' . $extension;
$cacheTime = 604800;
if ((file_exists($cacheFile) && time() - $cacheTime < filemtime($cacheFile)) || !file_exists($cacheFile)) {
@copy($url, $cacheFile);
}
}
public function checkFrame($array, $url)
{
if (array_key_exists("x-frame-options", $array)) {
if ($array['x-frame-options'] == "deny") {
return false;
} elseif ($array['x-frame-options'] == "sameorgin") {
$digest = parse_url($url);
$host = (isset($digest['host']) ? $digest['host'] : '');
if ($this->getServer() == $host) {
return true;
} else {
return false;
}
}
} else {
if (!$array) {
return false;
}
return true;
}
}
public function frameTest($url)
{
if (!$url || $url == '') {
$this->setAPIResponse('error', 'URL not supplied', 404);
return false;
}
$array = array_change_key_case(get_headers($this->qualifyURL($url), 1));
$url = $this->qualifyURL($url);
if ($this->checkFrame($array, $url)) {
$this->setAPIResponse('success', 'URL approved for iFrame', 200);
return true;
} else {
$this->setAPIResponse('error', 'URL failed approval for iFrame', 409);
return false;
}
}
public function groupSelect()
{
$groups = $this->getAllGroups();
$select = array();
foreach ($groups as $key => $value) {
$select[] = array(
'name' => $value['group'],
'value' => $value['group_id']
);
}
return $select;
}
public function showLogin()
{
if ($this->config['hideRegistration'] == false) {
return 'Don\'t have an account?Sign Up
';
}
}
public function checkoAuth()
{
return $this->config['plexoAuth'] && $this->config['authBackend'] == 'plex' && $this->config['authType'] !== 'internal';
}
public function checkoAuthOnly()
{
return $this->config['plexoAuth'] && $this->config['authBackend'] == 'plex' && $this->config['authType'] == 'external';
}
public function showoAuth()
{
$buttons = '';
if ($this->config['plexoAuth'] && $this->config['authBackend'] == 'plex' && $this->config['authType'] !== 'internal') {
$buttons .= ' Login ';
}
return ($buttons) ? '
' : '';
}
public function logoOrText()
{
if ($this->config['useLogoLogin'] == false) {
return '' . $this->config['title'] . '
';
} else {
return '
';
}
}
public function settingsDocker()
{
$type = ($this->docker) ? 'Official Docker' : 'Native';
return '
Install Type ' . $type . '';
}
public function settingsPathChecks()
{
$paths = $this->pathsWritable($this->paths);
$items = '';
$type = (array_search(false, $paths)) ? 'Not Writable' : 'Writable';
$result = '
Organizr Paths ' . $type . '';
foreach ($paths as $k => $v) {
$items .= '
' . $k . ' ' . (($v['writable']) ? 'Writable' : 'Not Writable') . '';
}
return $result . $items;
}
public function pathsWritable($paths)
{
$results = array();
foreach ($paths as $k => $v) {
$results[$k] = [
'writable' => is_writable($v),
'path' => $v
];
}
return $results;
}
public function clearTautulliTokens()
{
foreach (array_keys($_COOKIE) as $k => $v) {
if (strpos($v, 'tautulli') !== false) {
$this->coookie('delete', $v);
}
}
}
public function analyzeIP($ip)
{
if (strpos($ip, '/') !== false) {
$explodeIP = explode('/', $ip);
$prefix = $explodeIP[1];
$start_ip = $explodeIP[0];
$ip_count = 1 << (32 - $prefix);
$start_ip_long = ip2long($start_ip);
$last_ip_long = ip2long($start_ip) + $ip_count - 1;
} elseif (substr_count($ip, '.') == 3) {
$start_ip_long = ip2long($ip);
$last_ip_long = ip2long($ip);
}
return (isset($start_ip_long) && isset($last_ip_long)) ? array('from' => $start_ip_long, 'to' => $last_ip_long) : false;
}
public function authProxyRangeCheck($from, $to)
{
$approved = false;
$userIP = ip2long($_SERVER['REMOTE_ADDR']);
$low = $from;
$high = $to;
if ($userIP <= $high && $low <= $userIP) {
$approved = true;
}
return $approved;
}
}
function embyJoinAPI($array)
{
$username = ($array['username']) ?? null;
$email = ($array['email']) ?? null;
$password = ($array['password']) ?? null;
if (!$username) {
$GLOBALS['api']['response']['result'] = 'error';
$GLOBALS['api']['response']['message'] = 'Username not supplied';
return false;
}
if (!$email) {
$GLOBALS['api']['response']['result'] = 'error';
$GLOBALS['api']['response']['message'] = 'Email not supplied';
return false;
}
if (!$password) {
$GLOBALS['api']['response']['result'] = 'error';
$GLOBALS['api']['response']['message'] = 'Password not supplied';
return false;
}
return embyJoin($username, $email, $password);
}
function embyJoin($username, $email, $password)
{
try {
#create user in emby.
$headers = array(
"Accept" => "application/json"
);
$data = array();
$url = $GLOBALS['embyURL'] . '/emby/Users/New?name=' . $username . '&api_key=' . $GLOBALS['embyToken'];
$response = Requests::Post($url, $headers, json_encode($data), array());
$response = $response->body;
//return($response);
$response = json_decode($response, true);
//return($response);
$userID = $response["Id"];
//return($userID);
#authenticate as user to update password.
//randomizer four digits of DeviceId
// I dont think ther would be security problems with hardcoding deviceID but randomizing it would mitigate any issue.
$deviceIdSeceret = rand(0, 9) . "" . rand(0, 9) . "" . rand(0, 9) . "" . rand(0, 9);
//hardcoded device id with the first three digits random 0-9,0-9,0-9,0-9
$embyAuthHeader = 'MediaBrowser Client="Emby Mobile", Device="Firefox", DeviceId="' . $deviceIdSeceret . 'aWxssS81LgAggFdpbmRvd3MgTlQgMTAuMDsgV2luNjxx7IHf2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzcyLjAuMzYyNi4xMTkgU2FmYXJpLzUzNy4zNnwxNTUxNTczMTAyNDI4", Version="4.0.2.0"';
$headers = array(
"Accept" => "application/json",
"Content-Type" => "application/json",
"X-Emby-Authorization" => $embyAuthHeader
);
$data = array(
"Pw" => "",
"Username" => $username
);
$url = $GLOBALS['embyURL'] . '/emby/Users/AuthenticateByName';
$response = Requests::Post($url, $headers, json_encode($data), array());
$response = $response->body;
$response = json_decode($response, true);
$userToken = $response["AccessToken"];
#update password
$embyAuthHeader = 'MediaBrowser Client="Emby Mobile", Device="Firefox", Token="' . $userToken . '", DeviceId="' . $deviceIdSeceret . 'aWxssS81LgAggFdpbmRvd3MgTlQgMTAuMDsgV2luNjxx7IHf2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzcyLjAuMzYyNi4xMTkgU2FmYXJpLzUzNy4zNnwxNTUxNTczMTAyNDI4", Version="4.0.2.0"';
$headers = array(
"Accept" => "application/json",
"Content-Type" => "application/json",
"X-Emby-Authorization" => $embyAuthHeader
);
$data = array(
"CurrentPw" => "",
"NewPw" => $password,
"Id" => $userID
);
$url = $GLOBALS['embyURL'] . '/emby/Users/' . $userID . '/Password';
Requests::Post($url, $headers, json_encode($data), array());
#update config
$headers = array(
"Accept" => "application/json",
"Content-Type" => "application/json"
);
$url = $GLOBALS['embyURL'] . '/emby/Users/' . $userID . '/Policy?api_key=' . $GLOBALS['embyToken'];
$response = Requests::Post($url, $headers, getEmbyTemplateUserJson(), array());
#add emby.media
try {
#seperate because this is not required
$headers = array(
"Accept" => "application/json",
"X-Emby-Authorization" => $embyAuthHeader
);
$data = array(
"ConnectUsername " => $email
);
$url = $GLOBALS['embyURL'] . '/emby/Users/' . $userID . '/Connect/Link';
Requests::Post($url, $headers, json_encode($data), array());
} catch (Requests_Exception $e) {
writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
$GLOBALS['api']['response']['message'] = $e->getMessage();
$GLOBALS['api']['response']['result'] = 'error';
return false;
}
$GLOBALS['api']['response']['message'] = 'User has joined Emby';
return (true);
//return( "USERID:".$userID);
} catch (Requests_Exception $e) {
writeLog('error', 'Emby create Function - Error: ' . $e->getMessage(), 'SYSTEM');
$GLOBALS['api']['response']['message'] = $e->getMessage();
$GLOBALS['api']['response']['result'] = 'error';
return false;
};
return false;
}
/*loads users from emby and returns a correctly formated policy for a new user.
*/
function getEmbyTemplateUserJson()
{
$headers = array(
"Accept" => "application/json"
);
$data = array();
$url = $GLOBALS['embyURL'] . '/emby/Users?api_key=' . $GLOBALS['embyToken'];
$response = Requests::Get($url, $headers, array());
$response = $response->body;
$response = json_decode($response, true);
//error_Log("response ".json_encode($response));
writeLog('error', 'userList:' . json_encode($response), 'SYSTEM');
//$correct stores the template users object
$correct = null;
foreach ($response as $element) {
if ($element['Name'] == $GLOBALS['INVITES-EmbyTemplate']) {
$correct = $element;
}
}
writeLog('error', 'Correct user:' . json_encode($correct), 'SYSTEM');
if ($correct == null) {
//return empty JSON if user incorectly configured template
return "{}";
}
//select policy section and remove possibly dangeours rows.
$policy = $correct['Policy'];
//writeLog('error', 'policy update'.$policy, 'SYSTEM');
unset($policy['AuthenticationProviderId']);
unset($policy['InvalidLoginAttemptCount']);
unset($policy['DisablePremiumFeatures']);
unset($policy['DisablePremiumFeatures']);
return (json_encode($policy));
}
function checkHostPrefix($s)
{
if (empty($s)) {
return $s;
}
return (substr($s, -1, 1) == '\\') ? $s : $s . '\\';
}