diff --git a/webif/html/browse/index.jim b/webif/html/browse/index.jim index 9c27973..2c8266d 100755 --- a/webif/html/browse/index.jim +++ b/webif/html/browse/index.jim @@ -69,7 +69,7 @@ proc directory {file bfile tbfile} { puts "" - puts "$bfile + puts "[string map {" "  } $bfile] " lassign [dir iconset $file] icons attrs @@ -106,13 +106,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]] 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..e9b794b 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 +