#!/usr/bin/env zsh # # ZShelf, file directory indexing for the web # # Copyright (C) 2014 Denis Roio # # 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 < Filename Size Date Preview 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="\"$name\"" icon="image.jpg" ;; esac } icon_width="width=\"50px\"" if [ -L "$file" ]; then # is a symlink if [ -d "$file" ]; then # symlink to folder link="" typefield="${link}\"symlink\"" namefield="${link}${name}" previewfield="" else # symlink to file link="" typefield="${link}\"symlink\"" namefield="${link}${name}" previewfield="${link}${preview}" fi elif [ -d "$file" ]; then # is a folder link="" typefield="${link}\"folder\"" namefield="${link}${name}" previewfield="" else # is a file { test "$icon" = "" } && { icon="`filetype_icon ${file}`" } link="" typefield="${link}\"${icon}\"" namefield="${link}${name}" previewfield="${link}${preview}" fi # render it all cat < ${typefield} ${namefield} $hsize $hdate ${previewfield} EOF done print "" } 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 }