Daniele Bonini (皮夕): WebDev, DevOps and project care by lots of Simplicity bits 3 жил өмнө
parent
commit
d0fb3a7f22

+ 85 - 0
Private/config/config.inc.sample

@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Invenktory.
+ *
+ * Invenktory is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Invenktory is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Invenktory. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * config.inc
+ * 
+ * Invenktory configuration settings.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode     
+ */
+
+define('DEBUG', true);
+ 
+define('APP_NAME', "Invenktory");
+
+// password: yourpassword
+// salt: yoursalt
+define('APP_HASH', "");
+
+define('APP_SPLASH', true);
+
+define('APP_SCRIPT_PATH', "/var/www/YourWebApp/Private/scripts");
+define('APP_ERROR_PATH', "/var/www/YourWebApp/Private/error");
+define('APP_PROMPT', "INV:~ $1$");
+define('APP_SALT', "yoursalt");
+define('APP_INV_PATH', "/var/www/YourWebApp/Public/stage");
+
+define('CMDLINE_VALIDCMDS', "~|help|ls|pwd|cd|cd ..|cp|mv|show|edit|");
+
+// Set here the max items/devices per xml file
+define('FILE_MAX_ITEMS', 10);
+
+define('HISTORY_MAX_ITEMS', 50);
+
+define('RECALL_HISTORY_MAX_ITEMS', 50);
+
+$CONFIG = [
+
+   'DEBUG' => true,
+
+   'APP' => [
+      'NAME' => "Http Console",
+      'HASH' => "",  
+      'SPLASH' => true,
+      'SCRIPT_PATH' => "/var/www/YourWebApp/Private/scripts",
+      'ERROR_PATH' => "/var/www/YourWebApp/Private/error",
+      'PROMPT' => "INV:~ $1$",
+      'SALT' => "yoursalt",
+      'INV_PATH' => "/var/www/YourWebApp/Public/stage"
+      ],
+     
+    'CMDLINE' => [
+       'VALIDCMDS' => "~|help|ls|pwd|cd|cd ..|cp|mv|show|edit|"  
+      ],
+
+    'FILE' => [
+       'MAX_ITEMS' => 10
+      ],
+      
+    'HISTORY' => [
+       'MAX_ITEMS' => 50
+      ],
+
+    'RECALL_HISTORY' => [
+       'MAX_ITEMS' => 50
+      ]
+    
+    ];  

+ 94 - 0
Private/config/const.inc

@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Http Console.
+ *
+ * Http Console is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Http Console is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * const.inc
+ * 
+ * Http Console constant file.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode     
+ */
+
+if (!defined("PHP_BR")) {
+  define('PHP_BR', "<br>");
+}
+if (!defined("PHP_CN")) {
+  define('PHP_CN', "zh-CN");
+}
+if (!defined("PHP_EN")) {
+  define('PHP_EN', "en-US");
+}
+if (!defined("PHP_ES")) {
+  define('PHP_ES', "es-ES");
+}
+if (!defined("PHP_FR")) {
+  define('PHP_FR', "fr-FR");
+}
+if (!defined("PHP_HYPHEN")) {
+  define('PHP_HYPHEN', "-");
+}
+if (!defined("PHP_IT")) {
+  define('PHP_IT', "it-IT");
+}
+if (!defined("PHP_PIPE")) {
+  define('PHP_PIPE', "|");
+}
+if (!defined("PHP_FILE_PIPE")) {
+  define('PHP_FILE_PIPE', ">");
+}
+if (!defined("PHP_SLASH")) {
+  define('PHP_SLASH', "/");
+}
+if (!defined("PHP_SPACE")) {
+  define('PHP_SPACE', " ");
+}
+if (!defined("PHP_STR")) {
+  define('PHP_STR', "");
+}
+if (!defined("PHP_TILDE")) {
+  define('PHP_TILDE', "~");
+}
+if (!defined("PHP_UNDERSCORE")) {
+  define('PHP_UNDERSCORE', "_");
+}
+if (!defined("PHP_UPLOAD_ERR_OK")) {
+  define('PHP_UPLOAD_ERR_OK', 0);
+}
+if (!defined("PHP_UPLOAD_ERR_INI_SIZE")) {
+  define('PHP_UPLOAD_ERR_INI_SIZE', 1);
+}
+if (!defined("PHP_UPLOAD_ERR_FORM_SIZE")) {
+  define('PHP_UPLOAD_ERR_FORM_SIZE', 2);
+}
+if (!defined("PHP_UPLOAD_ERR_PARTIAL")) {
+  define('PHP_UPLOAD_ERR_PARTIAL', 3);
+}
+if (!defined("PHP_UPLOAD_ERR_NO_FILE")) {
+  define('PHP_UPLOAD_ERR_NO_FILE', 4);
+}
+if (!defined("PHP_UPLOAD_ERR_NO_TMP_DIR")) {
+  define('PHP_UPLOAD_ERR_NO_TMP_DIR', 6);
+}
+if (!defined("PHP_UPLOAD_ERR_CANT_WRITE")) {
+  define('PHP_UPLOAD_ERR_CANT_WRITE', 7);
+}
+if (!defined("PHP_UPLOAD_ERR_EXTENSION")) {
+  define('PHP_UPLOAD_ERR_EXTENSION', 8);
+}

+ 66 - 0
Private/core/init.inc

@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Invenktory.
+ *
+ * Invenktory is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Invenktory is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * init.inc
+ * 
+ * Invenktory initialization file.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode     
+ */
+ 
+error_reporting(E_ALL & ~ (E_WARNING | E_NOTICE | E_STRICT | E_DEPRECATED));  
+ini_set('display_startup_errors',1);  
+ini_set('display_errors',1);  
+ini_set('log_errors',1);
+
+require dirname(__DIR__) . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "config.inc";
+
+// Checking a little the configuration..
+if (!file_exists(APP_INV_PATH)) {
+  die("Inventory folder doesn't exist. You must create an inventory folder in your web app public path and configure it properly inside the config file.");
+}	
+
+define("APP_SAMPLE_DIR", APP_INV_PATH . DIRECTORY_SEPARATOR . ".INVsampledir");
+if (!file_exists(APP_SAMPLE_DIR) || !is_dir(APP_SAMPLE_DIR)) {
+  die("Sample folder doesn't exist. You must create a sample folder named '.INVsampledir' inside your inventory folder. Give to it the proper write permissions.");
+}		
+
+define("APP_SAMPLE_FILE", APP_INV_PATH . DIRECTORY_SEPARATOR . ".INVsamplefile.xml");
+if (!file_exists(APP_SAMPLE_FILE)) {
+  die("Sample file doesn't exist. You must create a sample file named '.INVsamplefile.xml' inside your inventory folder. Give to it the proper write permissions.");
+}		
+
+require dirname(__DIR__) . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "const.inc";
+require dirname(__DIR__) . DIRECTORY_SEPARATOR . "functions" . DIRECTORY_SEPARATOR . "funct.inc";
+
+// ERROR HANDLING AND LOGGING
+
+if (DEBUG) {
+  error_reporting(E_ALL | E_STRICT);  
+  ini_set('display_startup_errors',1);  
+  ini_set('display_errors',1);
+  ini_set('log_errors',1); 
+} else {
+  error_reporting(E_ALL & ~ (E_WARNING | E_NOTICE | E_STRICT | E_DEPRECATED));  
+  ini_set('display_startup_errors',0);  
+  ini_set('display_errors',0);  
+  ini_set('log_errors',1); 
+}

+ 132 - 0
Private/functions/funct.inc

@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Invenktory.
+ *
+ * Invenktory is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Invenktory is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * funct.inc
+ * 
+ * Invenktory function file.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode     
+ */
+
+if (!function_exists("fixMultipleFileUpload")) { 
+/**
+ * Fix multiple file uploaded array ($_FILE)
+ * 
+ * @param array $f the $_FILE array
+ * @return array the array fixed
+ */
+function fixMultipleFileUpload(&$f): array
+{
+    $files = array();
+    $count = count($f['name']);
+    $keys = array_keys($f);
+   
+    for($i=0;$i<$count;$i++)
+    {
+        foreach($keys as $key)
+        {
+            $files[$i][$key] = $f[$key][$i];
+        }
+    }
+    return $files;
+}
+}
+ 
+ 
+if (!function_exists("HTMLencode")) { 
+/**
+ * Encode any HTML of a given string
+ * 
+ * @param string $s the string to encode
+ * @param bool $withBR keep the BR tag, true/false
+ * @return string the string encoded
+ */
+function HTMLencode(?string $s, bool $withBR = false): string 
+{
+  if (!isset($s)) {
+    return PHP_STR;
+  }
+    
+  $s = str_ireplace("&#39;", "'", $s); 
+  $s = str_ireplace("&#34;", "\"", $s);
+  $s = str_ireplace("\\n", "", $s);
+  $s = htmlspecialchars($s, ENT_QUOTES |ENT_IGNORE | ENT_HTML5, "UTF-8");
+    
+  if ($withBR) {
+    $s = str_ireplace(chr(10), PHP_BR, $s);
+  }  
+    
+  return $s;
+} 
+}
+
+if (!function_exists("is_word")) {
+/**
+ * Determine if the given string is a word 
+ * 
+ * @param string $string the string being checked
+ * @return bool true/false if it a word o not    
+ */
+ function is_word(string $string) {
+	 
+   if (($string === ".") || ($string === "..")) {
+	  return false;
+   }	  	 
+	 
+   return preg_match("/^[\w\-\.]+?$/", $string);	 
+ }	 
+
+}
+
+if (!function_exists("left")) { 
+/**
+ * Left cut the given substring for the specified length 
+ * 
+ * @param string $string the string being cut on the left
+ * @param int $length the length of the substring to return
+ * @return string the resulting substring    
+ */
+function left(?string $string, int $length): string 
+{
+  if (!isset($string) || $string === PHP_STR) {
+    return PHP_STR;
+  }
+  return mb_substr($string, 0, $length);
+}
+}
+
+if (!function_exists("right")) {
+/**
+ * Right cut the given string for the specified length 
+ * 
+ * @param string $string the string being cut on the right
+ * @param int $length the length of the substring to return
+ * @return string the resulting substring    
+ */
+function right(?string $string, int $length): string 
+{
+  if (!isset($string) || $string === PHP_STR) {
+    return PHP_STR;
+  }  
+  return mb_substr($string, mb_strlen($string) - $length);
+}
+}
+

+ 1373 - 0
Private/scripts/home.php

