Fix index page generation code
[bpgallery.git] / bpgallery.sh
1 #!/usr/bin/env bash
2
3 # bpgallery.sh - builds a simple 'gallery' from a collection of images
4 # Copyright (C) 2004 Brett Parker <iDunno@sommitrealweird.co.uk>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 set -e
21 set -f
22
23 VERSION="1.1+arch"
24
25 function bpgallery_default_head() {
26 cat <<END
27 <?xml version="1.0"?>
28 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
29 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
30 <head>
31         <title>${TITLE}</title>
32         <link rel="stylesheet" href="style.css" type="text/css" />
33 </head>
34 <body>
35 END
36 }
37
38 declare -rf bpgallery_default_head
39
40 function bpgallery_default_description() {
41 cat <<END
42         <h1>${TITLE}</h1>
43         ${DESCRIPTION}
44 END
45 }
46
47 declare -rf bpgallery_default_description
48
49 function bpgallery_default_thumbsline() {
50 if [[ -z $caption ]]; then
51         caption_alt=Unknown
52 else
53         caption_alt=$caption
54 fi
55 cat << END
56 <div class="thumbnail"><a href="$link"><img src="icons/$filename" alt="$caption_alt" /></a><div class="caption">$caption</div></div>
57 END
58 }
59
60 declare -rf bpgallery_default_thumbsline
61
62 function bpgallery_default_tail() {
63 cat << END
64 </body>
65 </html>
66 END
67 }
68
69 declare -rf bpgallery_default_tail
70
71 function bpgallery_default_stylesheet() {
72 cat <<END
73 body {
74         background: white;
75         color: black;
76         font-family: sans-serif;
77         font-size: 10pt;
78 }
79
80 div.thumbnail {
81         float: left;
82         padding: 20px;
83         border: 0px;
84         width: ${WIDTH}px;
85         height: ${MAXHEIGHT}px;
86 }
87
88 div.caption {
89         width: 100%;
90         text-align: center;
91         font-weight: bold;
92 }
93
94 div.navigation {
95         margin: 0;
96 }
97
98 div.navigation ul {
99         display: inline;
100         margin: 0;
101         padding: 0;
102         text-align: center;
103 }
104
105 div.navigation ul li {
106         display: inline;
107         margin: 2em;
108 }
109
110 a {
111         border: 0px;
112 }
113
114 img {
115         border: 0px;
116 }
117 END
118 }
119
120 declare -rf bpgallery_default_stylesheet
121
122 function bpgallery_default_page() {
123         $BPGALLERY_HEAD_FUNCTION
124
125         linkstart=""
126         linkend=""
127
128         if [[ ! -z $linklocation ]]; then
129                 linkstart="<a href='$linklocation'>"
130                 linkend="</a>"
131         fi
132         
133         cat <<END
134 <h1>${caption}</h1>
135 <div class="navigation">
136         <ul>
137                 <li><a href='${INDEXDOCUMENT}'>Thumbnails</a></li>
138 END
139         if [[ ! -z $previouspage ]]; then
140                 $ECHOCOMMAND "<li><a href='${previouspage}'>Previous</a></li>"
141         else
142                 $ECHOCOMMAND "<li>Previous</li>"
143         fi
144
145         if [[ ! -z $nextpage ]]; then
146                 $ECHOCOMMAND "<li><a href='${nextpage}'>Next</a></li>"
147         else
148                 $ECHOCOMMAND "<li>Next</li>"
149         fi
150 cat <<END
151         </ul>
152 </div>
153 <div class="mainimage">
154         ${linkstart}<img src="${filename}" alt="${caption}" />${linkend}
155 </div>
156 END
157         $BPGALLERY_TAIL_FUNCTION
158 }
159
160 declare -rf bpgallery_default_page
161
162 function bpgallery_escape_url() {
163         temp=$1
164         temp=${temp//\%/%25}
165         temp=${temp//:/%3A}
166         temp=${temp//;/%3B}
167         temp=${temp// /%20}
168         temp=${temp//$/%24}
169         temp=${temp//&/%26}
170         temp=${temp//+/%2B}
171         temp=${temp//,/%2C}
172         temp=${temp//\//%2F}
173         temp=${temp//=/%3D}
174         temp=${temp//\?/%3F}
175         temp=${temp//@/%40}
176         temp=${temp//\"/%22}
177         $ECHOCOMMAND $temp
178 }
179
180 declare -rf bpgallery_escape_url
181
182 if [[ ! -z ${BPGALLERY_THEME} ]] ; then
183         declare -r BPGALLERY_THEME
184 fi
185
186 if [[ ! -z ${TITLE} ]] ; then
187         declare -r TITLE
188 fi
189
190 if [[ -e /usr/local/etc/bpgallery/config ]] ; then
191         . /usr/local/etc/bpgallery/config 2>/dev/null
192 fi
193
194 if [[ -e /etc/bpgallery/config ]] ; then
195         . /etc/bpgallery/config 2>/dev/null
196 fi
197
198 if [[ -e $HOME/.bpgallery.rc ]]; then
199         . $HOME/.bpgallery.rc 2>/dev/null
200 fi
201
202 if [[ -e $1 && -d $1 && -e $1/.bpgallery.rc ]]; then
203         . $1/.bpgallery.rc 2>/dev/null
204 fi
205
206 if [[ -z ${BPGALLERY_THEME} ]]; then
207         BPGALLERY_THEME=default
208 fi
209
210 if [[ ! -z ${BPGALLERY_THEME_DIR} ]] && \
211         [[ -e ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} ]]; then
212         . ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} 2>/dev/null
213 elif [[ -e $HOME/.bpgallery.themes/${BPGALLERY_THEME} ]]; then
214         . $HOME/.bpgallery.themes/${BPGALLERY_THEME} 2>/dev/null
215 elif [[ -e /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
216         . /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
217 elif [[ -e /etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
218         . /etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
219 fi
220
221 if [[ -z $TITLE ]]; then 
222         TITLE="Photo Gallery"
223 fi
224
225 if [[ -z $CONVERTTOOL ]]; then
226         CONVERTTOOL=convert
227 fi
228
229 if [[ -z $FINDCOMMAND ]]; then
230         FINDCOMMAND=find
231 fi
232
233 if [[ -z $XARGSCOMMAND ]]; then
234         XARGSCOMMAND=xargs
235 fi
236
237 if [[ -z $ECHOCOMMAND ]]; then
238         ECHOCOMMAND=echo
239 fi
240
241 if [[ -z $SORTCOMMAND ]]; then
242         SORTCOMMAND=sort
243 fi
244
245 if [[ -z $IDENTIFYCOMMAND ]]; then
246         IDENTIFYCOMMAND=identify
247 fi
248
249 if [[ -z $HEADCOMMAND ]]; then
250         HEADCOMMAND=head
251 fi
252
253 if [[ -z $GREPCOMMAND ]]; then
254         GREPCOMMAND=grep
255 fi
256
257 if [[ -z $SEDCOMMAND ]]; then
258         SEDCOMMAND=sed
259 fi
260
261 if [[ -z $WIDTH ]]; then
262         WIDTH=100
263 fi
264
265 if [[ -z $IMAGEEXTENSIONS ]]; then
266         IMAGEEXTENSIONS="jpeg jpg gif png";
267 fi
268
269 if [[ -z $WCCOMMAND ]]; then
270         WCCOMMAND="wc -l"
271 fi
272
273 if [[ -z $CAPTIONHEIGHT ]]; then
274         CAPTIONHEIGHT=75
275 fi
276
277 if [[ -z $OUTPUTHTML ]]; then
278         OUTPUTHTML=0
279 fi
280
281 if [[ -z $GENERATEPAGESFORFULLSIZE ]]; then
282         GENERATEPAGESFORFULLSIZE=0
283 fi
284
285 if [[ -z $GENERATEPAGESFORMEDIUMSIZE ]]; then
286         GENERATEPAGESFORMEDIUMSIZE=1
287 fi
288
289 if [[ -z $MEDIUMWIDTH ]]; then
290         MEDIUMWIDTH=400
291 fi
292
293 if [[ -z $INDEXDOCUMENT ]]; then
294         INDEXDOCUMENT=index.html
295 fi
296
297 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
298         if declare -F "bpgallery_${BPGALLERY_THEME}_page" > /dev/null ; then
299                 BPGALLERY_PAGE_FUNCTION="bpgallery_${BPGALLERY_THEME}_page"
300         else
301                 BPGALLERY_PAGE_FUNCTION="bpgallery_default_page"
302         fi
303 fi
304
305 if declare -F "bpgallery_${BPGALLERY_THEME}_head" > /dev/null ; then
306         BPGALLERY_HEAD_FUNCTION="bpgallery_${BPGALLERY_THEME}_head"
307 else
308         BPGALLERY_HEAD_FUNCTION="bpgallery_default_head"
309 fi
310
311 if declare -F "bpgallery_${BPGALLERY_THEME}_description" > /dev/null ; then
312         BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_${BPGALLERY_THEME}_description"
313 else
314         BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_default_description"
315 fi
316
317 if declare -F "bpgallery_${BPGALLERY_THEME}_thumbsline" > /dev/null ; then
318         BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_${BPGALLERY_THEME}_thumbsline"
319 else
320         BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_default_thumbsline"
321 fi
322
323 if declare -F "bpgallery_${BPGALLERY_THEME}_tail" > /dev/null ; then
324         BPGALLERY_TAIL_FUNCTION="bpgallery_${BPGALLERY_THEME}_tail"
325 else
326         BPGALLERY_TAIL_FUNCTION="bpgallery_default_tail"
327 fi
328
329 if declare -F "bpgallery_${BPGALLERY_THEME}_stylesheet" > /dev/null ; then
330         BPGALLERY_STYLESHEET_FUNCTION="bpgallery_${BPGALLERY_THEME}_stylesheet"
331 else
332         BPGALLERY_STYLESHEET_FUNCTION="bpgallery_default_stylesheet"
333 fi
334
335 FINDIMAGESOPTIONS=""
336
337 for imageext in $IMAGEEXTENSIONS; do
338         FINDIMAGESOPTIONS=$FINDIMAGESOPTIONS' -o -type f -iname '*.$imageext' -print0'
339 done
340
341 FINDIMAGESOPTIONS=${FINDIMAGESOPTIONS## -o }
342 FINDIMAGESOPTIONS='-maxdepth 1 '${FINDIMAGESOPTIONS}
343
344 function usage() {
345 cat <<END
346 Usage:
347   $0 [--help|--version|<path to images>]
348
349     --help
350         displays this help screen
351     --version
352         displays the version and exits
353
354 This can also takes some environment variables, these will use defaults if not
355 set.
356
357         TITLE
358             the title of the gallery
359
360         WIDTH
361             the width to make the icons
362
363         MEDIUMWIDTH
364             set the width of images in the medium size pages
365
366         BPGALLERY_THEME
367             set the theme to use (described below)
368
369         BPGALLERY_THEME_DIR
370             set an extra location to look for themes
371
372         OUTPUTHTML
373             sets the script output to be wrapped in a <pre> block
374
375         GENERATEPAGESFORMEDIUMSIZE
376             generate medium sized images and pages
377
378         GENERATEPAGESFORFULLSIZE
379             decide wether to generate pages for the full size images or not
380
381         INDEXDOCUMENT
382             name of the index page (e.g. index.html)
383
384 Example:
385         TITLE="My Funky Gallery" WIDTH=200 INDEXDOCUMENT="welcome.html" GENERATEPAGESFORFULLSIZE=1 GENERATEPAGESFORMEDIUMSIZE=1 MEDIUMWIDTH=400 $0 /path/to/image/folder
386 END
387 }
388
389 function version() {
390 cat <<END
391 Version: $VERSION
392 END
393 }
394
395 function generate_resized_images() {
396         $ECHOCOMMAND "Generating $2"
397         currentimage=0
398         totalimages=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | $WCCOMMAND);
399         imagestoupdate=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | while read filename; do filename=${filename//\"/\\\"}; if [ ! -r "$2/$filename" ] || [ "$filename" -nt "$2/$filename" ] || [ $($IDENTIFYCOMMAND -format "%w" "$2/$filename") -ne $1 ]; then $ECHOCOMMAND $filename; fi; done | $WCCOMMAND)
400         
401         if [ $totalimages -eq 0 ]; then
402                 # might as well exit at this point - there are no pictures
403                 $ECHOCOMMAND "No images for the gallery - exiting."
404                 exit 64
405         else
406                 # check if the directory exists and create it other wise
407                 if [ ! -d $2 ]; then
408                         mkdir $2
409                 fi
410
411                 if [ ! -w $2 ]; then
412                         $ECHOCOMMAND "Can't write to $2 directory, exiting"
413                         exit 16
414                 fi
415         fi
416
417         if [ $totalimages -eq $imagestoupdate ]; then
418                 $ECHOCOMMAND "Regenerating all $2"
419         elif [ $imagestoupdate -eq 0 ]; then
420                 $ECHOCOMMAND "No Updated $2, not regenerating"
421                 return
422         else
423                 $ECHOCOMMAND "Generating $imagestoupdate of $totalimages $2"
424         fi
425         
426         $FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | while read filename; do tempfilename=${filename//\"/\\\"/}; if [ ! -r "$2/$tempfilename" ] || [ "$tempfilename" -nt "$2/$tempfilename" ] || [ $($IDENTIFYCOMMAND -format "%w" "$2/$filename") -ne $1 ]; then $ECHOCOMMAND -n $filename; $ECHOCOMMAND -n -e "\000"; fi; done | $XARGSCOMMAND -0 --verbose --max-procs=4 -I {} $CONVERTTOOL -resize $1 '{}' $2/'{}' 2>&1 | while read throwout; do $ECHOCOMMAND done: $currentimage/$imagestoupdate images; currentimage=$((currentimage+1)); done
427         $ECHOCOMMAND done: $imagestoupdate/$imagestoupdate images
428         $ECHOCOMMAND "Completed generating $2 for $totalimages images"
429 }
430
431 function generate_thumbs() {
432         generate_resized_images $WIDTH icons
433 }
434
435 function generate_medium() {
436         generate_resized_images $MEDIUMWIDTH medium
437 }
438
439 function generate_pages() {
440         $ECHOCOMMAND "Generating Pages"
441         previouspage=""
442         currentpage=""
443         nextpage=""
444         previousimage=""
445         currentimage=""
446         nextimage=""
447         extra=""
448         extradir=""
449         addlinks=0
450         
451         if [ ! -z $1 ]; then
452                 extra=$1
453         fi
454
455         if [ ! -z $2 ]; then
456                 extradir=$2/
457                 addlinks=1
458         fi
459
460         if [ -z $2 ] && [[ $GENERATEPAGESFORMEDIUMSIZE != 0 ]]; then
461                 addlinks=2
462         fi
463         
464         $FINDCOMMAND . $FINDIMAGESOPTIONS | \
465         $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | \
466         $SORTCOMMAND -g | \
467         while read imagefilename; do
468                 previousimage=$currentimage
469                 currentimage=$nextimage
470                 nextimage=${imagefilename#./}
471                 addlink=""
472                 
473                 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
474                         addlink=${currentimage}${extra}.html
475                 else
476                         addlink=${currentimage}
477                 fi
478
479                 if [[ $addlinks == 1 ]]; then
480                         addlink=${currentimage}.html
481                 else
482                         addlink=${currentimage}${extra}.html
483                 fi
484
485                 previouspage=$currentpage
486                 currentpage=$nextpage
487                 if [[ $addlinks == 1 ]]; then
488                         nextpage=${nextimage}${extra}.html
489                 else
490                         nextpage=${nextimage}.html
491                 fi
492                 filename=${extradir}${currentimage}
493                 generate_general_page "$previouspage" "$currentpage" "$nextpage" $addlink
494                 $ECHOCOMMAND $nextimage
495         done | tail -n 2 | (
496                 read previouspage
497                 read currentpage
498                 addlink=""
499
500                 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
501                         addlink=${currentpage}.html
502                 else
503                         addlink=${currentpage}
504                 fi
505
506                 if [[ $addlinks == 1 ]]; then
507                         addlink=${currentpage}.html
508                 else
509                         addlink=${currentpage}${extra}.html
510                 fi
511                 
512                 filename=${extradir}${currentpage}
513                 if [[ $addlinks == 1 ]]; then
514                         currentpage=${currentpage}${extra}.html
515                         previouspage=${previouspage}${extra}.html
516                 else
517                         currentpage=${currentpage}.html
518                         previouspage=${previouspage}.html
519                 fi
520                 nextpage=""
521                 generate_general_page "$previouspage" "$currentpage" "" $addlink
522         )
523 }
524
525 function generate_medium_pages() {
526         generate_pages __medium medium
527 }
528
529 function generate_general_page() {
530
531         if [[ -z $1 ]]; then
532                 previouspage=""
533         fi
534
535         if [[ -z $2 ]]; then
536                 currentpage=""
537                 return
538         fi
539
540         if [[ -z $3 ]]; then
541                 nextpage=""
542         fi
543
544         if [[ ! -z $4 ]]; then
545                 linklocation=$4
546         fi
547
548         if [ -r captions.txt ]; then
549                 caption=$($GREPCOMMAND -E "^${filename}   " captions.txt); caption=${caption#*    }
550         else
551                 caption=""
552         fi
553         
554         $BPGALLERY_PAGE_FUNCTION > "$currentpage"
555 }
556
557 if [[ $OUTPUTHTML != 0 ]]; then
558         $ECHOCOMMAND "<pre>"
559 fi
560
561 if [[ -z $1 ]]; then
562         $ECHOCOMMAND "No path given"
563         usage
564         exit 1
565 fi
566
567 if [[ "$1" == "--help" || "$1" == "-h" ]]; then
568         usage
569         exit 0
570 fi
571
572 if [[ "$1" == "--version" || "$1" == "-v" ]]; then
573         version
574         exit 0
575 fi
576
577 if [[ ! -d $1 ]]; then
578         $ECHOCOMMAND "$1 is not a directory"
579         usage
580         exit 2
581 fi
582
583 cd "$1"
584
585 if ( ! $FINDCOMMAND . $FINDIMAGESOPTIONS > /dev/null 2>/dev/null ); then
586         $ECHOCOMMAND "$1 does not contain any images. Quitting."
587         exit 4
588 fi
589
590 if [ ! -w . ]; then
591         $ECHOCOMMAND "Can't write to images directory, exiting"
592         exit 8
593 fi
594
595 if [ -e ${INDEXDOCUMENT} ] && [ ! -w ${INDEXDOCUMENT} ]; then
596         $ECHOCOMMAND "Can't write ${INDEXDOCUMENT}, exiting"
597         exit 8
598 fi
599
600 if [ -e style.css ] && [ ! -w style.css ]; then
601         $ECHOCOMMAND "Can't write style.css, exiting"
602         exit 8
603 fi
604
605 generate_thumbs
606
607 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
608         generate_medium
609         generate_medium_pages
610 fi
611
612 if [ $GENERATEPAGESFORFULLSIZE != 0 ]; then
613         if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
614                 generate_pages __medium
615         else
616                 generate_pages
617         fi
618 fi
619
620 if [ -r description.txt ] ; then
621         DESCRIPTION=$($SEDCOMMAND -e '1 { s/^/<p>/; }; /^$/ { s,$,</p><p>,; }; $ { s,$,</p>, };' description.txt)
622 else
623         DESCRIPTION=""
624 fi
625
626
627 $ECHOCOMMAND "Starting to generate page"
628
629 $BPGALLERY_HEAD_FUNCTION > ${INDEXDOCUMENT}
630 $BPGALLERY_DESCRIPTION_FUNCTION >> ${INDEXDOCUMENT}
631
632 $ECHOCOMMAND "Adding Captions"
633
634 extra=""
635 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
636         extra=__medium
637 fi
638
639 $FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | $SORTCOMMAND -g | while read filename; do filename=${filename#./}; if [ -r captions.txt ]; then caption=$($GREPCOMMAND -E "^$filename      " captions.txt); caption=${caption#*    }; else caption=""; fi; if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then link=$(bpgallery_escape_url "${filename}${extra}.html"); elif [ $GENERATEPAGESFORFULLSIZE != 0 ]; then link=$(bpgallery_escape_url "${filename}.html"); else link=$(bpgallery_escape_url "$filename"); fi; filename=$(bpgallery_escape_url "$filename"); $BPGALLERY_THUMBSLINE_FUNCTION; done >> ${INDEXDOCUMENT}
640
641 $BPGALLERY_TAIL_FUNCTION >> ${INDEXDOCUMENT}
642
643 $ECHOCOMMAND "Finished generating the page"
644 $ECHOCOMMAND "Generating stylesheet"
645 cd icons
646
647 MAXHEIGHT=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%h\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
648 MAXWIDTH=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%w\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
649
650 cd ..
651
652 # add a bit to the maxheight for the size of the caption
653 MAXHEIGHT=$((MAXHEIGHT+$CAPTIONHEIGHT))
654
655 $BPGALLERY_STYLESHEET_FUNCTION > style.css
656
657 $ECHOCOMMAND "All done"
658
659 if [[ $OUTPUTHTML != 0 ]]; then
660         $ECHOCOMMAND "</pre>"
661 fi