diff --git a/webif/html/browse/index.jim b/webif/html/browse/index.jim
index 9c27973..6351ab5 100755
--- a/webif/html/browse/index.jim
+++ b/webif/html/browse/index.jim
@@ -58,6 +58,10 @@ proc icon {img {hover ""} {extra ""} {class "va"}} {
puts ">"
}
+proc nbsp {str} {
+ return [string map {" " } $str]
+}
+
proc directory {file bfile tbfile} {
puts "
"
set img "/images/711_1_09_Media_Folder.png"
@@ -69,7 +73,7 @@ proc directory {file bfile tbfile} {
puts "
"
- puts "$bfile
+ puts "[nbsp $bfile]
"
lassign [dir iconset $file] icons attrs
@@ -106,13 +110,12 @@ proc entry {file} {{i 0}} {
global dircount filecount dinuse
set bfile [file tail $file]
- regsub -all " +" $bfile "" tbfile
if {[string index $bfile 0] == "\025"} {
set bfile [string range $bfile 1 end]
}
if {[file isdirectory "$file"]} {
incr dircount
- directory $file $bfile $tbfile
+ directory $file $bfile [b64uencode [jsescape $bfile]]
return
}
set ext [string tolower [file extension $file]]
@@ -174,7 +177,7 @@ proc entry {file} {{i 0}} {
- $bfile
+ [nbsp $bfile]
"
diff --git a/webif/html/browse/script.js b/webif/html/browse/script.js
index 28ad4b1..cec02bb 100755
--- a/webif/html/browse/script.js
+++ b/webif/html/browse/script.js
@@ -111,8 +111,13 @@ function epginfo_callback(data, status, xhr)
function insert_folder_size(folder, size)
{
- folder = folder.replace(/ /g, '');
- folder = folder.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1');
+ // folder = folder.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1');
+ // ID of size element is ID + RFC4648 s5 encoding of folder name
+ folder = "ID" +
+ btoa(escape(folder))
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_')
+ .replace(/=/g, '');
//console.log("Folder: (%s) = (%s)", folder, size);
if (size.search(/\d$/) == -1)
size += 'iB';
diff --git a/webif/lib/utils b/webif/lib/utils
index 53eaf04..7eb71e4 100644
--- a/webif/lib/utils
+++ b/webif/lib/utils
@@ -20,3 +20,98 @@ proc midnight {} {{today ""}} {
return [clock scan "$today 00:00:00" -format "%Y %m %d %T"]
}
+# Base-64 according to RFC 4648
+# See https://wiki.tcl-lang.org/page/base64
+
+if {![exists -command binary]} { package require binary }
+
+# RFC 4648 section 4
+set ::b64::map {
+ 000000 A 000001 B 000010 C 000011 D 000100 E 000101 F
+ 000110 G 000111 H 001000 I 001001 J 001010 K 001011 L
+ 001100 M 001101 N 001110 O 001111 P 010000 Q 010001 R
+ 010010 S 010011 T 010100 U 010101 V 010110 W 010111 X
+ 011000 Y 011001 Z 011010 a 011011 b 011100 c 011101 d
+ 011110 e 011111 f 100000 g 100001 h 100010 i 100011 j
+ 100100 k 100101 l 100110 m 100111 n 101000 o 101001 p
+ 101010 q 101011 r 101100 s 101101 t 101110 u 101111 v
+ 110000 w 110001 x 110010 y 110011 z 110100 0 110101 1
+ 110110 2 110111 3 111000 4 111001 5 111010 6 111011 7
+ 111100 8 111101 9 111110 + 111111 /
+}
+
+set ::b64::unmap [join [lmap {a b} $::b64::map {list $b $a}]]
+
+proc ::b64::encode {str} {
+ binary scan $str B* bits
+ switch [expr {[string length $bits]%6}] {
+ 0 {set tail {}}
+ 2 {append bits 0000; set tail ==}
+ 4 {append bits 00; set tail =}
+ }
+ return [string cat [string map $::b64::map $bits] $tail]
+}
+
+proc ::b64::decode {str} {
+ set nstr [string trimright $str =]
+ set dstr [string map $::b64::unmap $nstr]
+ switch [expr [string length $str]-[string length $nstr]] {
+ 0 {#nothing to do}
+ 1 {set dstr [string range $dstr 0 {end-2}]}
+ 2 {set dstr [string range $dstr 0 {end-4}]}
+ }
+ return [binary format B* $dstr]
+}
+
+# RFC 4648 section 5
+proc ::b64::url_encode {str} {
+ tailcall string map {+ - / _ = ""} [::b64::encode $str]
+}
+
+proc ::b64::url_decode {str} {
+ tailcall ::b64::decode [string map {- + _ /} $str]
+}
+
+alias b64encode ::b64::encode
+alias b64decode ::b64::decode
+alias b64uencode ::b64::url_encode
+alias b64udecode ::b64::url_decode
+
+
+# ECMA-262 Annex B.2.1
+proc ::js::_escape {str} {
+ return [join [lmap c [split $str ""] {
+ if {1 != [scan $c "%c" cc]} {
+ format "%s" $c
+ } elseif {$cc < 256} {
+ format "%%%02X" $cc
+ } else {
+ format "%%u%04X" $cc
+ }
+ }] ""]
+}
+
+proc ::js::_unescape {str} {
+ if {1 == [scan $str "%%%2x" cc] ||
+ 1 == [scan $str "%%u%4x" cc]} {
+ return [format "%c" $cc]
+ } else {
+ return $str
+ }
+}
+
+proc ::js::escape {str} {
+ return [subst -nobackslashes -novariables \
+ [regsub -all -- {[^A-Za-z0-9@*_+-./]+} $str \
+ {[::js::_escape {&}]}]]
+}
+
+proc ::js::unescape {str} {
+ return [subst -nobackslashes -novariables \
+ [regsub -all -- {%(u[[:xdigit:]]{2})?[[:xdigit:]]{2}} $str \
+ {[::js::_unescape {&}]}]]
+}
+
+alias jsescape ::js::escape
+alias jsunescape ::js::unescape
+