summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/ruby/www/dir.rb
blob: 09e088d772d05d06b961ebc1114ffaa4fc52a919 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
require 'www/lib'

# dir handling

class WWW

    # borrowed code from webrick demo, patched

    @@dir_name_width = 25

    def handle_dir(dirpath=@variables.get('path'),hidden=[],showdirs=true)
        check_template_file('dir','text-template.htm')
        docroot = @interface.get('path:docroot')
        dirpath = dirpath || ''
        hidden = [] unless hidden
        local_path = dirpath.dup
        title, str = "Index of #{escaped(dirpath)}", ''
        begin
            local_path.gsub!(/[\/\\]+/,'/')
            local_path.gsub!(/\/$/, '')
            if local_path !~ /^(\.|\.\.|\/|[a-zA-Z]\:)$/io then # maybe also /...
                full_path = File.join(docroot,local_path)
                @interface.set('log:dir', full_path)
                begin
                    list = Dir::entries(full_path)
                rescue
                    str << "unable to parse #{local_path}"
                else
                    if list then
                        list.collect! do |name|
                            if name =~ /^\.+/o then
                                nil # no . and ..
                            else
                                st = (File::stat(File.join(docroot,local_path,name)) rescue nil)
                                if st.nil? then
                                    [name, nil, -1, false]
                                elsif st.directory? then
                                    if showdirs then [name + "/", st.mtime, -1, true] else nil end
                                elsif hidden.length > 0 then
                                    if hidden.include?(name) then nil else [name, st.mtime, st.size, false] end
                                else
                                    [name, st.mtime, st.size, false]
                                end
                            end
                        end
                        list.compact!
                        n, m, s = @variables.get('n'), @variables.get('m'), @variables.get('s')
                        if    ! n.empty? then
                            idx, d0 = 0, n
                        elsif ! m.empty? then
                            idx, d0 = 1, m
                        elsif ! s.empty? then
                            idx, d0 = 2, s
                        else
                            idx, d0 = 0, 'a'
                        end
                        d1 = if d0 == 'a' then 'd' else 'a' end
                        if d0 == 'a' then
                            list.sort! do |a,b| a[idx] <=> b[idx] end
                        else
                            list.sort! do |a,b| b[idx] <=> a[idx] end
                        end
                        u = dir_uri(@variables.get('path') || '.')
                        str << "<div class='dir-view'>\n<pre>\n"
                        str << "<a href=\"#{u}&n=#{d1}\">name</A>".ljust(49+u.length)
                        str << "<a href=\"#{u}&m=#{d1}\">last modified</A>".ljust(41+u.length)
                        str << "<a href=\"#{u}&s=#{d1}\">size</A>".rjust(31+u.length) << "\n" << "\n"
                        # parent path
                        if showdirs && ! hidden.include?('..') then
                            dname = "parent directory"
                            fname = "#{File.dirname(dirpath)}"
                            time = File::mtime(File.join(docroot,local_path,"/.."))
                            str << dir_entry(fname,dname,time,-1,true)
                            str << "\n"
                        end
                        # directories
                        done = false
                        list.each do |name, time, size, dir|
                            if dir then
                                if name.size > @@dir_name_width then
                                    dname = name.sub(/^(.#{@@dir_name_width-2})(.*)/) do $1 + ".." end
                                else
                                    dname = name
                                end
                                fname = "#{escaped(dirpath)}/#{escaped(name)}"
                                str << dir_entry(fname,dname,time,size,dir)
                                done = true
                            end
                        end
                        str << "\n" if done
                        # files
                        list.each do |name, time, size, dir|
                            unless dir then
                                if name.size > @@dir_name_width then
                                    dname = name.sub(/^(.#{@@dir_name_width-2})(.*)/) do $1 + ".." end
                                else
                                    dname = name
                                end
                                fname = "#{escaped(dirpath)}/#{escaped(name)}"
                                str << dir_entry(fname,dname,time,size,dir)
                            end
                        end
                        str << "\n"
                        str << '</pre></div>'
                    else
                        str << 'no info'
                    end
                end
            else
                str << 'no access'
            end
        rescue
            str << "error #{$!}<br/><pre>"
            str << $@.join("\n")
            str << "</pre>"
        end
        message(title,str)
    end
    def dir_uri(f='.')
        u, t, o = @interface.get('dir:uri'), @interface.get('dir:task'), @interface.get('dir:option') # takes precedence, in case we run under cgi control
        if u.empty? then
            u, t, o = @interface.get('process:uri'), '', ''
        elsif ! t.empty? then
            t = "task=#{t}&"
            o = "option=#{o}&"
        end
        if u && ! u.empty? then
            u = u.sub(/\?.*$/,'') # frozen string
            if f =~ /^\.+$/ then
                "#{u}?#{t}#{o}path="
            else
                "#{u}?#{t}#{o}path=#{f}"
            end
        else
            ''
        end
    end

    def dir_entry(fname,dname,time,size,dir=false)
        if dir then
            f = fname.sub(/\/+$/,'').sub(/^\/+/,'')
            s = "<a href=\"#{dir_uri(f)}\">#{dname}</a>"
        elsif ! @interface.get('dir:uri').empty? then # takes precedence, in case we run under cgi control
            s = "<a href=\"#{dir_uri(fname.gsub(/\/+/,'/'))}\">#{dname}</a>"
        else
            s = "<a href=\"#{fname.gsub(/\/+/,'/')}\">#{dname}</a>"
        end
        # s << " " * (30 - dname.size)
        s << " " * (@@dir_name_width + 5 - dname.size)
        s << (time ? time.strftime("%Y/%m/%d %H:%M      ") : " " * 22)
        s << (size >= 0 ? size.to_s : "-").rjust(12) << "\n"
        return s
    end

end