tazpanel rev 463

Add prism.js syntax highlighter; now files can be edited "in place" without page reloading; allow ANY characters in the Wi-Fi password (bug 126); change web-app layout: main window isn't scrollable, with scrollable contents.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Apr 24 16:00:14 2015 +0300 (2015-04-24)
parents d0dbe11a2060
children c23efdafb18d
files README.devel index.cgi lib/libtazpanel lib/prism.js lib/tazpanel.js network.cgi styles/default/base.css styles/default/footer.html styles/default/tweaks.css
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README.devel	Fri Apr 24 16:00:14 2015 +0300
     1.3 @@ -0,0 +1,159 @@
     1.4 +Various Development Notes
     1.5 +=========================
     1.6 +
     1.7 +--------------------------------------------------------------------------------
     1.8 +
     1.9 +network.cgi
    1.10 +-----------
    1.11 +
    1.12 +Goal: allow ANY symbols in the WPA PSK (Wi-Fi password).
    1.13 +We can find WPA PSK in the different places, and there are different
    1.14 +restrictions to write it.
    1.15 +
    1.16 +a) /etc/network.conf: SliTaz system wide networking configuration;
    1.17 +b) /etc/wpa/wpa.conf: wpa_supplicant configuration file;
    1.18 +c) html input form in the TazPanel > Network > Wireless;
    1.19 +d) saved passwords for known networks in the javascript in the same place.
    1.20 +
    1.21 +Let's see all that files/places one by one.
    1.22 +
    1.23 +
    1.24 +a) network.conf
    1.25 +
    1.26 +Really "network.conf" is a shell script. It contains variables definitions, and
    1.27 +it sourced into other shell scripts to define all Wi-Fi configuration variables.
    1.28 +By default, we can see variable and its content in the double quotes:
    1.29 +
    1.30 +WIFI_KEY="mypassword"
    1.31 +
    1.32 +There are many pitfalls if we allow ANY symbols here:
    1.33 +
    1.34 +Variable expansion:
    1.35 +WIFI_KEY="123$HOME"
    1.36 +WIFI_KEY="$0$#$? *"
    1.37 +
    1.38 +Command expansion:
    1.39 +WIFI_KEY="123$(echo 456)789"
    1.40 +WIFI_KEY="`rm -rf /`"
    1.41 +
    1.42 +Quoting problem:
    1.43 +WIFI_KEY="abc"def'ghi"
    1.44 +
    1.45 +Seems, we'll solve the problem when escape some symbols:
    1.46 +\ → \\
    1.47 +" → \"
    1.48 +$ → \$
    1.49 +` → \`
    1.50 +
    1.51 +Another solution exists (and currently I stick to it): single quotes. We need no
    1.52 +escape anything but single quotes (') in the single quotes terminated string.
    1.53 +And yes, this quoting is a pain for brain:
    1.54 +
    1.55 +Password: abc"def'ghi
    1.56 +String  : WIFI_KEY='abc"def'"'"'ghi'
    1.57 +But it is simple work for sed command.
    1.58 +
    1.59 +
    1.60 +b) wpa.conf
    1.61 +
    1.62 +wpa_supplicant actually connects us to our Wi-Fi networks, and it is a file
    1.63 +where we can store all our networks settings, including passwords. It is handy
    1.64 +when you have one network at home, other - at work, and another - at your
    1.65 +friends home. Really, you shouldn't to re-enter all these passwords again.
    1.66 +
    1.67 +We can read a lot of useful information in the wpa_cupplicant.conf file
    1.68 +(/etc/wpa/wpa_supplicant.conf):
    1.69 +
    1.70 +# psk: WPA preshared key; 256-bit pre-shared key
    1.71 +# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
    1.72 +# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
    1.73 +# generated using the passphrase and SSID). ASCII passphrase must be between
    1.74 +# 8 and 63 characters (inclusive). ext:<name of external PSK field> format can
    1.75 +# be used to indicate that the PSK/passphrase is stored in external storage.
    1.76 +# This field is not needed, if WPA-EAP is used.
    1.77 +# Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys
    1.78 +# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant
    1.79 +# startup and reconfiguration time can be optimized by generating the PSK only
    1.80 +# only when the passphrase or SSID has actually changed.
    1.81 +
    1.82 +
    1.83 +Interesting and good method to use 64 symbols "passwords", maybe we switch to it
    1.84 +sometimes. Example of using "wpa_passphrase":
    1.85 +Let network name is: my_wifi
    1.86 +Let password is    : abc'def"ghi
    1.87 +Let's run utility twice - with different quoting style:
    1.88 +
    1.89 +tux@slitaz:~$ wpa_passphrase my_wifi "abc'def\"ghi"
    1.90 +network={
    1.91 +	ssid="my_wifi"
    1.92 +	#psk="abc'def"ghi"
    1.93 +	psk=e99c121a998a0c35419b16fd56beb38d2b471fd5519518c056af933e9daf3e30
    1.94 +}
    1.95 +tux@slitaz:~$ wpa_passphrase my_wifi 'abc'"'"'def"ghi'
    1.96 +network={
    1.97 +	ssid="my_wifi"
    1.98 +	#psk="abc'def"ghi"
    1.99 +	psk=e99c121a998a0c35419b16fd56beb38d2b471fd5519518c056af933e9daf3e30
   1.100 +}
   1.101 +
   1.102 +Here psk are identical, so we can use this method.
   1.103 +
   1.104 +But I can't find advanced info about quoting style in the wpa_supplicant
   1.105 +configuration file. So, I ended with little experiment. I've created new
   1.106 +network connection in my Android smartphone and viewed my
   1.107 +/data/misc/wifi/wpa_supplicant.conf file using Root Explorer application:
   1.108 +
   1.109 +network={
   1.110 +  ssid="my_wifi"
   1.111 +  scan_ssid=1
   1.112 +  psk="abc'def"ghi"
   1.113 +  key_mgmt=WPA-PSK
   1.114 +}
   1.115 +
   1.116 +Yes, we can see unpaired quotes. Really don't know is it right. Maybe,
   1.117 +wpa_supplicant just readed line content between first and last quotes. Need to
   1.118 +dig into sources... And now I not quote psk in any manner.
   1.119 +
   1.120 +
   1.121 +c) network.cgi form input
   1.122 +
   1.123 +Piece of html code:
   1.124 +
   1.125 +<input type="password" name="password" value="$WIFI_KEY" id="password"/>
   1.126 +
   1.127 +Here we free to use single quotes or double quotes, but we should escape them
   1.128 +in the html manner:
   1.129 +' → &apos;
   1.130 +" → &quot;
   1.131 +
   1.132 +Also, don't forget about these symbols:
   1.133 +& → &amp;
   1.134 +< → &lt;
   1.135 +> → &gt;
   1.136 +
   1.137 +
   1.138 +d) network.cgi javascript database
   1.139 +
   1.140 +Also, we store passwords in the known networks database in the form of
   1.141 +javascript to gain user experience without page to be reloaded: you can click
   1.142 +Wi-Fi network name and script will fill its password for you.
   1.143 +
   1.144 +Here example of that script on the html page:
   1.145 +
   1.146 +<script type="text/javascript">
   1.147 +	ajax('network.cgi?wifi_list', '1', 'wifiList');
   1.148 +	networks = [
   1.149 +{ssid:"my_wifi", scan_ssid:"1", psk:"my_password", key_mgmt:"WPA-PSK",
   1.150 + priority:"1"},
   1.151 +{ssid:"your_wifi", scan_ssid:"1", key_mgmt:"NONE", auth_alg:"OPEN SHARED",
   1.152 + wep_key0:"01234567890123456789abcdef", priority:"3"}
   1.153 +];
   1.154 +</script>
   1.155 +
   1.156 +Here we need to escape ('"&<>) symbols as described above.
   1.157 +
   1.158 +
   1.159 +So, what do you think about this very special password? :=D
   1.160 +a'b"c $(echo  2)=$HOME`date`\t&#x
   1.161 +
   1.162 +--------------------------------------------------------------------------------
     2.1 --- a/index.cgi	Sat Apr 18 16:26:58 2015 +0300
     2.2 +++ b/index.cgi	Fri Apr 24 16:00:14 2015 +0300
     2.3 @@ -112,6 +112,7 @@
     2.4  		header
     2.5  		file="$(GET file)"
     2.6  		action="$(POST action)"; [ -z "$action" ] && action="$(GET action)" # receive 'action' both on POST or GET
     2.7 +		title="$(POST title)";   [ -z "$title"  ] && title="$(GET title)"   # (optional)
     2.8  
     2.9  		case $file in
    2.10  			*.html)
    2.11 @@ -125,8 +126,8 @@
    2.12  				cat <<EOT
    2.13  <section>
    2.14  	<header>
    2.15 -		<span data-icon="edit">$file</span>
    2.16 -		<form id="editform" method="post" action="?file=$file" class="nogap">
    2.17 +		<span data-icon="edit">${title:-$file}</span>
    2.18 +		<form id="editform" method="post" action="?file=$file">
    2.19  			<button data-icon="save">$(_ 'Save')</button>
    2.20  			<button name="action" value="diff" data-icon="diff">$(_ 'Differences')</button>
    2.21  		</form>
    2.22 @@ -173,17 +174,22 @@
    2.23  			fi
    2.24  
    2.25  			cat <<EOT
    2.26 -<section>
    2.27 +<section class="bigNoScrollable">
    2.28  	<header>
    2.29 -		<span data-icon="text">$file</span>
    2.30 +		<span data-icon="text">${title:-$file}</span>
    2.31  EOT
    2.32  			if [ -w "$file" ]; then
    2.33  				cat <<EOT
    2.34 -		<form>
    2.35 +		<span class="float-right">
    2.36 +			<button onclick='editFile()' id="edit_button" data-icon="edit">$(_ 'Edit')</button>
    2.37 +			<button onclick='saveFile("$file", "$title")' id="save_button" 
    2.38 +				data-icon="save" style="display:none">$(_ 'Save')</button>
    2.39 +		</span>
    2.40 +		<!--form>
    2.41  			<input type="hidden" name="file" value="$file"/>
    2.42  			<button name="action" value="edit" data-icon="edit">$(_ 'Edit')</button><!--
    2.43  			-->$(file_is_modified $file button)
    2.44 -		</form>
    2.45 +		</form-->
    2.46  EOT
    2.47  			elif [ -r "$file" ]; then
    2.48  				cat <<EOT
    2.49 @@ -197,25 +203,28 @@
    2.50  	</header>
    2.51  
    2.52  	<div>
    2.53 -		<pre>
    2.54 +		<pre id="fileContent" class="bigScrollable">
    2.55  EOT
    2.56 +			end_code=''
    2.57  			# Handle file type by extension as a Web Server does it.
    2.58  			case "$file" in
    2.59 +				*.sh|*.cgi|*/receipt|*.conf)
    2.60 +					echo '<code class="language-bash">'; end_code='</code>'
    2.61 +					cat | htmlize ;;
    2.62 +				*.ini)
    2.63 +					echo '<code class="language-ini">'; end_code='</code>'
    2.64 +					cat | htmlize ;;
    2.65  				*.conf|*.lst)
    2.66  					syntax_highlighter conf ;;
    2.67 -				*.sh|*.cgi)
    2.68 -					syntax_highlighter sh ;;
    2.69  				*Xorg.0.log)
    2.70  					syntax_highlighter xlog ;;
    2.71  				*dmesg.log)
    2.72  					syntax_highlighter kernel ;;
    2.73 -				*/receipt)
    2.74 -					syntax_highlighter sh ;;
    2.75  				*)
    2.76  					cat | htmlize ;;
    2.77  			esac < $file
    2.78  			cat <<EOT
    2.79 -		</pre>
    2.80 +$end_code</pre>
    2.81  	</div>
    2.82  </section>
    2.83  EOT
    2.84 @@ -295,7 +304,7 @@
    2.85  		case "$cmd" in
    2.86  		usage|help)
    2.87  			_ 'Small non-interactive terminal emulator.'; echo
    2.88 -			_ 'Run any command at your own risk, avoid interactive commands (%s)' "nano, mc, ..."; echo
    2.89 +			_ 'Run any command at your own risk, avoid interactive commands (%s)' 'nano, mc, ...'; echo
    2.90  			;;
    2.91  		wget*)
    2.92  			dl=/var/cache/downloads
    2.93 @@ -398,7 +407,7 @@
    2.94  		fi
    2.95  
    2.96  		cat <<EOT
    2.97 -<section>
    2.98 +<section style="position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: 0.5rem;">
    2.99  	<header>
   2.100  		$(_ 'Terminal settings')
   2.101  		<form>
     3.1 --- a/lib/libtazpanel	Sat Apr 18 16:26:58 2015 +0300
     3.2 +++ b/lib/libtazpanel	Fri Apr 24 16:00:14 2015 +0300
     3.3 @@ -7,6 +7,16 @@
     3.4  
     3.5  . /lib/libtaz.sh
     3.6  
     3.7 +
     3.8 +# Redefine gettext functions
     3.9 +
    3.10 +_()  { local T="$1"; shift; printf "$(gettext "$T")" "$@"; echo; }
    3.11 +_n() { local T="$1"; shift; printf "$(gettext "$T")" "$@"; }
    3.12 +_p() {
    3.13 +	local S="$1" P="$2" N="$3"; shift 3;
    3.14 +	printf "$(ngettext "$S" "$P" "$N")" "$@"; }
    3.15 +
    3.16 +
    3.17  [ "$(id -un)" == "${REMOTE_USER:=nobody}" ] || exec su -s /bin/sh -c "$(realpath $0) $@" $REMOTE_USER
    3.18  
    3.19  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/lib/prism.js	Fri Apr 24 16:00:14 2015 +0300
     4.3 @@ -0,0 +1,5 @@
     4.4 +/* http://prismjs.com/download.html?themes=prism&languages=clike+bash+ini */
     4.5 +self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=t.util.clone(e[r]));return a;case"Array":return e.map(function(e){return t.util.clone(e)})}return e}},languages:{extend:function(e,n){var a=t.util.clone(t.languages[e]);for(var r in n)a[r]=n[r];return a},insertBefore:function(e,n,a,r){r=r||t.languages;var i=r[e];if(2==arguments.length){a=arguments[1];for(var l in a)a.hasOwnProperty(l)&&(i[l]=a[l]);return i}var s={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var l in a)a.hasOwnProperty(l)&&(s[l]=a[l]);s[o]=i[o]}return t.languages.DFS(t.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=s)}),r[e]=s},DFS:function(e,n,a){for(var r in e)e.hasOwnProperty(r)&&(n.call(e,r,e[r],a||r),"Object"===t.util.type(e[r])?t.languages.DFS(e[r],n):"Array"===t.util.type(e[r])&&t.languages.DFS(e[r],n,r))}},highlightAll:function(e,n){for(var a,r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),i=0;a=r[i++];)t.highlightElement(a,e===!0,n)},highlightElement:function(a,r,i){for(var l,s,o=a;o&&!e.test(o.className);)o=o.parentNode;if(o&&(l=(o.className.match(e)||[,""])[1],s=t.languages[l]),s){a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=a.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var u=a.textContent;if(u){u=u.replace(/^(?:\r?\n|\r)/,"");var g={element:a,language:l,grammar:s,code:u};if(t.hooks.run("before-highlight",g),r&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){g.highlightedCode=n.stringify(JSON.parse(e.data),l),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(g.element),t.hooks.run("after-highlight",g)},c.postMessage(JSON.stringify({language:g.language,code:g.code}))}else g.highlightedCode=t.highlight(g.code,g.grammar,g.language),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(a),t.hooks.run("after-highlight",g)}}},highlight:function(e,a,r){var i=t.tokenize(e,a);return n.stringify(t.util.encode(i),r)},tokenize:function(e,n){var a=t.Token,r=[e],i=n.rest;if(i){for(var l in i)n[l]=i[l];delete n.rest}e:for(var l in n)if(n.hasOwnProperty(l)&&n[l]){var s=n[l];s="Array"===t.util.type(s)?s:[s];for(var o=0;o<s.length;++o){var u=s[o],g=u.inside,c=!!u.lookbehind,f=0,h=u.alias;u=u.pattern||u;for(var p=0;p<r.length;p++){var d=r[p];if(r.length>e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);;
     4.6 +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/("|')(\\\n|\\?.)*?\1/,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":{pattern:/[a-z0-9_]+\(/i,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/,ignore:/&(lt|gt|amp);/i,punctuation:/[{}[\];(),.:]/};;
     4.7 +Prism.languages.bash=Prism.languages.extend("clike",{comment:{pattern:/(^|[^"{\\])(#.*?(\r?\n|$))/,lookbehind:!0},string:{pattern:/("|')(\\?[\s\S])*?\1/,inside:{property:/\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^\}]+\})/}},number:{pattern:/([^\w\.])-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/,lookbehind:!0},"function":/\b(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|declare|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|echo|egrep|eject|enable|env|ethtool|eval|exec|exit|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|select|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|until|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)\b/,keyword:/\b(if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)\b/}),Prism.languages.insertBefore("bash","keyword",{property:/\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^}]+\})/}),Prism.languages.insertBefore("bash","comment",{important:/(^#!\s*\/bin\/bash)|(^#!\s*\/bin\/sh)/});;
     4.8 +Prism.languages.ini={comment:/^\s*;.*$/m,important:/\[.*?\]/m,constant:/^\s*[^\s=]+?(?=[ \t]*=)/m,"attr-value":{pattern:/=.*/m,inside:{punctuation:/^[=]/}}};;
     5.1 --- a/lib/tazpanel.js	Sat Apr 18 16:26:58 2015 +0300
     5.2 +++ b/lib/tazpanel.js	Fri Apr 24 16:00:14 2015 +0300
     5.3 @@ -468,3 +468,49 @@
     5.4  	else
     5.5  		improveText.value = document.getElementById(improveType.value).innerText;
     5.6  }
     5.7 +
     5.8 +
     5.9 +//
    5.10 +// Edit and save files "in place"
    5.11 +//
    5.12 +
    5.13 +function editFile() {
    5.14 +	document.getElementById('edit_button').style.display = 'none';
    5.15 +	document.getElementById('save_button').style.display = '';
    5.16 +
    5.17 +	with(document.getElementById('fileContent')) {
    5.18 +		contentEditable = true;
    5.19 +		onkeydown = insertTab;
    5.20 +		focus();
    5.21 +	}
    5.22 +}
    5.23 +
    5.24 +function saveFile(file, fileTitle) {
    5.25 +	var newArea = document.createElement('TEXTAREA');
    5.26 +	with(newArea) {
    5.27 +		name = 'content';
    5.28 +		textContent = document.getElementById('fileContent').textContent;
    5.29 +	}
    5.30 +
    5.31 +	var newTitle = document.createElement('INPUT');
    5.32 +	with(newTitle) {
    5.33 +		name = 'title';
    5.34 +		value = fileTitle;
    5.35 +	}
    5.36 +
    5.37 +	var newForm = document.createElement('FORM');
    5.38 +	with(newForm) {
    5.39 +		appendChild(newArea);
    5.40 +		appendChild(newTitle);
    5.41 +		method = 'post';
    5.42 +		action = "?file=" + file;
    5.43 +		submit();
    5.44 +	}
    5.45 +}
    5.46 +
    5.47 +function insertTab(e) {
    5.48 +	var evt = e ? e:event;
    5.49 +	if (evt.keyCode == 9) {
    5.50 +		evt.preventDefault();
    5.51 +	}
    5.52 +}
     6.1 --- a/network.cgi	Sat Apr 18 16:26:58 2015 +0300
     6.2 +++ b/network.cgi	Fri Apr 24 16:00:14 2015 +0300
     6.3 @@ -25,34 +25,15 @@
     6.4  	ifconfig $WIFI_INTERFACE up
     6.5  	iwconfig $WIFI_INTERFACE txpower auto
     6.6  	/etc/init.d/network.sh restart | log
     6.7 -	# Sleep until connection established (max 20 seconds)
     6.8 -	for i in $(seq 20); do
     6.9 +
    6.10 +	# Sleep until connection established (max 5 seconds)
    6.11 +	for i in $(seq 5); do
    6.12  		[ -n "$(iwconfig 2>/dev/null | fgrep Link)" ] && break
    6.13  		sleep 1
    6.14  	done
    6.15  }
    6.16  
    6.17  
    6.18 -# Connect to a Wi-Fi network
    6.19 -connect_wifi() {
    6.20 -	/etc/init.d/network.sh stop | log
    6.21 -	sed -i \
    6.22 -		-e "s|^WIFI_ESSID=.*|WIFI_ESSID=\"$(GET essid)\"|" \
    6.23 -		-e "s|^WIFI_BSSID=.*|WIFI_BSSID=\"$(GET bssid)\"|" \
    6.24 -		-e "s|^WIFI_KEY_TYPE=.*|WIFI_KEY_TYPE=\"$(GET keyType)\"|" \
    6.25 -		-e "s|^WIFI_KEY=.*|WIFI_KEY=\"$(GET password)\"|" \
    6.26 -		-e "s|^WIFI_EAP_METHOD=.*|WIFI_EAP_METHOD=\"$(GET eap)\"|" \
    6.27 -		-e "s|^WIFI_CA_CERT=.*|WIFI_CA_CERT=\"$(GET caCert)\"|" \
    6.28 -		-e "s|^WIFI_CLIENT_CERT=.*|WIFI_CLIENT_CERT=\"$(GET clientCert)\"|" \
    6.29 -		-e "s|^WIFI_IDENTITY=.*|WIFI_IDENTITY=\"$(GET identity)\"|" \
    6.30 -		-e "s|^WIFI_ANONYMOUS_IDENTITY=.*|WIFI_ANONYMOUS_IDENTITY=\"$(GET anonymousIdentity)\"|" \
    6.31 -		-e "s|^WIFI_PHASE2=.*|WIFI_PHASE2=\"$(GET phase2)\"|" \
    6.32 -		/etc/network.conf
    6.33 -	. /etc/network.conf
    6.34 -	start_wifi
    6.35 -}
    6.36 -
    6.37 -
    6.38  # Start an Ethernet connection
    6.39  
    6.40  start_eth() {
    6.41 @@ -95,11 +76,24 @@
    6.42  			if ($0 ~ "=") {
    6.43  				if (begin_obj == 0) printf ", ";
    6.44  				begin_obj = 0;
    6.45 -				split($0, a, "=");
    6.46 -				if (a[2] ~ "\"")
    6.47 -					printf "%s:%s", a[1], a[2];
    6.48 -				else
    6.49 -					printf "%s:\"%s\"", a[1], a[2];
    6.50 +
    6.51 +				# split line into variable and value (note "=" can appear in the value)
    6.52 +				split($0, a, "="); variable = a[1];
    6.53 +				value = gensub(variable "=", "", "");
    6.54 +
    6.55 +				# escape html entities
    6.56 +				value = gensub("\\\\", "\\\\",    "g", value);
    6.57 +				value = gensub("&",    "\\&amp;", "g", value);
    6.58 +				value = gensub("<",    "\\&lt;",  "g", value);
    6.59 +				value = gensub(">",    "\\&gt;",  "g", value);
    6.60 +				value = gensub("\"",   "\\\"",    "g", value);
    6.61 +
    6.62 +				# if value was already quoted - remove \" from begin and end
    6.63 +				if (substr(value, 1, 2) == "\\\"")
    6.64 +					value = substr(value, 3, length(value) - 4);
    6.65 +
    6.66 +				# output in form: variable:"escaped value"
    6.67 +				printf "%s:\"%s\"", variable, value;
    6.68  			}
    6.69  		}
    6.70  		if (network == 1 && $0 ~ "}") { printf "}"; network = 0; next; }
    6.71 @@ -112,11 +106,12 @@
    6.72  # Waiting for network link up
    6.73  
    6.74  wait_up() {
    6.75 -	for i in $(seq 10); do
    6.76 +	for i in $(seq 5); do
    6.77  		[ -z "$(cat /sys/class/net/*/operstate | fgrep up)"] && sleep 1
    6.78  	done
    6.79  }
    6.80  
    6.81 +
    6.82  # Actions commands before page is displayed
    6.83  
    6.84  case " $(GET) " in
    6.85 @@ -134,14 +129,38 @@
    6.86  		start_wifi ;;
    6.87  	*\ start_eth\ *)
    6.88  		start_eth ;;
    6.89 -	*\ connect_wifi\ *)
    6.90 -		connect_wifi ;;
    6.91  	*\ host\ *)
    6.92  		get_hostname="$(GET host)"
    6.93  		echo $(_ 'Changed hostname: %s' $get_hostname) | log
    6.94  		echo "$get_hostname" > /etc/hostname ;;
    6.95  esac
    6.96  
    6.97 +case " $(POST) " in
    6.98 +	*\ connect_wifi\ *)
    6.99 +		# Connect to a Wi-Fi network
   6.100 +		/etc/init.d/network.sh stop | log
   6.101 +		password="$(POST password)"
   6.102 +
   6.103 +		# Escape special characters to use with sed substitutions
   6.104 +		password="$(echo -n "$password" | sed 's|\\|\\\\|g; s|&|\\\&|g' | sed "s|'|'\"'\"'|g")"
   6.105 +
   6.106 +		sed -i \
   6.107 +			-e "s|^WIFI_ESSID=.*|WIFI_ESSID=\"$(POST essid)\"|" \
   6.108 +			-e "s|^WIFI_BSSID=.*|WIFI_BSSID=\"$(POST bssid)\"|" \
   6.109 +			-e "s|^WIFI_KEY_TYPE=.*|WIFI_KEY_TYPE=\"$(POST keyType)\"|" \
   6.110 +			-e "s|^WIFI_KEY=.*|WIFI_KEY='$password'|" \
   6.111 +			-e "s|^WIFI_EAP_METHOD=.*|WIFI_EAP_METHOD=\"$(POST eap)\"|" \
   6.112 +			-e "s|^WIFI_CA_CERT=.*|WIFI_CA_CERT=\"$(POST caCert)\"|" \
   6.113 +			-e "s|^WIFI_CLIENT_CERT=.*|WIFI_CLIENT_CERT=\"$(POST clientCert)\"|" \
   6.114 +			-e "s|^WIFI_IDENTITY=.*|WIFI_IDENTITY=\"$(POST identity)\"|" \
   6.115 +			-e "s|^WIFI_ANONYMOUS_IDENTITY=.*|WIFI_ANONYMOUS_IDENTITY=\"$(POST anonymousIdentity)\"|" \
   6.116 +			-e "s|^WIFI_PHASE2=.*|WIFI_PHASE2=\"$(POST phase2)\"|" \
   6.117 +			/etc/network.conf
   6.118 +		. /etc/network.conf
   6.119 +		start_wifi
   6.120 +		;;
   6.121 +esac
   6.122 +
   6.123  
   6.124  # Get values only now since they could have been modified by actions.
   6.125  
   6.126 @@ -412,18 +431,14 @@
   6.127  </script>
   6.128  EOT
   6.129  
   6.130 -			# ESSID names are clickable
   6.131 -			#SELECT="$(GET select)"
   6.132 -			#if [ -n "$SELECT" ]; then
   6.133 -			#	[ "$SELECT" != "$WIFI_ESSID" ] && WIFI_KEY=''
   6.134 -			#	WIFI_ESSID="$SELECT"
   6.135 -			#fi
   6.136 +		# Escape html characters in the WIFI_KEY
   6.137 +		WIFI_KEY_ESCAPED="$(echo -n "$WIFI_KEY" | sed 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g; s|"|\&quot;|g')"
   6.138  
   6.139  			cat <<EOT
   6.140  <section>
   6.141  	<header>$(_ 'Connection')</header>
   6.142  	<div>
   6.143 -		<form id="connection">
   6.144 +		<form method="post" action="?wifi" id="connection">
   6.145  			<input type="hidden" name="connect_wifi"/>
   6.146  			<input type="hidden" name="bssid" id="bssid"/>
   6.147  			<table>
   6.148 @@ -487,7 +502,7 @@
   6.149  				<tr class="wep wpa eap">
   6.150  					<td><div>$(_ 'Password')</div></td>
   6.151  					<td><div>
   6.152 -						<input type="password" name="password" value="$WIFI_KEY" id="password"/>
   6.153 +						<input type="password" name="password" value="$WIFI_KEY_ESCAPED" id="password"/>
   6.154  						<span data-img="view" title="$(_ 'Show password')"
   6.155  							onmousedown="document.getElementById('password').type='text'; return false"
   6.156  							  onmouseup="document.getElementById('password').type='password'"
   6.157 @@ -496,13 +511,6 @@
   6.158  					</div></td>
   6.159  				</tr>
   6.160  
   6.161 -
   6.162 -<!--
   6.163 -				<tr><td>$(_ 'Access point')</td>
   6.164 -					<td><input type="text" name="ap" value="$WIFI_AP"/></td>
   6.165 -				</tr>
   6.166 --->
   6.167 -
   6.168  				<script type="text/javascript">
   6.169  function wifiSettingsChange() {
   6.170  	document.getElementById('connection').className = 
   6.171 @@ -556,7 +564,7 @@
   6.172  		cat <<EOT
   6.173  	</header>
   6.174  	<div>$(_ "These values are the wifi settings in the main /etc/network.conf configuration file")</div>
   6.175 -	<pre>$(grep ^WIFI /etc/network.conf | sed '/WIFI_KEY=/s|".*"|"********"|' | syntax_highlighter conf)</pre>
   6.176 +	<pre>$(grep ^WIFI /etc/network.conf | sed 's|WIFI_KEY=.*|WIFI_KEY="********"|' | syntax_highlighter conf)</pre>
   6.177  </section>
   6.178  
   6.179  
     7.1 --- a/styles/default/base.css	Sat Apr 18 16:26:58 2015 +0300
     7.2 +++ b/styles/default/base.css	Fri Apr 24 16:00:14 2015 +0300
     7.3 @@ -23,7 +23,7 @@
     7.4  body > header h1 {
     7.5  	margin: 0;
     7.6  	color: #fff;
     7.7 -	font-size: 20px; line-height: 40px; /* center vertical */
     7.8 +	font-size: 18px; line-height: 40px; /* center vertical */
     7.9  	font-style: italic;
    7.10  	white-space: nowrap; overflow: hidden;
    7.11  	vertical-align: middle;
    7.12 @@ -211,11 +211,11 @@
    7.13  
    7.14  
    7.15  /* Page content container */
    7.16 -#content { margin: 1ex; }
    7.17 +#content { margin: 0; padding: 1ex; }
    7.18  
    7.19  
    7.20  /* Page first header */
    7.21 -h2 { font-size: 1.5rem; padding: 0.5rem 0 0 0; margin: 0; }
    7.22 +h2 { font-size: 1.5rem; height: 1.5rem; padding: 0; margin: 0; }
    7.23  
    7.24  
    7.25  /* Additional headers (obsolete) */
    7.26 @@ -224,7 +224,7 @@
    7.27  
    7.28  
    7.29  /* Plain paragraph */
    7.30 -p { margin: 1ex 0; }
    7.31 +p { margin: 0.5ex 0; }
    7.32  
    7.33  
    7.34  #actions p { margin: 6px 0; }
    7.35 @@ -364,7 +364,7 @@
    7.36  body > footer {
    7.37  	border-top: 1px solid;
    7.38  	text-align: center;
    7.39 -	padding: 0.5em;
    7.40 +	height: 1rem;
    7.41  	font-size: smaller;
    7.42  }
    7.43  
    7.44 @@ -740,3 +740,18 @@
    7.45  /* Disable some links to root actions */
    7.46  button:not([disabled]) { cursor: pointer; }
    7.47  .user [data-root] { pointer-events: none; cursor: default !important; }
    7.48 +
    7.49 +
    7.50 +html,body { height: 100%; width: 100%; margin: 0; padding: 0; }
    7.51 +body > header { position: absolute; top: 0; }
    7.52 +body > footer { position: absolute; bottom: 0; left: 0; right: 0; }
    7.53 +#content, #content-sidebar {
    7.54 +	position: absolute; top: 63px; bottom: 1rem; left: 0; right: 0;
    7.55 +	overflow-y: auto; overflow-x: hidden;
    7.56 +}
    7.57 +
    7.58 +.bigNoScrollable { position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; }
    7.59 +section.bigNoScrollable { margin: 0.5rem; }
    7.60 +
    7.61 +.bigScrollable { position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow: auto; }
    7.62 +#fileContent.bigScrollable { margin: 0.2rem; top: 2.5rem; }
     8.1 --- a/styles/default/footer.html	Sat Apr 18 16:26:58 2015 +0300
     8.2 +++ b/styles/default/footer.html	Fri Apr 24 16:00:14 2015 +0300
     8.3 @@ -3,6 +3,8 @@
     8.4  <!-- End of content-->
     8.5  </div>
     8.6  
     8.7 +</td></tr></table>
     8.8 +
     8.9  <footer>
    8.10  	$(gettext 'Copyright') &copy; $(date +%Y)
    8.11  	<a href="http://www.slitaz.org/" target="_blank">SliTaz GNU/Linux</a>
     9.1 --- a/styles/default/tweaks.css	Sat Apr 18 16:26:58 2015 +0300
     9.2 +++ b/styles/default/tweaks.css	Fri Apr 24 16:00:14 2015 +0300
     9.3 @@ -184,8 +184,9 @@
     9.4   * Buttons with icons *
     9.5   **********************/
     9.6  
     9.7 -.light a[data-icon]::before, .light button[data-icon]::before
     9.8 -{ color: #333; }
     9.9 +/*.light a[data-icon]:not([disabled])::before,
    9.10 +.light button[data-icon]:not([disabled])::before
    9.11 +{ color: #333; }*/
    9.12  
    9.13  .light button[data-icon]::before {
    9.14  	text-shadow: 0 1px 0 hsla(0, 0%, 100%, 0.9); }