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') ?>:
+					

+					
* providet by Gavatar
+				
+				
+					
echo('l_userName') ?>:
+					
+				
+				
+					
echo('l_userEmail') ?>:
+					
+				
+				
+			
+			
+				
echo('t_notification') ?>
+				
+				
echo('l_notificationStatus') ?>
+				
+			
+			
+				
echo('t_experimental') ?>
+				
+			
+			
+				
echo('t_changePassword') ?>
+				
+			
+			
+				
echo('t_ota') ?>
+				
+					

+					
+					
+				
+					
+				
+			
+			
+				
echo('t_listUsers') ?>
+				
+					
+						
+							| echo('t_avatar');?>+ | echo('t_userName');?>+ | echo('t_ota');?>+ | echo('t_action');?>+ | 
+					
+					
+						 $user) { ?>
+							
+								| + | + | ' : ''); ?>+ | + | 
+						
+					
+				
+			
+			
+				
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