diff --git a/doc/connect_remote.html b/doc/connect_remote.html index 73d9a13..1dfb7c7 100644 --- a/doc/connect_remote.html +++ b/doc/connect_remote.html @@ -32,6 +32,7 @@ ol{ text-align: left; width: fit-content; + width: -moz-fit-content; margin:0 auto; } ul li{list-style-position: inside;} diff --git a/doc/localhost.html b/doc/localhost.html index c897934..a884601 100644 --- a/doc/localhost.html +++ b/doc/localhost.html @@ -32,6 +32,7 @@ ol,ul{ text-align: left; width: fit-content; + width: -moz-fit-content; margin:0 auto; } ul li{list-style-position: inside;} diff --git a/licenses.html b/licenses.html index 6bf75c4..5605ab1 100644 --- a/licenses.html +++ b/licenses.html @@ -35,7 +35,7 @@
- +

diff --git a/main.php b/main.php index d4adab0..fdf7845 100644 --- a/main.php +++ b/main.php @@ -16,9 +16,9 @@ - +
- + DB:
diff --git a/php/100.php b/php/100.php index e443f30..889fd33 100644 --- a/php/100.php +++ b/php/100.php @@ -4,17 +4,16 @@ * Login */ - $LOCALHOST=(($_SERVER["SERVER_ADDR"]=="::1" || $_SERVER["SERVER_ADDR"]=="127.0.0.1") ? true:false); // Turn true to allow localhost connections. - //$LOCALHOST=true; // Enable this line and comment the previous one to allow localhost access. - error_reporting(E_ALL ^ E_WARNING); // Supress warnings, comment to debug. + require("config.php"); + if(!$DEBUG_MODE){error_reporting(E_ALL ^ E_WARNING);} // Supress warnings session_start(); require("conn.php"); $h=$_REQUEST["h"]; $hn=$h; - if(!$LOCALHOST){ + if(!$_CONFIG["allow_localhost"]){ if($h == "localhost"){die("For security reasons, conections to 'localhost' are bloqued. Learn more about localhost here.

Return");} } $u=$_REQUEST["u"]; @@ -31,6 +30,6 @@ die("[System] Conection failed - ".mysqli_connect_errno()."
".mysqli_connect_error()."

