1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2009-2014, VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(http_dirindex, 36 [ http_reply_dirindex/3, % +PhysicalDir, +Options, +Request 37 directory_index//2 % +PhysicalDir, +Options 38 ]). 39:- use_module(library(http/html_write)). 40:- use_module(library(http/http_path)). 41:- use_module(library(http/http_dispatch)). 42:- use_module(library(http/http_server_files)). 43:- use_module(library(http/html_head)). 44:- use_module(library(http/mimetype)). 45:- use_module(library(apply)). 46:- use_module(library(option)). 47 48:- predicate_options(http_reply_dirindex/3, 2, 49 [ title(any), 50 pass_to(http_dispatch:http_safe_file/2, 2) 51 ]).
The calling conventions allows for direct calling from http_handler/3.
72http_reply_dirindex(DirSpec, Options, Request) :- 73 http_safe_file(DirSpec, Options), 74 absolute_file_name(DirSpec, Dir, 75 [ file_type(directory), 76 access(read) 77 ]), 78 memberchk(path(Path), Request), 79 ( atom_concat(PlainPath, /, Path), 80 merge_options(Options, 81 [ title(['Index of ', PlainPath]) ], 82 Options1) 83 -> dir_index(Dir, Options1) 84 ; atom_concat(Path, /, NewLocation), 85 throw(http_reply(moved(NewLocation))) 86 ). 87 88dir_index(Dir, Options) :- 89 directory_members(Dir, SubDirs, Files), 90 option(title(Title), Options, Dir), 91 reply_html_page( 92 dir_index(Dir, Title), 93 title(Title), 94 [ h1(Title), 95 \dirindex_table(SubDirs, Files, Options) 96 ]). 97 98directory_members(Dir, Dirs, Files) :- 99 atom_concat(Dir, '/*', Pattern), 100 expand_file_name(Pattern, Matches), 101 partition(exists_directory, Matches, Dirs, Files).
name
(default), size
or time
.ascending
. The altenative is
descending
114directory_index(Dir, Options) --> 115 { directory_members(Dir, SubDirs, Files) }, 116 dirindex_table(SubDirs, Files, Options). 117 118dirindex_table(SubDirs, Files, Options) --> 119 { option(order_by(By), Options, name), 120 sort_files(By, Files, SortedFiles0), 121 asc_desc(SortedFiles0, SortedFiles, Options) 122 }, 123 html_requires(http_dirindex), 124 html(table(class(dirindex), 125 [ \dirindex_title, 126 \back 127 | \dirmembers(SubDirs, SortedFiles) 128 ])). 129 130sort_files(name, Files, Files) :- !. 131sort_files(Order, Files, Sorted) :- 132 map_list_to_pairs(key_file(Order), Files, Pairs), 133 keysort(Pairs, SortedPairs), 134 pairs_values(SortedPairs, Sorted). 135 136key_file(name, File, Base) :- 137 file_base_name(File, Base). 138key_file(size, File, Size) :- 139 size_file(File, Size). 140key_file(time, File, Time) :- 141 time_file(File, Time). 142 143asc_desc(Files, Ordered, Options) :- 144 ( option(order(ascending), Options, ascending) 145 -> Ordered = Files 146 ; reverse(Files, Ordered) 147 ). 148 149dirindex_title --> 150 html(tr(class(dirindex_header), 151 [ th(class(icon), ''), 152 th(class(name), 'Name'), 153 th(class(modified), 'Last modified'), 154 th(class(size), 'Size') 155 ])). 156 157back --> 158 html(tr([ \icon_cell('back.png', '[UP]'), 159 \name_cell(.., 'Up'), 160 td(class(modified), -), 161 td(class(size), -) 162 ])). 163 164dirmembers(Dirs, Files) --> 165 dir_rows(Dirs, odd, End), 166 file_rows(Files, End, _). 167 168dir_rows([], OE, OE) --> []. 169dir_rows([H|T], OE0, OE) --> 170 dir_row(H, OE0), 171 { oe(OE0, OE1) }, 172 dir_rows(T, OE1, OE). 173 174file_rows([], OE, OE) --> []. 175file_rows([H|T], OE0, OE) --> 176 file_row(H, OE0), 177 {oe(OE0, OE1)}, 178 file_rows(T, OE1, OE). 179 180oe(odd, even). 181oe(even, odd). 182 183dir_row(Dir, OE) --> 184 { file_base_name(Dir, Name) 185 }, 186 html(tr(class(OE), 187 [ \icon_cell('folder.png', '[DIR]'), 188 \name_cell(Name, Name), 189 \modified_cell(Dir), 190 td(class(size), -) 191 ])). 192 193 194file_row(File, OE) --> 195 { file_base_name(File, Name), 196 file_mime_type(File, MimeType), 197 mime_type_icon(MimeType, IconName), 198 uri_encoded(path, Name, Ref) 199 }, 200 html(tr(class(OE), 201 [ \icon_cell(IconName, '[FILE]'), 202 \name_cell(Ref, Name), 203 \modified_cell(File), 204 td(class(size), \size(File)) 205 ])). 206 207icon_cell(IconName, Alt) --> 208 { http_absolute_location(icons(IconName), Icon, []) 209 }, 210 html(td(class(icon), img([src(Icon), alt(Alt)]))). 211 212 213name_cell(Ref, Name) --> 214 html(td(class(name), a(href(Ref), Name))). 215 216 217modified_cell(Name) --> 218 { time_file(Name, Stamp), 219 format_time(string(Date), '%+', Stamp) 220 }, 221 html(td(class(modified), Date)). 222 223size(Name) --> 224 { size_file(Name, Size) 225 }, 226 html('~D'-[Size]).
icons
.
239mime_type_icon(Ext, Icon) :- 240 http:mime_type_icon(Ext, Icon), 241 !. 242mime_type_icon(_, 'generic.png').
absolute_file_name(icons(IconName), Path, [])
.
252:- multifile 253 http:mime_type_icon/2. 254 255httpmime_type_icon(application/pdf, 'layout.png'). 256httpmime_type_icon(text/csrc, 'c.png'). 257httpmime_type_icon(application/'x-gzip', 'compressed.png'). 258httpmime_type_icon(application/'x-gtar', 'compressed.png'). 259httpmime_type_icon(application/zip, 'compressed.png'). 260 261 262 /******************************* 263 * RESOURCES * 264 *******************************/ 265 266:- html_resource(http_dirindex, 267 [ virtual(true), 268 requires([ css('dirindex.css') 269 ]) 270 ]).
HTTP directory listings
This module provides a simple API to generate an index for a physical directory. The index can be customised by overruling the dirindex.css CSS file and by defining additional rules for icons using the hook file_extension_icon/2.