diff --git a/www/.htaccess b/.htaccess
similarity index 93%
rename from www/.htaccess
rename to .htaccess
index 54bbdf8..71ae402 100644
--- a/www/.htaccess
+++ b/.htaccess
@@ -10,6 +10,7 @@ RewriteRule . - [e=HTTP_AUTHORIZATION:%1]
# serve all files from public subfolder
RewriteCond %{REQUEST_FILENAME} !.php
+RewriteCond %{REQUEST_FILENAME} !.log
RewriteCond %{REQUEST_FILENAME} \.
RewriteRule (.*) ./public/$1 [L]
diff --git a/www/New_JS_EDITOR_ TEST.php b/New_JS_EDITOR_ TEST.php
similarity index 100%
rename from www/New_JS_EDITOR_ TEST.php
rename to New_JS_EDITOR_ TEST.php
diff --git a/www/api.php b/api.php
similarity index 100%
rename from www/api.php
rename to api.php
diff --git a/app/Bootstrap.php b/app/Bootstrap.php
new file mode 100644
index 0000000..3c41b3d
--- /dev/null
+++ b/app/Bootstrap.php
@@ -0,0 +1,93 @@
+';
+ //var_dump($directorys);
+ //echo '';
+
+ $files = new RecursiveIteratorIterator($directorys, RecursiveIteratorIterator::LEAVES_ONLY);
+
+ $filename = $className . static::$extension;
+
+ foreach ($files as $key => $file) {
+ if (strtolower($file->getFilename()) === strtolower($filename) && $file->isReadable()) {
+ include_once $file->getPathname();
+ return;
+ }
+ }
+ }
+
+ static function setRoot($rootPath){
+ static::$root = $rootPath;
+ }
+}
+
+spl_autoload_register("Autoloader::ClassLoader");
+Autoloader::setRoot('/var/www/dev.steelants.cz/vasek/home-update/');
+
+class ErrorHandler {
+ static function exception($exception){
+ error_log($exception);
+ http_response_code($exception->getCode());
+ $message = [
+ 'code' => $exception->getCode(),
+ 'message' => $exception->getMessage(),
+ ];
+ echo json_encode($message);
+
+ $apiLogManager = new LogManager('../logs/'. date("Y-m-d").'.log');
+ $apiLogManager->write("[APACHE] ERROR\n" . json_encode($message, JSON_PRETTY_PRINT), LogRecordType::INFO);
+ }
+}
+set_exception_handler("ErrorHandler::exception");
+
+$json = file_get_contents('php://input');
+$obj = json_decode($json, true);
+
+$apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log');
+
+$apiLogManager->write("[API] request body\n" . json_encode($obj, JSON_PRETTY_PRINT), LogRecordType::INFO);
+$apiLogManager->write("[API] POST body\n" . json_encode($_POST, JSON_PRETTY_PRINT), LogRecordType::INFO);
+$apiLogManager->write("[API] GET body\n" . json_encode($_GET, JSON_PRETTY_PRINT), LogRecordType::INFO);
+
+//Debug
+error_reporting(E_ALL);
+ini_set( 'display_errors','1');
+
+//setup
+ini_set ('session.cookie_httponly', '1');
+ini_set('session.cookie_domain', $_SERVER['HTTP_HOST']);
+ini_set('session.cookie_path', str_replace("login", "", str_replace('https://' . $_SERVER['HTTP_HOST'], "", $_SERVER['REQUEST_URI'])));
+ini_set('session.cookie_secure', '1');
+session_start ();
+mb_internal_encoding ("UTF-8");
+
+// import configs
+require_once '../config/config.php';
+
+// Logs
+$logManager = new LogManager();
+
+// Language
+if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
+ $langTag = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
+ $langMng = new LanguageManager($langTag);
+ $langMng->load();
+}
+
+//D B Conector
+Db::connect (DBHOST, DBUSER, DBPASS, DBNAME);
+
+// TODO: Přesunout do Login Pohledu
+$userManager = new UserManager();
+
+// import routes
+require_once '../app/Routes.php';
diff --git a/app/Routes.php b/app/Routes.php
new file mode 100644
index 0000000..f973faa
--- /dev/null
+++ b/app/Routes.php
@@ -0,0 +1,31 @@
+setDefault(function(){
+ echo $_GET['url'].': 404';
+});
+
+//Pages
+$router->any('/', 'Log');
+$router->any('/login', 'Login');
+$router->any('/logout', 'Logout');
+$router->any('/automation', 'Automation');
+$router->any('/setting', 'Setting');
+$router->any('/ajax', 'Ajax');
+
+$router->post('/api/login', 'AuthApi@login');
+$router->post('/api/logout', 'AuthApi@logout');
+
+$router->get('/api/devices', 'DevicesApi@default');
+$router->get('/api/rooms', 'RoomsApi@default');
+
+$router->get('/api/HA/auth', 'GoogleHomeApi@autorize');
+$router->any('/api/HA', 'GoogleHomeApi@response');
+
+// examples
+$router->any('/api/example', 'ExampleApi@example');
+$router->any('/example', 'ExampleController@index');
+$router->any('/example/subpage', 'ExampleController@subpage');
+
+$router->run($_SERVER['REQUEST_METHOD'], '/'.(isset($_GET['url']) ? $_GET['url'] : ''));
diff --git a/app/api/AuthApi.php b/app/api/AuthApi.php
new file mode 100644
index 0000000..a9d6101
--- /dev/null
+++ b/app/api/AuthApi.php
@@ -0,0 +1,25 @@
+getToken($this->input->username,$this->input->password);
+ if (!$token) {
+ throw new Exception("Auth failed", 401);
+ }
+ $this->response(['token' => $token]);
+ }
+
+ public function logout(){
+ $authenticationBearrer = $_SERVER['HTTP_AUTHORIZATION'];
+ if (!(new AuthManager)->deleteToken($authenticationBearrer)) {
+ throw new Exception("logout Failed", 401);
+ }
+ }
+
+ public function registration(){
+
+ }
+
+ public function restartPassword(){
+
+ }
+}
diff --git a/app/api/DevicesApi.php b/app/api/DevicesApi.php
new file mode 100644
index 0000000..daa8ece
--- /dev/null
+++ b/app/api/DevicesApi.php
@@ -0,0 +1,17 @@
+requireAuth();
+ $response = [];
+
+ // TODO: process the request
+
+ $this->response($response);
+ }
+
+ public function getDevicesByRoom($roomId){
+
+ }
+}
diff --git a/app/api/ExampleApi.php b/app/api/ExampleApi.php
new file mode 100644
index 0000000..0fe5727
--- /dev/null
+++ b/app/api/ExampleApi.php
@@ -0,0 +1,24 @@
+requireAuth();
+ // if user is logged in, next lines will be processed
+ // otherwise script get terminated with 401 UNAUTHORIZED
+
+
+ // input data are stored in $this->input
+ // in this example we just copy input to response
+ $response = $this->input;
+
+
+ // this method returns response as json
+ $this->response($response);
+ // you can specify returned http code by second optional parameter
+ // default value is 200
+ // $this->response($response, $httpCode);
+ }
+
+}
diff --git a/app/api/GoogleHomeApi.php b/app/api/GoogleHomeApi.php
new file mode 100644
index 0000000..40f67cd
--- /dev/null
+++ b/app/api/GoogleHomeApi.php
@@ -0,0 +1,46 @@
+write("[Google Home] action.devices.SYNC", LogRecordType::INFO);
+ break;
+
+ case 'action.devices.QUERY':
+ GoogleHome::query($obj['requestId'], $obj['inputs'][0]['payload']);
+ //$apiLogManager->write("[Google Home] action.devices.QUERY", LogRecordType::INFO);
+ break;
+
+ case 'action.devices.EXECUTE':
+ GoogleHome::execute($obj['requestId'], $obj['inputs'][0]['payload']);
+ $apiLogManager->write("[Google Home] action.devices.EXECUTE", LogRecordType::INFO);
+ break;
+ }
+ }
+
+ static function autorize(){
+ $json = file_get_contents('php://input');
+ $obj = json_decode($json, true);
+
+ $apiLogManager = new LogManager('../logs/api/HA/'. date("Y-m-d").'.log');
+ $apiLogManager->write("[API] request body\n" . json_encode($obj, JSON_PRETTY_PRINT), LogRecordType::INFO);
+ $apiLogManager->write("[API] GET body\n" . json_encode($_GET, JSON_PRETTY_PRINT), LogRecordType::INFO);
+
+ $get = [
+ "access_token"=>"2222255888",
+ "token_type"=>"Bearer",
+ "state"=>$_GET["state"],
+ ];
+
+ echo $_GET["redirect_uri"] . '#' . http_build_query($get) ;
+ echo 'FINISH';
+ }
+}
diff --git a/www/app/api/RoomsApi.php b/app/api/RoomsApi.php
similarity index 100%
rename from www/app/api/RoomsApi.php
rename to app/api/RoomsApi.php
diff --git a/app/controllers/ExampleController.php b/app/controllers/ExampleController.php
new file mode 100644
index 0000000..45a6d8c
--- /dev/null
+++ b/app/controllers/ExampleController.php
@@ -0,0 +1,14 @@
+view->title = 'Example title';
+ $this->view->render('example.phtml');
+ }
+
+ public function subpage(){
+ echo 'subpage';
+ }
+
+}
diff --git a/app/controllers/automationController.php b/app/controllers/automationController.php
new file mode 100644
index 0000000..f7ae6fd
--- /dev/null
+++ b/app/controllers/automationController.php
@@ -0,0 +1,77 @@
+ $_POST['atSelector'],
+ "value" => $value,
+ ], JSON_PRETTY_PRINT);
+ $onDays = $_POST['atDays'];
+
+ //Debug
+ // if (DEBUGMOD == 1) {
+ // echo '
+
+
+ prepare('item', 'log');
+ $partial->prepare('langMng',$LANGMNG);
+ $partial->prepare('debugMod',$DEBUGMOD);
+ $partial->render();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ';
+ foreach ($file_lines as $line) {
+ echo $line;
+ }
+ echo '';
+ }
+ ?>
+
+
+
+ render();
+ //TODO js do main.js
+ ?>
+
+
diff --git a/app/views/templates/login.phtml b/app/views/templates/login.phtml
new file mode 100644
index 0000000..ae0636b
--- /dev/null
+++ b/app/views/templates/login.phtml
@@ -0,0 +1,27 @@
+
+
+
+ render();
+ ?>
+
+
+
+ prepare('ota',$ota);
+ $partial->render();
+ } else {
+ $partial = new Partial('loginForm');
+ $partial->render();
+ }
+ ?>
+
+ render();
+ ?>
+
+
diff --git a/app/views/templates/part/automationButton.phtml b/app/views/templates/part/automationButton.phtml
new file mode 100644
index 0000000..002aaab
--- /dev/null
+++ b/app/views/templates/part/automationButton.phtml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ type) {
+ case 'sunSet':
+ echo'';
+ break;
+
+ case 'sunRise':
+ echo' ';
+ break;
+
+ case 'inHome':
+ echo'';
+ break;
+
+ case 'outHome':
+ echo'';
+ break;
+
+ case 'outDevice':
+ echo'';
+ break;
+
+ default:
+ echo'';
+ break;
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/views/templates/part/automationCreate.phtml b/app/views/templates/part/automationCreate.phtml
new file mode 100644
index 0000000..44a731a
--- /dev/null
+++ b/app/views/templates/part/automationCreate.phtml
@@ -0,0 +1,69 @@
+
+
+
+
echo('t_createAutomation')?>
+
+
+
diff --git a/app/views/templates/part/automationCreateFinal.phtml b/app/views/templates/part/automationCreateFinal.phtml
new file mode 100644
index 0000000..0eb48c3
--- /dev/null
+++ b/app/views/templates/part/automationCreateFinal.phtml
@@ -0,0 +1,44 @@
+
+
+
+
echo('t_createAutomation'); ?>
+
+
+
diff --git a/app/views/templates/part/automationEdit.phtml b/app/views/templates/part/automationEdit.phtml
new file mode 100644
index 0000000..6411388
--- /dev/null
+++ b/app/views/templates/part/automationEdit.phtml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
echo('t_createAutomation');?>
+
+
+
+
diff --git a/app/views/templates/part/footer.phtml b/app/views/templates/part/footer.phtml
new file mode 100644
index 0000000..0fcb4bf
--- /dev/null
+++ b/app/views/templates/part/footer.phtml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/views/templates/part/head.phtml b/app/views/templates/part/head.phtml
new file mode 100644
index 0000000..1555607
--- /dev/null
+++ b/app/views/templates/part/head.phtml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/views/templates/part/loginForm.phtml b/app/views/templates/part/loginForm.phtml
new file mode 100644
index 0000000..c06b535
--- /dev/null
+++ b/app/views/templates/part/loginForm.phtml
@@ -0,0 +1,20 @@
+
diff --git a/app/views/templates/part/loginOta.phtml b/app/views/templates/part/loginOta.phtml
new file mode 100644
index 0000000..3e8d294
--- /dev/null
+++ b/app/views/templates/part/loginOta.phtml
@@ -0,0 +1,13 @@
+
diff --git a/app/views/templates/part/menu.phtml b/app/views/templates/part/menu.phtml
new file mode 100644
index 0000000..79c3fa4
--- /dev/null
+++ b/app/views/templates/part/menu.phtml
@@ -0,0 +1,35 @@
+
+ [
+ 'slug' => 'setting',
+ 'lngKey' => 'settings',
+ 'path' => 'setting',
+ ],
+ 'fa-calendar-o' => [
+ 'slug' => 'automation',
+ 'lngKey' => 'automatization',
+ 'path' => 'automation',
+ ],
+ 'fa-bug' =>[
+ 'slug' => 'log',
+ 'lngKey' => 'log',
+ 'path' => '',
+ ],
+ ];
+ foreach ( $menuItems as $key => $value) {
+ if ($DEBUGMOD == 0 && $value['path'] == 'log') {
+ continue;
+ }
+ ?>
+
+
+
+
diff --git a/app/views/templates/part/test.phtml b/app/views/templates/part/test.phtml
new file mode 100644
index 0000000..002c703
--- /dev/null
+++ b/app/views/templates/part/test.phtml
@@ -0,0 +1,3 @@
+
+ TEST - TEST
+
\ No newline at end of file
diff --git a/app/views/templates/setting.phtml b/app/views/templates/setting.phtml
new file mode 100644
index 0000000..18ac4f2
--- /dev/null
+++ b/app/views/templates/setting.phtml
@@ -0,0 +1,203 @@
+
+
+
+ prepare('baseDir', $BASEDIR);
+ $partial->render();
+ ?>
+
+
+
+
+
+
+ prepare('item', 'setting');
+ $partial->prepare('langMng',$LANGMNG);
+ $partial->prepare('debugMod',$DEBUGMOD);
+ $partial->render();
+ ?>
+
+
+
+
+
+ echo('t_pageAfterLogIn') ?>
+
+
+
+
+
echo('t_profile') ?>
+
+
echo('l_userAvatar') ?>:
+
![](<?php echo $USERAVATARURL; ?>)
+
* providet by Gavatar
+
+
+
echo('l_userName') ?>:
+
+
+
+
echo('l_userEmail') ?>:
+
+
+
+
+
+
echo('t_notification') ?>
+
+
echo('l_notificationStatus') ?>
+
+
+
+
echo('t_experimental') ?>
+
+
+
+
echo('t_changePassword') ?>
+
+
+
+
echo('t_ota') ?>
+
+
![](<?php echo $QRURL;?>)
+
+
+
+
+
+
+
+
echo('t_listUsers') ?>
+
+
+
+ echo('t_avatar');?> |
+ echo('t_userName');?> |
+ echo('t_ota');?> |
+ echo('t_action');?> |
+
+
+
+ $user) { ?>
+
+ ![](<?php echo $user['gavatar_url']; ?>) |
+ |
+ ' : ''); ?> |
+ |
+
+
+
+
+
+
+
echo('t_createuser') ?>
+
+
+
+
+
+
echo('t_listRooms') ?>
+
+
+
+ echo('t_roomName');?> |
+ echo('t_action');?> |
+
+
+
+ $room) { ?>
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
echo('t_createRoom') ?>
+
+
+
+
+
+
+
+
+ render();
+ ?>
+
+
+
+
diff --git a/app/views/templates/template.phtml b/app/views/templates/template.phtml
new file mode 100644
index 0000000..090cd1b
--- /dev/null
+++ b/app/views/templates/template.phtml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
title ?>
+
+
+ content(); ?>
+
+
diff --git a/www/config/config_sample.php b/config/config_sample.php
similarity index 100%
rename from www/config/config_sample.php
rename to config/config_sample.php
diff --git a/www/docker-compose.yml b/docker-compose.yml
similarity index 100%
rename from www/docker-compose.yml
rename to docker-compose.yml
diff --git a/www/lang/cs.php b/lang/cs.php
similarity index 100%
rename from www/lang/cs.php
rename to lang/cs.php
diff --git a/www/lang/en.php b/lang/en.php
similarity index 100%
rename from www/lang/en.php
rename to lang/en.php
diff --git a/www/lang/nl.php b/lang/nl.php
similarity index 100%
rename from www/lang/nl.php
rename to lang/nl.php
diff --git a/www/lang/pl.php b/lang/pl.php
similarity index 100%
rename from www/lang/pl.php
rename to lang/pl.php
diff --git a/www/library/ApiController.php b/library/ApiController.php
similarity index 100%
rename from www/library/ApiController.php
rename to library/ApiController.php
diff --git a/www/library/Controller.php b/library/Controller.php
similarity index 100%
rename from www/library/Controller.php
rename to library/Controller.php
diff --git a/www/library/DB.php b/library/DB.php
similarity index 100%
rename from www/library/DB.php
rename to library/DB.php
diff --git a/library/Partial.php b/library/Partial.php
new file mode 100644
index 0000000..5609556
--- /dev/null
+++ b/library/Partial.php
@@ -0,0 +1,34 @@
+debug = $debug;
+ if (!empty('../app/views/templates/part/' . $path . '.phtml') && file_exists('../app/views/templates/part/' . $path . '.phtml')) {
+ $this->path = $path;
+ } else {
+ echo '
';
+ echo 'PHTML: Parial File ' . $path . ' not found';
+ echo '
';
+ die();
+ }
+ }
+
+ function prepare($searchS, $repleaceS) {
+ if (!empty($searchS)) {
+ $this->assignedValues[strtoupper($searchS)] = $repleaceS;
+ }
+ echo ($this->debug == true ? var_dump($this->assignedValues) : '');
+ }
+
+ function render() {
+ if (!empty($this->assignedValues)){
+ extract($this->assignedValues);
+ }
+
+ require('../app/views/templates/part/' . $this->path . '.phtml');
+ }
+}
diff --git a/www/library/Router.php b/library/Router.php
similarity index 100%
rename from www/library/Router.php
rename to library/Router.php
diff --git a/www/library/Template.php b/library/Template.php
similarity index 100%
rename from www/library/Template.php
rename to library/Template.php
diff --git a/www/library/View.php b/library/View.php
similarity index 100%
rename from www/library/View.php
rename to library/View.php
diff --git a/www/library/vendor/PHPGangsta_GoogleAuthenticator.php b/library/vendor/GoogleAuthenticator.php
similarity index 100%
rename from www/library/vendor/PHPGangsta_GoogleAuthenticator.php
rename to library/vendor/GoogleAuthenticator.php
diff --git a/library/vendor/PHPGangsta_GoogleAuthenticator.php b/library/vendor/PHPGangsta_GoogleAuthenticator.php
new file mode 100644
index 0000000..bf7d116
--- /dev/null
+++ b/library/vendor/PHPGangsta_GoogleAuthenticator.php
@@ -0,0 +1,252 @@
+_getBase32LookupTable();
+
+ // Valid secret lengths are 80 to 640 bits
+ if ($secretLength < 16 || $secretLength > 128) {
+ throw new Exception('Bad secret length');
+ }
+ $secret = '';
+ $rnd = false;
+ if (function_exists('random_bytes')) {
+ $rnd = random_bytes($secretLength);
+ } elseif (function_exists('mcrypt_create_iv')) {
+ $rnd = mcrypt_create_iv($secretLength, MCRYPT_DEV_URANDOM);
+ } elseif (function_exists('openssl_random_pseudo_bytes')) {
+ $rnd = openssl_random_pseudo_bytes($secretLength, $cryptoStrong);
+ if (!$cryptoStrong) {
+ $rnd = false;
+ }
+ }
+ if ($rnd !== false) {
+ for ($i = 0; $i < $secretLength; ++$i) {
+ $secret .= $validChars[ord($rnd[$i]) & 31];
+ }
+ } else {
+ throw new Exception('No source of secure random');
+ }
+
+ return $secret;
+ }
+
+ /**
+ * Calculate the code, with given secret and point in time.
+ *
+ * @param string $secret
+ * @param int|null $timeSlice
+ *
+ * @return string
+ */
+ public function getCode($secret, $timeSlice = null)
+ {
+ if ($timeSlice === null) {
+ $timeSlice = floor(time() / 30);
+ }
+
+ $secretkey = $this->_base32Decode($secret);
+
+ // Pack time into binary string
+ $time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice);
+ // Hash it with users secret key
+ $hm = hash_hmac('SHA1', $time, $secretkey, true);
+ // Use last nipple of result as index/offset
+ $offset = ord(substr($hm, -1)) & 0x0F;
+ // grab 4 bytes of the result
+ $hashpart = substr($hm, $offset, 4);
+
+ // Unpak binary value
+ $value = unpack('N', $hashpart);
+ $value = $value[1];
+ // Only 32 bits
+ $value = $value & 0x7FFFFFFF;
+
+ $modulo = pow(10, $this->_codeLength);
+
+ return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT);
+ }
+
+ /**
+ * Get QR-Code URL for image, from google charts.
+ *
+ * @param string $name
+ * @param string $secret
+ * @param string $title
+ * @param array $params
+ *
+ * @return string
+ */
+ public function getQRCodeGoogleUrl($name, $secret, $title = null, $params = array())
+ {
+ $width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200;
+ $height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200;
+ $level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M';
+
+ $urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
+ if (isset($title)) {
+ $urlencoded .= urlencode('&issuer='.urlencode($title));
+ }
+
+ return "https://api.qrserver.com/v1/create-qr-code/?data=$urlencoded&size=${width}x${height}&ecc=$level";
+ }
+
+ /**
+ * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now.
+ *
+ * @param string $secret
+ * @param string $code
+ * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
+ * @param int|null $currentTimeSlice time slice if we want use other that time()
+ *
+ * @return bool
+ */
+ public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null)
+ {
+ if ($currentTimeSlice === null) {
+ $currentTimeSlice = floor(time() / 30);
+ }
+
+ if (strlen($code) != 6) {
+ return false;
+ }
+
+ for ($i = -$discrepancy; $i <= $discrepancy; ++$i) {
+ $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
+ if ($this->timingSafeEquals($calculatedCode, $code)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set the code length, should be >=6.
+ *
+ * @param int $length
+ *
+ * @return PHPGangsta_GoogleAuthenticator
+ */
+ public function setCodeLength($length)
+ {
+ $this->_codeLength = $length;
+
+ return $this;
+ }
+
+ /**
+ * Helper class to decode base32.
+ *
+ * @param $secret
+ *
+ * @return bool|string
+ */
+ protected function _base32Decode($secret)
+ {
+ if (empty($secret)) {
+ return '';
+ }
+
+ $base32chars = $this->_getBase32LookupTable();
+ $base32charsFlipped = array_flip($base32chars);
+
+ $paddingCharCount = substr_count($secret, $base32chars[32]);
+ $allowedValues = array(6, 4, 3, 1, 0);
+ if (!in_array($paddingCharCount, $allowedValues)) {
+ return false;
+ }
+ for ($i = 0; $i < 4; ++$i) {
+ if ($paddingCharCount == $allowedValues[$i] &&
+ substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) {
+ return false;
+ }
+ }
+ $secret = str_replace('=', '', $secret);
+ $secret = str_split($secret);
+ $binaryString = '';
+ for ($i = 0; $i < count($secret); $i = $i + 8) {
+ $x = '';
+ if (!in_array($secret[$i], $base32chars)) {
+ return false;
+ }
+ for ($j = 0; $j < 8; ++$j) {
+ $x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
+ }
+ $eightBits = str_split($x, 8);
+ for ($z = 0; $z < count($eightBits); ++$z) {
+ $binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : '';
+ }
+ }
+
+ return $binaryString;
+ }
+
+ /**
+ * Get array with all 32 characters for decoding from/encoding to base32.
+ *
+ * @return array
+ */
+ protected function _getBase32LookupTable()
+ {
+ return array(
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
+ 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
+ '=', // padding char
+ );
+ }
+
+ /**
+ * A timing safe equals comparison
+ * more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html.
+ *
+ * @param string $safeString The internal (safe) value to be checked
+ * @param string $userString The user submitted (unsafe) value
+ *
+ * @return bool True if the two strings are identical
+ */
+ private function timingSafeEquals($safeString, $userString)
+ {
+ if (function_exists('hash_equals')) {
+ return hash_equals($safeString, $userString);
+ }
+ $safeLen = strlen($safeString);
+ $userLen = strlen($userString);
+
+ if ($userLen != $safeLen) {
+ return false;
+ }
+
+ $result = 0;
+
+ for ($i = 0; $i < $userLen; ++$i) {
+ $result |= (ord($safeString[$i]) ^ ord($userString[$i]));
+ }
+
+ // They are only identical strings if $result is exactly 0...
+ return $result === 0;
+ }
+}
diff --git a/www/logs/.gitkeep b/logs/.gitkeep
similarity index 100%
rename from www/logs/.gitkeep
rename to logs/.gitkeep
diff --git a/www/manifest.json b/manifest.json
similarity index 100%
rename from www/manifest.json
rename to manifest.json
diff --git a/www/public/.htaccess b/public/.htaccess
similarity index 100%
rename from www/public/.htaccess
rename to public/.htaccess
diff --git a/www/public/Elementum/scss/elements/_buttons.scss b/public/Elementum/scss/elements/_buttons.scss
similarity index 100%
rename from www/public/Elementum/scss/elements/_buttons.scss
rename to public/Elementum/scss/elements/_buttons.scss
diff --git a/www/public/css/font-awesome.min.css b/public/css/font-awesome.min.css
similarity index 100%
rename from www/public/css/font-awesome.min.css
rename to public/css/font-awesome.min.css
diff --git a/public/css/loading.css b/public/css/loading.css
new file mode 100644
index 0000000..6c58598
--- /dev/null
+++ b/public/css/loading.css
@@ -0,0 +1,19 @@
+.loader {
+ border: 16px solid #f3f3f3;
+ border-radius: 50%;
+ border-top: 16px solid rgb(101, 30, 122);;
+ width: 100%;
+ height: 100%;
+ -webkit-animation: spin 2s linear infinite; /* Safari */
+ animation: spin 2s linear infinite;
+}
+
+@-webkit-keyframes spin {
+ 0% { -webkit-transform: rotate(0deg); }
+ 100% { -webkit-transform: rotate(360deg); }
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
\ No newline at end of file
diff --git a/www/public/css/main.css b/public/css/main.css
similarity index 100%
rename from www/public/css/main.css
rename to public/css/main.css
diff --git a/www/public/css/main.css.map b/public/css/main.css.map
similarity index 100%
rename from www/public/css/main.css.map
rename to public/css/main.css.map
diff --git a/www/public/css/modal.css b/public/css/modal.css
similarity index 100%
rename from www/public/css/modal.css
rename to public/css/modal.css
diff --git a/www/public/css/override.css b/public/css/override.css
similarity index 100%
rename from www/public/css/override.css
rename to public/css/override.css
diff --git a/www/public/css/pre.css b/public/css/pre.css
similarity index 100%
rename from www/public/css/pre.css
rename to public/css/pre.css
diff --git a/www/public/fonts/FontAwesome.otf b/public/fonts/FontAwesome.otf
similarity index 100%
rename from www/public/fonts/FontAwesome.otf
rename to public/fonts/FontAwesome.otf
diff --git a/www/public/fonts/Metropolis-Medium.otf b/public/fonts/Metropolis-Medium.otf
similarity index 100%
rename from www/public/fonts/Metropolis-Medium.otf
rename to public/fonts/Metropolis-Medium.otf
diff --git a/www/public/fonts/Metropolis-Regular.otf b/public/fonts/Metropolis-Regular.otf
similarity index 100%
rename from www/public/fonts/Metropolis-Regular.otf
rename to public/fonts/Metropolis-Regular.otf
diff --git a/www/public/fonts/Metropolis-SemiBold.otf b/public/fonts/Metropolis-SemiBold.otf
similarity index 100%
rename from www/public/fonts/Metropolis-SemiBold.otf
rename to public/fonts/Metropolis-SemiBold.otf
diff --git a/www/public/fonts/fontawesome-webfont.eot b/public/fonts/fontawesome-webfont.eot
similarity index 100%
rename from www/public/fonts/fontawesome-webfont.eot
rename to public/fonts/fontawesome-webfont.eot
diff --git a/www/public/fonts/fontawesome-webfont.svg b/public/fonts/fontawesome-webfont.svg
similarity index 100%
rename from www/public/fonts/fontawesome-webfont.svg
rename to public/fonts/fontawesome-webfont.svg
diff --git a/www/public/fonts/fontawesome-webfont.ttf b/public/fonts/fontawesome-webfont.ttf
similarity index 100%
rename from www/public/fonts/fontawesome-webfont.ttf
rename to public/fonts/fontawesome-webfont.ttf
diff --git a/www/public/fonts/fontawesome-webfont.woff b/public/fonts/fontawesome-webfont.woff
similarity index 100%
rename from www/public/fonts/fontawesome-webfont.woff
rename to public/fonts/fontawesome-webfont.woff
diff --git a/www/public/fonts/fontawesome-webfont.woff2 b/public/fonts/fontawesome-webfont.woff2
similarity index 100%
rename from www/public/fonts/fontawesome-webfont.woff2
rename to public/fonts/fontawesome-webfont.woff2
diff --git a/www/public/images/icon-192x192.png b/public/images/icon-192x192.png
similarity index 100%
rename from www/public/images/icon-192x192.png
rename to public/images/icon-192x192.png
diff --git a/www/public/images/icon-512x512.png b/public/images/icon-512x512.png
similarity index 100%
rename from www/public/images/icon-512x512.png
rename to public/images/icon-512x512.png
diff --git a/www/public/index.php b/public/index.php
similarity index 100%
rename from www/public/index.php
rename to public/index.php
diff --git a/www/public/js/automation.js b/public/js/automation.js
similarity index 100%
rename from www/public/js/automation.js
rename to public/js/automation.js
diff --git a/www/public/js/jquery.js b/public/js/jquery.js
similarity index 100%
rename from www/public/js/jquery.js
rename to public/js/jquery.js
diff --git a/www/public/js/jquery.redirect.js b/public/js/jquery.redirect.js
similarity index 100%
rename from www/public/js/jquery.redirect.js
rename to public/js/jquery.redirect.js
diff --git a/www/public/js/post.js b/public/js/post.js
similarity index 100%
rename from www/public/js/post.js
rename to public/js/post.js
diff --git a/www/public/js/script.js b/public/js/script.js
similarity index 100%
rename from www/public/js/script.js
rename to public/js/script.js
diff --git a/www/public/js/setting.js b/public/js/setting.js
similarity index 100%
rename from www/public/js/setting.js
rename to public/js/setting.js
diff --git a/www/serviceWorker.js b/serviceWorker.js
similarity index 100%
rename from www/serviceWorker.js
rename to serviceWorker.js
diff --git a/www/update.php b/update.php
similarity index 100%
rename from www/update.php
rename to update.php
diff --git a/www/updater/.gitkeep b/updater/.gitkeep
similarity index 100%
rename from www/updater/.gitkeep
rename to updater/.gitkeep