@@ -0,0 +1,1373 @@
+<?php
+
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Invenktory.
+ *
+ * Invenktory is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Invenktory is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Invenktory. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * home.php
+ * 
+ * Invenktory home page.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode      
+ */
+ 
+ $cmdHistory = [];
+ $cmd = PHP_STR;
+ $opt = PHP_STR;
+ $param1 = PHP_STR;
+ $param2 = PHP_STR;
+ $param3 = PHP_STR;
+ 
+ $cmdRecallHistory = [];
+  
+ $editBoard = [];
+  
+ $editBoardParams = [];
+  
+ function showHistory() {
+   global $cmdHistory;
+   $i = 1;	 
+   foreach($cmdHistory as $val) {
+	 echo(str_replace("\n", "<br>", $val));
+	 $i++;   
+   }
+ }
+ 
+function updateHistory(&$update, $maxItems) {
+   global $cmdHistory;
+   // Making enough space in $cmdHistory for the update..
+   $shift = (count($cmdHistory) + count($update)) - $maxItems;
+   if ($shift > 0) {
+     $cmdHistory = array_slice($cmdHistory, $shift, $maxItems); 
+   }		  
+   // Adding $cmdHistory update..
+   if (count($update) > $maxItems) {
+      $beginUpd = count($update) - ($maxItems-1);
+   } else {
+	  $beginUpd = 0;
+   }	        
+   $update = array_slice($update, $beginUpd, $maxItems); 
+   foreach($update as $val) {  
+	 $cmdHistory[] = $val;   
+   }
+   // Writing out $cmdHistory on disk..
+   $filepath = dirname(__DIR__) . PHP_SLASH . "logs" . PHP_SLASH . ".INV_history";
+   file_put_contents($filepath, implode('', $cmdHistory));	 
+ }
+ 
+ function loadRecallHistory() { 
+	global $cmdRecallHistory; 
+	$tmpcmdRecallHistory = file(dirname(__DIR__) . PHP_SLASH . "logs" . PHP_SLASH . ".INV_Recallhistory");
+	foreach($tmpcmdRecallHistory as $val) {
+	  $cmdRecallHistory[left($val, strlen($val)-1)]=$val;  	
+    } 
+ }	 
+	  
+ function updateRecallHistory($update, $maxItems) {
+   global $cmdRecallHistory;
+   
+   if (!array_key_exists($update, $cmdRecallHistory)) {
+	 // Making enough space in $cmdHistory for the update..
+	 $shift = (count($cmdRecallHistory) + 1) - $maxItems;
+	 if ($shift > 0) {
+  	   $cmdRecallHistory = array_slice($cmdRecallHistory, $shift, $maxItems); 
+	 }
+	 
+	 $cmdRecallHistory[$update] = $update . "\n";
+   }
+   		     
+   // Writing out $cmdRecallHistory on disk..
+   $filepath = dirname(__DIR__) . PHP_SLASH . "logs" . PHP_SLASH . ".INV_Recallhistory";
+   file_put_contents($filepath, implode('', $cmdRecallHistory));	 
+ }	 
+
+ function updateHistoryWithErr(string $err, bool $withCommand = true) 
+ {
+   global $prompt;
+   global $command;
+   	 
+   $output = [];  
+   if ($withCommand) {
+     $output[] = $prompt . " " . $command . "\n";
+   }
+   $output[] = "$err\n";
+   updateHistory($output, HISTORY_MAX_ITEMS);  	 
+ }	 	 
+ 
+ function myExecCommand() {
+   global $prompt;
+   global $command;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   exec($command, $output);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (right($val,1)!="\n") {
+	   $val = $val . "\n";
+	 }	     
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+ 
+ function myExecCPCommand() {
+   global $prompt;
+   global $command;
+ 
+   $realCommand = str_replace("cp", "cp -Rp", $command);
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   exec($realCommand, $output);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (right($val,1)!="\n") {
+	   $val = $val . "\n";
+	 }	     
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+ 
+ 
+ function myExecCopy() {
+   global $prompt;
+   global $command;
+   global $param1;
+   global $param2;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   copy($param1, $param2);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (right($val,1)!="\n") {
+	   $val = $val . "\n";
+	 }	     
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function myExecCDFolderCommand() {
+   global $prompt;
+   global $command;
+   global $param1;
+   global $curPath;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   //exec($command, $output);
+
+   $newPath = $curPath . PHP_SLASH . $param1;
+   chdir($newPath);
+
+   $curPath = $newPath;
+   $curDir = $param1;
+ 
+   // Creating the Download folder if doesn't exist..
+   $downloadPath = $curPath . PHP_SLASH . ".HCdownloads";
+   if (!file_exists($downloadPath)) {
+	 //copy(APP_INV_PATH . PHP_SLASH . ".HCsampledir", $downloadPath);  
+     $mycmd = "cp -Rp " . APP_INV_PATH . PHP_SLASH . ".HCsampledir" . " " . $downloadPath;
+     $myret = exec($mycmd);
+   }
+ 
+   $prompt = str_replace("$1", $curDir, APP_PROMPT);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (right($val,1)!="\n") {
+	   $val = $val . "\n";
+	 }	     
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+ 
+ function myExecCDBackwCommand() {
+   global $prompt;
+   global $command;
+   global $curPath;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   //exec($command, $output);
+
+   $ipos = strripos($curPath, PHP_SLASH);
+   $newPath = substr($curPath, 0, $ipos);
+   chdir($newPath);
+
+   $curPath = getcwd();
+   $ipos = strripos($curPath, PHP_SLASH);
+   $curDir = substr($curPath, $ipos);
+ 
+   $prompt = str_replace("$1", $curDir, APP_PROMPT);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (right($val,1)!="\n") {
+	   $val = $val . "\n";
+	 }	     
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function myarray_filter_cb($val) {
+   return isset($val);  
+ }
+
+ function myExecLSCommand() {
+   global $prompt;
+   global $command;
+   global $curPath;
+ 
+   $downloadPath = $curPath . PHP_SLASH . ".HCdownloads";
+ 
+   $realCommand = "ls -a";
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   exec($realCommand, $output);
+   
+   // Creating the Download path for the current folder..
+   /*
+   if (!file_exists($downloadPath)) {
+     //copy(APP_INV_PATH . PHP_SLASH . ".HCsampledir", $downloadPath);
+     $mycmd = "cp -Rp " . APP_INV_PATH . PHP_SLASH . ".HCsampledir" . " " . $downloadPath;
+     $myret=exec($mycmd);
+   }
+   
+   // Cleaning the Download folder..
+   if (file_exists($downloadPath)) {
+	   $files1 = scandir($downloadPath);
+	   foreach($files1 as $file) {
+		   if (!is_dir($downloadPath . PHP_SLASH . $file) && $file !== "." && $file !== "..") {
+		     unlink($downloadPath . PHP_SLASH . $file);
+		   }	     
+	   }
+   }*/
+   
+   // Update history..
+   foreach ($output as &$val) {
+	   if ($val === $prompt . " " . $realCommand . "\n") {
+     } else if ($val === "." || $val === "..") {
+       $val = null; 
+     } else {	   
+       if (right($val,1)==="\n") {
+         $val = left($val, strlen($val)-1);
+       }  
+       
+       // Creating the tmp download for the file entry and generating the virtual path..
+       /*
+       $virtualPath = PHP_STR;
+       if (file_exists($downloadPath)) {
+         if (!is_dir($curPath . PHP_SLASH . $val) && filesize($curPath . PHP_SLASH . $val)<=651000) {
+           $fileext = strtolower(pathinfo($val, PATHINFO_EXTENSION));
+           if ($fileext === "php" || $fileext === "inc") {
+             copy($curPath . PHP_SLASH . $val, $downloadPath . PHP_SLASH . $val . ".hcd");  
+             $virtualPath = getVirtualPath($downloadPath . PHP_SLASH . $val . ".hcd");			   	 
+             } else {
+             copy($curPath . PHP_SLASH . $val, $downloadPath . PHP_SLASH . $val);  
+             $virtualPath = getVirtualPath($downloadPath . PHP_SLASH . $val);			   
+           }	 
+         }
+       } else {
+         $virtualPath=PHP_STR;
+       }      
+       if ($virtualPath!==PHP_STR) {
+         $val = "<a href='$virtualPath'>" . $val . "</a>\n";   	     
+       } else {
+         $val = $val . "\n";
+       }
+       */
+       
+       $val = $val . "\n";
+     }      	         
+   }	 
+   
+   $output = array_filter($output, "myarray_filter_cb");
+   
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function myExecHelpCommand() {
+   global $prompt;
+   global $command;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   //exec($command, $output);
+
+   //cd, cd.., cp, help, ls, ls -lsa, mv, pwd
+
+   $output[] = "Copyright 2021, 2024 5 Mode" . "\n";
+   $output[] = "Invenktory is licensed GNUv3" . "\n";
+   $output[] = "" . "\n";
+   $output[] = "Supported commands are:" . "\n";
+   $output[] = "cd" . "\n";
+   $output[] = "cd .." . "\n";
+   $output[] = "cp" . "\n";
+   $output[] = "edit" . " " . "[CTRL]+[X]=Close [CTRL]+[S]=Save" . "\n";
+   $output[] = "help" . "\n";
+   $output[] = "ls" . "\n";
+   $output[] = "mv" . "\n";
+   $output[] = "pwd" . "\n";
+   $output[] = "show" . "\n";
+   $output[] = "\n";
+   $output[] = "Thx for using Invenktory! :)" . "\n";
+   $output[] = "\n";
+   
+   // Update History
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function myExecPWDCommand() {
+   global $prompt;
+   global $command;
+   global $curPath;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   exec($command, $output);
+
+   // Update history..
+   foreach ($output as &$val) {
+	 if (mb_stripos("~".$val,APP_INV_PATH)) {  
+	   $val = str_replace(dirname(APP_INV_PATH), "~ ", $val) . "\n";
+	 }  
+   }	 
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function myExecShowCommand() {
+   global $prompt;
+   global $command;
+   global $param1;
+   global $curPath;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   //exec($command, $output);
+
+   $path = $curPath . DIRECTORY_SEPARATOR . $param1; 
+   $xml = simplexml_load_file($path);
+
+   $output[] = "\n";
+
+   $output[] = "Location: " . $xml->attributes()['location'] . "\n";
+   $output[] = "\n";
+   
+   // Printing out the item descriptions
+   foreach ($xml->children() as $child) {
+     $text = $child->DESCRIPTION;
+     $text = ltrim($text,PHP_SPACE); 
+     $text = rtrim($text,PHP_SPACE); 
+     $text = ltrim($text,"\n");
+     $text = rtrim($text,"\n"); 
+     $output[] = $child->attributes()['type'] . " #" . $child->INDEX . ":\n" . $text . "\n";
+   }
+   
+   $output[] = "\n";
+   
+   // Update History
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function parseCommand() {
+   global $command;
+   global $cmd;
+   global $opt;
+   global $param1;
+   global $param2;
+   global $param3;
+   
+   $str = trim($command);
+   
+   $ipos = stripos($str, PHP_SPACE);
+   if ($ipos > 0) {
+     $cmd = left($str, $ipos);
+     $str = substr($str, $ipos+1);
+   } else {
+	 $cmd = $str;
+	 return;
+   }	     
+   
+   if (left($str, 1) === "-") {
+	 $ipos = stripos($str, PHP_SPACE);
+	 if ($ipos > 0) {
+	   $opt = left($str, $ipos);
+	   $str = substr($str, $ipos+1);
+	 } else {
+	   $opt = $str;
+	   return;
+	 }	     
+   }
+   
+   $ipos = stripos($str, PHP_SPACE);
+   if ($ipos > 0) {
+     $param1 = left($str, $ipos);
+     $str = substr($str, $ipos+1);
+   } else {
+	 $param1 = $str;
+	 return;
+   }	     
+  
+   $ipos = stripos($str, PHP_SPACE);
+   if ($ipos > 0) {
+     $param2 = left($str, $ipos);
+     $str = substr($str, $ipos+1);
+   } else {
+	 $param2 = $str;
+	 return;
+   }
+   
+   $ipos = stripos($str, PHP_SPACE);
+   if ($ipos > 0) {
+     $param3 = left($str, $ipos);
+     $str = substr($str, $ipos+1);
+   } else {
+	 $param3 = $str;
+	 return;
+   }	     
+ 	     
+ }
+ 
+ function cdparamValidation() {
+	global $curPath;
+	global $opt;
+	global $param1;
+    global $param2;
+    global $param3;
+
+    //opt==""
+    if ($opt!=PHP_STR) {
+	  updateHistoryWithErr("invalid options");	
+      return false;
+    }
+    //param1==""
+	if ($param1===PHP_STR) {
+	  updateHistoryWithErr("invalid parameters");	
+      return false;
+    }	    	 
+	//param1!="" and !isword
+	if (($param1!==PHP_STR) && !is_word($param1)) {
+	  updateHistoryWithErr("invalid dir");	
+      return false;
+    }
+    //param2==""
+	if ($param2!==PHP_STR) {
+	  updateHistoryWithErr("invalid parameters");	
+      return false;
+    }	
+    //param3==""
+	if ($param3!=PHP_STR) {
+	  updateHistoryWithErr("invalid parameters");	
+      return false;
+    }	
+	//param1 exist and is_dir
+	$path = $curPath . PHP_SLASH . $param1;
+	if (!file_exists($path) || !is_dir($path)) {
+	  updateHistoryWithErr("dir doesn't exist");	
+	  return false;
+	}  	
+	return true;
+ }	 
+ 
+ function is_subfolderdest(string $path): bool 
+ {
+	global $curPath;
+	
+	$ret=false;
+	
+	if ($path === "../") {
+	  return $ret;	
+	}	
+	
+	if ($path!=PHP_STR) {
+	  $folderName = left($path, strlen($path)-1);
+
+      if (!is_word($folderName)) {
+		return $ret;  
+	  }	  
+
+      if (is_dir($curPath . PHP_SLASH . $folderName) && (right($path,1)==="/")) {
+	    $ret=true;	
+	  }
+    }
+    return $ret;  
+ }
+ 
+ function cpparamValidation() {
+	global $curPath;
+	global $opt;
+	global $param1;
+	global $param2; 
+	global $param3;
+	
+	//ori opt!="" and opt!="-R" and opt!="-Rp"
+  //ori if (($opt!==PHP_STR) && ($opt!=="-R") && ($opt!=="-Rp") && ($opt!=="-p")) {
+  if ($opt!==PHP_STR) {
+	  updateHistoryWithErr("invalid options");	
+    return false;
+  }	
+	//param1!="" and isword  
+	if (($param1===PHP_STR) || !is_word($param1)) {
+	  updateHistoryWithErr("invalid source path");	
+    return false;
+  }
+	//param2!="" and (isword or param2=="../" or is_subfolderdest)
+	if (($param2===PHP_STR) || (!is_word($param2) && ($param2!="../") && !is_subfolderdest($param2))) {
+    updateHistoryWithErr("invalid destination path");
+    return false;
+  }
+  //param3==""
+  if ($param3!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+  //param1 != param2
+  if ($param1 === $param2) {
+    updateHistoryWithErr("source same as destination");
+    return false;	  	
+  }
+	//param1 exist
+	$path = $curPath . PHP_SLASH . $param1;
+	if (!file_exists($path)) {
+	  updateHistoryWithErr("source must exists");	
+	  return false;
+	}  	
+	//isword(param2) && doesn't exist 
+	if (is_word($param2)) {
+	  $path = $curPath . PHP_SLASH . $param2;
+	  if (file_exists($path)) {
+		updateHistoryWithErr("destination already exists");	
+		return false;
+	  }
+	}    	
+  // param2=="../" && is_root 
+  // param2=="../" && dest exists	
+  if ($param2==="../") {
+	  if ($curPath === APP_INV_PATH) {	
+	    updateHistoryWithErr("out of root boundary");
+	    return false;
+	  }  
+	  $path = dirname($curPath) . PHP_SLASH . $param1;
+    if (file_exists($path)) {
+      updateHistoryWithErr("destination already exists");	
+      return false;
+    }	  
+	}	
+	return true;
+ }
+
+ function mvparamValidation() {
+	global $curPath;
+	global $opt;
+	global $param1;
+	global $param2;
+	global $param3; 
+	
+	//opt!=""
+  if ($opt!=PHP_STR)	{
+	  updateHistoryWithErr("invalid options");	
+    return false;
+  }	
+	//param1!="" and isword
+	if (($param1===PHP_STR) || !is_word($param1)) {
+	  updateHistoryWithErr("invalid source path");	
+    return false;
+  }	
+	//param2!="" and (isword or param2=="../" or is_subfolderdest)
+	if (($param2===PHP_STR) || (!is_word($param2) && ($param2!="../") && !is_subfolderdest($param2))) {
+    updateHistoryWithErr("invalid destination path");
+    return false;
+  }
+  //param3!=""
+  if ($param3!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+  //param1 != param2
+  if ($param1 === $param2) {
+    updateHistoryWithErr("source same as destination");
+    return false;	  	
+  }
+	//param1 exist
+	$path = $curPath . PHP_SLASH . $param1;
+	if (!file_exists($path)) {
+	  updateHistoryWithErr("source must exists");	
+	  return false;
+	}  	
+	//isword(param2) && doesn't exist
+	if (is_word($param2)) {
+	  $path = $curPath . PHP_SLASH . $param2;
+	  if (file_exists($path)) {
+  		updateHistoryWithErr("destination already exists");	
+	  	return false;
+    }
+  }  
+  // param2=="../" && is_root 
+  // param2=="../" && dest exists	
+  if ($param2==="../") {
+	  if ($curPath === APP_INV_PATH) {	
+	    updateHistoryWithErr("out of root boundary");
+	    return false;
+	  }  
+	  $path = dirname($curPath) . PHP_SLASH . $param1;
+    if (file_exists($path)) {
+      updateHistoryWithErr("destination already exists");	
+      return false;
+    }	  
+	}	
+	return true;
+ }
+
+
+function myExecEditCommand() {
+   global $prompt;
+   global $command;
+   global $param1;
+   global $curPath;
+ 
+    // Exec command..
+   $output = [];
+   $output[] = $prompt . " " . $command . "\n";   
+   //exec($command, $output);
+
+   $path = $curPath . DIRECTORY_SEPARATOR . $param1; 
+   loadEditBoard($path);
+
+   // Update History
+   updateRecallHistory($command, RECALL_HISTORY_MAX_ITEMS);
+   updateHistory($output, HISTORY_MAX_ITEMS);
+ }
+
+ function loadEditBoard($file) {
+   
+   global $editBoard;
+   
+   $xml = simplexml_load_file($file);
+   
+   $editBoard[] = "\n";
+   $editBoard[] = "<div id='editBoard' style='display:none'>" . "\n";
+
+   $location = $xml->attributes()['location'];
+
+   $editBoard[] = "<label id='labLocation' for='txtLocation'>Location:&nbsp;</label><input id='txtLocation' name='txtLocation' class='standardfield' type='text' autocomplete='off' style='width:200px; height:22px; background-color: black; color:white;' value='" . $location . "'>" . "\n";
+
+   $i=0;
+   foreach ($xml->children() as $child) {
+     
+     $i++;
+     
+     $deviceType = $child->attributes()['type'];
+     $description = ltrim($child->DESCRIPTION, "\n");
+     $index = $child->INDEX;
+     
+     $editBoard[] = "<br>\n";
+     $editBoard[] = "<label id='labDevice" . $i . "'>Device #" . $i . "&nbsp;</label>" . "\n";
+     $editBoard[] = "<label id='labType" . $i . "' for='txtType" . $i . "'>Device type:&nbsp;</label><input id='txtType" . $i . "' name='txtType" . $i . "' class='standardfield' type='text' autocomplete='off' style='width:200px; height:22px; background-color: black; color:white;' value='" . $deviceType . "'>" . "\n";
+     $editBoard[] = "<textarea id='txtDesc" . $i . "' name='txtDesc" . $i . "' class='standardfield' placeholder='description' style='position:relative; top:3px; width: 400px; height:120px; background-color: #EEEEEE; color:black; resize: none;'>";
+     $editBoard[] = $description;
+     $editBoard[] = "</textarea>" . "\n";
+
+   }
+   
+   $i++;
+
+   for ($y=$i;$y<=10;$y++) {
+    
+     $editBoard[] = "<br>\n";
+     $editBoard[] = "<label id='labDevice" . $y . "'>Device #" . $y . "&nbsp;</label>" . "\n";
+     $editBoard[] = "<label id='labType" . $y. "' for='txtType" . $y. "'>Device type:&nbsp;</label><input id='txtType" . $y. "' name='txtType" . $y. "' class='standardfield' type='text' autocomplete='off' placeholder='type' style='width:200px; height:22px; background-color: black; color:white;' value=''>" . "\n";
+     $editBoard[] = "<textarea id='txtDesc" . $y. "' name='txtDesc" . $y. "' class='standardfield' placeholder='description' style='position:relative; top:3px; width: 400px; height:120px; background-color: #EEEEEE; color:black; border:0px; resize: none;'>";
+     $editBoard[] = "</textarea>\n";
+     
+   }
+   
+   $editBoard[] = "<input type='hidden' name='editBoardDest' value='" . $file . "'>\n";
+   $editBoard[] = "<br>\n";
+   $editBoard[] = "</div>\n";		
+
+ }  
+
+ function showEditBoard() {
+   global $editBoard;
+   $i = 1;	 
+   foreach($editBoard as $val) {
+	 //echo(str_replace("\n", "<br>", $val));
+   echo($val);
+	 $i++;   
+   }
+ }
+ 
+ function showparamValidation() {
+	global $curPath;
+	global $opt;
+	global $param1;
+	global $param2; 
+	global $param3;
+	
+	//opt!=""
+  if ($opt!==PHP_STR) {
+	  updateHistoryWithErr("invalid options");	
+    return false;
+  }	
+	//param1!="" and isword  
+	if (($param1===PHP_STR) || !is_word($param1)) {
+	  updateHistoryWithErr("invalid inventory file");	
+    return false;
+  }
+	//param2!="" and (isword or param2=="../" or is_subfolderdest)
+	if ($param2!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+  //param3==""
+  if ($param3!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+	//param1 exist
+	$path = $curPath . PHP_SLASH . $param1;
+	if (!file_exists($path)) {
+	  updateHistoryWithErr("file must exists");	
+	  return false;
+	}  	
+	//param1 is_file
+	if (!is_file($path)) {
+	  updateHistoryWithErr("invalid inventory file");	
+	  return false;
+	}  	
+  //param1 file extension == xml
+  $fileExt = pathinfo($param1, PATHINFO_EXTENSION);
+  if ($fileExt != "xml") {
+	  updateHistoryWithErr("invalid inventory file");	
+	  return false;
+  }    
+   
+	return true;
+ } 
+
+function editparamValidation() {
+	global $curPath;
+	global $opt;
+	global $param1;
+	global $param2; 
+	global $param3;
+	
+	//opt!=""
+  if ($opt!==PHP_STR) {
+	  updateHistoryWithErr("invalid options");	
+    return false;
+  }	
+	//param1!="" and isword  
+	if (($param1===PHP_STR) || !is_word($param1)) {
+	  updateHistoryWithErr("invalid inventory file");	
+    return false;
+  }
+	//param2!="" and (isword or param2=="../" or is_subfolderdest)
+	if ($param2!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+  //param3==""
+  if ($param3!=PHP_STR) {
+    updateHistoryWithErr("invalid parameters");
+    return false;
+  }
+	//param1 exist
+	$path = $curPath . PHP_SLASH . $param1;
+	if (!file_exists($path)) {
+	  updateHistoryWithErr("file must exists");	
+	  return false;
+	}  	
+	//param1 is_file
+	if (!is_file($path)) {
+	  updateHistoryWithErr("invalid inventory file");	
+	  return false;
+	}  	
+  //param1 file extension == xml
+  $fileExt = pathinfo($param1, PATHINFO_EXTENSION);
+  if ($fileExt != "xml") {
+	  updateHistoryWithErr("invalid inventory file");	
+	  return false;
+  }    
+   
+	return true;
+ }
+
+  
+ function upload() {
+
+   global $curPath;
+   global $prompt;
+
+   //if (!empty($_FILES['files'])) {
+   if (!empty($_FILES['files']['tmp_name'][0])) {
+	   
+     // Updating history..
+     $output = [];
+     $output[] = $prompt . " " . "File upload" . "\n";   
+     updateHistory($output, HISTORY_MAX_ITEMS);
+	   	 
+     $uploads = (array)fixMultipleFileUpload($_FILES['files']);
+     
+     //no file uploaded
+     if ($uploads[0]['error'] === PHP_UPLOAD_ERR_NO_FILE) {
+       updateHistoryWithErr("No file uploaded.", false);
+       return;
+     } 
+ 
+     foreach($uploads as &$upload) {
+		
+	   switch ($upload['error']) {
+		 case PHP_UPLOAD_ERR_OK:
+		   break;
+		 case PHP_UPLOAD_ERR_NO_FILE:
+		   updateHistoryWithErr("One or more uploaded files are missing.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_INI_SIZE:
+		   updateHistoryWithErr("File exceeded INI size limit.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_FORM_SIZE:
+		   updateHistoryWithErr("File exceeded form size limit.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_PARTIAL:
+		   updateHistoryWithErr("File only partially uploaded.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_NO_TMP_DIR:
+		   updateHistoryWithErr("TMP dir doesn't exist.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_CANT_WRITE:
+		   updateHistoryWithErr("Failed to write to the disk.", false);
+		   return;
+		 case PHP_UPLOAD_ERR_EXTENSION:
+		   updateHistoryWithErr("A PHP extension stopped the file upload.", false);
+		   return;
+		 default:
+		   updateHistoryWithErr("Unexpected error happened.", false);
+		   return;
+	   }
+		
+	   if (!is_uploaded_file($upload['tmp_name'])) {
+		 updateHistoryWithErr("One or more file have not been uploaded.", false);
+		 return;
+	   }
+		
+	   // name	 
+	   $name = (string)substr((string)filter_var($upload['name']), 0, 255);
+	   if ($name == PHP_STR) {
+         updateHistoryWithErr("Invalid file name: " . $name, false);
+         return;
+       } 
+	   $upload['name'] = $name;
+	   
+	   // fileType
+	   $fileType = substr((string)filter_var($upload['type']), 0, 30);
+	   $upload['type'] = $fileType;	 
+	   
+	   // tmp_name
+	   $tmp_name = substr((string)filter_var($upload['tmp_name']), 0, 300);
+	   if ($tmp_name == PHP_STR || !file_exists($tmp_name)) {
+         updateHistoryWithErr("Invalid file temp path: " . $tmp_name, false);
+         return;
+       } 
+	   $upload['tmp_name'] = $tmp_name;
+	   
+ 	   //size
+ 	   $size = substr((string)filter_var($upload['size'], FILTER_SANITIZE_NUMBER_INT), 0, 12);
+	   if ($size == "") {
+		 updateHistoryWithErr("Invalid file size.", false);
+		 return;
+	   } 
+	   $upload["size"] = $size;
+
+	   $tmpFullPath = $upload["tmp_name"];
+	   
+	   $originalFilename = pathinfo($name, PATHINFO_FILENAME);
+	   $originalFileExt = pathinfo($name, PATHINFO_EXTENSION);
+	   $FileExt = strtolower(pathinfo($name, PATHINFO_EXTENSION));
+	   
+	   if ($originalFileExt!==PHP_STR) {
+	     $destFileName = $originalFilename . "." . $originalFileExt;
+	   } else {
+		 $destFileName = $originalFilename;  
+       }	   
+       $destFullPath = $curPath . PHP_SLASH . $destFileName;
+	   
+	   if (file_exists($destFullPath)) {
+		 updateHistoryWithErr("destination already exists", false);
+		 return;
+	   }	   
+	    
+	   copy($tmpFullPath, $destFullPath);
+
+       // Updating history..
+       $output = [];
+       $output[] = $destFileName . " " . "uploaded" . "\n";   
+       updateHistory($output, HISTORY_MAX_ITEMS);
+  
+	   // Cleaning up..
+	  
+	   // Delete the tmp file..
+	   unlink($tmpFullPath); 
+	    
+	 }	 
+ 
+   }
+ }	  
+  
+ function saveEditBoard() {
+    
+    global $editBoardParams;
+    
+    if (!empty($editBoardParams) && $editBoardParams[0]['location']!=PHP_STR) {
+    
+      $xml = PHP_STR;
+      $xml .= "<?xml version='1.0' encoding='UTF-8'?>";
+      $xml .= "<INVENTORY location='" . HTMLencode($editBoardParams[0]['location']) . "'>";
+      
+      for($i=1;$i<=10;$i++) {
+        if ($editBoardParams[$i]['type']!=PHP_STR) {
+          $xml .= "<ITEM type='" . HTMLencode($editBoardParams[$i]['type']) . "'>";
+          $xml .= "<DESCRIPTION>";
+          $xml .= "<![CDATA[";
+          $xml .= HTMLencode($editBoardParams[$i]['desc']);
+          $xml .= "]]>";
+          $xml .= "</DESCRIPTION>";
+          $xml .= "<INDEX>" . $i . "</INDEX>";
+          $xml .= "</ITEM>";
+        } else {
+          break;
+        }    
+      }  
+      
+      $xml .= "</INVENTORY>";
+      
+      file_put_contents($editBoardParams[0]['file'], $xml);
+    }
+    
+ }
+  
+  
+ $password = filter_input(INPUT_POST, "Password");
+ $command = filter_input(INPUT_POST, "CommandLine");
+ 
+ $pwd = filter_input(INPUT_POST, "pwd"); 
+ $hideSplash = filter_input(INPUT_POST, "hideSplash");
+ $hideHCSplash = filter_input(INPUT_POST, "hideHCSplash");
+
+ //EditBoard
+ if (filter_input(INPUT_POST, "txtLocation")!==PHP_STR) {
+   $editBoardParams[0] = [
+     'file' => filter_input(INPUT_POST, "editBoardDest"),
+     'location' => filter_input(INPUT_POST, "txtLocation")
+     ];
+   for($i=1;$i<=10;$i++) {
+     $editBoardParams[$i] = [ 
+         'type' => filter_input(INPUT_POST, "txtType" . $i),
+         'desc' => filter_input(INPUT_POST, "txtDesc" . $i)
+       ];   
+   }
+ }  
+
+ if ($password !== PHP_STR) {	
+	$hash = hash("sha256", $password . APP_SALT, false);
+
+	if ($hash !== APP_HASH) {
+	  $password=PHP_STR;	
+    }	 
+ } 
+ 
+ $curPath = APP_INV_PATH;
+ if ($pwd!==PHP_STR) {
+   if (left($pwd, strlen(APP_INV_PATH)) === APP_INV_PATH) {
+     $curPath = $pwd;
+     chdir($curPath);	   
+   }	    
+ }	 
+ $ipos = strripos($curPath, PHP_SLASH);
+ $curDir = substr($curPath, $ipos);
+ 
+ $prompt = str_replace("$1", $curDir, APP_PROMPT);
+ 
+ if ($password !== PHP_STR) {
+   
+   loadRecallHistory();
+   $cmdHistory = file(dirname(__DIR__) . PHP_SLASH . "logs" . PHP_SLASH . ".INV_history");
+   
+   parseCommand($command);
+   //echo("cmd=" . $cmd . "<br>");
+   //echo("opt=" . $opt . "<br>");
+   //echo("param1=" . $param1 . "<br>");
+   //echo("param2=" . $param2 . "<br>");
+   
+   upload();
+   saveEditBoard();   
+   
+   if (mb_stripos(CMDLINE_VALIDCMDS, "|" . $command . "|")) {
+     
+     if ($command === "cd ..") {
+	   
+	     $ipos = strripos($curPath, PHP_SLASH);
+	     $nextPath = substr($curPath, 0, $ipos);
+	   
+	     if (strlen(APP_INV_PATH) > strlen($nextPath)) {
+         updateHistoryWithErr("out of root boundary");
+       } else {
+		     myExecCDBackwCommand();
+	     }	
+
+     } else if ($command === "help") {
+   
+       myExecHelpCommand();	 
+ 
+     } else if ($command === "ls") {
+   
+       myExecLSCommand();	 
+ 
+     } else if ($command === "pwd") { 
+   
+       myExecPWDCommand();
+      
+     } else {
+       myExecCommand(); 
+     }
+ 
+   } else if (mb_stripos(CMDLINE_VALIDCMDS, "|" . $cmd . "|")) {
+       
+     if ($cmd === "cd") {
+       if (cdparamValidation()) {
+         myExecCDFolderCommand();
+       }	     
+     } else if ($cmd === "cp") {
+       if (cpparamValidation()) {
+         myExecCPCommand();
+       }	     
+     } else if ($cmd === "mv") {
+       if (mvparamValidation()) {
+         myExecCommand();
+       }	     
+     } else if ($cmd === "show") {
+       if (showparamValidation()) {
+         myExecShowCommand();
+       }	     
+     } else if ($cmd === "edit") {
+       if (editparamValidation()) {
+         myExecEditCommand();
+       }	     
+     } 	   
+  	   
+       
+   } else {
+     
+     // if I'm not saving data..
+     if (empty($editBoardParams) || $editBoardParams[0]['location']===PHP_STR) {
+       if (empty($_FILES['files']['tmp_name'][0])) {  
+         updateHistoryWithErr("invalid command");
+       }
+     }      
+   }
+      
+ } else {
+   
+   $cmdHistory = [];	 
+ 
+ }
+ 
+ ?>
+ 
+
+<!DOCTYPE html>
+<html lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	
+  <meta charset="UTF-8"/>
+  <meta name="style" content="day1"/>
+  
+  <meta name="viewport" content="width=device-width, initial-scale=1"/>
+  
+<!--
+    Copyright 2021, 2024 5 Mode
+
+    This file is part of Invenktory.
+
+    Invenktory is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Invenktory is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Invenktory. If not, see <https://www.gnu.org/licenses/>.
+ -->
+  
+    
+  <title>Invenktory: every device its place..</title>
+	
+  <link rel="shortcut icon" href="./res/favicon66.ico?v=<?php echo(time()); ?>" />
+    
+  <meta name="description" content="Welcome to <?php echo(APP_NAME); ?>"/>
+  <meta name="author" content="5 Mode"/> 
+  <meta name="robots" content="noindex"/>
+  
+  <script src="./js/jquery-3.1.0.min.js" type="text/javascript"></script>
+  <script src="./js/common.js" type="text/javascript"></script>
+  <script src="./js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="./js/sha.js" type="text/javascript"></script>
+  
+  <script src="./js/home.js" type="text/javascript" defer></script>
+  
+  <link href="./css/bootstrap.min.css" type="text/css" rel="stylesheet">
+  <link href="./css/style.css?v=<?php echo(time()); ?>" type="text/css" rel="stylesheet">
+     
+  <script>
+	
+	 $(document).ready(function() {
+	  
+		 $(document).on("keydown",function(e){
+		   key = e.which;
+		   if (key===88 && e.ctrlKey && ($("#editBoard").css("display")!="none")) {
+			   // Closing..
+         e.preventDefault();
+         $("#editBoard").hide();
+         $("#CommandL").show()
+         document.getElementById("CommandLine").focus();
+       } else if (key===83 && e.ctrlKey && ($("#editBoard").css("display")!="none")) {
+         // Saving data
+         if ($("#txtLocation").val()==="") {
+           $("#txtLocation").addClass("editemptyfield");
+           document.getElementById("txtLocation").focus();
+           return;
+         }  
+         if ($("#txtType1").val()==="") {
+           $("#txtType1").addClass("editemptyfield");
+           document.getElementById("txtType1").focus();
+           return;
+         }  
+         if ($("#txtDesc1").val()==="") {
+           $("#txtDesc1").addClass("editemptyfield");
+           document.getElementById("txtDesc1").focus();
+           return;
+         }  
+         // 1 2 3 4 5 6 7 8 9 10
+         for(i=2;i<=10;i++) {
+           y=i-1;
+           if ($("#txtType"+y).val()==="") { 
+             if ($("#txtType"+i).val()!="") {
+               $("#txtType"+y).addClass("editemptyfield");
+               document.getElementById("txtType"+y).focus();
+               return;
+             }
+           }   
+           if ($("#txtDesc"+y).val()==="") { 
+             if ($("#txtDesc"+i).val()!="") {
+               $("#txtDesc"+y).addClass("editemptyfield");
+               document.getElementById("txtDesc"+y).focus();
+               return;
+             }
+           }   
+         }  
+         e.preventDefault();
+         frmHC.submit();
+		   } else { 
+         $("#Salt").val(key);
+		   }
+		 });
+
+		 $("#CommandLine").on("keydown",function(e){
+		   key = e.which;
+		   //alert(key);
+		   if (key===13) {
+			 e.preventDefault();
+			 frmHC.submit();
+		   } else { 
+			 //e.preventDefault();
+		   }
+		 });
+
+   });
+		  
+   window.addEventListener("load", function() {		 
+		 <?php if($password===PHP_STR):?>
+		    $("#Password").addClass("emptyfield");
+		 <?php endif; ?>
+     maxY = document.getElementById("Console").scrollHeight;
+     //alert(maxY);
+     if (document.getElementById("editBoard")) {
+		   document.getElementById("txtDesc1").focus();
+     } else {
+       //maxY = document.getElementById("Consolep").scrollHeight;
+       document.getElementById("CommandLine").focus();
+     }    
+     //document.getElementById("Console").scrollTop=maxY;
+	 }, true);
+
+  function startApp() {
+	  $("#HCsplash").hide();
+	  $("#frmHC").show();
+    <?php if (!empty($editBoard)): ?>
+    $("#editBoard").show();
+    $("#CommandL").hide();
+    <?php endif; ?>
+    if (document.getElementById("editBoard")) {
+		   document.getElementById("txtDesc1").focus();
+    }
+	}			
+  <?php if($hideHCSplash!=="1"): ?>
+	window.addEventListener("load", function() {
+	
+	  $("#HCsplash").show();	  
+	  setTimeout("startApp()", 5000);
+	  
+	}, true);
+	<?php else: ?>
+  window.addEventListener("load", function() {
+		  
+	  startApp();
+	  
+	});	
+  <?php endif; ?>
+
+  </script>    
+    
+</head>
+<body>
+
+<div id="HCsplash" style="padding-top: 200px; text-align:center;" style="display:none;">
+   <img src="res/INVsplash.gif" style="width:310px;">
+</div>
+
+<form id="frmHC" method="POST" action="/" target="_self" enctype="multipart/form-data" style="display:<?php echo(($hideHCSplash==="1"?"inline":"none"));?>;">
+
+<div class="header">
+   <a href="http://invenktory.com" target="_blank" style="color:white; text-decoration: none;"><img src="res/INVlogo.png" style="width:48px;">&nbsp;Invenktory</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/par7133/Invenktory" style="color:#ffffff"><span style="color:#119fe2">on</span> github</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="mailto:info@invenktory.com" style="color:#ffffff"><span style="color:#119fe2">for</span> feedback</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="tel:+39-331-4029415" style="font-size:13px;background-color:#15c60b;border:2px solid #15c60b;color:white;height:27px;text-decoration:none;">&nbsp;&nbsp;get support&nbsp;&nbsp;</a>
+</div>
+	
+<div style="clear:both; float:left; padding:8px; width:15%; height:100%; text-align:center;">
+	<div style="padding-left:12px;text-align: left;">
+	  <!--&nbsp;Upload-->
+	  &nbsp;<a href="#" id="upload" style="<?php echo(($password===PHP_STR?'text-decoration:none;color:gray;':'color:#ffffff;')); ?>" onclick="<?php echo(($password!==PHP_STR?'upload()':'')); ?>">Upload</a>
+	  <input id="files" name="files[]" type="file" accept=".xml" style="visibility: hidden;">
+	</div>
+    <br><br>
+    <img src="res/INVgenius.png" alt="HC Genius" title="HC Genius" style="position:relative; left:+6px; width:90%; border: 1px dashed #EEEEEE;">
+    &nbsp;<br><br><br>
+    &nbsp;<input type="text" id="Password" name="Password" placeholder="password" style="font-size:10px; background:#393939; color:#ffffff; width: 90%; border-radius:3px;" value="<?php echo($password);?>" autocomplete="off"><br>
+    &nbsp;<input type="text" id="Salt" placeholder="salt" style="position:relative; top:+5px; font-size:10px; background:#393939; color:#ffffff; width: 90%; border-radius:3px;" autocomplete="off"><br>
+    &nbsp;<a href="#" onclick="showEncodedPassword();" style="position:relative; left:-2px; top:+5px; color:#ffffff; font-size:12px;">Hash Me!</a>     
+</div>
+
+<div style="float:left; width:85%;height:100%; padding:8px; border-left: 1px solid #2c2f34;">
+	
+	<?php if (APP_SPLASH): ?>
+	<?php if ($hideSplash !== PHP_STR): ?>
+	<div id="splash" style="border-radius:20px; position:relative; left:+3px; width:98%; background-color: #33aced; padding: 20px; margin-bottom:8px;">	
+	
+	   <button type="button" class="close" aria-label="Close" onclick="closeSplash();" style="position:relative; left:-10px;">
+          <span aria-hidden="true">&times;</span>
+       </button>
+	
+	   Hello and welcome to Invenktory!<br><br>
+	   
+	   Invenktory is a light and simple software on premise to track your devices.<br><br>
+	   
+	   Invenktory is released under GPLv3 license, it is supplied AS-IS and we do not take any responsibility for its misusage.<br><br>
+	   
+	   First step, use the left side panel password and salt fields to create the hash to insert in the config file. Remember to manually set there also the salt value.<br><br>
+	   
+	   As you are going to run Invenktory in the PHP process context, using a limited web server or phpfpm user, you must follow some simple directives for an optimal first setup:<br>
+	   <ol>
+	   <li>Check the permissions of your "Inventory" folder in your web app private path; and set its path in the config file.</li>
+	   <li>In the Inventory path create a ".INVsampledir" folder and give to this folder the write permission. This folder will be the sample folder to copy from new folders inside the inventory path.</li>
+	   <li>Likewise, in the Inventory path must exist ".INVsamplefile.xml" and give to this file the write permission. This file will be the sample file to copy from new inventory files.</li>
+	   <li>Configure the max devices per xml file as required (default: 10).</li>	      
+     <li>Configure the max history items and max recall history items as required (default: 50).</li>	      
+	   </ol>
+	   
+	   <br>	
+	   
+	   Invenktory understands a limited set of commands with a far limited set of parameters:<br>
+	   cd, cd.., cp, edit, help, ls, mv, pwd, show<br><br>	   
+	   
+     In edit mode press [CTRL]+[X] to exit or [CTRL]+[S] to save.<br><br> 
+     
+	   Hope you can enjoy it and let us know about any feedback: <a href="mailto:info@invenktory.com" style="color:#e6d236;">info@invenktory.com</a>
+	   
+	</div>	
+	<?php endif; ?>
+	<?php endif; ?>
+	
+	&nbsp;Console<br>
+	<div id="Console" style="height:493px; overflow-y:auto; margin-top:10px;">
+  <!--<div id="Console" style="height:493px; margin-top:10px;">-->
+	<pre id="Consolep" style="margin-left:5px;padding-left:0px;border:0px;background-color: #000000; color: #ffffff;">
+<?php showHistory($cmdHistory); ?>
+<?php showEditBoard(); ?>
+<div id="CommandL" style="position:relative;top:3px;"><label id="Prompt" for="CommandLine"><?php echo($prompt); ?></label>&nbsp;<input id="CommandLine" name="CommandLine" list="CommandList" type="text" autocomplete="off" style="width:80%; height:22px; background-color: black; color:white; border:0px; border-bottom: 1px dashed #EEEEEE;"></div>	
+	</pre>	
+	</div>
+	
+	<datalist id="CommandList">
+	<?php foreach($cmdRecallHistory as &$val): ?>
+	<?php $val = left($val, strlen($val)-1); ?>
+	<?php echo("<option value='$val'>\n"); ?>
+	<?php endforeach; ?>	
+	</datalist>	
+	
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+</div>
+
+<div class="footer">
+<div id="footerCont">&nbsp;</div>
+<div id="footer"><span style="background:#FFFFFF;opacity:1.0;margin-right:10px;">&nbsp;&nbsp;A <a href="http://5mode.com">5 Mode</a> project and <a href="http://wysiwyg.systems">WYSIWYG</a> system. Some rights reserved.</span></div>	
+</div>
+
+<input type="hidden" name="pwd" value="<?php echo($curPath); ?>" style="color:black">
+<input type="hidden" name="hideSplash" value="<?php echo($hideSplash); ?>">
+<input type="hidden" name="hideHCSplash" value="1">
+
+</form>
+
+</body>	 
+</html>	 

+ 65 - 0
Public/index.php

@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * Copyright (c) 2016, 2024, the Open Gallery's contributors
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither Open Gallery nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * index.php
+ * 
+ * The index file.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2016, 2024, the Open Gallery's contributors     
+ * @license https://opensource.org/licenses/BSD-3-Clause 
+ */
+
+require "../Private/core/init.inc";
+
+
+// FUNCTION AND VARIABLE DECLARATIONS
+
+$scriptPath = APP_SCRIPT_PATH;
+
+// PARAMETERS VALIDATION
+
+$url = strtolower(rtrim(substr(filter_input(INPUT_GET, "url", FILTER_SANITIZE_STRING), 0, 300), "/"));
+
+switch ($url) {
+  case "":
+  case "home":
+    define("SCRIPT_NAME", "home");
+    define("SCRIPT_FILENAME", "home.php");   
+    break;   
+  default:
+    $scriptPath = APP_ERROR_PATH;
+    define("SCRIPT_NAME", "err-404");
+    define("SCRIPT_FILENAME", "err-404.php");  
+}
+
+if (SCRIPT_NAME==="err-404") {
+  header("HTTP/1.1 404 Not Found");
+}  
+
+require $scriptPath . "/" . SCRIPT_FILENAME;

+ 587 - 0
Public/static/css/bootstrap-theme.css

@@ -0,0 +1,587 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-default.disabled,
+.btn-primary.disabled,
+.btn-success.disabled,
+.btn-info.disabled,
+.btn-warning.disabled,
+.btn-danger.disabled,
+.btn-default[disabled],
+.btn-primary[disabled],
+.btn-success[disabled],
+.btn-info[disabled],
+.btn-warning[disabled],
+.btn-danger[disabled],
+fieldset[disabled] .btn-default,
+fieldset[disabled] .btn-primary,
+fieldset[disabled] .btn-success,
+fieldset[disabled] .btn-info,
+fieldset[disabled] .btn-warning,
+fieldset[disabled] .btn-danger {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn-default .badge,
+.btn-primary .badge,
+.btn-success .badge,
+.btn-info .badge,
+.btn-warning .badge,
+.btn-danger .badge {
+  text-shadow: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #e0e0e0;
+  background-image: none;
+}
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #245580;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #265a88;
+  background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #265a88;
+  border-color: #245580;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #265a88;
+  background-image: none;
+}
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #419641;
+  background-image: none;
+}
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #2aabd2;
+  background-image: none;
+}
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #eb9316;
+  background-image: none;
+}
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #c12e2a;
+  background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #2e6da4;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image:      -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
+  background-image:         linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image:      -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image:      -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
+  background-image:         linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+@media (max-width: 767px) {
+  .navbar .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+    background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+    background-repeat: repeat-x;
+  }
+}
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+}
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+}
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+}
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+}
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #286090 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #286090;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+}
+.list-group-item.active .badge,
+.list-group-item.active:hover .badge,
+.list-group-item.active:focus .badge {
+  text-shadow: none;
+}
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
Public/static/css/bootstrap-theme.css.map


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 4 - 0
Public/static/css/bootstrap-theme.min.css


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
Public/static/css/bootstrap-theme.min.css.map


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
Public/static/css/bootstrap.css.map


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 4 - 0
Public/static/css/bootstrap.min.css


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
Public/static/css/bootstrap.min.css.map


+ 84 - 0
Public/static/css/style.css

@@ -0,0 +1,84 @@
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Http Console.
+ *
+ * Http Console is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Http Console is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * style.css
+ * 
+ * CSS file.
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, 5 Mode     
+ */
+
+html {
+  height: 100%;
+}
+body {
+  margin: 0px; 
+  padding: 0px;
+  height:100%; 
+  font-family: helvetica neue,helvetica,arial,sans-serif;
+  background-color: #000000;
+  color: #FFFFFF;
+}
+.standardfield{
+  border: 0px;
+  border-bottom: 1px dashed #EEEEEE;
+}
+.emptyfield{
+  border: 1px solid red;
+}
+.editemptyfield{
+  border-bottom: 3px dashed red;
+}
+#footerCont {
+  position: fixed; 
+  top: 2000px; 
+  left:-10px;
+  width: 102%; 
+  border: 1px solid #C2DBF2; 
+  padding: 7px; 
+  background: #ffedf0; 
+  opacity: 0.0;
+  color:white; 
+  font-family: Sans;
+  font-size: 12px; 
+  text-align: center; 
+  z-index: 99990;
+}
+#footer {
+  position: fixed;
+  float: right;
+  top: 2000px; 
+  left:-10px;
+  width: 100%; 
+  border: 0px solid #C2DBF2; 
+  padding: 7px; 
+  opacity: 1.0;
+  color:black; 
+  font-family: Sans;
+  font-size: 12px; 
+  font-weight: 400;
+  text-align: right; 
+  z-index: 99991;
+}
+.header {
+  height: 65px;
+  vertical-align: middle;
+  border-bottom: 1px solid #2c2f34;
+  padding: 8px;
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 5 - 0
Public/static/js/bootstrap.min.js


+ 38 - 0
Public/static/js/common.js

@@ -0,0 +1,38 @@
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Http Console.
+ *
+ * Http Console is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Http Console is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * commons.js
+ * 
+ * Common constants and functions
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, the Open Gallery's contributors     
+ */
+
+
+/**
+ * Encrypt the given string
+ * 
+ * @param {string} string - The string to encrypt
+ * @returns {string} the encrypted string
+ */
+function encryptSha2(string) {
+  var jsSHAo = new jsSHA("SHA-256", "TEXT", 1);
+  jsSHAo.update(string);
+  return jsSHAo.getHash("HEX");
+}

+ 100 - 0
Public/static/js/home.js

@@ -0,0 +1,100 @@
+/**
+ * Copyright 2021, 2024 5 Mode
+ *
+ * This file is part of Http Console.
+ *
+ * Http Console is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Http Console is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.  
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Http Console. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * home.js
+ * 
+ * JS file for Home page
+ *
+ * @author Daniele Bonini <my25mb@aol.com>
+ * @copyrights (c) 2021, 2024, the Open Gallery's contributors     
+ */
+
+function closeSplash() {
+  $("#hideSplash").val("1");
+  $("#splash").hide();	
+}
+
+/**
+ * Encrypt the given string
+ * 
+ * @param {string} string - The string to encrypt
+ * @returns {string} the encrypted string
+ */
+function encryptSha2(string) {
+  var jsSHAo = new jsSHA("SHA-256", "TEXT", 1);
+  jsSHAo.update(string);
+  return jsSHAo.getHash("HEX");
+}
+
+function setFooterPos() {
+  if (document.getElementById("footerCont")) {
+	if ($("#Password").val() === "") {  
+      tollerance = 48;
+    } else {
+	  tollerance = 15;
+	}  	  
+    $("#footerCont").css("top", parseInt( window.innerHeight - $("#footerCont").height() - tollerance ) + "px");
+    $("#footer").css("top", parseInt( window.innerHeight - $("#footer").height() - tollerance ) + "px");
+  }
+}
+
+function showEncodedPassword() {
+   if ($("#Password").val() === "") {
+	 $("#Password").addClass("emptyfield");
+	 return;  
+   }
+   if ($("#Salt").val() === "") {
+	 $("#Salt").addClass("emptyfield");
+	 return;  
+   }	   	
+   passw = encryptSha2( $("#Password").val() + $("#Salt").val());
+   msg = "Please set your hash in the config file with this value:";
+   alert(msg + "\n\n" + passw);	
+}
+
+function upload() {
+  $("input#files").click();
+} 
+
+$("input#files").on("change", function(e) {
+  frmHC.submit();
+});
+
+$("#Password").on("keydown", function(e){
+	$("#Password").removeClass("emptyfield");
+});	
+
+$("#Salt").on("keydown", function(e){
+	$("#Salt").removeClass("emptyfield");
+});	
+
+window.addEventListener("load", function() {
+    
+  setTimeout("setFooterPos()", 3000);
+
+  //document.getElementById("CommandLine").focus();  
+  
+}, true);
+
+window.addEventListener("resize", function() {
+
+  setTimeout("setFooterPos()", 3000);
+
+}, true);
+
+

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 0
Public/static/js/jquery-3.1.0.min.js


+ 45 - 0
Public/static/js/sha.js

@@ -0,0 +1,45 @@
+/*
+ A JavaScript implementation of the SHA family of hashes, as
+ defined in FIPS PUB 180-4 and FIPS PUB 202, as well as the corresponding
+ HMAC implementation as defined in FIPS PUB 198a
+
+ Copyright Brian Turek 2008-2016
+ Distributed under the BSD License
+ See http://caligatio.github.com/jsSHA/ for more information
+
+ Several functions taken from Paul Johnston
+*/
+'use strict';(function(Y){function C(b,a,c){var g=0,d=[],n=0,h,l,e,f,m,q,u,r,I=!1,v=[],w=[],t,y=!1,A=!1,x=-1;c=c||{};h=c.encoding||"UTF8";t=c.numRounds||1;if(t!==parseInt(t,10)||1>t)throw Error("numRounds must a integer >= 1");if("SHA-1"===b)m=512,q=K,u=Z,f=160,r=function(a){return a.slice()};else if(0===b.lastIndexOf("SHA-",0))if(q=function(a,c){return L(a,c,b)},u=function(a,c,g,d){var k,f;if("SHA-224"===b||"SHA-256"===b)k=(c+65>>>9<<4)+15,f=16;else if("SHA-384"===b||"SHA-512"===b)k=(c+129>>>10<<
+5)+31,f=32;else throw Error("Unexpected error in SHA-2 implementation");for(;a.length<=k;)a.push(0);a[c>>>5]|=128<<24-c%32;c=c+g;a[k]=c&4294967295;a[k-1]=c/4294967296|0;g=a.length;for(c=0;c<g;c+=f)d=L(a.slice(c,c+f),d,b);if("SHA-224"===b)a=[d[0],d[1],d[2],d[3],d[4],d[5],d[6]];else if("SHA-256"===b)a=d;else if("SHA-384"===b)a=[d[0].a,d[0].b,d[1].a,d[1].b,d[2].a,d[2].b,d[3].a,d[3].b,d[4].a,d[4].b,d[5].a,d[5].b];else if("SHA-512"===b)a=[d[0].a,d[0].b,d[1].a,d[1].b,d[2].a,d[2].b,d[3].a,d[3].b,d[4].a,
+d[4].b,d[5].a,d[5].b,d[6].a,d[6].b,d[7].a,d[7].b];else throw Error("Unexpected error in SHA-2 implementation");return a},r=function(a){return a.slice()},"SHA-224"===b)m=512,f=224;else if("SHA-256"===b)m=512,f=256;else if("SHA-384"===b)m=1024,f=384;else if("SHA-512"===b)m=1024,f=512;else throw Error("Chosen SHA variant is not supported");else if(0===b.lastIndexOf("SHA3-",0)||0===b.lastIndexOf("SHAKE",0)){var F=6;q=D;r=function(a){var b=[],d;for(d=0;5>d;d+=1)b[d]=a[d].slice();return b};x=1;if("SHA3-224"===
+b)m=1152,f=224;else if("SHA3-256"===b)m=1088,f=256;else if("SHA3-384"===b)m=832,f=384;else if("SHA3-512"===b)m=576,f=512;else if("SHAKE128"===b)m=1344,f=-1,F=31,A=!0;else if("SHAKE256"===b)m=1088,f=-1,F=31,A=!0;else throw Error("Chosen SHA variant is not supported");u=function(a,b,d,c,g){d=m;var k=F,f,h=[],n=d>>>5,l=0,e=b>>>5;for(f=0;f<e&&b>=d;f+=n)c=D(a.slice(f,f+n),c),b-=d;a=a.slice(f);for(b%=d;a.length<n;)a.push(0);f=b>>>3;a[f>>2]^=k<<f%4*8;a[n-1]^=2147483648;for(c=D(a,c);32*h.length<g;){a=c[l%
+5][l/5|0];h.push(a.b);if(32*h.length>=g)break;h.push(a.a);l+=1;0===64*l%d&&D(null,c)}return h}}else throw Error("Chosen SHA variant is not supported");e=M(a,h,x);l=B(b);this.setHMACKey=function(a,d,c){var k;if(!0===I)throw Error("HMAC key already set");if(!0===y)throw Error("Cannot set HMAC key after calling update");if(!0===A)throw Error("SHAKE is not supported for HMAC");h=(c||{}).encoding||"UTF8";d=M(d,h,x)(a);a=d.binLen;d=d.value;k=m>>>3;c=k/4-1;if(k<a/8){for(d=u(d,a,0,B(b),f);d.length<=c;)d.push(0);
+d[c]&=4294967040}else if(k>a/8){for(;d.length<=c;)d.push(0);d[c]&=4294967040}for(a=0;a<=c;a+=1)v[a]=d[a]^909522486,w[a]=d[a]^1549556828;l=q(v,l);g=m;I=!0};this.update=function(a){var b,c,k,f=0,h=m>>>5;b=e(a,d,n);a=b.binLen;c=b.value;b=a>>>5;for(k=0;k<b;k+=h)f+m<=a&&(l=q(c.slice(k,k+h),l),f+=m);g+=f;d=c.slice(f>>>5);n=a%m;y=!0};this.getHash=function(a,c){var k,h,e,m;if(!0===I)throw Error("Cannot call getHash after setting HMAC key");e=N(c);if(!0===A){if(-1===e.shakeLen)throw Error("shakeLen must be specified in options");
+f=e.shakeLen}switch(a){case "HEX":k=function(a){return O(a,f,x,e)};break;case "B64":k=function(a){return P(a,f,x,e)};break;case "BYTES":k=function(a){return Q(a,f,x)};break;case "ARRAYBUFFER":try{h=new ArrayBuffer(0)}catch(p){throw Error("ARRAYBUFFER not supported by this environment");}k=function(a){return R(a,f,x)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");}m=u(d.slice(),n,g,r(l),f);for(h=1;h<t;h+=1)!0===A&&0!==f%32&&(m[m.length-1]&=16777215>>>24-f%32),m=u(m,f,
+0,B(b),f);return k(m)};this.getHMAC=function(a,c){var k,h,e,p;if(!1===I)throw Error("Cannot call getHMAC without first setting HMAC key");e=N(c);switch(a){case "HEX":k=function(a){return O(a,f,x,e)};break;case "B64":k=function(a){return P(a,f,x,e)};break;case "BYTES":k=function(a){return Q(a,f,x)};break;case "ARRAYBUFFER":try{k=new ArrayBuffer(0)}catch(v){throw Error("ARRAYBUFFER not supported by this environment");}k=function(a){return R(a,f,x)};break;default:throw Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER");
+}h=u(d.slice(),n,g,r(l),f);p=q(w,B(b));p=u(h,f,m,p,f);return k(p)}}function c(b,a){this.a=b;this.b=a}function O(b,a,c,g){var d="";a/=8;var n,h,e;e=-1===c?3:0;for(n=0;n<a;n+=1)h=b[n>>>2]>>>8*(e+n%4*c),d+="0123456789abcdef".charAt(h>>>4&15)+"0123456789abcdef".charAt(h&15);return g.outputUpper?d.toUpperCase():d}function P(b,a,c,g){var d="",n=a/8,h,e,p,f;f=-1===c?3:0;for(h=0;h<n;h+=3)for(e=h+1<n?b[h+1>>>2]:0,p=h+2<n?b[h+2>>>2]:0,p=(b[h>>>2]>>>8*(f+h%4*c)&255)<<16|(e>>>8*(f+(h+1)%4*c)&255)<<8|p>>>8*(f+
+(h+2)%4*c)&255,e=0;4>e;e+=1)8*h+6*e<=a?d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(p>>>6*(3-e)&63):d+=g.b64Pad;return d}function Q(b,a,c){var g="";a/=8;var d,e,h;h=-1===c?3:0;for(d=0;d<a;d+=1)e=b[d>>>2]>>>8*(h+d%4*c)&255,g+=String.fromCharCode(e);return g}function R(b,a,c){a/=8;var g,d=new ArrayBuffer(a),e;e=-1===c?3:0;for(g=0;g<a;g+=1)d[g]=b[g>>>2]>>>8*(e+g%4*c)&255;return d}function N(b){var a={outputUpper:!1,b64Pad:"=",shakeLen:-1};b=b||{};a.outputUpper=b.outputUpper||
+!1;!0===b.hasOwnProperty("b64Pad")&&(a.b64Pad=b.b64Pad);if(!0===b.hasOwnProperty("shakeLen")){if(0!==b.shakeLen%8)throw Error("shakeLen must be a multiple of 8");a.shakeLen=b.shakeLen}if("boolean"!==typeof a.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!==typeof a.b64Pad)throw Error("Invalid b64Pad formatting option");return a}function M(b,a,c){switch(a){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");
+}switch(b){case "HEX":b=function(a,b,e){var h=a.length,l,p,f,m,q,u;if(0!==h%2)throw Error("String of HEX type must be in byte increments");b=b||[0];e=e||0;q=e>>>3;u=-1===c?3:0;for(l=0;l<h;l+=2){p=parseInt(a.substr(l,2),16);if(isNaN(p))throw Error("String of HEX type contains invalid characters");m=(l>>>1)+q;for(f=m>>>2;b.length<=f;)b.push(0);b[f]|=p<<8*(u+m%4*c)}return{value:b,binLen:4*h+e}};break;case "TEXT":b=function(b,d,e){var h,l,p=0,f,m,q,u,r,t;d=d||[0];e=e||0;q=e>>>3;if("UTF8"===a)for(t=-1===
+c?3:0,f=0;f<b.length;f+=1)for(h=b.charCodeAt(f),l=[],128>h?l.push(h):2048>h?(l.push(192|h>>>6),l.push(128|h&63)):55296>h||57344<=h?l.push(224|h>>>12,128|h>>>6&63,128|h&63):(f+=1,h=65536+((h&1023)<<10|b.charCodeAt(f)&1023),l.push(240|h>>>18,128|h>>>12&63,128|h>>>6&63,128|h&63)),m=0;m<l.length;m+=1){r=p+q;for(u=r>>>2;d.length<=u;)d.push(0);d[u]|=l[m]<<8*(t+r%4*c);p+=1}else if("UTF16BE"===a||"UTF16LE"===a)for(t=-1===c?2:0,f=0;f<b.length;f+=1){h=b.charCodeAt(f);"UTF16LE"===a&&(m=h&255,h=m<<8|h>>>8);r=
+p+q;for(u=r>>>2;d.length<=u;)d.push(0);d[u]|=h<<8*(t+r%4*c);p+=2}return{value:d,binLen:8*p+e}};break;case "B64":b=function(a,b,e){var h=0,l,p,f,m,q,u,r,t;if(-1===a.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");p=a.indexOf("=");a=a.replace(/\=/g,"");if(-1!==p&&p<a.length)throw Error("Invalid '=' found in base-64 string");b=b||[0];e=e||0;u=e>>>3;t=-1===c?3:0;for(p=0;p<a.length;p+=4){q=a.substr(p,4);for(f=m=0;f<q.length;f+=1)l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(q[f]),
+m|=l<<18-6*f;for(f=0;f<q.length-1;f+=1){r=h+u;for(l=r>>>2;b.length<=l;)b.push(0);b[l]|=(m>>>16-8*f&255)<<8*(t+r%4*c);h+=1}}return{value:b,binLen:8*h+e}};break;case "BYTES":b=function(a,b,e){var h,l,p,f,m,q;b=b||[0];e=e||0;p=e>>>3;q=-1===c?3:0;for(l=0;l<a.length;l+=1)h=a.charCodeAt(l),m=l+p,f=m>>>2,b.length<=f&&b.push(0),b[f]|=h<<8*(q+m%4*c);return{value:b,binLen:8*a.length+e}};break;case "ARRAYBUFFER":try{b=new ArrayBuffer(0)}catch(g){throw Error("ARRAYBUFFER not supported by this environment");}b=
+function(a,b,e){var h,l,p,f,m;b=b||[0];e=e||0;l=e>>>3;m=-1===c?3:0;for(h=0;h<a.byteLength;h+=1)f=h+l,p=f>>>2,b.length<=p&&b.push(0),b[p]|=a[h]<<8*(m+f%4*c);return{value:b,binLen:8*a.byteLength+e}};break;default:throw Error("format must be HEX, TEXT, B64, BYTES, or ARRAYBUFFER");}return b}function y(b,a){return b<<a|b>>>32-a}function S(b,a){return 32<a?(a-=32,new c(b.b<<a|b.a>>>32-a,b.a<<a|b.b>>>32-a)):0!==a?new c(b.a<<a|b.b>>>32-a,b.b<<a|b.a>>>32-a):b}function w(b,a){return b>>>a|b<<32-a}function t(b,
+a){var k=null,k=new c(b.a,b.b);return k=32>=a?new c(k.a>>>a|k.b<<32-a&4294967295,k.b>>>a|k.a<<32-a&4294967295):new c(k.b>>>a-32|k.a<<64-a&4294967295,k.a>>>a-32|k.b<<64-a&4294967295)}function T(b,a){var k=null;return k=32>=a?new c(b.a>>>a,b.b>>>a|b.a<<32-a&4294967295):new c(0,b.a>>>a-32)}function aa(b,a,c){return b&a^~b&c}function ba(b,a,k){return new c(b.a&a.a^~b.a&k.a,b.b&a.b^~b.b&k.b)}function U(b,a,c){return b&a^b&c^a&c}function ca(b,a,k){return new c(b.a&a.a^b.a&k.a^a.a&k.a,b.b&a.b^b.b&k.b^a.b&
+k.b)}function da(b){return w(b,2)^w(b,13)^w(b,22)}function ea(b){var a=t(b,28),k=t(b,34);b=t(b,39);return new c(a.a^k.a^b.a,a.b^k.b^b.b)}function fa(b){return w(b,6)^w(b,11)^w(b,25)}function ga(b){var a=t(b,14),k=t(b,18);b=t(b,41);return new c(a.a^k.a^b.a,a.b^k.b^b.b)}function ha(b){return w(b,7)^w(b,18)^b>>>3}function ia(b){var a=t(b,1),k=t(b,8);b=T(b,7);return new c(a.a^k.a^b.a,a.b^k.b^b.b)}function ja(b){return w(b,17)^w(b,19)^b>>>10}function ka(b){var a=t(b,19),k=t(b,61);b=T(b,6);return new c(a.a^
+k.a^b.a,a.b^k.b^b.b)}function G(b,a){var c=(b&65535)+(a&65535);return((b>>>16)+(a>>>16)+(c>>>16)&65535)<<16|c&65535}function la(b,a,c,g){var d=(b&65535)+(a&65535)+(c&65535)+(g&65535);return((b>>>16)+(a>>>16)+(c>>>16)+(g>>>16)+(d>>>16)&65535)<<16|d&65535}function H(b,a,c,g,d){var e=(b&65535)+(a&65535)+(c&65535)+(g&65535)+(d&65535);return((b>>>16)+(a>>>16)+(c>>>16)+(g>>>16)+(d>>>16)+(e>>>16)&65535)<<16|e&65535}function ma(b,a){var e,g,d;e=(b.b&65535)+(a.b&65535);g=(b.b>>>16)+(a.b>>>16)+(e>>>16);d=(g&
+65535)<<16|e&65535;e=(b.a&65535)+(a.a&65535)+(g>>>16);g=(b.a>>>16)+(a.a>>>16)+(e>>>16);return new c((g&65535)<<16|e&65535,d)}function na(b,a,e,g){var d,n,h;d=(b.b&65535)+(a.b&65535)+(e.b&65535)+(g.b&65535);n=(b.b>>>16)+(a.b>>>16)+(e.b>>>16)+(g.b>>>16)+(d>>>16);h=(n&65535)<<16|d&65535;d=(b.a&65535)+(a.a&65535)+(e.a&65535)+(g.a&65535)+(n>>>16);n=(b.a>>>16)+(a.a>>>16)+(e.a>>>16)+(g.a>>>16)+(d>>>16);return new c((n&65535)<<16|d&65535,h)}function oa(b,a,e,g,d){var n,h,l;n=(b.b&65535)+(a.b&65535)+(e.b&
+65535)+(g.b&65535)+(d.b&65535);h=(b.b>>>16)+(a.b>>>16)+(e.b>>>16)+(g.b>>>16)+(d.b>>>16)+(n>>>16);l=(h&65535)<<16|n&65535;n=(b.a&65535)+(a.a&65535)+(e.a&65535)+(g.a&65535)+(d.a&65535)+(h>>>16);h=(b.a>>>16)+(a.a>>>16)+(e.a>>>16)+(g.a>>>16)+(d.a>>>16)+(n>>>16);return new c((h&65535)<<16|n&65535,l)}function z(b){var a=0,e=0,g;for(g=0;g<arguments.length;g+=1)a^=arguments[g].b,e^=arguments[g].a;return new c(e,a)}function B(b){var a=[],e;if("SHA-1"===b)a=[1732584193,4023233417,2562383102,271733878,3285377520];
+else if(0===b.lastIndexOf("SHA-",0))switch(a=[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428],e=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],b){case "SHA-224":break;case "SHA-256":a=e;break;case "SHA-384":a=[new c(3418070365,a[0]),new c(1654270250,a[1]),new c(2438529370,a[2]),new c(355462360,a[3]),new c(1731405415,a[4]),new c(41048885895,a[5]),new c(3675008525,a[6]),new c(1203062813,a[7])];break;case "SHA-512":a=[new c(e[0],
+4089235720),new c(e[1],2227873595),new c(e[2],4271175723),new c(e[3],1595750129),new c(e[4],2917565137),new c(e[5],725511199),new c(e[6],4215389547),new c(e[7],327033209)];break;default:throw Error("Unknown SHA variant");}else if(0===b.lastIndexOf("SHA3-",0)||0===b.lastIndexOf("SHAKE",0))for(b=0;5>b;b+=1)a[b]=[new c(0,0),new c(0,0),new c(0,0),new c(0,0),new c(0,0)];else throw Error("No SHA variants supported");return a}function K(b,a){var c=[],e,d,n,h,l,p,f;e=a[0];d=a[1];n=a[2];h=a[3];l=a[4];for(f=
+0;80>f;f+=1)c[f]=16>f?b[f]:y(c[f-3]^c[f-8]^c[f-14]^c[f-16],1),p=20>f?H(y(e,5),d&n^~d&h,l,1518500249,c[f]):40>f?H(y(e,5),d^n^h,l,1859775393,c[f]):60>f?H(y(e,5),U(d,n,h),l,2400959708,c[f]):H(y(e,5),d^n^h,l,3395469782,c[f]),l=h,h=n,n=y(d,30),d=e,e=p;a[0]=G(e,a[0]);a[1]=G(d,a[1]);a[2]=G(n,a[2]);a[3]=G(h,a[3]);a[4]=G(l,a[4]);return a}function Z(b,a,c,e){var d;for(d=(a+65>>>9<<4)+15;b.length<=d;)b.push(0);b[a>>>5]|=128<<24-a%32;a+=c;b[d]=a&4294967295;b[d-1]=a/4294967296|0;a=b.length;for(d=0;d<a;d+=16)e=
+K(b.slice(d,d+16),e);return e}function L(b,a,k){var g,d,n,h,l,p,f,m,q,u,r,t,v,w,y,z,A,x,F,B,C,D,E=[],J;if("SHA-224"===k||"SHA-256"===k)u=64,t=1,D=Number,v=G,w=la,y=H,z=ha,A=ja,x=da,F=fa,C=U,B=aa,J=e;else if("SHA-384"===k||"SHA-512"===k)u=80,t=2,D=c,v=ma,w=na,y=oa,z=ia,A=ka,x=ea,F=ga,C=ca,B=ba,J=V;else throw Error("Unexpected error in SHA-2 implementation");k=a[0];g=a[1];d=a[2];n=a[3];h=a[4];l=a[5];p=a[6];f=a[7];for(r=0;r<u;r+=1)16>r?(q=r*t,m=b.length<=q?0:b[q],q=b.length<=q+1?0:b[q+1],E[r]=new D(m,
+q)):E[r]=w(A(E[r-2]),E[r-7],z(E[r-15]),E[r-16]),m=y(f,F(h),B(h,l,p),J[r],E[r]),q=v(x(k),C(k,g,d)),f=p,p=l,l=h,h=v(n,m),n=d,d=g,g=k,k=v(m,q);a[0]=v(k,a[0]);a[1]=v(g,a[1]);a[2]=v(d,a[2]);a[3]=v(n,a[3]);a[4]=v(h,a[4]);a[5]=v(l,a[5]);a[6]=v(p,a[6]);a[7]=v(f,a[7]);return a}function D(b,a){var e,g,d,n,h=[],l=[];if(null!==b)for(g=0;g<b.length;g+=2)a[(g>>>1)%5][(g>>>1)/5|0]=z(a[(g>>>1)%5][(g>>>1)/5|0],new c(b[g+1],b[g]));for(e=0;24>e;e+=1){n=B("SHA3-");for(g=0;5>g;g+=1)h[g]=z(a[g][0],a[g][1],a[g][2],a[g][3],
+a[g][4]);for(g=0;5>g;g+=1)l[g]=z(h[(g+4)%5],S(h[(g+1)%5],1));for(g=0;5>g;g+=1)for(d=0;5>d;d+=1)a[g][d]=z(a[g][d],l[g]);for(g=0;5>g;g+=1)for(d=0;5>d;d+=1)n[d][(2*g+3*d)%5]=S(a[g][d],W[g][d]);for(g=0;5>g;g+=1)for(d=0;5>d;d+=1)a[g][d]=z(n[g][d],new c(~n[(g+1)%5][d].a&n[(g+2)%5][d].a,~n[(g+1)%5][d].b&n[(g+2)%5][d].b));a[0][0]=z(a[0][0],X[e])}return a}var e,V,W,X;e=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,
+2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,
+2428436474,2756734187,3204031479,3329325298];V=[new c(e[0],3609767458),new c(e[1],602891725),new c(e[2],3964484399),new c(e[3],2173295548),new c(e[4],4081628472),new c(e[5],3053834265),new c(e[6],2937671579),new c(e[7],3664609560),new c(e[8],2734883394),new c(e[9],1164996542),new c(e[10],1323610764),new c(e[11],3590304994),new c(e[12],4068182383),new c(e[13],991336113),new c(e[14],633803317),new c(e[15],3479774868),new c(e[16],2666613458),new c(e[17],944711139),new c(e[18],2341262773),new c(e[19],
+2007800933),new c(e[20],1495990901),new c(e[21],1856431235),new c(e[22],3175218132),new c(e[23],2198950837),new c(e[24],3999719339),new c(e[25],766784016),new c(e[26],2566594879),new c(e[27],3203337956),new c(e[28],1034457026),new c(e[29],2466948901),new c(e[30],3758326383),new c(e[31],168717936),new c(e[32],1188179964),new c(e[33],1546045734),new c(e[34],1522805485),new c(e[35],2643833823),new c(e[36],2343527390),new c(e[37],1014477480),new c(e[38],1206759142),new c(e[39],344077627),new c(e[40],
+1290863460),new c(e[41],3158454273),new c(e[42],3505952657),new c(e[43],106217008),new c(e[44],3606008344),new c(e[45],1432725776),new c(e[46],1467031594),new c(e[47],851169720),new c(e[48],3100823752),new c(e[49],1363258195),new c(e[50],3750685593),new c(e[51],3785050280),new c(e[52],3318307427),new c(e[53],3812723403),new c(e[54],2003034995),new c(e[55],3602036899),new c(e[56],1575990012),new c(e[57],1125592928),new c(e[58],2716904306),new c(e[59],442776044),new c(e[60],593698344),new c(e[61],3733110249),
+new c(e[62],2999351573),new c(e[63],3815920427),new c(3391569614,3928383900),new c(3515267271,566280711),new c(3940187606,3454069534),new c(4118630271,4000239992),new c(116418474,1914138554),new c(174292421,2731055270),new c(289380356,3203993006),new c(460393269,320620315),new c(685471733,587496836),new c(852142971,1086792851),new c(1017036298,365543100),new c(1126000580,2618297676),new c(1288033470,3409855158),new c(1501505948,4234509866),new c(1607167915,987167468),new c(1816402316,1246189591)];
+X=[new c(0,1),new c(0,32898),new c(2147483648,32906),new c(2147483648,2147516416),new c(0,32907),new c(0,2147483649),new c(2147483648,2147516545),new c(2147483648,32777),new c(0,138),new c(0,136),new c(0,2147516425),new c(0,2147483658),new c(0,2147516555),new c(2147483648,139),new c(2147483648,32905),new c(2147483648,32771),new c(2147483648,32770),new c(2147483648,128),new c(0,32778),new c(2147483648,2147483658),new c(2147483648,2147516545),new c(2147483648,32896),new c(0,2147483649),new c(2147483648,
+2147516424)];W=[[0,36,3,41,18],[1,44,10,45,2],[62,6,43,15,61],[28,55,25,21,56],[27,20,39,8,14]];"function"===typeof define&&define.amd?define(function(){return C}):"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(module.exports=C),exports=C):Y.jsSHA=C})(this);

BIN
Public/static/res/INVgenius.png


BIN
Public/static/res/INVlogo.png


BIN
Public/static/res/INVsplash.gif


BIN
Public/static/res/favicon66.ico


+ 161 - 0
index.html

@@ -0,0 +1,161 @@
+ 
+
+<!DOCTYPE html>
+<html lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	
+  <meta charset="UTF-8"/>
+  <meta name="style" content="day1"/>
+  
+  <meta name="viewport" content="width=device-width, initial-scale=1"/>
+  
+<!--
+    Copyright 2021, 2024 5 Mode
+
+    This file is part of Invenktory.
+
+    Invenktory is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Invenktory is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Invenktory. If not, see <https://www.gnu.org/licenses/>.
+ -->
+     
+  <title>Invenktory: every device its place..</title>
+	
+  <link rel="shortcut icon" href="Public/static/res/favicon66.ico" />
+    
+  <meta name="description" content="Welcome to Invenktory"/>
+  <meta name="author" content="5 Mode"/> 
+  <meta name="keywords" content="track,your,hardware,devices,on,premise,solution"/>
+  
+  <script src="Public/static/js/jquery-3.1.0.min.js" type="text/javascript"></script>
+  <script src="Public/static/js/jquery-ui.1.12.1.min.js" type="text/javascript"></script>
+  <script src="Public/static/js/common.js" type="text/javascript"></script>
+  <script src="Public/static/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="Public/static/js/sha.js" type="text/javascript"></script>
+  
+  <script src="Public/static/js/home.js" type="text/javascript" defer></script>
+  
+  <link href="Public/static/css/bootstrap.min.css" type="text/css" rel="stylesheet">
+  <link href="Public/static/css/jquery-ui.1.12.1.css" type="text/css" rel="stylesheet">
+  <link href="Public/static/css/style.css?v=1631827555" type="text/css" rel="stylesheet">
+
+  <script>	
+    function startApp() {
+	  $("#HCsplash").hide();
+	  $("#frmHC").show();  	
+	}	
+		
+	window.addEventListener("load", function() {
+		  
+	  setTimeout("startApp()", 5000);
+	  
+	}, true);
+  </script>
+         
+</head>
+<body>
+
+<div id="HCsplash" style="padding-top: 200px; text-align:center;">
+   <img src="Public/static/res/INVsplash.gif" style="width:310px;">
+</div>
+
+<form id="frmHC" method="POST" target="_self" enctype="multipart/form-data" style="display:none;">
+
+<div class="header">
+   <a href="/" style="color:white; text-decoration: none;"><img src="Public/static/res/INVlogo.png" style="width:48px;">&nbsp;Invenktory</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/par7133/Invenktory" style="color:#ffffff"><span style="color:#119fe2">on</span> github</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="mailto:info@invenktory.com" style="color:#ffffff"><span style="color:#119fe2">for</span> feedback</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="tel:+39-331-4029415" style="font-size:13px;background-color:#15c60b;border:2px solid #15c60b;color:white;height:27px;text-decoration:none;">&nbsp;&nbsp;get support&nbsp;&nbsp;</a>
+</div>
+	
+<div style="clear:both; float:left; padding:8px; width:15%; height:100%; text-align:center;">
+	<div style="padding-left:10px;text-align: left;">
+	  &nbsp;Download<br>	
+	  &nbsp;<a href="https://github.com/par7133/Invenktory/archive/refs/tags/v1.0.5.zip">Release 1.0.5 (zip)</a><br>
+	  &nbsp;<a href="https://github.com/par7133/Invenktory/archive/refs/tags/v1.0.5.tar.gz">Release 1.0.5 (tar.gz)</a><br>
+	</div>  
+    <br><br>
+    <img src="Public/static/res/INVgenius.png" alt="HC Genius" title="HC Genius" style="position:relative; left:+6px; width:90%; border: 1px dashed #EEEEEE;">
+    &nbsp;<br><br><br>
+    &nbsp;<input type="text" id="Password" name="Password" placeholder="password" style="font-size:10px; background:#393939; color:#ffffff; width: 90%; border-radius:3px;" value="" autocomplete="off"><br>
+    &nbsp;<input type="text" id="Salt" placeholder="salt" style="position:relative; top:+5px; font-size:10px; background:#393939; color:#ffffff; width: 90%; border-radius:3px;" autocomplete="off"><br>
+    &nbsp;<a href="#" onclick="showEncodedPassword();" style="position:relative; left:-2px; top:+5px; color:#ffffff; font-size:12px;">Hash Me!</a>
+    <br><br><br>
+</div>
+
+<div style="float:left; width:85%;height:100%; padding:8px; border-left: 1px solid #2c2f34;">
+	
+	   <div id="splash" style="border-radius:20px; position:relative; left:+3px; width:98%; background-color: #33aced; padding: 20px; margin-bottom:8px;">	
+	
+	   <button type="button" class="close" aria-label="Close" onclick="" style="position:relative; left:-10px;">
+          <span aria-hidden="true">&times;</span>
+     </button>
+	
+	   Hello and welcome to Invenktory!<br><br>
+	   
+	   Invenktory is a light and simple software on premise to track your devices.<br><br>
+	   
+	   Invenktory is released under GPLv3 license, it is supplied AS-IS and we do not take any responsibility for its misusage.<br><br>
+	   
+	   First step, use the left side panel password and salt fields to create the hash to insert in the config file. Remember to manually set there also the salt value.<br><br>
+	   
+	   As you are going to run Invenktory in the PHP process context, using a limited web server or phpfpm user, you must follow some simple directives for an optimal first setup:<br>
+	   <ol>
+	   <li>Check the permissions of your "Inventory" folder in your web app private path; and set its path in the config file.</li>
+	   <li>In the Inventory path create a ".INVsampledir" folder and give to this folder the write permission. This folder will be the sample folder to copy from new folders inside the inventory path.</li>
+	   <li>Likewise, in the Inventory path must exist ".INVsamplefile.xml" and give to this file the write permission. This file will be the sample file to copy from new inventory files.</li>
+	   <li>Configure the max devices per xml file as required (default: 10).</li>	      
+     <li>Configure the max history items and max recall history items as required (default: 50).</li>	      
+	   </ol>
+	   
+	   <br>	
+	   
+	   Invenktory understands a limited set of commands with a far limited set of parameters:<br>
+	   cd, cd.., cp, edit, help, ls, mv, pwd, show<br><br>	   
+	   
+     In edit mode press [CTRL]+[X] to exit or [CTRL]+[S] to save.<br><br> 
+     
+	   Hope you can enjoy it and let us know about any feedback: <a href="mailto:info@invenktory.com" style="color:#e6d236;">info@invenktory.com</a>
+	   
+	</div>	
+	
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>	
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>	
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+	<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>	
+	
+</div>
+
+<div class="footer">
+<div id="footerCont">&nbsp;</div>
+<div id="footer"><span style="background:#FFFFFF;opacity:1.0;margin-right:10px;">&nbsp;&nbsp;A <a href="http://5mode.com">5 Mode</a> project and <a href="http://wysiwyg.systems">WYSIWYG</a> system. Some rights reserved.</span></div>	
+</div>
+
+</form>
+
+<!-- Yandex.Metrika counter -->
+<script type="text/javascript" >
+   (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
+   m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
+   (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
+
+   ym(85728648, "init", {
+        clickmap:true,
+        trackLinks:true,
+        accurateTrackBounce:true
+   });
+</script>
+<noscript><div><img src="https://mc.yandex.ru/watch/85728648" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
+<!-- /Yandex.Metrika counter -->
+
+</body>	 
+</html>	 
+

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно