mirror of https://github.com/dyne/webnomad.git
262 lines
7.3 KiB
Bash
Executable File
262 lines
7.3 KiB
Bash
Executable File
#!/usr/bin/env zsh
|
|
#
|
|
# ZShelf, file directory indexing for the web
|
|
#
|
|
# Copyright (C) 2014 Denis Roio <jaromil@dyne.org>
|
|
#
|
|
# This source code is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This source code is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
# Please refer to the GNU Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Public License along with
|
|
# this source code; if not, write to:
|
|
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
# API in brief:
|
|
#
|
|
# filetype_icon() - takes a filename as arg (can be file only or real path)
|
|
# - returns a filename for the icon to be used from icons/
|
|
#
|
|
# index_dir() - indexes a directory into an html file linking all its contents
|
|
#
|
|
# preview_file() - takes a filename as arg
|
|
# renders the file in a usable format (thumb if image, html if markdown, etc.)
|
|
# returns the filename of the rendered result
|
|
#
|
|
|
|
# file list map for current dir
|
|
# format: filename;size;date
|
|
typeset -alU files
|
|
|
|
|
|
filetype_icon() {
|
|
|
|
{ test "$1" = "" } && { error "filetype_icon called without argument"; return 1 }
|
|
|
|
path=""
|
|
filename="$1"
|
|
{ test -r "$1" } && {
|
|
act "fuletype_icon: argument is not a real path, skipping mimecheck"
|
|
path="$1"
|
|
filename="${path##*/}"
|
|
}
|
|
|
|
ext="${filename##*.}"
|
|
name="${filename%%.*}"
|
|
res="default.jpg"
|
|
|
|
# analize extensions, will be overridden by name
|
|
case $ext:l in
|
|
txt) res=text-plain.jpg ;;
|
|
html) res=text-x-html.jpg ;;
|
|
xml) res=text-xml.jpg ;;
|
|
md5|sha*) res=hash.jpg ;;
|
|
asc|gpg) res=signature.jpg ;;
|
|
tex|md|org) res=text-x-texinfo.jpg ;;
|
|
patch) res=text-x-patch.jpg ;;
|
|
sql) res=text-x-sql.jpg ;;
|
|
vcart) res=text-x-vcard.jpg ;;
|
|
dmg) res=dmg.png ;;
|
|
esac
|
|
# analize name
|
|
case $name:l in
|
|
changelog) res=text-x-changelog.jpg ;;
|
|
readme) res=text-x-readme.jpg ;;
|
|
install) res=text-x-install.jpg ;;
|
|
authors) res=text-x-authors.jpg ;;
|
|
makefile) res=text-x-makefile.jpg ;;
|
|
news|usage) res=text-x-nfo.jpg ;;
|
|
copying) res=text-x-copying.jpg ;;
|
|
known_bugs|todo) res=text-x-log.jpg ;;
|
|
esac
|
|
|
|
# check physical file properties
|
|
{ test "$path" = "" } || {
|
|
# is a directory
|
|
{ test -d "$path" } && {
|
|
case $name:l in
|
|
sources) res=folder-development.jpg ;;
|
|
doc|docs) res=folder-documents.jpg ;;
|
|
releases|binaries) res=folder-downloads.jpg ;;
|
|
esac
|
|
}
|
|
# todo using mimetype -b and more
|
|
}
|
|
}
|
|
|
|
index_dir() {
|
|
{ test -d "$1" } || { error "cannot index: not a directory '$1'"; return 1 }
|
|
files=()
|
|
ttmp=`ls -l --time-style=long-iso "$1" | awk '
|
|
/^total/ { next }
|
|
/^$/ { next }
|
|
{ printf "files+=(\"%s;%s;%s\")", $8, $5, $6 }
|
|
'`
|
|
{ test $? = 0 } || {
|
|
error "Error parsing directory: $1"
|
|
return 1 }
|
|
|
|
eval "$ttmp"
|
|
|
|
act "${#files} files parsed in $1"
|
|
|
|
# setup paths for test
|
|
{ test "$destination" = "test" } && {
|
|
LINK_PREFIX="file://$1"
|
|
act "LINK_PREFIX = $LINK_PREFIX"
|
|
}
|
|
|
|
# human size dividers
|
|
_mb=$((1024 * 1024))
|
|
_gb=$((1024 * 1024 * 1024))
|
|
|
|
cat <<EOF
|
|
<table class="table table-hover table-condensed">
|
|
<thead><tr>
|
|
<th class="col-sm-1 col-md-1 col-lg-1"><!-- filetype icon --></th>
|
|
<th class="col-sm-4 col-md-4 col-lg-4">Filename</th>
|
|
<th class="col-sm-1 col-md-2 col-lg-3">Size</th>
|
|
<th class="col-sm-1 col-md-2 col-lg-3">Date</th>
|
|
<th class="col-sm-3 col-md-4 col-lg-5">Preview</th>
|
|
</tr></thead>
|
|
EOF
|
|
for f in ${files}; do
|
|
name="${f[(ws:;:)1]}"
|
|
size="${f[(ws:;:)2]}"
|
|
date="${f[(ws:;:)3]}"
|
|
|
|
ext="${name##*.}" # file extension
|
|
file="${1}/${name}" # file path
|
|
|
|
# format size to human readable form
|
|
if [[ $size -lt 1024 ]]; then hsize="$size B"
|
|
elif [[ $size -gt 1024 ]]; then hsize="$(( $size / 1024 )) KB"
|
|
elif [[ $size -gt 1048576 ]]; then hsize="$(( $size / $mb )) MB"
|
|
else hsize="$(( $size / $gb )) GB"
|
|
fi
|
|
|
|
# format date to human readable form
|
|
hdate=`date -d "$date" +'%d %b %Y'`
|
|
|
|
func "$name \t $size \t $date"
|
|
|
|
typefield=""
|
|
namefield=""
|
|
previewfield=""
|
|
link=""
|
|
icon=""
|
|
|
|
preview=`preview_file "$file"`
|
|
|
|
{ test "$preview" = "" } || {
|
|
func "file preview produced"
|
|
case $ext:l in
|
|
jpg|jpeg|png|gif|pdf|svg|eps)
|
|
func "preview is a thumbnail"
|
|
preview="<img src=\"$preview\" alt=\"$name\" title=\"$name\">"
|
|
icon="image.jpg"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
icon_width="width=\"50px\""
|
|
|
|
if [ -L "$file" ]; then # is a symlink
|
|
if [ -d "$file" ]; then # symlink to folder
|
|
link="<a href=\"${name}/index.html\">"
|
|
typefield="${link}<img src=\"${WEB_ROOT}/icons/symlink.jpg\" alt=\"symlink\" ${icon_width}></a>"
|
|
namefield="${link}${name}</a>"
|
|
previewfield="<!-- folder -->"
|
|
else # symlink to file
|
|
link="<a href=\"${LINK_PREFIX}/${link}\">"
|
|
typefield="${link}<img src=\"${WEB_ROOT}/icons/symlink.jpg\" alt=\"symlink\" ${icon_width}></a>"
|
|
namefield="${link}${name}</a>"
|
|
previewfield="${link}${preview}</a>"
|
|
fi
|
|
elif [ -d "$file" ]; then # is a folder
|
|
link="<a href=\"${name}/index.html\">"
|
|
typefield="${link}<img src=\"${WEB_ROOT}/icons/folder.jpg\" alt=\"folder\" ${icon_width}></a>"
|
|
namefield="${link}${name}</a>"
|
|
previewfield="<!-- folder -->"
|
|
else # is a file
|
|
{ test "$icon" = "" } && { icon="`filetype_icon ${file}`" }
|
|
link="<a href=\"${LINK_PREFIX}/${link}\">"
|
|
typefield="${link}<img src=\"${WEB_ROOT}/icons/${icon}\" alt=\"${icon}\" ${icon_width}></a>"
|
|
namefield="${link}${name}</a>"
|
|
previewfield="${link}${preview}</a>"
|
|
fi
|
|
|
|
# render it all
|
|
cat <<EOF
|
|
<tr>
|
|
<td style="vertical-align:middle;">${typefield}</td>
|
|
<td style="vertical-align:middle;font-size:2em">${namefield}</td>
|
|
<td style="vertical-align:middle">$hsize</td>
|
|
<td style="vertical-align:middle">$hdate</td>
|
|
<td style="vertical-align:middle">${previewfield}</td>
|
|
</tr>
|
|
EOF
|
|
done
|
|
print "</table>"
|
|
}
|
|
|
|
preview_file() {
|
|
{ test "$1" = "" } && { error "no file to preview."; return 1 }
|
|
# get the file extension using zsh builtins
|
|
# %% is for deleting prefix and ## is for deleting suffix
|
|
for f in ${1}; do
|
|
filename="${f##*/}"
|
|
name="${filename%%.*}"
|
|
ext="${f##*.}"
|
|
|
|
# lowercase
|
|
case $ext:l in
|
|
md) # markdown
|
|
notice "$f: rendering markdown using maruku"
|
|
output="$name".html
|
|
maruku --html --html-frag $f -o "$output"
|
|
print "$output"
|
|
;;
|
|
jpg|jpeg|png)
|
|
output="${name}-thumb.${ext}"
|
|
{ test -r "$output" } && {
|
|
act "$f: thumbnail found, skip rendering"
|
|
print "$output"
|
|
continue }
|
|
notice "$f: rendering thumbnail using ImageMagick"
|
|
convert $f -resize 100 $output
|
|
print "$output"
|
|
;;
|
|
pdf|gif) # only first page / animation frame
|
|
output="${name}-thumb.jpg"
|
|
{ test -r "$output" } && {
|
|
act "$f: thumbnail found, skip rendering"
|
|
print "$output"
|
|
continue }
|
|
notice "$f: rendering thumbnail using ImageMagick"
|
|
convert "${f}[0]" -resize 100 $output
|
|
print "$output"
|
|
;;
|
|
svg|eps)
|
|
output="${name}-thumb.jpg"
|
|
{ test -r "$output" } && {
|
|
act "$f: thumbnail found, skip rendering"
|
|
print "$output"
|
|
continue }
|
|
notice "$f: rendering thumbnail using ImageMagick"
|
|
convert -density 144 "${f}" -resize 100 $output
|
|
print "$output"
|
|
;;
|
|
|
|
esac
|
|
done
|
|
return 0
|
|
}
|
|
|