Init Repo

This commit is contained in:
Gregor Schulte
2021-06-15 11:08:34 +02:00
parent d0b72a118d
commit b303dd00d6
330 changed files with 93268 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,6 @@
;<?php
;die();
language = "de"
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,3 @@
;<?php
;die();
;?>

View File

@@ -0,0 +1,37 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'cache/cache.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Detaillierte &Uuml;bersicht'));
$cpu = rpi_getCPULoad(true, true);
$ram = rpi_getMemoryUsage();
$memory = rpi_getMemoryInfo();
$tpl->assign('time', date('d.m.Y H:i:s', time()));
$tpl->assign('timezone', date('e (P)', time()));
$tpl->assign('run_time', getDateFormat(rpi_getRuntime()));
$tpl->assign('start_time', formatTime(time() - rpi_getRuntime()));
$tpl->assign('serial', rpi_getRpiSerial());
$tpl->assign('revision', rpi_getRpiRevision());
$tpl->assign('distribution', rpi_getDistribution());
$tpl->assign('kernel', rpi_getKernelVersion());
$tpl->assign('webserver', $_SERVER['SERVER_SOFTWARE']);
$tpl->assign('php', PHP_VERSION);
$tpl->assign('whoami', exec('whoami'));
$tpl->assign('cpu_clock', rpi_getCpuClock().' MHz');
$tpl->assign('cpu_max_clock', rpi_getCpuMaxClock().' MHz');
$tpl->assign('cpu_load', $cpu['cpu']);
$tpl->assign('cpu_loads', (count($cpu) == 1) ? array() : array_slice($cpu, 1));
$tpl->assign('cpu_type', rpi_getCPUType());
$tpl->assign('cpu_model', rpi_getCpuModel());
$tpl->assign('cpu_temp', numberFormat(rpi_getCoreTemprature()).' &deg;C');
$tpl->assign('ram_percentage', $ram['percent'].'%');
$tpl->assign('memory', $memory);
$tpl->assign('memory_count', count($memory));
$tpl->assign('runningTasksCount', rpi_getCountRunningTasks());
$tpl->assign('installedPackagesCount', rpi_getCountInstalledPackages());
$tpl->draw('detailed_overview');
?>

View File

@@ -0,0 +1,45 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('Plugins entdecken'));
$showList = true;
$plugins = pluginList();
$onlinePlugins = getOnlinePlugins();
$availableUpdates = checkPluginUpdate($plugins, $onlinePlugins);
if (!is_array($onlinePlugins))
{
$tpl->error(_t('Fehler beim Abrufen'), _t('Leider ist beim Abrufen der Plugins ein Fehler aufgetreten. Fehlercode: %s', $onlinePlugins));
$showList = false;
}
if (isset($_GET['id']) && $_GET['id'] != '')
{
if (isset($onlinePlugins[$_GET['id']]))
{
$showList = false;
include_once 'discover_plugins_info.php';
}
else
$tpl->msg('error', _t('Plugin nicht gefunden'), _t('Das von dir gesuchte Plugin konnte nicht gefunden werden.'));
}
if ($showList == true)
{
$disabledPluginsCount = 0;
foreach ($plugins as $plugin)
{
if ($plugin['disabled'] == true)
$disabledPluginsCount += 1;
}
$tpl->assign('plugins', $plugins);
$tpl->assign('onlinePlugins', $onlinePlugins);
$tpl->assign('availableUpdates', $availableUpdates);
$tpl->assign('disabledPluginsCount', $disabledPluginsCount);
$tpl->draw('discover_plugins');
}
?>

View File

@@ -0,0 +1,31 @@
<?php
if (!defined('PICONTROL')) exit();
$pluginId = $_GET['id'];
$tpl->setHeaderTitle($onlinePlugins[$pluginId]['name'].' - '._t('Plugins entdecken'));
if (isset($_GET['status']) && $_GET['status'] == '')
{
$gPlugin = $plugins[$pluginId];
include_once 'settings/plugins_status.php';
$plugins = pluginList();
}
if (isset($_GET['install']) && $_GET['install'] == '')
$tpl->redirect('?i=download_plugin&id='.$pluginId);
if (isset($_GET['installed']) && $_GET['installed'] == '')
$tpl->msg('success', _t('Plugin installiert'), _t('Das Plugin wurde erfolgreich installiert.'));
if (isset($_GET['update']) && $_GET['update'] == '')
$tpl->redirect('?i=update_plugin&id='.$pluginId);
if (isset($_GET['updated']) && $_GET['updated'] == '')
$tpl->msg('success', _t('Plugin aktualisiert'), _t('Das Plugin wurde erfolgreich aktualisiert.'));
$tpl->assign('plugin', isset($plugins[$pluginId]) ? $plugins[$pluginId] : array());
$tpl->assign('onlinePlugin', $onlinePlugins[$pluginId]);
$tpl->draw('discover_plugins_info');
?>

View File

@@ -0,0 +1,14 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl = new PiTpl;
global $globalLanguage;
$tpl->assign('errorHandler', urlencode(base64_encode(json_encode($tplErrorHandler))));
$tpl->assign('version', $tplConfig['version']['version']);
$tpl->assign('helpLink', $tplConfig['url']['help'].getURLLangParam(false, true, true));
$tpl->assign('language', $globalLanguage);
$tpl->draw('html_footer');
?>

View File

@@ -0,0 +1,67 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl = new PiTpl;
$tpl->assign('title', (isset($data['title']) && $data['title'] != '') ? $data['title'] : 'Pi Control');
$pluginHeaderNavi = array();
$pluginHeaderNaviString = '';
if (file_exists(PLUGINS_PATH) && is_dir(PLUGINS_PATH))
{
foreach (pluginList(false) as $plugin)
{
if (is_array($plugin))
$pluginHeaderNavi[] = array('name' => $plugin['name'], 'id' => $plugin['id']);
}
if (empty($pluginHeaderNavi))
$pluginHeaderNaviString = '<strong class="red">'._t('Keine Plugins!').'</strong>';
if ((getConfig('cron:updateCheck.plugins', 0)+86400) < time() || (isset($_GET['s']) && $_GET['s'] == 'discover_plugins'))
{
$availableUpdates = checkPluginUpdate();
if (isset($availableUpdates) && is_array($availableUpdates) && !empty($availableUpdates))
setConfig('cron:updateCheck.plugins', time()-86400);
else
setConfig('cron:updateCheck.plugins', time());
}
if ((getConfig('cron:updateCheck.picontrol', 0)+86400) < time() || (isset($_GET['s'], $_GET['do']) && $_GET['s'] == 'settings' && $_GET['do'] == 'update'))
{
$picontrolUpdate = checkUpdate();
if (!is_array($picontrolUpdate))
setConfig('cron:updateCheck.picontrol', time());
else
setConfig('cron:updateCheck.picontrol', time()-86400);
}
}
else
$pluginHeaderNaviString = '<strong class="red">'._t('Pluginordner nicht gefunden!').'</strong>';
$referer = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
if ($referer != '')
$referer = '&referer='.urlencode($referer);
// Uebersetzung
$jsTranslations = $data['jsTranslations'];
$jsTranslations[] = 'Leider ist ein unerwarteter Fehler aufgetreten. Bitte schließe das Feedback-Fenster und versuche es erneut. Andernfalls, schreibe mir unter <a href="%%s" target="_blank">Kontakt</a>.';
$jsTranslations[] = 'Schließen';
$jsTranslations[] = 'F&uuml;r das Feedback m&uuml;ssen noch einige Daten gesammelt werden.';
$jsTranslations[] = 'Diagnosedaten wurden gesammelt. Beim Klick auf den folgenden Button wird ein neues Fenster ge&ouml;ffnet.';
$jsTranslations[] = 'Feedback &ouml;ffnen';
$tpl->assign('jsTranslations', getTranslatedArrayForJs($jsTranslations));
$tpl->assign('naviPlugins', !empty($pluginHeaderNavi) ? array_sort($pluginHeaderNavi, 'name', SORT_ASC) : $pluginHeaderNaviString);
$tpl->assign('naviPluginsUpdates', (isset($availableUpdates) && !empty($availableUpdates)) ? $availableUpdates : NULL);
$tpl->assign('updatePicontrol', isset($picontrolUpdate) ? $picontrolUpdate : '');
$tpl->assign('cronExecutionFault', (getConfig('cron:execution.cron', 0)+140 < time()) ? true : false);
$tpl->assign('username', getConfig('user:user_'.getConfig('login:token_'.$_COOKIE['_pi-control_login'].'.username', '').'.username', ''));
$tpl->assign('referer', $referer);
$tpl->assign('headerInfo', getInfoForHeaderBar());
$tpl->draw('html_header');
?>

View File

@@ -0,0 +1,13 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Installierte Pakete'));
$packages = rpi_getInstalledPackages();
$tpl->assign('installedPackages', $packages);
$tpl->assign('installedPackagesCount', count($packages));
$tpl->draw('installed_packages');
?>

126
resources/content/login.php Normal file
View File

@@ -0,0 +1,126 @@
<?php
if (!defined('PICONTROL')) exit();
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'main/tpl.class.php') or die('Error: 0x0011');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0012');
$tpl = new PiTpl;
$tpl->setTpl($tpl);
$tpl->setTplFolder(TEMPLATES_PATH);
$tpl->setDrawHeader(false);
$tpl->setDrawFooter(false, $config);
$externalAccess = (urlIsPublic($_SERVER['REMOTE_ADDR']) && getConfig('main:access.external', 'false') == 'false') ? false : true;
$nextTry = getConfig('login:login.nextTry');
if ($externalAccess === false)
$tpl->assign('errorMsg', _t('Der Zugang steht nur im lokalem Netzwerk (LAN) zur Verf&uuml;gung!'));
elseif ($nextTry > time())
$tpl->assign('errorMsg', _t('Login noch f&uuml;r %d Sekunden gesperrt!', $nextTry-time()));
if (isset($_POST['submit'], $_POST['username'], $_POST['password']) && $externalAccess === true)
{
if (trim($_POST['username']) != '' && $_POST['password'] != '')
{
$pUsername = strtolower(trim($_POST['username']));
$pPassword = $_POST['password'];
$try = getConfig('login:login.try');
do
{
if ($nextTry > time())
break;
if (($userinfo = getConfig('user:user_'.$pUsername, 0)) === 0)
break;
if (!is_array($userinfo))
break;
if (strtolower($userinfo['username']) != $pUsername || password_verify($pPassword, $userinfo['password']) !== true)
break;
setConfig('login:login.try', 0);
setConfig('login:login.nextTry', 0);
$uniqid = generateUniqId(32, false);
if (setConfig('login:token_'.$uniqid.'.created', time()) !== true) break;
if (setConfig('login:token_'.$uniqid.'.username', $pUsername) !== true) break;
if (setConfig('login:token_'.$uniqid.'.address', $_SERVER['REMOTE_ADDR']) !== true) break;
if (setConfig('user:user_'.$pUsername.'.last_login', time()) !== true) break;
if (isset($_POST['rememberMe']) && $_POST['rememberMe'] == 'checked')
{
setConfig('login:token_'.$uniqid.'.remember_me', 'true');
setcookie('_pi-control_login', $uniqid, time()+60*60*24*30);
}
else
setcookie('_pi-control_login', $uniqid, time()+60*60*12);
if (isset($_POST['referer']) && $_POST['referer'] != '')
header('Location: ?'.urldecode($_POST['referer']));
else
header('Location: ?s=overview');
exit();
}
while (false);
if ($nextTry > time())
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!<br />Login noch f&uuml;r %d Sekunden gesperrt!', $nextTry-time()));
}
elseif ($try == 5)
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!<br />Zu viele Fehlversuche. Login f&uuml;r %d Sekunden gesperrt!', 30));
setConfig('login:login.nextTry', time() + 30);
}
elseif ($try == 6)
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!<br />Zu viele Fehlversuche. Login f&uuml;r %d Minute gesperrt!', 1));
setConfig('login:login.nextTry', time() + 60);
}
elseif ($try == 7)
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!<br />Zu viele Fehlversuche. Login f&uuml;r %d Minuten gesperrt!', 2));
setConfig('login:login.nextTry', time() + 120);
}
elseif ($try >= 8)
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!<br />Zu viele Fehlversuche. Login f&uuml;r %d Minuten gesperrt!', 5));
setConfig('login:login.nextTry', time() + 300);
}
else
{
$tpl->assign('errorMsg', _t('Fehler bei der Anmeldung!'));
}
setConfig('login:login.try', $try + 1);
}
}
if (isset($_GET['logout']))
{
if (isset($_COOKIE['_pi-control_login']))
{
$uniqid = $_COOKIE['_pi-control_login'];
removeConfig('login:token_'.$uniqid);
setcookie('_pi-control_login', '', time()-60);
}
if (isset($_GET['referer']) && $_GET['referer'] != '')
header('Location: ?i=login&referer='.urlencode($_GET['referer']));
else
header('Location: ?i=login');
exit();
}
$tpl->assign('referer', isset($_GET['referer']) ? $_GET['referer'] : (isset($_POST['referer']) ? urlencode($_POST['referer']) : ''));
$tpl->assign('externalAccess', $externalAccess);
$tpl->draw('login');
?>

View File

@@ -0,0 +1,53 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'log/log.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'log/log.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Logdateien'));
if (isset($_POST['open_file']))
{
$tpl->redirect('?s=logs&view='.urlencode($_POST['relative_path'].$_POST['filename']));
}
if (isset($_GET['view']) && ($view = trim(urldecode($_GET['view']))) != '')
{
$logController = new LogController('/var/log');
$log = $logController->getLogFromRelativePath($view);
if (!$log instanceof LogEntry) {
$tpl->error(_t('Logdatei nicht gefunden'), _t('Leider konnte die angegebene Logdatei nicht gefunden oder ge&ouml;ffnet werden!'));
}
else
{
if ($log->getFilesize() > 10240000) {
$tpl->assign('filesizeError', true);
} else {
set_time_limit(60);
$readLog = $logController->readLog($log->getPath());
$tpl->assign('logOutput', $readLog['output']);
$tpl->assign('logLines', $readLog['lines']);
}
$tpl->assign('log', $log);
$tpl->draw('logs_view');
}
}
elseif (isset($_GET['download']))
{
$tpl->redirect('api/v1/logs_download.php?log='.$_GET['download']);
}
else
{
$logController = new LogController('/var/log/');
$tpl->assign('logs', $logController->getAll());
$tpl->assign('sshAvailable', $logController->isSshAvailable());
$tpl->draw('logs');
}
?>

11
resources/content/msg.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl = new PiTpl;
$tpl->assign('type', $data['type']);
$tpl->assign('title', $data['title']);
$tpl->assign('msg', $data['msg']);
$tpl->assign('cancelable', $data['cancelable']);
$tpl->draw('msg');
?>

View File

@@ -0,0 +1,60 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'network/network.function.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Netzwerk'));
if (isset($_GET['hostname']))
{
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['hostname']) && trim($pHostname = trim($_POST['hostname'])) != '')
{
if (preg_match('/^([a-z][a-z0-9\-\.]*[^\-]){1,24}$/im', $pHostname))
{
if (($status = editHostname($pHostname)) === true)
$tpl->msg('success', _t('Hostname gespeichert'), _t('Damit die &Auml;nderung wirksam wird, muss dein Raspberry Pi neu gestartet werden. <a href="%s">Jetzt neu starten.</a>', '?s=shutdown&restart'));
else
$tpl->msg('error', _t('Fehler'), _t('Fehler beim &Auml;ndern des Hostname! Fehlercode: %s', $status));
}
else
$tpl->msg('error', _t('Fehler'), _t('Der Hostname ist ung&uuml;ltig! Er muss aus mindestens 1 bis 24 Zeichen bestehen und darf nur folgende Zeichen enthalten: A-Z a-z 0-9 -<br />Der Hostname darf nicht mit einem Bindestrich Anfangen oder Enden.'));
}
}
$tpl->assign('hostname', rpi_getHostname());
$tpl->draw('network_hostname');
}
else
{
$networkConnections = getAllNetworkConnections();
$networkCounts = unserialize(htmlspecialchars_decode(getConfig('main:network.overflowCount', 'a:0:{}')));
$counter = 0;
foreach ($networkConnections as $network)
{
$countSent = 0;
$countReceive = 0;
if (isset($networkCounts[$network['interface']]['sent']))
$countSent = $networkCounts[$network['interface']]['sent'];
if (isset($networkCounts[$network['interface']]['receive']))
$countReceive = $networkCounts[$network['interface']]['receive'];
$networkConnections[$counter]['sent'] = (4294967295 * $countSent) + $network['sent'];
$networkConnections[$counter]['receive'] = (4294967295 * $countReceive) + $network['receive'];
$counter += 1;
}
$tpl->assign('network_connections', $networkConnections);
$tpl->assign('hostname', rpi_getHostname());
$tpl->assign('wlan', scanAccessPoints($networkConnections, (isset($_GET['refresh_wlan'])) ? true : false));
$tpl->draw('network');
}
?>

View File

@@ -0,0 +1,44 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'network/network.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'network/network.class.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Netzwerkkonfiguration'));
$jsTranslations = array();
$jsTranslations[] = 'Das Interface wird neu gestartet...';
$jsTranslations[] = 'Das Interface wurde neu gestartet.';
$jsTranslations[] = 'Es ist ein unerwarteter Fehler aufgetreten!';
$jsTranslations[] = 'Es ist ein Fehler aufgetreten! Vermutlich wurde die Verbindung getrennt.';
$jsTranslations[] = 'Es kann nur ein Interface zeitgleich neu gestartet werden.';
$networkInterface = new NetworkInterface($tpl);
if (isset($_GET['msg']) && $_GET['msg'] == 'add')
$tpl->msg('success', _t('Interface hinzugef&uuml;gt'), _t('Interface wurde erfolgreich hinzugef&uuml;gt. Damit diese Einstellungen jedoch wirksam werden, muss das Interface neu gestartet werden.'));
elseif (isset($_GET['msg']) && $_GET['msg'] == 'delete')
$tpl->msg('success', _t('Interface gel&ouml;scht'), _t('Interface wurde erfolgreich gel&ouml;scht.'));
if (isset($_GET['add']) && $_GET['add'] == '')
include_once 'network_configuration_add.php';
elseif (isset($_GET['edit']) && $_GET['edit'] != '' && $networkInterface->existsInterface(urldecode($_GET['edit'])))
include_once 'network_configuration_edit.php';
elseif (isset($_GET['delete']) && $_GET['delete'] != '' && $networkInterface->existsInterface(urldecode($_GET['delete'])))
include_once 'network_configuration_delete.php';
elseif (isset($_GET['edit']) || isset($_GET['delete']))
{
$tpl->msg('error', _t('Interface nicht verf&uuml;gbar'), _t('Es wurde kein Interface mit dem angegebenen Namen gefunden!'), false);
$tpl->assign('interfaces', $networkInterface->getInterfaces());
$tpl->assign('jsTranslations', $jsTranslations);
$tpl->draw('network_configuration');
}
else
{
$tpl->assign('interfaces', $networkInterface->getInterfaces());
$tpl->assign('jsTranslations', $jsTranslations);
$tpl->draw('network_configuration');
}
?>

View File

@@ -0,0 +1,60 @@
<?php
if (!defined('PICONTROL')) exit();
// Fehler vorbeugen
$tpl->getSSHResource(1);
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['interface'], $_POST['protocol'], $_POST['method'], $_POST['checksum']) && ($pInterface = trim($_POST['interface'])) != '' && ($pProtocol = trim($_POST['protocol'])) != '' && ($pMethod = trim($_POST['method'])) != '' && ($pChecksum = trim($_POST['checksum'])) != '' && in_array($_POST['protocol'], array('inet', 'inet6', 'ipx')) && in_array($_POST['method'], array('dhcp', 'static', 'manual')))
{
if ($pChecksum == $networkInterface->getInterfaceHash())
{
$newInterface = array('protocol' => $pProtocol, 'method' => $pMethod);
if ($pMethod == 'static')
{
if (isset($_POST['address']) && ($pAddress = trim($_POST['address'])) != '')
$newInterface['iface']['address'] = $pAddress;
else
$newInterface['iface']['address'] = NULL;
if (isset($_POST['netmask']) && ($pNetmask = trim($_POST['netmask'])) != '')
$newInterface['iface']['netmask'] = $pNetmask;
else
$newInterface['iface']['netmask'] = NULL;
if (isset($_POST['gateway']) && ($pGateway = trim($_POST['gateway'])) != '')
$newInterface['iface']['gateway'] = $pGateway;
else
$newInterface['iface']['gateway'] = NULL;
}
if ($networkInterface->existsInterface($pInterface) === true)
$tpl->msg('error', _t('Fehler'), _t('Leider konnte das Interface nicht gespeichert werden. Der Name f&uuml;r dieses Interface ist bereits vergeben.'), true, 10);
if ($tpl->msgExists(10) === false)
{
if ($networkInterface->addInterface($pInterface, $newInterface) === true)
$tpl->redirect('?s=network_configuration&edit='.urlencode($pInterface).'&msg=add');
else
$tpl->msg('error', _t('Fehler'), _t('Leider konnte das Interface nicht gespeichert werden. Es ist w&auml;hrend der &Uuml;bertragung ein Fehler aufgetreten.'));
}
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider wurde die Konfigurationsdatei zwischenzeitlich ver&auml;ndert, versuche es deshalb noch einmal.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte vergebe eine Interfacebezeichnung, ein Protokoll und eine Methode!'));
}
$tpl->assign('checksum', $networkInterface->getInterfaceHash());
$tpl->assign('interfaceName', isset($_POST['interface']) ? $_POST['interface'] : '');
$tpl->assign('interfaceProtocol', isset($_POST['protocol']) ? $_POST['protocol'] : '');
$tpl->assign('interfaceMethod', isset($_POST['method']) ? $_POST['method'] : '');
$tpl->assign('interfaceAddress', isset($_POST['address']) ? $_POST['address'] : '');
$tpl->assign('interfaceNetmask', isset($_POST['netmask']) ? $_POST['netmask'] : '');
$tpl->assign('interfaceGateway', isset($_POST['gateway']) ? $_POST['gateway'] : '');
$tpl->draw('network_configuration_add');
?>

View File

@@ -0,0 +1,29 @@
<?php
if (!defined('PICONTROL')) exit();
$interfaceName = urldecode($_GET['delete']);
// Fehler vorbeugen
$tpl->getSSHResource(1);
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['checksum']) && ($pChecksum = trim($_POST['checksum'])) != '')
{
if ($pChecksum == $networkInterface->getInterfaceHash())
{
if ($networkInterface->deleteInterface($interfaceName) === true)
$tpl->redirect('?s=network_configuration&msg=delete');
else
$tpl->msg('error', _t('Fehler'), _t('Leider konnte das Interface nicht gel&ouml;scht werden. Es ist w&auml;hrend der &Uuml;bertragung ein Fehler aufgetreten.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider wurde die Konfigurationsdatei zwischenzeitlich ver&auml;ndert, versuche es deshalb noch einmal.'));
}
}
$tpl->assign('checksum', $networkInterface->getInterfaceHash());
$tpl->assign('interfaceName', $interfaceName);
$tpl->draw('network_configuration_delete');
?>

View File

@@ -0,0 +1,69 @@
<?php
if (!defined('PICONTROL')) exit();
$interfaceName = urldecode($_GET['edit']);
$interface = $networkInterface->getInterface($interfaceName);
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['interface'], $_POST['protocol'], $_POST['method'], $_POST['checksum']) && ($pInterface = trim($_POST['interface'])) != '' && ($pProtocol = trim($_POST['protocol'])) != '' && ($pMethod = trim($_POST['method'])) != '' && ($pChecksum = trim($_POST['checksum'])) != '' && in_array($_POST['protocol'], array('inet', 'inet6', 'ipx')) && in_array($_POST['method'], array('dhcp', 'static', 'manual')))
{
if ($pChecksum == $networkInterface->getInterfaceHash())
{
$newInterfaceName = NULL;
$newInterface = array('protocol' => $pProtocol, 'method' => $pMethod);
if ($pMethod == 'static')
{
if (isset($_POST['address']) && ($pAddress = trim($_POST['address'])) != '')
$newInterface['iface']['address'] = $pAddress;
else
$newInterface['iface']['address'] = NULL;
if (isset($_POST['netmask']) && ($pNetmask = trim($_POST['netmask'])) != '')
$newInterface['iface']['netmask'] = $pNetmask;
else
$newInterface['iface']['netmask'] = NULL;
if (isset($_POST['gateway']) && ($pGateway = trim($_POST['gateway'])) != '')
$newInterface['iface']['gateway'] = $pGateway;
else
$newInterface['iface']['gateway'] = NULL;
}
else
$newInterface['iface'] = NULL;
if ($pInterface != $interfaceName && $networkInterface->existsInterface($pInterface) == false)
$newInterfaceName = $pInterface;
elseif ($pInterface != $interfaceName)
$tpl->msg('error', _t('Fehler'), _t('Leider konnte das Interface nicht gespeichert werden. Der Name f&uuml;r dieses Interface ist bereits vergeben.'), true, 10);
if ($tpl->msgExists(10) === false)
{
if ($networkInterface->editInterface($interfaceName, $newInterface, $newInterfaceName) === true)
$tpl->msg('success', _t('Interface gespeichert'), _t('Interface wurde erfolgreich gespeichert. Damit diese Einstellungen jedoch wirksam werden, muss das Interface neu gestartet werden.'));
else
$tpl->msg('error', _t('Fehler'), _t('Leider konnte das Interface nicht gespeichert werden. Es ist w&auml;hrend der &Uuml;bertragung ein Fehler aufgetreten.'));
$interfaceName = $pInterface;
}
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider wurde die Konfigurationsdatei zwischenzeitlich ver&auml;ndert, versuche es deshalb noch einmal.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte vergebe eine Interfacebezeichnung, ein Protokoll und eine Methode!'));
}
$interfaces = $networkInterface->getInterfaces();
$tpl->assign('checksum', $networkInterface->getInterfaceHash());
$tpl->assign('interfaceName', $interfaceName);
$tpl->assign('interfaceProtocol', isset($networkInterface->getInterface($interfaceName)['protocol']) ? $networkInterface->getInterface($interfaceName)['protocol'] : '');
$tpl->assign('interfaceMethod', isset($networkInterface->getInterface($interfaceName)['method']) ? $networkInterface->getInterface($interfaceName)['method'] : '');
$tpl->assign('interfaceAddress', isset($networkInterface->getInterface($interfaceName)['iface']['address']) ? $networkInterface->getInterface($interfaceName)['iface']['address'] : '');
$tpl->assign('interfaceNetmask', isset($networkInterface->getInterface($interfaceName)['iface']['netmask']) ? $networkInterface->getInterface($interfaceName)['iface']['netmask'] : '');
$tpl->assign('interfaceGateway', isset($networkInterface->getInterface($interfaceName)['iface']['gateway']) ? $networkInterface->getInterface($interfaceName)['iface']['gateway'] : '');
$tpl->draw('network_configuration_edit');
?>

View File

@@ -0,0 +1,21 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('WLAN-Verbindung herstellen'));
$jsTranslations = array();
$jsTranslations[] = 'Das Passwort sollte mindestens 8 Zeichen betragen.';
$jsTranslations[] = 'Verbindung wird getrennt...';
$jsTranslations[] = 'Verbindung wird wieder hergestellt...';
$jsTranslations[] = 'Ermittle IP-Adresse von Verbindung...';
$jsTranslations[] = 'Verbindung mit "%%s" war erfolgreich.';
$jsTranslations[] = 'IP-Adresse';
$tpl->assign('jsVariables', 'var _interface = \''.urldecode($_GET['interface']).'\'; var _ssid = \''.urldecode($_GET['ssid']).'\';');
$tpl->assign('interface', urldecode($_GET['interface']));
$tpl->assign('ssid', urldecode($_GET['ssid']));
$tpl->assign('encryption', urldecode($_GET['encryption']));
$tpl->assign('jsTranslations', $jsTranslations);
$tpl->draw('network_connect');
?>

View File

@@ -0,0 +1,34 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'cache/cache.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('&Uuml;bersicht'));
$ram = rpi_getMemoryUsage();
$memory = rpi_getMemoryInfo();
$weather = new Cache('weather', 'getWeather');
$usbDevices = new Cache('usb_devices', 'rpi_getUsbDevices');
$weather->load();
$usbDevices->load();
$tpl->assign('js_variables', 'var reload_timeout = '.(getConfig('main:overview.interval', 30)*1000).';');
$tpl->assign('show_weather', (getConfig('main:weather.activation', 'false') == 'true') ? true : false);
$tpl->assign('weather', (getConfig('main:weather.activation', 'false') == 'true') ? $weather->getContent() : '');
$tpl->assign('weather_cache_hint', $weather->displayHint());
$tpl->assign('run_time', getDateFormat(rpi_getRuntime()));
$tpl->assign('start_time', formatTime(time() - rpi_getRuntime()));
$tpl->assign('cpu_clock', rpi_getCpuClock().' MHz');
$tpl->assign('cpu_load', rpi_getCPULoad().'%');
$tpl->assign('cpu_type', rpi_getCPUType());
$tpl->assign('cpu_temp', numberFormat(rpi_getCoreTemprature()).' &deg;C');
$tpl->assign('ram_percentage', $ram['percent'].'%');
$tpl->assign('memory', end($memory));
$tpl->assign('usb_devices', (getConfig('main:overview.showDevices', 'true') == 'true') ? $usbDevices->getContent() : '');
$tpl->assign('usb_devices_cache_hint', $usbDevices->displayHint());
$tpl->assign('jsTranslations', array('Fehler!'));
$tpl->draw('overview');
?>

View File

@@ -0,0 +1,62 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('Plugins'));
$plugins = pluginList();
$pluginLoaded = false;
if (isset($_GET['id']))
{
if (isset($plugins[$_GET['id']]))
{
$plugin = $plugins[$_GET['id']];
if ($plugin['disabled'] == false)
{
if ($plugin['compatible'] == true)
{
$pluginLoaded = true;
$tpl->setTplFolderPlugin('resources/plugins/'.$plugin['id']);
define('PLUGIN_ID', $plugin['id']);
define('PLUGIN_PATH', PLUGINS_PATH.$plugin['id'].'/');
define('PLUGIN_PUBLIC_PATH', str_replace(PICONTROL_PATH, '', PLUGINS_PATH.$plugin['id'].'/'));
$tpl->setHeaderTitle(_t($plugin['name']));
if (file_exists(PLUGIN_PATH.'resources/library/main/sites.php') && is_file(PLUGIN_PATH.'resources/library/main/sites.php'))
include PLUGIN_PATH.'resources/library/main/sites.php';
if (isset($_GET['settings']))
{
if ($plugin['settings'] === true)
include PLUGIN_PATH.'resources/content/settings/settings.php';
else
$tpl->msg('error', _t('Fehler beim Laden des Plugins'), _t('Das gesuchte Plugin unterst&uuml;tzt momentan keine Einstellungen.'), false);
}
elseif (isset($pluginSite, $_GET['do']) && isset($pluginSite[$_GET['do']]) && file_exists(PLUGIN_PATH.'resources/content/'.$pluginSite[$_GET['do']]))
include PLUGIN_PATH.'resources/content/'.$pluginSite[$_GET['do']];
else
include PLUGIN_PATH.'resources/content/index.php';
$tpl->setTplFolderPlugin('');
}
else
$tpl->msg('error', _t('Plugin ist inkompatibel'), _t('Das gesuchte Plugin kann aktuell nicht ge&ouml;ffnet werden, da es inkompatibel ist. Bitte aktualisiere dein Pi Control, um das Plugin weiterhin verwenden zu k&ouml;nnen.'), true);
}
else
$tpl->msg('error', _t('Plugin ist deaktiviert'), _t('Das gesuchte Plugin kann aktuell nicht ge&ouml;ffnet werden, da es deaktiviert ist.'));
}
else
$tpl->msg('error', _t('Plugin nicht gefunden'), _t('Das gesuchte Plugin kann aktuell nicht gefunden werden oder es existiert nicht.'));
}
if ($pluginLoaded === false)
{
$plugins = array_filter($plugins, function($plugin) { if ($plugin['disabled'] == true) return false; return true; });
$tpl->assign('plugins', $plugins);
$tpl->draw('plugins');
}
?>

View File

@@ -0,0 +1,49 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'process/process.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'process/process.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Prozesse'));
$processController = new ProcessController;
if (isset($_POST['terminate'], $_POST['pid'], $_POST['startTime']) && $_POST['terminate'] != '' && ($pid = $_POST['pid']) != '' && ($startTime = $_POST['startTime']) != '')
{
if ($pid > 0)
{
if (ProcessController::isPidWithStartTimeExists($pid, $startTime))
{
if ($processController->terminatePid($pid, $startTime))
$tpl->msg('success', _t('Prozess beendet'), _t('Der Prozess mit der ID %s wurde erfolgreich beendet.', $pid));
else
$tpl->msg('error', _t('Fehler'), _t('Der Prozess mit der ID %s konnte nicht beendet werden.', $pid));
}
else
$tpl->msg('error', _t('Fehler'), _t('Der Prozess mit der ID %s konnte nicht gefunden werden.', $pid));
}
}
elseif (isset($_POST['kill'], $_POST['pid'], $_POST['startTime']) && $_POST['kill'] != '' && ($pid = $_POST['pid']) != '' && ($startTime = $_POST['startTime']) != '')
{
if ($pid > 0)
{
if (ProcessController::isPidWithStartTimeExists($pid, $startTime))
{
if ($processController->killPid($pid, $startTime))
$tpl->msg('success', _t('Prozess abgew&uuml;rgt'), _t('Der Prozess mit der ID %s wurde erfolgreich abgew&uuml;rgt.', $pid));
else
$tpl->msg('error', _t('Fehler'), _t('Der Prozess mit der ID %s konnte nicht abgew&uuml;rgt werden.', $pid));
}
else
$tpl->msg('error', _t('Fehler'), _t('Der Prozess mit der ID %s konnte nicht gefunden werden.', $pid));
}
}
$tpl->assign('processCount', $processController->getCount());
$tpl->assign('processCountRunning', $processController->getCountRunning());
$tpl->assign('processes', $processController->getProcesses());
$tpl->assign('sshAvailable', ($tpl->getSSHResource() instanceof Net_SSH2) ? true : false);
$tpl->draw('processes');
?>

View File

@@ -0,0 +1,41 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'cron/cron.class.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'cache/cache.class.php') or die('Error: 0x0011');
(include_once LIBRARY_PATH.'curl/curl.class.php') or die('Error: 0x0012');
$tpl->setHeaderTitle(_t('Einstellungen'));
switch ((isset($_GET['do']) ? $_GET['do'] : ''))
{
case 'overview':
include_once CONTENT_PATH.'settings/overview.php';
break;
case 'pi-control':
include_once CONTENT_PATH.'settings/pi-control.php';
break;
case 'update':
include_once CONTENT_PATH.'settings/update.php';
break;
case 'plugins':
include_once CONTENT_PATH.'settings/plugins.php';
break;
case 'troubleshooting':
include_once CONTENT_PATH.'settings/troubleshooting.php';
break;
case 'statistic':
include_once CONTENT_PATH.'settings/statistic.php';
break;
case 'notification':
include_once CONTENT_PATH.'settings/notification.php';
break;
case 'user':
include_once CONTENT_PATH.'settings/user.php';
break;
case 'cache':
include_once CONTENT_PATH.'settings/cache.php';
break;
default:
$tpl->draw('settings');
}
?>

View File

@@ -0,0 +1,45 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'cache/cache.function.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Cache'));
if (isset($_GET['clear']) && $_GET['clear'] != '')
{
$clearCache = new Cache;
$clearCache->setName($_GET['clear']);
if ($clearCache->clear() === true)
$tpl->msg('success', _t('Cache geleert'), _t('Der Cache wurder erfolgreich geleert.'));
else
$tpl->msg('error', _t('Fehler'), _t('Leider konnte der Cache nicht geleert werden!'));
if (isset($_GET['redirect']) && $_GET['redirect'] != '')
$tpl->redirect('?'.urldecode($_GET['redirect']));
}
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
setConfig('cache:activation.cache', (isset($_POST['activation']) && $_POST['activation'] == 'checked') ? 'true' : 'false');
$list = getCacheList();
foreach ($list as $name => $info)
{
if (isset($_POST['text-'.$name]) && $_POST['text-'.$name] != '' && $_POST['text-'.$name] >= 1 && $_POST['text-'.$name] <= 9999)
setConfig('cache:lifetime.'.$name, $_POST['text-'.$name]);
else
$tpl->msg('error', _t('Fehler'), _t('Bitte vergebe f&uuml;r die Speicherzeit eine g&uuml;ltige Zahl zwischen 1 und 9999.'), true, 10);
setConfig('cache:activation.'.$name, (isset($_POST['cb-'.$name]) && $_POST['cb-'.$name] == 'checked') ? 'true' : 'false');
}
if ($tpl->msgExists(10) === false)
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
$tpl->assign('cache-activation', (getConfig('cache:activation.cache', 'false') == 'true') ? true : false);
$tpl->assign('cache-files', getCacheList(true));
$tpl->draw('settings/cache');
?>

View File

@@ -0,0 +1,142 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('Benachrichtigung'));
$cron = new Cron;
$cron->setName('notification');
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['token']) && ($token = trim($_POST['token'])) != '' && ((isset($_POST['event-pi-control-version']) && $_POST['event-pi-control-version'] == 'checked') || (isset($_POST['event-cpu-temperature'], $_POST['event-cpu-temperature-maximum']) && $_POST['event-cpu-temperature'] == 'checked') || (isset($_POST['event-memory-used'], $_POST['event-memory-used-text']) && $_POST['event-memory-used'] == 'checked')))
{
$cpu_temperature_maximum = trim($_POST['event-cpu-temperature-maximum']);
$memory_used_text = trim($_POST['event-memory-used-text']);
if (strlen($token) >= 32 && strlen($token) <= 46)
setConfig('main:notificationPB.token', $token);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist der angegebene Zugangstoken ung&uuml;ltig!'), true, 10);
if ($cpu_temperature_maximum != '' && $cpu_temperature_maximum >= 40 && $cpu_temperature_maximum <= 90)
setConfig('main:notificationPB.cpuTemperatureMaximum', $cpu_temperature_maximum);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist die angegebene Temperatur ung&uuml;ltig!'), true, 11);
if ($memory_used_text != '' && $memory_used_text >= 1 && $memory_used_text <= 100)
setConfig('main:notificationPB.memoryUsedLimit', $memory_used_text);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist der angegebene Prozentsatz ung&uuml;ltig!'), true, 12);
if ($tpl->msgExists(10) === false)
setConfig('main:notificationPB.picontrolVersionEnabled', (isset($_POST['event-pi-control-version'])) ? 'true' : 'false');
if ($tpl->msgExists(11) === false)
setConfig('main:notificationPB.cpuTemperatureEnabled', (isset($_POST['event-cpu-temperature'])) ? 'true' : 'false');
if ($tpl->msgExists(12) === false)
setConfig('main:notificationPB.memoryUsedEnabled', (isset($_POST['event-memory-used'])) ? 'true' : 'false');
if (isset($_POST['activation']) && $_POST['activation'] == 'checked' && (getConfig('main:notificationPB.picontrolVersionEnabled', false) == true || getConfig('main:notificationPB.cpuTemperatureEnabled', false) == true || getConfig('main:notificationPB.memoryUsedEnabled', false) == true))
{
if ($cron->isExists() === false)
{
$cron->setInterval(1);
$cron->setSource(TEMPLATES2_PATH.'notification.tmp.php');
if ($cron->save() === true)
{
$tpl->msg('success', _t('Benachrichtigung aktiviert'), _t('Die Benachrichtigung wurde aktiviert.'));
setConfig('main:notificationPB.enabled', 'true');
}
else
$tpl->msg('error', _t('Fehler'), _t('Konnte die Benachrichtigung nicht aktivieren!'));
}
}
else
{
if ($cron->isExists() === true)
{
$cron->getInterval();
if ($cron->delete() === true)
{
$tpl->msg('success', _t('Benachrichtigung deaktiviert'), _t('Die Benachrichtigung wurde deaktiviert.'));
setConfig('main:notificationPB.enabled', 'false');
}
else
$tpl->msg('error', _t('Fehler'), _t('Konnte die Benachrichtigung nicht deaktivieren!'));
}
}
if ($tpl->msgExists(10) === false && $tpl->msgExists(11) === false && $tpl->msgExists(12) === false)
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'));
}
elseif (isset($_POST['token']) && ($token = trim($_POST['token'])) == '')
{
setConfig('main:notificationPB.token', '');
$tpl->msg('success', _t('Token entfernt'), _t('Der Token wurde erfolgreich entfernt.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte f&uuml;lle alle n&ouml;tigen Felder aus und w&auml;hle mindestens eine der Aktionen!'));
}
$token = getConfig('main:notificationPB.token', '');
if ($token != '')
{
if (isset($_POST['submit-test-notification']) && $_POST['submit-test-notification'] != '')
{
$curl = new cURL('https://api.pushbullet.com/v2/pushes', HTTP_POST);
$curl->addHeader(array('Authorization: Bearer '.$token, 'Content-Type: application/json'));
$curl->setParameterRaw(json_encode(array('type' => 'note', 'title' => 'Pi Control', 'body' => _t('Dein Pi Control "%s" hat dir eine Testbenachrichtigung gesendet.', getConfig('main:main.label', 'Raspberry Pi')))));
$curl->execute();
if ($curl->getStatusCode() != 200)
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zu Pushbullet ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $curl->getStatusCode()));
}
$curl = new cURL('https://api.pushbullet.com/v2/users/me');
$curl->addHeader(array('Authorization: Bearer '.$token));
$curl->execute();
if (in_array($curl->getStatusCode(), array(200, 400, 401, 403, 404, 429)))
{
if ($curl->getResult($dataMe) == JSON_ERROR_NONE)
{
if (isset($dataMe['error']))
$tpl->msg('error', 'Pushbullet', _t('Pushbullet meldet einen Fehler mit einer Anfrage: %s', $dataMe['error']['message']));
else
{
$curl = new cURL('https://api.pushbullet.com/v2/devices');
$curl->addHeader(array('Authorization: Bearer '.$token));
$curl->execute();
if (in_array($curl->getStatusCode(), array(200, 400, 401, 403, 404, 429)))
{
if ($curl->getResult($dataDevices) == JSON_ERROR_NONE)
{
if (isset($dataDevices['error']))
$tpl->msg('error', 'Pushbullet', _t('Pushbullet meldet einen Fehler mit einer Anfrage: %s', $dataDevices['error']['message']));
}
}
else
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zu Pushbullet ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $curl->getStatusCode()));
}
}
}
else
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zu Pushbullet ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $curl->getStatusCode()));
}
$tpl->assign('activation', (getConfig('main:notificationPB.enabled', 'false') == 'true') ? true : false);
$tpl->assign('token', $token);
$tpl->assign('me', (isset($dataMe)) ? $dataMe : '');
$tpl->assign('devices', (isset($dataDevices)) ? $dataDevices : '');
$tpl->assign('pi-control-enabled', (getConfig('main:notificationPB.picontrolVersionEnabled', 'false') == 'true') ? true : false);
$tpl->assign('cpu-temperature-enabled', (getConfig('main:notificationPB.cpuTemperatureEnabled', 'false') == 'true') ? true : false);
$tpl->assign('cpu-temperature-maximum', getConfig('main:notificationPB.cpuTemperatureMaximum', 65));
$tpl->assign('memory-used-enabled', (getConfig('main:notificationPB.memoryUsedEnabled', 'false') == 'true') ? true : false);
$tpl->assign('memory-used-limit', getConfig('main:notificationPB.memoryUsedLimit', 80));
$tpl->draw('settings/notification');
?>

View File

@@ -0,0 +1,107 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('Einstellungen zur &Uuml;bersicht'));
if (isset($_POST['submit-main']) && $_POST['submit-main'] != '')
{
if (isset($_POST['overview-interval']) && is_numeric($_POST['overview-interval']) && $_POST['overview-interval'] >= 1 && $_POST['overview-interval'] <= 9999)
{
setConfig('main:overview.interval', $_POST['overview-interval']);
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte vergebe f&uuml;r den Intervall einen Wert zwischen 1 und 9999.'), true, 10);
if (isset($_POST['show-devices']) && $_POST['show-devices'] == 'checked')
setConfig('main:overview.showDevices', 'true');
else
setConfig('main:overview.showDevices', 'false');
}
if (isset($_POST['submit-weather']) && $_POST['submit-weather'] != '')
{
if (isset($_POST['weather-service'], $_POST['weather-location-country'], $_POST['weather-location-type']) &&
in_array($_POST['weather-service'], array('openweathermap', 'yahoo', 'wunderground', 'darksky', 'yr')) &&
in_array($_POST['weather-location-country'], array('germany', 'austria', 'swiss', 'uk')) &&
((isset($_POST['weather-service-token']) && in_array($_POST['weather-service'], array('openweathermap', 'wunderground', 'darksky')) && ($pWeatherServiceToken = trim($_POST['weather-service-token'])) != '') || in_array($_POST['weather-service'], array('yahoo', 'yr'))) &&
(($_POST['weather-location-type'] == 'postcode' && isset($_POST['weather-location-postcode-text']) && $_POST['weather-location-postcode-text'] != '') || ($_POST['weather-location-type'] == 'city' && isset($_POST['weather-location-city-text']) && ($cityText = trim($_POST['weather-location-city-text'])) != '') || ($_POST['weather-location-type'] == 'coordinates' && isset($_POST['weather-location-coordinates-latitude-text'], $_POST['weather-location-coordinates-longitude-text']) && ($coordinatesLatitudeText = trim($_POST['weather-location-coordinates-latitude-text'])) != '' && ($coordinatesLongitudeText = trim($_POST['weather-location-coordinates-longitude-text'])) != '')))
{
setConfig('main:weather.service', $_POST['weather-service']);
setConfig('main:weather.country', $_POST['weather-location-country']);
setConfig('main:weather.type', $_POST['weather-location-type']);
if (isset($pWeatherServiceToken) && ((strlen($pWeatherServiceToken) == 32 && in_array($_POST['weather-service'], array('openweathermap', 'darksky'))) || (strlen($pWeatherServiceToken) == 16 && in_array($_POST['weather-service'], array('wunderground')))))
setConfig('main:weather.serviceToken', $pWeatherServiceToken);
elseif (in_array($_POST['weather-service'], array('openweathermap', 'wunderground', 'darksky')))
$tpl->msg('error', _t('Fehler'), _t('Leider ist der angegebene API-Schl&uuml;ssel zu kurz!'), true, 10);
else
setConfig('main:weather.serviceToken', '');
if ($_POST['weather-location-type'] == 'postcode')
{
if (in_array($_POST['weather-location-country'], array('germany', 'austria', 'swiss')))
{
if (in_array(strlen($_POST['weather-location-postcode-text']), array(4, 5)) && $_POST['weather-location-postcode-text'] >= 1 && $_POST['weather-location-postcode-text'] <= 99999)
setConfig('main:weather.postcode', $_POST['weather-location-postcode-text']);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist die angegebene Postleitzahl ung&uuml;ltig!'), true, 10);
}
elseif (in_array($_POST['weather-location-country'], array('uk')))
{
if (in_array(strlen($_POST['weather-location-postcode-text']), array(5, 6, 7, 8)) && preg_match('/^([A-Z]{1,2}[0-9][A-Z]?[0-9]?)( )?([0-9]{1}[A-Z]{2})$/', $_POST['weather-location-postcode-text']))
setConfig('main:weather.postcode', $_POST['weather-location-postcode-text']);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist die angegebene Postleitzahl ung&uuml;ltig!'), true, 10);
}
}
elseif ($_POST['weather-location-type'] == 'city')
{
if (strlen($cityText) >= 3 && preg_match('/^[A-Za-zÄÖÜäöü \(\)\.\-\/]+$/', $cityText))
setConfig('main:weather.city', $cityText);
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist der angegebene Stadtname ung&uuml;ltig!'), true, 10);
}
elseif ($_POST['weather-location-type'] == 'coordinates')
{
if (preg_match('/^-?[0-9]{1,2}([\.|,][0-9]{1,6})?$/', $coordinatesLatitudeText) && preg_match('/^-?[0-9]{1,2}([\.|,][0-9]{1,6})?$/', $coordinatesLongitudeText))
{
setConfig('main:weather.latitude', str_replace(',', '.', $coordinatesLatitudeText));
setConfig('main:weather.longitude', str_replace(',', '.', $coordinatesLongitudeText));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider sind die angegebenen Koordinaten ung&uuml;ltig!'), true, 10);
}
if ($tpl->msgExists(10) === false)
{
setConfig('main:weather.activation', (isset($_POST['weather-activation']) && $_POST['weather-activation'] == 'checked') ? 'true' : 'false');
if ($_POST['weather-service'] == 'yr')
setConfig('main:weather.yrCache', '');
if ($_POST['weather-service'] == 'wunderground')
setConfig('main:weather.wundergroundCache', '');
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'));
}
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte f&uuml;lle alle ben&ouml;tigten Felder aus!'));
}
$tpl->assign('main-overview-interval', getConfig('main:overview.interval', '30'));
$tpl->assign('main-show-devices', getConfig('main:overview.showDevices', 'true'));
$tpl->assign('weather-activation', (getConfig('main:weather.activation', 'false') == 'true') ? true : false);
$tpl->assign('weather-service', getConfig('main:weather.service', 'openweathermap'));
$tpl->assign('weather-service-token', getConfig('main:weather.serviceToken', ''));
$tpl->assign('weather-country', getConfig('main:weather.country', 'germany'));
$tpl->assign('weather-type', getConfig('main:weather.type', 'postcode'));
$tpl->assign('weather-city', getConfig('main:weather.city', ''));
$tpl->assign('weather-postcode', getConfig('main:weather.postcode', ''));
$tpl->assign('weather-coordinates-latitude', getConfig('main:weather.latitude', ''));
$tpl->assign('weather-coordinates-longitude', getConfig('main:weather.longitude', ''));
$tpl->assign('weather-info', getWeather());
$tpl->draw('settings/overview');
?>

View File

@@ -0,0 +1,251 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'pi-control/pi-control.function.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Einstellungen zum Pi Control'));
if (isset($_GET['msg']) && $_GET['msg'] == 'theme')
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.<br /><br />Tipp: Um die Theme-&Auml;nderung wirksam zu machen, leere deinen Browser-Cache mit Strg + F5 (Windows) / &#8997;&#8984; + E (OS X / Safari) / &#8679;&#8984; + R (OS X / Chrome)'));
elseif (isset($_GET['msg']) && $_GET['msg'] == 'main')
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'));
if (isset($_POST['submit-main']) && $_POST['submit-main'] != '')
{
$redirect = 0;
if (isset($_POST['theme-color']) && in_array($_POST['theme-color'], array('red', 'pink', 'purple', 'deepPurple', 'indigo', 'blue', 'lightBlue', 'cyan', 'teal', 'green', 'lightGreen', 'lime', 'yellow', 'amber', 'orange', 'deepOrange', 'brown', 'grey', 'blueGrey')) === true)
{
if (getConfig('main:theme.color', 'blue') != $_POST['theme-color'])
$redirect += 1;
setConfig('main:theme.color', $_POST['theme-color']);
setConfig('main:theme.colorChanged', time());
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
if (isset($_POST['pi-control-language']) && in_array($_POST['pi-control-language'], array('de', 'en')) === true)
{
if (getConfig('init:language', 'de') != $_POST['pi-control-language'])
$redirect += 2;
setConfig('init:language', $_POST['pi-control-language']);
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
if (isset($_POST['pi-control-header-info']) && in_array($_POST['pi-control-header-info'], array('disable', 'label', 'label-ip', 'label-hostname', 'ip', 'hostname')) === true)
{
setConfig('main:headerInfo.type', $_POST['pi-control-header-info']);
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
if (isset($_POST['external-access']) && $_POST['external-access'] == 'checked')
{
setConfig('main:access.external', 'true');
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
else
{
setConfig('main:access.external', 'false');
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
if (isset($_POST['pi-control-label']) && ($pLabel = trim($_POST['pi-control-label'])) != '')
{
if (preg_match('/^[a-z][a-z0-9_\-\+\/\.\(\)\[\] ]{2,32}$/i', $pLabel) === 1)
{
setConfig('main:main.label', $pLabel);
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'), true, 10);
}
else
{
$redirect = 0;
$tpl->msg('error', _t('Fehler'), _t('Leider ist die Bezeichnung ung&uuml;ltig! Die Bezeichnung muss aus 2 bis 32 Zeichen bestehen. Das erste Zeichen muss ein Buchstabe sein und es sind nur folgende Zeichen erlaubt: A-Z 0-9 _ - + / . ( ) [ ] "Leerzeichen"'), true, 10);
}
}
else
{
$redirect = 0;
$tpl->msg('error', _t('Fehler'), _t('Bitte vergebe f&uuml;r dein Pi Control eine Bezeichnung!'), true, 10);
}
if ($redirect == 1 || $redirect == 3)
header('Location: ?s=settings&do=pi-control&msg=theme');
elseif ($redirect == 2)
header('Location: ?s=settings&do=pi-control&msg=main');
}
elseif (isset($_POST['submit-temperature']) && $_POST['submit-temperature'] != '')
{
$cron = new Cron;
$cron->setName('coretemp_monitoring');
if (isset($_POST['temperature-maximum']) && $_POST['temperature-maximum'] >= 40 && $_POST['temperature-maximum'] <= 90 && ((isset($_POST['temperature-action-email']) && $_POST['temperature-action-email'] == 'checked') || (isset($_POST['temperature-action-shell']) && $_POST['temperature-action-shell'] == 'checked')))
{
setConfig('main:monitoringCpuTemp.maximum', $_POST['temperature-maximum']);
setConfig('main:monitoringCpuTemp.emailEnabled', isset($_POST['temperature-action-email']) ? 'true' : 'false');
setConfig('main:monitoringCpuTemp.shellEnabled', isset($_POST['temperature-action-shell']) ? 'true' : 'false');
$pActionEmail = trim($_POST['temperature-action-email-text']);
$pActionShell = trim($_POST['temperature-action-shell-text']);
if (isset($_POST['temperature-action-email']))
{
if (!filter_var($pActionEmail, FILTER_VALIDATE_EMAIL) || !strlen($pActionEmail) >= 6)
$tpl->msg('error', _t('Fehler'), _t('Bitte gebe eine g&uuml;ltige E-Mailadresse an.'), true, 10);
}
if ($tpl->msgExists(10) === false)
setConfig('main:monitoringCpuTemp.email', $pActionEmail);
if (isset($_POST['temperature-action-shell']))
{
if ($pActionShell == '')
$tpl->msg('error', _t('Fehler'), _t('Bitte gebe einen g&uuml;ltigen Shell Befehl an.'), true, 11);
}
if ($tpl->msgExists(11) === false)
setConfig('main:monitoringCpuTemp.shell', base64_encode($pActionShell));
if (getConfig('main:monitoringCpuTemp.id', '') == '')
{
$uniqid = generateUniqId();
setConfig('main:monitoringCpuTemp.id', $uniqid);
}
if (isset($_POST['temperature-action-email']) && $tpl->msgExists(10) === false)
checkTemperatureMonitoringEmailStatus();
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte w&auml;hle mindestens eine Aktion.'), true, 10);
if (isset($_POST['temperature-activation']) && $_POST['temperature-activation'] == 'checked')
{
if ($cron->isExists() === false)
{
$cron->setInterval(1);
$cron->setSource(TEMPLATES2_PATH.'coretemp_monitoring.tmp.php');
if ($cron->save() === true)
$tpl->msg('success', _t('Temperatur&uuml;berwachung aktiviert'), _t('Die Temperatur&uuml;berwachung wurde aktiviert.'));
else
$tpl->msg('error', _t('Fehler'), _t('Konnte die Temperatur&uuml;berwachung nicht aktivieren!'));
}
}
else
{
if ($cron->isExists() === true)
{
//$cron->readFile();
$cron->setInterval($cron->getInterval());
if ($cron->delete() === true)
$tpl->msg('success', _t('Temperatur&uuml;berwachung deaktiviert'), _t('Die Temperatur&uuml;berwachung wurde deaktiviert.'));
else
$tpl->msg('error', _t('Fehler'), _t('Konnte die Temperatur&uuml;berwachung nicht deaktivieren!'));
}
}
if ($tpl->msgExists(10) === false && $tpl->msgExists(11) === false)
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'));
}
if (isset($_POST['submit-temperature-confirmation']) && $_POST['submit-temperature-confirmation'] != '')
{
$id = getConfig('main:monitoringCpuTemp.id', '');
$code = getConfig('main:monitoringCpuTemp.code', '');
$email = getConfig('main:monitoringCpuTemp.email', '');
$label = getConfig('main:main.label', '');
if ($id == '' || $email == '' || $label == '')
$tpl->msg('error', _t('Fehler'), _t('Leider ist ein Fehler aufgetreten. Bitte wiederhole die Vergabe der Bezeichnung und der E-Mailadresse.'));
else
{
$fields = array('type' => 'add', 'id' => $id, 'email' => $email, 'label' => $label, 'referer' => $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], 'lang' => $globalLanguage);
$data = NULL;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $config['url']['temperatureMonitoring']);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl, CURLOPT_POST, count($fields));
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($fields));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
do
{
if (($data = curl_exec($curl)) === false)
{
$info = curl_getinfo($curl);
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d (%s)', $info['http_code'], curl_error($curl)));
break;
}
else
{
$info = curl_getinfo($curl);
if ($info['http_code'] == 404)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Leider konnte keine Verbindung zum Server hergestellt werden, da dieser momentan vermutlich nicht erreichbar ist. Fehlercode: %d', $info['http_code']));
break;
}
elseif ($info['http_code'] != 200)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $info['http_code']));
break;
}
if ($data == '')
{
$tpl->msg('error', _t('Serverfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine leere Antwort.'));
break;
}
// Verarbeite Datenstring
$json = json_decode($data, true);
if (json_last_error() != JSON_ERROR_NONE && (!isset($json['existing'], $json['sent']) || !isset($json['type'], $json['title'], $json['msg'], $json['skip'])))
{
$tpl->msg('error', _t('Verarbeitungsfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine fehlerhafte Antwort.'));
break;
}
if (isset($json['type'], $json['title'], $json['msg'], $json['skip']))
{
$tpl->msg($json['type'], $json['title'], $json['msg'], true, 10);
if ($json['skip'] === true)
break;
}
// Antwort in Ordnung
$tpl->msg('success', _t('E-Mail gesendet'), _t('Eine E-Mail mit einem Best&auml;tigungslink wurde an <strong>%s</strong> versandt. In der E-Mail ist ein Link, der angeklickt bzw. ge&ouml;ffnet werden muss. Sollte die E-Mail nach sp&auml;testens 10 Minuten nicht angekommen sein, schaue in deinem Spam-Ordner nach. Ansonsten wiederhole den Vorgang.', $email));
}
}
while (false);
curl_close($curl);
}
}
if (isset($_GET['mail_check']) && $_GET['mail_check'] == '')
{
checkTemperatureMonitoringEmailCode();
}
$cron = new Cron;
$cron->setName('coretemp_monitoring');
$tpl->assign('main-theme-color', getConfig('main:theme.color', 'blue'));
$tpl->assign('main-pi-control-label', getConfig('main:main.label', 'Raspberry Pi'));
$tpl->assign('main-pi-control-language', getConfig('init:language', 'de'));
$tpl->assign('main-pi-control-header-info', getConfig('main:headerInfo.type', 'disable'));
$tpl->assign('main-external-access', getConfig('main:access.external', 'false'));
$tpl->assign('temperature-activation', $cron->isExists());
$tpl->assign('temperature-maximum', getConfig('main:monitoringCpuTemp.maximum', 60));
$tpl->assign('temperature-action-email', (getConfig('main:monitoringCpuTemp.emailEnabled', 'false') == 'true') ? true : false);
$tpl->assign('temperature-action-email-text', getConfig('main:monitoringCpuTemp.email', ''));
$tpl->assign('temperature-action-email-status', (getConfig('main:monitoringCpuTemp.code', '') == '') ? 0 : 1);
$tpl->assign('temperature-action-shell', (getConfig('main:monitoringCpuTemp.shellEnabled', 'false') == 'true') ? true : false);
$tpl->assign('temperature-action-shell-text', htmlentities(base64_decode(getConfig('main:monitoringCpuTemp.shell', ''))));
$tpl->assign('temperature-last-execution', (getConfig('cron:execution.monitoringCpuTemp', 0)-time()+3600 > 0) ? getDateFormat(getConfig('cron:execution.monitoringCpuTemp', 0)-time()+3600) : '');
$tpl->assign('whoami', exec('whoami'));
$tpl->assign('configHelp', $config['url']['help'].'?s=view&amp;i=8'.getURLLangParam());
$tpl->draw('settings/pi-control');
?>

View File

@@ -0,0 +1,24 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('Einstellungen zu Plugins'));
$showList = true;
if (isset($_GET['status']) && $_GET['status'] != '' && ($gPlugin = pluginConfig($_GET['status'])) != false)
include_once 'plugins_status.php';
elseif (isset($_GET['delete']) && $_GET['delete'] != '' && ($gPlugin = pluginConfig($_GET['delete'])) != false)
{
$showList = false;
include_once 'plugins_delete.php';
}
if ($showList == true)
{
$plugins = pluginList();
$tpl->assign('plugins', $plugins);
$tpl->draw('settings/plugins');
}
?>

View File

@@ -0,0 +1,23 @@
<?php
if (!defined('PICONTROL')) exit();
$plugin = $gPlugin;
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (deletePlugin($plugin['id']) == true)
{
$tpl->msg('success', _t('Plugin gel&ouml;scht'), _t('Das Plugin "%s" wurde erfolgreich gel&ouml;scht.', _t($plugin['name'])));
$showList = true;
}
else
$tpl->msg('error', _t('Fehler'), _t('Das Plugin "%s" konnte nicht gel&ouml;scht werden.', _t($plugin['name'])));
}
if ($showList == false)
{
$tpl->assign('plugin', $plugin);
$tpl->draw('settings/plugin_delete');
}
?>

View File

@@ -0,0 +1,20 @@
<?php
if (!defined('PICONTROL')) exit();
$plugin = $gPlugin;
if ($plugin['disabled'] == true)
{
if (setPluginStatus($plugin['id'], true) == true)
$tpl->msg('success', _t('Plugin aktiviert'), _t('Das Plugin "%s" wurde erfolgreich aktiviert.', $plugin['name']));
else
$tpl->msg('error', _t('Fehler'), _t('Das Plugin "%s" konnte nicht aktiviert werden.', $plugin['name']));
}
elseif ($plugin['disabled'] == false)
{
if (setPluginStatus($plugin['id'], false) == true)
$tpl->msg('success', _t('Plugin deaktiviert'), _t('Das Plugin "%s" wurde erfolgreich deaktiviert.', $plugin['name']));
else
$tpl->msg('error', _t('Fehler'), _t('Das Plugin "%s" konnte nicht deaktiviert werden.', $plugin['name']));
}
?>

View File

@@ -0,0 +1,73 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Einstellungen zur Statistik'));
$statistics = array();
$statisticIDs = array();
$controller = new StatisticController();
$controller->loadStatistics('statistic/');
foreach ($controller->getStatistics() as $statistic)
{
$builder = new StatisticBuilder();
$builder->loadFromFile($statistic);
$array = $builder->getArray();
$statistics[$builder->getId()] = array('array' => $array);
$statisticIDs[] = $array['id'];
}
if (!isset($_GET['reset']) && (!isset($_GET['download'])))
{
$hiddenStatistics = unserialize(htmlspecialchars_decode(getConfig('main:statistic.hidden', 'a:0:{}')));
if (isset($_POST['submit']))
{
$hiddenStatistics = array_values(array_diff($statisticIDs, (isset($_POST['check'])) ? $_POST['check'] : array()));
if (setConfig('main:statistic.hidden', htmlspecialchars(serialize($hiddenStatistics))) !== false)
$tpl->msg('success', _t('Einstellungen gespeichert'), _t('Die Einstellungen wurden erfolgreich gespeichert.'));
else
$tpl->msg('error', _t('Fehler'), _t('Konnte Wert nicht in Konfigurationsdatei speichern!'));
}
foreach ($statistics as &$statistic)
{
$array = $statistic['array'];
$statistic += array('visible' => (!in_array($array['id'], $hiddenStatistics)) ? true : false);
}
$tpl->assign('statistics', $statistics);
$tpl->draw('settings/statistic');
}
elseif (isset($_GET['reset']))
{
if (!isset($statistics[$_GET['reset']]))
$tpl->msg('error', _t('Fehler'), _t('Der Verlauf konnte nicht gefunden werden: %s', $_GET['reset']));
if (isset($_GET['confirm']) && $_GET['confirm'] == '')
{
if (isset($statistics[$_GET['reset']]))
{
if (($logFile = fopen(LOG_PATH.$statistics[$_GET['reset']]['array']['raw'].'.csv', 'w')) !== false)
{
$tpl->msg('success', _t('Verlauf zur&uuml;ckgesetzt'), _t('Verlauf wurde erfolgreich zur&uuml;ckgesetzt.'));
fclose($logFile);
}
else
$tpl->msg('error', _t('Fehler'), _t('Verlauf konnte nicht zur&uuml;ckgesetzt werden.'));
}
}
$tpl->assign('log', $_GET['reset']);
$tpl->assign('label', $statistics[$_GET['reset']]['array']['title']);
$tpl->draw('settings/statistic_reset');
}
elseif (isset($_GET['download']))
$tpl->redirect('api/v1/statistic_download.php?id='.$_GET['download']);
?>

View File

@@ -0,0 +1,55 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'troubleshooting/troubleshooting.function.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Problembehandlung'));
// Dateien und Ordner
$filesFolders = fileFolderPermission();
$filesFoldersError = false;
foreach ($filesFolders as $file => $info)
{
if ($info['error'] === true)
{
$filesFoldersError = true;
break;
}
}
// Cron
$cronEntry = '* * * * * '.exec('whoami').' php -f "'.CRON_PATH.'init.php" >/dev/null 2>&1 # By Pi Control';
exec('cat /etc/crontab', $crontab);
$cronMatch = preg_match('/^\*\s\*\s\*\s\*\s\*\s'.preg_quote(exec('whoami')).'\sphp \-f "'.preg_quote(CRON_PATH, '/').'init\.php"( )?(# By Pi Control)?/im', implode(PHP_EOL, $crontab));
$lastExecutionLog = array(
(file_exists(LOG_PATH.'statistic/coretemp.csv')) ? filemtime(LOG_PATH.'statistic/coretemp.csv') : 1,
(file_exists(LOG_PATH.'statistic/cpuload.csv')) ? filemtime(LOG_PATH.'statistic/cpuload.csv') : 1,
(file_exists(LOG_PATH.'statistic/ram.csv')) ? filemtime(LOG_PATH.'statistic/ram.csv') : 1,
(file_exists(LOG_PATH.'statistic/network_eth0.csv')) ? filemtime(LOG_PATH.'statistic/network_eth0.csv') : 1
);
rsort($lastExecutionLog);
$tpl->assign('filesFolders', $filesFolders);
$tpl->assign('filesFoldersError', $filesFoldersError);
$tpl->assign('configHelpFilesFolders', $config['url']['help'].'?s=view&amp;i=1'.getURLLangParam());
$tpl->assign('configHelpCron', $config['url']['help'].'?s=view&amp;i=10'.getURLLangParam());
$tpl->assign('cronEntry', $cronEntry);
$tpl->assign('cronMatch', $cronMatch);
$tpl->assign('cronPHPCLI', ($cronPHPCLI = (trim(exec('dpkg -s php5-cli | grep Status: ')) != '' || trim(exec('dpkg -s php7.0-cli | grep Status: ')) != '') ? true : false));
$tpl->assign('cronLastExecution', formatTime(getConfig('cron:execution.cron', 0)));
$tpl->assign('cronLastExecutionBool', ($cronLastExecutionBool = (getConfig('cron:execution.cron', 0) > time()-150) ? true : false));
$tpl->assign('cronLastExecutionLog', formatTime($lastExecutionLog[0]));
$tpl->assign('cronLastExecutionLogBool', ($cronLastExecutionLogBool = ($lastExecutionLog[0] > time()-330) ? true : false));
$tpl->assign('cronPermission', $filesFolders['resources/cron/init.php']['permission']);
$tpl->assign('cronPermissionBool',($cronPermissionBool = $filesFolders['resources/cron/init.php']['permissionBool']));
$tpl->assign('cronUserGroup', $filesFolders['resources/cron/init.php']['userGroup']);
$tpl->assign('cronUserGroupBool', ($cronUserGroupBool = $filesFolders['resources/cron/init.php']['userGroupBool']));
$tpl->assign('cronCharacterEncoding', trim(exec('file /etc/crontab -b')));
$tpl->assign('cronCharacterEncodingBool', ($cronCharacterEncodingBool = trim(exec('file /etc/crontab -b') == 'ASCII text') ? true : false));
$tpl->assign('cronError', ($cronMatch !== 1) ? 1 : (($cronPHPCLI !== true || $cronLastExecutionBool !== true || $cronLastExecutionLogBool !== true || $cronPermissionBool !== true || $cronUserGroupBool !== true || $cronCharacterEncodingBool !== true ) ? 2 : 0));
$tpl->draw('settings/troubleshooting');
?>

View File

@@ -0,0 +1,52 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'troubleshooting/troubleshooting.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'update/update.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Aktualisierung'));
$updateController = new UpdateController();
$updateController->setStage(getConfig('main:update.stage', 'release'));
$updateStatus = $updateController->fetchData();
if ($updateStatus === true)
$updateStatus = $updateController->getNextUpdate();
if (isset($_POST['update']) && $_POST['update'] != '')
$tpl->redirect('?i=update');
if (isset($_GET['complete']))
{
checkUpdate();
$tpl->msg('success', _t('Pi Control auf Version %s aktualisiert', $config['version']['version']), _t('Dein Pi Control wurde erfolgreich aktualisiert und ist nun einsatzbereit. Sollten Probleme auftreten, klicke einfach unten auf "Feedback" und schreibe mir. Viel Spaß!<br /><br />Tipp: Leere deinen Browser-Cache mit Strg + F5 (Windows) / &#8997;&#8984; + E (OS X / Safari) / &#8679;&#8984; + R (OS X / Chrome)'));
}
if (isset($_POST['beta']) && $_POST['beta'] != '')
{
$newStage = getConfig('main:update.stage', 'release') == 'release' ? 'beta' : 'release';
if ($newStage == 'release')
$tpl->msg('success', _t('Erfolgreich zur&uuml;ckgetreten'), _t('Du bist erfolgreich von Pi Control Beta zur&uuml;ckgetreten. Ab sofort erh&auml;ltst du ausschließlich stabile Aktualisierungen.'));
else
$tpl->msg('success', _t('Erfolgreich teilgenommen'), _t('Vielen Dank f&uuml;r deine Teilnahme an Pi Control Beta. Ab sofort erh&auml;ltst du Beta-Aktualisierungen.'));
setConfig('main:update.stage', $newStage);
$updateController->setStage($newStage);
$updateStatus = $updateController->getNextUpdate();
}
$filesFolders = fileFolderPermission();
$fileError = (array_search(true, array_column($filesFolders, 'error'))) ? true : false;
if ($fileError === true)
$tpl->msg('error', _t('Aktualisierung blockiert'), _t('Es wurde mindestens ein Fehler mit den Dateien oder Ordnern des Pi Control festgestellt! Bitte behebe zun&auml;chst das Problem mit Hilfe der <a href="%s">Problembehandlung</a>, ansonsten ist eine Aktualisierung nicht m&ouml;glich.', '?s=settings&amp;do=troubleshooting'), false);
$tpl->assign('updateError', $fileError);
$tpl->assign('updateStatus', $updateStatus);
$tpl->assign('updateStage', getConfig('main:update.stage', 'release'));
$tpl->assign('configVersion', $config['version']['version']);
$tpl->assign('configMailUrl', $config['url']['updateNotification'].getURLLangParam());
$tpl->draw('settings/update');
?>

View File

@@ -0,0 +1,163 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'user/user.function.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Einstellungen zum Benutzer'));
$showOverview = true;
if (isset($_GET['add']) && $_GET['add'] == '')
{
if (isset($_POST['submit']) && $_POST['submit'] != '')
{
if (isset($_POST['username'], $_POST['password'], $_POST['password2']) && ($pUsername = trim($_POST['username'])) != '' && ($pPassword = $_POST['password']) != '' && ($pPassword2 = $_POST['password2']) != '')
{
if (preg_match('/^[a-z][a-z0-9\-_]{1,31}$/i', $pUsername) === 1)
{
$lowerUsername = strtolower($pUsername);
if (getConfig('user:user_'.$lowerUsername.'.username', '') == '')
{
if (preg_match('/^[a-z0-9_\-\+\*\/\#.\!\?@\(\)\[\]\{\}\<\>\=\$%&,\|\:~§;]{4,64}$/i', $pPassword) === 1)
{
if ($pPassword === $pPassword2)
{
setConfig('user:user_'.$lowerUsername.'.username', $pUsername);
setConfig('user:user_'.$lowerUsername.'.created', time());
setConfig('user:user_'.$lowerUsername.'.password', password_hash($pPassword, PASSWORD_BCRYPT));
setConfig('user:user_'.$lowerUsername.'.last_login', 0);
$tpl->msg('success', _t('Benutzer angelegt'), _t('Der Benutzer "%s" wurder erfolgreich angelegt.', $pUsername));
}
else
$tpl->msg('error', _t('Fehler'), _t('Die angegebenen Passw&ouml;rter stimmen nicht &uuml;berein!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist das Passwort ung&uuml;ltig! Das Passwort muss aus 4 bis 64 Zeichen bestehen und darf nur folgende Zeichen beinhalten: A-Z 0-9 - _ + * / # . ! ? @ ( ) [ ] { } < > = $ %% & , | : ~ § ;'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist der Benutzername bereits vergeben! Bitte w&auml;hle einen anderen.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist der Benutzername ung&uuml;ltig! Der Benutzername muss aus 2 bis 32 Zeichen bestehen. Das erste Zeichen muss ein Buchstabe sein und es sind nur folgende Zeichen erlaubt: A-Z 0-9 - _'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte alle Felder ausf&uuml;llen.'));
}
$showOverview = false;
$tpl->draw('settings/user_add');
}
elseif (isset($_GET['delete']) && $_GET['delete'] != '')
{
$lowerUsername = $_GET['delete'];
$username = getConfig('user:user_'.$lowerUsername.'.username', '');
if ($username != '')
{
$showDelete = true;
if (isset($_POST['submit']))
{
if (isset($_POST['password']) && ($pPassword = $_POST['password']) != '')
{
$password = getConfig('user:user_'.$lowerUsername.'.password', '');
if (password_verify($pPassword, $password) === true)
{
removeConfig('user:user_'.$lowerUsername);
$loggedInUsers = getConfig('login');
foreach ($loggedInUsers as $key => $user)
{
if ($user['username'] == $lowerUsername)
removeConfig('login:'.$key);
}
$showDelete = false;
$tpl->msg('success', _t('Benutzer gel&ouml;scht'), _t('Der Benutzer wurde erfolgreich gel&ouml;scht!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Das Passwort ist nicht korrekt!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte alle Felder ausf&uuml;llen.'));
}
if ($showDelete === true)
{
$tpl->assign('lowerUsername', $lowerUsername);
$tpl->assign('username', $username);
$showOverview = false;
$tpl->draw('settings/user_delete');
}
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider existiert der Benutzer nicht!'));
}
elseif (isset($_GET['edit']) && $_GET['edit'] != '')
{
$lowerUsername = $_GET['edit'];
$username = getConfig('user:user_'.$lowerUsername.'.username', '');
if ($username != '')
{
if (isset($_POST['submit']))
{
if (isset($_POST['passwordOld'], $_POST['passwordNew'], $_POST['passwordNew2']) && ($pPasswordOld = $_POST['passwordOld']) != '' && ($pPasswordNew = $_POST['passwordNew']) != '' && ($pPasswordNew2 = $_POST['passwordNew2']) != '')
{
if (preg_match('/^[a-z0-9_\-\+\*\/\#.\!\?@\(\)\[\]\{\}\<\>\=\$%&,\|\:~§;]{4,64}$/i', $pPasswordNew) === 1)
{
$passwordOld = getConfig('user:user_'.$lowerUsername.'.password', '');
if (password_verify($pPasswordOld, $passwordOld) === true)
{
if ($pPasswordNew === $pPasswordNew2)
{
setConfig('user:user_'.$lowerUsername.'.password', password_hash($pPasswordNew, PASSWORD_BCRYPT));
$tpl->msg('success', _t('Benutzer bearbeitet'), _t('Der Benutzer "%s" wurde erfolgreich bearbeitet und gespeichert.', $username));
}
else
$tpl->msg('error', _t('Fehler'), _t('Das neue Passwort stimmt nicht mit der Wiederholung &uuml;berein!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Das alte Passwort ist nicht korrekt!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider ist das Passwort ung&uuml;ltig! Das Passwort muss aus 4 bis 64 Zeichen bestehen und darf nur folgende Zeichen beinhalten: A-Z 0-9 - _ + * / # . ! ? @ ( ) [ ] { } < > = $ %% & , | : ~ § ;'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte alle Felder ausf&uuml;llen.'));
}
$tpl->assign('lowerUsername', $lowerUsername);
$tpl->assign('username', $username);
$showOverview = false;
$tpl->draw('settings/user_edit');
}
else
$tpl->msg('error', _t('Fehler'), _t('Leider existiert der Benutzer nicht!'));
}
if ($showOverview === true)
{
if (isset($_POST['logout']) && $_POST['logout'] != '' && strlen($_POST['logout']) == 32)
{
removeConfig('login:token_'.$_POST['logout']);
$tpl->msg('success', _t('Benutzer abgemeldet'), _t('Der Benutzer wurde erfolgreich abgemeldet.'));
}
$allUsers = getConfig('user');
$loggedInUsers = getConfig('login');
unset($loggedInUsers['login']);
array_walk($loggedInUsers, 'loggedInUsers', $allUsers);
$loggedInUsers = array_sort($loggedInUsers, 'created', SORT_DESC);
$tpl->assign('allUsers', $allUsers);
$tpl->assign('loggedInUsers', $loggedInUsers);
$tpl->draw('settings/user');
}
?>

View File

@@ -0,0 +1,36 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->assign('overviewUrl', '?s=overview');
if (isset($_GET['restart']) && $_GET['restart'] == '')
{
$tpl->setHeaderTitle(_t('Neu starten'));
list ($SSHReturn, $SSHError, $SSHExitStatus) = $tpl->executeSSH('sudo /sbin/shutdown -r now', true);
if (!empty($SSHError))
$tpl->msg('error', _t('Neu starten nicht m&ouml;glich'), nl2br($SSHError));
else
{
$jsTranslations = array();
$jsTranslations[] = 'Online - Du wirst sofort weitergeleitet';
$jsTranslations[] = 'Offline';
$tpl->assign('jsTranslations', $jsTranslations);
$tpl->draw('restart');
}
}
else
{
$tpl->setHeaderTitle(_t('Herunterfahren'));
list ($SSHReturn, $SSHError, $SSHExitStatus) = $tpl->executeSSH('sudo /sbin/shutdown -h now', true);
if (!empty($SSHError))
$tpl->msg('error', _t('Herunterfahren nicht m&ouml;glich'), nl2br($SSHError));
else
$tpl->draw('shutdown');
}
?>

View File

@@ -0,0 +1,80 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle(_t('SSH-Login'));
// Anmelden
if (isset($_POST['submit'], $_POST['ssh-login']) && $_POST['submit'] != '' && in_array($_POST['ssh-login'], array('password', 'publickey')))
{
$pType = $_POST['ssh-login'];
if ($pType == 'password')
{
if (isset($_POST['port'], $_POST['username'], $_POST['password']) && ($pPort = intval(trim($_POST['port']))) != '' && ($pUsername = trim($_POST['username'])) != '' && ($pPassword = $_POST['password']) != '')
{
$pRememberMe = (isset($_POST['remember-me']) && $_POST['remember-me'] == 'checked') ? true : false;
if (is_numeric($pPort) && $pPort >= 0 && $pPort <= 65535)
{
if ($tpl->setSSHInfo($pType, $pPort, $pUsername, $pPassword, NULL, $pRememberMe) === true)
{
if ($tpl->getSSHResource() !== false)
$tpl->msg('success', _t('Verbindung hergestellt'), _t('Verbindung zum Raspberry Pi wurde hergestellt.'));
else
$tpl->msg('error', _t('Fehler'), _t('Verbindung zum Raspberry Pi war nicht erfolgreich!<br /><br />Bitte &uuml;berpr&uuml;fe die eingegebenen Daten. Schl&auml;gt ein erneuter Versuch mit korrekten Daten fehl, wende dich bitte unten unter "Feedback" an mich, ich werde dir so schnell wie m&ouml;glich weiterhelfen.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Fehler beim Speichern der Daten!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Ung&uuml;ltiger Port. Der Port muss zwischen 0 und 65535 liegen.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte alle Felder ausf&uuml;llen.'));
}
elseif ($pType == 'publickey')
{
if (isset($_POST['port_'], $_POST['username_'], $_POST['privatekey_']) && ($pPort = intval(trim($_POST['port_']))) != '' && ($pUsername = trim($_POST['username_'])) != '' && ($pPrivateKey = $_POST['privatekey_']) != '')
{
$pPassword = isset($_POST['password_']) ? $_POST['password_'] : '';
$pRememberMe = (isset($_POST['remember-me_']) && $_POST['remember-me_'] == 'checked') ? true : false;
if (is_numeric($pPort) && $pPort >= 0 && $pPort <= 65535)
{
if ($tpl->setSSHInfo($pType, $pPort, $pUsername, $pPassword, $pPrivateKey, $pRememberMe) === true)
{
if ($tpl->getSSHResource() !== false)
$tpl->msg('success', _t('Verbindung hergestellt'), _t('Verbindung zum Raspberry Pi wurde hergestellt.'));
else
$tpl->msg('error', _t('Fehler'), _t('Verbindung zum Raspberry Pi war nicht erfolgreich!<br /><br />Bitte &uuml;berpr&uuml;fe die eingegebenen Daten. Schl&auml;gt ein erneuter Versuch mit korrekten Daten fehl, wende dich bitte unten unter "Feedback" an mich, ich werde dir so schnell wie m&ouml;glich weiterhelfen.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Fehler beim Speichern der Daten!'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Ung&uuml;ltiger Port. Der Port muss zwischen 0 und 65535 liegen.'));
}
else
$tpl->msg('error', _t('Fehler'), _t('Bitte alle Felder ausf&uuml;llen.'));
}
}
// Abmelden
if (isset($_GET['logout']))
{
if ($tpl->logoutSSH() === true)
$tpl->msg('success', _t('Verbindung getrennt'), _t('Erfolgreich abgemeldet.'));
else
$tpl->msg('error', _t('Fehler'), _t('Beim Abmelden ist ein Fehler aufgetreten!'));
}
$SSHInfo = $tpl->getSSHInfo();
if (!is_array($SSHInfo))
$tpl->msg('error', _t('Fehler'), _t('Konnte SSH-Informationen nicht abrufen.'), false);
$tpl->assign('ssh_info', $SSHInfo);
$tpl->assign('logged_in', ($tpl->getSSHResource() !== false));
$tpl->draw('ssh_login');
?>

View File

@@ -0,0 +1,27 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0010');
$tpl->setHeaderTitle(_t('Statistik'));
$statistics = array();
$hiddenStatistics = unserialize(htmlspecialchars_decode(getConfig('main:statistic.hidden', 'a:0:{}')));
$controller = new StatisticController($tpl);
$controller->loadStatistics('statistic/');
foreach ($controller->getStatistics() as $statistic)
{
$builder = new StatisticBuilder();
$builder->loadFromFile($statistic);
$array = $builder->getArray();
if (!in_array($builder->getId(), $hiddenStatistics))
$statistics[] = array('array' => $array, 'json' => $builder->getJSON());
}
$tpl->assign('statistics', $statistics);
$tpl->assign('msgInfo', (count($hiddenStatistics) == count($controller->getStatistics())) ? 'invisible' : ((count($controller->getStatistics()) == 0) ? 'empty' : ''));
$tpl->draw('statistic');
?>

View File

@@ -0,0 +1,70 @@
<?php
if (!defined('PICONTROL')) exit();
$tpl->setHeaderTitle('Terminal');
$jsTranslations = array();
$jsTranslations[] = 'Verbindung herstellen...';
$jsTranslations[] = 'Bitte gebe einen Befehl ein!';
$jsTranslations[] = 'Verbunden';
$jsTranslations[] = 'Verbindung getrennt';
$jsTranslations[] = 'Fehler aufgetreten!';
$jsTranslations[] = 'Verbindung erneut herstellen';
$jsTranslations[] = 'Verbindung getrennt<br />(Anmeldung an anderem Fenster)';
$jsTranslations[] = 'Verbindung getrennt<br />(Keine Berechtigung)';
$selectedPort = (isset($_GET['port'])) ? $_GET['port'] : 9001;
$ports = array();
if (isset($_GET['kill']) && $_GET['kill'])
{
if (($terminal = getConfig('terminal:port_'.$_GET['kill'], '')) != '')
{
removeConfig('terminal:port_'.$_GET['kill']);
exec('kill -9 '.$terminal['pid']);
$tpl->msg('success', _t('Terminal beendet'), _t('Das Terminal wurde erfolgreich beendet.'));
}
}
if ($tpl->getSSHResource(1) !== false)
{
$termials = getConfig('terminal', array());
$ports = array(
array('port' => 9001, 'active' => false),
array('port' => 9002, 'active' => false),
array('port' => 9003, 'active' => false),
array('port' => 9004, 'active' => false),
array('port' => 9005, 'active' => false)
);
foreach ($ports as $index => $port)
{
if (($terminal = getConfig('terminal:port_'.$port['port'], '')) != '')
{
if (shell_exec('netstat -atn | grep :'.$port['port']) == '')
{
removeConfig('terminal:port_'.$port['port']);
exec('kill -9 '.$terminal['pid']);
}
}
if (isset($termials['port_'.$port['port']]) && shell_exec('netstat -atn | grep :'.$port['port']) != '')
$ports[$index]['active'] = true;
}
}
// Vorkehrung aufgrund fehlendem HTTPS-Support
if (isset($_SERVER['HTTPS']))
{
$tpl->msg('info', _t('Terminal nicht verf&uuml;gbar'), _t('Das Terminal kann momentan noch nicht unter HTTPS verwendet werden.'));
}
$tpl->assign('port', $selectedPort);
$tpl->assign('ports', $ports);
$tpl->assign('cookie', substr($_COOKIE['_pi-control_login'], 0, 16));
$tpl->assign('jsTranslations', $jsTranslations);
$tpl->draw('terminal');
?>

View File

@@ -0,0 +1,16 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'cache/cache.class.php') or die('Error: 0x0011');
$tpl->setHeaderTitle(_t('Benutzer/Gruppen'));
$users = new Cache('users', 'rpi_getAllUsers');
$users->load();
$tpl->assign('all_users', $users->getContent());
$tpl->assign('users_cache_hint', $users->displayHint());
$tpl->draw('users_groups');
?>

View File

@@ -0,0 +1,20 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
$loggedInUsers = getConfig('login');
unset($loggedInUsers['login']);
foreach ($loggedInUsers as $token => $user)
{
if ($user['created'] < time()-60*60*12 && !(isset($user['remember_me']) && $user['remember_me'] == 'true'))
removeConfig('login:'.$token);
if ($user['created'] < time()-60*60*24*30 && (isset($user['remember_me']) && $user['remember_me'] == 'true'))
removeConfig('login:'.$token);
}
?>

View File

@@ -0,0 +1,16 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/coretemp.csv');
$log->setLimit(2016);
$log->add(array(time(), rpi_getCoreTemprature()));
$log->close();
?>

View File

@@ -0,0 +1,17 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/cpufrequency.csv');
$log->setLimit(2016);
sleep(7);
$log->add(array(time(), rpi_getCpuClock()));
$log->close();
?>

View File

@@ -0,0 +1,16 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/cpuload.csv');
$log->setLimit(2016);
$log->add(array(time(), rpi_getCPULoad(true)));
$log->close();
?>

View File

@@ -0,0 +1,19 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$memories = rpi_getMemoryInfo();
$memory = end($memories);
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/memory.csv');
$log->setLimit(2016);
$log->add(array(time(), $memory['total'], $memory['used']));
$log->close();
?>

View File

@@ -0,0 +1,59 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$networkConnections = getAllNetworkConnections();
$networkCounts = unserialize(htmlspecialchars_decode(getConfig('main:network.overflowCount', 'a:0:{}')));
foreach ($networkConnections as $network)
{
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/network_'.$network['interface'].'.csv');
$log->setLimit(2016);
$last = $log->getLast();
$countSent = 0;
$countReceive = 0;
if (isset($networkCounts[$network['interface']]['sent']))
$countSent = $networkCounts[$network['interface']]['sent'];
if (isset($networkCounts[$network['interface']]['receive']))
$countReceive = $networkCounts[$network['interface']]['receive'];
$rpiRuntime = rpi_getRuntime();
if ((time() - $rpiRuntime) < (int) $last[0] && (float) $last[1] > (float) ($network['sent'] + 4294967295 * $countSent))
$countSent++;
if ((time() - $rpiRuntime) < (int) $last[0] && (float) $last[2] > (float) ($network['receive'] + 4294967295 * $countReceive))
$countReceive++;
if ((time() - $rpiRuntime) > (int) $last[0] && (int) $last[0] != 0)
{
$countSent = 0;
$countReceive = 0;
}
$networkCounts[$network['interface']]['sent'] = $countSent;
$networkCounts[$network['interface']]['receive'] = $countReceive;
$log->add(array(time(), ($last[1] + (4294967295 * $countSent - $last[1]) + $network['sent']), ($last[2] + (4294967295 * $countReceive - $last[2]) + $network['receive'])));
$log->close();
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/network_packets_'.$network['interface'].'.csv');
$log->setLimit(2016);
$log->add(array(time(), $network['packets']['sent'], $network['packets']['received']));
$log->close();
}
setConfig('main:network.overflowCount', htmlspecialchars(serialize($networkCounts)));
?>

18
resources/cron/5-ram.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'statistic/statistic.class.php') or die('Error: 0x0002');
(include_once LIBRARY_PATH.'main/rpi.function.php') or die('Error: 0x0003');
$ram = rpi_getMemoryUsage();
$log = new LogStatistic();
$log->setFile(LOG_PATH.'statistic/ram.csv');
$log->setLimit(2016);
$log->add(array(time(), $ram['percent']));
$log->close();
?>

36
resources/cron/init.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
if (PHP_SAPI != 'cli') exit();
define('PICONTROL', true);
$doNotCheckForAuthentification = true;
(include_once realpath(dirname(__FILE__)).'/../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0001');
$folder = CRON_PATH;
$fileArray = array();
foreach (@scandir($folder) as $file)
{
if ($file[0] != '.')
{
if (is_file($folder.'/'.$file) && $file != 'init.php')
$fileArray[] = $file;
}
}
foreach ($fileArray as $file)
{
$timeOfFile = str_replace('-', '', substr($file, 0, 2));
$rest = date('i', time()) % $timeOfFile;
if (is_numeric($rest) && $rest == 0)
{
exec('/usr/bin/php -f "'.CRON_PATH.$file.'"');
set_time_limit(30);
usleep(500000);
}
}
if (trim(exec('dpkg -s php5-cli | grep Status: ')) != '' || trim(exec('dpkg -s php7.0-cli | grep Status: ')) || trim(exec('dpkg -s php7.3-cli | grep Status: ')) != '')
setConfig('cron:execution.cron', time());
?>

84
resources/init.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
if (!defined('PICONTROL')) exit();
$initConfig = parse_ini_file('config/init.config.ini.php');
if (!isset($config))
{
$config = array(
'ssh' => array(
'ssh_ip' => '127.0.0.1'
),
'version' => array(
'version' => '2.1.2',
'versioncode' => 29,
'android_comp_level' => 25
),
'url' => array(
'update' => 'https://pi-control.de/service/v1/update/',
'updateDownload' => 'https://pi-control.de/?service=update',
'updateNotification' => 'https://pi-control.de/?service=update_notification',
'plugin' => 'https://pi-control.de/service/v1/plugin/',
'pluginDownload' => 'https://pi-control.de/?service=plugin',
'temperatureMonitoring' => 'https://pi-control.de/service/v1/temperature_monitoring/',
'help' => 'https://pi-control.de/help/'
)
);
}
defined('PICONTROL_PATH') or define('PICONTROL_PATH', realpath(dirname(__FILE__).'/../').'/');
defined('RESOURCE_PATH') or define('RESOURCE_PATH', realpath(dirname(__FILE__)).'/');
defined('LIBRARY_PATH') or define('LIBRARY_PATH', realpath(dirname(__FILE__).'/library/').'/');
defined('CONTENT_PATH') or define('CONTENT_PATH', realpath(dirname(__FILE__).'/content/').'/');
defined('CONFIG_PATH') or define('CONFIG_PATH', realpath(dirname(__FILE__).'/config/').'/');
defined('PLUGINS_PATH') or define('PLUGINS_PATH', realpath(dirname(__FILE__).'/plugins/').'/');
defined('UPDATE_PATH') or define('UPDATE_PATH', realpath(dirname(__FILE__).'/update/').'/');
defined('TEMPLATES_PATH') or define('TEMPLATES_PATH', realpath(dirname(__FILE__).'/../public_html/templates/').'/');
defined('TEMPLATES2_PATH') or define('TEMPLATES2_PATH',realpath(dirname(__FILE__).'/templates/').'/');
defined('LOG_PATH') or define('LOG_PATH', realpath(dirname(__FILE__).'/log/').'/');
defined('CRON_PATH') or define('CRON_PATH', realpath(dirname(__FILE__).'/cron/').'/');
defined('LANGUAGE_PATH') or define('LANGUAGE_PATH', realpath(dirname(__FILE__).'/languages/').'/');
defined('CACHE_PATH') or define('CACHE_PATH', realpath(dirname(__FILE__).'/cache/').'/');
defined('INSTALL_PATH') or define('INSTALL_PATH', realpath(dirname(__FILE__).'/../').'/install/');
$globalLanguage = isset($initConfig['language']) ? $initConfig['language'] : 'de';
$globalLanguageArray = array();
if (isset($_GET['debug']))
{
if ($_GET['debug'] == 'hide')
{
setcookie('debug', NULL, 0);
unset($_COOKIE['debug']);
}
else
{
setcookie('debug', 'debug_mode', time()+3600);
$_COOKIE['debug'] = 'debug_mode'; // Setze, damit direkt verfuegbar
}
}
$errorHandler = array();
function myErrorHandler($code, $msg, $file, $line)
{
global $errorHandler;
$errorHandler[] = 'Fehler ['.$code.']: '.$msg.' in der Datei '.$file.', Zeile '.$line;
if (isset($_COOKIE['debug']) && $_COOKIE['debug'] == 'debug_mode')
return false;
else
return true;
}
error_reporting(E_ALL ^ E_STRICT);
ini_set('display_errors', 1);
set_error_handler('myErrorHandler');
header('Content-Type: text/html; charset=utf-8');
if (isset($_COOKIE['debug'], $_GET['s']) && $_COOKIE['debug'] == 'debug_mode')
echo '<!DOCTYPE HTML><div style="background: #F44336; color: #FFFFFF; padding: 3px;">DEBUG: PHP-Fehlermeldungen werden angezeigt. <a href="'.$_SERVER['REQUEST_URI'].'&debug=hide" style="color: #FFFF00;">Deaktivieren.</a></div>';
if (!isset($doNotCheckForAuthentification))
(include LIBRARY_PATH.'main/authentification.php') or die('Nicht gefunden!');
?>

620
resources/languages/en.php Normal file
View File

@@ -0,0 +1,620 @@
<?php
if (!defined('PICONTROL')) exit();
// English
$langArray = array(
'920c3931' => 'Failed to get IP address!',
'2963f17d' => 'Unfortunately, an unexpected error has occurred. Please close the feedback window and try again. Otherwise, write me at <a href="%%s" target="_blank">contact</a>.',
'8311b9b6' => 'Close',
'bea4c2c8' => 'Feedback',
'28c330db' => 'Some data must be collected for the feedback.',
'fcb4bb2f' => 'Diagnostic data was collected. A new window will open when you click on the button below.',
'db72d0d6' => 'Open feedback',
'd4d2d713' => 'The interface will be restarted...',
'808784ec' => 'The interface has been restarted.',
'ed6aabd6' => 'An unexpected error has occurred!',
'97be4473' => 'An error has occurred! Probably, the connection was closed.',
'995ae7be' => 'It can be restarted only one interface at the same time.',
'2ff2ad4e' => 'The password should be at least 8 characters.',
'08ca4b4b' => 'Disconnects...',
'77c09673' => 'Connects...',
'79435d54' => 'Find IP address of connection...',
'991b47c2' => 'Connection with "%%s" was successful.',
'74d42e1c' => 'IP address',
'4694c564' => 'Fault!',
'229de263' => 'Online - You will be redirected immediately',
'8d9da4bc' => 'Offline',
'1710fb15' => 'No values are available. Values will be registered every %%s minutes.',
'8b46562c' => 'An error has occurred! Error: %%s',
'7182718z' => 'Time',
'21d0815d' => 'An error has occurred! Error code: %%s',
'7833f4fb' => 'Connect...',
'c68f2cae' => 'Please enter a command!',
'62cfb21c' => 'Connected',
'54f664c7' => 'Online',
'3ab1b0ef' => 'Error occurred!',
'e9c4586f' => 'Reconnect',
'306964c0' => 'Disconnected<br />(Log on to another window)',
'9121f198' => 'Disconnected<br />(No permission)',
'70b55b88' => 'Disconnected',
'ab0cf104' => 'Cache',
'2958e45z' => 'Activate',
'63909f76' => 'Use',
'2aa12a5f' => 'Size',
'a2db4ba7' => 'Last change',
'667a3040' => 'Cache time',
'33dddf44' => 'Clear',
'b97d23bf' => 'Save',
'e76cf8a6' => 'You',
'c0f3a410' => 'Your devices',
'a4afc7ee' => 'Verified as ',
'e21141e5' => 'Device name',
'9bc8a493' => 'Create date',
'490ba398' => 'Notification',
'5be418d9' => 'The notifications are realised by Pushbullet. Therefore, an account at Pushbullet is necessary.',
'aba85c65' => 'Access token',
'19279a9e' => 'Test notification',
'02efac7b' => 'Send now',
'540356eb' => 'Notify me when...',
'c3829179' => 'a new Pi Control Version appears',
'83b6557b' => 'the CPU temperature exceeds a value',
'4bb63b47' => 'the memory usage (total memory) exceeds a value',
'756330b2' => 'Settings for overview',
'9a899bca' => 'Interval overview update',
'8472022z' => 'Seconds',
'238c21ae' => 'Show "Connected devices"',
'e8e6f5ed' => 'Activation causes a longer loading time of the overview.',
'8328b196' => 'Weather',
'd5d9a3bf' => 'Service',
'91aa3dc3' => 'Location',
'512ef7c6' => 'Country',
'3c2f8b8c' => 'Germany',
'ba9160fb' => 'Austria',
'7a0be5a1' => 'Swiss',
'b7709fb2' => 'United Kingdom',
'e3a7b549' => 'Server not reachable!',
'40acacf0' => 'Postcode',
'c05fc5cd' => 'City',
'e458e5b8' => 'Settings for Pi Control',
'9c22f572' => 'Theme color',
'6e2ee1c6' => 'Label',
'9b22aa23' => 'Give your Pi Control a name to identify it better in notifications.',
'ff940ad7' => 'Language',
'8f0ca218' => 'German',
'319be822' => 'English',
'fc1629ac' => 'External access',
'eab46a55' => 'Accessible outside of the local network? If necessary think of port forwarding.',
'eb081ce8' => 'Temperature monitoring',
'3955039z' => 'Activate this option to be notified by your Raspberry Pi, when a certain temperature is exceeded. In this case, it can be set specific behavior.',
'15b9ca9e' => 'Paused for %s',
'16f93748' => 'Maximum temperature',
'e6c7a581' => 'Action',
'bdabbcc7' => 'Send email',
'dec44579' => 'Confirm',
'0d225a0d' => 'Check',
'ba515a56' => 'Verified',
'637b84d1' => 'Shell command',
'0ab43de2' => 'Runs as %s.',
'ae455599' => 'Remove Pi Control',
'4c51f524' => 'If you don\'t like the Pi Control and you want to remove it, let me know the reason below under "Feedback" please. So I can better take on possible problems and constantly improve Pi Control.',
'7a92f000' => 'Instructions to remove',
'a28a5e7e' => 'Settings for plugins - Delete plugin',
'9323a797' => 'Would you really irrevocably delete the plugin <strong>%s</strong>?',
'49c81cd0' => 'Delete',
'3c45a1e8' => 'Settings for plugins',
'3c972504' => 'Version %s',
'27014dd1' => 'Settings',
'5e3e0783' => 'Disable',
'570e8f21' => 'Settings for statistic',
'664006b3' => 'Hide not used statistics to improve the loading times and to keep track.',
'f2d37233' => 'Statistics are, regardless of the display status, recorded.',
'49ee3087' => 'Name',
'801ab246' => 'Download',
'9b151bfe' => 'Reset',
'7b213e2d' => 'Settings for statistic - Reset history',
'9d266f6d' => 'Do you really want to reset the history of %s?',
'742937f0' => 'Troubleshooting',
'ed7243fc' => 'The troubleshooter can help you with problems and even remove them if necessary.',
'053b183c' => 'Files and folders',
'e2aa67cf' => 'File',
'45a882e7' => 'Folder',
'de9af927' => 'Exists',
'f913ca67' => 'Permission',
'45b589ec' => 'User:Group',
'5b3b6a11' => 'Guide to troubleshooting',
'daa242c9' => 'Cron for Pi Control',
'ae7f5a76' => 'The cron for your Pi Control is as follows:',
'c9ccf692' => 'Mark all with double click.',
'519f3478' => 'Registered in crontab',
'3231457z' => 'PHP-CLI installed',
'c89b288f' => 'Last execution',
'e8a54e95' => 'Last entry log',
'b846f886' => 'Fix problem',
'34b6cd75' => 'Version',
'50c6a2e1' => 'Email notification',
'f8bc0f0d' => 'If you want to receive an email when a new version of the Pi Control is out, you can register via the following button in a list.',
'e4e816c4' => 'Enter email',
'a5b3f2c8' => 'Update',
'2688c7f7' => 'Your Pi Control is no longer up-to-date. Version %s is available!',
'2f0deed4' => 'What\'s new in version %s',
'c6e641f2' => 'Your Pi Control is up-to-date.',
'2009c832' => 'An error occurred when connecting to the server. The server sends a invalid response.',
'659126ez' => 'An unexpected error occurred when connecting to the server. Error code: %s',
'58d37757' => 'Install update',
'0a9c591b' => 'Is an update available, you can download this and install over the button below.',
'fa1ba9e2' => 'Download &amp; install update',
'c95c08dd' => 'Settings for user',
'cca8493f' => 'Username',
'7c6cb747' => 'Created',
'6d6c763b' => 'Last activity',
'01e91d2e' => 'Never logged in',
'5ad05dd4' => 'Edit',
'd9901e46' => 'Add',
'bd586bb0' => 'Users logged-in',
'3b6f8e4f' => 'Non-fixed login users are automatically logged off after 12 hours of inactivity.',
'f50c371f' => 'Logged in at',
'86c735a6' => 'Logged in by',
'08c540e1' => 'Remember me',
'e4cc0dcc' => 'Current session',
'375ee260' => 'Yes',
'b397ec0b' => 'No',
'03b246c1' => 'Logout',
'5d83abec' => 'Settings for user - Add user',
'3e45af4c' => 'Password',
'1d8982a9' => 'Repeat password',
'f081d2a0' => 'Settings for user - Delete user',
'546baa5f' => 'Please enter the password of the user for confirmation.',
'7be0c4a0' => 'Settings for user - Edit user',
'd5a1b623' => 'Old password',
'c8a18c65' => 'New password',
'7d93c125' => 'Repeat new password',
'0d94a8c5' => 'Detailed overview',
'0a6892b9' => 'General',
'622fcb1e' => 'Raspberry Pi Model',
'b86aa88e' => 'Manufacturer',
'32c676ac' => 'Revision',
'1f4e5730' => 'PCB Revision',
'e65a75be' => 'Serial number',
'c32566d1' => 'Current time',
'9e6a07bb' => 'Current timezone',
'77f0ba28' => 'Run time',
'6d202d5f' => 'Last start',
'719d067b' => 'Software',
'f0bac093' => 'Distribution',
'6ff9f444' => 'Kernel',
'a45da96d' => 'System',
'66bd721f' => 'Running tasks',
'69032d57' => 'Installed packages',
'2e6ed7fa' => 'List packages',
'7417eeb4' => 'Webserver',
'e69c69c6' => 'HTTP-Server',
'7bde7505' => 'PHP-Version',
'b15b7b03' => 'User',
'3b80444f' => 'Processor',
'beea054d' => 'Clock',
'4db9161e' => 'Maximum clock',
'2002d516' => 'Total load',
'6016245z' => 'Load %s',
'c2ea8433' => 'Type',
'd490a3ea' => 'Model',
'898901aa' => 'Temperature',
'b71b74e6' => 'Main memory',
'927cee1b' => 'Total',
'd4bbf105' => 'Load',
'52404cb6' => 'Total memory',
'3349300z' => 'Partition',
'0d18c373' => 'Mountpoint',
'74533df5' => 'Used',
'6956635z' => 'Free',
'2722ef4e' => 'All user',
'34f43597' => 'User-ID',
'8ddf190a' => 'Group-ID',
'60aaf44d' => 'Port',
'197bf841' => 'Last login',
'ac9bebfc' => 'By',
'31493eab' => 'Logged in',
'339ed42d' => 'At %s on %s at %s from %s',
'9ba4b588' => 'Statistic',
'bb38096a' => 'Plugins',
'71f221d8' => 'Count',
'aef86156' => 'Total',
'7e0cea5f' => 'Installed',
'0693306z' => 'Update',
'e729d5b1' => 'Disabled',
'cc28ac9e' => 'Discover plugins',
'47ab20bc' => 'There are currently no plugins available.',
'6c6655f3' => 'Install',
'15ad4b1c' => 'Go to plugin',
'bf3cfcc6' => 'Update',
'7710266e' => 'The plugin is out of date. Version %s is available!',
'cda4c3b2' => 'Published at',
'17eeee92' => 'Last update',
'35bedb45' => 'Description',
'bf6c5608' => 'Languages',
'7306fb5c' => 'Manual',
'c2efebc7' => 'Requirements',
'743966b9' => 'Changes with version %s',
'46fa564b' => 'Screenshots',
'9c0864a5' => 'ABOUT ME',
'021321ez' => 'VERSION',
'57d0632a' => 'Help',
'b6d49679' => 'Open at Play Store',
'9a4883bb' => 'App in Play Store',
'62db69f3' => 'My blog',
'2491bc9c' => 'Twitter',
'd3b7c913' => 'GitHub',
'f41ea892' => 'Donate',
'922d7e28' => 'LICENSE',
'1034eec6' => 'Raspberry Pi is a trademark<br />of the %s.',
'28ba4993' => 'With %s developed by %s.',
'1cb3236e' => 'Logged in as %s',
'417b5de9' => 'Overview',
'a983288c' => 'Network',
'514d8a49' => 'Terminal',
'3cee9f12' => 'Unsupported browser version',
'e23dd547' => 'Your current browser version is not supported by Pi Control. Please update your browser or use another!',
'96ae48ee' => 'Pi Control %s is available',
'fa13b1ea' => 'Go to <a href="%s">update</a> to view and start it.',
'c3049ac9' => 'Error with the cron',
'38a39b09' => 'Apparently, there\'s an issue with the cron for the Pi Control. It was no longer running for more than 2 minutes. If this message still appears in about 5 minutes, perform <a href="%s">troubleshooting</a>.',
'567df44c' => 'Number of installed packages: %s',
'f90b8f32' => 'Package name',
'99dea780' => 'Login',
'694c5fec' => 'Cookies must be enabled for this feature.',
'ecff6ecb' => 'Log in',
'2255f45c' => 'Raspberry Pi is a trademark of the Raspberry Pi Foundation.',
'7041838z' => 'Configuration',
'e7935ae6' => 'Traffic',
'3c1aac82' => 'Interface',
'fa02f30e' => 'Sent',
'0c78bbf3' => 'Received',
'c8f4b8c4' => 'Hostname',
'317907a0' => 'Your Raspberry Pi will be displayed at network under the following name: <strong>%s</strong>',
'279f3416' => 'Change',
'a12a3079' => 'IP',
'eb9de48f' => 'MAC-Address',
'17b6fa0e' => 'Not connected',
'29f0e281' => 'Network name',
'46393c49' => 'Security',
'84eb8685' => 'Channel',
'394a653c' => 'No WiFi networks found. <a href="%s">Scan.</a>',
'ec53a8c4' => 'Status',
'8385a5ce' => 'Network configuration',
'd1fd5dc4' => 'Protocol',
'41aa696a' => 'Method',
'28bba8c5' => 'Network configuration - Add interface',
'b3370824' => 'Please make more settings for IPX/SPX yourself',
'54201c55' => 'DHCP',
'292176d4' => 'Static',
'52a4c908' => 'Manual',
'50d46c2f' => 'Address',
'e701001d' => 'Netmask',
'926dec94' => 'Gateway',
'bb2fa70e' => 'Network configuration - Delete interface',
'ff4b5d6b' => 'Would you really irrevocably delete the interface <strong>%s</strong>?',
'a026a765' => 'Network configuration - Edit interface',
'f93acacf' => 'Please activate JavaScript to be able to connect to a WLAN network.',
'f6771532' => 'Connect to WLAN network',
'55ad9ac8' => 'Password (if needed)',
'b70ad43d' => 'Connect',
'ec4482f9' => 'Connecting to "%s"...',
'66c09a2c' => 'Connection with "%s" was not successful! <a href="%s">Try again.</a>',
'3bb82d0b' => 'If you change the hostname, the new name is visible only after a reboot.',
'4ffd5e49' => 'Do you really want restart your Raspberry Pi?',
'bad5b81c' => 'Restart',
'4da1bb14' => 'Do you really want shutdown your Raspberry Pi?',
'4eac40b9' => 'Shutdown',
'4ce188e1' => 'The current postal code is invalid.',
'6500e84c' => 'Weather has not been configured. <a href="%s">To the settings.</a>',
'c5e7fef5' => 'The weather can not be accessed currently.',
'913a8b4e' => 'Wind force | Humidity',
'b6f55f38' => 'Start time',
'742c5587' => 'CPU-Clock',
'a35c5056' => 'CPU-Load',
'719e599e' => 'CPU-Temperature',
'e53619c1' => 'RAM',
'5582e12z' => 'Memory used',
'785c3f86' => 'Memory free',
'4f02abcd' => 'Show more',
'0ffcd1dc' => 'Connected devices',
'84186a7b' => 'There are currently no plugins installed.',
'5a457123' => 'Raspberry Pi is restarting',
'1a319d8b' => 'As soon as your Raspberry Pi is available again, you\'ll automatically redirected to the overview.<br />Should you not be redirected, you come <a href="%s">here back to the overview.</a><br /><br />',
'e713f04a' => 'Current status: <strong class="green">Online</strong>',
'6734713f' => 'Raspberry Pi shuts down',
'6463ed80' => 'As soon as your Raspberry Pi is available again, you come <a href="%s">here back to the overview.</a>',
'280d3e18' => 'SSH-Login',
'ad16b2ee' => 'You are not logged in. Thereby you cannot use some functions.',
'f2fba58e' => 'Log in with a password',
'8617afc3' => 'Click to activate',
'3139471z' => 'SSH-Port',
'6fc3213d' => 'Standard: %d',
'6673e2ed' => 'SSH-Username',
'1335e66z' => 'SSH-Password',
'ca3b9b74' => 'SSH-Login saving?',
'eb6694f7' => 'Saves the password to not have to be re-log in after each session.',
'30aefd8a' => 'OR',
'0118609z' => 'Log in with a publickey',
'40431ebc' => 'Standard: 22',
'dbf970b1' => 'SSH-Privatekey',
'f8805681' => 'Privatekey-Password (if required)',
'6583ab9a' => 'You are already logged in with the user %s.',
'3067c491' => 'Please enable JavaScript to view the statistics.',
'87f4a935' => 'Period of time',
'71c3e827' => 'All (7 days)',
'4c0e0cf7' => 'Last 6 days',
'6c8a29be' => 'Last 5 days',
'059b6bde' => 'Last 4 days',
'e52b6b76' => 'Last 3 days',
'9e134b29' => 'Last 2 days',
'8591edd8' => 'Last 24 hours',
'1dfceccb' => 'All statistics are hidden!',
'9a1195e0' => 'There are still no statistics available. Values are entered every 5 minutes.',
'e65569e7' => 'Load...',
'88e7e4ab' => 'Terminal %d (%s)',
'3a12ad89' => 'Disconnect',
'c737e167' => 'The Terminal offers you the ability to perform simple commands directly in the Pi Control.',
'8b622980' => 'Command: ',
'10ec760e' => 'Send',
'21f5916a' => 'Cache cleared',
'35fa6d1c' => 'The cache has been successfully cleared.',
'52e5304c' => 'Fault',
'786d9da7' => 'Unfortunately, the cache could not be cleared!',
'fbf49a53' => 'Please assign a valid number between 1 and 9999 for the storage time.',
'62c128cf' => 'Settings saved',
'8e2b9292' => 'The settings have been successfully saved.',
'ca4a2339' => 'Unfortunately, the specified access token is not valid!',
'3cd46c39' => 'Unfortunately, the specified temperature is invalid!',
'55e6ff09' => 'Unfortunately, the specified percentage is invalid!',
'daf2902f' => 'Enable notification',
'3c93ba20' => 'The notification was enabled.',
'3bf35e85' => 'Could not activate the notification!',
'dfcedc9d' => 'Disable notification',
'bed43f6f' => 'The notification was disabled.',
'c24fbff7' => 'Could not disable the notification!',
'191b8d9c' => 'Token removed',
'206a2719' => 'The token was successfully removed.',
'021ce11e' => 'Please fill out all required fields and choose one or more of the actions!',
'6ba29415' => 'Your Pi Control "%s" has sent you a test notification.',
'4730e82z' => 'Connection error',
'7d72dd71' => 'An unexpected error occurred when connecting to Pushbullet. Error code: %d',
'a5b12f8c' => 'Pushbullet reports an error with a request: %s',
'5c234b18' => 'Please assign a valid value between 1 and 9999 for the interval.',
'ec6c4274' => 'Unfortunately, the specified API key is too short!',
'5f30639f' => 'Unfortunately, the specified postcode is invalid!',
'433e876z' => 'Unfortunately, the town name is invalid!',
'5805e7ce' => 'Please fill out all required fields!',
'9c7509af' => 'The settings have been successfully saved.<br /><br />Tip: To make effective the theme change, empty your browser cache with Ctrl+ F5 (Windows) / &#8997;&#8984; + E (OS X / Safari) / &#8679;&#8984; + R (OS X / Chrome)',
'25641a9a' => 'Unfortunately, the label is invalid! The name must consist of 2 to 32 characters. The first character must be a letter, and only the following characters are allowed: A-Z 0-9 _ - + / . ( ) [ ] "Spaces"',
'c89cee57' => 'Please assign a label for your Pi Control!',
'4068485z' => 'Please enter a valid email address.',
'8397f10d' => 'Please enter a valid shell command.',
'7a80a6b0' => 'Please choose at least one action.',
'41cfb898' => 'Temperature monitoring enabled',
'3ac6f708' => 'The temperature monitoring has been enabled.',
'885f7934' => 'Could not activate the temperature monitoring!',
'54ffcc1a' => 'Temperature monitoring disabled',
'd3618a3d' => 'The temperature monitoring has been disabled.',
'7ba545da' => 'Could not disable the temperature monitoring!',
'8421b3f6' => 'Unfortunately, an error has occurred. Please repeat the assignment of the name and the email address.',
'e8113527' => 'An unexpected error occurred when connecting to the server. Error code: %d (%s)',
'9e539a2e' => 'Unfortunately, no connection to the server was able to establish because it is at the moment probably unreachable. Error code: %d',
'e746cbb2' => 'An unexpected error occurred when connecting to the server. Error code: %d',
'5c9ed40b' => 'Server error',
'fc95e503' => 'An error occurred when connecting to the server. The server sends an empty response.',
'315f97dd' => 'Processing error',
'a71c8512' => 'Email sent',
'5244a7b2' => 'An email with a confirmation link has been sent to <strong>%s</strong>. In the email is a link that must be clicked or opened. Should the email not be arrived after 10 minutes, look in your spam folder. Otherwise repeat the process.',
'04d0ced9' => 'Plugin deleted',
'73d87db2' => 'The plugin "%s" was successfully deleted.',
'ba28d467' => 'The plugin "%s" could not be deleted.',
'afa753b4' => 'Plugin enabled',
'11d79a74' => 'The plugin "%s" has been successfully enabled.',
'75b0b99e' => 'The plugin "%s" could not be enabled.',
'8e9b5fa6' => 'Plugin disabled',
'a56a6e08' => 'The plugin "%s" has been successfully disabled.',
'4a2e71b8' => 'The plugin "%s" could not be disabled.',
'953fbe20' => 'Could value not save in configuration file!',
'e815ef70' => 'The history could not be found: %s',
'58876dbf' => 'History reseted',
'707a0c9b' => 'History has been reset successfully.',
'b11d776d' => 'History could not be reset.',
'4c30bad9' => 'Pi Control updated to version %s',
'ef0db072' => 'Your Pi Control was successfully updated and is now ready for use. Should problems occur, click below on "Feedback" and write me. Have fun!<br /><br />Tip: Clear your browser cache with Ctrl + F5 (Windows) / &#8997;&#8984; + E (OS X / Safari) / &#8679;&#8984; + R (OS X / Chrome)',
'9ec860ec' => 'Update blocked',
'e203e667' => 'It was found at least one error with the files or folders of the Pi Control. Please fix the problem using the <a href="%s">troubleshooting</a> first, otherwise an update is not possible.',
'21caa2f6' => 'User created',
'8c5d3ec0' => 'The user "%s" was successfully created.',
'11379b49' => 'The specified passwords do not match!',
'cfca6225' => 'Unfortunately, the password is invalid! The password must consist of 4 to 64 characters and must contain only the following characters: A-Z 0-9 - _ + * / # . ! ? @ ( ) [ ] { } < > = $ %% & , | : ~ § ;',
'8f37b0f8' => 'Unfortunately, the username is already taken! Please choose another.',
'fceff235' => 'Unfortunately, the username is invalid! The username must consist of 2 to 32 characters. The first character must be a letter, and only the following characters are allowed: A-Z 0-9 - _',
'23341f35' => 'Please fill all fields.',
'73bd321c' => 'User deleted',
'426ef24b' => 'The user was successfully deleted!',
'05525c21' => 'The password is not correct!',
'6ef228fa' => 'Unfortunately, the user does not exist!',
'7264b91f' => 'User edited',
'832e48a1' => 'The user "%s" was successfully edited and saved.',
'73377bad' => 'The new password does not match the repetition!',
'a3e990a1' => 'The old password is not correct!',
'78f14302' => 'User logged out',
'c0e2703c' => 'The user has been logged out successfully.',
'92fcd39f' => 'No plugins!',
'4b68e7b6' => 'Pluginfolder not found!',
'fc877665' => 'Access is only available in the local area network (LAN)!',
'7c4bd417' => 'Login blocked for %d seconds!',
'6ae0a563' => 'Login failed!<br />Login blocked for %d seconds!',
'266342aa' => 'Login failed!<br />Too many failed attempts. Login blocked for %d seconds!',
'491b8c75' => 'Login failed!<br />Too many failed attempts. Login blocked for %d minute!',
'df7545f1' => 'Login failed!<br />Too many failed attempts. Login blocked for %d minutes!',
'dbee4e1e' => 'Error during login!',
'101b60f8' => 'Hostname saved',
'91c90c67' => 'In order for the change to take effect, your Raspberry Pi needs to be restarted. <a href="%s">Now restart.</a>',
'50f84dd2' => 'Failed to change the hostname! Error code: %s',
'5a7d26a2' => 'The hostname is invalid! It must consist of at least 1 to 24 characters and may contain only the following characters: A-Z a-z 0-9 -<br />The hostname cannot start or end with a dash.',
'9bd19732' => 'Interface added',
'cb892b7e' => 'Interface has been added successfully. The interface must be restarted in order for these settings to be effective however.',
'63f897f0' => 'Interface deleted',
'3cb08490' => 'Interface was successfully deleted.',
'5f361165' => 'Interface not available',
'b33f8f3b' => 'No interface with the specified name was found.',
'e82d2f60' => 'Unfortunately, the interface could not be saved. The name for this interface is already in use.',
'2d5b67f7' => 'Unfortunately, the interface could not be saved. An error occurred during transmission.',
'89cf06f3' => 'Unfortunately, the configuration file has been modified in the meantime, try therefore again.',
'4ca9aa46' => 'Please assign an interfacename, a protocol and a method!',
'492f4319' => 'Unfortunately, the interface could not be deleted. An error occurred during transmission.',
'23950fb1' => 'Interface saved',
'ac3dbb12' => 'Interface has been saved successfully. The interface must be restarted in order for these settings to be effective however.',
'd51fd6f1' => 'Failed to load the plugins',
'2eaf52d4' => 'The selected plugin supports at the moment no settings.',
'1a8204f0' => 'Plugin is incompatible',
'9ebb114d' => 'Currently, the plugin you\'re looking for cannot be opened because it is not compatible. Please update your Pi Control to continue to use the plugin.',
'8ac6b33b' => 'Plugin is disabled',
'73ac414b' => 'Currently, the plugin you\'re looking for cannot be opened because it is disabled.',
'df67d56c' => 'Plugin not found',
'ded55eda' => 'Currently the plugin you\'re looking for can not be found or it does not exist.',
'14fca6f1' => 'Restart not possible',
'8c73b4a2' => 'Shutdown not possible',
'f9f52265' => 'Connected',
'965122d5' => 'Connection to Raspberry Pi was prepared.',
'd3f7826c' => 'Connection to Raspberry Pi was unsuccessful!<br /><br />Please check your entered dates. Failed a second try to log in with correct dates please contect me under "Feedback" at the bottom. I will help you as soon as possible.',
'88a298d6' => 'Error while saving the dates!',
'a4f68fac' => 'Invalid port. The port must to be between 0 and 65535.',
'3e0b52a8' => 'Successfully logged out.',
'3608adcd' => 'When log off an error has occurred!',
'122d6738' => 'Cannot read SSH-Information.',
'059fd062' => 'Terminal stopped',
'484bd720' => 'The terminal has been stopped successfully.',
'4ead1058' => 'Update available',
'424332a2' => 'Pi Control version %s is now available for download for your Pi Control "%s".',
'6aaa0133' => 'Temperature exceeded',
'e9e4c44a' => 'Your Pi Control "%s" reports an increased temperature of the CPU by %s °C.',
'bcd5b6b5' => 'Memory used',
'ce102228' => 'Your Pi Control "%s" reports a memory consumption of %d%%.',
'f5e531e3' => 'Status',
'064bede9' => 'Cached',
'35c9c1df' => 'Back',
'fdb69343' => 'Click for help',
'f9a26283' => 'Unknown',
'c63bc415' => 'File "%s" does not exists or is not a valid file.',
'55f91856' => 'Could not open and read file "%s".',
'72ee0a08' => 'Redirection',
'c12b82b7' => 'Header already sent. Redirect not available. Please click on <a href="%s">this link</a>.',
'19aa065f' => 'SSH-Authentification error',
'3fa4345d' => 'No SSH-Access, please log in! <a href="%s">Log in now.</a>',
'f3b2bd21' => 'Email confirmed',
'f67d50cd' => 'Your email has been successfully confirmed.',
'f2024246' => 'The server could not find related information. Assure that you have confirmed the email.',
'54ddb475' => 'Could not delete log file: %s',
'4ef54a08' => 'Could not open log file: %s',
'd874be69' => 'Unfortunately, an error is occurred when unzip the update! Error code: %s',
'a6c5267f' => 'The update was not completely downloaded. Please try again. Should the error persist, write me at <a href="%s" target="_blank">contact</a>, so that I can help you as quickly as possible.',
'8faea4b1' => 'Could not cache the update! Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'a03e97c2' => 'Couldn\'t find the update on the server! Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'dbfe2368' => 'Unfortunately, an error has occurred during the update: %s<br />Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'c0b73d75' => 'Return to the update',
'4dd11823' => 'Access error',
'f35106fb' => 'The expected page is not available.',
'b1722ba6' => 'Unfortunately, an error has occurred in the structure of the page.<br /><br />%s',
'7e28887b' => 'Please report the problem <a href="%s" target="_blank">here</a>.',
'359cabda' => 'Dynamic',
'802238f7' => 'There has been an error! Error code: %s',
'c1d48b16' => 'Filename "%s" is invalid.',
'9ba51734' => 'Date',
'5a9ed090' => 'Temperature in degrees Celsius',
'e056e124' => 'Load in percent',
'25a22b12' => 'Sent in bytes',
'a2c9a77d' => 'Received in bytes',
'01ac370c' => 'Degrees Celsius',
'4b4f4d53' => 'Load %%',
'5185a813' => 'Traffic (MB)',
'15a8022d' => 'UPDATE',
'4eb57703' => 'An error has occurred! Error: %s',
'431e27fd' => 'Plugin installation',
'481c6ece' => 'Back to plugin',
'ca7290c4' => 'Unfortunately, an error is occurred when unzip the plugin! Error code: %s',
'daa48153' => 'The folder for the plugin could not be created. Check folder permissions and try again. Should the error persist, write me at <a href="%s" target="_blank">contact</a>, so that I can help you as quickly as possible.',
'38ce1a5f' => 'The folder for the plugin already exists. Please delete the folder.',
'a62b406c' => 'The plugin was not completely downloaded. Please try again. Should the error persist, write me at <a href="%s" target="_blank">contact</a>, so that I can help you as quickly as possible.',
'c54273b0' => 'Could the plugin not cache! Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'8408cdf7' => 'Couldn\'t find the plugin on the server! Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'15ae31f8' => 'Couldn\'t find the PluginID on the server! Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'97c5ea2f' => 'Unfortunately, an error has occurred while retrieving the plugins. Error code: %s<br />Please write me at <a href="%s" target="_blank">contact</a> so that I can help you as quickly on.',
'cd9ff94e' => 'The folder for the plugin does not exist. Please install the plugin first.',
'de3e456f' => 'Total in byte',
'8e19b4db' => 'Used in byte',
'4ad0e6c0' => 'Usage in MHz',
'532d516e' => 'Error while retrieving',
'26c88659' => 'Unfortunately, an error has occurred while retrieving the plugin. Error code: %s',
'01c5cdaa' => 'The plugin is already installed.',
'9d34e0e2' => 'The plugin you are looking for could not be found.',
'eef7f68b' => 'Character encoding',
'cdb36567' => 'RAM-Load',
'50ba55ca' => 'Terminal not available',
'ca9e3c3f' => 'The terminal cannot be used under HTTPS at the moment.',
'fc1cafe2' => 'Unfortunately, the specified coordinates are invalid!',
'71032b12' => 'Without API key',
'fe4b1dff' => 'With API key',
'fb79710d' => 'To the provider',
'a520cdd1' => 'Coordinates',
'9440e2eb' => 'Latitude',
'e045e08f' => 'Longitude',
'8360feef' => 'Info display',
'b44005b5' => 'Select the format for the info display.',
'cf0a6993' => 'GitLab',
'091c2ed7' => 'Processes',
'f81578aa' => 'Process terminated',
'ca232db6' => 'The process with the ID %s has been successfully terminated.',
'1d40974e' => 'The process with the ID %s could not be terminated.',
'a8f0855f' => 'The process with the ID %s could not be found.',
'3cf4790e' => 'Process killed',
'72a8f132' => 'The process with the ID %s has been successfully killed.',
'0c4e70a6' => 'The process with the ID %s could not be killed.',
'459266d4' => 'Users/Groups',
'981385c0' => 'Due to lack of permissions, processes cannot be terminated. Log in via SSH to terminate processes. <a href="%s">Sign in now.</a>',
'b8b4f704' => 'Number of processes',
'cc5db449' => 'Number of active processes',
'2d73559f' => 'PID',
'2b55387d' => 'CPU',
'58f34ee3' => 'Start time',
'5476144z' => 'Command',
'0576cf2c' => 'Terminate',
'0755c4ab' => 'Kill',
'39472a85' => 'Uninterruptible',
'ce733d85' => 'Running',
'db9cf7b6' => 'Sleep',
'a104185d' => 'Stopped',
'7c3d115a' => 'Zombie',
'a23aa6be' => 'Logs',
'b5df6448' => 'Some files cannot be opened due to a lack of permission. Login via SSH to open it as well. <a href="%s">Sign in now.</a>',
'5ec530b6' => 'Filename',
'9ea1fafd' => 'File size',
'6815ac1c' => 'more available',
'60d441bc' => 'View',
'54a16e99' => 'Logs - View',
'2099e6cd' => 'Download',
'3036610z' => 'Additional files',
'a50ba410' => 'Open',
'19e444f0' => 'Unfortunately, the requested file cannot be opened due to its file size (&lt; %s).',
'6246c405' => 'Log not found',
'03972bf6' => 'Unfortunately, the specified log could not be found or opened!',
'81c1cc42' => 'Data',
'7054e2c8' => 'Packets',
'c6e55e97' => 'Network data - %%s',
'c85db4fc' => 'Network packets - %%s',
'02c1e560' => 'Data (MB)',
'78ce56f4' => 'Sent packets',
'509c39f5' => 'Received packets',
'5b345635' => 'Pi Control Beta',
'714afec3' => 'With the participation in Pi Control Beta, you will get an initial insight into upcoming functions and features, even before the final release of Pi Control. By participating, you will also receive regular and stable updates, in addition to the updates for the beta.<br />You can withdraw from Pi Control beta at any time, but you cannot downgrade to an older/regular version. Afterwards, you will receive the stable updates as usual.',
'6625894z' => 'NOTE: During the beta, Pi Control may appear unexpectedly, either by mistake or data loss (Pi Control only). Please send me your feedback (see below).',
'a2d6a573' => 'Join Pi Control Beta',
'df5b26ea' => 'Leave Pi Control Beta',
'68507e1d' => 'Successfully resigned',
'a1638677' => 'You have successfully resigned from Pi Control Beta. From now on you get only stable updates.',
'c1cde0d1' => 'Successfully participated',
'557d925e' => 'Thank you for your participation in Pi Control Beta. From now on you get beta updates.',
'8832e0ab' => 'There is no update available at the moment!'
);
?>

View File

@@ -0,0 +1,150 @@
<?php
if (!defined('PICONTROL')) exit();
class API
{
// Startzeit
private $startTime = 0;
// Statuscode
private $status = 200;
// Daten
private $dataArray = array();
// Fehler
private $error = array();
/**
* Konstrukter, welcher die Startzeit für die Lauftzeit festlegt.
*
* <code>$api = new API;</code>
*/
function __construct()
{
$this->startTime = microtime(true);
}
/**
* Fügt ein Element hinzu.
*
* <code>$api->addData('Key', 'Wert');</code>
*
* @param string $key Schlüsselwert
* @param string|array|bool $value Wert
* @return bool
*/
public function addData($key, $value)
{
if (!empty($this->error))
return false;
$dummyStatus = $this->status;
$this->status = 500;
if (($key = trim($key)) == '')
return false;
$splits = explode('.', $key);
switch (count($splits))
{
case 1:
$this->dataArray[$splits[0]] = $value;
break;
case 2:
if ($splits[1] == '')
$this->dataArray[$splits[0]][] = $value;
else
$this->dataArray[$splits[0]][$splits[1]] = $value;
break;
case 3:
if ($splits[2] == '')
$this->dataArray[$splits[0]][$splits[1]][] = $value;
else
$this->dataArray[$splits[0]][$splits[1]][$splits[2]] = $value;
break;
default:
return false;
}
$this->status = $dummyStatus;
return true;
}
/**
* Setzt den Statuscode.
*
* <code>$api->setStatus(200);</code>
*
* @param int $status Statuscode
* @return bool
*/
public function setStatus($status)
{
if (!is_int($status))
return false;
$this->status = $status;
return true;
}
/**
* Setzt eine Fehlermeldung.
*
* <code>$api->setError('client', 'Falsche Benutzereingabe!', 500);</code>
*
* @param string $type Fehlertyp
* @param string $message Fehlernachricht
* @param int $status Statuscode
* @return bool
*/
public function setError($type, $message, $status = 500)
{
if (($type = trim($type)) == '')
return false;
if (($message = trim($message)) == '')
return false;
if (!is_int($status))
return false;
header('HTTP/1.0 '.$status);
$this->error = array('type' => $type, 'message' => $message);
$this->status = $status;
return true;
}
/**
* Erzeugt das fertige JSON und gibt dieses anschließend aus.
*
* <code>$api->display(true);</code>
*
* @param bool $prettyPrint Eingerückte Ausgabe des JSON
* @return bool Ausgabe erfolgt mit "echo".
*/
public function display($prettyPrint = false)
{
header('Content-Type: application/json');
$executionTime = microtime(true) - $this->startTime;
if (empty($this->error))
echo json_encode(array('data' => $this->dataArray, 'executionTime' => $executionTime, 'status' => $this->status), ($prettyPrint != false) ? JSON_PRETTY_PRINT : 0);
else
echo json_encode(array('error' => $this->error, 'executionTime' => $executionTime, 'status' => $this->status), ($prettyPrint != false) ? JSON_PRETTY_PRINT : 0);
return true;
}
}
?>

149
resources/library/cache/cache.class.php vendored Normal file
View File

@@ -0,0 +1,149 @@
<?php
if (!defined('PICONTROL')) exit();
class Cache
{
const FILE = 0;
const EXECUTION = 1;
const EXECUTION_NOCACHE = 2;
private $name, $lifetime, $content, $type, $stream, $loadType = self::FILE, $efFunction, $efArgs, $modificationTime = 0, $statusCode = 0;
private $cachePath = CACHE_PATH;
private $fileSuffix = '.cache.php';
public function __construct()
{
if (!func_num_args() >= 3)
{
$this->statusCode = 1;
return;
}
$args = func_get_args();
$this->name = $args[0];
$function = $args[1];
$lifetime = 0;
unset($args[0], $args[1]);
$this->efFunction = $function;
$this->efArgs = $args;
if (getConfig('cache:activation.cache', 'false') == 'false' || getConfig('cache:activation.'.$this->name, 'false') == 'false')
{
$this->loadType = self::EXECUTION_NOCACHE;
return;
}
if (($cLifetime = getConfig('cache:lifetime.'.$this->name, 0)) != 0)
$lifetime = $cLifetime * 60;
if (file_exists($this->cachePath.$this->name.$this->fileSuffix) && filemtime($this->cachePath.$this->name.$this->fileSuffix) > time() - $lifetime)
return;
$this->loadType = self::EXECUTION;
}
private function executeFunction()
{
$result = call_user_func_array($this->efFunction, $this->efArgs);
$this->setContent($result);
}
public function setName($name)
{
$this->name = $name;
}
public function setContent($content)
{
$this->content = serialize($content);
if ($this->loadType == self::FILE || $this->loadType == self::EXECUTION)
$this->statusCode = $this->saveToFile();
}
public function getContent()
{
return unserialize($this->content);
}
public function getStatusCode()
{
return $this->statusCode;
}
public function load()
{
if ($this->loadType == self::FILE)
$this->statusCode = $this->loadFromFile();
elseif ($this->loadType == self::EXECUTION || $this->loadType == self::EXECUTION_NOCACHE)
$this->statusCode = $this->executeFunction();
return false;
}
private function saveToFile()
{
if (($this->stream = fopen($this->cachePath.$this->name.$this->fileSuffix, 'w')) === false)
return 1;
if (flock($this->stream, LOCK_EX) === false)
return 2;
if (fwrite($this->stream, $this->content) === false)
return 3;
if (flock($this->stream, LOCK_UN) === false)
return 4;
fclose($this->stream);
if (touch($this->cachePath.$this->name.$this->fileSuffix) === false)
return 5;
return 0;
}
private function loadFromFile()
{
if (!file_exists($this->cachePath.$this->name.$this->fileSuffix) || !is_writable($this->cachePath.$this->name.$this->fileSuffix))
return 6;
if (($this->stream = fopen($this->cachePath.$this->name.$this->fileSuffix, 'r')) === false)
return 7;
if (flock($this->stream, LOCK_SH) === false)
return 8;
$data = '';
while (!feof($this->stream))
$data .= fread($this->stream, 512);
if (flock($this->stream, LOCK_UN) === false)
return 9;
fclose($this->stream);
$this->content = $data;
$this->modificationTime = filemtime($this->cachePath.$this->name.$this->fileSuffix);
return 0;
}
public function displayHint($boolean = false)
{
if ($this->statusCode != 0 || $this->loadType == self::EXECUTION || $this->loadType == self::EXECUTION_NOCACHE)
return NULL;
if ($boolean == false)
return '<div><span class="cached" title="'._t('Stand').': '.formatTime($this->modificationTime).'"><span>'._t('Cached').'</span><a href="?s=settings&amp;do=cache&amp;clear='.$this->name.'&amp;redirect='.urlencode($_SERVER['QUERY_STRING']).'">'._t('Aktualisieren').'</a></span></div>';
else
return array('name' => $this->name, 'modificationTime' => $this->modificationTime);
}
public function clear()
{
return unlink($this->cachePath.$this->name.$this->fileSuffix);
}
}
?>

View File

@@ -0,0 +1,38 @@
<?php
if (!defined('PICONTROL')) exit();
function getCacheList()
{
$fileSuffix = '.cache.php';
$cacheArray = array('usb_devices' => array(), 'users' => array(), 'weather' => array());
foreach ($cacheArray as $name => $info)
{
$cacheArray[$name]['active'] = (getConfig('cache:activation.'.$name, 'false') == 'true') ? true : false;
$cacheArray[$name]['lifetime'] = getConfig('cache:lifetime.'.$name, 0);
if (file_exists(CACHE_PATH.$name.$fileSuffix) && is_file(CACHE_PATH.$name.$fileSuffix))
{
$cacheArray[$name]['filesize'] = filesize(CACHE_PATH.$name.$fileSuffix);
$cacheArray[$name]['modification'] = filemtime(CACHE_PATH.$name.$fileSuffix);
}
}
return $cacheArray;
}
function getCacheName($file)
{
switch ($file)
{
case 'usb_devices':
return _t('Angeschlossene Ger&auml;te');
case 'users':
return _t('Alle Benutzer');
case 'weather':
return _t('Wetter');
default:
return $file;
}
}
?>

View File

@@ -0,0 +1,121 @@
<?php
if (!defined('PICONTROL')) exit();
class Cron
{
private $cronFile, $cronPath = CRON_PATH, $interval, $allFiles = array(), $sourceFileFile = '';
public function setName($file = '')
{
if (defined('PLUGIN_ID'))
$file = 'plugin.'.PLUGIN_ID.'.'.$file;
$this->cronFile = $file;
}
public function setPath($path = '')
{
$this->cronPath = realpath($path).'/';
}
public function isExists()
{
if (empty($this->allFiles))
$this->allFiles();
if (!empty($this->cronFile) && array_key_exists($this->cronFile, $this->allFiles))
return true;
return false;
}
public function getInterval()
{
if (empty($this->allFiles))
$this->allFiles();
if (!empty($this->cronFile) && array_key_exists($this->cronFile, $this->allFiles))
{
$this->interval = $this->allFiles[$this->cronFile];
return $this->interval;
}
return false;
}
public function setInterval($interval = 60)
{
$this->interval = $interval;
}
public function save()
{
if ($this->sourceFile != '' && $this->interval != '' && $this->cronFile != '')
{
if (symlink($this->sourceFile, $this->cronPath.$this->interval.'-'.$this->cronFile.'.php'))
{
$this->allFiles = '';
return true;
}
}
return false;
}
public function setSource($file = '')
{
$this->sourceFile = $file;
}
public function delete()
{
if (unlink($this->cronPath.$this->interval.'-'.$this->cronFile.'.php'))
{
$this->allFiles = '';
return true;
}
return false;
}
public function getAllFiles()
{
if (empty($this->allFiles))
$this->allFiles();
return $this->allFiles;
}
private function allFiles()
{
if (!function_exists('cube'))
{
function cube($n)
{
$exp = explode('-', $n);
$int = $exp[0];
unset($exp[0]);
return array($int, substr(implode('', $exp), 0, -4));
}
}
$folder = $this->cronPath;
$fileArray = array();
foreach (@scandir($folder) as $file)
{
if ($file[0] != '.')
{
if (is_file($folder.'/'.$file) && $file != 'init.php')
{
$fileArray[] = $file;
}
}
}
foreach(array_map('cube', $fileArray) as $arr_map)
$this->allFiles[$arr_map[1]] = $arr_map[0];
}
}
?>

View File

@@ -0,0 +1,196 @@
<?php
if (!defined('PICONTROL')) exit();
defined('HTTP_GET') or define('HTTP_GET', 'GET');
defined('HTTP_POST') or define('HTTP_POST', 'POST');
defined('HTTP_PUT') or define('HTTP_PUT', 'PUT');
defined('HTTP_DELETE') or define('HTTP_DELETE', 'DELETE');
class cURL
{
private $handler, $result, $info, $method = HTTP_GET, $url, $parameter = array(), $parameterRaw = '', $header = array(), $statusCode = 0, $customStatusCode = 0;
public function __construct($url, $method = HTTP_GET, $parameter = NULL)
{
$this->setUrl($url);
$this->setMethod($method);
$this->addParameter($parameter);
}
public function execute()
{
$this->handler = curl_init();
curl_setopt($this->handler, CURLOPT_URL, $this->url);
curl_setopt($this->handler, CURLOPT_CUSTOMREQUEST, $this->method);
curl_setopt($this->handler, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($this->handler, CURLOPT_TIMEOUT, 3);
curl_setopt($this->handler, CURLOPT_FOLLOWLOCATION, true);
if ($this->method != HTTP_GET && !empty($this->parameter))
{
curl_setopt($this->handler, CURLOPT_POST, count($this->parameter));
curl_setopt($this->handler, CURLOPT_POSTFIELDS, http_build_query($this->parameter));
}
if ($this->method != HTTP_GET && !empty($this->parameterRaw))
{
curl_setopt($this->handler, CURLOPT_POST, 1);
curl_setopt($this->handler, CURLOPT_POSTFIELDS, $this->parameterRaw);
}
if (!empty($this->header))
curl_setopt($this->handler, CURLOPT_HTTPHEADER, $this->header);
curl_setopt($this->handler, CURLOPT_RETURNTRANSFER, true);
if (($data = curl_exec($this->handler)) === false)
{
if (curl_errno($this->handler))
$this->customStatusCode = curl_errno($this->handler);
$this->info = curl_getinfo($this->handler);
curl_close($this->handler);
return false;
}
$this->info = curl_getinfo($this->handler);
curl_close($this->handler);
$this->result = $data;
}
public function setUrl($url)
{
if (($url = trim($url)) == '')
return $this->setCustomStatusCode(100);
$this->url = $url;
}
public function addParameter($parameter)
{
if (!is_array($parameter))
return false;
$this->parameter += $parameter;
}
public function setParameterRaw($parameter)
{
$this->parameterRaw = $parameter;
}
public function addHeader($header)
{
if (!is_array($header))
return false;
$this->header += $header;
}
public function setMethod($method)
{
if (!in_array($method, array(HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_DELETE)))
return false;
$this->method = $method;
}
public function getResult(&$result = -1, $jsonFormat = true)
{
if ($result === -1)
{
if ($jsonFormat === true)
return json_decode($this->result, true);
else
return $this->result;
}
else
{
if ($jsonFormat === true)
{
$result = json_decode($this->result, true);
return json_last_error();
}
else
$result = $this->result;
}
}
public function getInfo($name)
{
return $this->info[$name];
}
public function getInfos()
{
return $this->info;
}
public function getStatusCode()
{
return $this->info['http_code'];
}
private function setCustomStatusCode($code = -1)
{
$this->customStatusCode = $code;
return;
}
public function downloadFile($destination)
{
if (empty($destination))
return false;
if (!($filestream = fopen($destination, 'w+')))
return 1;
// Setze Zeitlimit auf unendlich
set_time_limit(0);
$this->handler = curl_init();
curl_setopt($this->handler, CURLOPT_URL, $this->url);
curl_setopt($this->handler, CURLOPT_FILE, $filestream);
curl_setopt($this->handler, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($this->handler, CURLOPT_TIMEOUT, 50);
curl_setopt($this->handler, CURLOPT_FOLLOWLOCATION, true);
// Pruefe ob Datei blockiert
$startTime = microtime();
do
{
$canWrite = flock($filestream, LOCK_EX);
if (!$canWrite)
usleep(round(rand(0, 100)*1000));
}
while ((!$canWrite) && ((microtime()-$startTime) < 2000));
if (!$canWrite)
return 2;
if (($data = curl_exec($this->handler)) === false)
{
if (curl_errno($this->handler))
$this->customStatusCode = curl_errno($this->handler);
$this->info = curl_getinfo($this->handler);
curl_close($this->handler);
flock($filestream, LOCK_UN);
fclose($filestream);
return false;
}
$this->info = curl_getinfo($this->handler);
curl_close($this->handler);
flock($filestream, LOCK_UN);
fclose($filestream);
return true;
}
}
?>

View File

@@ -0,0 +1,389 @@
<?php
if (!defined('PICONTROL')) exit();
class LogController
{
private $logPath;
private $logs = [];
private $sshAvailable = false;
function __construct($path)
{
global $tpl;
// Pruefe SSH
$this->sshAvailable = ($tpl->getSSHResource() instanceof Net_SSH2) ? true : false;
$this->logPath = realpath($path).'/';
if (!file_exists($this->logPath))
return 1;
if (!is_readable($this->logPath))
return 2;
$this->scanDirectory($this->logPath);
}
public function getAll()
{
return $this->logs;
}
public function getAllArray()
{
$output = [];
foreach ($this->logs as $log)
$output[] = $log->toArray();
return $output;
}
public function getGroupFromRelativePath($path)
{
$log = $this->getGroupFromPath($this->logPath.$path);
return $log;
}
public function getLogFromRelativePath($path)
{
if (!($log = $this->getGroupFromPath($this->logPath.$path)))
return false;
$log = $log->getEntry($this->getFilenameFromPath($path));
return $log;
}
private function scanDirectory($path)
{
$path = realpath($path).'/';
foreach (scandir($path) as $name)
{
if (in_array($name, ['.', '..']))
continue;
if (is_dir($path.$name))
{
$this->scanDirectory($path.$name);
continue;
}
elseif (is_file($path.$name))
$this->addLogFromPath($path.$name);
}
}
private function addLogFromPath($path)
{
$path = realpath($path);
if (!file_exists($path))
return 1;
$group = $this->getGroupFromPath($path);
if ($group instanceof LogGroup)
{
$filename = $this->getFilenameFromPath($path);
$newEntry = new LogEntry();
$newEntry->setFilename($filename);
$group->addEntry($newEntry);
}
elseif ($group === false)
{
$groupName = $this->getGroupNameFromPath($path);
$groupPath = $this->getGroupPathFromPath($path);
$newGroup = new LogGroup();
$newGroup->setName($groupName);
$newGroup->setPath($groupPath);
$newGroup->setRelativePath(preg_replace('#^'.preg_quote($this->logPath).'#', '', $groupPath));
$newGroup->setSshAvailable($this->sshAvailable);
$this->logs[] = $newGroup;
// Eintrag hinzufuegen
$filename = $this->getFilenameFromPath($path);
$newEntry = new LogEntry();
$newEntry->setFilename($filename);
$newGroup->addEntry($newEntry);
}
return 1;
}
private function getFilenameFromPath($path)
{
return basename($path);
}
private function getGroupFromPath($path)
{
$path = realpath($path);
$groupName = $this->getGroupNameFromPath($path);
$groupPath = $this->getGroupPathFromPath($path);
foreach ($this->logs as $log)
{
if ($log->name == $groupName && $log->path == $groupPath)
return $log;
}
return false;
}
private function getGroupNameFromPath($path)
{
$path = realpath($path);
$p_match = preg_match('#^(.*\/)?([^\/]*)$#i', $path, $matches);
if ($p_match === false || count($matches) != 3)
return 1;
$p_match = preg_match('#(.+?)(?:\.(?:old|[0-9]+|[0-9]+\.gz))?$#i', $matches[2], $matches);
if ($p_match === false || count($matches) != 2)
return 2;
return $matches[1];
}
private function getGroupPathFromPath($path)
{
$path = realpath($path);
$p_match = preg_match('#^(.*\/)?([^\/]*)$#i', $path, $matches);
if ($p_match === false || count($matches) != 3)
return 1;
return $matches[1];
}
public function setLogPath($path)
{
$this->logPath = $path;
}
public function readLog($path) {
global $tpl;
if ($this->sshAvailable === true)
{
if (substr($path, -3) == '.gz') {
list ($logOutput, , ) = $tpl->executeSSH('zcat '.escapeshellarg($path));
list ($logLines, , ) = $tpl->executeSSH('zcat '.escapeshellarg($path).' | wc -l');
}
else
{
list ($logOutput, , ) = $tpl->executeSSH('cat '.escapeshellarg($path));
list ($logLines, , ) = $tpl->executeSSH('cat '.escapeshellarg($path).' | wc -l');
}
}
else
{
if (substr($path, -3) == '.gz') {
$logOutput = shell_exec('zcat '.escapeshellarg($path));
$logLines = shell_exec('zcat '.escapeshellarg($path).' | wc -l');
}
else {
$logOutput = shell_exec('cat '.escapeshellarg($path));
$logLines = shell_exec('cat '.escapeshellarg($path).' | wc -l');
}
}
return array('output' => $logOutput, 'lines' => trim($logLines));
}
public function isSshAvailable()
{
return $this->sshAvailable;
}
}
class LogGroup
{
public $name;
public $path;
public $relativePath;
private $entries = [];
private $sshAvailable = false;
public function addEntry(LogEntry $entry)
{
$entry->setLogGroup($this);
$this->entries[] = $entry;
}
public function getEntry($entry)
{
if (is_int($entry))
return $this->entries[$entry];
elseif (is_string($entry))
{
foreach ($this->entries as $entry_)
{
if ($entry_->getFilename() == $entry)
return $entry_;
}
}
return false;
}
public function getMain()
{
return $this->entries[0];
}
public function getAll($withoutMain = false)
{
if ($withoutMain === true)
{
$dummy = $this->entries;
unset($dummy[0]);
return $dummy;
}
return $this->entries;
}
public function getCount($withoutMain = false)
{
return count($this->getAll($withoutMain));
}
public function setName($name)
{
$this->name = $name;
}
public function setPath($path)
{
$this->path = realpath($path).'/';
}
public function setRelativePath($relativePath)
{
$this->relativePath = $relativePath;
}
public function getName()
{
return $this->name;
}
public function getPath()
{
return $this->path;
}
public function getRelativePath()
{
return $this->relativePath;
}
public function isSshAvailable()
{
return $this->sshAvailable;
}
public function setSshAvailable($sshAvailable)
{
$this->sshAvailable = $sshAvailable;
}
public function toArray() {
$entries = [];
foreach ($this->entries as $entry)
$entries[] = $entry->toArray();
return [
'name' => $this->name,
'path' => $this->path,
'relativePath' => $this->relativePath,
'entries' => $entries
];
}
}
class LogEntry
{
private $logGroup;
private $filename;
public function setLogGroup(LogGroup $logGroup)
{
$this->logGroup = $logGroup;
}
public function setFilename($filename)
{
$this->filename = $filename;
}
public function getLogGroup()
{
return $this->logGroup;
}
public function getFilename()
{
return $this->filename;
}
public function getReadable()
{
if ($this->logGroup->isSshAvailable())
return true;
return is_readable($this->getPath());
}
public function getFilesize()
{
return filesize($this->getPath());
}
public function getModified()
{
return filemtime($this->getPath());
}
public function getPath()
{
return $this->logGroup->getPath().$this->filename;
}
public function getRelativePath()
{
return $this->logGroup->getRelativePath().$this->filename;
}
public function toArray() {
return [
'filename' => $this->filename,
'readable' => $this->getReadable(),
'filesize' => $this->getFilesize(),
'modified' => $this->getModified(),
'path' => $this->getPath(),
'relativePath' => $this->getRelativePath()
];
}
}
?>

View File

@@ -0,0 +1,116 @@
<?php
if (!defined('PICONTROL')) exit();
function getLogs($logPath = '/var/log/', $startPath = null)
{
$startPath = ($startPath === null) ? $logPath : $startPath;
if (!file_exists($logPath) || !is_readable($logPath))
return 0;
$logs = [];
foreach (scandir($logPath) as $log)
{
if (in_array($log, ['.', '..']))
continue;
if (is_dir($logPath.$log))
{
$logsDirectory = getLogs($logPath.$log.'/', $startPath);
$logs = array_merge($logs, is_array($logsDirectory) ? $logsDirectory : []);
continue;
}
$logName = preg_replace('#(.+?)\.(old|[0-9]+|[0-9]+\.gz)$#i', '$1', $log);
$key = array_search($logName, array_column($logs, 'name'));
if ($key !== false)
{
$logs[$key]['additional'][] = [
'filename' => $log,
'readable' => is_readable($logPath.$log),
'modified' => filemtime($logPath.$log),
'filesize' => filesize($logPath.$log)
];
continue;
}
$logs[] = [
'name' => $logName,
'filename' => $log,
'path' => $logPath,
'directory' => preg_replace('#^'.preg_quote($startPath).'#', '', $logPath),
'readable' => is_readable($logPath.$log),
'modified' => filemtime($logPath.$log),
'filesize' => filesize($logPath.$log),
'additional' => []
];
}
return $logs;
}
function getLog($log, $logPath = '/var/log/', $startPath = null)
{
$logs = getLogs($logPath);
// $split = [total, directory, file]
$match = preg_match('#^(.*\/)?([^\/]*)$#i', $log, $split);
if ($match !== 1 || count($split) != 3)
return 0;
$logName = preg_replace('#(.+?)\.(old|[0-9]+|[0-9]+\.gz)$#i', '$1', $split[2]);
if ($split[1] != '')
{
foreach ($logs as $log_)
{
}
$keyDirectory = array_search($split[1], array_column($logs, 'directory'));
if ($keyDirectory === false)
return 1;
var_dump($keyDirectory);
$logs = $logs[$keyDirectory];
}
$key = array_search($logName, array_column($logs, 'name'));
var_dump($key, $logName, $logs);
$logs = $logs[$key];
if ($logs['filename'] == $split[2])
{
$log = [
'filename' => $logs['filename'],
'readable' => $logs['readable'],
'modified' => $logs['modified'],
'filesize' => $logs['filesize']
];
}
else
{
$key = array_search($split[2], array_column($logs['additional'], 'filename'));
var_dump($logs);
$logs = $logs['additional'][$key];
$log = [
'filename' => $logs['filename'],
'readable' => $logs['readable'],
'modified' => $logs['modified'],
'filesize' => $logs['filesize']
];
}
return [$log, $logs];
}

View File

@@ -0,0 +1,62 @@
<?php
if (!defined('PICONTROL')) exit();
(include_once realpath(dirname(__FILE__)).'/../../init.php') or die('Error: 0x0010');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0011');
$logout = true;
if (isset($_COOKIE['_pi-control_login']) || isset($_POST['token']))
{
$uniqid = isset($_COOKIE['_pi-control_login']) ? $_COOKIE['_pi-control_login'] : $_POST['token'];
$tokenCreated = getConfig('login:token_'.$uniqid.'.created', 0);
$tokenRememberMe = getConfig('login:token_'.$uniqid.'.remember_me', 'false');
$tokenUsername = getConfig('login:token_'.$uniqid.'.username', '');
$tokenLastLogin = getConfig('user:user_'.$tokenUsername.'.last_login', 0);
if ($tokenCreated == 0 || ($tokenCreated < time()-60*60*12 && $tokenRememberMe != 'true'))
{
removeConfig('login:token_'.$uniqid);
if (isset($_COOKIE['_pi-control_login']))
setcookie('_pi-control_login', '', time()-60);
}
elseif ($tokenLastLogin < time()-60*60)
{
setConfig('user:user_'.$tokenUsername.'.last_login', time());
$logout = false;
}
else
$logout = false;
}
if (isset($_POST['token']) && $logout === true)
{
if (isset($authentificationMsg))
die($authentificationMsg);
else
{
header('HTTP/1.0 403 Forbidden');
exit();
}
}
elseif ((!isset($_COOKIE['_pi-control_login']) || $logout === true) && !isset($_POST['token']))
{
if (isset($authentificationMsg))
die($authentificationMsg);
else
{
$referer = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
if ($referer != '')
$referer = '&referer='.urlencode($referer);
$dir = '';
for ($i = 0; $i < substr_count(str_replace(realpath(dirname(__FILE__).'/../../../').'/', '', realpath(dirname($_SERVER["SCRIPT_FILENAME"])).'/'), '/'); $i += 1)
$dir .= '../';
header('Location: '.$dir.'?i=login'.$referer);
exit();
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
<?php
/**
* A Compatibility library with PHP 5.5's simplified password hashing API.
*
* @author Anthony Ferrara <ircmaxell@php.net>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @copyright 2012 The Authors
*/
namespace {
if (!defined('PICONTROL')) exit(); // Ausnahme, da namespace
if (!defined('PASSWORD_BCRYPT')) {
/**
* PHPUnit Process isolation caches constants, but not function declarations.
* So we need to check if the constants are defined separately from
* the functions to enable supporting process isolation in userland
* code.
*/
define('PASSWORD_BCRYPT', 1);
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
define('PASSWORD_BCRYPT_DEFAULT_COST', 10);
}
if (!function_exists('password_hash')) {
/**
* Hash the password using the specified algorithm
*
* @param string $password The password to hash
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
* @param array $options The options for the algorithm to use
*
* @return string|false The hashed password, or false on error.
*/
function password_hash($password, $algo, array $options = array()) {
if (!function_exists('crypt')) {
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
return null;
}
if (is_null($password) || is_int($password)) {
$password = (string) $password;
}
if (!is_string($password)) {
trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
return null;
}
if (!is_int($algo)) {
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
return null;
}
$resultLength = 0;
switch ($algo) {
case PASSWORD_BCRYPT:
$cost = PASSWORD_BCRYPT_DEFAULT_COST;
if (isset($options['cost'])) {
$cost = (int) $options['cost'];
if ($cost < 4 || $cost > 31) {
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
return null;
}
}
// The length of salt to generate
$raw_salt_len = 16;
// The length required in the final serialization
$required_salt_len = 22;
$hash_format = sprintf("$2y$%02d$", $cost);
// The expected length of the final crypt() output
$resultLength = 60;
break;
default:
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
return null;
}
$salt_req_encoding = false;
if (isset($options['salt'])) {
switch (gettype($options['salt'])) {
case 'NULL':
case 'boolean':
case 'integer':
case 'double':
case 'string':
$salt = (string) $options['salt'];
break;
case 'object':
if (method_exists($options['salt'], '__tostring')) {
$salt = (string) $options['salt'];
break;
}
case 'array':
case 'resource':
default:
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
return null;
}
if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) {
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING);
return null;
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
$salt_req_encoding = true;
}
} else {
$buffer = '';
$buffer_valid = false;
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
$buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
if ($buffer) {
$buffer_valid = true;
}
}
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
$strong = false;
$buffer = openssl_random_pseudo_bytes($raw_salt_len, $strong);
if ($buffer && $strong) {
$buffer_valid = true;
}
}
if (!$buffer_valid && @is_readable('/dev/urandom')) {
$file = fopen('/dev/urandom', 'r');
$read = 0;
$local_buffer = '';
while ($read < $raw_salt_len) {
$local_buffer .= fread($file, $raw_salt_len - $read);
$read = PasswordCompat\binary\_strlen($local_buffer);
}
fclose($file);
if ($read >= $raw_salt_len) {
$buffer_valid = true;
}
$buffer = str_pad($buffer, $raw_salt_len, "\0") ^ str_pad($local_buffer, $raw_salt_len, "\0");
}
if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) {
$buffer_length = PasswordCompat\binary\_strlen($buffer);
for ($i = 0; $i < $raw_salt_len; $i++) {
if ($i < $buffer_length) {
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
} else {
$buffer .= chr(mt_rand(0, 255));
}
}
}
$salt = $buffer;
$salt_req_encoding = true;
}
if ($salt_req_encoding) {
// encode string with the Base64 variant used by crypt
$base64_digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$bcrypt64_digits =
'./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$base64_string = base64_encode($salt);
$salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
}
$salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len);
$hash = $hash_format . $salt;
$ret = crypt($password, $hash);
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) {
return false;
}
return $ret;
}
/**
* Get information about the password hash. Returns an array of the information
* that was used to generate the password hash.
*
* array(
* 'algo' => 1,
* 'algoName' => 'bcrypt',
* 'options' => array(
* 'cost' => PASSWORD_BCRYPT_DEFAULT_COST,
* ),
* )
*
* @param string $hash The password hash to extract info from
*
* @return array The array of information about the hash.
*/
function password_get_info($hash) {
$return = array(
'algo' => 0,
'algoName' => 'unknown',
'options' => array(),
);
if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) {
$return['algo'] = PASSWORD_BCRYPT;
$return['algoName'] = 'bcrypt';
list($cost) = sscanf($hash, "$2y$%d$");
$return['options']['cost'] = $cost;
}
return $return;
}
/**
* Determine if the password hash needs to be rehashed according to the options provided
*
* If the answer is true, after validating the password using password_verify, rehash it.
*
* @param string $hash The hash to test
* @param int $algo The algorithm used for new password hashes
* @param array $options The options array passed to password_hash
*
* @return boolean True if the password needs to be rehashed.
*/
function password_needs_rehash($hash, $algo, array $options = array()) {
$info = password_get_info($hash);
if ($info['algo'] !== (int) $algo) {
return true;
}
switch ($algo) {
case PASSWORD_BCRYPT:
$cost = isset($options['cost']) ? (int) $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST;
if ($cost !== $info['options']['cost']) {
return true;
}
break;
}
return false;
}
/**
* Verify a password against a hash using a timing attack resistant approach
*
* @param string $password The password to verify
* @param string $hash The hash to verify against
*
* @return boolean If the password matches the hash
*/
function password_verify($password, $hash) {
if (!function_exists('crypt')) {
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
return false;
}
$ret = crypt($password, $hash);
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) {
return false;
}
$status = 0;
for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) {
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
}
return $status === 0;
}
}
}
namespace PasswordCompat\binary {
if (!function_exists('PasswordCompat\\binary\\_strlen')) {
/**
* Count the number of bytes in a string
*
* We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension.
* In this case, strlen() will count the number of *characters* based on the internal encoding. A
* sequence of bytes might be regarded as a single multibyte character.
*
* @param string $binary_string The input string
*
* @internal
* @return int The number of bytes
*/
function _strlen($binary_string) {
if (function_exists('mb_strlen')) {
return mb_strlen($binary_string, '8bit');
}
return strlen($binary_string);
}
/**
* Get a substring based on byte limits
*
* @see _strlen()
*
* @param string $binary_string The input string
* @param int $start
* @param int $length
*
* @internal
* @return string The substring
*/
function _substr($binary_string, $start, $length) {
if (function_exists('mb_substr')) {
return mb_substr($binary_string, $start, $length, '8bit');
}
return substr($binary_string, $start, $length);
}
/**
* Check if current PHP version is compatible with the library
*
* @return boolean the check result
*/
function check() {
static $pass = NULL;
if (is_null($pass)) {
if (function_exists('crypt')) {
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = $test == $hash;
} else {
$pass = false;
}
}
return $pass;
}
}
}
?>

View File

@@ -0,0 +1,448 @@
<?php
if (!defined('PICONTROL')) exit();
function rpi_getRuntime()
{
$runtime = trim(@shell_exec('cat /proc/uptime | awk -F \'.\' \'{print $1}\''));
return $runtime;
}
function rpi_getHostname()
{
$host = trim(@shell_exec('cat /proc/sys/kernel/hostname'));
return $host;
}
function rpi_getHostAddr()
{
if (!isset($_SERVER['SERVER_ADDR']))
return 'unknown';
if (!$ip = $_SERVER['SERVER_ADDR'])
return gethostbyname($this->getHostname());
return $ip;
}
function rpi_getCoreTemprature()
{
$file = 85000;
while ($file == 85000)
$file = @shell_exec('cat /sys/class/thermal/thermal_zone0/temp');
if ($file != false)
return round((trim($file)/1000), 2);
return 0;
}
function rpi_getCpuClock()
{
$file = shell_exec('cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq');
if ($file !== false)
return (int) round(trim($file)/1000);
return 0;
}
function rpi_getCpuMinClock()
{
$file = shell_exec('cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq');
if ($file !== false)
return (int) round(trim($file)/1000);
return 0;
}
function rpi_getCpuMaxClock()
{
$file = shell_exec('cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq');
if ($file !== false)
return (int) round(trim($file)/1000);
return 0;
}
function rpi_getCPUType()
{
$file = shell_exec('cat /proc/cpuinfo');
preg_match('#Hardware\s*:\s*([^\s]+)#i', $file, $match);
if (isset($match[1]))
return $match[1];
return NULL;
}
function rpi_getCpuModel()
{
$model = trim(@shell_exec('cat /proc/cpuinfo | grep -m 1 "model name" | tr -d " " | cut -d ":" -f 2'));
return $model;
}
function rpi_getCPULoad($accurate = false, $mulitcore = false)
{
$return = NULL;
if ($accurate === true)
$file = shell_exec('cat /proc/stat; sleep 2; echo "##--##"; cat /proc/stat');
else
$file = shell_exec('cat /proc/stat; sleep 0.5; echo "##--##"; cat /proc/stat');
$file = explode('##--##', $file);
if (!isset($file[0], $file[1]))
return NULL;
preg_match_all('/^cpu[0-9]?(.*)$/im', $file[0], $prevCPUStrings);
preg_match_all('/^cpu[0-9]?(.*)$/im', $file[1], $curCPUStrings);
for ($i = 0; $i < count($prevCPUStrings[0]); $i++)
{
$prevCPU = preg_split('/\s+/', $prevCPUStrings[0][$i]);
$curCPU = preg_split('/\s+/', $curCPUStrings[0][$i]);
if ($prevCPU[0] != 'cpu' && $mulitcore == false)
break;
if (!isset($prevCPU[0], $curCPU[1]) || count($prevCPU) != 11 || count($curCPU) != 11)
return NULL;
$prevIdle = $prevCPU[4] + $prevCPU[5];
$curIdle = $curCPU[4] + $curCPU[5];
$prevNonIdle = $prevCPU[1] + $prevCPU[2] + $prevCPU[3] + $prevCPU[6] + $prevCPU[7] + $prevCPU[8];
$curNonIdle = $curCPU[1] + $curCPU[2] + $curCPU[3] + $curCPU[6] + $curCPU[7] + $curCPU[8];
$prevTotal = $prevIdle + $prevNonIdle;
$curTotal = $curIdle + $curNonIdle;
$total = $curTotal - $prevTotal;
$idle = $curIdle - $prevIdle;
if ($mulitcore == true)
$return[$prevCPU[0]] = (int) round(($total - $idle) / $total * 100);
else
$return = (int) round(($total - $idle) / $total * 100);
}
return $return;
}
function rpi_getDistribution()
{
$distribution = trim(@shell_exec('cat /etc/issue | cut -d " " -f 1-3'));
if ($distribution == '')
{
$distributionString = @shell_exec('cat /etc/*-release | grep PRETTY_NAME');
preg_match('/.*="([\w\s\d\/]*).*"/i', $distributionString, $match);
if (count($match) == 2)
$distribution = trim($match[1]);
else
$distribution = _t('Unbekannt');
}
return $distribution;
}
function rpi_getKernelVersion()
{
$kernel = trim(@shell_exec('cat /proc/version | cut -d " " -f 1,3'));
return $kernel;
}
function rpi_getCountRunningTasks()
{
$tasks = trim(@shell_exec('ps -auxeaf| wc -l'));
return $tasks;
}
function rpi_getCountInstalledPackages()
{
$packages = trim(@shell_exec('dpkg --get-selections | grep -v deinstall | wc -l'));
return $packages;
}
function rpi_getInstalledPackages()
{
@exec('dpkg -l | grep ^ii', $packages);
$packages = array_map(function($package) { return preg_split('/[\s]+/', $package, 5); }, $packages);
return $packages;
}
function rpi_getRpiRevision()
{
$revision = array();
$revision[2] = array('revision' => '0002', 'model' => 'B', 'pcb' => '1.0', 'memory' => 256, 'manufacturer' => '');
$revision[3] = array('revision' => '0003', 'model' => 'B', 'pcb' => '1.0', 'memory' => 256, 'manufacturer' => '');
$revision[4] = array('revision' => '0004', 'model' => 'B', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Sony');
$revision[5] = array('revision' => '0005', 'model' => 'B', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Qisda');
$revision[6] = array('revision' => '0006', 'model' => 'B', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Egoman');
$revision[7] = array('revision' => '0007', 'model' => 'A', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Egoman');
$revision[8] = array('revision' => '0008', 'model' => 'A', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Sony');
$revision[9] = array('revision' => '0009', 'model' => 'A', 'pcb' => '2.0', 'memory' => 256, 'manufacturer' => 'Qisda');
$revision[13] = array('revision' => '000d', 'model' => 'B', 'pcb' => '2.0', 'memory' => 512, 'manufacturer' => 'Egoman');
$revision[14] = array('revision' => '000e', 'model' => 'B', 'pcb' => '2.0', 'memory' => 512, 'manufacturer' => 'Sony');
$revision[15] = array('revision' => '000f', 'model' => 'B', 'pcb' => '2.0', 'memory' => 512, 'manufacturer' => 'Qisda');
$revision[16] = array('revision' => '0010', 'model' => 'B+', 'pcb' => '1.0', 'memory' => 512, 'manufacturer' => 'Sony');
$revision[17] = array('revision' => '0011', 'model' => 'Compute Module', 'pcb' => '1.0', 'memory' => 512, 'manufacturer' => 'Sony');
$revision[18] = array('revision' => '0012', 'model' => 'A+', 'pcb' => '1.0', 'memory' => 256, 'manufacturer' => 'Sony');
$revision[19] = array('revision' => '0013', 'model' => 'B+', 'pcb' => '1.2', 'memory' => 512, 'manufacturer' => 'Embest');
$revision[20] = array('revision' => '0014', 'model' => 'Compute Module', 'pcb' => '1.0', 'memory' => 512, 'manufacturer' => 'Embest');
$revision[21] = array('revision' => '0015', 'model' => 'A+', 'pcb' => '1.1', 'memory' => 256, 'manufacturer' => 'Embest');
$revision_model = array(0 => 'A', 1 => 'B', 2 => 'A+', 3 => 'B+', 4 => 'Pi 2 B', 5 => 'Alpha', 6 => 'Compute Module', 7 => 'Zero', 8 => 'Pi 3 B', 9 => 'Zero', 10 => 'Compute Module 3', 12 => 'Zero W');
$revision_memory = array(0 => 256, 1 => 512, 2 => 1024);
$revision_manufacturer = array(0 => 'Sony', 1 => 'Egoman', 2 => 'Embest', 3 => 'Sony Japan', 4 => 'Embest');
$file = shell_exec('cat /proc/cpuinfo');
preg_match('#\nRevision\s*:\s*([\da-f]+)#i', $file, $match);
/*
* ######
* |||||+- PCB
* ||||+- Model
* |||+- Model
* ||+- Unknown
* |+- Manufacturer
* +- Memory
*/
if (isset($match[1]))
{
if ($match[1][0] == '1' || $match[1][0] == '2')
$match[1] = substr($match[1], 1);
if (strlen($match[1]) == 4)
return $revision[hexdec($match[1])];
elseif (strlen($match[1]) == 6 && $match[1][0] != 'a' && $match[1][0] != '9')
return $revision[hexdec(substr($match[1], -4))];
elseif (strlen($match[1]) == 6)
{
return array('revision' => $match[1],
'model' => $revision_model[hexdec(substr($match[1], 3, 2))],
'pcb' => '1.'.hexdec(substr($match[1], -1)),
'memory' => $revision_memory[bindec(substr(decbin(hexdec(substr($match[1], 0, 1))), 1))],
'manufacturer' => $revision_manufacturer[hexdec(substr($match[1], 1, 1))]);
}
}
return NULL;
}
function rpi_getRpiSerial()
{
$file = shell_exec('cat /proc/cpuinfo');
preg_match('#\nSerial\s*:\s*([\da-f]+)#i', $file, $match);
return $match[1];
}
function rpi_getMemorySplit()
{
$rev = $this->getRpiRevision();
if ($rev >= 7)
{
// 512 MB
$config = @shell_exec('cat /boot/config.txt');
preg_match('#gpu_mem=([0-9]+)#i', $config, $match);
$total = intval($match[1]);
if ($total == 16)
return array('system' => '496 MiB', 'video' => '16 MiB');
elseif ($total == 32)
return array('system' => '480 MiB', 'video' => '32 MiB');
elseif ($total == 64)
return array('system' => '448 MiB', 'video' => '64 MiB');
elseif ($total == 128)
return array('system' => '384 MiB', 'video' => '128 MiB');
return array('system' => '256 MiB', 'video' => '256 MiB');
}
// 256 MB
$mem = $this->getMemoryUsage();
$total = round($mem['total'] / 1024 / 1024, 0);
if ($total <= 128)
return array('system' => '128 MiB', 'video' => '128 MiB');
elseif ($total > 128 && $total <= 192)
return array('system' => '192 MiB', 'video' => '64 MiB');
elseif ($total > 192 && $total <= 224)
return array('system' => '224 MiB', 'video' => '32 MiB');
return array('system' => '240 MiB', 'video' => '16 MiB');
}
function rpi_getMemoryUsage()
{
exec('free -bo 2>/dev/null || free -b', $data);
if (strpos($data[0], 'available') !== false) {
list($type, $total, $used, $free, $shared, $buffers, $available) = preg_split('#\s+#', $data[1]);
$usage = (int) round(($total - $available) / $total * 100);
return array('percent' => $usage, 'total' => $total, 'free' => $available, 'used' => ($total - $available));
}
list($type, $total, $used, $free, $shared, $buffers, $cached) = preg_split('#\s+#', $data[1]);
$usage = (int) round(($used - $buffers - $cached) / $total * 100);
return array('percent' => $usage, 'total' => $total, 'free' => ($free + $buffers + $cached), 'used' => ($used - $buffers - $cached));
}
function rpi_getSwapUsage()
{
exec('free -bo 2>/dev/null || free -b', $data);
list($type, $total, $used, $free) = preg_split('#\s+#', $data[2]);
$usage = (int) round($used / $total * 100);
return array('percent' => $usage, 'total' => $total, 'free' => $free, 'used' => $used);
}
function multiArraySearch($array, $key, $value)
{
foreach ($array as $item)
if (isset($item[$key]) && $item[$key] == $value)
return true;
return false;
}
function rpi_getMemoryInfo()
{
exec('df -lT | grep -vE "tmpfs|rootfs|Filesystem|Dateisystem"', $data);
$devices = array();
$totalSize = 0;
$usedSize = 0;
foreach ($data as $row)
{
list($device, $type, $blocks, $use, $available, $used, $mountpoint) = preg_split('#[\s%]+#i', $row);
if (multiArraySearch($devices, 'device', $device) === false)
{
$totalSize += $blocks * 1024;
$usedSize += $use * 1024;
}
$devices[] = array(
'device' => $device,
'type' => $type,
'total' => $blocks * 1024,
'used' => $use * 1024,
'free' => $available * 1024,
'percent' => (int) round(($use * 100 / $blocks)),
'mountpoint' => $mountpoint
);
}
usort($devices, function($a, $b)
{
return strcasecmp($a['device'], $b['device']);
});
$devices[] = array('total' => $totalSize, 'used' => $usedSize, 'free' => $totalSize - $usedSize, 'percent' => (int) round(($usedSize * 100 / $totalSize)));
return $devices;
}
function rpi_getUsbDevices()
{
exec('lsusb', $data);
$devices = array();
foreach ($data as $row)
{
preg_match('#[0-9a-f]{4}:[0-9a-f]{4}\s+(.+)#i', $row, $match);
if (count($match) == 2)
$devices[] = trim($match[1]);
else
$devices[] = '<'._t('Unbekannt').'>';
}
return $devices;
}
function rpi_getAllUsers()
{
function array_orderby()
{
$args = func_get_args();
$data = array_shift($args);
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}
exec('/usr/bin/who --ips', $dataLoggedIn);
exec('/usr/bin/lastlog | grep -vE "Benutzername|Username" | cut -f 1 -d " "', $dataAllUsers);
$usersLoggedIn = array();
$usersAll = array();
foreach ($dataLoggedIn as $row)
{
$split = preg_split('/\s+/i', $row);
if (count($split) == 6)
$usersLoggedIn[$split[0]][] = array('port' => $split[1], 'lastLogin' => strtotime($split[2].' '.$split[3].' '.$split[4]), 'lastLoginAddress' => $split[5]);
}
foreach ($dataAllUsers as $row)
{
$userLastLoginInformation = '';
$userLastLoginInformation = shell_exec('/usr/bin/last -i -f /var/log/wtmp | grep -m 1 "^'.$row.' "');
if ($userLastLoginInformation == '')
$userLastLoginInformation = shell_exec('/usr/bin/last -i -f /var/log/wtmp.1 | grep -m 1 "^'.$row.' "');
if ($userLastLoginInformation != '')
{
$split = preg_split('/\s+/i', $userLastLoginInformation);
$usersAll[] = array('username' => $row,
'userId' => exec('id -u '.escapeshellarg($row)),
'groupId' => exec('id -g '.escapeshellarg($row)),
'port' => $split[1],
'lastLoginAddress' => $split[2],
'lastLogin' => strtotime($split[4].' '.$split[5].' '.$split[6]),
'isLoggedIn' => isset($usersLoggedIn[$row]) ? true : false,
'loggedIn' => isset($usersLoggedIn[$row]) ? $usersLoggedIn[$row] : array());
}
else
{
$usersAll[] = array('username' => $row,
'userId' => exec('id -u '.escapeshellarg($row)),
'groupId' => exec('id -g '.escapeshellarg($row)),
'port' => '',
'lastLoginAddress' => '',
'lastLogin' => 0,
'isLoggedIn' => isset($usersLoggedIn[$row]) ? true : false);
}
}
$usersAll = array_orderby($usersAll, 'isLoggedIn', SORT_DESC, 'username', SORT_ASC);
return $usersAll;
}
?>

View File

@@ -0,0 +1,30 @@
<?php
if (!defined('PICONTROL')) exit();
$site = array(
'overview' => 'overview.php',
'detailed_overview' => 'detailed_overview.php',
'installed_packages' => 'installed_packages.php',
'network' => 'network.php',
'network_connect' => 'network_connect.php',
'network_configuration' => 'network_configuration.php',
'statistic' => 'statistic.php',
'plugins' => 'plugins.php',
'discover_plugins' => 'discover_plugins.php',
'settings' => 'settings.php',
'ssh_login' => 'ssh_login.php',
'terminal' => 'terminal.php',
'shutdown' => 'shutdown.php',
'users_groups' => 'users_groups.php',
'logs' => 'logs.php',
'processes' => 'processes.php'
);
$include = array(
'login' => 'resources/content/login.php',
'update' => 'resources/update/update_picontrol.php',
'download_plugin' => 'resources/plugins/download_plugin.php',
'update_plugin' => 'resources/plugins/update_plugin.php',
'feedback' => LIBRARY_PATH.'feedback/feedback.php'
);
?>

View File

@@ -0,0 +1,965 @@
<?php
if (!defined('PICONTROL')) exit();
/**
* Beschreibung. Mehr unter: http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.pkg.html
*/
class FileException extends Exception { }
class PiTpl
{
// Sprache
private $tplLanguage = 'de';
private $tplLanguageFileArray = array();
// Pfade
private $tplFolderPath = 'public_html/templates/';
private $tplFileSuffix = '.tpl.php';
private $tplConfigs = array('main', 'cron');
private $tplConfigSuffix = '.config.ini.php';
private $tplLanguagePath = 'resources/languages/';
private $tplFolderPathPlugin = '';
// Laufzeit
private $runtimeStart = 0;
// Template Variablen
private $tplVariables = array();
// Geladene Elemente
private $tplLoaded = false;
private $tplLoadedHeader = false;
private $tplLoadedFooter = false;
// Lade Elemente?
private $tplLoadHeader = false;
private $tplLoadFooter = false;
// Fehler / Nachrichten
private $ifError = false;
private $tplMsg = array();
private $tpl = NULL;
private $tplConfigArray = array();
public $tplDraw = false;
// Headertitel
private $tplHeaderTitle = '';
private $tplHeaderTitleFormat = '%s | Pi Control';
// Footer
private $tplFooterConfig = array();
// SSH
private $tplSSH = NULL;
function __construct()
{
global $globalLanguage, $globalLanguageArray;
$this->runtimeStart = microtime(true);
$lang = $globalLanguage;
$langFile = LANGUAGE_PATH.$lang.'.php';
if (empty($globalLanguageArray) && file_exists($langFile) === true && is_file($langFile) === true)
{
include $langFile;
$globalLanguageArray = $langArray;
}
foreach ($this->tplConfigs as $configFile)
{
if (file_exists(CONFIG_PATH.$configFile.$this->tplConfigSuffix) === true && is_file(CONFIG_PATH.$configFile.$this->tplConfigSuffix) === true)
$this->tplConfigArray[$configFile] = parse_ini_file(CONFIG_PATH.$configFile.$this->tplConfigSuffix, true);
}
}
/**
* Übergibt der Klasse die eigene Klassenvariable.
*
* <code>$tpl->setTpl($tpl);</code>
*
* @param class $tpl Klasse
* @return bool
*/
public function setTpl($tpl)
{
$this->tpl = $tpl;
return true;
}
/**
* Setzt Sprache.
*
* <code>$tpl->setLanguage('en'); // Für Englisch.</code>
*
* @param string $lang Sprache
* @return bool
*/
public function setLanguage($lang = 'de')
{
global $globalLanguage;
if (strlen($lang) != 2 || !is_string($lang))
return false;
$this->tplLanguage = $lang;
$globalLanguage = $lang;
return true;
}
/**
* Übersetzt Text in andere Sprache.
*
* <code>$tpl->_t('Hallo %s!', 'Welt'); // Rückgabe: Hallo Welt!</code>
*
* @param string $text Text
* @param string|int|float $args[] Argumente
* @return string
*/
public function _t()
{
$args = func_get_args();
$checksum = substr(md5($args[0]), 0, 8);
if (isset($this->tplLanguageFileArray[$checksum]) && $this->tplLanguage != 'de')
$args[0] = $this->tplLanguageFileArray[$checksum];
return call_user_func_array('sprintf', $args);
}
/**
* Übersetzt Text in andere Sprache und gibt ihn anschließend aus.
*
* <code>$tpl->_e('Hallo %s!', 'Welt'); // Ausgabe: Hallo Welt!</code>
*
* @param string $text Text
* @param string|int|float $args[] Argumente
* @return bool Ausgabe erfolgt mit "echo".
*/
public function _e()
{
$args = func_get_args();
$checksum = substr(md5($args[0]), 0, 8);
if (isset($this->tplLanguageFileArray[$checksum]) && $this->tplLanguage != 'de')
$args[0] = $this->tplLanguageFileArray[$checksum];
echo call_user_func_array('sprintf', $args);
return true;
}
/**
* Setzt Konfigurationswert für config.ini.php.
*
* <code>$tpl->setConfig('other.test', 'Wert'); // Weißt der Konfigvariable ['other']['test'] den Wert "Wert" zu.</code>
*
* @param string $config Konfigschlüssel
* @param string $value Konfigwert
* @return bool
*/
public function setConfig($config, $value, $customFile = NULL)
{
$configPath = CONFIG_PATH;
if ($this->tplFolderPathPlugin != '')
$configPath = $this->tplFolderPathPlugin.'/resources/config/';
if ($customFile !== NULL)
$configPath = $customFile;
$file = explode(':', $config);
if (count($file) != 2)
return false;
$configFile = $configPath.$file[0].$this->tplConfigSuffix;
$md5 = substr(md5($configFile), 0, 6);
if (!isset($this->tplConfigArray[$md5]))
{
if (file_exists($configFile) === true && is_file($configFile) === true)
$this->tplConfigArray[$md5] = parse_ini_file($configFile, true);
else
return false;
}
if (!strlen($config) > 0 || !is_string($config))
return false;
$var = explode('.', $file[1]);
if (count($var) != 2)
return false;
$this->tplConfigArray[$md5][$var[0]][$var[1]] = $value;
return writeConfig($this->tplConfigArray[$md5], $configFile);
}
/**
* Ermittelt Konfigurationswert aus config.ini.php.
*
* <code>$tpl->getConfig('other.test', 'Wert'); // Ermittelt den Wert von Konfigvariable ['other']['test']. Standardwert: "Wert".</code>
*
* @param string $config Konfigschlüssel
* @param string $default Standardwert
* @return string|int Im Fehlerfall der Standardwert, ansonsten den Konfigwert.
*/
public function getConfig($config, $default = NULL, $customFile = NULL)
{
$configPath = CONFIG_PATH;
if ($this->tplFolderPathPlugin != '')
$configPath = $this->tplFolderPathPlugin.'/resources/config/';
if ($customFile !== NULL)
$configPath = $customFile;
$file = explode(':', $config);
if (count($file) != 2)
return $default;
$configFile = $configPath.$file[0].$this->tplConfigSuffix;
$md5 = substr(md5($configFile), 0, 6);
if (!isset($this->tplConfigArray[$md5]))
{
if (file_exists($configFile) === true && is_file($configFile) === true)
$this->tplConfigArray[$md5] = parse_ini_file($configFile, true);
else
return false;
}
if (!strlen($config) > 0 || !is_string($config))
return $default;
if (!count($this->tplConfigArray) > 0)
return $default;
$var = explode('.', $file[1]);
if (count($var) == 1 && isset($this->tplConfigArray[$md5][$var[0]]))
return $this->tplConfigArray[$md5][$var[0]];
elseif (count($var) == 2 && isset($this->tplConfigArray[$md5][$var[0]][$var[1]]))
return $this->tplConfigArray[$md5][$var[0]][$var[1]];
else
return $default;
}
public function removeConfig($config)
{
if (!strlen($config) > 0 || !is_string($config))
return false;
$file = explode(':', $config);
if (count($file) != 2)
return false;
$var = explode('.', $file[1]);
if (count($var) == 1)
unset($this->tplConfigArray[$file[0]][$var[0]]);
elseif (count($var) == 2)
unset($this->tplConfigArray[$file[0]][$var[0]][$var[1]]);
else
return false;
return writeConfig($this->tplConfigArray[$file[0]], CONFIG_PATH.$file[0].$this->tplConfigSuffix);
}
/**
* Übergibt dem TPL-System eine Variable
*
* <code>$tpl->assign('test', 'Wert'); // "test" ist der Name der Variable, "Wert" der Wert.</code>
*
* @param string $name Name der Variable.
* @param string $value Wert der Variable.
* @return bool
*/
public function assign($name, $value = NULL, $merge = false)
{
if (!strlen($name) > 0 || !is_string($name))
return false;
if ($merge === true)
$this->tplVariables[$name] = array_merge((isset($this->tplVariables[$name])) ? $this->tplVariables[$name] : array(), $value);
else
$this->tplVariables[$name] = $value;
return true;
}
/**
* Setzt den Ordner mit den Template-Dateien.
*
* <code>$tpl->setTplFolder('/var/www/public_html/templates'); // Setzt den Pfad auf "/var/www/public_html/templates".</code>
*
* @param string $path Pfad zum Ordner.
* @return bool
*/
public function setTplFolder($path)
{
if (!strlen($path) > 0 || !is_string($path))
return false;
if (file_exists($path) !== true || is_dir($path) !== true)
return false;
$this->tplFolderPath = $path;
return true;
}
/**
* Setzt den Ordner mit den Template-Dateien für Plugins.
*
* <code>$tpl->setTplFolder('/var/www/resources/plugins/test/public_html/templates'); // Setzt den Pfad auf "/var/www/resources/plugins/test/public_html/templates".</code>
*
* @param string $path Pfad zum Ordner.
* @return bool
*/
public function setTplFolderPlugin($path)
{
if (!strlen($path) > 0 || !is_string($path))
return false;
if (file_exists($path) !== true || is_dir($path) !== true)
return false;
$this->tplFolderPathPlugin = $path;
return true;
}
/**
* Setzt den title-Tag.
*
* <code>$tpl->setHeaderTitle('Übersicht');</code>
*
* @param string $title Titel
* @return bool
*/
public function setHeaderTitle($title)
{
if (!strlen($title) > 0 || !is_string($title))
return false;
$this->tplHeaderTitle = $title;
return true;
}
/**
* Setzt das Format für den title-Tag.
*
* <code>$tpl->setHeaderTitleFormat('Pi Control | %s');</code>
*
* @param string $format Format für den Titel.
* @return bool
*/
public function setHeaderTitleFormat($format)
{
if (!strlen($format) > 0 || !is_string($format))
return false;
$this->tplHeaderTitleFormat = $format;
return true;
}
/**
* Setzt den Wert, ob der Header angezeigt werden soll oder nicht.
*
* <code>$tpl->setDrawHeader(true); // Header wird angezeigt.</code>
*
* @param bool $draw
* @return bool
*/
public function setDrawHeader($draw = true)
{
$this->tplLoadHeader = $draw;
return true;
}
/**
* Zeigt Header an.
*
* <code>$tpl->drawHeader();</code>
*
* @return bool
*/
private function drawHeader()
{
if ($this->tplLoadHeader !== true)
return false;
$fileName = CONTENT_PATH.'html_header.php';
$this->tplLoadedHeader = true;
if (file_exists($fileName) !== true || is_file($fileName) !== true)
throw new FileException(self::_t('Datei "%s" existiert nicht oder ist keine g&uuml;ltige Datei.', $fileName));
$tplMain = $this->tpl;
// Übergebe Titel
$data['title'] = sprintf($this->tplHeaderTitleFormat, $this->tplHeaderTitle);
// Uebergebe Uebersetzung
$data['jsTranslations'] = isset($this->tplVariables['jsTranslations']) ? $this->tplVariables['jsTranslations'] : array();
(include_once $fileName) or self::tplError(self::_t('Konnte Datei "%s" nicht &ouml;ffnen und auslesen.', $fileName), __LINE__);
return true;
}
/**
* Setzt den Wert, ob der Footer angezeigt werden soll oder nicht.
*
* <code>$tpl->setDrawFooter(true, $config, $errorHandler); // Footer wird angezeigt.</code>
*
* @param bool $draw
* @param array $mainConfig Konfig-Array aus main_config.php.
* @param array $errorHandler
* @return bool
*/
public function setDrawFooter($draw = true, $mainConfig = NULL)
{
$this->tplLoadFooter = $draw;
$this->tplFooterConfig = $mainConfig;
return true;
}
/**
* Zeigt Footer an.
*
* <code>$tpl->drawFooter();</code>
*
* @return bool
*/
private function drawFooter()
{
global $errorHandler;
if ($this->tplLoadFooter !== true)
return false;
$fileName = CONTENT_PATH.'html_footer.php';
$this->tplLoadedFooter = true;
if (file_exists($fileName) !== true || is_file($fileName) !== true)
throw new FileException(self::_t('Datei "%s" existiert nicht oder ist keine g&uuml;ltige Datei.', $fileName));
$tplMain = $this->tpl;
$tplConfig = $this->tplFooterConfig;
$tplErrorHandler = $errorHandler;
(include_once $fileName) or self::tplError(self::_t('Konnte Datei "%s" nicht &ouml;ffnen und auslesen.', $fileName), __LINE__);
return true;
}
/**
* Öffnet Template-Datei und zeigt Inhalt anschließend an.
*
* <code>$tpl->draw('home'); // Für Home</code>
*
* @param string $tplFileName Template-Datei
* @return bool
*/
public function draw($tplFileName = '')
{
self::drawHeader();
if ($this->ifError === true)
return false;
$this->tplDraw = true;
$folderPath = $this->tplFolderPath;
if ($this->tplFolderPathPlugin != '')
$folderPath = $this->tplFolderPathPlugin.'/public_html/templates/';
if (strlen($tplFileName) >= 1 && is_string($tplFileName))
{
if (file_exists($folderPath.$tplFileName.$this->tplFileSuffix) !== true || is_file($folderPath.$tplFileName.$this->tplFileSuffix) !== true)
return self::tplError(self::_t('Datei "%s" existiert nicht oder ist keine g&uuml;ltige Datei.', $tplFileName), __LINE__-1);
}
self::drawMsg();
$data = $this->tplVariables;
if (strlen($tplFileName) >= 1 && is_string($tplFileName))
(include_once $folderPath.$tplFileName.$this->tplFileSuffix) or self::error(self::_t('Konnte Datei "%s" nicht &ouml;ffnen und auslesen.', $tplFileName), __LINE__);
// Optisch schöner
echo PHP_EOL;
self::drawFooter();
return true;
}
/**
* Öffnet Error-Template-Datei und zeigt Inhalt + Fehler anschließend an
*
* <code>$tpl->drawError('Fehler', 'Nachricht', true); // Für Fehler.</code>
*
* @param string $errorTitle Titel des Fehlers.
* @param string $errorMsg Nachricht des Fehlers.
* @param bool $errorCancel Soll nur die Fehlermeldung angezeigt werden?
* @return bool
*/
private function drawError($errorTitle, $errorMsg, $errorCancel)
{
if (!strlen($errorMsg) > 0 || !is_string($errorMsg))
return false;
if (file_exists($this->tplFolderPath.'error'.$this->tplFileSuffix) !== true || is_file($this->tplFolderPath.'error'.$this->tplFileSuffix) !== true)
return false;
if ($errorCancel === true)
if (self::drawHeader() === false)
return false;
$data['title'] = $errorTitle;
$data['msg'] = $errorMsg;
include $this->tplFolderPath.'error'.$this->tplFileSuffix;
if ($errorCancel === true)
if (self::drawFooter() === false)
return false;
return true;
}
/**
* Fehler anzeigen.
*
* <code>$tpl->error('Fehler', 'Nachricht', true); // Für Fehler.</code>
*
* @param string $errorTitle Titel des Fehlers.
* @param string $errorMsg Nachricht des Fehlers.
* @param bool $errorCancel Soll nur die Fehlermeldung angezeigt werden?
* @return bool
*
* @TODO Wenn $errorCancel auf false steht, wird der Fehler falsch angezeigt.
*/
public function error($errorTitle, $errorMsg, $errorCancel = true)
{
$this->ifError = $errorCancel;
// Prüfe, ob Error-Template-Datei existiert
if (self::drawError($errorTitle, $errorMsg, $errorCancel) === true)
return false;
printf('<h1>%s</h1>%s', $errorTitle, $errorMsg);
return true;
}
/**
* Fehler anzeigen.
*
* <code>$tpl->tplError('Fehler', __LINE__); // Für Fehler.</code>
*
* @param string $errorMsg Nachricht des Fehlers.
* @param int $errorLine Zeilennummer des Fehlers.
* @return bool
*/
private function tplError($errorMsg, $errorLine = 0)
{
self::error('Fehler im TPL-System', sprintf('%s Zeile: %s', $errorMsg, $errorLine), true);
// Rückgabewert für andere Funktion
return false;
}
/**
* Leitet auf eine andere Seite weiter.
*
* <code>$tpl->redirect('?s=overview'); // Leitet auf "?s=overview" weiter.</code>
*
* @param string $url URL auf die weitergeleitet werden soll.
* @return bool
*/
public function redirect($url)
{
if (!strlen($url) > 0 || !is_string($url))
return false;
if (!headers_sent($filename, $linenum))
exit(header('Location: '.$url));
else
{
self::error(self::_t('Weiterleitung'),
'<strong class="red">'.self::_t('Header bereits gesendet. Redirect nicht m&ouml;glich, klicke daher stattdessen <a href="%s">diesen Link</a> an.', $url).'</strong>',
true);
}
return true;
}
/**
* Zeigt Debugmeldungen an.
*
* <code>$tpl->showDebug();</code>
*
* @return bool
*/
public function showDebug()
{
printf(PHP_EOL.'<!-- DEBUG - Start -->'.PHP_EOL.' <hr /><p>Ladezeit: %f<br />Fehler: %s</p>'.PHP_EOL.'<!-- DEBUG - End -->'.PHP_EOL, round(microtime(true)-$this->runtimeStart, 5), ($this->ifError) ? 'true' : 'false');
return true;
}
/**
* Fügt Infomeldung hinzu.
*
* <code>$tpl->msg('red', 'Warnung', 'Infotext', true); // Zeigt rote Warnmeldung an.</code>
*
* @param string $type Type (Farbe) der Meldung. Möglich: red, green, yellow.
* @param string $title Titel der Meldung.
* @param string $msg Nachricht der Meldung.
* @param bool $cancelable Soll die Meldung geschlossen werden können?
* @return bool
*/
public function msg($type, $title = NULL, $msg, $cancelable = true, $id = 0)
{
if (!strlen($type) > 0 || !is_string($type) ||
!strlen($msg) > 0 || !is_string($msg)
)
return false;
if ($id > 0)
{
$this->tplMsg[$id + 100] = array($type, $title, $msg, $cancelable);
}
else
$this->tplMsg[] = array($type, $title, $msg, $cancelable);
return true;
}
public function msgExists($id)
{
if (isset($this->tplMsg[$id + 100]))
return true;
return false;
}
/**
* Zeigt Infomeldung(en) an.
*
* <code>$tpl->drawMsg();</code>
*
* @return bool
*/
private function drawMsg()
{
if (is_array($this->tplMsg) !== true || count($this->tplMsg) == 0)
return false;
if (file_exists($this->tplFolderPath.'msg'.$this->tplFileSuffix) !== true || is_file($this->tplFolderPath.'msg'.$this->tplFileSuffix) !== true)
return false;
foreach ($this->tplMsg as $key => $msg)
{
$data['id'] = $key;
$data['type'] = $msg[0];
$data['title'] = $msg[1];
$data['msg'] = $msg[2];
$data['cancelable'] = $msg[3];
(include $this->tplFolderPath.'msg'.$this->tplFileSuffix) or self::tplError(self::_t('Konnte Datei "%s" nicht &ouml;ffnen und auslesen.', $this->tplFolderPath.'msg'.$this->tplFileSuffix), __LINE__);
}
return false;
}
/**
* Verbindet sich mit SSH.
*
* <code>$tpl->loadSSH();</code>
*
* @return bool
*/
private function loadSSH()
{
set_include_path(LIBRARY_PATH.'terminal');
if (!class_exists('Net_SSH2'))
{
include(LIBRARY_PATH.'terminal/Net/SSH2.php');
include(LIBRARY_PATH.'terminal/File/ANSI.php');
include(LIBRARY_PATH.'terminal/Crypt/RSA.php');
}
$ssh = NULL;
if (!(isset($_COOKIE['_pi-control_ssh']) && $_COOKIE['_pi-control_ssh'] != ''))
return false;
$token = $_COOKIE['_pi-control_ssh'];
$token2 = $_COOKIE['_pi-control_ssh_'.$token];
$sshType = getConfig('ssh:token_'.$token.'.type', 'password');
$sshPort = getConfig('ssh:token_'.$token.'.port', 22);
$sshUsername = getConfig('ssh:token_'.$token.'.username', 'root');
$sshPassword = getConfig('ssh:token_'.$token.'.password', '');
$sshPrivateKey = base64_decode(getConfig('ssh:token_'.$token.'.privateKey', ''));
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
$sshPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $token2, base64_decode($sshPassword), MCRYPT_MODE_ECB, $iv);
$sshPassword = rtrim($sshPassword, "\0");
$ssh = new Net_SSH2('127.0.0.1', $sshPort);
if ($sshType == 'password')
{
if (!$ssh->login($sshUsername, $sshPassword))
return false;
}
if ($sshType == 'publickey')
{
$sshKey = new Crypt_RSA();
if ($sshPassword != '')
$sshKey->setPassword($sshPassword);
$sshKey->loadKey($sshPrivateKey);
if (!$ssh->login($sshUsername, $sshKey))
return false;
}
if ($ssh === NULL)
return false;
$this->tplSSH = $ssh;
return true;
}
/**
* Führt einen SSH-Befehl aus.
* $canelIfError: 0 = Keine Auswirkung
* 1 = Fehlermeldung
* 2 = Fehlermeldung + Abbrechen
*
* <code>$tpl->executeSSH('ls', true, 0); // Im Fehlerfall wird keine Meldung ausgegeben.</code>
*
* @param string $command SSH-Befehl
* @param bool $blockStream Soll gewartet werden, bis Rückgabe?
* @param int $cancelIfError Verhalten im Fehlerfall.
* @return bool|array
*/
public function executeSSH($command, $timeout = NULL, $cancelIfError = 1)
{
if ($this->tplSSH === NULL)
if (self::loadSSH() !== true)
if ($cancelIfError !== 0)
return self::error(_t('SSH-Zugriffsfehler'), _t('Kein SSH-Zugriff, bitte anmelden! <a href="%s">Jetzt anmelden.</a>', '?s=ssh_login'), ($cancelIfError === 1) ? true : false);
if ($timeout != NULL)
$this->tplSSH->setTimeout($timeout);
else
$this->tplSSH->setTimeout(10);
$this->tplSSH->enableQuietMode();
if ($this->tplSSH === NULL || ($output = $this->tplSSH->exec($command)) === false)
return false;
$error = $this->tplSSH->getStdError();
$exitStatus = $this->tplSSH->getExitStatus();
return array($output, $error, $exitStatus);
}
/**
* Rückgabe der SSH-Ressource.
*
* <code>$tpl->getSSHResource();</code>
*
* @return bool|resource
*/
public function getSSHResource($cancelIfError = 0)
{
if ($this->tplSSH === NULL)
if (self::loadSSH() !== true)
{
if ($cancelIfError !== 0)
self::error(_t('SSH-Zugriffsfehler'), _t('Kein SSH-Zugriff, bitte anmelden! <a href="%s">Jetzt anmelden.</a>', '?s=ssh_login'), ($cancelIfError === 1) ? true : false);
return false;
}
return $this->tplSSH;
}
/**
* Ermittelt Informationen der gespeicherten SSH-Informationen.
*
* <code>$tpl->getSSHInfo();</code>
*
* @return bool|array
*/
public function getSSHInfo()
{
$sshType = getConfig('ssh:latest.type', 'password');
$sshPort = getConfig('ssh:latest.port', 22);
$sshUsername = getConfig('ssh:latest.username', '');
if (isset($_COOKIE['_pi-control_ssh']) && $_COOKIE['_pi-control_ssh'] != '')
{
$token = $_COOKIE['_pi-control_ssh'];
$sshType = getConfig('ssh:token_'.$token.'.type', $sshType);
$sshPort = getConfig('ssh:token_'.$token.'.port', $sshPort);
$sshUsername = getConfig('ssh:token_'.$token.'.username', $sshUsername);
}
return array('type' => $sshType, 'port' => $sshPort, 'username' => $sshUsername);
}
/**
* Setzt SSH-Informationen.
*
* <code>$tpl->setSSHInfo(22, 'pi', 'raspberry', false); // Login nur für aktuelle Sitzung</code>
*
* @param int $port SSH-Port
* @param string $username SSH-Benutzername
* @param string $password SSH-Passwort
* @param bool $saveInFile Langer Login (true) oder nur aktuelle Sitzung (false)?
* @return bool
*/
public function setSSHInfo($type, $port, $username, $password, $privateKey, $rememberMe = false)
{
if (!is_array($SSHInfo = self::getSSHInfo()))
return false;
if ($type != '' && is_string($type))
$SSHInfo['type'] = $type;
if ($port != '' && is_numeric($port))
$SSHInfo['port'] = $port;
if ($username != '' && is_string($username))
$SSHInfo['username'] = $username;
if ($privateKey != '' && is_string($privateKey))
$SSHInfo['privateKey'] = $privateKey;
if ($password != '')
{
if (isset($_COOKIE['_pi-control_ssh']) && $_COOKIE['_pi-control_ssh'] != '')
$this->logoutSSH();
$uniqid = generateUniqId(16, false);
$uniqid2 = generateUniqId(32, false);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
$SSHInfo['password'] = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $uniqid2, $password, MCRYPT_MODE_ECB, $iv));
$SSHInfo['privateKey'] = $privateKey;
if (setConfig('ssh:token_'.$uniqid.'.created', time()) !== true) return false;
if (setConfig('ssh:token_'.$uniqid.'.type', $SSHInfo['type']) !== true) return false;
if (setConfig('ssh:token_'.$uniqid.'.port', $SSHInfo['port']) !== true) return false;
if (setConfig('ssh:token_'.$uniqid.'.username', $SSHInfo['username']) !== true) return false;
if (setConfig('ssh:token_'.$uniqid.'.password', $SSHInfo['password']) !== true) return false;
if (setConfig('ssh:token_'.$uniqid.'.privateKey', base64_encode($SSHInfo['privateKey'])) !== true) return false;
setConfig('ssh:latest.type', $SSHInfo['type']);
setConfig('ssh:latest.port', $SSHInfo['port']);
setConfig('ssh:latest.username', $SSHInfo['username']);
if ($rememberMe == false)
{
setcookie('_pi-control_ssh', $uniqid, time()+60*60*12);
setcookie('_pi-control_ssh_'.$uniqid, $uniqid2, time()+60*60*12);
}
else
{
setcookie('_pi-control_ssh', $uniqid, time()+60*60*24*30);
setcookie('_pi-control_ssh_'.$uniqid, $uniqid2, time()+60*60*24*30);
}
$_COOKIE['_pi-control_ssh'] = $uniqid;
$_COOKIE['_pi-control_ssh_'.$uniqid] = $uniqid2;
}
return true;
}
/**
* Löscht SSH-Login.
*
* <code>$tpl->logoutSSH();</code>
*
* @return bool
*/
public function logoutSSH()
{
if (isset($_COOKIE['_pi-control_ssh']) && $_COOKIE['_pi-control_ssh'] != '')
{
$token = $_COOKIE['_pi-control_ssh'];
removeConfig('ssh:token_'.$token);
setcookie('_pi-control_ssh', '', time()-60);
setcookie('_pi-control_ssh_'.$token, '', time()-60);
$_COOKIE['_pi-control_ssh'] = '';
$_COOKIE['_pi-control_ssh_'.$token] = '';
}
return true;
}
}
?>

View File

@@ -0,0 +1,3 @@
<?php
if (!defined('PICONTROL')) exit();
?>

View File

@@ -0,0 +1,223 @@
<?php
if (!defined('PICONTROL')) exit();
class NetworkInterface
{
private $tpl;
private $file;
private $interfaces = array();
private $comments = array();
private $others = array();
public function __construct($tpl)
{
$this->tpl = $tpl;
$this->readInterfaces();
}
public function getInterfaces($removeEmpty = true)
{
$return = $this->interfaces;
if ($removeEmpty === true)
{
foreach ($return as $interface => $value)
{
if (!isset($value['protocol']) || !isset($value['method']))
unset($return[$interface]);
}
}
return $return;
}
public function getInterface($interface, $removeEmpty = true)
{
if (!isset($this->interfaces[$interface]))
return false;
$return = $this->interfaces[$interface];
if ($removeEmpty === true)
{
if (!isset($return['protocol']) || !isset($return['method']))
return false;
}
return $return;
}
public function addInterface($interface, $interfaceSettings, $writeToFile = true)
{
if (empty($interface) || empty($interfaceSettings))
return 0;
if (isset($this->interfaces[$interface], $this->interfaces[$interface]['protocol'], $this->interfaces[$interface]['method']))
return 1;
$this->interfaces[$interface] = $interfaceSettings;
if ($writeToFile === true)
return $this->writeNetworkInterface();
else
return true;
}
public function editInterface($interface, $interfaceSettings, $newInterfaceName = NULL, $writeToFile = true)
{
if (empty($interface) || empty($interfaceSettings))
return 0;
$this->interfaces[$interface] = array_merge($this->interfaces[$interface], $interfaceSettings);
$this->interfaces[$interface] = array_filter($this->interfaces[$interface]);
if ($newInterfaceName != NULL)
{
$this->interfaces[$newInterfaceName] = $this->interfaces[$interface];
unset($this->interfaces[$interface]);
}
if ($writeToFile === true)
return $this->writeNetworkInterface();
else
return true;
}
public function deleteInterface($interface, $writeToFile = true)
{
if (empty($interface))
return false;
unset($this->interfaces[$interface]);
if ($writeToFile === true)
return $this->writeNetworkInterface();
else
return true;
}
public function existsInterface($interface, $removeEmpty = true)
{
if (!isset($this->interfaces[$interface]))
return false;
if ($removeEmpty === true)
{
if (!isset($this->interfaces[$interface]['protocol']) || !isset($this->interfaces[$interface]['method']))
return false;
}
return true;
}
public function getInterfaceHash()
{
return md5(serialize($this->file));
}
private function readInterfaces()
{
$this->file = shell_exec('cat /etc/network/interfaces');
$lines = explode(PHP_EOL, $this->file);
$isInterface = NULL;
foreach ($lines as $index => $line)
{
if (isset($line[0]) && trim($line)[0] != '#')
{
if (substr($line, 0, 4) == 'auto')
{
$isInterface = NULL;
$this->interfaces[trim(substr($line, 5))]['auto'] = true;
continue;
}
if (substr($line, 0, 10) == 'allow-auto')
{
$isInterface = NULL;
$this->interfaces[trim(substr($line, 10))]['allow-auto'] = true;
continue;
}
if (substr($line, 0, 13) == 'allow-hotplug')
{
$isInterface = NULL;
$this->interfaces[trim(substr($line, 13))]['allow-hotplug'] = true;
continue;
}
if (substr($line, 0, 5) == 'iface')
{
$interface = explode(' ', $line);
$isInterface = trim($interface[1]);
$this->interfaces[$isInterface]['protocol'] = $interface[2];
$this->interfaces[$isInterface]['method'] = $interface[3];
continue;
}
if ($isInterface != NULL)
{
preg_match('/^[\s]*([\w\d\-]*)[\s]+(.*)$/im', $line, $match);
$this->interfaces[$isInterface]['iface'][$match[1]] = $match[2];
}
}
elseif (isset($line[0]) && trim($line)[0] == '#')
$this->comments[] = $line;
elseif (trim($line) != '')
$this->others[] = $line;
}
return true;
}
private function writeNetworkInterface()
{
$fileLines = '';
foreach ($this->interfaces as $interface => $line)
{
if (is_array($line))
{
if (isset($line['auto']) && $line['auto'] == true)
$fileLines .= 'auto '.$interface.PHP_EOL;
if (isset($line['allow-auto']) && $line['allow-auto'] == true)
$fileLines .= 'allow-auto '.$interface.PHP_EOL;
if (isset($line['allow-hotplug']) && $line['allow-hotplug'] == true)
$fileLines .= 'allow-hotplug '.$interface.PHP_EOL;
if (isset($line['protocol'], $line['method']) && $line['protocol'] != '' && $line['method'] != '')
{
$fileLines .= 'iface '.$interface.' '.$line['protocol'].' '.$line['method'].PHP_EOL;
if (isset($line['iface']))
{
foreach ($line['iface'] as $key => $value)
{
if ($value != NULL)
$fileLines .= ' '.$key.' '.$value.PHP_EOL;
}
}
}
$fileLines .= PHP_EOL;
}
}
foreach ($this->others as $other)
$fileLines .= trim($other).PHP_EOL;
foreach ($this->comments as $comment)
$fileLines .= trim($comment).PHP_EOL;
list ($status, $error, $exitStatus) = $this->tpl->executeSSH('echo -e '.escapeshellarg($fileLines).' | sudo /bin/su -c "cat > /etc/network/interfaces"');
if ($status == '')
return $this->readInterfaces();
return false;
}
}
?>

View File

@@ -0,0 +1,170 @@
<?php
if (!defined('PICONTROL')) exit();
function writeNetworkWPASupplicant($lines)
{
global $tpl;
if (empty($lines))
return false;
$fileLines = '';
foreach ($lines as $line)
{
if (is_array($line))
{
$fileLines .= 'network={'.PHP_EOL;
foreach ($line as $key => $value)
$fileLines .= ' '.$key.'='.$value.PHP_EOL;
$fileLines .= '}'.PHP_EOL.PHP_EOL;
}
else
$fileLines .= $line.PHP_EOL;
}
list ($status, $error, $exitStatus) = $tpl->executeSSH('echo -e '.escapeshellarg($fileLines).' | sudo /bin/su -c "cat > /etc/wpa_supplicant/wpa_supplicant.conf"');
if ($status == '')
return true;
return $error;
}
function getAllNetworkWPASupplicant()
{
global $tpl;
list ($status, $error, $exitStatus) = $tpl->executeSSH('sudo cat /etc/wpa_supplicant/wpa_supplicant.conf');
$splits = explode(PHP_EOL, $status);
$lines = array();
$isNetwork = false;
$network = array();
foreach ($splits as $index => $split)
{
if (count($split) == 0 || (isset($split[0]) && trim($split)[0] == '#'))
{
$lines[] = $split;
continue;
}
if (substr($split, 0, 8) == 'network=' && $isNetwork == false)
{
$network = array();
$isNetwork = true;
continue;
}
if (isset($split[0]) && $split[0] == '}' && $isNetwork == true)
{
$lines[] = $network;
$isNetwork = false;
continue;
}
if ($isNetwork == true)
{
preg_match_all('/^(.*)=(.*)$/', trim($split), $matches);
if (count($matches) == 3 && isset($matches[1][0]) && $matches[1][0] != '')
$network[$matches[1][0]] = $matches[2][0];
continue;
}
if (trim($split) != '')
$lines[] = $split;
}
return $lines;
}
function addNetworkWPASupplicant($network)
{
global $tpl;
$lines = getAllNetworkWPASupplicant();
$isAdded = false;
foreach ($lines as $index => $line)
{
if (!is_array($line))
continue;
if (!isset($line['id_str']) && $line['ssid'] == $network['ssid'])
{
$lines[$index] = $network;
$isAdded = true;
break;
}
}
if ($isAdded == false)
$lines[] = $network;
return writeNetworkWPASupplicant($lines);
}
function editHostname($hostname)
{
global $tpl;
$hosts = shell_exec('cat /etc/hosts');
if (empty($hosts))
return 5;
$new = preg_replace('/^(127\.0\.1\.1[\s]+)(.+)$/im', '$1'.$hostname, $hosts);
list ($status, $error, $exitStatus) = $tpl->executeSSH('echo -e '.escapeshellarg($new).' | sudo /bin/su -c "cat > /etc/hosts"');
if ($status == '')
list ($status2, $error2, $exitStatus2) = $tpl->executeSSH('echo -e '.escapeshellarg($hostname).' | sudo /bin/su -c "cat > /etc/hostname"');
else
return $status;
if ($status2 == '')
return true;
return $status2;
}
function formatInterfaceProtocol($string)
{
switch ($string)
{
case 'inet':
return 'IPv4';
break;
case 'inet6':
return 'IPv6';
break;
case 'ipx':
return 'IPX/SPX';
break;
}
}
function formatInterfaceMethod($string)
{
switch ($string)
{
case 'loopback':
return 'Loopback';
break;
case 'dhcp':
return 'Dynamisch';
break;
case 'static':
return 'Statisch';
break;
case 'manual':
return 'Manuell';
break;
}
}
?>

View File

@@ -0,0 +1,129 @@
<?php
if (!defined('PICONTROL')) exit();
function checkTemperatureMonitoringEmailStatus()
{
global $tpl, $config;
$id = getConfig('main:monitoringCpuTemp.id', '');
$code = getConfig('main:monitoringCpuTemp.code', '');
$email = getConfig('main:monitoringCpuTemp.email', '');
$data = NULL;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $config['url']['temperatureMonitoring'].'?'.http_build_query(array('id' => $id, 'code' => $code, 'email' => $email)));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
do
{
if (($data = curl_exec($curl)) === false)
{
$info = curl_getinfo($curl);
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d (%s)', $info['http_code'], curl_error($curl)), true, 12);
break;
}
else
{
$info = curl_getinfo($curl);
if ($info['http_code'] == 404)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Leider konnte keine Verbindung zum Server hergestellt werden, da dieser momentan vermutlich nicht erreichbar ist. Fehlercode: %d', $info['http_code']), true, 12);
break;
}
elseif ($info['http_code'] != 200)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $info['http_code']), true, 12);
break;
}
if ($data == '')
{
$tpl->msg('error', _t('Serverfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine leere Antwort.'), true, 12);
break;
}
// Verarbeite Datenstring
$json = json_decode($data, true);
if (json_last_error() != JSON_ERROR_NONE || !isset($json['existing'], $json['email'], $json['code']))
{
$tpl->msg('error', _t('Verarbeitungsfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine fehlerhafte Antwort.'), true, 12);
break;
}
// Antwort in Ordnung
if ($json['existing'] == false || $json['email'] == false || $json['code'] == false)
setConfig('main:monitoringCpuTemp.code', '');
}
}
while (false);
curl_close($curl);
}
function checkTemperatureMonitoringEmailCode()
{
global $tpl, $config;
$id = getConfig('main:monitoringCpuTemp.id', '');
$email = getConfig('main:monitoringCpuTemp.email', '');
$data = NULL;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $config['url']['temperatureMonitoring'].'?'.http_build_query(array('id' => $id, 'code' => true, 'email' => $email)));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
do
{
if (($data = curl_exec($curl)) === false)
{
$info = curl_getinfo($curl);
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d (%s)', $info['http_code'], curl_error($curl)), true, 12);
break;
}
else
{
$info = curl_getinfo($curl);
if ($info['http_code'] == 404)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Leider konnte keine Verbindung zum Server hergestellt werden, da dieser momentan vermutlich nicht erreichbar ist. Fehlercode: %d', $info['http_code']), true, 12);
break;
}
elseif ($info['http_code'] != 200)
{
$tpl->msg('error', _t('Verbindungsfehler'), _t('Bei der Verbindung zum Server ist ein unerwarteter Fehler aufgetreten. Fehlercode: %d', $info['http_code']), true, 12);
break;
}
if ($data == '')
{
$tpl->msg('error', _t('Serverfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine leere Antwort.'), true, 12);
break;
}
// Verarbeite Datenstring
$json = json_decode($data, true);
if (json_last_error() != JSON_ERROR_NONE || !isset($json['existing'], $json['email'], $json['code']))
{
$tpl->msg('error', _t('Verarbeitungsfehler'), _t('Bei der Verbindung zum Server ist ein Fehler aufgetreten. Der Server sendet eine fehlerhafte Antwort.'), true, 12);
break;
}
// Antwort in Ordnung
if ($json['code'] != false && strlen($json['code']) == 16)
{
setConfig('main:monitoringCpuTemp.code', $json['code']);
$tpl->msg('success', _t('E-Mail best&auml;tigt'), _t('Deine E-Mail wurde erfolgreich best&auml;tigt.'));
}
else
$tpl->msg('error', _t('Verarbeitungsfehler'), _t('Der Server konnte zugeh&ouml;rige Daten nicht finden. Versichere, dass du die E-Mail best&auml;tigt hast.'), true, 12);
}
}
while (false);
curl_close($curl);
}
?>

View File

@@ -0,0 +1,290 @@
<?php
if (!defined('PICONTROL')) exit();
function initPluginConstants($pluginId = NULL)
{
if ($pluginId == NULL)
{
$debug = debug_backtrace();
$file = $debug[0]['file'];
$file = str_replace(PLUGINS_PATH, '', $file);
$explodes = explode('/', $file);
$pluginId = $explodes[0];
}
defined('PLUGIN_ID') or define('PLUGIN_ID', $pluginId);
defined('PLUGIN_PATH') or define('PLUGIN_PATH', PLUGINS_PATH.$pluginId.'/');
return true;
}
function pluginDisabled($pluginId)
{
if (file_exists(PLUGINS_PATH.$pluginId.'/plugin_disabled.php') && is_file(PLUGINS_PATH.$pluginId.'/plugin_disabled.php'))
return true;
return false;
}
function pluginConfig($pluginId)
{
global $config;
if (!file_exists(PLUGINS_PATH.$pluginId.'/plugin.config.php') || !is_file(PLUGINS_PATH.$pluginId.'/plugin.config.php') || !include PLUGINS_PATH.$pluginId.'/plugin.config.php')
return false;
if (!isset($pluginConfig) || empty($pluginConfig))
return false;
if ($pluginConfig['id'] != $pluginId)
return false;
$pluginConfig['disabled'] = pluginDisabled($pluginId);
if (file_exists(PLUGINS_PATH.$pluginId.'/resources/content/settings/settings.php') && is_file(PLUGINS_PATH.$pluginId.'/resources/content/settings/settings.php'))
$pluginConfig['settings'] = true;
else
$pluginConfig['settings'] = false;
if (file_exists(PLUGINS_PATH.$pluginId.'/resources/content/widget/widget.php') && is_file(PLUGINS_PATH.$pluginId.'/resources/content/widget/widget.php'))
$pluginConfig['widget'] = true;
else
$pluginConfig['widget'] = false;
if ($pluginConfig['version']['require'] <= $config['version']['versioncode'])
$pluginConfig['compatible'] = true;
else
$pluginConfig['compatible'] = false;
return $pluginConfig;
}
function pluginLanguage($pluginId)
{
global $globalLanguage, $globalLanguageArray;
$pluginConfig = pluginConfig($pluginId);
if (!is_array($pluginConfig))
return false;
$lang = $globalLanguage;
$langFile = PLUGINS_PATH.$pluginConfig['id'].'/resources/languages/'.$lang.'.php';
if (file_exists($langFile) === true && is_file($langFile) === true)
{
if ((include_once $langFile) === 1)
$globalLanguageArray = array_merge($globalLanguageArray, $langArray);
else
return false;
}
return true;
}
function pluginList($listDisabled = true, $listConfig = true)
{
if (!file_exists(PLUGINS_PATH) || !is_dir(PLUGINS_PATH))
return false;
$pluginList = array();
foreach (scandir(PLUGINS_PATH) as $plugin)
{
if ($plugin == '.' || $plugin == '..')
continue;
if (!file_exists(PLUGINS_PATH.$plugin.'/plugin.config.php') || !is_file(PLUGINS_PATH.'/'.$plugin.'/plugin.config.php'))
continue;
$pluginConfig = pluginConfig($plugin);
if (!is_array($pluginConfig))
continue;
if ($listDisabled === false && $pluginConfig['disabled'] === true)
continue;
pluginLanguage($pluginConfig['id']);
$pluginConfig['name'] = _t($pluginConfig['name']);
$pluginConfig['description'] = _t($pluginConfig['description']);
if ($listConfig === true)
$pluginList[$pluginConfig['id']] = $pluginConfig;
else
$pluginList[] = $plugin;
}
array_multisort($pluginList, SORT_ASC);
return $pluginList;
}
function setPluginStatus($pluginId, $status)
{
if (empty($pluginId) || !is_bool($status))
return false;
if ($status == true)
{
if (unlink(PLUGINS_PATH.$pluginId.'/plugin_disabled.php') == true)
return true;
else
return false;
}
if (($stream = fopen(PLUGINS_PATH.$pluginId.'/plugin_disabled.php', 'w')) !== false)
{
if ((fwrite($stream, '<?php exit(); ?>')) !== false)
{
fclose($stream);
return true;
}
else
{
fclose($stream);
return false;
}
}
else
return false;
}
function deletePlugin($pluginId, $referer = NULL)
{
if (empty($pluginId))
return false;
foreach (scandir(CRON_PATH) as $file)
{
if ($file[0] == '.' || !is_file(CRON_PATH.$file) || CRON_PATH.$file == 'init.php')
continue;
if (($pos = strpos($file, '-')) === false)
continue;
if (substr($file, $pos+1, strlen($pluginId)+8) == 'plugin.'.$pluginId.'.')
unlink(CRON_PATH.$file);
}
foreach (scandir(CONFIG_PATH) as $file)
{
if ($file[0] == '.' || !is_file(CONFIG_PATH.$file))
continue;
if (substr($file, 0, strlen($pluginId)+8) == 'plugin.'.$pluginId.'.')
unlink(CONFIG_PATH.$file);
}
foreach (scandir(LOG_PATH.'plugin/') as $file)
{
if ($file[0] == '.' || !is_file(LOG_PATH.'plugin/'.$file))
continue;
if (substr($file, 0, strlen($pluginId)+1) == $pluginId.'.')
unlink(LOG_PATH.'plugin/'.$file);
}
if (file_exists(PLUGINS_PATH.$pluginId.'/uninstall.php') && is_file(PLUGINS_PATH.$pluginId.'/uninstall.php'))
{
if ($referer != NULL)
$tpl->redirect('resources/plugins/'.$pluginId.'/uninstall.php?referer='.urlencode($referer));
}
else
{
deleteFolder(PLUGINS_PATH.$pluginId.'/');
if ($referer != NULL)
$tpl->redirect($referer);
}
return true;
}
function getOnlinePlugins()
{
global $config, $globalLanguage;
$lang = $globalLanguage;
if (!class_exists('cURL'))
(include LIBRARY_PATH.'curl/curl.class.php');
$curl = new cURL($config['url']['plugin']);
$curl->execute();
if ($curl->getStatusCode() != '200')
return $curl->getStatusCode();
if ($curl->getResult($data) != JSON_ERROR_NONE)
return 0;
if (!isset($data['plugins']))
return 1;
$attributes = array('name', 'description', 'manual', 'requirement', 'screenshots');
foreach ($data['plugins'] as $pluginName => &$plugin)
{
foreach ($attributes as $attribute)
{
if (!isset($plugin[$attribute]))
continue;
if (isset($plugin[$attribute][$lang]))
$plugin[$attribute] = $plugin[$attribute][$lang];
else
$plugin[$attribute] = current($plugin[$attribute]);
}
if (isset($plugin['versions'][$plugin['latestVersion']]['changelog'][$lang]))
$plugin['versions'][$plugin['latestVersion']]['changelog'] = $plugin['versions'][$plugin['latestVersion']]['changelog'][$lang];
else
$plugin['versions'][$plugin['latestVersion']]['changelog'] = current($plugin['versions'][$plugin['latestVersion']]['changelog'][$lang]);
}
array_multisort($data['plugins'], SORT_ASC);
return $data['plugins'];
}
function checkPluginUpdate($plugins = NULL, $onlinePlugins = NULL)
{
$plugins = ($plugins != NULL) ? $plugins : pluginList();
$onlinePlugins = ($onlinePlugins != NULL) ? $onlinePlugins : getOnlinePlugins();
if (!is_array($plugins) || !is_array($onlinePlugins))
return array();
$availableUpdates = array();
foreach ($plugins as $plugin)
{
if (!isset($onlinePlugins[$plugin['id']]))
continue;
if ($plugin['version']['code'] < $onlinePlugins[$plugin['id']]['latestVersion'])
$availableUpdates[$plugin['id']] = array('id' => $plugin['id'], 'name' => $plugin['name'], 'version' => array('name' => $plugin['version']['name'], 'code' => $onlinePlugins[$plugin['id']]['latestVersion']));
}
return $availableUpdates;
}
function getPluginConfig($config, $default = NULL)
{
return getConfig('plugin.'.PLUGIN_ID.'.'.$config, $default);
}
function setPluginConfig($config, $value)
{
return setConfig('plugin.'.PLUGIN_ID.'.'.$config, $value);
}
function removePluginConfig($config)
{
return removeConfig('plugin.'.PLUGIN_ID.'.'.$config);
}
?>

View File

@@ -0,0 +1,253 @@
<?php
if (!defined('PICONTROL')) exit();
class ProcessController
{
private $rawOutput;
private $processes;
private function runCommand()
{
$this->rawOutput = shell_exec('ps axo pid,ppid,user,stat,pcpu,pmem,etime,time,comm | tail -n +2');
}
private function handleRawOutput()
{
if ($this->rawOutput === NULL)
$this->runCommand();
$output = explode("\n", $this->rawOutput);
foreach ($output as $process)
{
if (empty($process))
continue;
$split = preg_split('#[\s]+#', $process);
if ($split[0] == '')
{
unset($split[0]);
$split = array_values($split);
}
$newProcess = new ProcessEntry();
$newProcess->setPid($split[0]);
$newProcess->setPpid($split[1]);
$newProcess->setUser($split[2]);
$newProcess->setStatus($split[3]);
$newProcess->setCpu($split[4]);
$newProcess->setRam($split[5]);
$newProcess->setElapsedTime($split[6]);
$newProcess->setRuntime($split[7]);
$newProcess->setCommand($split[8]);
$this->processes[] = $newProcess;
}
}
public function getProcesses()
{
if ($this->rawOutput === NULL)
$this->handleRawOutput();
return $this->processes;
}
public function getProcessesArray()
{
$output = [];
foreach ($this->getProcesses() as $process) {
$output[] = $process->toArray();
}
return $output;
}
public function getCount()
{
if ($this->rawOutput === NULL)
$this->handleRawOutput();
return count($this->processes);
}
public function getCountRunning()
{
if ($this->rawOutput === NULL)
$this->handleRawOutput();
$count = 0;
foreach ($this->processes as $process)
{
if ($process->getStatus() == 'R')
$count += 1;
}
return $count;
}
static public function isPidWithStartTimeExists($pid, $time) {
if (!function_exists('getSecondsFromTime'))
(include_once LIBRARY_PATH.'process/process.function.php');
$rawOutput = shell_exec('ps -eo pid,etime | grep -E \'^[[:space:]]*'.escapeshellarg($pid).' \' | head -n 1');
$split = preg_split('#[\s]+#', $rawOutput);
if ($split[0] == '')
{
unset($split[0]);
$split = array_values($split);
}
return ($split[0] == $pid && abs((time() - getSecondsFromTime($split[1])) - $time) < 10);
}
public function terminatePid($pid)
{
global $tpl;
list ($SSHReturn, $SSHError, $SSHExitStatus) = $tpl->executeSSH('sudo kill -SIGTERM '.escapeshellarg($pid));
return ($SSHError == '' && $SSHExitStatus == 0) ? true : false;
}
public function killPid($pid)
{
global $tpl;
list ($SSHReturn, $SSHError, $SSHExitStatus) = $tpl->executeSSH('sudo kill -SIGKILL '.escapeshellarg($pid));
return ($SSHError == '' && $SSHExitStatus == 0) ? true : false;
}
}
class ProcessEntry
{
private $pid;
private $ppid;
private $user;
private $status;
private $cpu;
private $ram;
private $elapsedTime;
private $runtime;
private $command;
public function getPid()
{
return $this->pid;
}
public function setPid($pid)
{
$this->pid = $pid;
}
public function getPpid()
{
return $this->ppid;
}
public function setPpid($ppid)
{
$this->ppid = $ppid;
}
public function getUser()
{
return $this->user;
}
public function setUser($user)
{
$this->user = $user;
}
public function getStatus()
{
return $this->status;
}
public function setStatus($status)
{
$this->status = $status;
}
public function getCpu()
{
return $this->cpu;
}
public function setCpu($cpu)
{
$this->cpu = $cpu;
}
public function getRam()
{
return $this->ram;
}
public function setRam($ram)
{
$this->ram = $ram;
}
public function getElapsedTime()
{
if (!function_exists('getSecondsFromTime'))
(include_once LIBRARY_PATH.'process/process.function.php');
return getSecondsFromTime($this->elapsedTime);
}
public function setElapsedTime($elapsedTime)
{
$this->elapsedTime = $elapsedTime;
}
public function getRuntime()
{
if (!function_exists('getSecondsFromTime'))
(include_once LIBRARY_PATH.'process/process.function.php');
return getSecondsFromTime($this->runtime);
}
public function setRuntime($runtime)
{
$this->runtime = $runtime;
}
public function getCommand()
{
return $this->command;
}
public function setCommand($command)
{
$this->command = $command;
}
public function toArray() {
return [
'pid' => $this->pid,
'ppid' => $this->ppid,
'user' => $this->user,
'status' => $this->status,
'cpu' => $this->cpu,
'ram' => $this->ram,
'elapsedTime' => $this->getElapsedTime(),
'runtime' => $this->getRuntime(),
'command' => $this->command
];
}
}
?>

View File

@@ -0,0 +1,32 @@
<?php
if (!defined('PICONTROL')) exit();
function getReadableStatus($status)
{
switch (substr($status, 0, 1))
{
case 'D':
return _t('Ununterbrechbar');
case 'R':
return _t('L&auml;uft');
case 'S':
return _t('Schl&auml;ft');
case 'T':
return _t('Gestoppt');
case 'Z':
return _t('Zombie');
}
}
function getSecondsFromTime($time)
{
$split = preg_split('#[-:]+#', $time);
if (count($split) == 4)
return $split[0]*86400 + $split[1]*3600 + $split[2]*60 + $split[3];
elseif (count($split) == 3)
return $split[0]*3600 + $split[1]*60 + $split[2];
return $split[0]*60 + $split[1];
}
?>

View File

@@ -0,0 +1,363 @@
<?php
if (!defined('PICONTROL')) exit();
class LogStatistic
{
private $file, $stream, $limit = -1, $length = 100;
function __destruct()
{
if (is_resource($this->stream))
fclose($this->stream);
}
public function setFile($pFile = '')
{
$this->file = $pFile;
}
public function setLimit($pLimit = -1)
{
$this->limit = $pLimit;
}
public function setLength($pLength = 100)
{
$this->length = $pLength;
}
public function add($entry, $moreThanOne = false)
{
if (!is_array($entry) || empty($entry))
return false;
if (!is_resource($this->stream))
$this->open();
if ($this->limit > -1)
$this->shortLog();
fseek($this->stream, 0, SEEK_END);
if ($moreThanOne === false)
fputcsv($this->stream, $entry);
else
{
foreach ($entry as $item)
fputcsv($this->stream, $item);
}
return true;
}
public function getAll()
{
if (!is_resource($this->stream))
$this->open();
$entries = array();
fseek($this->stream, 0);
while (($entry = fgetcsv($this->stream, $this->length)) !== false)
$entries[] = $entry;
return $entries;
}
public function getLast()
{
if (!is_resource($this->stream))
$this->open();
$entries = $this->getAll();
if (is_array($entries))
return end($entries);
}
private function shortLog()
{
if ($this->limit == -1)
return false;
if (!is_array(($entries = $this->getAll())))
return false;
if (count($entries) >= $this->limit)
{
$unsetLineCount = count($entries) - $this->limit;
for ($i = 0; $i <= $unsetLineCount; $i++)
unset($entries[$i]);
fseek($this->stream, 0);
ftruncate($this->stream, 0);
foreach ($entries as $entry)
fputcsv($this->stream, $entry);
}
return true;
}
public function deleteLog()
{
if (is_file($this->file))
{
if (unlink($this->file) or exit(_t('Konnte Log-Datei nicht l&ouml;schen: %s', $this->file)))
return true;
}
else
return false;
}
public function clearLog()
{
if (!is_resource($this->stream))
$this->open();
fseek($this->stream, 0);
ftruncate($this->stream, 0);
}
public function close()
{
fclose($this->stream);
}
private function open()
{
if (!file_exists($this->file) || !is_file($this->file))
touch($this->file);
$this->stream = fopen($this->file, 'r+') or exit(_t('Konnte Log-Datei nicht &ouml;ffnen: %s', $this->file));
}
}
class StatisticController
{
private $statistics = array();
public function __construct($tpl = NULL)
{
if (!isset($tpl))
return;
$jsTranslations = array();
$jsTranslations[] = 'Es sind noch keine Werte verf&uuml;gbar. Werte werden alle %%s Minuten eingetragen.';
$jsTranslations[] = 'Es ist ein Fehler aufgetreten! Fehler: %%s';
$jsTranslations[] = 'Zeit';
$jsTranslations[] = 'Es ist ein Fehler aufgetreten! Fehlercode: %%s';
$tpl->assign('jsTranslations', $jsTranslations, true);
}
public function loadStatistics($folder = NULL)
{
$files = array();
if ($folder == NULL)
$possibleFolders = array(LOG_PATH);
else
$possibleFolders = array(LOG_PATH.$folder);
while (list($key, $folder) = each($possibleFolders))
{
foreach (@scandir($folder) as $file)
{
if ($file[0] != '.')
{
if (is_file($folder.'/'.$file) && substr($file, -4) == '.csv')
{
$fileName = str_replace(LOG_PATH, '', $folder).substr($file, 0, -4);
$this->statistics[substr(md5($fileName), 0, 8)] = $fileName;
}
elseif (is_dir($folder.$file))
$possibleFolders[] = $folder.$file.'/';
}
}
}
}
public function getStatisticID($name)
{
if (empty($this->statistics))
$this->loadStatistics();
if (!is_string($name))
return false;
if (($id = array_search($name, $this->statistics)) !== false)
return $id;
return false;
}
public function getStatisticName($id)
{
if (empty($this->statistics))
$this->loadStatistics();
if (!is_string($id))
return false;
if (isset($this->statistics[$id]))
return $this->statistics[$id];
return false;
}
public function checkStatistic($value, $isID = false)
{
if (!is_string($value))
return false;
if (!is_bool($isID))
return false;
if ($isID === true)
{
if ($this->getStatisticName($value) !== false)
return true;
else
return false;
}
elseif ($isID === false)
{
if ($this->getStatisticID($value) !== false)
return true;
else
return false;
}
return false;
}
public function getStatistics()
{
if (empty($this->statistics))
$this->loadStatistics();
return $this->statistics;
}
}
class StatisticBuilder
{
private $name, $columns, $title, $prefix, $suffix, $raw, $label, $unit, $cycle, $limits;
public function loadFromFile($name, $plugin = NULL)
{
$source = LIBRARY_PATH.'statistic/statistic.config.php';
if ($plugin != NULL && is_string($plugin))
$source = PLUGINS_PATH.$plugin.'/plugin.statistic.config.php';
if (!file_exists($source) || !is_file($source))
return false;
include $source;
if (!isset($statisticConfig) || !is_array($statisticConfig))
return false;
$this->raw = $name;
if (strpos($name, '/') !== false)
{
$explodes = explode('/', strrev($name), 2);
$name = strrev($explodes[0]);
$prefix = strrev($explodes[1]).'/';
}
if (!isset($statisticConfig[$name]) && isset($statisticConfig[substr($name, 0, strpos($name, '_'))]))
{
if (strpos($name, '_') !== false)
{
$explodes = explode('_', strrev($name), 2);
$suffix = strrev($explodes[0]);
$name = strrev($explodes[1]);
}
}
if (!isset($statisticConfig[$name]))
return false;
$statistic = $statisticConfig[$name];
$this->name = $name;
$this->title = _t($statistic['title']);
$this->prefix = isset($prefix) ? $prefix : '';
$this->suffix = isset($suffix) ? $suffix : NULL;
$this->label = _t($statistic['label']);
$this->unit = $statistic['unit'];
$this->cycle = $statistic['cycle'];
$this->limits = $statistic['limits'];
foreach ($statistic['columns'] as $column)
{
foreach ($column as &$values)
{
if (is_string($values))
$values = _t($values);
}
$this->columns[] = $column;
}
if (substr_count($this->title, '%s') == 1) {
$this->title = sprintf($this->title, $this->suffix);
}
if ($this->title == '')
$this->title = $this->suffix;
return true;
}
public function setTitle($title)
{
if (!is_string($title))
return false;
$this->title = $title;
}
public function getId()
{
return substr(md5($this->raw), 0, 8);
}
public function getArray()
{
return array(
'id' => $this->getId(),
'name' => $this->name,
'title' => $this->title,
'prefix' => $this->prefix,
'suffix' => $this->suffix,
'raw' => $this->raw,
'label' => $this->label,
'unit' => $this->unit,
'cycle' => $this->cycle,
'columns' => $this->columns,
'limits' => $this->limits
);
}
public function getJSON()
{
$json = json_encode(array(
'id' => $this->getId(),
'label' => $this->label,
'unit' => $this->unit,
'cycle' => $this->cycle,
'columns' => $this->columns
)
);
return $json;
}
}
?>

View File

@@ -0,0 +1,241 @@
<?php
$statisticConfig = array(
'coretemp' => array(
'title' => 'CPU-Temperatur',
'label' => 'Grad Celsius',
'unit' => '°C',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Temperatur',
'type' => 'number',
'downloadTitle' => 'Temperatur in Grad Celsius'
)
),
'limits' => array(
'min' => array(
'value' => 0.95,
'use' => 'multiply',
'fix' => true
),
'max' => array(
'value' => 1.05,
'use' => 'multiply',
'fix' => true
)
)
),
'cpuload' => array(
'title' => 'CPU-Auslastung',
'label' => 'Auslastung %%',
'unit' => '%',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Auslastung',
'type' => 'number',
'downloadTitle' => 'Auslastung in Prozent'
)
),
'limits' => array(
'min' => array(
'value' => 0.01,
'use' => 'fix',
'fix' => true
),
'max' => array(
'value' => 100,
'use' => 'fix',
'fix' => true
)
)
),
'cpufrequency' => array(
'title' => 'CPU-Takt',
'label' => 'MHz',
'unit' => 'MHz',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Takt',
'type' => 'number',
'downloadTitle' => 'Auslastung in MHz'
)
),
'limits' => array(
'min' => array(
'value' => 0.01,
'use' => 'fix',
'fix' => true
),
'max' => array(
'value' => 1200,
'use' => 'fix',
'fix' => true
)
)
),
'ram' => array(
'title' => 'RAM-Auslastung',
'label' => 'Auslastung %%',
'unit' => '%',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Auslastung',
'type' => 'number',
'downloadTitle' => 'Auslastung in Prozent'
)
),
'limits' => array(
'min' => array(
'value' => 0.01,
'use' => 'fix',
'fix' => true
),
'max' => array(
'value' => 100,
'use' => 'fix',
'fix' => true
)
)
),
'network' => array(
'title' => 'Netzwerkdaten - %%s',
'label' => 'Daten (MB)',
'unit' => 'MB',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Gesendet',
'type' => 'number',
'downloadTitle' => 'Gesendet in Byte',
'division' => 1048576
),
array(
'label' => 'Empfangen',
'type' => 'number',
'downloadTitle' => 'Empfangen in Byte',
'division' => 1048576
)
),
'limits' => array(
'min' => array(
'value' => 0.90,
'use' => 'multiply',
'fix' => false
),
'max' => array(
'value' => 1.10,
'use' => 'multiply',
'fix' => false
)
)
),
'network_packets' => array(
'title' => 'Netzwerkpakete - %%s',
'label' => 'Pakete',
'unit' => 'Pakete',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Gesendet',
'type' => 'number',
'downloadTitle' => 'Gesendete Pakete'
),
array(
'label' => 'Empfangen',
'type' => 'number',
'downloadTitle' => 'Empfangene Pakete'
)
),
'limits' => array(
'min' => array(
'value' => 0.90,
'use' => 'multiply',
'fix' => false
),
'max' => array(
'value' => 1.10,
'use' => 'multiply',
'fix' => false
)
)
),
'memory' => array(
'title' => 'Speicherverbrauch',
'label' => 'MB',
'unit' => 'MB',
'cycle' => 5,
'columns' => array(
array(
'label' => 'Zeit',
'type' => 'datetime',
'downloadTitle' => 'Datum'
),
array(
'label' => 'Gesamt',
'type' => 'number',
'downloadTitle' => 'Gesamt in Byte',
'division' => 1048576,
'style' => array(
'color' => '#3366cc',
'type' => 'line',
'lineDashStyle' => 10
)
),
array(
'label' => 'Belegt',
'type' => 'number',
'downloadTitle' => 'Belegt in Byte',
'division' => 1048576,
'style' => array(
'color' => '#3366cc'
)
)
),
'limits' => array(
'min' => array(
'value' => 0.01,
'use' => 'fix',
'fix' => true
),
'max' => array(
'value' => 1.10,
'use' => 'multiply',
'fix' => false
)
)
)
);
?>

View File

@@ -0,0 +1,150 @@
<?php
if (!defined('PICONTROL')) exit();
function minNotNull($values)
{
return min(array_diff(array_map('intval', $values), array(0)));
}
function getValueRow($value)
{
return array('v' => floatval(str_replace(array("\n", ','), array('', '.'), $value)));
}
function calculatePeriods(&$info, $lastTime)
{
$info['periods']['seven'] = ($lastTime - 604800) * 1000;
$info['periods']['six'] = ($lastTime - 518400) * 1000;
$info['periods']['five'] = ($lastTime - 432000) * 1000;
$info['periods']['four'] = ($lastTime - 345600) * 1000;
$info['periods']['three'] = ($lastTime - 259200) * 1000;
$info['periods']['two'] = ($lastTime - 172800) * 1000;
$info['periods']['one'] = ($lastTime - 86400) * 1000;
}
function calculateEmptyRows(&$arr, $columns, $firstTime, $lastTime, $cycle)
{
$buffer = array();
if ($lastTime < (time() - ($cycle * 60)))
{
for ($i = 0; $i < ceil(((time() - ($cycle * 60)) - $lastTime) / ($cycle * 60)); $i++)
{
$dummy = array($lastTime + (($i + 1) * ($cycle * 60)));
for ($j = 1; $j < count($columns); $j++)
$dummy[] = 0;
$buffer[] = $dummy;
}
$arr['rows'] = array_merge($arr['rows'], $buffer);
}
$buffer = array();
if (isset($arr['rows']) && count($arr['rows']) < (604800 / ($cycle * 60)))
{
for ($i = 0; $i < ((604800 / ($cycle * 60)) - count($arr['rows'])); $i++)
{
$dummy = array($firstTime - (($i + 1) * ($cycle * 60)));
for ($j = 1; $j < count($columns); $j++)
$dummy[] = 0;
$buffer[] = $dummy;
}
$arr['rows'] = array_merge(array_reverse($buffer), $arr['rows']);
}
}
function getRowsFromLog(&$arr, &$info, $log, $columns, $cycle)
{
$lastTime = NULL;
$firstTime = 0;
$leapyear = -1;
$leapyearSkip = 0;
foreach ($log as $row)
{
foreach ($row as &$data)
$data = trim($data);
if ($leapyearSkip != 0)
{
$leapyearSkip--;
continue;
}
if ($leapyear != -1 && $leapyear > date('I', $row[0]))
{
$leapyear = 0;
$leapyearSkip = (60/$cycle)-1;
continue;
}
$leapyear = date('I', $row[0]);
if ($lastTime !== NULL && ($lastTime + ($cycle * 60) + 100) < $row[0])
{
$skipped = round(($row[0] - ($lastTime + ($cycle * 60))) / ($cycle * 60));
for ($i = 0; $i < $skipped; $i++)
{
$dummy = array($lastTime + (($i + 1) * ($cycle * 60)));
for ($j = 1; $j < count($columns); $j++)
$dummy[] = 0;
$arr['rows'][] = $dummy;
}
}
$dummy = array((int) $row[0]);
for ($i = 1; $i < count($columns); $i++)
{
$rowFloat = 0;
if (isset($columns[$i]['division']))
$rowFloat = (float) round(str_replace(array("\n", ','), array('', '.'), $row[$i]) / $columns[$i]['division'], 2);
elseif (isset($columns[$i]['multiplication']))
$rowFloat = (float) round(str_replace(array("\n", ','), array('', '.'), $row[$i]) * $columns[$i]['multiplication'], 2);
else
$rowFloat = (float) $row[$i];
if (!isset($info['min']) || $rowFloat < $info['min'])
$info['min'] = $rowFloat;
if (!isset($info['max']) || $rowFloat > $info['max'])
$info['max'] = $rowFloat;
$dummy[] = $rowFloat;
}
$arr['rows'][] = $dummy;
if ($firstTime == 0)
$firstTime = $row[0];
$lastTime = $row[0];
}
calculateEmptyRows($arr, $columns, $firstTime, $lastTime, $cycle);
calculatePeriods($info, $lastTime);
}
function convertForGoogleChart($rows)
{
foreach ($rows as $index => $row)
{
$dummy = array('c' => array(array('v' => 'Date('.date('Y,'.(date('m', $row[0])-1).',d,H,i', $row[0]).')')));
unset($row[0]);
foreach ($row as $inde2 => $row2)
$dummy['c'][] = array('v' => $row2);
$rows[$index] = $dummy;
}
return $rows;
}
?>

View File

@@ -0,0 +1,197 @@
<?php
/**
* Pure-PHP implementation of AES.
*
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
* is called, again, at which point, it'll be recalculated.
*
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/AES.php';
*
* $aes = new Crypt_AES();
*
* $aes->setKey('abcdefghijklmnop');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $aes->decrypt($aes->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_AES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Rijndael
*/
if (!class_exists('Crypt_Rijndael')) {
include_once 'Rijndael.php';
}
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of AES.
*
* @package Crypt_AES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_AES extends Crypt_Rijndael
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'AES';
/**
* Dummy function
*
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
*
* @see Crypt_Rijndael::setBlockLength()
* @access public
* @param int $length
*/
function setBlockLength($length)
{
return;
}
/**
* Sets the key length
*
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @see Crypt_Rijndael:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
switch ($length) {
case 160:
$length = 192;
break;
case 224:
$length = 256;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Rijndael supports five different key lengths, AES only supports three.
*
* @see Crypt_Rijndael:setKey()
* @see setKeyLength()
* @access public
* @param string $key
*/
function setKey($key)
{
parent::setKey($key);
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_length = 16;
break;
case $length <= 24:
$this->key_length = 24;
break;
default:
$this->key_length = 32;
}
$this->_setEngine();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,671 @@
<?php
/**
* Pure-PHP implementation of Blowfish.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Blowfish.php';
*
* $blowfish = new Crypt_Blowfish();
*
* $blowfish->setKey('12345678901234567890123456789012');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $blowfish->decrypt($blowfish->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Blowfish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of Blowfish.
*
* @package Crypt_Blowfish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @access public
*/
class Crypt_Blowfish extends Crypt_Base
{
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var int
* @access private
*/
var $block_size = 8;
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'BLOWFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'blowfish';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 500;
/**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
*
* S-Box 0
*
* @access private
* @var array
*/
var $sbox0 = array(
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
);
/**
* S-Box 1
*
* @access private
* @var array
*/
var $sbox1 = array(
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
);
/**
* S-Box 2
*
* @access private
* @var array
*/
var $sbox2 = array(
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
);
/**
* S-Box 3
*
* @access private
* @var array
*/
var $sbox3 = array(
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
);
/**
* P-Array consists of 18 32-bit subkeys
*
* @var array
* @access private
*/
var $parray = array(
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
);
/**
* The BCTX-working Array
*
* Holds the expanded key [p] and the key-depended s-boxes [sb]
*
* @var array
* @access private
*/
var $bctx;
/**
* Holds the last used key
*
* @var array
* @access private
*/
var $kl;
/**
* The Key Length (in bytes)
*
* @see Crypt_Base::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $key_length = 16;
/**
* Sets the key length.
*
* Key lengths can be between 32 and 448 bits.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
if ($length < 32) {
$this->key_length = 7;
} elseif ($length > 448) {
$this->key_length = 56;
} else {
$this->key_length = $length >> 3;
}
parent::setKeyLength($length);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::isValidEngine()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
if ($this->key_length < 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'bf-ecb';
$this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key);
/* key-expanding p[] and S-Box building sb[] */
$this->bctx = array(
'p' => array(),
'sb' => array(
$this->sbox0,
$this->sbox1,
$this->sbox2,
$this->sbox3
)
);
// unpack binary string in unsigned chars
$key = array_values(unpack('C*', $this->key));
$keyl = count($key);
for ($j = 0, $i = 0; $i < 18; ++$i) {
// xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
for ($data = 0, $k = 0; $k < 4; ++$k) {
$data = ($data << 8) | $key[$j];
if (++$j >= $keyl) {
$j = 0;
}
}
$this->bctx['p'][] = $this->parray[$i] ^ $data;
}
// encrypt the zero-string, replace P1 and P2 with the encrypted data,
// encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
$data = "\0\0\0\0\0\0\0\0";
for ($i = 0; $i < 18; $i += 2) {
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
$this->bctx['p'][$i ] = $l;
$this->bctx['p'][$i + 1] = $r;
}
for ($i = 0; $i < 4; ++$i) {
for ($j = 0; $j < 256; $j += 2) {
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
$this->bctx['sb'][$i][$j ] = $l;
$this->bctx['sb'][$i][$j + 1] = $r;
}
}
}
/**
* Encrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
$p = $this->bctx["p"];
// extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
$sb_0 = $this->bctx["sb"][0];
$sb_1 = $this->bctx["sb"][1];
$sb_2 = $this->bctx["sb"][2];
$sb_3 = $this->bctx["sb"][3];
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i];
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]);
$r^= $p[$i + 1];
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]);
}
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
}
/**
* Decrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
$p = $this->bctx["p"];
$sb_0 = $this->bctx["sb"][0];
$sb_1 = $this->bctx["sb"][1];
$sb_2 = $this->bctx["sb"][2];
$sb_3 = $this->bctx["sb"][3];
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
for ($i = 17; $i > 2; $i-= 2) {
$l^= $p[$i];
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]);
$r^= $p[$i - 1];
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]);
}
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a unique hash for our generated code
$code_hash = "Crypt_Blowfish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad
switch (true) {
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
case version_compare(PHP_VERSION, '5.3.0') >= 0:
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
$safeint = '%s';
break;
default:
$safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
$safeint.= '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$p = $this->bctx['p'];
$init_crypt = '
static $sb_0, $sb_1, $sb_2, $sb_3;
if (!$sb_0) {
$sb_0 = $self->bctx["sb"][0];
$sb_1 = $self->bctx["sb"][1];
$sb_2 = $self->bctx["sb"][2];
$sb_3 = $self->bctx["sb"][3];
}
';
break;
default:
$p = array();
for ($i = 0; $i < 18; ++$i) {
$p[] = '$p_' . $i;
}
$init_crypt = '
list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
list(' . implode(',', $p) . ') = $self->bctx["p"];
';
}
// Generating encrypt code:
$encrypt_block = '
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
';
for ($i = 0; $i < 16; $i+= 2) {
$encrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]') . ';
$r^= ' . $p[$i + 1] . ';
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]') . ';
';
}
$encrypt_block.= '
$in = pack("N*",
$r ^ ' . $p[17] . ',
$l ^ ' . $p[16] . '
);
';
// Generating decrypt code:
$decrypt_block = '
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
';
for ($i = 17; $i > 2; $i-= 2) {
$decrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]') . ';
$r^= ' . $p[$i - 1] . ';
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]') . ';
';
}
$decrypt_block.= '
$in = pack("N*",
$r ^ ' . $p[0] . ',
$l ^ ' . $p[1] . '
);
';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'init_encrypt' => '',
'init_decrypt' => '',
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
$this->inline_crypt = $lambda_functions[$code_hash];
}
/**
* Convert float to int
*
* On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work
*
* @access private
* @param string $x
* @return int
*/
function safe_intval($x)
{
// PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
if (is_int($x) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
return $x;
}
return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
((fmod(floor($x / 0x80000000), 2) & 1) << 31);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,861 @@
<?php
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
*
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
*
* If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
* the hash. If no valid algorithm is provided, sha1 will be used.
*
* PHP versions 4 and 5
*
* {@internal The variable names are the same as those in
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Hash.php';
*
* $hash = new Crypt_Hash('sha1');
*
* $hash->setKey('abcdefg');
*
* echo base64_encode($hash->hash('abcdefg'));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Hash
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access private
* @see self::Crypt_Hash()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_HASH_MODE_INTERNAL', 1);
/**
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
*/
define('CRYPT_HASH_MODE_MHASH', 2);
/**
* Toggles the hash() implementation, which works on PHP 5.1.2+.
*/
define('CRYPT_HASH_MODE_HASH', 3);
/**#@-*/
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* @package Crypt_Hash
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_Hash
{
/**
* Hash Parameter
*
* @see self::setHash()
* @var int
* @access private
*/
var $hashParam;
/**
* Byte-length of compression blocks / key (Internal HMAC)
*
* @see self::setAlgorithm()
* @var int
* @access private
*/
var $b;
/**
* Byte-length of hash output (Internal HMAC)
*
* @see self::setHash()
* @var int
* @access private
*/
var $l = false;
/**
* Hash Algorithm
*
* @see self::setHash()
* @var string
* @access private
*/
var $hash;
/**
* Key
*
* @see self::setKey()
* @var string
* @access private
*/
var $key = false;
/**
* Outer XOR (Internal HMAC)
*
* @see self::setKey()
* @var string
* @access private
*/
var $opad;
/**
* Inner XOR (Internal HMAC)
*
* @see self::setKey()
* @var string
* @access private
*/
var $ipad;
/**
* Default Constructor.
*
* @param string $hash
* @return Crypt_Hash
* @access public
*/
function __construct($hash = 'sha1')
{
if (!defined('CRYPT_HASH_MODE')) {
switch (true) {
case extension_loaded('hash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
break;
case extension_loaded('mhash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
break;
default:
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
}
}
$this->setHash($hash);
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @param int $mode
* @access public
*/
function Crypt_Hash($hash = 'sha1')
{
$this->__construct($hash);
}
/**
* Sets the key for HMACs
*
* Keys can be of any length.
*
* @access public
* @param string $key
*/
function setKey($key = false)
{
$this->key = $key;
}
/**
* Gets the hash function.
*
* As set by the constructor or by the setHash() method.
*
* @access public
* @return string
*/
function getHash()
{
return $this->hashParam;
}
/**
* Sets the hash function.
*
* @access public
* @param string $hash
*/
function setHash($hash)
{
$this->hashParam = $hash = strtolower($hash);
switch ($hash) {
case 'md5-96':
case 'sha1-96':
case 'sha256-96':
case 'sha512-96':
$hash = substr($hash, 0, -3);
$this->l = 12; // 96 / 8 = 12
break;
case 'md2':
case 'md5':
$this->l = 16;
break;
case 'sha1':
$this->l = 20;
break;
case 'sha256':
$this->l = 32;
break;
case 'sha384':
$this->l = 48;
break;
case 'sha512':
$this->l = 64;
}
switch ($hash) {
case 'md2':
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
break;
case 'sha384':
case 'sha512':
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
break;
default:
$mode = CRYPT_HASH_MODE;
}
switch ($mode) {
case CRYPT_HASH_MODE_MHASH:
switch ($hash) {
case 'md5':
$this->hash = MHASH_MD5;
break;
case 'sha256':
$this->hash = MHASH_SHA256;
break;
case 'sha1':
default:
$this->hash = MHASH_SHA1;
}
return;
case CRYPT_HASH_MODE_HASH:
switch ($hash) {
case 'md5':
$this->hash = 'md5';
return;
case 'md2':
case 'sha256':
case 'sha384':
case 'sha512':
$this->hash = $hash;
return;
case 'sha1':
default:
$this->hash = 'sha1';
}
return;
}
switch ($hash) {
case 'md2':
$this->b = 16;
$this->hash = array($this, '_md2');
break;
case 'md5':
$this->b = 64;
$this->hash = array($this, '_md5');
break;
case 'sha256':
$this->b = 64;
$this->hash = array($this, '_sha256');
break;
case 'sha384':
case 'sha512':
$this->b = 128;
$this->hash = array($this, '_sha512');
break;
case 'sha1':
default:
$this->b = 64;
$this->hash = array($this, '_sha1');
}
$this->ipad = str_repeat(chr(0x36), $this->b);
$this->opad = str_repeat(chr(0x5C), $this->b);
}
/**
* Compute the HMAC.
*
* @access public
* @param string $text
* @return string
*/
function hash($text)
{
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
if (!empty($this->key) || is_string($this->key)) {
switch ($mode) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text, $this->key);
break;
case CRYPT_HASH_MODE_HASH:
$output = hash_hmac($this->hash, $text, $this->key, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
resultant L byte string as the actual key to HMAC."
-- http://tools.ietf.org/html/rfc2104#section-2 */
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
$key = str_pad($key, $this->b, chr(0)); // step 1
$temp = $this->ipad ^ $key; // step 2
$temp .= $text; // step 3
$temp = call_user_func($this->hash, $temp); // step 4
$output = $this->opad ^ $key; // step 5
$output.= $temp; // step 6
$output = call_user_func($this->hash, $output); // step 7
}
} else {
switch ($mode) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text);
break;
case CRYPT_HASH_MODE_HASH:
$output = hash($this->hash, $text, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
$output = call_user_func($this->hash, $text);
}
}
return substr($output, 0, $this->l);
}
/**
* Returns the hash length (in bytes)
*
* @access public
* @return int
*/
function getLength()
{
return $this->l;
}
/**
* Wrapper for MD5
*
* @access private
* @param string $m
*/
function _md5($m)
{
return pack('H*', md5($m));
}
/**
* Wrapper for SHA1
*
* @access private
* @param string $m
*/
function _sha1($m)
{
return pack('H*', sha1($m));
}
/**
* Pure-PHP implementation of MD2
*
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
*
* @access private
* @param string $m
*/
function _md2($m)
{
static $s = array(
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
);
// Step 1. Append Padding Bytes
$pad = 16 - (strlen($m) & 0xF);
$m.= str_repeat(chr($pad), $pad);
$length = strlen($m);
// Step 2. Append Checksum
$c = str_repeat(chr(0), 16);
$l = chr(0);
for ($i = 0; $i < $length; $i+= 16) {
for ($j = 0; $j < 16; $j++) {
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
$l = $c[$j];
}
}
$m.= $c;
$length+= 16;
// Step 3. Initialize MD Buffer
$x = str_repeat(chr(0), 48);
// Step 4. Process Message in 16-Byte Blocks
for ($i = 0; $i < $length; $i+= 16) {
for ($j = 0; $j < 16; $j++) {
$x[$j + 16] = $m[$i + $j];
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
}
$t = chr(0);
for ($j = 0; $j < 18; $j++) {
for ($k = 0; $k < 48; $k++) {
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
}
$t = chr(ord($t) + $j);
}
}
// Step 5. Output
return substr($x, 0, 16);
}
/**
* Pure-PHP implementation of SHA256
*
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
*
* @access private
* @param string $m
*/
function _sha256($m)
{
if (extension_loaded('suhosin')) {
return pack('H*', sha256($m));
}
// Initialize variables
$hash = array(
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
);
// Initialize table of round constants
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
static $k = array(
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);
// Pre-processing
$length = strlen($m);
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
$m[$length] = chr(0x80);
// we don't support hashing strings 512MB long
$m.= pack('N2', 0, $length << 3);
// Process the message in successive 512-bit chunks
$chunks = str_split($m, 64);
foreach ($chunks as $chunk) {
$w = array();
for ($i = 0; $i < 16; $i++) {
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
$w[] = $temp;
}
// Extend the sixteen 32-bit words into sixty-four 32-bit words
for ($i = 16; $i < 64; $i++) {
// @codingStandardsIgnoreStart
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
$this->_rightRotate($w[$i - 15], 18) ^
$this->_rightShift( $w[$i - 15], 3);
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
$this->_rightRotate($w[$i - 2], 19) ^
$this->_rightShift( $w[$i - 2], 10);
// @codingStandardsIgnoreEnd
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
}
// Initialize hash value for this chunk
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
// Main loop
for ($i = 0; $i < 64; $i++) {
$s0 = $this->_rightRotate($a, 2) ^
$this->_rightRotate($a, 13) ^
$this->_rightRotate($a, 22);
$maj = ($a & $b) ^
($a & $c) ^
($b & $c);
$t2 = $this->_add($s0, $maj);
$s1 = $this->_rightRotate($e, 6) ^
$this->_rightRotate($e, 11) ^
$this->_rightRotate($e, 25);
$ch = ($e & $f) ^
($this->_not($e) & $g);
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
$h = $g;
$g = $f;
$f = $e;
$e = $this->_add($d, $t1);
$d = $c;
$c = $b;
$b = $a;
$a = $this->_add($t1, $t2);
}
// Add this chunk's hash to result so far
$hash = array(
$this->_add($hash[0], $a),
$this->_add($hash[1], $b),
$this->_add($hash[2], $c),
$this->_add($hash[3], $d),
$this->_add($hash[4], $e),
$this->_add($hash[5], $f),
$this->_add($hash[6], $g),
$this->_add($hash[7], $h)
);
}
// Produce the final hash value (big-endian)
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
}
/**
* Pure-PHP implementation of SHA384 and SHA512
*
* @access private
* @param string $m
*/
function _sha512($m)
{
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
static $init384, $init512, $k;
if (!isset($k)) {
// Initialize variables
$init384 = array( // initial values for SHA384
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
);
$init512 = array( // initial values for SHA512
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
);
for ($i = 0; $i < 8; $i++) {
$init384[$i] = new Math_BigInteger($init384[$i], 16);
$init384[$i]->setPrecision(64);
$init512[$i] = new Math_BigInteger($init512[$i], 16);
$init512[$i]->setPrecision(64);
}
// Initialize table of round constants
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
$k = array(
'428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
'3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
'72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
'2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
'983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
'27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
'650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
'19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
'391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
'748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
'90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
'06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
'28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
'4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
);
for ($i = 0; $i < 80; $i++) {
$k[$i] = new Math_BigInteger($k[$i], 16);
}
}
$hash = $this->l == 48 ? $init384 : $init512;
// Pre-processing
$length = strlen($m);
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
$m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
$m[$length] = chr(0x80);
// we don't support hashing strings 512MB long
$m.= pack('N4', 0, 0, 0, $length << 3);
// Process the message in successive 1024-bit chunks
$chunks = str_split($m, 128);
foreach ($chunks as $chunk) {
$w = array();
for ($i = 0; $i < 16; $i++) {
$temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
$temp->setPrecision(64);
$w[] = $temp;
}
// Extend the sixteen 32-bit words into eighty 32-bit words
for ($i = 16; $i < 80; $i++) {
$temp = array(
$w[$i - 15]->bitwise_rightRotate(1),
$w[$i - 15]->bitwise_rightRotate(8),
$w[$i - 15]->bitwise_rightShift(7)
);
$s0 = $temp[0]->bitwise_xor($temp[1]);
$s0 = $s0->bitwise_xor($temp[2]);
$temp = array(
$w[$i - 2]->bitwise_rightRotate(19),
$w[$i - 2]->bitwise_rightRotate(61),
$w[$i - 2]->bitwise_rightShift(6)
);
$s1 = $temp[0]->bitwise_xor($temp[1]);
$s1 = $s1->bitwise_xor($temp[2]);
$w[$i] = $w[$i - 16]->copy();
$w[$i] = $w[$i]->add($s0);
$w[$i] = $w[$i]->add($w[$i - 7]);
$w[$i] = $w[$i]->add($s1);
}
// Initialize hash value for this chunk
$a = $hash[0]->copy();
$b = $hash[1]->copy();
$c = $hash[2]->copy();
$d = $hash[3]->copy();
$e = $hash[4]->copy();
$f = $hash[5]->copy();
$g = $hash[6]->copy();
$h = $hash[7]->copy();
// Main loop
for ($i = 0; $i < 80; $i++) {
$temp = array(
$a->bitwise_rightRotate(28),
$a->bitwise_rightRotate(34),
$a->bitwise_rightRotate(39)
);
$s0 = $temp[0]->bitwise_xor($temp[1]);
$s0 = $s0->bitwise_xor($temp[2]);
$temp = array(
$a->bitwise_and($b),
$a->bitwise_and($c),
$b->bitwise_and($c)
);
$maj = $temp[0]->bitwise_xor($temp[1]);
$maj = $maj->bitwise_xor($temp[2]);
$t2 = $s0->add($maj);
$temp = array(
$e->bitwise_rightRotate(14),
$e->bitwise_rightRotate(18),
$e->bitwise_rightRotate(41)
);
$s1 = $temp[0]->bitwise_xor($temp[1]);
$s1 = $s1->bitwise_xor($temp[2]);
$temp = array(
$e->bitwise_and($f),
$g->bitwise_and($e->bitwise_not())
);
$ch = $temp[0]->bitwise_xor($temp[1]);
$t1 = $h->add($s1);
$t1 = $t1->add($ch);
$t1 = $t1->add($k[$i]);
$t1 = $t1->add($w[$i]);
$h = $g->copy();
$g = $f->copy();
$f = $e->copy();
$e = $d->add($t1);
$d = $c->copy();
$c = $b->copy();
$b = $a->copy();
$a = $t1->add($t2);
}
// Add this chunk's hash to result so far
$hash = array(
$hash[0]->add($a),
$hash[1]->add($b),
$hash[2]->add($c),
$hash[3]->add($d),
$hash[4]->add($e),
$hash[5]->add($f),
$hash[6]->add($g),
$hash[7]->add($h)
);
}
// Produce the final hash value (big-endian)
// (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
$hash[4]->toBytes() . $hash[5]->toBytes();
if ($this->l != 48) {
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
}
return $temp;
}
/**
* Right Rotate
*
* @access private
* @param int $int
* @param int $amt
* @see self::_sha256()
* @return int
*/
function _rightRotate($int, $amt)
{
$invamt = 32 - $amt;
$mask = (1 << $invamt) - 1;
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
}
/**
* Right Shift
*
* @access private
* @param int $int
* @param int $amt
* @see self::_sha256()
* @return int
*/
function _rightShift($int, $amt)
{
$mask = (1 << (32 - $amt)) - 1;
return ($int >> $amt) & $mask;
}
/**
* Not
*
* @access private
* @param int $int
* @see self::_sha256()
* @return int
*/
function _not($int)
{
return ~$int & 0xFFFFFFFF;
}
/**
* Add
*
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
* possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
*
* @param int $...
* @return int
* @see self::_sha256()
* @access private
*/
function _add()
{
static $mod;
if (!isset($mod)) {
$mod = pow(2, 32);
}
$result = 0;
$arguments = func_get_args();
foreach ($arguments as $argument) {
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
}
// PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
if (is_int($result) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
return fmod($result, $mod);
}
return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
((fmod(floor($result / 0x80000000), 2) & 1) << 31);
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
}

View File

@@ -0,0 +1,761 @@
<?php
/**
* Pure-PHP implementation of RC2.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://tools.ietf.org/html/rfc2268}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/RC2.php';
*
* $rc2 = new Crypt_RC2();
*
* $rc2->setKey('abcdefgh');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $rc2->decrypt($rc2->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_RC2
* @author Patrick Monnerat <pm@datasphere.ch>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_RC2_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_RC2_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_RC2_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of RC2.
*
* @package Crypt_RC2
* @access public
*/
class Crypt_RC2 extends Crypt_Base
{
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var int
* @access private
*/
var $block_size = 8;
/**
* The Key
*
* @see Crypt_Base::key
* @see self::setKey()
* @var string
* @access private
*/
var $key;
/**
* The Original (unpadded) Key
*
* @see Crypt_Base::key
* @see self::setKey()
* @see self::encrypt()
* @see self::decrypt()
* @var string
* @access private
*/
var $orig_key;
/**
* Don't truncate / null pad key
*
* @see Crypt_Base::_clearBuffers()
* @var bool
* @access private
*/
var $skip_key_adjustment = true;
/**
* Key Length (in bytes)
*
* @see Crypt_RC2::setKeyLength()
* @var int
* @access private
*/
var $key_length = 16; // = 128 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'RC2';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'rc2';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 500;
/**
* The key length in bits.
*
* @see self::setKeyLength()
* @see self::setKey()
* @var int
* @access private
* @internal Should be in range [1..1024].
* @internal Changing this value after setting the key has no effect.
*/
var $default_key_length = 1024;
/**
* The key length in bits.
*
* @see self::isValidEnine()
* @see self::setKey()
* @var int
* @access private
* @internal Should be in range [1..1024].
*/
var $current_key_length;
/**
* The Key Schedule
*
* @see self::_setupKey()
* @var array
* @access private
*/
var $keys;
/**
* Key expansion randomization table.
* Twice the same 256-value sequence to save a modulus in key expansion.
*
* @see self::setKey()
* @var array
* @access private
*/
var $pitable = array(
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
);
/**
* Inverse key expansion randomization table.
*
* @see self::setKey()
* @var array
* @access private
*/
var $invpitable = array(
0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
);
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'rc2-ecb';
$this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
* Sets the key length.
*
* Valid key lengths are 8 to 1024.
* Calling this function after setting the key has no effect until the next
* Crypt_RC2::setKey() call.
*
* @access public
* @param int $length in bits
*/
function setKeyLength($length)
{
if ($length < 8) {
$this->default_key_length = 8;
} elseif ($length > 1024) {
$this->default_key_length = 128;
} else {
$this->default_key_length = $length;
}
$this->current_key_length = $this->default_key_length;
parent::setKeyLength($length);
}
/**
* Returns the current key length
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->current_key_length;
}
/**
* Sets the key.
*
* Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
* strlen($key) <= 128), however, we only use the first 128 bytes if $key
* has more then 128 bytes in it, and set $key to a single null byte if
* it is empty.
*
* If the key is not explicitly set, it'll be assumed to be a single
* null byte.
*
* @see Crypt_Base::setKey()
* @access public
* @param string $key
* @param int $t1 optional Effective key length in bits.
*/
function setKey($key, $t1 = 0)
{
$this->orig_key = $key;
if ($t1 <= 0) {
$t1 = $this->default_key_length;
} elseif ($t1 > 1024) {
$t1 = 1024;
}
$this->current_key_length = $t1;
// Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
$t = strlen($key);
// The mcrypt RC2 implementation only supports effective key length
// of 1024 bits. It is however possible to handle effective key
// lengths in range 1..1024 by expanding the key and applying
// inverse pitable mapping to the first byte before submitting it
// to mcrypt.
// Key expansion.
$l = array_values(unpack('C*', $key));
$t8 = ($t1 + 7) >> 3;
$tm = 0xFF >> (8 * $t8 - $t1);
// Expand key.
$pitable = $this->pitable;
for ($i = $t; $i < 128; $i++) {
$l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
}
$i = 128 - $t8;
$l[$i] = $pitable[$l[$i] & $tm];
while ($i--) {
$l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
}
// Prepare the key for mcrypt.
$l[0] = $this->invpitable[$l[0]];
array_unshift($l, 'C*');
parent::setKey(call_user_func_array('pack', $l));
}
/**
* Encrypts a message.
*
* Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code
*
* @see self::decrypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine == CRYPT_ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::encrypt($plaintext);
$this->key = $temp;
return $result;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code
*
* @see self::encrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine == CRYPT_ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::decrypt($ciphertext);
$this->key = $temp;
return $result;
}
return parent::decrypt($ciphertext);
}
/**
* Encrypts a block
*
* @see Crypt_Base::_encryptBlock()
* @see Crypt_Base::encrypt()
* @access private
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
$keys = $this->keys;
$limit = 20;
$actions = array($limit => 44, 44 => 64);
$j = 0;
for (;;) {
// Mixing round.
$r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
$r0 |= $r0 >> 16;
$r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
$r1 |= $r1 >> 16;
$r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
$r2 |= $r2 >> 16;
$r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
$r3 |= $r3 >> 16;
if ($j === $limit) {
if ($limit === 64) {
break;
}
// Mashing round.
$r0 += $keys[$r3 & 0x3F];
$r1 += $keys[$r0 & 0x3F];
$r2 += $keys[$r1 & 0x3F];
$r3 += $keys[$r2 & 0x3F];
$limit = $actions[$limit];
}
}
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Decrypts a block
*
* @see Crypt_Base::_decryptBlock()
* @see Crypt_Base::decrypt()
* @access private
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
$keys = $this->keys;
$limit = 44;
$actions = array($limit => 20, 20 => 0);
$j = 64;
for (;;) {
// R-mixing round.
$r3 = ($r3 | ($r3 << 16)) >> 5;
$r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
$r2 = ($r2 | ($r2 << 16)) >> 3;
$r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
$r1 = ($r1 | ($r1 << 16)) >> 2;
$r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
$r0 = ($r0 | ($r0 << 16)) >> 1;
$r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
if ($j === $limit) {
if ($limit === 0) {
break;
}
// R-mashing round.
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
$limit = $actions[$limit];
}
}
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Setup the CRYPT_ENGINE_MCRYPT $engine
*
* @see Crypt_Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
if (!isset($this->key)) {
$this->setKey('');
}
parent::_setupMcrypt();
}
/**
* Creates the key schedule
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
if (!isset($this->key)) {
$this->setKey('');
}
// Key has already been expanded in Crypt_RC2::setKey():
// Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key);
array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
unset($l['a']);
unset($l['b']);
$this->keys = $l;
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions = &Crypt_RC2::_getLambdaFunctions();
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a unique hash for our generated code
$code_hash = "Crypt_RC2, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there?
// If not, we have to create it.
if (!isset($lambda_functions[$code_hash])) {
// Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;';
switch (true) {
case $gen_hi_opt_code:
$keys = $this->keys;
default:
$keys = array();
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = '
$in = unpack("v4", $in);
$r0 = $in[1];
$r1 = $in[2];
$r2 = $in[3];
$r3 = $in[4];
';
// Create code for encryption.
$limit = 20;
$actions = array($limit => 44, 44 => 64);
$j = 0;
for (;;) {
// Mixing round.
$encrypt_block .= '
$r0 = (($r0 + ' . $keys[$j++] . ' +
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
$r0 |= $r0 >> 16;
$r1 = (($r1 + ' . $keys[$j++] . ' +
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
$r1 |= $r1 >> 16;
$r2 = (($r2 + ' . $keys[$j++] . ' +
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
$r2 |= $r2 >> 16;
$r3 = (($r3 + ' . $keys[$j++] . ' +
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
$r3 |= $r3 >> 16;';
if ($j === $limit) {
if ($limit === 64) {
break;
}
// Mashing round.
$encrypt_block .= '
$r0 += $keys[$r3 & 0x3F];
$r1 += $keys[$r0 & 0x3F];
$r2 += $keys[$r1 & 0x3F];
$r3 += $keys[$r2 & 0x3F];';
$limit = $actions[$limit];
}
}
$encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
// Create code for decryption.
$limit = 44;
$actions = array($limit => 20, 20 => 0);
$j = 64;
for (;;) {
// R-mixing round.
$decrypt_block .= '
$r3 = ($r3 | ($r3 << 16)) >> 5;
$r3 = ($r3 - ' . $keys[--$j] . ' -
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
$r2 = ($r2 | ($r2 << 16)) >> 3;
$r2 = ($r2 - ' . $keys[--$j] . ' -
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
$r1 = ($r1 | ($r1 << 16)) >> 2;
$r1 = ($r1 - ' . $keys[--$j] . ' -
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
$r0 = ($r0 | ($r0 << 16)) >> 1;
$r0 = ($r0 - ' . $keys[--$j] . ' -
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
if ($j === $limit) {
if ($limit === 0) {
break;
}
// R-mashing round.
$decrypt_block .= '
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
$limit = $actions[$limit];
}
}
$decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
// Creates the inline-crypt function
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
// Set the inline-crypt function as callback in: $this->inline_crypt
$this->inline_crypt = $lambda_functions[$code_hash];
}
}

View File

@@ -0,0 +1,350 @@
<?php
/**
* Pure-PHP implementation of RC4.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
*
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/RC4.php';
*
* $rc4 = new Crypt_RC4();
*
* $rc4->setKey('abcdefgh');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $rc4->decrypt($rc4->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_RC4
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access private
* @see self::_crypt()
*/
define('CRYPT_RC4_ENCRYPT', 0);
define('CRYPT_RC4_DECRYPT', 1);
/**#@-*/
/**
* Pure-PHP implementation of RC4.
*
* @package Crypt_RC4
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_RC4 extends Crypt_Base
{
/**
* Block Length of the cipher
*
* RC4 is a stream cipher
* so we the block_size to 0
*
* @see Crypt_Base::block_size
* @var int
* @access private
*/
var $block_size = 0;
/**
* Key Length (in bytes)
*
* @see Crypt_RC4::setKeyLength()
* @var int
* @access private
*/
var $key_length = 128; // = 1024 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'RC4';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'arcfour';
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see Crypt_Base::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt = false; // currently not available
/**
* The Key
*
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0";
/**
* The Key Stream for decryption and encryption
*
* @see self::setKey()
* @var array
* @access private
*/
var $stream;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* @see Crypt_Base::Crypt_Base()
* @return Crypt_RC4
* @access public
*/
function __construct()
{
parent::__construct(CRYPT_MODE_STREAM);
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @access public
*/
function Crypt_RC4()
{
$this->__construct();
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
$this->cipher_name_openssl = 'rc4-40';
}
return parent::isValidEngine($engine);
}
/**
* Dummy function.
*
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
* calling setKey().
*
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
* the IV's are relatively easy to predict, an attack described by
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
* can be used to quickly guess at the rest of the key. The following links elaborate:
*
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
*
* @param string $iv
* @see self::setKey()
* @access public
*/
function setIV($iv)
{
}
/**
* Sets the key length
*
* Keys can be between 1 and 256 bytes long.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
if ($length < 8) {
$this->key_length = 1;
} elseif ($length > 2048) {
$this->key_length = 256;
} else {
$this->key_length = $length >> 3;
}
parent::setKeyLength($length);
}
/**
* Encrypts a message.
*
* @see Crypt_Base::decrypt()
* @see self::_crypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
}
/**
* Decrypts a message.
*
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* At least if the continuous buffer is disabled.
*
* @see Crypt_Base::encrypt()
* @see self::_crypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
$key = $this->key;
$keyLength = strlen($key);
$keyStream = range(0, 255);
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->stream = array();
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
0, // index $i
0, // index $j
$keyStream
);
}
/**
* Encrypts or decrypts a message.
*
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @param string $text
* @param int $mode
* @return string $text
*/
function _crypt($text, $mode)
{
if ($this->changed) {
$this->_setup();
$this->changed = false;
}
$stream = &$this->stream[$mode];
if ($this->continuousBuffer) {
$i = &$stream[0];
$j = &$stream[1];
$keyStream = &$stream[2];
} else {
$i = $stream[0];
$j = $stream[1];
$keyStream = $stream[2];
}
$len = strlen($text);
for ($k = 0; $k < $len; ++$k) {
$i = ($i + 1) & 255;
$ksi = $keyStream[$i];
$j = ($j + $ksi) & 255;
$ksj = $keyStream[$j];
$keyStream[$i] = $ksj;
$keyStream[$j] = $ksi;
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
}
return $text;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,334 @@
<?php
/**
* Random Number Generator
*
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Random.php';
*
* echo bin2hex(crypt_random_string(8));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Random
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
// a "Cannot redeclare crypt_random_string()" error.
if (!function_exists('crypt_random_string')) {
/**
* "Is Windows" test
*
* @access private
*/
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
/**
* Generate a random string.
*
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
* microoptimizations because this function has the potential of being called a huge number of times.
* eg. for RSA key generation.
*
* @param int $length
* @return string
* @access public
*/
function crypt_random_string($length)
{
if (CRYPT_RANDOM_IS_WINDOWS) {
// method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows
if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
return mcrypt_create_iv($length);
}
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
// call php_win32_get_random_bytes():
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
//
// php_win32_get_random_bytes() is defined thusly:
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
//
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
return openssl_random_pseudo_bytes($length);
}
} else {
// method 1. the fastest
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
return openssl_random_pseudo_bytes($length);
}
// method 2
static $fp = true;
if ($fp === true) {
// warning's will be output unles the error suppression operator is used. errors such as
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
$fp = @fopen('/dev/urandom', 'rb');
}
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
return fread($fp, $length);
}
// method 3. pretty much does the same thing as method 2 per the following url:
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
// restrictions or some such
if (extension_loaded('mcrypt')) {
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
}
// at this point we have no choice but to use a pure-PHP CSPRNG
// cascade entropy across multiple PHP instances by fixing the session and collecting all
// environmental variables, including the previous session data and the current session
// data.
//
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
// however, a ton of people visiting the website. obviously you don't want to base your seeding
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
// on the data sent by all users. one user requests the page and a hash of their info is saved.
// another user visits the page and the serialization of their data is utilized along with the
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
// a hash of the session data before that). certainly an attacker should be assumed to have
// full control over his own http requests. he, however, is not going to have control over
// everyone's http requests.
static $crypto = false, $v;
if ($crypto === false) {
// save old session data
$old_session_id = session_id();
$old_use_cookies = ini_get('session.use_cookies');
$old_session_cache_limiter = session_cache_limiter();
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
if ($old_session_id != '') {
session_write_close();
}
session_id(1);
ini_set('session.use_cookies', 0);
session_cache_limiter('');
session_start();
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
(isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
(isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
(isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
(isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
phpseclib_safe_serialize($GLOBALS) .
phpseclib_safe_serialize($_SESSION) .
phpseclib_safe_serialize($_OLD_SESSION)
));
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
session_write_close();
// restore old session data
if ($old_session_id != '') {
session_id($old_session_id);
session_start();
ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
}
}
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
//
// http://tools.ietf.org/html/rfc4253#section-7.2
//
// see the is_string($crypto) part for an example of how to expand the keys
$key = pack('H*', sha1($seed . 'A'));
$iv = pack('H*', sha1($seed . 'C'));
// ciphers are used as per the nist.gov link below. also, see this link:
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case phpseclib_resolve_include_path('Crypt/AES.php'):
if (!class_exists('Crypt_AES')) {
include_once 'AES.php';
}
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
if (!class_exists('Crypt_Twofish')) {
include_once 'Twofish.php';
}
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
if (!class_exists('Crypt_Blowfish')) {
include_once 'Blowfish.php';
}
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
if (!class_exists('Crypt_TripleDES')) {
include_once 'TripleDES.php';
}
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/DES.php'):
if (!class_exists('Crypt_DES')) {
include_once 'DES.php';
}
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/RC4.php'):
if (!class_exists('Crypt_RC4')) {
include_once 'RC4.php';
}
$crypto = new Crypt_RC4();
break;
default:
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
return false;
}
$crypto->setKey($key);
$crypto->setIV($iv);
$crypto->enableContinuousBuffer();
}
//return $crypto->encrypt(str_repeat("\0", $length));
// the following is based off of ANSI X9.31:
//
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
//
// OpenSSL uses that same standard for it's random numbers:
//
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
// (do a search for "ANS X9.31 A.2.4")
$result = '';
while (strlen($result) < $length) {
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
$result.= $r;
}
return substr($result, 0, $length);
}
}
if (!function_exists('phpseclib_safe_serialize')) {
/**
* Safely serialize variables
*
* If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
* PHP 5.3 will emit a warning.
*
* @param mixed $arr
* @access public
*/
function phpseclib_safe_serialize(&$arr)
{
if (is_object($arr)) {
return '';
}
if (!is_array($arr)) {
return serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = array();
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = phpseclib_safe_serialize($arr[$key]);
}
}
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
}
if (!function_exists('phpseclib_resolve_include_path')) {
/**
* Resolve filename against the include path.
*
* Wrapper around stream_resolve_include_path() (which was introduced in
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
*
* @param string $filename
* @return string|false
* @access public
*/
function phpseclib_resolve_include_path($filename)
{
if (function_exists('stream_resolve_include_path')) {
return stream_resolve_include_path($filename);
}
// handle non-relative paths
if (file_exists($filename)) {
return realpath($filename);
}
$paths = PATH_SEPARATOR == ':' ?
preg_split('#(?<!phar):#', get_include_path()) :
explode(PATH_SEPARATOR, get_include_path());
foreach ($paths as $prefix) {
// path's specified in include_path don't always end in /
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
$file = $prefix . $ds . $filename;
if (file_exists($file)) {
return realpath($file);
}
}
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,517 @@
<?php
/**
* Pure-PHP implementation of Triple DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/TripleDES.php';
*
* $des = new Crypt_TripleDES();
*
* $des->setKey('abcdefghijklmnopqrstuvwx');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $des->decrypt($des->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_DES
*/
if (!class_exists('Crypt_DES')) {
include_once 'DES.php';
}
/**#@+
* @access public
* @see self::Crypt_TripleDES()
*/
/**
* Encrypt / decrypt using inner chaining
*
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
*/
define('CRYPT_MODE_3CBC', -2);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_3CBC', -2);
/**
* Encrypt / decrypt using outer chaining
*
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
*/
define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
/**#@-*/
/**
* Pure-PHP implementation of Triple DES.
*
* @package Crypt_TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_TripleDES extends Crypt_DES
{
/**
* Key Length (in bytes)
*
* @see Crypt_TripleDES::setKeyLength()
* @var int
* @access private
*/
var $key_length = 24;
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::password_default_salt
* @see Crypt_Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_DES::const_namespace
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'DES';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_DES::cipher_name_mcrypt
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'tripledes';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 750;
/**
* max possible size of $key
*
* @see self::setKey()
* @see Crypt_DES::setKey()
* @var string
* @access private
*/
var $key_length_max = 24;
/**
* Internal flag whether using CRYPT_DES_MODE_3CBC or not
*
* @var bool
* @access private
*/
var $mode_3cbc;
/**
* The Crypt_DES objects
*
* Used only if $mode_3cbc === true
*
* @var array
* @access private
*/
var $des;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_DES_MODE_ECB
*
* - CRYPT_DES_MODE_CBC
*
* - CRYPT_DES_MODE_CTR
*
* - CRYPT_DES_MODE_CFB
*
* - CRYPT_DES_MODE_OFB
*
* - CRYPT_DES_MODE_3CBC
*
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
*
* @see Crypt_DES::Crypt_DES()
* @see Crypt_Base::Crypt_Base()
* @param int $mode
* @access public
*/
function __construct($mode = CRYPT_MODE_CBC)
{
switch ($mode) {
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC
case CRYPT_DES_MODE_3CBC:
parent::Crypt_Base(CRYPT_MODE_CBC);
$this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array(
new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_MODE_CBC),
);
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
break;
// If not 3CBC, we init as usual
default:
parent::__construct($mode);
}
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @param int $mode
* @access public
*/
function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
{
$this->__construct($mode);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* @see Crypt_Base::setIV()
* @access public
* @param string $iv
*/
function setIV($iv)
{
parent::setIV($iv);
if ($this->mode_3cbc) {
$this->des[0]->setIV($iv);
$this->des[1]->setIV($iv);
$this->des[2]->setIV($iv);
}
}
/**
* Sets the key length.
*
* Valid key lengths are 64, 128 and 192
*
* @see Crypt_Base:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$length >>= 3;
switch (true) {
case $length <= 8:
$this->key_length = 8;
break;
case $length <= 16:
$this->key_length = 16;
break;
default:
$this->key_length = 24;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
*
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* @access public
* @see Crypt_DES::setKey()
* @see Crypt_Base::setKey()
* @param string $key
*/
function setKey($key)
{
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
if ($length > 8) {
$key = str_pad(substr($key, 0, 24), 24, chr(0));
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
// http://php.net/function.mcrypt-encrypt#47973
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else {
$key = str_pad($key, 8, chr(0));
}
parent::setKey($key);
// And in case of CRYPT_DES_MODE_3CBC:
// if key <= 64bits we not need the 3 $des to work,
// because we will then act as regular DES-CBC with just a <= 64bit key.
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
if ($this->mode_3cbc && $length > 8) {
$this->des[0]->setKey(substr($key, 0, 8));
$this->des[1]->setKey(substr($key, 8, 8));
$this->des[2]->setKey(substr($key, 16, 8));
}
}
/**
* Encrypts a message.
*
* @see Crypt_Base::encrypt()
* @access public
* @param string $plaintext
* @return string $cipertext
*/
function encrypt($plaintext)
{
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: CRYPT_MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->des[2]->encrypt(
$this->des[1]->decrypt(
$this->des[0]->encrypt(
$this->_pad($plaintext)
)
)
);
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* @see Crypt_Base::decrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->_unpad(
$this->des[0]->decrypt(
$this->des[1]->encrypt(
$this->des[2]->decrypt(
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
)
)
)
);
}
return parent::decrypt($ciphertext);
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $des->encrypt(substr($plaintext, 0, 8));
* echo $des->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $des->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $des->encrypt(substr($plaintext, 0, 8));
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_Base::enableContinuousBuffer()
* @see self::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
parent::enableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->enableContinuousBuffer();
$this->des[1]->enableContinuousBuffer();
$this->des[2]->enableContinuousBuffer();
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_Base::disableContinuousBuffer()
* @see self::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
parent::disableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->disableContinuousBuffer();
$this->des[1]->disableContinuousBuffer();
$this->des[2]->disableContinuousBuffer();
}
}
/**
* Creates the key schedule
*
* @see Crypt_DES::_setupKey()
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
switch (true) {
// if $key <= 64bits we configure our internal pure-php cipher engine
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
case strlen($this->key) <= 8:
$this->des_rounds = 1;
break;
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
default:
$this->des_rounds = 3;
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
if ($this->mode_3cbc) {
$this->des[0]->_setupKey();
$this->des[1]->_setupKey();
$this->des[2]->_setupKey();
// because $des[0-2] will, now, do all the work we can return here
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
return;
}
}
// setup our key
parent::_setupKey();
}
/**
* Sets the internal crypt engine
*
* @see Crypt_Base::Crypt_Base()
* @see Crypt_Base::setPreferredEngine()
* @param int $engine
* @access public
* @return int
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
}

View File

@@ -0,0 +1,881 @@
<?php
/**
* Pure-PHP implementation of Twofish.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Twofish.php';
*
* $twofish = new Crypt_Twofish();
*
* $twofish->setKey('12345678901234567890123456789012');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $twofish->decrypt($twofish->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Twofish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of Twofish.
*
* @package Crypt_Twofish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @access public
*/
class Crypt_Twofish extends Crypt_Base
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'TWOFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'twofish';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 800;
/**
* Q-Table
*
* @var array
* @access private
*/
var $q0 = array(
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
);
/**
* Q-Table
*
* @var array
* @access private
*/
var $q1 = array(
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
);
/**
* M-Table
*
* @var array
* @access private
*/
var $m0 = array(
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
);
/**
* M-Table
*
* @var array
* @access private
*/
var $m1 = array(
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
);
/**
* M-Table
*
* @var array
* @access private
*/
var $m2 = array(
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
);
/**
* M-Table
*
* @var array
* @access private
*/
var $m3 = array(
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
);
/**
* The Key Schedule Array
*
* @var array
* @access private
*/
var $K = array();
/**
* The Key depended S-Table 0
*
* @var array
* @access private
*/
var $S0 = array();
/**
* The Key depended S-Table 1
*
* @var array
* @access private
*/
var $S1 = array();
/**
* The Key depended S-Table 2
*
* @var array
* @access private
*/
var $S2 = array();
/**
* The Key depended S-Table 3
*
* @var array
* @access private
*/
var $S3 = array();
/**
* Holds the last used key
*
* @var array
* @access private
*/
var $kl;
/**
* The Key Length (in bytes)
*
* @see Crypt_Twofish::setKeyLength()
* @var int
* @access private
*/
var $key_length = 16;
/**
* Sets the key length.
*
* Valid key lengths are 128, 192 or 256 bits
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
switch (true) {
case $length <= 128:
$this->key_length = 16;
break;
case $length <= 192:
$this->key_length = 24;
break;
default:
$this->key_length = 32;
}
parent::setKeyLength($length);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key);
/* Key expanding and generating the key-depended s-boxes */
$le_longs = unpack('V*', $this->key);
$key = unpack('C*', $this->key);
$m0 = $this->m0;
$m1 = $this->m1;
$m2 = $this->m2;
$m3 = $this->m3;
$q0 = $this->q0;
$q1 = $this->q1;
$K = $S0 = $S1 = $S2 = $S3 = array();
switch (strlen($this->key)) {
case 16:
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
}
break;
case 24:
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
}
break;
default: // 32
list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
}
}
$this->K = $K;
$this->S0 = $S0;
$this->S1 = $S1;
$this->S2 = $S2;
$this->S3 = $S3;
}
/**
* _mdsrem function using by the twofish cipher algorithm
*
* @access private
* @param string $A
* @param string $B
* @return array
*/
function _mdsrem($A, $B)
{
// No gain by unrolling this loop.
for ($i = 0; $i < 8; ++$i) {
// Get most significant coefficient.
$t = 0xff & ($B >> 24);
// Shift the others up.
$B = ($B << 8) | (0xff & ($A >> 24));
$A<<= 8;
$u = $t << 1;
// Subtract the modular polynomial on overflow.
if ($t & 0x80) {
$u^= 0x14d;
}
// Remove t * (a * x^2 + 1).
$B ^= $t ^ ($u << 16);
// Form u = a*t + t/a = t*(a + 1/a).
$u^= 0x7fffffff & ($t >> 1);
// Add the modular polynomial on underflow.
if ($t & 0x01) {
$u^= 0xa6 ;
}
// Remove t * (a + 1/a) * (x^3 + x).
$B^= ($u << 24) | ($u << 8);
}
return array(
0xff & $B >> 24,
0xff & $B >> 16,
0xff & $B >> 8,
0xff & $B);
}
/**
* Encrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
$S0 = $this->S0;
$S1 = $this->S1;
$S2 = $this->S2;
$S3 = $this->S3;
$K = $this->K;
$in = unpack("V4", $in);
$R0 = $K[0] ^ $in[1];
$R1 = $K[1] ^ $in[2];
$R2 = $K[2] ^ $in[3];
$R3 = $K[3] ^ $in[4];
$ki = 7;
while ($ki < 39) {
$t0 = $S0[ $R0 & 0xff] ^
$S1[($R0 >> 8) & 0xff] ^
$S2[($R0 >> 16) & 0xff] ^
$S3[($R0 >> 24) & 0xff];
$t1 = $S0[($R1 >> 24) & 0xff] ^
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= $t0 + $t1 + $K[++$ki];
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
$S2[($R2 >> 16) & 0xff] ^
$S3[($R2 >> 24) & 0xff];
$t1 = $S0[($R3 >> 24) & 0xff] ^
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + $K[++$ki]);
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
}
// @codingStandardsIgnoreStart
return pack("V4", $K[4] ^ $R2,
$K[5] ^ $R3,
$K[6] ^ $R0,
$K[7] ^ $R1);
// @codingStandardsIgnoreEnd
}
/**
* Decrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
$S0 = $this->S0;
$S1 = $this->S1;
$S2 = $this->S2;
$S3 = $this->S3;
$K = $this->K;
$in = unpack("V4", $in);
$R0 = $K[4] ^ $in[1];
$R1 = $K[5] ^ $in[2];
$R2 = $K[6] ^ $in[3];
$R3 = $K[7] ^ $in[4];
$ki = 40;
while ($ki > 8) {
$t0 = $S0[$R0 & 0xff] ^
$S1[$R0 >> 8 & 0xff] ^
$S2[$R0 >> 16 & 0xff] ^
$S3[$R0 >> 24 & 0xff];
$t1 = $S0[$R1 >> 24 & 0xff] ^
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + $K[--$ki];
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
$S2[$R2 >> 16 & 0xff] ^
$S3[$R2 >> 24 & 0xff];
$t1 = $S0[$R3 >> 24 & 0xff] ^
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + $K[--$ki];
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
}
// @codingStandardsIgnoreStart
return pack("V4", $K[0] ^ $R2,
$K[1] ^ $R3,
$K[2] ^ $R0,
$K[3] ^ $R1);
// @codingStandardsIgnoreEnd
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a unique hash for our generated code
$code_hash = "Crypt_Twofish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$K = $this->K;
$init_crypt = '
static $S0, $S1, $S2, $S3;
if (!$S0) {
for ($i = 0; $i < 256; ++$i) {
$S0[] = (int)$self->S0[$i];
$S1[] = (int)$self->S1[$i];
$S2[] = (int)$self->S2[$i];
$S3[] = (int)$self->S3[$i];
}
}
';
break;
default:
$K = array();
for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i;
}
$init_crypt = '
$S0 = $self->S0;
$S1 = $self->S1;
$S2 = $self->S2;
$S3 = $self->S3;
list(' . implode(',', $K) . ') = $self->K;
';
}
// Generating encrypt code:
$encrypt_block = '
$in = unpack("V4", $in);
$R0 = '.$K[0].' ^ $in[1];
$R1 = '.$K[1].' ^ $in[2];
$R2 = '.$K[2].' ^ $in[3];
$R3 = '.$K[3].' ^ $in[4];
';
for ($ki = 7, $i = 0; $i < 8; ++$i) {
$encrypt_block.= '
$t0 = $S0[ $R0 & 0xff] ^
$S1[($R0 >> 8) & 0xff] ^
$S2[($R0 >> 16) & 0xff] ^
$S3[($R0 >> 24) & 0xff];
$t1 = $S0[($R1 >> 24) & 0xff] ^
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= ($t0 + $t1 + '.$K[++$ki].');
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
$S2[($R2 >> 16) & 0xff] ^
$S3[($R2 >> 24) & 0xff];
$t1 = $S0[($R3 >> 24) & 0xff] ^
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + '.$K[++$ki].');
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
';
}
$encrypt_block.= '
$in = pack("V4", '.$K[4].' ^ $R2,
'.$K[5].' ^ $R3,
'.$K[6].' ^ $R0,
'.$K[7].' ^ $R1);
';
// Generating decrypt code:
$decrypt_block = '
$in = unpack("V4", $in);
$R0 = '.$K[4].' ^ $in[1];
$R1 = '.$K[5].' ^ $in[2];
$R2 = '.$K[6].' ^ $in[3];
$R3 = '.$K[7].' ^ $in[4];
';
for ($ki = 40, $i = 0; $i < 8; ++$i) {
$decrypt_block.= '
$t0 = $S0[$R0 & 0xff] ^
$S1[$R0 >> 8 & 0xff] ^
$S2[$R0 >> 16 & 0xff] ^
$S3[$R0 >> 24 & 0xff];
$t1 = $S0[$R1 >> 24 & 0xff] ^
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
$S2[$R2 >> 16 & 0xff] ^
$S3[$R2 >> 24 & 0xff];
$t1 = $S0[$R3 >> 24 & 0xff] ^
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
';
}
$decrypt_block.= '
$in = pack("V4", '.$K[0].' ^ $R2,
'.$K[1].' ^ $R3,
'.$K[2].' ^ $R0,
'.$K[3].' ^ $R1);
';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'init_encrypt' => '',
'init_decrypt' => '',
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
$this->inline_crypt = $lambda_functions[$code_hash];
}
}

View File

@@ -0,0 +1,601 @@
<?php
/**
* Pure-PHP ANSI Decoder
*
* PHP versions 4 and 5
*
* If you call read() in Net_SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
* They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC). They tell a
* {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
* color to display them in, etc. File_ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category File
* @package File_ANSI
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Pure-PHP ANSI Decoder
*
* @package File_ANSI
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class File_ANSI
{
/**
* Max Width
*
* @var int
* @access private
*/
var $max_x;
/**
* Max Height
*
* @var int
* @access private
*/
var $max_y;
/**
* Max History
*
* @var int
* @access private
*/
var $max_history;
/**
* History
*
* @var array
* @access private
*/
var $history;
/**
* History Attributes
*
* @var array
* @access private
*/
var $history_attrs;
/**
* Current Column
*
* @var int
* @access private
*/
var $x;
/**
* Current Row
*
* @var int
* @access private
*/
var $y;
/**
* Old Column
*
* @var int
* @access private
*/
var $old_x;
/**
* Old Row
*
* @var int
* @access private
*/
var $old_y;
/**
* An empty attribute cell
*
* @var object
* @access private
*/
var $base_attr_cell;
/**
* The current attribute cell
*
* @var object
* @access private
*/
var $attr_cell;
/**
* An empty attribute row
*
* @var array
* @access private
*/
var $attr_row;
/**
* The current screen text
*
* @var array
* @access private
*/
var $screen;
/**
* The current screen attributes
*
* @var array
* @access private
*/
var $attrs;
/**
* Current ANSI code
*
* @var string
* @access private
*/
var $ansi;
/**
* Tokenization
*
* @var array
* @access private
*/
var $tokenization;
/**
* Default Constructor.
*
* @return File_ANSI
* @access public
*/
function __construct()
{
$attr_cell = new stdClass();
$attr_cell->bold = false;
$attr_cell->underline = false;
$attr_cell->blink = false;
$attr_cell->background = 'black';
$attr_cell->foreground = 'white';
$attr_cell->reverse = false;
$this->base_attr_cell = clone($attr_cell);
$this->attr_cell = clone($attr_cell);
$this->setHistory(200);
$this->setDimensions(80, 24);
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @access public
*/
function File_ANSI()
{
$this->__construct($mode);
}
/**
* Set terminal width and height
*
* Resets the screen as well
*
* @param int $x
* @param int $y
* @access public
*/
function setDimensions($x, $y)
{
$this->max_x = $x - 1;
$this->max_y = $y - 1;
$this->x = $this->y = 0;
$this->history = $this->history_attrs = array();
$this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
$this->screen = array_fill(0, $this->max_y + 1, '');
$this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
$this->ansi = '';
}
/**
* Set the number of lines that should be logged past the terminal height
*
* @param int $x
* @param int $y
* @access public
*/
function setHistory($history)
{
$this->max_history = $history;
}
/**
* Load a string
*
* @param string $source
* @access public
*/
function loadString($source)
{
$this->setDimensions($this->max_x + 1, $this->max_y + 1);
$this->appendString($source);
}
/**
* Appdend a string
*
* @param string $source
* @access public
*/
function appendString($source)
{
$this->tokenization = array('');
for ($i = 0; $i < strlen($source); $i++) {
if (strlen($this->ansi)) {
$this->ansi.= $source[$i];
$chr = ord($source[$i]);
// http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
// single character CSI's not currently supported
switch (true) {
case $this->ansi == "\x1B=":
$this->ansi = '';
continue 2;
case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
break;
default:
continue 2;
}
$this->tokenization[] = $this->ansi;
$this->tokenization[] = '';
// http://ascii-table.com/ansi-escape-sequences-vt-100.php
switch ($this->ansi) {
case "\x1B[H": // Move cursor to upper left corner
$this->old_x = $this->x;
$this->old_y = $this->y;
$this->x = $this->y = 0;
break;
case "\x1B[J": // Clear screen from cursor down
$this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
$this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
$this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
$this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
if (count($this->history) == $this->max_history) {
array_shift($this->history);
array_shift($this->history_attrs);
}
case "\x1B[K": // Clear screen from cursor right
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
break;
case "\x1B[2K": // Clear entire line
$this->screen[$this->y] = str_repeat(' ', $this->x);
$this->attrs[$this->y] = $this->attr_row;
break;
case "\x1B[?1h": // set cursor key to application
case "\x1B[?25h": // show the cursor
case "\x1B(B": // set united states g0 character set
break;
case "\x1BE": // Move to next line
$this->_newLine();
$this->x = 0;
break;
default:
switch (true) {
case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
$this->old_y = $this->y;
$this->y+= $match[1];
break;
case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
$this->old_x = $this->x;
$this->old_y = $this->y;
$this->x = $match[2] - 1;
$this->y = $match[1] - 1;
break;
case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
$this->old_x = $this->x;
$this->x+= $match[1];
break;
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
$this->old_x = $this->x;
$this->x-= $match[1];
break;
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
break;
case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
$attr_cell = &$this->attr_cell;
$mods = explode(';', $match[1]);
foreach ($mods as $mod) {
switch ($mod) {
case 0: // Turn off character attributes
$attr_cell = clone($this->base_attr_cell);
break;
case 1: // Turn bold mode on
$attr_cell->bold = true;
break;
case 4: // Turn underline mode on
$attr_cell->underline = true;
break;
case 5: // Turn blinking mode on
$attr_cell->blink = true;
break;
case 7: // Turn reverse video on
$attr_cell->reverse = !$attr_cell->reverse;
$temp = $attr_cell->background;
$attr_cell->background = $attr_cell->foreground;
$attr_cell->foreground = $temp;
break;
default: // set colors
//$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
$front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
//$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
$back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
switch ($mod) {
// @codingStandardsIgnoreStart
case 30: $front = 'black'; break;
case 31: $front = 'red'; break;
case 32: $front = 'green'; break;
case 33: $front = 'yellow'; break;
case 34: $front = 'blue'; break;
case 35: $front = 'magenta'; break;
case 36: $front = 'cyan'; break;
case 37: $front = 'white'; break;
case 40: $back = 'black'; break;
case 41: $back = 'red'; break;
case 42: $back = 'green'; break;
case 43: $back = 'yellow'; break;
case 44: $back = 'blue'; break;
case 45: $back = 'magenta'; break;
case 46: $back = 'cyan'; break;
case 47: $back = 'white'; break;
// @codingStandardsIgnoreEnd
default:
//user_error('Unsupported attribute: ' . $mod);
$this->ansi = '';
break 2;
}
}
}
break;
default:
//user_error("{$this->ansi} is unsupported\r\n");
}
}
$this->ansi = '';
continue;
}
$this->tokenization[count($this->tokenization) - 1].= $source[$i];
switch ($source[$i]) {
case "\r":
$this->x = 0;
break;
case "\n":
$this->_newLine();
break;
case "\x08": // backspace
if ($this->x) {
$this->x--;
$this->attrs[$this->y][$this->x] = clone($this->base_attr_cell);
$this->screen[$this->y] = substr_replace(
$this->screen[$this->y],
$source[$i],
$this->x,
1
);
}
break;
case "\x0F": // shift
break;
case "\x1B": // start ANSI escape code
$this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
//if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
// array_pop($this->tokenization);
//}
$this->ansi.= "\x1B";
break;
default:
$this->attrs[$this->y][$this->x] = clone($this->attr_cell);
if ($this->x > strlen($this->screen[$this->y])) {
$this->screen[$this->y] = str_repeat(' ', $this->x);
}
$this->screen[$this->y] = substr_replace(
$this->screen[$this->y],
$source[$i],
$this->x,
1
);
if ($this->x > $this->max_x) {
$this->x = 0;
$this->y++;
} else {
$this->x++;
}
}
}
}
/**
* Add a new line
*
* Also update the $this->screen and $this->history buffers
*
* @access private
*/
function _newLine()
{
//if ($this->y < $this->max_y) {
// $this->y++;
//}
while ($this->y >= $this->max_y) {
$this->history = array_merge($this->history, array(array_shift($this->screen)));
$this->screen[] = '';
$this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
$this->attrs[] = $this->attr_row;
if (count($this->history) >= $this->max_history) {
array_shift($this->history);
array_shift($this->history_attrs);
}
$this->y--;
}
$this->y++;
}
/**
* Returns the current coordinate without preformating
*
* @access private
* @return string
*/
function _processCoordinate($last_attr, $cur_attr, $char)
{
$output = '';
if ($last_attr != $cur_attr) {
$close = $open = '';
if ($last_attr->foreground != $cur_attr->foreground) {
if ($cur_attr->foreground != 'white') {
$open.= '<span style="color: ' . $cur_attr->foreground . '">';
}
if ($last_attr->foreground != 'white') {
$close = '</span>' . $close;
}
}
if ($last_attr->background != $cur_attr->background) {
if ($cur_attr->background != 'black') {
$open.= '<span style="background: ' . $cur_attr->background . '">';
}
if ($last_attr->background != 'black') {
$close = '</span>' . $close;
}
}
if ($last_attr->bold != $cur_attr->bold) {
if ($cur_attr->bold) {
$open.= '<b>';
} else {
$close = '</b>' . $close;
}
}
if ($last_attr->underline != $cur_attr->underline) {
if ($cur_attr->underline) {
$open.= '<u>';
} else {
$close = '</u>' . $close;
}
}
if ($last_attr->blink != $cur_attr->blink) {
if ($cur_attr->blink) {
$open.= '<blink>';
} else {
$close = '</blink>' . $close;
}
}
$output.= $close . $open;
}
$output.= htmlspecialchars($char);
return $output;
}
/**
* Returns the current screen without preformating
*
* @access private
* @return string
*/
function _getScreen()
{
$output = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i <= $this->max_y; $i++) {
for ($j = 0; $j <= $this->max_x; $j++) {
$cur_attr = $this->attrs[$i][$j];
$output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
$last_attr = $this->attrs[$i][$j];
}
$output.= "\r\n";
}
$output = substr($output, 0, -2);
// close any remaining open tags
$output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
return rtrim($output);
}
/**
* Returns the current screen
*
* @access public
* @return string
*/
function getScreen()
{
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
}
/**
* Returns the current screen and the x previous lines
*
* @access public
* @return string
*/
function getHistory()
{
$scrollback = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i < count($this->history); $i++) {
for ($j = 0; $j <= $this->max_x + 1; $j++) {
$cur_attr = $this->history_attrs[$i][$j];
$scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
$last_attr = $this->history_attrs[$i][$j];
}
$scrollback.= "\r\n";
}
$base_attr_cell = $this->base_attr_cell;
$this->base_attr_cell = $last_attr;
$scrollback.= $this->_getScreen();
$this->base_attr_cell = $base_attr_cell;
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,373 @@
<?php
/**
* Pure-PHP implementation of SCP.
*
* PHP versions 4 and 5
*
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Net/SCP.php';
* include 'Net/SSH2.php';
*
* $ssh = new Net_SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('bad login');
* }
*
* $scp = new Net_SCP($ssh);
* $scp->put('abcd', str_repeat('x', 1024*1024));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2010 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see self::put()
*/
/**
* Reads data from a local file.
*/
define('NET_SCP_LOCAL_FILE', 1);
/**
* Reads data from a string.
*/
define('NET_SCP_STRING', 2);
/**#@-*/
/**#@+
* @access private
* @see self::_send()
* @see self::_receive()
*/
/**
* SSH1 is being used.
*/
define('NET_SCP_SSH1', 1);
/**
* SSH2 is being used.
*/
define('NET_SCP_SSH2', 2);
/**#@-*/
/**
* Pure-PHP implementations of SCP.
*
* @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SCP
{
/**
* SSH Object
*
* @var object
* @access private
*/
var $ssh;
/**
* Packet Size
*
* @var int
* @access private
*/
var $packet_size;
/**
* Mode
*
* @var int
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Connects to an SSH server
*
* @param Net_SSH1|Net_SSH2 $ssh
* @return Net_SCP
* @access public
*/
function __construct($ssh)
{
if (!is_object($ssh)) {
return;
}
switch (strtolower(get_class($ssh))) {
case 'net_ssh2':
$this->mode = NET_SCP_SSH2;
break;
case 'net_ssh1':
$this->packet_size = 50000;
$this->mode = NET_SCP_SSH1;
break;
default:
return;
}
$this->ssh = $ssh;
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @param Net_SSH1|Net_SSH2 $ssh
* @access public
*/
function Net_SCP($ssh)
{
$this->__construct($ssh);
}
/**
* Uploads a file to the SCP server.
*
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* @param string $remote_file
* @param string $data
* @param int $mode
* @param callable $callback
* @return bool
* @access public
*/
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
return false;
}
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
if ($this->mode == NET_SCP_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
}
$remote_file = basename($remote_file);
if ($mode == NET_SCP_STRING) {
$size = strlen($data);
} else {
if (!is_file($data)) {
user_error("$data is not a valid file", E_USER_NOTICE);
return false;
}
$fp = @fopen($data, 'rb');
if (!$fp) {
return false;
}
$size = filesize($data);
}
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
$sent = 0;
while ($sent < $size) {
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$this->_send($temp);
$sent+= strlen($temp);
if (is_callable($callback)) {
call_user_func($callback, $sent);
}
}
$this->_close();
if ($mode != NET_SCP_STRING) {
fclose($fp);
}
return true;
}
/**
* Downloads a file from the SCP server.
*
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation
*
* @param string $remote_file
* @param string $local_file
* @return mixed
* @access public
*/
function get($remote_file, $local_file = false)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
return false;
}
$this->_send("\0");
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
return false;
}
$this->_send("\0");
$size = 0;
if ($local_file !== false) {
$fp = @fopen($local_file, 'wb');
if (!$fp) {
return false;
}
}
$content = '';
while ($size < $info['size']) {
$data = $this->_receive();
// SCP usually seems to split stuff out into 16k chunks
$size+= strlen($data);
if ($local_file === false) {
$content.= $data;
} else {
fputs($fp, $data);
}
}
$this->_close();
if ($local_file !== false) {
fclose($fp);
return true;
}
return $content;
}
/**
* Sends a packet to an SSH server
*
* @param string $data
* @access private
*/
function _send($data)
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
break;
case NET_SCP_SSH1:
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
$this->ssh->_send_binary_packet($data);
}
}
/**
* Receives a packet from an SSH server
*
* @return string
* @access private
*/
function _receive()
{
switch ($this->mode) {
case NET_SCP_SSH2:
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
case NET_SCP_SSH1:
if (!$this->ssh->bitmap) {
return false;
}
while (true) {
$response = $this->ssh->_get_binary_packet();
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
case NET_SSH1_SMSG_STDOUT_DATA:
if (strlen($response[NET_SSH1_RESPONSE_DATA]) < 4) {
return false;
}
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
case NET_SSH1_SMSG_STDERR_DATA:
break;
case NET_SSH1_SMSG_EXITSTATUS:
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
fclose($this->ssh->fsock);
$this->ssh->bitmap = 0;
return false;
default:
user_error('Unknown packet received', E_USER_NOTICE);
return false;
}
}
}
}
/**
* Closes the connection to an SSH server
*
* @access private
*/
function _close()
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
break;
case NET_SCP_SSH1:
$this->ssh->disconnect();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,815 @@
<?php
/**
* SFTP Stream Wrapper
*
* Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
*
* PHP version 5
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SFTP_Stream
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2013 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* SFTP Stream Wrapper
*
* @package Net_SFTP_Stream
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SFTP_Stream
{
/**
* SFTP instances
*
* Rather than re-create the connection we re-use instances if possible
*
* @var array
*/
static $instances;
/**
* SFTP instance
*
* @var object
* @access private
*/
var $sftp;
/**
* Path
*
* @var string
* @access private
*/
var $path;
/**
* Mode
*
* @var string
* @access private
*/
var $mode;
/**
* Position
*
* @var int
* @access private
*/
var $pos;
/**
* Size
*
* @var int
* @access private
*/
var $size;
/**
* Directory entries
*
* @var array
* @access private
*/
var $entries;
/**
* EOF flag
*
* @var bool
* @access private
*/
var $eof;
/**
* Context resource
*
* Technically this needs to be publically accessible so PHP can set it directly
*
* @var resource
* @access public
*/
var $context;
/**
* Notification callback function
*
* @var callable
* @access public
*/
var $notification;
/**
* Registers this class as a URL wrapper.
*
* @param string $protocol The wrapper name to be registered.
* @return bool True on success, false otherwise.
* @access public
*/
static function register($protocol = 'sftp')
{
if (in_array($protocol, stream_get_wrappers(), true)) {
return false;
}
$class = function_exists('get_called_class') ? get_called_class() : __CLASS__;
return stream_wrapper_register($protocol, $class);
}
/**
* The Constructor
*
* @access public
*/
function __construct()
{
if (defined('NET_SFTP_STREAM_LOGGING')) {
echo "__construct()\r\n";
}
if (!class_exists('Net_SFTP')) {
include_once 'Net/SFTP.php';
}
}
/**
* Path Parser
*
* Extract a path from a URI and actually connect to an SSH server if appropriate
*
* If "notification" is set as a context parameter the message code for successful login is
* NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
*
* @param string $path
* @return string
* @access private
*/
function _parse_path($path)
{
$orig = $path;
extract(parse_url($path) + array('port' => 22));
if (isset($query)) {
$path.= '?' . $query;
} elseif (preg_match('/(\?|\?#)$/', $orig)) {
$path.= '?';
}
if (isset($fragment)) {
$path.= '#' . $fragment;
} elseif ($orig[strlen($orig) - 1] == '#') {
$path.= '#';
}
if (!isset($host)) {
return false;
}
if (isset($this->context)) {
$context = stream_context_get_params($this->context);
if (isset($context['notification'])) {
$this->notification = $context['notification'];
}
}
if ($host[0] == '$') {
$host = substr($host, 1);
global $$host;
if (!is_object($$host) || get_class($$host) != 'Net_SFTP') {
return false;
}
$this->sftp = $$host;
} else {
if (isset($this->context)) {
$context = stream_context_get_options($this->context);
}
if (isset($context[$scheme]['session'])) {
$sftp = $context[$scheme]['session'];
}
if (isset($context[$scheme]['sftp'])) {
$sftp = $context[$scheme]['sftp'];
}
if (isset($sftp) && is_object($sftp) && get_class($sftp) == 'Net_SFTP') {
$this->sftp = $sftp;
return $path;
}
if (isset($context[$scheme]['username'])) {
$user = $context[$scheme]['username'];
}
if (isset($context[$scheme]['password'])) {
$pass = $context[$scheme]['password'];
}
if (isset($context[$scheme]['privkey']) && is_object($context[$scheme]['privkey']) && get_Class($context[$scheme]['privkey']) == 'Crypt_RSA') {
$pass = $context[$scheme]['privkey'];
}
if (!isset($user) || !isset($pass)) {
return false;
}
// casting $pass to a string is necessary in the event that it's a Crypt_RSA object
if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
$this->sftp = self::$instances[$host][$port][$user][(string) $pass];
} else {
$this->sftp = new Net_SFTP($host, $port);
$this->sftp->disableStatCache();
if (isset($this->notification) && is_callable($this->notification)) {
/* if !is_callable($this->notification) we could do this:
user_error('fopen(): failed to call user notifier', E_USER_WARNING);
the ftp wrapper gives errors like that when the notifier isn't callable.
i've opted not to do that, however, since the ftp wrapper gives the line
on which the fopen occurred as the line number - not the line that the
user_error is on.
*/
call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
if (!$this->sftp->login($user, $pass)) {
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
return false;
}
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
} else {
if (!$this->sftp->login($user, $pass)) {
return false;
}
}
self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
}
}
return $path;
}
/**
* Opens file or URL
*
* @param string $path
* @param string $mode
* @param int $options
* @param string $opened_path
* @return bool
* @access public
*/
function _stream_open($path, $mode, $options, &$opened_path)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$this->path = $path;
$this->size = $this->sftp->size($path);
$this->mode = preg_replace('#[bt]$#', '', $mode);
$this->eof = false;
if ($this->size === false) {
if ($this->mode[0] == 'r') {
return false;
} else {
$this->sftp->touch($path);
$this->size = 0;
}
} else {
switch ($this->mode[0]) {
case 'x':
return false;
case 'w':
$this->sftp->truncate($path, 0);
$this->size = 0;
}
}
$this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
return true;
}
/**
* Read from stream
*
* @param int $count
* @return mixed
* @access public
*/
function _stream_read($count)
{
switch ($this->mode) {
case 'w':
case 'a':
case 'x':
case 'c':
return false;
}
// commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
//if ($this->pos >= $this->size) {
// $this->eof = true;
// return false;
//}
$result = $this->sftp->get($this->path, false, $this->pos, $count);
if (isset($this->notification) && is_callable($this->notification)) {
if ($result === false) {
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
return 0;
}
// seems that PHP calls stream_read in 8k chunks
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
}
if (empty($result)) { // ie. false or empty string
$this->eof = true;
return false;
}
$this->pos+= strlen($result);
return $result;
}
/**
* Write to stream
*
* @param string $data
* @return mixed
* @access public
*/
function _stream_write($data)
{
switch ($this->mode) {
case 'r':
return false;
}
$result = $this->sftp->put($this->path, $data, NET_SFTP_STRING, $this->pos);
if (isset($this->notification) && is_callable($this->notification)) {
if (!$result) {
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
return 0;
}
// seems that PHP splits up strings into 8k blocks before calling stream_write
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
}
if ($result === false) {
return false;
}
$this->pos+= strlen($data);
if ($this->pos > $this->size) {
$this->size = $this->pos;
}
$this->eof = false;
return strlen($data);
}
/**
* Retrieve the current position of a stream
*
* @return int
* @access public
*/
function _stream_tell()
{
return $this->pos;
}
/**
* Tests for end-of-file on a file pointer
*
* In my testing there are four classes functions that normally effect the pointer:
* fseek, fputs / fwrite, fgets / fread and ftruncate.
*
* Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true.
*
* @return bool
* @access public
*/
function _stream_eof()
{
return $this->eof;
}
/**
* Seeks to specific location in a stream
*
* @param int $offset
* @param int $whence
* @return bool
* @access public
*/
function _stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset >= $this->size || $offset < 0) {
return false;
}
break;
case SEEK_CUR:
$offset+= $this->pos;
break;
case SEEK_END:
$offset+= $this->size;
}
$this->pos = $offset;
$this->eof = false;
return true;
}
/**
* Change stream options
*
* @param string $path
* @param int $option
* @param mixed $var
* @return bool
* @access public
*/
function _stream_metadata($path, $option, $var)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
// stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
// see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
// and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
switch ($option) {
case 1: // PHP_STREAM_META_TOUCH
return $this->sftp->touch($path, $var[0], $var[1]);
case 2: // PHP_STREAM_OWNER_NAME
case 3: // PHP_STREAM_GROUP_NAME
return false;
case 4: // PHP_STREAM_META_OWNER
return $this->sftp->chown($path, $var);
case 5: // PHP_STREAM_META_GROUP
return $this->sftp->chgrp($path, $var);
case 6: // PHP_STREAM_META_ACCESS
return $this->sftp->chmod($path, $var) !== false;
}
}
/**
* Retrieve the underlaying resource
*
* @param int $cast_as
* @return resource
* @access public
*/
function _stream_cast($cast_as)
{
return $this->sftp->fsock;
}
/**
* Advisory file locking
*
* @param int $operation
* @return bool
* @access public
*/
function _stream_lock($operation)
{
return false;
}
/**
* Renames a file or directory
*
* Attempts to rename oldname to newname, moving it between directories if necessary.
* If newname exists, it will be overwritten. This is a departure from what Net_SFTP
* does.
*
* @param string $path_from
* @param string $path_to
* @return bool
* @access public
*/
function _rename($path_from, $path_to)
{
$path1 = parse_url($path_from);
$path2 = parse_url($path_to);
unset($path1['path'], $path2['path']);
if ($path1 != $path2) {
return false;
}
$path_from = $this->_parse_path($path_from);
$path_to = parse_url($path_to);
if ($path_from === false) {
return false;
}
$path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2
// "It is an error if there already exists a file with the name specified by newpath."
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
if (!$this->sftp->rename($path_from, $path_to)) {
if ($this->sftp->stat($path_to)) {
return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
}
return false;
}
return true;
}
/**
* Open directory handle
*
* The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
* removed in 5.4 I'm just going to ignore it.
*
* Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
* sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
* the SFTP specs:
*
* The SSH_FXP_NAME response has the following format:
*
* uint32 id
* uint32 count
* repeats count times:
* string filename
* string longname
* ATTRS attrs
*
* @param string $path
* @param int $options
* @return bool
* @access public
*/
function _dir_opendir($path, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$this->pos = 0;
$this->entries = $this->sftp->nlist($path);
return $this->entries !== false;
}
/**
* Read entry from directory handle
*
* @return mixed
* @access public
*/
function _dir_readdir()
{
if (isset($this->entries[$this->pos])) {
return $this->entries[$this->pos++];
}
return false;
}
/**
* Rewind directory handle
*
* @return bool
* @access public
*/
function _dir_rewinddir()
{
$this->pos = 0;
return true;
}
/**
* Close directory handle
*
* @return bool
* @access public
*/
function _dir_closedir()
{
return true;
}
/**
* Create a directory
*
* Only valid $options is STREAM_MKDIR_RECURSIVE
*
* @param string $path
* @param int $mode
* @param int $options
* @return bool
* @access public
*/
function _mkdir($path, $mode, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
}
/**
* Removes a directory
*
* Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
* <http://php.net/rmdir> does not have a $recursive parameter as mkdir() does so I don't know how
* STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
* $options. What does 8 correspond to?
*
* @param string $path
* @param int $mode
* @param int $options
* @return bool
* @access public
*/
function _rmdir($path, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->rmdir($path);
}
/**
* Flushes the output
*
* See <http://php.net/fflush>. Always returns true because Net_SFTP doesn't cache stuff before writing
*
* @return bool
* @access public
*/
function _stream_flush()
{
return true;
}
/**
* Retrieve information about a file resource
*
* @return mixed
* @access public
*/
function _stream_stat()
{
$results = $this->sftp->stat($this->path);
if ($results === false) {
return false;
}
return $results;
}
/**
* Delete a file
*
* @param string $path
* @return bool
* @access public
*/
function _unlink($path)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->delete($path, false);
}
/**
* Retrieve information about a file
*
* Ignores the STREAM_URL_STAT_QUIET flag because the entirety of Net_SFTP_Stream is quiet by default
* might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
* cross that bridge when and if it's reached
*
* @param string $path
* @param int $flags
* @return mixed
* @access public
*/
function _url_stat($path, $flags)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
if ($results === false) {
return false;
}
return $results;
}
/**
* Truncate stream
*
* @param int $new_size
* @return bool
* @access public
*/
function _stream_truncate($new_size)
{
if (!$this->sftp->truncate($this->path, $new_size)) {
return false;
}
$this->eof = false;
$this->size = $new_size;
return true;
}
/**
* Change stream options
*
* STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
* The other two aren't supported because of limitations in Net_SFTP.
*
* @param int $option
* @param int $arg1
* @param int $arg2
* @return bool
* @access public
*/
function _stream_set_option($option, $arg1, $arg2)
{
return false;
}
/**
* Close an resource
*
* @access public
*/
function _stream_close()
{
}
/**
* __call Magic Method
*
* When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
* Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
* lets you figure that out.
*
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
*
* @param string
* @param array
* @return mixed
* @access public
*/
function __call($name, $arguments)
{
if (defined('NET_SFTP_STREAM_LOGGING')) {
echo $name . '(';
$last = count($arguments) - 1;
foreach ($arguments as $i => $argument) {
var_export($argument);
if ($i != $last) {
echo ',';
}
}
echo ")\r\n";
}
$name = '_' . $name;
if (!method_exists($this, $name)) {
return false;
}
return call_user_func_array(array($this, $name), $arguments);
}
}
Net_SFTP_Stream::register();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,486 @@
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP versions 4 and 5
*
* Here are some examples of how to use this library:
* <code>
* <?php
* include 'System/SSH/Agent.php';
* include 'Net/SSH2.php';
*
* $agent = new System_SSH_Agent();
*
* $ssh = new Net_SSH2('www.domain.tld');
* if (!$ssh->login('username', $agent)) {
* exit('Login Failed');
* }
*
* echo $ssh->exec('pwd');
* echo $ssh->exec('ls -la');
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category System
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
/**#@+
* Message numbers
*
* @access private
*/
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
define('SYSTEM_SSH_AGENT_FAILURE', 5);
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
/**@+
* Agent forwarding status
*
* @access private
*/
// no forwarding requested and not active
define('SYSTEM_SSH_AGENT_FORWARD_NONE', 0);
// request agent forwarding when opportune
define('SYSTEM_SSH_AGENT_FORWARD_REQUEST', 1);
// forwarding has been request and is active
define('SYSTEM_SSH_AGENT_FORWARD_ACTIVE', 2);
/**#@-*/
/**
* Pure-PHP ssh-agent client identity object
*
* Instantiation should only be performed by System_SSH_Agent class.
* This could be thought of as implementing an interface that Crypt_RSA
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
* The methods in this interface would be getPublicKey, setSignatureMode
* and sign since those are the methods phpseclib looks for to perform
* public key authentication.
*
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent_Identity
{
/**
* Key Object
*
* @var Crypt_RSA
* @access private
* @see self::getPublicKey()
*/
var $key;
/**
* Key Blob
*
* @var string
* @access private
* @see self::sign()
*/
var $key_blob;
/**
* Socket Resource
*
* @var resource
* @access private
* @see self::sign()
*/
var $fsock;
/**
* Default Constructor.
*
* @param resource $fsock
* @return System_SSH_Agent_Identity
* @access private
*/
function __construct($fsock)
{
$this->fsock = $fsock;
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @param resource $fsock
* @access public
*/
function System_SSH_Agent_Identity($fsock)
{
$this->__construct($fsock);
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities()
*
* @param Crypt_RSA $key
* @access private
*/
function setPublicKey($key)
{
$this->key = $key;
$this->key->setPublicKey();
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation.
*
* @param string $key_blob
* @access private
*/
function setPublicKeyBlob($key_blob)
{
$this->key_blob = $key_blob;
}
/**
* Get Public Key
*
* Wrapper for $this->key->getPublicKey()
*
* @param int $format optional
* @return mixed
* @access public
*/
function getPublicKey($format = null)
{
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
}
/**
* Set Signature Mode
*
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
*
* @param int $mode
* @access public
*/
function setSignatureMode($mode)
{
}
/**
* Create a signature
*
* See "2.6.2 Protocol 2 private key signature request"
*
* @param string $message
* @return string
* @access public
*/
function sign($message)
{
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
$packet = pack('Na*', strlen($packet), $packet);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed during signing');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
user_error('Unable to retreive signature');
}
$signature_blob = fread($this->fsock, $length - 1);
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
// the + 12 is for the other various SSH added length fields
return substr($signature_blob, strlen('ssh-rsa') + 12);
}
}
/**
* Pure-PHP ssh-agent client identity factory
*
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
*
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent
{
/**
* Socket Resource
*
* @var resource
* @access private
*/
var $fsock;
/**
* Agent forwarding status
*
* @access private
*/
var $forward_status = SYSTEM_SSH_AGENT_FORWARD_NONE;
/**
* Buffer for accumulating forwarded authentication
* agent data arriving on SSH data channel destined
* for agent unix socket
*
* @access private
*/
var $socket_buffer = '';
/**
* Tracking the number of bytes we are expecting
* to arrive for the agent socket on the SSH data
* channel
*/
var $expected_bytes = 0;
/**
* Default Constructor
*
* @return System_SSH_Agent
* @access public
*/
function __construct()
{
switch (true) {
case isset($_SERVER['SSH_AUTH_SOCK']):
$address = $_SERVER['SSH_AUTH_SOCK'];
break;
case isset($_ENV['SSH_AUTH_SOCK']):
$address = $_ENV['SSH_AUTH_SOCK'];
break;
default:
user_error('SSH_AUTH_SOCK not found');
return false;
}
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
if (!$this->fsock) {
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
}
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @access public
*/
function System_SSH_Agent()
{
$this->__construct();
}
/**
* Request Identities
*
* See "2.5.2 Requesting a list of protocol 2 keys"
* Returns an array containing zero or more System_SSH_Agent_Identity objects
*
* @return array
* @access public
*/
function requestIdentities()
{
if (!$this->fsock) {
return array();
}
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed while requesting identities');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
user_error('Unable to request identities');
}
$identities = array();
$keyCount = current(unpack('N', fread($this->fsock, 4)));
for ($i = 0; $i < $keyCount; $i++) {
$length = current(unpack('N', fread($this->fsock, 4)));
$key_blob = fread($this->fsock, $length);
$key_str = 'ssh-rsa ' . base64_encode($key_blob);
$length = current(unpack('N', fread($this->fsock, 4)));
if ($length) {
$key_str.= ' ' . fread($this->fsock, $length);
}
$length = current(unpack('N', substr($key_blob, 0, 4)));
$key_type = substr($key_blob, 4, $length);
switch ($key_type) {
case 'ssh-rsa':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$key = new Crypt_RSA();
$key->loadKey($key_str);
break;
case 'ssh-dss':
// not currently supported
break;
}
// resources are passed by reference by default
if (isset($key)) {
$identity = new System_SSH_Agent_Identity($this->fsock);
$identity->setPublicKey($key);
$identity->setPublicKeyBlob($key_blob);
$identities[] = $identity;
unset($key);
}
}
return $identities;
}
/**
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return bool
* @access public
*/
function startSSHForwarding($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_NONE) {
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_REQUEST;
}
}
/**
* Request agent forwarding of remote server
*
* @param Net_SSH2 $ssh
* @return bool
* @access private
*/
function _request_forwarding($ssh)
{
$request_channel = $ssh->_get_open_channel();
if ($request_channel === false) {
return false;
}
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$ssh->server_channels[$request_channel],
strlen('auth-agent-req@openssh.com'),
'auth-agent-req@openssh.com',
1
);
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$ssh->_send_binary_packet($packet)) {
return false;
}
$response = $ssh->_get_channel_packet($request_channel);
if ($response === false) {
return false;
}
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_ACTIVE;
return true;
}
/**
* On successful channel open
*
* This method is called upon successful channel
* open to give the SSH Agent an opportunity
* to take further action. i.e. request agent forwarding
*
* @param Net_SSH2 $ssh
* @access private
*/
function _on_channel_open($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_REQUEST) {
$this->_request_forwarding($ssh);
}
}
/**
* Forward data to SSH Agent and return data reply
*
* @param string $data
* @return data from SSH Agent
* @access private
*/
function _forward_data($data)
{
if ($this->expected_bytes > 0) {
$this->socket_buffer.= $data;
$this->expected_bytes -= strlen($data);
} else {
$agent_data_bytes = current(unpack('N', $data));
$current_data_bytes = strlen($data);
$this->socket_buffer = $data;
if ($current_data_bytes != $agent_data_bytes + 4) {
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
return false;
}
}
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
user_error('Connection closed attempting to forward data to SSH agent');
}
$this->socket_buffer = '';
$this->expected_bytes = 0;
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
$agent_reply_data = current(unpack('a*', $agent_reply_data));
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* Pure-PHP ssh-agent client wrapper
*
* PHP versions 4 and 5
*
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
* don't support that kind of directory layout hence the package being moved and
* this "alias" being created to maintain backwards compatibility.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category System
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
require_once 'SSH/Agent.php';

View File

@@ -0,0 +1,228 @@
<?php
define('PICONTROL', true);
(include_once realpath(dirname(__FILE__)).'/../../init.php') or die('Error: 0x0000');
(include_once LIBRARY_PATH.'main/tpl.class.php') or die('Error: 0x0001');
(include_once LIBRARY_PATH.'main/main.function.php') or die('Error: 0x0002');
$host = '127.0.0.1';
$port = (isset($_GET['port'])) ? $_GET['port'] : 0;
$null = NULL;
$tpl = new PiTpl;
$tpl->setTpl($tpl);
$termial = getConfig('terminal:port_'.$port, array());
if (is_array($termial) && $port > 9000 && $port < 9006 && ((empty($termial) || $termial['pid'] == getmypid())))
setConfig('terminal:port_'.$port.'.pid', getmypid());
else
exit();
set_time_limit(0);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, 0, $port);
socket_listen($socket);
$clients = array($socket);
$ssh = NULL;
$stdio = NULL;
$lastLine = '';
$i = 0;
while (true)
{
$changed = $clients;
socket_select($changed, $null, $null, 0, 10);
if (in_array($socket, $changed))
{
$newSocket = socket_accept($socket);
$header = socket_read($newSocket, 1024);
perform_handshaking($header, $newSocket, $host, $port);
if (substr($header, 6, 16) == substr($_COOKIE['_pi-control_login'], 0, 16))
{
$clients[] = $newSocket;
$diff = array_diff($clients, array($socket, $newSocket));
foreach ($diff as $client)
{
$response = mask(json_encode(array('type'=>'system', 'message'=> 'newSession')));
@socket_write($client, $response, strlen($response));
@socket_write($client, 'ping', strlen('ping'));
}
$clients = array($socket, $newSocket);
socket_getpeername($newSocket, $ip);
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
$response = mask(json_encode(array('type'=> 'system', 'message' => 'connected')));
send_message($response);
$response_text = mask(json_encode(array('type' => 'console', 'message' => $lastLine)));
send_message($response_text);
}
else
{
$response = mask(json_encode(array('type'=> 'system', 'message' => 'denied')));
@socket_write($newSocket, $response, strlen($response));
}
}
foreach ($changed as $changedSocket)
{
if (@socket_recv($changedSocket, $buf, 1024, 0) === 0)
{
$found_socket = array_search($changedSocket, $clients);
socket_getpeername($changedSocket, $ip);
unset($clients[$found_socket]);
}
else
{
$received_text = unmask($buf);
$tst_msg = json_decode($received_text);
if (isset($tst_msg->message))
{
$user_message = $tst_msg->message;
if ($user_message == '^PI')
{
removeConfig('terminal:port_'.$port);
socket_close($socket);
exec('kill -9 '.getmypid());
break 2;
}
if ($user_message != '^C')
$ssh->write($user_message."\n");
else
$ssh->write(chr(3));
}
}
}
if (count($clients) == 2 && $ssh === NULL)
{
if (($ssh = $tpl->getSSHResource()) === false)
exit('Login Failed');
$ssh->setTimeout(1);
stream_set_timeout($ssh->fsock, 999999);
}
if ($ssh !== NULL)
{
if ($output = $ssh->read())
{
$ansi = new File_ANSI();
$ansi->appendString($output);
$lastLine = $ansi->getScreen();
$response_text = mask(json_encode(array('type' => 'console', 'message' => $ansi->getScreen())));
send_message($response_text);
$response = mask(json_encode(array('type' => 'system', 'message' => 'connected')));
send_message($response);
}
}
$i += 1;
if ($i == 60)
{
$termial = getConfig('terminal:port_'.$port, array());
if (!is_array($termial) || empty($termial) || $termial['pid'] != getmypid())
{
socket_close($socket);
exec('kill -9 '.getmypid());
break;
}
$i = 0;
}
}
socket_close($socket);
function send_message($msg)
{
global $clients;
foreach ($clients as $client)
@socket_write($client, $msg, strlen($msg));
return true;
}
function unmask($text)
{
$length = ord($text[1]) & 127;
if ($length == 126)
{
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif ($length == 127)
{
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else
{
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i)
$text .= $data[$i] ^ $masks[$i%4];
return $text;
}
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack('CC', $b1, $length);
elseif ($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif ($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
function perform_handshaking($receved_header, $client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_header);
foreach($lines as $line)
{
$line = chop($line);
if (preg_match('/\A(\S+): (.*)\z/', $line, $matches))
$headers[$matches[1]] = $matches[2];
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
exit();
?>

Some files were not shown because too many files have changed in this diff Show More