Return"); } - //header('Location: ../main'); + //header('Location: ../main'); // This won't work on some servers die(''); ?> diff --git a/php/101.php b/php/101.php index a5e65ec..4846a8a 100644 --- a/php/101.php +++ b/php/101.php @@ -4,7 +4,9 @@ * Used by AJAX JavaScript to execute an SQL query and return its result. */ - error_reporting(E_ALL ^ E_WARNING); // Supress warnings, comment to debug. + + require("config.php"); + if(!$DEBUG_MODE){error_reporting(E_ALL ^ E_WARNING);} // Supress warnings session_start(); require("conn.php"); diff --git a/php/102.php b/php/102.php index 426ad5a..ba958a7 100644 --- a/php/102.php +++ b/php/102.php @@ -4,10 +4,11 @@ * Log out */ + session_start(); session_unset(); - //header('Location: ../login'); + //header('Location: ../login'); // This won't work on some servers die(''); ?> diff --git a/php/103.php b/php/103.php index 0083ddc..8c75a91 100644 --- a/php/103.php +++ b/php/103.php @@ -4,7 +4,9 @@ * Returns the hintOptions[table] for the code editor using AJAX. */ - error_reporting(E_ALL ^ E_WARNING); // Supress warnings, comment to debug. + + require("config.php"); + if(!$DEBUG_MODE){error_reporting(E_ALL ^ E_WARNING);} // Supress warnings session_start(); require("conn.php"); diff --git a/php/config.php b/php/config.php new file mode 100644 index 0000000..ef977a6 --- /dev/null +++ b/php/config.php @@ -0,0 +1,14 @@ + diff --git a/script.js b/script.js index 8158208..0e7265c 100644 --- a/script.js +++ b/script.js @@ -1,4 +1,4 @@ -var cardHTML = '
SQL
Result
Raw result
'; +var cardHTML = '
SQL
Result
Raw result
'; var defaults = { lineNumbers: true, matchBrackets: true, @@ -12,11 +12,16 @@ var defaults = { lineWrapping: true, hintOptions: {} }; +var snippets=[]; +var snippetsHTML=""; var G_TEXTAREA=null; function CopyBtn(btn_elem){ var textarea = btn_elem.parentElement.children[0]; - navigator.clipboard.writeText(textarea.value); + copyTextToClipboard(textarea.value); +} +function CopySnippet(this_elm){ + copyTextToClipboard(snippets[this_elm.value][1]); } function SelectNext(btn_elem,ind){ var elm = btn_elem.parentElement.children[ind]; @@ -30,6 +35,7 @@ function RunQuery(){ G_TEXTAREA.setAttribute("readonly","true"); table.parentElement.style.backgroundColor="var(--color2)"; G_TEXTAREA.parentElement.lastChild.setAttribute("onclick","CopyBtn(this)"); + G_TEXTAREA.parentElement.lastChild.previousSibling.setAttribute("disabled","true"); G_TEXTAREA.parentElement.lastChild.value="Copy"; ExecQuery(val,table.children[1].children[1],table.children[2].children[1]); @@ -44,14 +50,29 @@ function InstantiateCard(){ G_TEXTAREA = document.querySelector(".card:last-child textarea"); window.editor = CodeMirror.fromTextArea(G_TEXTAREA, defaults); - ScrollBottom(); + + if(snippetsHTML==""){ // Never loaded snippets.txt + G_TEXTAREA.parentElement.lastChild.previousSibling.style.display="none"; + GetSnippets(); + + // Wait 100 milliseconds. + setTimeout(function () { + if(snippetsHTML!=""){ + G_TEXTAREA.parentElement.lastChild.previousSibling.innerHTML = snippetsHTML; + G_TEXTAREA.parentElement.lastChild.previousSibling.style.display="inline"; + } + }, 100); + }else{ + G_TEXTAREA.parentElement.lastChild.previousSibling.innerHTML = snippetsHTML; + } AutocompletChanged(); GetTableHint(); + ScrollBottom(); } function ExecQuery(sqlstr,resulte,rawr){ - console.log(sqlstr); + console.debug("SQL: "+sqlstr); if (sqlstr.length == 0) { InstantiateCard(); } else { @@ -62,7 +83,7 @@ function ExecQuery(sqlstr,resulte,rawr){ if (this.readyState == 4 && this.status == 200) { var res=this.responseText; - console.log(res); + console.debug("RAW: "+res); rawr.innerHTML=escapeHtml(res); resulte.parentElement.style.display="table-row"; @@ -75,11 +96,10 @@ function ExecQuery(sqlstr,resulte,rawr){ InstantiateCard(); return; } - console.log(resarray); + console.debug("Parsed: "+resarray); var pres=""; for (var i = 0; i < resarray.length; i++) { - console.log(typeof resarray[i]); if(typeof resarray[i]==="boolean" || resarray[i].length==0){ pres+="

No result.

