7 var achar = 'a'.charCodeAt(0)
8 for (var i=0; i<str.length; i++) {
9 var c = str.charCodeAt(i)
10 res += String.fromCharCode((c>>4)+achar) + String.fromCharCode((c&0xf)+achar)
17 var achar = 'a'.charCodeAt(0)
18 for (var i=0; i<str.length; i+=2) {
19 var c1 = str.charCodeAt(i)-achar, c2 = str.charCodeAt(i+1)-achar
20 res += String.fromCharCode((c1<<4)+c2)
25 function cgireq(script, qs, body, cb) {
26 var req = new XMLHttpRequest()
27 req.open((body!=null)?'POST':'GET', '/cgi-bin/cwebfiles/'+script+(qs?'?'+qs:''), !!cb)
29 req.onloadend = function() {
30 cb(req.status, req.responseText)
35 return {status: req.status, data: req.responseText}
39 function login(user, pass, cb) {
40 return cgireq('login', null, user+':'+pass, cb)
43 function listdir(path, cb) {
44 cgireq('listdir', hex(path), null, function(status, data) {
45 if (status != 200) return cb(status, data, null)
46 var listing = data.split('\n').filter(function(line) {
47 return line.trim().length > 0
48 }).map(function(line) {
49 var parts = line.split(' ')
50 return {name: dehex(parts[0]), size: parseInt(parts[1]), mode: parseInt(parts[2])}
52 cb(status, data, listing)
56 var S_IFMT = parseInt("0170000",8) // bit mask for the file type bit fields
57 var S_IFSOCK = parseInt("0140000",8) // socket
58 var S_IFLNK = parseInt("0120000",8) // symbolic link
59 var S_IFREG = parseInt("0100000",8) // regular file
60 var S_IFBLK = parseInt("0060000",8) // block device
61 var S_IFDIR = parseInt("0040000",8) // directory
62 var S_IFCHR = parseInt("0020000",8) // character device
63 var S_IFIFO = parseInt("0010000",8) // FIFO
65 var S_ISUID = parseInt("0004000",8) // set UID bit
66 var S_ISGID = parseInt("0002000",8) // set-group-ID bit (see below)
67 var S_ISVTX = parseInt("0001000",8) // sticky bit (see below)
69 var S_IRWXU = parseInt("00700",8) // mask for file owner permissions
70 var S_IRUSR = parseInt("00400",8) // owner has read permission
71 var S_IWUSR = parseInt("00200",8) // owner has write permission
72 var S_IXUSR = parseInt("00100",8) // owner has execute permission
73 var S_IRWXG = parseInt("00070",8) // mask for group permissions
74 var S_IRGRP = parseInt("00040",8) // group has read permission
75 var S_IWGRP = parseInt("00020",8) // group has write permission
76 var S_IXGRP = parseInt("00010",8) // group has execute permission
77 var S_IRWXO = parseInt("00007",8) // mask for permissions for others (not in group)
78 var S_IROTH = parseInt("00004",8) // others have read permission
79 var S_IWOTH = parseInt("00002",8) // others have write permission
80 var S_IXOTH = parseInt("00001",8) // others have execute permission
84 typechars[S_IFSOCK] = 's'
85 typechars[S_IFLNK] = 'l'
86 typechars[S_IFREG] = '-'
87 typechars[S_IFBLK] = 'b'
88 typechars[S_IFDIR] = 'd'
89 typechars[S_IFCHR] = 'c'
90 typechars[S_IFIFO] = 'p'
92 function escapehtml(text) {
93 return text.replace(/&/g, '&')
94 .replace(/</g, '<')
95 .replace(/>/g, '>')
96 .replace(/"/g, '"')
101 function dive(hexedname) { __listdir(loc + dehex(hexedname) + '/'); }
103 function format_entry(entry) {
105 modeline += typechars[entry.mode&S_IFMT]
106 modeline += (entry.mode&S_IRUSR) ? 'r' : '-'
107 modeline += (entry.mode&S_IWUSR) ? 'w' : '-'
108 modeline += (entry.mode&S_ISUID) ? ((entry.mode&S_IXUSR) ? 's' : 'S') : ((entry.mode&S_IXUSR) ? 'x' : '-')
109 modeline += (entry.mode&S_IRGRP) ? 'r' : '-'
110 modeline += (entry.mode&S_IWGRP) ? 'w' : '-'
111 modeline += (entry.mode&S_ISGID) ? ((entry.mode&S_IXGRP) ? 's' : 'S') : ((entry.mode&S_IXGRP) ? 'x' : '-')
112 modeline += (entry.mode&S_IROTH) ? 'r' : '-'
113 modeline += (entry.mode&S_IWOTH) ? 'w' : '-'
114 modeline += (entry.mode&S_ISVTX) ? ((entry.mode&S_IXOTH) ? 's' : 'S') : ((entry.mode&S_IXOTH) ? 'x' : '-')
116 var markred = (entry.mode&(S_ISUID|S_ISGID))
118 modeline = '<span style="color: red">'+modeline+'</span>'
121 var showsize = (entry.mode&S_IFMT) == S_IFREG
123 var escaped_name = escapehtml(entry.name)
126 if ((entry.mode&S_IFMT) == S_IFDIR) clickcode = "dive('"+hex(entry.name)+"')"
128 return '<tr><td>'+modeline+'</td><td '+(clickcode?'class="clickme" ':'')+'onclick="'+clickcode+'">'+escaped_name+'</td><td>'+(showsize?entry.size:'')+'</td></tr>'
131 function renderloc(path) {
132 var parts = path.split('/')
134 var linkparts = parts.map(function(dir, i) {
135 var esc = (i==0) ? 'main directory' : escapehtml(dir)
136 if (i != 0) curpath += dir + '/'
137 var hexpath = hex(curpath)
138 var clickcode = "__listdir(dehex('"+hexpath+"'))"
139 return '<span class="clickme" onclick="'+clickcode+'">'+esc+'</span>'
141 return '<div id="loc">'+linkparts.join(' / ')+'</div>'
144 function __listdir(path) {
145 listdir(path, function(status, err, listing) {
151 var body = document.getElementsByTagName('body')[0]
152 body.innerHTML = renderloc(path)
153 + '<table><thead><tr><th>mode</th><th>name</th><th>size</th></tr></thead><tbody>'+listing.filter(function(e) {
154 return e.name != '.' && e.name != '..'
156 return format_entry(e)
157 }).join('')+'</tbody></table>'
158 /*listing.forEach(function(e) {
159 //e.mode = e.mode.toString(8)
160 console.log(Object.keys(e).map(function(k) {
171 text-decoration: underline;
177 <body onload="__listdir('/')">