"; }else if(typeof resarray[i] !== "object"){ @@ -125,9 +145,8 @@ function AutocompletChanged(){ if(document.getElementById("totalCompletion").checked){ window.editor.on("keyup", function (cm, event) { var cr=cm.getCursor(); - var pr_char=cm.getLine(cr["line"]).charCodeAt([cr["ch"]]-1); // Character before cursor. - - if(pr_char===undefined || pr_char<48 || pr_char===59){return false;} // Not autocomplete if its <"0", OR ; " ' + var pr_char=cm.getLine(cr["line"]).charAt([cr["ch"]]-1); // Character before cursor. + if(pr_char===undefined || (pr_char!="." && !(/^[a-zA-Z0-9]+$/).test(pr_char))){return false;} // Not autocomplete if its not alfanumeric. if (!cm.state.completionActive && event.keyCode != 13) { CodeMirror.commands.autocomplete(cm, null, {completeSingle: false}); @@ -157,6 +176,51 @@ function GetTableHint(){ } } } +function GetSnippets(){ + var xmlhttp = new XMLHttpRequest(); + xmlhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + var res=this.responseText; + res=res.split("\n"); + + for (var i = 0; i < res.length; i++) { + if(res[i].toString().trim()==="---"){continue;} + + res[i]=res[i].split("::"); + if(res[i].length<2){ + res.splice(i, 1); + continue; + } + + res[i][1]=res[i][1].replace(/\\n/g,"\n").replace(/\\t/g,"\t"); + } + + snippets=res; + + snippetsHTML=''; + var groupclosing=false; + for (var i = 0; i < snippets.length; i++) { + if(snippets[i].toString().trim()==="---"){ + snippetsHTML+=''; + continue; + }else if(snippets[i][0]===""){ + if(groupclosing){snippetsHTML+="
";} + + snippetsHTML+=''; + snippetsHTML+='' + groupclosing=true; + continue; + } + + snippetsHTML+='"; + } + if(groupclosing){snippetsHTML+="

";} + snippetsHTML+=''; + } + }; + xmlhttp.open("GET", "snippets.txt", true); + xmlhttp.send(); +} /* EXTRAS */ @@ -187,3 +251,30 @@ function escapeHtml(text) { return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } +function copyTextToClipboard(text) { + if (!navigator.clipboard) { + var textArea = document.createElement("textarea"); + textArea.value = text; + + // Avoid scrolling to bottom + textArea.style.position = "fixed"; + textArea.style.top = "0"; + textArea.style.left = "0"; + + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + } catch (err) { + console.error('Fallback: Oops, unable to copy', err); + } + + document.body.removeChild(textArea); + return; + } + navigator.clipboard.writeText(text).then(function() {}, function(err) { + console.error('Async: Could not copy text. ', err); + }); +} diff --git a/snippets.txt b/snippets.txt new file mode 100644 index 0000000..c6c70fb --- /dev/null +++ b/snippets.txt @@ -0,0 +1,28 @@ +::General +Select *::SELECT * FROM table_name; +Select::SELECT column1, column2, columnN\nFROM table_name\nWHERE condition; +Update::UPDATE table_name\nSET column1=value, column2=value, columnN=value\nWHERE condition; +Insert into::INSERT INTO table_name (column1,column2,columnN)\nVALUES (value1,value2,valueN); +Delete::DELETE FROM table_name\nWHERE 0; -- Change this +::Database +Show databases::SHOW DATABASES; +Create database::CREATE DATABASE database_name; +Drop database::DROP DATABASE database_name; +::Table +Show tables::SHOW TABLES; +Create table::CREATE TABLE table_name (\n\tid int PRIMARY KEY,\n\tcolumn2 datatype,\n\tcolumn3 datatype,\n\tcolumnN datatype\n); +Drop table::DROP TABLE table_name; +Truncate table::TRUNCATE TABLE table_name; +--- +Show columns::SELECT ORDINAL_POSITION AS "N", COLUMN_NAME AS "Column Name", COLUMN_TYPE AS "Datatype", COLUMN_KEY AS "Key", EXTRA\nFROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'table_name'; +Add column::ALTER TABLE table_name\nADD column_name datatype; +Drop column::ALTER TABLE table_name\nDROP COLUMN column_name; +Modify column::ALTER TABLE table_name\nMODIFY COLUMN column_name datatype; +::Users +Show users::SELECT User, Host, CASE\n WHEN Password="" THEN "NO" ELSE "YES"\nEND AS "Using password" FROM mysql.user; +Create user::CREATE USER 'username'@'localhost' IDENTIFIED BY 'user_password'; -- This user will not have any privileges. Use GRANT to assign them. +Grant privileges::GRANT INSERT, UPDATE, DELETE, ... /* For all privileges use: ALL PRIVILEGES */\nON table_name\nTO username@localhost; +Drop user::DROP USER 'username'@'localhost'; +::Misc +Set autoincrement::ALTER TABLE table_name AUTO_INCREMENT=100; +CASE Statement::CASE\n\tWHEN condition1 THEN result1\n\tWHEN condition2 THEN result2\n\tWHEN conditionN THEN resultN\n\tELSE result\nEND diff --git a/style.css b/style.css index fbfd853..a9e14f3 100644 --- a/style.css +++ b/style.css @@ -64,6 +64,14 @@ tt{ background-color:rgba(0,0,0,0.05); border-radius: 3px; } +optgroup{font-weight: bold;font-style: normal;} +select option[disabled]{ + font-weight: bold; + color:red; +} +select option.separator{ + font-size: 0.25em; +} .center{text-align: center;} .mono{font-family: 'Roboto',monospace;} @@ -77,12 +85,16 @@ input[type="text"],input[type="password"]{ } .button{ font-family: sans-serif; - padding:6px 12px; + padding:0.5em 1em; cursor:pointer; } +.button.little{ + font-size:10px; +} + .tip{ border-bottom: 1px dotted var(--aux2); - font-family: monospace; + font-family: 'Roboto',monospace; } #top{height:32px;} @@ -102,9 +114,10 @@ input[type="text"],input[type="password"]{ margin-right: 6px; vertical-align: middle; } +#topbar hr{cursor:default;} #topbar span{ cursor: text; - font-family: monospace; + font-family: 'Roboto',monospace; margin-right: 12px; user-select: text; } @@ -131,6 +144,7 @@ input[type="text"],input[type="password"]{ background-color: var(--color44); box-shadow: 0 9px 20px 0px #000; margin:16px; + overflow-x: auto; } .card table{ width:100%;