From: Don Armstrong Date: Wed, 16 Mar 2011 15:57:38 +0000 (+0000) Subject: [svn-inject] Installing original source of libapache-gallery-perl (0.99-svn060811) X-Git-Tag: upstream/0.99-svn060811~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=d3c8d55b4f2598bf8232642796c2a0e8c1b8cfcd;p=deb_pkgs%2Flibapache-gallery-perl.git [svn-inject] Installing original source of libapache-gallery-perl (0.99-svn060811) git-svn-id: file:///srv/don_svn/deb_pkgs/libapache-gallery-perl/branches/upstream/current@533 8f7917da-ec0b-0410-a553-b9b0e350d17e --- d3c8d55b4f2598bf8232642796c2a0e8c1b8cfcd diff --git a/Changes b/Changes new file mode 100644 index 0000000..9e221e4 --- /dev/null +++ b/Changes @@ -0,0 +1,218 @@ +$Author: mil $ $Rev: 308 $ +$Date: 2005-09-16 11:52:59 +0300 (Fri, 16 Sep 2005) $ + +Revision history for Perl extension Apache::Gallery. + + - Handle files that match both GalleryDocFile and GalleryImgFile + correctly. (Claus Faerber) + +1.0RC3 Fri Sep 16 10:27:48 CEST 2005 + + - Add watermark even when picture doesn't need to be rescaled + (Andreas Plesner) + - Fix logging to work in Apache 1.3 (Andreas Plesner) + - Bugfix: If only one GallerySize was specified, the image's + max width was autmatically added to GallerySizes + (Andreas Plesner) + - Bugfix: Locate thm files if they are called .thm or .THM + (Michael Legart) + +1.0RC2 Wed Jun 1 09:11:50 CEST 2005 + + - Added access keys for navigation (Michael Knudsen) + +1.0RC1 Tue May 24 13:31:50 CEST 2005 + + - Added submit button to form in selection mode (Vlad Marchenko) + - Added new option GalleryRootPath for use when the gallery + is not running from the root of the virtual host (Lubomir Host) + - Report proper errors when there are problems with templates (Don Armstrong) + - Support newest mod_perl2 version (Philip Paeps) + +0.9.1 Sat Sep 11 23:52:16 CEST 2004 + + - Fix mod_perl 1 support that was broken with 0.9 (Michael Legart) + +0.9 Sat Sep 11 22:03:20 CEST 2004 + + - Handle .thm for all filetypes and not just tiff, gif and png + (Michael Legart) + - Make GallerySortBy work for directories (Michael Legart) + - Make GalleryDirSortBy override GallerySortBy for directories + (Andreas Plesner) + - Report 404 for HEAD requests to non-existing files or directories + (Michael Legart) + - Scale images when they are requested from the cache instead of + before the index is displayed. (Michael Legart) + - Sort pictures the same way when viewing images as when viewing + directories (Andreas Plesner) + - Make the "back" link on the error page work in IE (Michael Legart) + - Fixed the TITLE tag for folder comments (Ondra Kudlik) + - New option GalleryUnderscoresToSpaces to convert underscores to + spaces in the listing of directories. (Ondra Kudlik) + - Bugfix for when running outside a virtual host (Jeffrey Hartmann) + - Support Apache2 on FreeBSD (Jesper Dalberg) + - Avoid false 404 errors when running under mod_perl 2 (Tom Brown) + +0.8 Sun Mar 7 11:22:00 CET 2004 + + - Remember choosen width by setting a cookie (Rene Joergensen) + - Fixed a bug where $EXIFVALUES was left blank if a picture + had a comment. (Michael Legart) + - Fixed a bug where one line comments was showed as $COMMENT + (Jesper Skriver) + - Fixed a bug where comments did not get shown when using + the variables exif mode (Thomas L. Kjeldsen) + - Added two new configuration options GalleryDocFile and + GalleryImgFile that makes it possible to configured which + filetypes should be displayed. See the documentation for + details. (Guillaume Rousse) + - Added new option GalleryThumbnailSizeLS. If set to 1, + GalleryThumbnailSize is the long and the short side + of the thumbnail image instead of the width and height. + (Don Armstrong) + - Switched to use Text::Template instead of CGI::FastTemplate, + see the UPGRADE file for details. (Don Armstrong) + - Create copyright notices on pictures using truetype fonts + instead of png images. Font, color and size can be configured + (Thomas Petersen, Michael Legart) + +0.7 Mon Sep 8 22:30:35 CEST 2003 + + - Support mod_perl version 1 and 2 (1.99) (Michael Legart) + - Send status code 500 on errors, 404 on file not found and + make IE show our own errorpage. (Thomas L. Kjeldsen) + - Bugfix for directories named "0" (Andreas Plesner Jacobsen) + - Added "selection mode". Select images with checkboxes and + get a list of filenames. (Peter Andreasen) + - Fix to let the module work with perl 5.005 (Aaron) + - Do not allow scaling pictures to sizes above their + original size (Aaron) + - Added GalleryUseFileDate option to make A::G show + the files timestamps instead of using the EXIF value (Dennis Haney) + - Remember display size when turning Slideshow off (Hans Joergensen) + - Nice new layout (Thomas Kjaer) + - New option GalleryEXIFMode to control the way EXIF + info is displayed. See docs for details (Michael Legart) + - Support for the FNumber EXIF value (Thomas Corell) + - Added GalleryRootText option to allow changing the name of + the root element in the menu (Christopher Knight) + - Use Image::Imlib2 instead of Inline::C (Andreas Plesner Jacobsen) + - New option GalleryMaxThumbnailsPerPage to limit the number + of thumbnails displayed per page. Disabled by default + and requires templates update. (Michael Legart) + - Bugfix for the GalleryThumbnailSize option. Both height and + width max sizes are now obeyed. (David Gee) + +0.6 Tue Apr 22 10:24:40 CEST 2003 + + - Apache now internally handles image dispatch which enables + use of all Apache caching possibilities (Thomas Eibner) + - Documentation and better implementation of the .folder + feature. (Jesper Skriver) + - Support the EXIF Orientation key for automatic rotate, + if your camera supports that - like Canon G3. You can + disable this by setting GalleryAutoRotate to 0 (Me) + - Works with Inline > 0.42 (Andreas Plesner) + - Show nice icons and allow downloads for doc,mp3,ogg,rtf,wav + and wmv in addition to the current movie types (Me) + - Now displays nice values for Aperture,FocalLength,ShutterSpeed + exif values (Thomas Eibner) + - Directory comments added (Hans Joergensen) + - New GallerySortBy option to allow sort by time, size etc (Iain Wade) + - Set width/height on thumbnail images for better performance (Iain Wade) + +0.5.1 Sat Nov 9 11:49:29 CET 2002 + + - InlineDir is no longer configurable using PerlSetVar, which + fixes make test. (Me) + - Added test-suite (Me, Andreas Plesner Jacobsen) + - Write to the error log if unable to open files in the cache (Me) + - cache_dir changed to use File::Spec to make Apache::Gallery + more portable. It may even run under Windows now? (Andreas Plesner Jacobsen) + +0.5 Sun Sep 15 11:55:56 CEST 2002 + + - Added slideshow feature (Me) + - Code cleanup (Me) + - Moved the cache to one single directory outside the webscope (Rene Joergensen) + - Allow user to customize the "No info found" message (Me) + +0.4.1 Sun Aug 11 17:48:09 CEST 2002 + + - URI Escape image URL in the size selection URLs. (Me) + - Fixed bug where .cache directory was not created when requesting images directly (Me) + - Don't allow scaling images more than their original size (Jan Chrillesen) + - Handle already rotated images correct (Jan Chrillesen, Me) + - Fix bug when rotating pictures and a .thm file was present (Thomas Eibner) + - Apache::Gallery now allows for regular files to be served correctly (Thomas Eibner) + - Support for detailed flash information from Image::Info 1.11 (Me, Allan Joergensen) + - Moved Apache::Gallery into subversion revision control instead of CVS (Me) + +0.4 Sun Jun 2 13:11:09 CEST 2002 + + - Round height and width to integers when scaling to avoid + widths like 640x479.393939393939 (Me) + - Regenerate scaled pictures and thumbnails if the original + image has changed, the image.rotate file has been added or + changed or if the copyright image was added og changed. (Me) + - Don't show files starting with "." in the thumbnail index (Yann Kerhervé) + - Made thumbnailsizes configurable with the GalleryThumbnailSize + option. (Me) + - Print "Unknown" instead of $INFO in the imageinfo field if + unable to find any EXIF information. (Me) + - Added perldoc documentation of the module and a installationguide. (Me) + - Always list directories before images (Me) + - Allow textfiles (ie, robots.txt) (Me) + - Fixed a bug where $FILES was printed instead of "Empty directory" + if directory contained unsupported files (.txt, .htaccess etc) (Me) + - New templates where folders doesn't get displayed one on each line (Thomas Kjaer) + - Works without a VirtualHost now (Does not use DocumentRoot) (Peter Breton) + - New option GalleryWrapNavigation to enable a new feature in the + pictureview where "Next" at the end displays the first picture etc + (Peter Breton/Me) + - New option AllowOriginal for the user to be able to download the + original picture, not enabled by default (Thomas Eibner) + - TIFF and PPM support (Thomas Eibner) + - Initial movie support - download movie clips (Rene Joergensen) + +0.3.1 Thu Jan 10 15:47:39 CET 2002 + + - Fixed a huge memoryleak. + +0.3 Wed Jan 2 00:25:21 CET 2002 + + - Made Inline dir configurable. (Tim Coleman) + - Made it configurable which information about the image + should be viewed. (Thomas Eibner) + - Added GallerySizes option. You can now choose which + resolutions the user can scale between. The Gallery + will not allow scaling to 641x480 if you only configured + 640x480. (To prevent evil people filling up your disk) (Me) + - Handle spaces in files and directories correct. + - Now possible to rotate pictures on the fly. (Thomas Eibner) + - Copyright picture can be included on each picture (Thomas Eibner) + - Comments for each picture changed to be in + picture.jpg.comments (Thomas Eibner) + - Scale thumbnails correct when images are rotated 90-degrees. (Me) + +0.2 Sun Oct 14 19:57:06 2001 + - addcomments.pl renamed to gallery-editcomments.pl + - Added "viewing picture X of Y" when viewing images + - Switched to using Imlib2 instead of GD. Apache::Gallery + now supports all the image formats Imlib2 supports. + - Added gallery-buildcache.pl script to generated thumbnails + (Usefull if your browser times out the first time you + visit a new gallery) + +0.1.1 Sat Sep 30 01:10:03 2001 + - Added src/addcomments.pl script for editing picture + comments. + + - Templates have been updated by Erwin Lansing and + Thomas Kjaer and are now much nicer by default! + +0.1 Mon Aug 20 19:38:31 2001 + - original version; created by h2xs 1.21 with options + -XA -n Apache::Gallery + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..71369d4 --- /dev/null +++ b/INSTALL @@ -0,0 +1,117 @@ +Apache/Gallery version 1.0 +=========================== + +INSTALLATION + +Before you start installing Apache::Gallery you need to check +that you have the following installed: + +- Perl 5 (http://www.cpan.org/src/README.html) +- Apache (http://httpd.apache.org/) - 1.3.x or 2.x +- mod_perl (http://perl.apache.org/) - 1.x or 2.x (2.0.0 or newer) +- X11 libraries (ie, XFree86) +- Imlib2 (http://prdownloads.sourceforge.net/enlightenment/imlib2-1.0.3.tar.gz) + +Perl Modules: (Use http://search.cpan.org/ to find them) + +- URI::Escape +- Image::Info version 1.11. (NB NB NB: Version 1.12 is known to give problems) +- Image::Size +- Text::Template +- CGI (3.08) +- Image::Imlib2 (1.02) + +When installing Imlib2 from rpm, deb or other packages formats, remember +that you need the imlib2-dev package too. On Debian this can be installed +by running: + +apt-get install libimlib2-dev + +Then, to install Apache::Gallery run the following commands: + + perl Makefile.PL + make + export MOD_PERL_API_VERSION=2 # Only if you run mod_perl 2.0 + make test (optional) + make install + +If you use Apache 1.3 and mod_perl 1, you need to configure +your virtualhostblock to look like: + + + ServerName gallery.yourdomain.org + DocumentRoot /data/pictures/ + ErrorLog logs/gallery-error_log + TransferLog logs/gallery-access_log + PerlSetVar GalleryTemplateDir '/usr/local/apache/gallery/templates/default/' + PerlSetVar GalleryInfo 'Picture Taken => DateTimeOriginal, Flash => Flash' + PerlSetVar GallerySizes '640 1024 1600 2272' + PerlSetVar GalleryThumbnailSize '100x75' + PerlSetVar GalleryCopyrightImage 'htdocs/c.png' + + SetHandler perl-script + PerlHandler Apache::Gallery + + + +In case you run apache 2 and modperl 2 (or 1.99), it needs to look +like: + + + ServerName gallery.yourdomain.org + DocumentRoot /data/pictures/ + ErrorLog logs/gallery-error_log + TransferLog logs/gallery-access_log + PerlSetVar GalleryTemplateDir '/usr/local/apache/gallery/templates/default/' + PerlSetVar GalleryInfo 'Picture Taken => DateTimeOriginal, Flash => Flash' + PerlSetVar GallerySizes '640 1024 1600 2272' + PerlSetVar GalleryThumbnailSize '100x75' + PerlSetVar GalleryCopyrightImage 'htdocs/c.png' + PerlOptions +GlobalRequest + + SetHandler modperl + PerlResponseHandler Apache::Gallery + + + +Warning: Apache::Gallery does not work properly if mod_autoindex +is loaded by Apache. Indeed, mod_autoindex overrides Apache::Gallery +and does not let it display directory content. + +To check if your apache loads mod_autoindex, just look for this line +in httpd.conf: + +LoadModule autoindex_module /usr/lib/apache/1.3/mod_autoindex.so + +If this line is not commented, Apache::Gallery will only work when an +image is loaded directly. Whenever a directory listing is requested, +Apache will respond with the classic (and ugly) directory listing performed +by mod_autoindex. + +Copy the files from templates/ to where you pointed GalleryTemplateDir to. + +Create a directory called gallery in your Apache icons directory and +copy the png files in htdocs to this directory. + +The gallery.css file from the template directory you choose must be +copied to the DocumentRoot of your gallery. + +It is possible to include a graphical copyright notice on each picture now. +By setting the GalleryCopyrightImage PerlSetVar you can define the path +to a picture that you want include in the bottom right of each picture. + +Feel free to contact me with questions if you have problems setting up +Apache::Gallery. You can write to michael@legart.dk + +Make sure you try the latest version of the gallery from + before reporting bugs. + +If you are brave you can also download the latest snapshot +from http://svn.apachegallery.dk/snapshots/ + +If you have problems installing Apache::Gallery, please make +sure to run "make test" to see, what may be the problem. + +When reporting bugs please use this page and include the output from make test +in your bugreport: + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dc8e7d2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,5 @@ +$Author: mil $ $Rev: 255 $ +$Date: 2004-04-12 20:49:02 +0300 (Mon, 12 Apr 2004) $ + +Apache::Gallery is free software and is released under the Artistic License. +See for details. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..3043ef1 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,79 @@ +MANIFEST +INSTALL +Makefile.PL +TODO +LICENSE +README +Changes +lib/Apache/Gallery.pm +UPGRADE +htdocs/sound-ogg.png +htdocs/video-wmv.png +htdocs/video-asf.png +htdocs/video-mov.png +htdocs/application-pdf.png +htdocs/application-doc.png +htdocs/sound-mp3.png +htdocs/sound-wav.png +htdocs/application-rtf.png +htdocs/video-mpeg.png +htdocs/video-mpg.png +htdocs/video-avi.png +htdocs/c.png +htdocs/agfolder.png +t/002_inpng.png +t/005_jpg.jpg +t/002_graphlibs.t +t/001_use.t +t/006_thumbnails.t +t/002_injpg.jpg +t/004_cache_dir.t +t/003_comment.t +t/003_commenttest +t/005_imageinfo.t +t/007_pod.t +templates/default/dircomment.tpl +templates/default/directory.tpl +templates/default/error.tpl +templates/default/file.tpl +templates/default/index.tpl +templates/default/info.tpl +templates/default/interval.tpl +templates/default/intervalactive.tpl +templates/default/layout.tpl +templates/default/navpicture.tpl +templates/default/nodircomment.tpl +templates/default/nopictureinfo.tpl +templates/default/orig.tpl +templates/default/picture.tpl +templates/default/pictureinfo.tpl +templates/default/refresh.tpl +templates/default/scale.tpl +templates/default/scaleactive.tpl +templates/default/showpicture.tpl +templates/default/slideshowisoff.tpl +templates/default/slideshowoff.tpl +templates/default/gallery.css +templates/new/intervalactive.tpl +templates/new/dircomment.tpl +templates/new/directory.tpl +templates/new/error.tpl +templates/new/file.tpl +templates/new/index.tpl +templates/new/info.tpl +templates/new/interval.tpl +templates/new/navpicture.tpl +templates/new/layout.tpl +templates/new/gallery.css +templates/new/nodircomment.tpl +templates/new/nopictureinfo.tpl +templates/new/orig.tpl +templates/new/picture.tpl +templates/new/pictureinfo.tpl +templates/new/refresh.tpl +templates/new/scale.tpl +templates/new/scaleactive.tpl +templates/new/showpicture.tpl +templates/new/slideshowisoff.tpl +templates/new/slideshowoff.tpl +META.yml Module meta-data (added by MakeMaker) diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..53e532e --- /dev/null +++ b/META.yml @@ -0,0 +1,18 @@ +# http://module-build.sourceforge.net/META-spec.html +#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# +name: Apache-Gallery +version: 1.0RC3 +version_from: lib/Apache/Gallery.pm +installdirs: site +requires: + CGI: 3.08 + File::Spec: 0 + Image::Imlib2: 1.02 + Image::Info: 0 + Image::Size: 0 + Test::More: 0 + Text::Template: 0 + URI: 1.23 + +distribution_type: module +generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..213b3bc --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,21 @@ +use ExtUtils::MakeMaker; +# $Id: Makefile.PL,v 1.7 2002/02/09 06:32:03 thomas Exp $ +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'NAME' => 'Apache::Gallery', + 'VERSION_FROM' => 'lib/Apache/Gallery.pm', # finds $VERSION + 'PREREQ_PM' => { + Image::Info => 0, + Image::Size => 0, + Image::Imlib2 => 1.02, + Text::Template => 0, + URI => 1.23, + CGI => 3.08, + Test::More => 0, + File::Spec => 0 + }, # e.g., Module::Name => 1.1 + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => 'lib/Apache/Gallery.pm', # retrieve abstract from module + AUTHOR => 'Michael Legart ') : ()), +); diff --git a/README b/README new file mode 100644 index 0000000..5572fe3 --- /dev/null +++ b/README @@ -0,0 +1,316 @@ +NAME + Apache::Gallery - mod_perl handler to create an image gallery + +SYNOPSIS + See the INSTALL file in the distribution for installation instructions. + +DESCRIPTION + Apache::Gallery creates an thumbnail index of each directory and allows + viewing pictures in different resolutions. Pictures are resized on the + fly and cached. The gallery can be configured and customized in many + ways and a custom copyright image can be added to all the images without + modifying the original. + +CONFIGURATION + In your httpd.conf you set the global options for the gallery. You can + also override each of the options in .htaccess files in your gallery + directories. + + The options are set in the httpd.conf/.htaccess file using the syntax: + PerlSetVar OptionName 'value' + + Example: PerlSetVar GalleryCacheDir '/var/tmp/Apache-Gallery/' + + GalleryAutoRotate + Some cameras, like the Canon G3, can detect the orientation of a the + pictures you take and will save this information in the + 'Orientation' EXIF field. Apache::Gallery will then automatically + rotate your images. + + This behavior is default but can be disabled by setting + GalleryAutoRotate to 0. + + GalleryCacheDir + Directory where Apache::Gallery should create its cache with scaled + pictures. The default is /var/tmp/Apache-Gallery/ . Here, a + directory for each virtualhost or location will be created + automaticly. Make sure your webserver has write access to the + CacheDir. + + GalleryTemplateDir + Full path to the directory where you placed the templates. This + option can be used both in your global configuration and in + .htaccess files, this way you can have different layouts in + different parts of your gallery. + + No default value, this option is required. + + GalleryInfo + With this option you can define which EXIF information you would + like to present from the image. The format is: ' + KeyInEXIF, MyOtherName => OtherKeyInEXIF' + + Examples of keys: ShutterSpeedValue, ApertureValue, SubjectDistance, + and Camera + + You can view all the keys from the EXIF header using this + perl-oneliner: + + perl "-e" 'use Data::Dumper; use Image::Info qw(image_info); print + Dumper(image_info(shift));' filename.jpg + + Default is: 'Picture Taken => DateTimeOriginal, Flash => Flash' + + GallerySizes + Defines which widths images can be scaled to. Images cannot be + scaled to other widths than the ones you define with this option. + + The default is '640 800 1024 1600' + + GalleryThumbnailSize + Defines the width and height of the thumbnail images. + + Defaults to '100x75' + + GalleryThumbnailSizeLS + If set to '1', GalleryThumbnailSize is the long and the short side + of the thumbnail image instead of the width and height. + + Defaults to '0'. + + GalleryCopyrightImage + Image you want to blend into your images in the lower right corner. + This could be a transparent png saying "copyright my name 2001". + + Optional. + + GalleryWrapNavigation + Make the navigation in the picture view wrap around (So Next at the + end displays the first picture, etc.) + + Set to 1 or 0, default is 0 + + GalleryAllowOriginal + Allow the user to download the Original picture without resizing or + putting the CopyrightImage on it. + + Set to 1 or 0, default is 0 + + GallerySlideshowIntervals + With this option you can configure which intervals can be selected + for a slideshow. The default is '3 5 10 15 30' + + GallerySortBy + Instead of the default filename ordering you can sort by any stat + attribute. For example size, atime, mtime, ctime. + + GalleryDirSortBy + Set this variable to sort directories differently than other items, + can be set to size, atime, mtime and ctime; setting any other value + will revert to sorting by name. + + GalleryMemoize + Cache EXIF data using Memoize - this will make Apache::Gallery + faster when many people access the same images, but it will also + cache EXIF data until the current Apache child dies. + + GalleryUseFileDate + Set this option to 1 to make A::G show the files timestamp instead + of the EXIF value for "Picture taken". + + GallerySelectionMode + Enable the selection mode. Select images with checkboxes and get a + list of filenames. + + GalleryEXIFMode + You can choose how Apache::Gallery should display EXIF info from + your images. + + The default setting is 'namevalue'. This setting will make + Apache::Gallery print out the names and values of the EXIF values + you configure with GalleryInfo. The information will be parsed into + $INFO in pictureinfo.tpl. + + You can also set it to 'values' which will make A::G parse the + configured values into the var $EXIFVALUES as 'value | value | + value' + + If you set this option to 'variables' the items you configure in + GalleryInfo will be available to your templates as $EXIF_ + (in all uppercase). That means that with the default setting + "Picture Taken => DateTimeOriginal, Flash => Flash" you will have + the variables $EXIF_DATETIMEORIGINAL and $EXIF_FLASH avilable to + your templates. You can place them anywhere you want. + + GalleryRootPath + Change the location of gallery root. The default is "" + + GalleryRootText + Change the name that appears as the root element in the menu. The + default is "root:" + + GalleryMaxThumbnailsPerPage + This options controls how many thumbnails should be displayed in a + page. It requires $BROWSELINKS to be in the index.tpl template file. + + GalleryImgFile + Pattern matching the files you want Apache::Gallery to view in the + index as thumbnails. + + The default is '\.(jpe?g|png|tiff?|ppm)$' + + GalleryDocFile + Pattern matching the files you want Apache::Gallery to view in the + index as normal files. All other filetypes will still be served by + Apache::Gallery but are not visible in the index. + + The default is + '\.(mpe?g|avi|mov|asf|wmv|doc|mp3|ogg|pdf|rtf|wav|dlt|html?|csv|eps) + $' + + GalleryTTFDir + To use the GalleryCopyrightText feature you must set this option to + the directory where your True Type fonts are stored. No default is + set. + + Example: + + PerlSetVar GalleryTTFDir '/usr/share/fonts/' + + GalleryTTFFile + To use the GalleryCopyrightText feature this option must be set to + the name of the True Type font you wish to use. Example: + + PerlSetVar GalleryTTFFile 'verdanab.ttf' + + GalleryTTFSize + Configure the size of the CopyrightText that will be inserted as + copyright notice in the corner of your pictures. + + Example: + + PerlSetVar GalleryTTFSize '10' + + GalleryCopyrightText + The text that will be inserted as copyright notice. + + Example: + + PerlSetVar GalleryCopyrightText '(c) Michael Legart' + + GalleryCopyrightColor + The text color of your copyright notice. + + Examples: + + White: PerlSetVar GalleryCopyrightColor '255,255,255,255' + + Black: PerlSetVar GalleryCopyrightColor '0,0,0,255' + + Red: PerlSetVar GalleryCopyrightColor '255,0,0,255' + + Green: PerlSetVar GalleryCopyrightColor '0,255,0,255' + + Blue: PerlSetVar GalleryCopyrightColor '0,0,255,255' + + Transparent orange: PerlSetVar GalleryCopyrightColor '255,127,0,127' + + GalleryCopyrightBackgroundColor + The background-color of a GalleryCopyrightText + + r,g,b,a - for examples, see GalleryCopyrightColor + + GalleryQuality + The quality (1-100) of scaled images + + This setting affects the quality of the scaled images. Set this to a + low number to reduce the size of the scaled images. Remember to + clear out your cache if you change this setting. Quality seems to + default to 75, at least in the jpeg and png loader code in Imlib2 + 1.1.0. + + Examples: + + Quality at 50: PerlSetVar GalleryQuality '50' + + GalleryUnderscoresToSpaces + Set this option to 1 to convert underscores to spaces in the listing + of directory names. + +FEATURES + Rotate images + Some cameras, like the Canon G3, detects the orientation of a + picture and adds this info to the EXIF header. Apache::Gallery + detects this and automaticly rotates images with this info. + + If your camera does not support this, you can rotate the images + manually, This can also be used to override the rotate information + from a camera that supports that. You can also disable this behavior + with the GalleryAutoRotate option. + + To use this functionality you have to create file with the name of + the picture you want rotated appened with ".rotate". The file should + include a number where these numbers are supported: + + "1", rotates clockwise by 90 degree + "2", rotates clockwise by 180 degrees + "3", rotates clockwise by 270 degrees + + So if we want to rotate "Picture1234.jpg" 90 degrees clockwise we + would create a file in the same directory called + "Picture1234.jpg.rotate" with the number 1 inside of it. + + Comments + To include comments for a directory you create a .comment + file where the first line can contain "TITLE: New title" which will + be the title of the page, and a comment on the following lines. To + include comments for each picture you create files called + picture.jpg.comment where the first line can contain "TITLE: New + title" which will be the title of the page, and a comment on the + following lines. + + Example: + + TITLE: This is the new title of the page + And this is the comment.
+ And this is line two of the comment. + + The visible name of the folder is by default identical to the name + of the folder, but can be changed by creating a file + .folder with the visible name of the folder. + +DEPENDENCIES + Perl 5 + Apache with mod_perl + URI::Escape + Image::Info + Image::Size + Text::Template + Image::Imlib2 + X11 libraries (ie, XFree86) + Imlib2 Remember the -dev package when using rpm, deb or other package + formats! + +AUTHOR + Michael Legart + +COPYRIGHT AND LICENSE + Copyright (C) 2001-2005 Michael Legart + + Templates designed by Thomas Kjaer + + Apache::Gallery is free software and is released under the Artistic + License. See http://www.perl.com/language/misc/Artistic.html for + details. + + The video icons are from the GNOME project. http://www.gnome.org/ + +THANKS + Thanks to Thomas Kjaer for templates and design of + http://apachegallery.dk Thanks to Thomas Eibner and other for patches. + (See the Changes file) + +SEE ALSO + perl, mod_perl, Image::Imlib2, CGI::FastTemplate, Image::Info, and + Image::Size. + diff --git a/TODO b/TODO new file mode 100644 index 0000000..8b4f1e1 --- /dev/null +++ b/TODO @@ -0,0 +1,24 @@ +$Author: mil $ $Rev: 255 $ +$Date: 2004-04-12 20:49:02 +0300 (Mon, 12 Apr 2004) $ + +- Write a gallery-cleancache.pl script for removing entries in + the cache where the original picture has been removed. + +- /admin page to edit comments and .rotate file. (Cleanup in + .cache when changing rotation) + +- Write perlscript to make static html galleries. + +- Sort by the DateTimeOriginal part of the EXIF header + if possible + +- Make the template and imagesystem pluggable + +- Make scaling quality configurable + +- Thumbnails are to be generated in tmp files first, + then moved to the correct location. + +- Use imlib_create_cropped_scaled_image in resizepicture + +- Try to avoid running too many resize processes diff --git a/UPGRADE b/UPGRADE new file mode 100644 index 0000000..6c82631 --- /dev/null +++ b/UPGRADE @@ -0,0 +1,121 @@ +# $Author: mil $ $Rev: 297 $ +# $Date: 2005-06-07 10:50:49 +0300 (Tue, 07 Jun 2005) $ + +For users upgrading to 1.0 + +If you are using mod_perl2 version mod_perl-2.0 is now required. + +Also, CGI 3.08 is required if using mod_perl2. + +To enable access keys for navigation update the navpicture.tpl and +showpicture.tpl templates. + +For users upgrading from 0.7 to 0.8 + +You need to create new directory called gallery in Apaches +icons directory. Copy the png files from the htdocs dictory +to this new directory. + +For those of you with pre-existing templates, a simple + + cd templates; perl -pi -e 's/(? DateTimeOriginal, Flash => Flash' +PerlSetVar GallerySizes '640 1024 1600 2272' + +to your virtualhost. + diff --git a/htdocs/agfolder.png b/htdocs/agfolder.png new file mode 100644 index 0000000..fe1180f Binary files /dev/null and b/htdocs/agfolder.png differ diff --git a/htdocs/application-doc.png b/htdocs/application-doc.png new file mode 100644 index 0000000..e404f9a Binary files /dev/null and b/htdocs/application-doc.png differ diff --git a/htdocs/application-pdf.png b/htdocs/application-pdf.png new file mode 100644 index 0000000..4e4725c Binary files /dev/null and b/htdocs/application-pdf.png differ diff --git a/htdocs/application-rtf.png b/htdocs/application-rtf.png new file mode 100644 index 0000000..8c5013c Binary files /dev/null and b/htdocs/application-rtf.png differ diff --git a/htdocs/c.png b/htdocs/c.png new file mode 100644 index 0000000..ef2cbc2 Binary files /dev/null and b/htdocs/c.png differ diff --git a/htdocs/sound-mp3.png b/htdocs/sound-mp3.png new file mode 100644 index 0000000..afb7e1b Binary files /dev/null and b/htdocs/sound-mp3.png differ diff --git a/htdocs/sound-ogg.png b/htdocs/sound-ogg.png new file mode 100644 index 0000000..ead3f62 Binary files /dev/null and b/htdocs/sound-ogg.png differ diff --git a/htdocs/sound-wav.png b/htdocs/sound-wav.png new file mode 100644 index 0000000..c586fc0 Binary files /dev/null and b/htdocs/sound-wav.png differ diff --git a/htdocs/video-asf.png b/htdocs/video-asf.png new file mode 100644 index 0000000..b0cd301 Binary files /dev/null and b/htdocs/video-asf.png differ diff --git a/htdocs/video-avi.png b/htdocs/video-avi.png new file mode 100644 index 0000000..065f0b2 Binary files /dev/null and b/htdocs/video-avi.png differ diff --git a/htdocs/video-mov.png b/htdocs/video-mov.png new file mode 100644 index 0000000..569727f Binary files /dev/null and b/htdocs/video-mov.png differ diff --git a/htdocs/video-mpeg.png b/htdocs/video-mpeg.png new file mode 100644 index 0000000..b304989 Binary files /dev/null and b/htdocs/video-mpeg.png differ diff --git a/htdocs/video-mpg.png b/htdocs/video-mpg.png new file mode 100644 index 0000000..f7dbd23 Binary files /dev/null and b/htdocs/video-mpg.png differ diff --git a/htdocs/video-wmv.png b/htdocs/video-wmv.png new file mode 100644 index 0000000..0dfce33 Binary files /dev/null and b/htdocs/video-wmv.png differ diff --git a/lib/Apache/Gallery.pm b/lib/Apache/Gallery.pm new file mode 100644 index 0000000..d543fca --- /dev/null +++ b/lib/Apache/Gallery.pm @@ -0,0 +1,1878 @@ +package Apache::Gallery; + +# $Author: mil $ $Rev: 316 $ +# $Date: 2006-08-04 16:28:06 +0300 (Fri, 04 Aug 2006) $ + +use strict; + +use vars qw($VERSION); + +$VERSION = "1.0RC3"; + +BEGIN { + + if (exists($ENV{MOD_PERL_API_VERSION}) + and ($ENV{MOD_PERL_API_VERSION}==2)) { + require mod_perl2; + if ($mod_perl::VERSION >= 1.99 && $mod_perl::VERSION < 2.0) { + die "mod_perl 2.0.0 or later is now required"; + } + require Apache2::ServerRec; + require Apache2::RequestRec; + require Apache2::Log; + require APR::Table; + require Apache2::RequestIO; + require Apache2::SubRequest; + require Apache2::Const; + + Apache2::Const->import(-compile => 'OK','DECLINED','FORBIDDEN','NOT_FOUND'); + + $::MP2 = 1; + } else { + require mod_perl; + + require Apache; + require Apache::Constants; + require Apache::Request; + + Apache::Constants->import('OK','DECLINED','FORBIDDEN','NOT_FOUND'); + $::MP2 = 0; + } +} + +use Image::Info qw(image_info); +use Image::Size qw(imgsize); +use Image::Imlib2; +use Text::Template; +use File::stat; +use File::Spec; +use POSIX qw(floor); +use URI::Escape; +use CGI; +use CGI::Cookie; + +use Data::Dumper; + +# Regexp for escaping URI's +my $escape_rule = "^A-Za-z0-9\-_.!~*'()\/"; +my $memoized; + +sub handler { + + my $r = shift or Apache2::RequestUtil->request(); + + if ((not $memoized) and ($r->dir_config('GalleryMemoize'))) { + require Memoize; + Memoize::memoize('get_imageinfo'); + $memoized=1; + } + + $r->headers_out->{"X-Powered-By"} = "apachegallery.dk $VERSION - Hest design!"; + $r->headers_out->{"X-Gallery-Version"} = '$Rev: 316 $ $Date: 2006-08-04 16:28:06 +0300 (Fri, 04 Aug 2006) $'; + + my $filename = $r->filename; + $filename =~ s/\/$//; + my $topdir = $filename; + + # Just return the http headers if the client requested that + if ($r->header_only) { + + if (!$::MP2) { + $r->send_http_header; + } + + if (-f $filename or -d $filename) { + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + else { + return $::MP2 ? Apache2::Const::NOT_FOUND() : Apache::Constants::NOT_FOUND(); + } + } + + my $cgi = new CGI; + + # Handle selected images + if ($cgi->param('selection')) { + my @selected = $cgi->param('selection'); + my $content = join "
\n",@selected; + $r->content_type('text/html'); + $r->headers_out->{'Content-Length'} = length($content); + + if (!$::MP2) { + $r->send_http_header; + } + + $r->print($content); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + + # Selectmode providing checkboxes beside all thumbnails + my $select_mode = $cgi->param('select'); + + # Let Apache serve icons without us modifying the request + if ($r->uri =~ m/^\/icons/i) { + return $::MP2 ? Apache2::Const::DECLINED() : Apache::Constants::DECLINED(); + } + # Lookup the file in the cache and scale the image if the cached + # image does not exist + if ($r->uri =~ m/\.cache\//i) { + + my $filename = $r->filename().$r->path_info(); + $filename =~ s/\.cache//; + + $filename =~ m/\/(\d+)x(\d+)\-/; + my $image_width = $1; + my $image_height = $2; + + $filename =~ s/\/(\d+)x(\d+)\-//; + + my ($width, $height, $type) = imgsize($filename); + + my $imageinfo = get_imageinfo($r, $filename, $type, $width, $height); + + my $cached = scale_picture($r, $filename, $image_width, $image_height, $imageinfo); + + my $file = cache_dir($r, 0); + $file =~ s/\.cache//; + + my $subr = $r->lookup_file($file); + $r->content_type($subr->content_type()); + + if ($::MP2) { + $r->sendfile($file); + return Apache2::Const::OK(); + } + else { + $r->path_info(''); + $r->filename($file); + return Apache::Constants::DECLINED(); + } + + } + + my $uri = $r->uri; + $uri =~ s/\/$//; + + unless (-f $filename or -d $filename) { + show_error($r, 404, "404!", "No such file or directory: ".uri_escape($r->uri, $escape_rule)); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + + my $doc_pattern = $r->dir_config('GalleryDocFile'); + unless ($doc_pattern) { + $doc_pattern = '\.(mpe?g|avi|mov|asf|wmv|doc|mp3|ogg|pdf|rtf|wav|dlt|html?|csv|eps)$' + } + my $img_pattern = $r->dir_config('GalleryImgFile'); + unless ($img_pattern) { + $img_pattern = '\.(jpe?g|png|tiff?|ppm)$' + } + + # Let Apache serve files we don't know how to handle anyway + if (-f $filename && $filename !~ m/$img_pattern/i) { + return $::MP2 ? Apache2::Const::DECLINED() : Apache::Constants::DECLINED(); + } + + if (-d $filename) { + + unless (-d cache_dir($r, 0)) { + unless (create_cache($r, cache_dir($r, 0))) { + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + } + + my $tpl_dir = $r->dir_config('GalleryTemplateDir'); + + # Instead of reading the templates every single time + # we need them, create a hash of template names and + # the associated Text::Template objects. + my %templates = create_templates({layout => "$tpl_dir/layout.tpl", + index => "$tpl_dir/index.tpl", + directory => "$tpl_dir/directory.tpl", + picture => "$tpl_dir/picture.tpl", + file => "$tpl_dir/file.tpl", + comment => "$tpl_dir/dircomment.tpl", + nocomment => "$tpl_dir/nodircomment.tpl", + }); + + + + + my %tpl_vars; + + $tpl_vars{TITLE} = "Index of: $uri"; + $tpl_vars{META} = " "; + + unless (opendir (DIR, $filename)) { + show_error ($r, 500, $!, "Unable to access directory $filename: $!"); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + + $tpl_vars{MENU} = generate_menu($r); + + $tpl_vars{FORM_BEGIN} = $select_mode?'
':''; + $tpl_vars{FORM_END} = $select_mode?'
':''; + + # Read, sort, and filter files + my @files = grep { !/^\./ && -f "$filename/$_" } readdir (DIR); + + @files=gallerysort($r, @files); + + my @downloadable_files; + + if (@files) { + # Remove unwanted files from list + my @new_files = (); + foreach my $picture (@files) { + + my $file = $topdir."/".$picture; + + if ($file =~ /$img_pattern/i) { + push (@new_files, $picture); + } + + if ($file =~ /$doc_pattern/i) { + push (@downloadable_files, $picture); + } + + } + @files = @new_files; + } + + # Read and sort directories + rewinddir (DIR); + my @directories = grep { !/^\./ && -d "$filename/$_" } readdir (DIR); + my $dirsortby; + if (defined($r->dir_config('GalleryDirSortBy'))) { + $dirsortby=$r->dir_config('GalleryDirSortBy'); + } else { + $dirsortby=$r->dir_config('GallerySortBy'); + } + if ($dirsortby && $dirsortby =~ m/^(size|atime|mtime|ctime)$/) { + @directories = map(/^\d+ (.*)/, sort map(stat("$filename/$_")->$dirsortby()." $_", @directories)); + } else { + @directories = sort @directories; + } + + closedir(DIR); + + + # Combine directories and files to one listing + my @listing; + push (@listing, @directories); + push (@listing, @files); + push (@listing, @downloadable_files); + + if (@listing) { + + my $filelist; + + my $file_counter = 0; + my $start_at = 1; + my $max_files = $r->dir_config('GalleryMaxThumbnailsPerPage'); + + if (defined($cgi->param('start'))) { + $start_at = $cgi->param('start'); + if ($start_at < 1) { + $start_at = 1; + } + } + + my $browse_links = ""; + if (defined($max_files)) { + + for (my $i=1; $i<=scalar(@listing); $i++) { + + my $from = $i; + + my $to = $i+$max_files-1; + if ($to > scalar(@listing)) { + $to = scalar(@listing); + } + + if ($start_at < $from || $start_at > $to) { + $browse_links .= "$from - ".$to." "; + } + else { + $browse_links .= "$from - $to "; + } + + $i+=$max_files-1; + + } + + } + + $tpl_vars{BROWSELINKS} = $browse_links; + + DIRLOOP: + foreach my $file (@listing) { + + $file_counter++; + + if ($file_counter < $start_at) { + next; + } + + if (defined($max_files) && $file_counter > $max_files+$start_at-1) { + last DIRLOOP; + } + + my $thumbfilename = $topdir."/".$file; + + my $fileurl = $uri."/".$file; + + if (-d $thumbfilename) { + my $dirtitle = ''; + if (-e $thumbfilename . ".folder") { + $dirtitle = get_filecontent($thumbfilename . ".folder"); + } + + $dirtitle = $dirtitle ? $dirtitle : $file; + $dirtitle =~ s/_/ /g if $r->dir_config('GalleryUnderscoresToSpaces'); + + $tpl_vars{FILES} .= + $templates{directory}->fill_in(HASH=> {FILEURL => uri_escape($fileurl, $escape_rule), + FILE => $dirtitle, + } + ); + } + elsif (-f $thumbfilename && $thumbfilename =~ /$doc_pattern/i && $thumbfilename !~ /$img_pattern/i) { + my $type = lc($1); + my $stat = stat($thumbfilename); + my $size = $stat->size; + my $filetype; + + if ($thumbfilename =~ m/\.(mpe?g|avi|mov|asf|wmv)$/i) { + $filetype = "video-$type"; + } elsif ($thumbfilename =~ m/\.(txt|html?)$/i) { + $filetype = "text-$type"; + } elsif ($thumbfilename =~ m/\.(mp3|ogg|wav)$/i) { + $filetype = "sound-$type"; + } elsif ($thumbfilename =~ m/\.(doc|pdf|rtf|csv|eps)$/i) { + $filetype = "application-$type"; + } else { + $filetype = "unknown"; + } + + $tpl_vars{FILES} .= + $templates{file}->fill_in(HASH => {%tpl_vars, + FILEURL => uri_escape($fileurl, $escape_rule), + ALT => "Size: $size Bytes", + FILE => $file, + TYPE => $type, + FILETYPE => $filetype, + } + ); + } + elsif (-f $thumbfilename) { + + my ($width, $height, $type) = imgsize($thumbfilename); + next if $type eq 'Data stream is not a known image file format'; + + my @filetypes = qw(JPG TIF PNG PPM GIF); + + next unless (grep $type eq $_, @filetypes); + my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $width, $height); + my $imageinfo = get_imageinfo($r, $thumbfilename, $type, $width, $height); + my $cached = get_scaled_picture_name($thumbfilename, $thumbnailwidth, $thumbnailheight); + + my $rotate = readfile_getnum($r, $imageinfo, $thumbfilename.".rotate"); + my %file_vars = (FILEURL => uri_escape($fileurl, $escape_rule), + FILE => $file, + DATE => $imageinfo->{DateTimeOriginal} ? $imageinfo->{DateTimeOriginal} : '', # should this really be a stat of the file instead of ''? + SRC => uri_escape($uri."/.cache/$cached", $escape_rule), + HEIGHT => (grep($rotate==$_, (1, 3)) ? $thumbnailwidth : $thumbnailheight), + WIDTH => (grep($rotate==$_, (1, 3)) ? $thumbnailheight : $thumbnailwidth), + SELECT => $select_mode?'  ':'',); + $tpl_vars{FILES} .= $templates{picture}->fill_in(HASH => {%tpl_vars, + %file_vars, + }, + ); + } + } + } + else { + $tpl_vars{FILES} = "No files found"; + $tpl_vars{BROWSELINKS} = ""; + } + + if (-f $topdir . '.comment') { + my $comment_ref = get_comment($topdir . '.comment'); + my %comment_vars; + $comment_vars{COMMENT} = $comment_ref->{COMMENT} . '
' if $comment_ref->{COMMENT}; + $comment_vars{TITLE} = $comment_ref->{TITLE} if $comment_ref->{TITLE}; + $tpl_vars{DIRCOMMENT} = $templates{comment}->fill_in(HASH => \%comment_vars); + $tpl_vars{TITLE} = $comment_ref->{TITLE} if $comment_ref->{TITLE}; + } else { + $tpl_vars{DIRCOMMENT} = $templates{nocomment}->fill_in(HASH=>\%tpl_vars); + } + + $tpl_vars{MAIN} = $templates{index}->fill_in(HASH => \%tpl_vars); + + $tpl_vars{MAIN} = $templates{layout}->fill_in(HASH => \%tpl_vars); + + $r->content_type('text/html'); + $r->headers_out->{'Content-Length'} = length($tpl_vars{MAIN}); + + if (!$::MP2) { + $r->send_http_header; + } + + $r->print($tpl_vars{MAIN}); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + + } + else { + + # original size + if (defined($ENV{QUERY_STRING}) && $ENV{QUERY_STRING} eq 'orig') { + if ($r->dir_config('GalleryAllowOriginal') ? 1 : 0) { + $r->filename($filename); + return $::MP2 ? Apache2::Const::DECLINED() : Apache::Constants::DECLINED(); + } else { + return $::MP2 ? Apache2::Const::FORBIDDEN() : Apache::Constants::FORBIDDEN(); + } + } + + # Create cache dir if not existing + my @tmp = split (/\//, $filename); + my $picfilename = pop @tmp; + my $path = (join "/", @tmp)."/"; + my $cache_path = cache_dir($r, 1); + + unless (-d $cache_path) { + unless (create_cache($r, $cache_path)) { + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + } + + my ($orig_width, $orig_height, $type) = imgsize($filename); + my $width = $orig_width; + + my $imageinfo = get_imageinfo($r, $filename, $type, $orig_width, $orig_height); + + my $original_size=$orig_height; + if ($orig_width>$orig_height) { + $original_size=$orig_width; + } + + # Check if the selected width is allowed + my @sizes = split (/ /, $r->dir_config('GallerySizes') ? $r->dir_config('GallerySizes') : '640 800 1024 1600'); + + my %cookies = fetch CGI::Cookie; + + if ($cgi->param('width')) { + unless ((grep $cgi->param('width') == $_, @sizes) or ($cgi->param('width') == $original_size)) { + show_error($r, 200, "Invalid width", "The specified width is invalid"); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + + $width = $cgi->param('width'); + my $cookie = new CGI::Cookie(-name => 'GallerySize', -value => $width, -expires => '+6M'); + $r->headers_out->{'Set-Cookie'} = $cookie; + + } elsif ($cookies{'GallerySize'} && (grep $cookies{'GallerySize'}->value == $_, @sizes)) { + + $width = $cookies{'GallerySize'}->value; + + } else { + $width = $sizes[0]; + } + + my $scale; + my $image_width; + if ($orig_width<$orig_height) { + $scale = ($orig_height ? $width/$orig_height: 1); + $image_width=$width*$orig_width/$orig_height; + } + else { + $scale = ($orig_width ? $width/$orig_width : 1); + $image_width = $width; + } + + my $height = $orig_height * $scale; + + $image_width = floor($image_width); + $width = floor($width); + $height = floor($height); + + my $cached = get_scaled_picture_name($filename, $image_width, $height); + + my $tpl_dir = $r->dir_config('GalleryTemplateDir'); + + my %templates = create_templates({layout => "$tpl_dir/layout.tpl", + picture => "$tpl_dir/showpicture.tpl", + navpicture => "$tpl_dir/navpicture.tpl", + info => "$tpl_dir/info.tpl", + scale => "$tpl_dir/scale.tpl", + scaleactive => "$tpl_dir/scaleactive.tpl", + orig => "$tpl_dir/orig.tpl", + refresh => "$tpl_dir/refresh.tpl", + interval => "$tpl_dir/interval.tpl", + intervalactive => "$tpl_dir/intervalactive.tpl", + slideshowisoff => "$tpl_dir/slideshowisoff.tpl", + slideshowoff => "$tpl_dir/slideshowoff.tpl", + pictureinfo => "$tpl_dir/pictureinfo.tpl", + nopictureinfo => "$tpl_dir/nopictureinfo.tpl", + }); + + my %tpl_vars; + + my $resolution = (($image_width > $orig_width) && ($height > $orig_height)) ? + "$orig_width x $orig_height" : "$image_width x $height"; + + $tpl_vars{TITLE} = "Viewing ".$r->uri()." at $image_width x $height"; + $tpl_vars{META} = " "; + $tpl_vars{RESOLUTION} = $resolution; + $tpl_vars{MENU} = generate_menu($r); + $tpl_vars{SRC} = uri_escape(".cache/$cached", $escape_rule); + $tpl_vars{URI} = $r->uri(); + + my $exif_mode = $r->dir_config('GalleryEXIFMode'); + unless ($exif_mode) { + $exif_mode = 'namevalue'; + } + + unless (opendir(DATADIR, $path)) { + show_error($r, 500, "Unable to access directory", "Unable to access directory $path"); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + my @pictures = grep { /$img_pattern/i } readdir (DATADIR); + closedir(DATADIR); + @pictures = gallerysort($r, @pictures); + + $tpl_vars{TOTAL} = scalar @pictures; + + my $prevpicture; + my $nextpicture; + + for (my $i=0; $i <= $#pictures; $i++) { + if ($pictures[$i] eq $picfilename) { + + $tpl_vars{NUMBER} = $i+1; + + $prevpicture = $pictures[$i-1]; + my $displayprev = ($i>0 ? 1 : 0); + + if ($r->dir_config("GalleryWrapNavigation")) { + $prevpicture = $pictures[$i>0 ? $i-1 : $#pictures]; + $displayprev = 1; + } + if ($prevpicture and $displayprev) { + my ($orig_width, $orig_height, $type) = imgsize($path.$prevpicture); + my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $orig_width, $orig_height); + my $imageinfo = get_imageinfo($r, $path.$prevpicture, $type, $orig_width, $orig_height); + my $cached = get_scaled_picture_name($path.$prevpicture, $thumbnailwidth, $thumbnailheight); + my %nav_vars; + $nav_vars{URL} = uri_escape($prevpicture, $escape_rule); + $nav_vars{FILENAME} = $prevpicture; + $nav_vars{WIDTH} = $width; + $nav_vars{PICTURE} = uri_escape(".cache/$cached", $escape_rule); + $nav_vars{DIRECTION} = "« prev"; + $nav_vars{ACCESSKEY} = "P"; + $tpl_vars{BACK} = $templates{navpicture}->fill_in(HASH => \%nav_vars); + } + else { + $tpl_vars{BACK} = " "; + } + + $nextpicture = $pictures[$i+1]; + if ($r->dir_config("GalleryWrapNavigation")) { + $nextpicture = $pictures[$i == $#pictures ? 0 : $i+1]; + } + + if ($nextpicture) { + my ($orig_width, $orig_height, $type) = imgsize($path.$nextpicture); + my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $orig_width, $orig_height); + my $imageinfo = get_imageinfo($r, $path.$nextpicture, $type, $thumbnailwidth, $thumbnailheight); + my $cached = get_scaled_picture_name($path.$nextpicture, $thumbnailwidth, $thumbnailheight); + my %nav_vars; + $nav_vars{URL} = uri_escape($nextpicture, $escape_rule); + $nav_vars{FILENAME} = $nextpicture; + $nav_vars{WIDTH} = $width; + $nav_vars{PICTURE} = uri_escape(".cache/$cached", $escape_rule); + $nav_vars{DIRECTION} = "next »"; + $nav_vars{ACCESSKEY} = "N"; + + $tpl_vars{NEXT} = $templates{navpicture}->fill_in(HASH => \%nav_vars); + $tpl_vars{NEXTURL} = uri_escape($nextpicture, $escape_rule); + } + else { + $tpl_vars{NEXT} = " "; + $tpl_vars{NEXTURL} = '#'; + } + } + } + + my $foundcomment = 0; + if (-f $path . '/' . $picfilename . '.comment') { + my $comment_ref = get_comment($path . '/' . $picfilename . '.comment'); + $foundcomment = 1; + $tpl_vars{COMMENT} = $comment_ref->{COMMENT} . '
' if $comment_ref->{COMMENT}; + $tpl_vars{TITLE} = $comment_ref->{TITLE} if $comment_ref->{TITLE}; + } else { + $tpl_vars{COMMENT} = ''; + } + + my @infos = split /, /, $r->dir_config('GalleryInfo') ? $r->dir_config('GalleryInfo') : 'Picture Taken => DateTimeOriginal, Flash => Flash'; + my $foundinfo = 0; + my $exifvalues; + foreach (@infos) { + + my ($human_key, $exif_key) = (split " => ")[0,1]; + my $value = $imageinfo->{$human_key}; + if (defined($value)) { + + $foundinfo = 1; + + if ($exif_mode eq 'namevalue') { + my %info_vars; + $info_vars{KEY} = $human_key; + $info_vars{VALUE} = $value; + $tpl_vars{INFO} .= $templates{info}->fill_in(HASH => \%info_vars); + } + + if ($exif_mode eq 'variables') { + $tpl_vars{"EXIF_".uc($exif_key)} = $value; + } + + if ($exif_mode eq 'values') { + $exifvalues .= "| ".$value." "; + } + + } + + } + + if ($exif_mode eq 'values') { + if (defined($exifvalues)) { + $tpl_vars{EXIFVALUES} = $exifvalues; + } + else { + $tpl_vars{EXIFVALUES} = ""; + } + } + + if ($foundcomment and !$foundinfo) { + $tpl_vars{INFO} = ""; + } + + if ($exif_mode ne 'namevalue') { + $tpl_vars{INFO} = ""; + } + + if ($exif_mode eq 'namevalue' && $foundinfo or $foundcomment) { + + $tpl_vars{PICTUREINFO} = $templates{pictureinfo}->fill_in(HASH => \%tpl_vars); + + unless (defined($exifvalues)) { + $tpl_vars{EXIFVALUES} = ""; + } + + } + else { + $tpl_vars{PICTUREINFO} = $templates{nopictureinfo}->fill_in(HASH => \%tpl_vars); + } + + # Fill in sizes and determine if any are smaller than the + # actual image. If they are, $scaleable=1 + my $scaleable = 0; + foreach my $size (@sizes) { + if ($size<=$original_size) { + my %sizes_vars; + $sizes_vars{IMAGEURI} = uri_escape($r->uri(), $escape_rule); + $sizes_vars{SIZE} = $size; + $sizes_vars{WIDTH} = $size; + if ($width == $size) { + $tpl_vars{SIZES} .= $templates{scaleactive}->fill_in(HASH => \%sizes_vars); + } + else { + $tpl_vars{SIZES} .= $templates{scale}->fill_in(HASH => \%sizes_vars); + } + $scaleable = 1; + } + } + + unless ($scaleable) { + my %sizes_vars; + $sizes_vars{IMAGEURI} = uri_escape($r->uri(), $escape_rule); + $sizes_vars{SIZE} = $original_size; + $sizes_vars{WIDTH} = $original_size; + $tpl_vars{SIZES} .= $templates{scaleactive}->fill_in(HASH => \%sizes_vars); + } + + $tpl_vars{IMAGEURI} = uri_escape($r->uri(), $escape_rule); + + if ($r->dir_config('GalleryAllowOriginal')) { + $tpl_vars{SIZES} .= $templates{orig}->fill_in(HASH => \%tpl_vars); + } + + my @slideshow_intervals = split (/ /, $r->dir_config('GallerySlideshowIntervals') ? $r->dir_config('GallerySlideshowIntervals') : '3 5 10 15 30'); + foreach my $interval (@slideshow_intervals) { + + my %slideshow_vars; + $slideshow_vars{IMAGEURI} = uri_escape($r->uri(), $escape_rule); + $slideshow_vars{SECONDS} = $interval; + $slideshow_vars{WIDTH} = ($width > $height ? $width : $height); + + if ($cgi->param('slideshow') && $cgi->param('slideshow') == $interval and $nextpicture) { + $tpl_vars{SLIDESHOW} .= $templates{intervalactive}->fill_in(HASH => \%slideshow_vars); + } + else { + + $tpl_vars{SLIDESHOW} .= $templates{interval}->fill_in(HASH => \%slideshow_vars); + + } + } + + if ($cgi->param('slideshow') and $nextpicture) { + + $tpl_vars{SLIDESHOW} .= $templates{slideshowoff}->fill_in(HASH => \%tpl_vars); + + unless ((grep $cgi->param('slideshow') == $_, @slideshow_intervals)) { + show_error($r, 200, "Invalid interval", "Invalid slideshow interval choosen"); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + } + + $tpl_vars{URL} = uri_escape($nextpicture, $escape_rule); + $tpl_vars{WIDTH} = ($width > $height ? $width : $height); + $tpl_vars{INTERVAL} = $cgi->param('slideshow'); + $tpl_vars{META} .= $templates{refresh}->fill_in(HASH => \%tpl_vars); + + } + else { + $tpl_vars{SLIDESHOW} .= $templates{slideshowisoff}->fill_in(HASH => \%tpl_vars); + } + + $tpl_vars{MAIN} = $templates{picture}->fill_in(HASH => \%tpl_vars); + $tpl_vars{MAIN} = $templates{layout}->fill_in(HASH => \%tpl_vars); + + $r->content_type('text/html'); + $r->headers_out->{'Content-Length'} = length($tpl_vars{MAIN}); + + if (!$::MP2) { + $r->send_http_header; + } + + $r->print($tpl_vars{MAIN}); + return $::MP2 ? Apache2::Const::OK() : Apache::Constants::OK(); + + } + +} + +sub cache_dir { + + my ($r, $strip_filename) = @_; + + my $cache_root; + + unless ($r->dir_config('GalleryCacheDir')) { + + $cache_root = '/var/tmp/Apache-Gallery/'; + if ($r->server->is_virtual) { + $cache_root = File::Spec->catdir($cache_root, $r->server->server_hostname); + } else { + $cache_root = File::Spec->catdir($cache_root, $r->location); + } + + } else { + + $cache_root = $r->dir_config('GalleryCacheDir'); + + } + + # If the uri contains .cache we need to remove it + my $uri = $r->uri; + $uri =~ s/\.cache//; + + my (undef, $dirs, $filename) = File::Spec->splitpath($uri); + # We don't need a volume as this is a relative path + + if ($strip_filename) { + return(File::Spec->canonpath(File::Spec->catdir($cache_root, $dirs))); + } else { + return(File::Spec->canonpath(File::Spec->catfile($cache_root, $dirs, $filename))); + } +} + +sub create_cache { + + my ($r, $path) = @_; + + unless (mkdirhier ($path)) { + show_error($r, 500, $!, "Unable to create cache directory in $path: $!"); + return 0; + } + + return 1; +} + +sub mkdirhier { + + my $dir = shift; + + unless (-d $dir) { + + unless (mkdir($dir, 0755)) { + my $parent = $dir; + $parent =~ s/\/[^\/]*$//; + + mkdirhier($parent); + + mkdir($dir, 0755); + } + } +} + +sub get_scaled_picture_name { + + my ($fullpath, $width, $height) = @_; + + my (undef, undef, $type) = imgsize($fullpath); + + my @dirs = split(/\//, $fullpath); + my $filename = pop(@dirs); + my $newfilename; + + if (grep $type eq $_, qw(PPM TIF GIF)) { + $newfilename = $width."x".$height."-".$filename; + # needs to be configurable + $newfilename =~ s/\.(\w+)$/-$1\.jpg/; + } else { + $newfilename = $width."x".$height."-".$filename; + } + + return $newfilename; + +} + +sub scale_picture { + + my ($r, $fullpath, $width, $height, $imageinfo) = @_; + + my @dirs = split(/\//, $fullpath); + my $filename = pop(@dirs); + + my ($orig_width, $orig_height, $type) = imgsize($fullpath); + + my $cache = cache_dir($r, 1); + + my $newfilename = get_scaled_picture_name($fullpath, $width, $height); + + if (($width > $orig_width) && ($height > $orig_height)) { + # Run it through the resize code anyway to get watermarks + $width = $orig_width; + $height = $orig_height; + } + + my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $orig_width, $orig_height); + + # Do we want to generate a new file in the cache? + my $scale = 1; + + if (-f $cache."/".$newfilename) { + $scale = 0; + + # Check to see if the image has changed + my $filestat = stat($fullpath); + my $cachestat = stat($cache."/".$newfilename); + if ($filestat->mtime >= $cachestat->mtime) { + $scale = 1; + } + + # Check to see if the .rotate file has been added or changed + if (-f $fullpath . ".rotate") { + my $rotatestat = stat($fullpath . ".rotate"); + if ($rotatestat->mtime > $cachestat->mtime) { + $scale = 1; + } + } + # Check to see if the copyrightimage has been added or changed + if ($r->dir_config('GalleryCopyrightImage') && -f $r->dir_config('GalleryCopyrightImage')) { + unless ($width == $thumbnailwidth or $width == $thumbnailheight) { + my $copyrightstat = stat($r->dir_config('GalleryCopyrightImage')); + if ($copyrightstat->mtime > $cachestat->mtime) { + $scale = 1; + } + } + } + + } + + if ($scale) { + + my $newpath = $cache."/".$newfilename; + my $rotate = readfile_getnum($r, $imageinfo, $fullpath . ".rotate"); + my $quality = $r->dir_config('GalleryQuality'); + + if ($width == $thumbnailwidth or $width == $thumbnailheight) { + + resizepicture($r, $fullpath, $newpath, $width, $height, $rotate, '', '', '', '', '', ''); + + } else { + + resizepicture($r, $fullpath, $newpath, $width, $height, $rotate, + ($r->dir_config('GalleryCopyrightImage') ? $r->dir_config('GalleryCopyrightImage') : ''), + ($r->dir_config('GalleryTTFDir') ? $r->dir_config('GalleryTTFDir') : ''), + ($r->dir_config('GalleryCopyrightText') ? $r->dir_config('GalleryCopyrightText') : ''), + ($r->dir_config('GalleryCopyrightColor') ? $r->dir_config('GalleryCopyrightColor') : ''), + ($r->dir_config('GalleryTTFFile') ? $r->dir_config('GalleryTTFFile') : ''), + ($r->dir_config('GalleryTTFSize') ? $r->dir_config('GalleryTTFSize') : ''), + ($r->dir_config('GalleryCopyrightBackgroundColor') ? $r->dir_config('GalleryCopyrightBackgroundColor') : ''), + $quality); + + } + } + + return $newfilename; + +} + +sub get_thumbnailsize { + my ($r, $orig_width, $orig_height) = @_; + + my $gallerythumbnailsize=$r->dir_config('GalleryThumbnailSize'); + + if (defined($gallerythumbnailsize)) { + warn("Invalid setting for GalleryThumbnailSize") unless + $gallerythumbnailsize =~ /^\s*\d+\s*x\s*\d+\s*$/i; + } + + my ($thumbnailwidth, $thumbnailheight) = split(/x/i, ($gallerythumbnailsize) ? $gallerythumbnailsize : "100x75"); + + my $width = $thumbnailwidth; + my $height = $thumbnailheight; + + # If the image is rotated, flip everything around. + if (defined $r->dir_config('GalleryThumbnailSizeLS') + and $r->dir_config('GalleryThumbnailSizeLS') eq '1' + and $orig_width < $orig_height) { + + $width = $thumbnailheight; + $height = $thumbnailwidth; + } + + my $scale = ($orig_width ? $width/$orig_width : 1); + + if ($orig_height) { + if ($orig_height * $scale > $thumbnailheight) { + $scale = $height/$orig_height; + $width = $orig_width * $scale; + } + } + + $height = $orig_height * $scale; + + $height = floor($height); + $width = floor($width); + + return ($width, $height); +} + +sub get_imageinfo { + my ($r, $file, $type, $width, $height) = @_; + my $imageinfo = {}; + if ($type eq 'Data stream is not a known image file format') { + # should never be reached, this is supposed to be handled outside of here + log_error("Something was fishy with the type of the file $file\n"); + } else { + + # Some files, like TIFF, PNG, GIF do not have EXIF info + # embedded but use .thm files instead. + $imageinfo = get_imageinfo_from_thm_file($file, $width, $height); + + # If there is no .thm file and our file is a JPEG file we try to extract the EXIf + # info using Image::Info + unless (defined($imageinfo) && (grep $type eq $_, qw(JPG))) { + # Only for files that natively keep the EXIF info in the same file + $imageinfo = image_info($file); + } + } + + unless (defined($imageinfo->{width}) and defined($imageinfo->{height})) { + $imageinfo->{width} = $width; + $imageinfo->{height} = $height; + } + + my @infos = split /, /, $r->dir_config('GalleryInfo') ? $r->dir_config('GalleryInfo') : 'Picture Taken => DateTimeOriginal, Flash => Flash'; + foreach (@infos) { + + my ($human_key, $exif_key) = (split " => ")[0,1]; + if (defined($exif_key) && defined($imageinfo->{$exif_key})) { + my $value = ""; + if (ref($imageinfo->{$exif_key}) eq 'Image::TIFF::Rational') { + $value = $imageinfo->{$exif_key}->as_string; + } + elsif (ref($imageinfo->{$exif_key}) eq 'ARRAY') { + foreach my $element (@{$imageinfo->{$exif_key}}) { + if (ref($element) eq 'ARRAY') { + foreach (@{$element}) { + $value .= $_ . ' '; + } + } + elsif (ref($element) eq 'HASH') { + $value .= "
{ "; + foreach (sort keys %{$element}) { + $value .= "$_ = " . $element->{$_} . ' '; + } + $value .= "} "; + } + else { + $value .= $element; + } + $value .= ' '; + } + } + else { + my $exif_value = $imageinfo->{$exif_key}; + if ($human_key eq 'Flash' && $exif_value =~ m/\d/) { + my %flashmodes = ( + "0" => "No", + "1" => "Yes", + "9" => "Yes", + "16" => "No (Compulsory) Should be External Flash", + "17" => "Yes (External)", + "24" => "No", + "25" => "Yes (Auto)", + "73" => "Yes (Compulsory, Red Eye Reducing)", + "89" => "Yes (Auto, Red Eye Reducing)" + ); + $exif_value = defined $flashmodes{$exif_value} ? $flashmodes{$exif_value} : 'unknown flash mode'; + } + $value = $exif_value; + } + if ($exif_key eq 'MeteringMode') { + my $exif_value = $imageinfo->{$exif_key}; + if ($exif_value =~ /^\d+$/) { + my %meteringmodes = ( + '0' => 'unknown', + '1' => 'Average', + '2' => 'CenterWeightedAverage', + '3' => 'Spot', + '4' => 'MultiSpot', + '5' => 'Pattern', + '6' => 'Partial', + '255' => 'Other' + ); + $exif_value = defined $meteringmodes{$exif_value} ? $meteringmodes{$exif_value} : 'unknown metering mode'; + } + $value = $exif_value; + + } + if ($exif_key eq 'LightSource') { + my $exif_value = $imageinfo->{$exif_key}; + if ($exif_value =~ /^\d+$/) { + my %lightsources = ( + '0' => 'unknown', + '1' => 'Daylight', + '2' => 'Fluorescent', + '3' => 'Tungsten (incandescent light)', + '4' => 'Flash', + '9' => 'Fine weather', + '10' => 'Cloudy weather', + '11' => 'Shade', + '12' => 'Daylight fluorescent', + '13' => 'Day white fluorescent', + '14' => 'Cool white fluorescent', + '15' => 'White fluorescent', + '17' => 'Standard light A', + '18' => 'Standard light B', + '19' => 'Standard light C', + '20' => 'D55', + '21' => 'D65', + '22' => 'D75', + '23' => 'D50', + '24' => 'ISO studio tungsten', + '255' => 'other light source' + ); + $exif_value = defined $lightsources{$exif_value} ? $lightsources{$exif_value} : 'unknown light source'; + } + $value = $exif_value; + } + if ($exif_key eq 'FocalLength') { + if ($value =~ /^(\d+)\/(\d+)$/) { + $value = eval { $1 / $2 }; + if ($@) { + $value = $@; + } else { + $value = int($value + 0.5) . "mm"; + + } + } + } + if ($exif_key eq 'ShutterSpeedValue') { + if ($value =~ /^((?:\-)?\d+)\/(\d+)$/) { + $value = eval { $1 / $2 }; + if ($@) { + $value = $@; + } else { + eval { + $value = 1/(exp($value*log(2))); + if ($value < 1) { + $value = "1/" . (int((1/$value))); + } else { + $value = int($value*10)/10; + } + }; + if ($@) { + $value = $@; + } else { + $value = $value . " sec"; + } + } + } + } + if ($exif_key eq 'ApertureValue') { + if ($value =~ /^(\d+)\/(\d+)$/) { + $value = eval { $1 / $2 }; + if ($@) { + $value = $@; + } else { + # poor man's rounding + $value = int(exp($value*log(2)*0.5)*10)/10; + $value = "f" . $value; + } + } + } + if ($exif_key eq 'FNumber') { + if ($value =~ /^(\d+)\/(\d+)$/) { + $value = eval { $1 / $2 }; + if ($@) { + $value = $@; + } else { + $value = int($value*10+0.5)/10; + $value = "f" . $value; + } + } + } + $imageinfo->{$human_key} = $value; + } + } + + if ($r->dir_config('GalleryUseFileDate') && + ($r->dir_config('GalleryUseFileDate') eq '1' + || !$imageinfo->{"Picture Taken"} )) { + + my $st = stat($file); + $imageinfo->{"DateTimeOriginal"} = $imageinfo->{"Picture Taken"} = scalar localtime($st->mtime) if $st; + } + + return $imageinfo; +} + +sub get_imageinfo_from_thm_file { + + my ($file, $width, $height) = @_; + + my $imageinfo = undef; + # Windows based file extensions are often .THM, so check + # for both .thm and .THM + my $unix_file = $file; + my $windows_file = $file; + $unix_file =~ s/\.(\w+)$/.thm/; + $windows_file =~ s/\.(\w+)$/.THM/; + + if (-e $unix_file && -f $unix_file && -r $unix_file) { + $imageinfo = image_info($unix_file); + $imageinfo->{width} = $width; + $imageinfo->{height} = $height; + } + elsif (-e $windows_file && -f $windows_file && -r $windows_file) { + $imageinfo = image_info($windows_file); + $imageinfo->{width} = $width; + $imageinfo->{height} = $height; + } + + return $imageinfo; +} + + +sub readfile_getnum { + my ($r, $imageinfo, $filename) = @_; + + my $rotate = 0; + + # Check to see if the image contains the Orientation EXIF key, + # but allow user to override using rotate + if (!defined($r->dir_config("GalleryAutoRotate")) + || $r->dir_config("GalleryAutoRotate") eq "1") { + if (defined($imageinfo->{Orientation})) { + if ($imageinfo->{Orientation} eq 'right_top') { + $rotate=1; + } + elsif ($imageinfo->{Orientation} eq 'left_bot') { + $rotate=3; + } + } + } + + if (open(FH, "<$filename")) { + my $temp = ; + chomp($temp); + close(FH); + unless ($temp =~ /^\d$/) { + $rotate = 0; + } + unless ($temp == 1 || $temp == 2 || $temp == 3) { + $rotate = 0; + } + $rotate = $temp; + } + + return $rotate; +} + +sub get_filecontent { + my $file = shift; + open(FH, $file) or return undef; + my $content = ''; + { + local $/; + $content = ; + } + close(FH); + return $content; +} + +sub get_comment { + my $filename = shift; + my $comment_ref = {}; + $comment_ref->{TITLE} = undef; + $comment_ref->{COMMENT} = ''; + + open(FH, $filename) or return $comment_ref; + my $title = ; + if ($title =~ m/^TITLE: (.*)$/) { + chomp($comment_ref->{TITLE} = $1); + } + else { + $comment_ref->{COMMENT} = $title; + } + + while () { + chomp; + $comment_ref->{COMMENT} .= $_; + } + close(FH); + + return $comment_ref; +} + +sub show_error { + + my ($r, $statuscode, $errortitle, $error) = @_; + + my $tpl = $r->dir_config('GalleryTemplateDir'); + + my %templates = create_templates({layout => "$tpl/layout.tpl", + error => "$tpl/error.tpl", + }); + + my %tpl_vars; + $tpl_vars{TITLE} = "Error! $errortitle"; + $tpl_vars{META} = ""; + $tpl_vars{ERRORTITLE} = "Error! $errortitle"; + $tpl_vars{ERROR} = $error; + + $tpl_vars{MAIN} = $templates{error}->fill_in(HASH => \%tpl_vars); + + $tpl_vars{PAGE} = $templates{layout}->fill_in(HASH => \%tpl_vars); + + $r->status($statuscode); + $r->content_type('text/html'); + + $r->print($tpl_vars{PAGE}); + +} + +sub generate_menu { + + my $r = shift; + + my $root_text = (defined($r->dir_config('GalleryRootText')) ? $r->dir_config('GalleryRootText') : "root:" ); + my $root_path = (defined($r->dir_config('GalleryRootPath')) ? $r->dir_config('GalleryRootPath') : "" ); + + my $subr = $r->lookup_uri($r->uri); + my $filename = $subr->filename; + + my @links = split (/\//, $r->uri); + my $uri = $r->uri; + $uri =~ s/^$root_path//g; + + @links = split (/\//, $uri); + + # Get the full path of the base directory + my $dirname; + { + my @direlem = split (/\//, $filename); + for my $i ( 0 .. ( scalar(@direlem) - scalar(@links) ) ) { + $dirname .= shift(@direlem) . '/'; + } + chop $dirname; + } + + my $picturename; + if (-f $filename) { + $picturename = pop(@links); + } + + if ($r->uri eq $root_path) { + return qq{ $root_text }; + } + + my $menu; + my $menuurl = $root_path; + foreach my $link (@links) { + + $menuurl .= $link."/"; + my $linktext = $link; + unless (length($link)) { + $linktext = "$root_text "; + } + else { + + $dirname = File::Spec->catdir($dirname, $link); + + if (-e $dirname . ".folder") { + $linktext = get_filecontent($dirname . ".folder"); + } + } + + if ("$root_path$uri" eq $menuurl) { + $menu .= "$linktext / "; + } + else { + $menu .= "$linktext / "; + } + + } + + if (-f $filename) { + $menu .= $picturename; + } + else { + + if ($r->dir_config('GallerySelectionMode') && $r->dir_config('GallerySelectionMode') eq '1') { + $menu .= "[select] "; + } + } + + return $menu; +} + +sub resizepicture { + my ($r, $infile, $outfile, $x, $y, $rotate, $copyrightfile, $GalleryTTFDir, $GalleryCopyrightText, $text_color, $GalleryTTFFile, $GalleryTTFSize, $GalleryCopyrightBackgroundColor, $quality) = @_; + + # Load image + my $image = Image::Imlib2->load($infile) or warn("Unable to open file $infile, $!"); + + # Scale image + $image=$image->create_scaled_image($x, $y) or warn("Unable to scale image $infile. Are you running out of memory?"); + + # Rotate image + if ($rotate != 0) { + $image->image_orientate($rotate); + } + + # blend copyright image onto image + if ($copyrightfile ne '') { + if (-f $copyrightfile and (my $logo=Image::Imlib2->load($copyrightfile))) { + my $x = $image->get_width(); + my $y = $image->get_height(); + my $logox = $logo->get_width(); + my $logoy = $logo->get_height(); + $image->blend($logo, 0, 0, 0, $logox, $logoy, $x-$logox, $y-$logoy, $logox, $logoy); + } + else { + log_error("GalleryCopyrightImage $copyrightfile was not found"); + } + } + + if ($GalleryTTFDir && $GalleryCopyrightText && $GalleryTTFFile && $text_color) { + if (!-d $GalleryTTFDir) { + + log_error("GalleryTTFDir $GalleryTTFDir is not a dir\n"); + + } elsif ($GalleryCopyrightText eq '') { + + log_error("GalleryCopyrightText is empty. No text inserted to picture\n"); + + } elsif (!-e "$GalleryTTFDir/$GalleryTTFFile") { + + log_error("GalleryTTFFile $GalleryTTFFile was not found\n"); + + } else { + + $GalleryTTFFile =~ s/\.TTF$//i; + $image->add_font_path("$GalleryTTFDir"); + + $image->load_font("$GalleryTTFFile/$GalleryTTFSize"); + my($text_x, $text_y) = $image->get_text_size("$GalleryCopyrightText"); + my $x = $image->get_width(); + my $y = $image->get_height(); + + my $offset = 3; + + if (($text_x < $x - $offset) && ($text_y < $y - $offset)) { + if ($GalleryCopyrightBackgroundColor =~ /^\d+,\d+,\d+,\d+$/) { + my ($br_val, $bg_val, $bb_val, $ba_val) = split (/,/, $GalleryCopyrightBackgroundColor); + $image->set_colour($br_val, $bg_val, $bb_val, $ba_val); + $image->fill_rectangle ($x-$text_x-$offset, $y-$text_y-$offset, $text_x, $text_y); + } + my ($r_val, $g_val, $b_val, $a_val) = split (/,/, $text_color); + $image->set_colour($r_val, $g_val, $b_val, $a_val); + $image->draw_text($x-$text_x-$offset, $y-$text_y-$offset, "$GalleryCopyrightText"); + } else { + log_error("Text is to big for the picture.\n"); + } + } + } + + if ($quality && $quality =~ m/^\d+$/) { + $image->set_quality($quality); + } + + $image->save($outfile); + +} + +sub gallerysort { + my $r=shift; + my @files=@_; + my $sortby = $r->dir_config('GallerySortBy'); + my $filename=$r->lookup_uri($r->uri)->filename; + $filename=(File::Spec->splitpath($filename))[1] if (-f $filename); + if ($sortby && $sortby =~ m/^(size|atime|mtime|ctime)$/) { + @files = map(/^\d+ (.*)/, sort map(stat("$filename/$_")->$sortby()." $_", @files)); + } else { + @files = sort @files; + } + return @files; +} + +# Create Text::Template objects used by Apache::Gallery. Takes a +# hashref of template_name, template_filename pairs, and returns a +# list of template_name, texttemplate_object pairs. +sub create_templates { + my $templates = shift; + + # This routine is called whenever a template has an error. Prints + # the error to STDERR and sticks the error in the output + sub tt_broken { + my %args = @_; + # Pull out the name and filename from the arg option [see + # Text::Template for details] + @args{qw(name file)} = @{$args{arg}}; + print STDERR qq(Template $args{name} ("$args{file}") is broken: $args{error}); + # Don't include the file name in the output, as the user can see this. + return qq(); + } + + + + my %texttemplate_objects; + + for my $template_name (keys %$templates) { + my $tt_obj = Text::Template->new(TYPE => 'FILE', + SOURCE => $$templates{$template_name}, + BROKEN => \&tt_broken, + BROKEN_ARG => [$template_name, $$templates{$template_name}], + ) + or die "Unable to create new Text::Template object for $template_name: $Text::Template::ERROR"; + $texttemplate_objects{$template_name} = $tt_obj; + } + return %texttemplate_objects; +} + +sub log_error { + if ($::MP2) { + Apache2::RequestUtil->request->log_error(shift()); + } else { + Apache->request->log_error(shift()); + } +} + +1; + +=head1 NAME + +Apache::Gallery - mod_perl handler to create an image gallery + +=head1 SYNOPSIS + +See the INSTALL file in the distribution for installation instructions. + +=head1 DESCRIPTION + +Apache::Gallery creates an thumbnail index of each directory and allows +viewing pictures in different resolutions. Pictures are resized on the +fly and cached. The gallery can be configured and customized in many ways +and a custom copyright image can be added to all the images without +modifying the original. + +=head1 CONFIGURATION + +In your httpd.conf you set the global options for the gallery. You can +also override each of the options in .htaccess files in your gallery +directories. + +The options are set in the httpd.conf/.htaccess file using the syntax: +B + +Example: B + +=over 4 + +=item B + +Some cameras, like the Canon G3, can detect the orientation of a +the pictures you take and will save this information in the +'Orientation' EXIF field. Apache::Gallery will then automatically +rotate your images. + +This behavior is default but can be disabled by setting GalleryAutoRotate +to 0. + +=item B + +Directory where Apache::Gallery should create its cache with scaled +pictures. The default is /var/tmp/Apache-Gallery/ . Here, a directory +for each virtualhost or location will be created automaticly. Make +sure your webserver has write access to the CacheDir. + +=item B + +Full path to the directory where you placed the templates. This option +can be used both in your global configuration and in .htaccess files, +this way you can have different layouts in different parts of your +gallery. + +No default value, this option is required. + +=item B + +With this option you can define which EXIF information you would like +to present from the image. The format is: ' KeyInEXIF, +MyOtherName => OtherKeyInEXIF' + +Examples of keys: B, B, B, +and B + +You can view all the keys from the EXIF header using this perl-oneliner: + +perl C<-e> 'use Data::Dumper; use Image::Info qw(image_info); print Dumper(image_info(shift));' filename.jpg + +Default is: 'Picture Taken => DateTimeOriginal, Flash => Flash' + +=item B + +Defines which widths images can be scaled to. Images cannot be +scaled to other widths than the ones you define with this option. + +The default is '640 800 1024 1600' + +=item B + +Defines the width and height of the thumbnail images. + +Defaults to '100x75' + +=item B + +If set to '1', B is the long and the short side of +the thumbnail image instead of the width and height. + +Defaults to '0'. + +=item B + +Image you want to blend into your images in the lower right +corner. This could be a transparent png saying "copyright +my name 2001". + +Optional. + +=item B + +Make the navigation in the picture view wrap around (So Next +at the end displays the first picture, etc.) + +Set to 1 or 0, default is 0 + +=item B + +Allow the user to download the Original picture without +resizing or putting the CopyrightImage on it. + +Set to 1 or 0, default is 0 + +=item B + +With this option you can configure which intervals can be selected for +a slideshow. The default is '3 5 10 15 30' + +=item B + +Instead of the default filename ordering you can sort by any +stat attribute. For example size, atime, mtime, ctime. + +=item B + +Set this variable to sort directories differently than other items, +can be set to size, atime, mtime and ctime; setting any other value +will revert to sorting by name. + +=item B + +Cache EXIF data using Memoize - this will make Apache::Gallery faster +when many people access the same images, but it will also cache EXIF +data until the current Apache child dies. + +=item B + +Set this option to 1 to make A::G show the files timestamp +instead of the EXIF value for "Picture taken". + +=item B + +Enable the selection mode. Select images with checkboxes and +get a list of filenames. + +=item B + +You can choose how Apache::Gallery should display EXIF info +from your images. + +The default setting is 'namevalue'. This setting will make +Apache::Gallery print out the names and values of the EXIF values +you configure with GalleryInfo. The information will be parsed into +$INFO in pictureinfo.tpl. + +You can also set it to 'values' which will make A::G parse +the configured values into the var $EXIFVALUES as 'value | value | value' + +If you set this option to 'variables' the items you configure in GalleryInfo +will be available to your templates as $EXIF_ (in all uppercase). +That means that with the default setting "Picture Taken => DateTimeOriginal, +Flash => Flash" you will have the variables $EXIF_DATETIMEORIGINAL and +$EXIF_FLASH avilable to your templates. You can place them +anywhere you want. + +=item B + +Change the location of gallery root. The default is "" + +=item B + +Change the name that appears as the root element in the menu. The +default is "root:" + +=item B + +This options controls how many thumbnails should be displayed in a +page. It requires $BROWSELINKS to be in the index.tpl template file. + +=item B + +Pattern matching the files you want Apache::Gallery to view in the +index as thumbnails. + +The default is '\.(jpe?g|png|tiff?|ppm)$' + +=item B + +Pattern matching the files you want Apache::Gallery to view in the index +as normal files. All other filetypes will still be served by Apache::Gallery +but are not visible in the index. + +The default is '\.(mpe?g|avi|mov|asf|wmv|doc|mp3|ogg|pdf|rtf|wav|dlt|html?|csv|eps)$' + +=item B + +To use the GalleryCopyrightText feature you must set this option to the +directory where your True Type fonts are stored. No default is set. + +Example: + + PerlSetVar GalleryTTFDir '/usr/share/fonts/' + +=item B + +To use the GalleryCopyrightText feature this option must be set to the +name of the True Type font you wish to use. Example: + + PerlSetVar GalleryTTFFile 'verdanab.ttf' + +=item B + +Configure the size of the CopyrightText that will be inserted as +copyright notice in the corner of your pictures. + +Example: + + PerlSetVar GalleryTTFSize '10' + +=item B + +The text that will be inserted as copyright notice. + +Example: + + PerlSetVar GalleryCopyrightText '(c) Michael Legart' + +=item B + +The text color of your copyright notice. + +Examples: + +White: + PerlSetVar GalleryCopyrightColor '255,255,255,255' + +Black: + PerlSetVar GalleryCopyrightColor '0,0,0,255' + +Red: + PerlSetVar GalleryCopyrightColor '255,0,0,255' + +Green: + PerlSetVar GalleryCopyrightColor '0,255,0,255' + +Blue: + PerlSetVar GalleryCopyrightColor '0,0,255,255' + +Transparent orange: + PerlSetVar GalleryCopyrightColor '255,127,0,127' + +=item B + +The background-color of a GalleryCopyrightText + +r,g,b,a - for examples, see GalleryCopyrightColor + +=item B + +The quality (1-100) of scaled images + +This setting affects the quality of the scaled images. +Set this to a low number to reduce the size of the scaled images. +Remember to clear out your cache if you change this setting. +Quality seems to default to 75, at least in the jpeg and png loader code in +Imlib2 1.1.0. + +Examples: + +Quality at 50: + PerlSetVar GalleryQuality '50' + +=item B + +Set this option to 1 to convert underscores to spaces in the listing +of directory names. + +=back + +=head1 FEATURES + +=over 4 + +=item B + +Some cameras, like the Canon G3, detects the orientation of a picture +and adds this info to the EXIF header. Apache::Gallery detects this +and automaticly rotates images with this info. + +If your camera does not support this, you can rotate the images +manually, This can also be used to override the rotate information +from a camera that supports that. You can also disable this behavior +with the GalleryAutoRotate option. + +To use this functionality you have to create file with the name of the +picture you want rotated appened with ".rotate". The file should include +a number where these numbers are supported: + + "1", rotates clockwise by 90 degree + "2", rotates clockwise by 180 degrees + "3", rotates clockwise by 270 degrees + +So if we want to rotate "Picture1234.jpg" 90 degrees clockwise we would +create a file in the same directory called "Picture1234.jpg.rotate" with +the number 1 inside of it. + +=item B + +To include comments for a directory you create a .comment +file where the first line can contain "TITLE: New title" which +will be the title of the page, and a comment on the following +lines. +To include comments for each picture you create files called +picture.jpg.comment where the first line can contain "TITLE: New +title" which will be the title of the page, and a comment on the +following lines. + +Example: + + TITLE: This is the new title of the page + And this is the comment.
+ And this is line two of the comment. + +The visible name of the folder is by default identical to the name of +the folder, but can be changed by creating a file .folder +with the visible name of the folder. + +=back + +=head1 DEPENDENCIES + +=over 4 + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B +(ie, XFree86) + +=item B +Remember the -dev package when using rpm, deb or other package formats! + +=back + +=head1 AUTHOR + +Michael Legart + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2001-2005 Michael Legart + +Templates designed by Thomas Kjaer + +Apache::Gallery is free software and is released under the Artistic License. +See B for details. + +The video icons are from the GNOME project. B + +=head1 THANKS + +Thanks to Thomas Kjaer for templates and design of B +Thanks to Thomas Eibner and other for patches. (See the Changes file) + +=head1 SEE ALSO + +L, L, L, L, +L, and L. + +=cut diff --git a/t/001_use.t b/t/001_use.t new file mode 100644 index 0000000..6704b01 --- /dev/null +++ b/t/001_use.t @@ -0,0 +1,5 @@ +use Test::More tests => 1; + +BEGIN { use_ok('Apache::Gallery'); } + + diff --git a/t/002_graphlibs.t b/t/002_graphlibs.t new file mode 100644 index 0000000..0c2d258 --- /dev/null +++ b/t/002_graphlibs.t @@ -0,0 +1,28 @@ +use Test::More; +use Apache::Gallery; +use Image::Size qw(imgsize); + +eval { require Apache::FakeRequest; }; +if ($@) { + plan skip_all => 'skip Apache::FakeRequest not found'; +} +else { + + plan tests => 4; + + my $request = Apache::FakeRequest->new('get_remote_host' => 'localhost'); + + Apache::Gallery::resizepicture($request, 't/002_inpng.png', 't/inpng-resized.png', 10, 10, 0, ''); + Apache::Gallery::resizepicture($request, 't/002_injpg.jpg', 't/injpg-resized.jpg', 10, 10, 0, ''); + my ($pngwidth, $pngheight)=imgsize('t/inpng-resized.png'); + my ($jpgwidth, $jpgheight)=imgsize('t/injpg-resized.jpg'); + + is ($pngwidth, 10, 'PNG Width') or diag('You need to install libpng before libimlib'); + is ($pngheight, 10, 'PNG Height') or diag('You need to install libpng before libimlib'); + is ($jpgwidth, 10, 'JPG Width') or diag('You need to install libjpeg before libimlib'); + is ($jpgheight, 10, 'JPG Height') or diag('You need to install libjpeg before libimlib'); + + unlink('t/inpng-resized.png'); + unlink('t/injpg-resized.jpg'); + +} diff --git a/t/002_injpg.jpg b/t/002_injpg.jpg new file mode 100644 index 0000000..b3f30f8 Binary files /dev/null and b/t/002_injpg.jpg differ diff --git a/t/002_inpng.png b/t/002_inpng.png new file mode 100644 index 0000000..2759ff3 Binary files /dev/null and b/t/002_inpng.png differ diff --git a/t/003_comment.t b/t/003_comment.t new file mode 100644 index 0000000..05dea34 --- /dev/null +++ b/t/003_comment.t @@ -0,0 +1,8 @@ +use Test::More tests => 2; + +use Apache::Gallery; + +my $comment = Apache::Gallery::get_comment("t/003_commenttest"); + +is ( $comment->{TITLE}, "My test title", 'Title'); +is ( $comment->{COMMENT}, "My test comment", 'Comment'); diff --git a/t/003_commenttest b/t/003_commenttest new file mode 100644 index 0000000..190ae42 --- /dev/null +++ b/t/003_commenttest @@ -0,0 +1,2 @@ +TITLE: My test title +My test comment diff --git a/t/004_cache_dir.t b/t/004_cache_dir.t new file mode 100644 index 0000000..4998b3c --- /dev/null +++ b/t/004_cache_dir.t @@ -0,0 +1,58 @@ +use Apache::Gallery; +my $tests; +BEGIN { + $tests=8; + eval { require Test::MockObject }; + if ($@) { + print("1..$tests\n"); + for (1..$tests) { + print ("ok $_ # skip Test::MockObject not found\n"); + } + exit 0; + } +} +use Test::More tests => $tests; +use File::Spec; + +# Test these cases: +# +--------------------------------------------------+ +# | No. | GalleryCacheDir | Virtual | Strip Filename | +# | 1 | undef | y | y | +# | 2 | undef | y | n | +# | 3 | undef | n | y | +# | 4 | undef | n | n | +# | 5 | 't/cachetest' | y | y | +# | 6 | 't/cachetest' | y | n | +# | 7 | 't/cachetest' | n | y | +# | 8 | 't/cachetest' | n | n | +# +-----+-----------------+---------+----------------+ + +sub request { + my ($cachedir, $virtual) = @_; + my $r=Test::MockObject->new(); + $r->set_always('location', '/location'); + $r->set_always('uri', '/uripath1/uripath2/urifile'); + $r->set_always('dir_config', $cachedir); + my $server=Test::MockObject->new(); + $server->set_always('is_virtual', $virtual); + $server->set_always('server_hostname', 'hostname' ); + $r->set_always('server', $server); + + return $r; +} + +my $r=request(undef, 1); +is(Apache::Gallery::cache_dir($r, 1), '/var/tmp/Apache-Gallery/hostname/uripath1/uripath2'); +is(Apache::Gallery::cache_dir($r, 0), '/var/tmp/Apache-Gallery/hostname/uripath1/uripath2/urifile'); + +$r=request(undef, 0); +is(Apache::Gallery::cache_dir($r, 1), '/var/tmp/Apache-Gallery/location/uripath1/uripath2'); +is(Apache::Gallery::cache_dir($r, 0), '/var/tmp/Apache-Gallery/location/uripath1/uripath2/urifile'); + +$r=request('t/cachetest', 1); +is(Apache::Gallery::cache_dir($r, 1), 't/cachetest/uripath1/uripath2'); +is(Apache::Gallery::cache_dir($r, 0), 't/cachetest/uripath1/uripath2/urifile'); + +$r=request('t/cachetest', 0); +is(Apache::Gallery::cache_dir($r, 1), 't/cachetest/uripath1/uripath2'); +is(Apache::Gallery::cache_dir($r, 0), 't/cachetest/uripath1/uripath2/urifile'); diff --git a/t/005_imageinfo.t b/t/005_imageinfo.t new file mode 100644 index 0000000..2ebe355 --- /dev/null +++ b/t/005_imageinfo.t @@ -0,0 +1,17 @@ +use Apache::Gallery; +use Test::More; + +eval { require Apache::FakeRequest; }; +if ($@) { + plan skip_all => 'skip Apache::FakeRequest not found'; +} +else { + + plan tests => 1; + + my $request = Apache::FakeRequest->new('get_remote_host' => 'localhost'); + + my $info = Apache::Gallery::get_imageinfo($request, "t/005_jpg.jpg", "JPG", 15, 11); + + is ( $info->{Comment}, "Created with The GIMP", 'Comment'); +} diff --git a/t/005_jpg.jpg b/t/005_jpg.jpg new file mode 100644 index 0000000..b3f30f8 Binary files /dev/null and b/t/005_jpg.jpg differ diff --git a/t/006_thumbnails.t b/t/006_thumbnails.t new file mode 100644 index 0000000..29cf3db --- /dev/null +++ b/t/006_thumbnails.t @@ -0,0 +1,24 @@ +use Apache::Gallery; +use Test::More; + +eval { require Test::MockObject; }; +if ($@) { + plan skip_all => 'skip because Test::MockObject not found'; +} +else { + + plan tests => 4; + + my $r = Test::MockObject->new(); + + $r->set_always('dir_config', '100x75'); + + my ($width, $height) = Apache::Gallery::get_thumbnailsize($r, 640, 480); + is ($width, 100, 'Width'); + is ($height, 75, 'Height'); + + ($width, $height) = Apache::Gallery::get_thumbnailsize($r, 480, 640); + is ($width, 56, 'Height rotated'); + is ($height, 75, 'Width rotated'); + +} diff --git a/t/007_pod.t b/t/007_pod.t new file mode 100644 index 0000000..77fe89e --- /dev/null +++ b/t/007_pod.t @@ -0,0 +1,19 @@ +use Test::More; +use File::Spec; +use File::Find; +use strict; + +eval "use Test::Pod 0.95"; + +if ($@) { + plan skip_all => 'Test::Pod v0.95 required for testing POD'; +} else { + Test::Pod->import; + my @files; + my $blib = File::Spec->catfile(qw(blib lib)); + find( sub {push @files, $File::Find::name if /\.p(l|m|od)$/}, $blib); + plan tests => scalar @files; + foreach my $file (@files) { + pod_file_ok($file); + } +} diff --git a/templates/bright/README b/templates/bright/README new file mode 100644 index 0000000..eeb95de --- /dev/null +++ b/templates/bright/README @@ -0,0 +1,9 @@ +For this template to work the first two of the following options are a necessity, option three and four only completes the +design. Option two should of course be hacked to fit the EXIF from your camera. + +Remember to copy the new gallery.css to your DocumentRoot as well. + +PerlSetVar GalleryEXIFMode 'variables' +PerlSetVar GalleryInfo 'Model => Model, Timestamp => DateTimeOriginal, Exposure Time => ExposureTime, ISO Speed Rating => ISOSpeedRatings, Focal Length => FocalLength, ApertureValue => ApertureValue, Flash => Flash' +PerlSetVar GalleryThumbnailSize '140x105' +PerlSetVar GalleryThumbnailSizeLS 1 diff --git a/templates/bright/dircomment.tpl b/templates/bright/dircomment.tpl new file mode 100644 index 0000000..2d12f64 --- /dev/null +++ b/templates/bright/dircomment.tpl @@ -0,0 +1,11 @@ + + + + + + +
+ { $COMMENT } +
+ + diff --git a/templates/bright/directory.tpl b/templates/bright/directory.tpl new file mode 100644 index 0000000..e828ec4 --- /dev/null +++ b/templates/bright/directory.tpl @@ -0,0 +1 @@ + diff --git a/templates/bright/error.tpl b/templates/bright/error.tpl new file mode 100644 index 0000000..bf0c033 --- /dev/null +++ b/templates/bright/error.tpl @@ -0,0 +1,22 @@ + + + + +
+

{ $ERRORTITLE }

+

{ $ERROR }

+

Back

+
+ + diff --git a/templates/bright/file.tpl b/templates/bright/file.tpl new file mode 100644 index 0000000..04ff664 --- /dev/null +++ b/templates/bright/file.tpl @@ -0,0 +1 @@ + diff --git a/templates/bright/gallery.css b/templates/bright/gallery.css new file mode 100644 index 0000000..5720dd0 --- /dev/null +++ b/templates/bright/gallery.css @@ -0,0 +1,128 @@ +body { + background-color: #eee; + font-family: tahoma, verdana, sans-serif; + color: #555; + text-align: center; + font-size: 11px; + margin: 10px; +} +td { + font-size: 11px; +} +a { + color: #506677; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +table { + margin: auto; +} +.gallery-info { + text-align: left; + margin-bottom: 30px; +} +/* +.img-white { + margin: 0px auto; + float: left; + background: url(/eeeBorder.gif) no-repeat top left; +} +.img-shadow { + float: left; + background: url(/eeeshadow.gif) no-repeat bottom right; +} +*/ +.img-border { + background-color: #fff; + border: 1px solid #555; + padding: 8px; + font-size: 11px; + margin: 6px; + text-align: right; +} +.img-shadow img { + border: 2px solid #ddd; + border-left: 2px solid #999; + border-top: 2px solid #999; +} +.img-border div { + margin-top: 4px; +} +.clr { + clear: both; +} +div.gallery-nav { + float: right; + text-align: right; +} +div.gallery-info { + float: left; + text-align: left; +} +div.gallery-info a { +} +div.gallery-info:hover { + color: #000; +} +div.gallery-info:hover a { + color: #5b8db2; +} +.img-info { + margin-bottom: 5px; +} +.img-info:hover { + color: #000; +} +.img-options { + margin-top: 5px; + margin-bottom: 100px; +} +.img-options:hover { + color: #000; +} +.img-options:hover a { + color: #5b8db2; +} +.aginfo:hover { + color: #000; +} +.aginfo:hover a { + color: #0066b2; +} +#directory { + background-color: #fff; + border: 4px solid #ddd; + padding: 20px; + text-align: left; + top: 0px; + width: 620px; +} +.thumb { + float: left; + text-align: center; + width: 150px; + height: 150px; + margin: 2px; +} +.thumb img { + border-color: #506677; + vertical-align: middle; +} +.folder { + float: left; + height: 100px; + padding: 2px; + text-align: center; + width: 120px; +} +.folder img { + border: 0px; +} +.folder a:hover img { + border: 0px; +} +.folder a:hover { + text-decoration: none; +} diff --git a/templates/bright/index.tpl b/templates/bright/index.tpl new file mode 100644 index 0000000..fcebc08 --- /dev/null +++ b/templates/bright/index.tpl @@ -0,0 +1,23 @@ + + +
+
+{ $FORM_BEGIN } +
+ + + + +
+
+{ $FILES } +
+
+ { $DIRCOMMENT } +
+
+ Indexed by Apache::Gallery - Copyright © 2001-2006 Michael Legart - Hest Design! +
+{ $FORM_END } diff --git a/templates/bright/info.tpl b/templates/bright/info.tpl new file mode 100644 index 0000000..b7f2e08 --- /dev/null +++ b/templates/bright/info.tpl @@ -0,0 +1 @@ +{ $KEY }: { $VALUE }
diff --git a/templates/bright/interval.tpl b/templates/bright/interval.tpl new file mode 100644 index 0000000..78e817f --- /dev/null +++ b/templates/bright/interval.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/bright/intervalactive.tpl b/templates/bright/intervalactive.tpl new file mode 100644 index 0000000..d0af3eb --- /dev/null +++ b/templates/bright/intervalactive.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/bright/layout.tpl b/templates/bright/layout.tpl new file mode 100644 index 0000000..7d82715 --- /dev/null +++ b/templates/bright/layout.tpl @@ -0,0 +1,18 @@ + + + + + +{ $TITLE } + + +{ $META } + + + +{ $MAIN } + + diff --git a/templates/bright/navpicture.tpl b/templates/bright/navpicture.tpl new file mode 100644 index 0000000..96c6112 --- /dev/null +++ b/templates/bright/navpicture.tpl @@ -0,0 +1 @@ +{ $DIRECTION } diff --git a/templates/bright/nodircomment.tpl b/templates/bright/nodircomment.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/bright/nopictureinfo.tpl b/templates/bright/nopictureinfo.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/bright/orig.tpl b/templates/bright/orig.tpl new file mode 100644 index 0000000..fd20746 --- /dev/null +++ b/templates/bright/orig.tpl @@ -0,0 +1 @@ +Original diff --git a/templates/bright/picture.tpl b/templates/bright/picture.tpl new file mode 100644 index 0000000..0036282 --- /dev/null +++ b/templates/bright/picture.tpl @@ -0,0 +1 @@ +
{ $FILE } - { $DATE }{ $SELECT }
diff --git a/templates/bright/pictureinfo.tpl b/templates/bright/pictureinfo.tpl new file mode 100644 index 0000000..c7b93c8 --- /dev/null +++ b/templates/bright/pictureinfo.tpl @@ -0,0 +1,5 @@ +
+
+ { $INFO } + { $COMMENT } +
diff --git a/templates/bright/refresh.tpl b/templates/bright/refresh.tpl new file mode 100644 index 0000000..8b9379f --- /dev/null +++ b/templates/bright/refresh.tpl @@ -0,0 +1 @@ + diff --git a/templates/bright/scale.tpl b/templates/bright/scale.tpl new file mode 100644 index 0000000..3e532b9 --- /dev/null +++ b/templates/bright/scale.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/bright/scaleactive.tpl b/templates/bright/scaleactive.tpl new file mode 100644 index 0000000..22a4e75 --- /dev/null +++ b/templates/bright/scaleactive.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/bright/showpicture.tpl b/templates/bright/showpicture.tpl new file mode 100644 index 0000000..07019da --- /dev/null +++ b/templates/bright/showpicture.tpl @@ -0,0 +1,38 @@ + + + +
+
+ IMG { $NUMBER } of { $TOTAL } + | { $EXIF_DATETIMEORIGINAL } + | { $EXIF_EXPOSURETIME }s + | { $EXIF_ISOSPEEDRATINGS }iso + | { $EXIF_FOCALLENGTH } + | { $EXIF_APERTUREVALUE } +
+ + + + +
+
+
+
+ * Image { $NUMBER } + { $PICTUREINFO } +
+
+
+
+
+
+[ Size: { $SIZES } | Slideshow: { $SLIDESHOW } ] +
+ +
+ Apache::Gallery © 2001-2006 Michael Legart, Hest Design! +
diff --git a/templates/bright/slideshowisoff.tpl b/templates/bright/slideshowisoff.tpl new file mode 100644 index 0000000..ce76936 --- /dev/null +++ b/templates/bright/slideshowisoff.tpl @@ -0,0 +1 @@ +Off diff --git a/templates/bright/slideshowoff.tpl b/templates/bright/slideshowoff.tpl new file mode 100644 index 0000000..3c03d57 --- /dev/null +++ b/templates/bright/slideshowoff.tpl @@ -0,0 +1 @@ +Off diff --git a/templates/default/dircomment.tpl b/templates/default/dircomment.tpl new file mode 100644 index 0000000..2d12f64 --- /dev/null +++ b/templates/default/dircomment.tpl @@ -0,0 +1,11 @@ + + + + + + +
+ { $COMMENT } +
+ + diff --git a/templates/default/directory.tpl b/templates/default/directory.tpl new file mode 100644 index 0000000..568bd3d --- /dev/null +++ b/templates/default/directory.tpl @@ -0,0 +1 @@ + diff --git a/templates/default/error.tpl b/templates/default/error.tpl new file mode 100644 index 0000000..3c18406 --- /dev/null +++ b/templates/default/error.tpl @@ -0,0 +1,9 @@ + + + + +
+

{ $ERRORTITLE }

+

{ $ERROR }

+

Back +

diff --git a/templates/default/file.tpl b/templates/default/file.tpl new file mode 100644 index 0000000..42a5194 --- /dev/null +++ b/templates/default/file.tpl @@ -0,0 +1 @@ + diff --git a/templates/default/gallery.css b/templates/default/gallery.css new file mode 100644 index 0000000..b9ac880 --- /dev/null +++ b/templates/default/gallery.css @@ -0,0 +1,66 @@ +body { + background-color: #cccccc; + font-family: Verdana, Lucida, Arial; + font-size: 10px; + margin-left: 10px; + margin-top: 10px; + text-align: center; +} +td { + font-size: 10px; +} +table { + margin-left: auto; + margin-right: auto; +} +#menu { + font-size: 11px; + text-align: left; + height: 30px; +} +#nav { + font-size: 11px; + text-align: left; + height: 30px; + text-align: right; +} +#directory { + background-color: #ffffff; + border: 1px solid #666666; + padding: 20px; + text-align: left; + top: 0px; +} +#folder { + float: left; + height: 100px; + padding: 2px; + text-align: center; + width: 120px; +} +#picture img { + border: 1px solid #000000; +} +a { + color: #5555aa; +} +a img { + border: 2px solid #5555aa; +} +a:hover { + color: #ff9400; +} +a:hover img { + border: 2px solid #ff9400; +} +#folder img { + border: 0px; +} +.info { + background-color: #eeeeee; + border: 1px dashed #888888; + color: #666666; + font-size: 10px; + margin: 10px; + padding: 5px; +} diff --git a/templates/default/index.tpl b/templates/default/index.tpl new file mode 100644 index 0000000..8208a5c --- /dev/null +++ b/templates/default/index.tpl @@ -0,0 +1,23 @@ +
+ + + + + + + { $DIRCOMMENT } + + + +
+
+{ $FILES } +
+
+ Indexed by Apache::Gallery - Copyright © 2001-2005 Michael Legart - Hest Design! +
+
diff --git a/templates/default/info.tpl b/templates/default/info.tpl new file mode 100644 index 0000000..06d0563 --- /dev/null +++ b/templates/default/info.tpl @@ -0,0 +1 @@ +{ $KEY }: { $VALUE }
diff --git a/templates/default/interval.tpl b/templates/default/interval.tpl new file mode 100644 index 0000000..b2d78fc --- /dev/null +++ b/templates/default/interval.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/default/intervalactive.tpl b/templates/default/intervalactive.tpl new file mode 100644 index 0000000..d0af3eb --- /dev/null +++ b/templates/default/intervalactive.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/default/layout.tpl b/templates/default/layout.tpl new file mode 100644 index 0000000..d9dea95 --- /dev/null +++ b/templates/default/layout.tpl @@ -0,0 +1,14 @@ + + + + + { $TITLE } + + { $META } + + + +{ $MAIN } + + diff --git a/templates/default/navpicture.tpl b/templates/default/navpicture.tpl new file mode 100644 index 0000000..10b30c0 --- /dev/null +++ b/templates/default/navpicture.tpl @@ -0,0 +1 @@ +
{ $DIRECTION } - { $FILENAME }
diff --git a/templates/default/nodircomment.tpl b/templates/default/nodircomment.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/default/nopictureinfo.tpl b/templates/default/nopictureinfo.tpl new file mode 100644 index 0000000..a5ead9b --- /dev/null +++ b/templates/default/nopictureinfo.tpl @@ -0,0 +1,11 @@ + +
+ + + + +
+   +
+
+ diff --git a/templates/default/orig.tpl b/templates/default/orig.tpl new file mode 100644 index 0000000..fd20746 --- /dev/null +++ b/templates/default/orig.tpl @@ -0,0 +1 @@ +Original diff --git a/templates/default/picture.tpl b/templates/default/picture.tpl new file mode 100644 index 0000000..41e97a3 --- /dev/null +++ b/templates/default/picture.tpl @@ -0,0 +1 @@ + { $FILE } - { $DATE } diff --git a/templates/default/pictureinfo.tpl b/templates/default/pictureinfo.tpl new file mode 100644 index 0000000..4a525a4 --- /dev/null +++ b/templates/default/pictureinfo.tpl @@ -0,0 +1,12 @@ + +
+ + + + +
+ { $COMMENT } + { $INFO } +
+
+ diff --git a/templates/default/refresh.tpl b/templates/default/refresh.tpl new file mode 100644 index 0000000..8b9379f --- /dev/null +++ b/templates/default/refresh.tpl @@ -0,0 +1 @@ + diff --git a/templates/default/scale.tpl b/templates/default/scale.tpl new file mode 100644 index 0000000..3e532b9 --- /dev/null +++ b/templates/default/scale.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/default/scaleactive.tpl b/templates/default/scaleactive.tpl new file mode 100644 index 0000000..22a4e75 --- /dev/null +++ b/templates/default/scaleactive.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/default/showpicture.tpl b/templates/default/showpicture.tpl new file mode 100644 index 0000000..d13f14b --- /dev/null +++ b/templates/default/showpicture.tpl @@ -0,0 +1,33 @@ +
+ +
+ + + + + + + + { $PICTUREINFO } + + + + + + +
+ +
{ $BACK }{ $NEXT }
+ +
+
+
diff --git a/templates/default/slideshowisoff.tpl b/templates/default/slideshowisoff.tpl new file mode 100644 index 0000000..ce76936 --- /dev/null +++ b/templates/default/slideshowisoff.tpl @@ -0,0 +1 @@ +Off diff --git a/templates/default/slideshowoff.tpl b/templates/default/slideshowoff.tpl new file mode 100644 index 0000000..3c03d57 --- /dev/null +++ b/templates/default/slideshowoff.tpl @@ -0,0 +1 @@ +Off diff --git a/templates/new/dircomment.tpl b/templates/new/dircomment.tpl new file mode 100644 index 0000000..2d12f64 --- /dev/null +++ b/templates/new/dircomment.tpl @@ -0,0 +1,11 @@ + + + + + + +
+ { $COMMENT } +
+ + diff --git a/templates/new/directory.tpl b/templates/new/directory.tpl new file mode 100644 index 0000000..5778170 --- /dev/null +++ b/templates/new/directory.tpl @@ -0,0 +1 @@ + diff --git a/templates/new/error.tpl b/templates/new/error.tpl new file mode 100644 index 0000000..e5f9540 --- /dev/null +++ b/templates/new/error.tpl @@ -0,0 +1,22 @@ + + + + +
+

{ $ERRORTITLE }

+

{ $ERROR }

+

Back

+
+ + diff --git a/templates/new/file.tpl b/templates/new/file.tpl new file mode 100644 index 0000000..cae88f4 --- /dev/null +++ b/templates/new/file.tpl @@ -0,0 +1 @@ + diff --git a/templates/new/gallery.css b/templates/new/gallery.css new file mode 100644 index 0000000..2cfbf32 --- /dev/null +++ b/templates/new/gallery.css @@ -0,0 +1,78 @@ +body { + background-color: #cccccc; + color: #666666; + font-family: Verdana, Lucida, Arial, serif; + font-size: 10px; + margin-left: 10px; + margin-top: 10px; + text-align: center; +} +td { + font-size: 10px; +} +table { + margin-left: auto; + margin-right: auto; +} +#title { + font-size: 11px; + text-align: left; +} +#menu { + font-size: 13px; + text-align: right; + height: 30px; + margin-right: 20px; +} +#directory { + background-color: #ffffff; + border: 6px solid #aaaaaa; + padding: 20px; + text-align: left; + top: 0px; +} +.folder { + float: left; + height: 100px; + padding: 2px; + text-align: center; + width: 120px; +} +#picture { + text-align: center; +} +#picture img { + border: 6px solid #777777; +} +a { + color: #5555aa; + text-decoration: none; +} +a img { + border: 3px solid #5555aa; +} +a:hover { + color: #ff9400; +} +a:hover img { + border: 3px solid #ff9400; +} +.folder img { + border: 0px; +} +.folder a:hover img { + border: 0px; +} +#gallery { + margin-top: 50px; +} +#comment { + background-color: #333333; + border: 3px solid #555555; + color: #999999; + width: 400px; + margin-left: auto; + margin-right: auto; + margin-top: 20px; + padding: 5px; +} diff --git a/templates/new/index.tpl b/templates/new/index.tpl new file mode 100644 index 0000000..4ba4105 --- /dev/null +++ b/templates/new/index.tpl @@ -0,0 +1,23 @@ +
+
+{ $MENU } +
+ + { $FORM_BEGIN } + + + + + { $DIRCOMMENT } + + + +
+
+{ $FILES } +
+
+ Indexed by Apache::Gallery - Copyright © 2001-2005 Michael Legart - Hest Design! +
+ { $FORM_END } +
diff --git a/templates/new/info.tpl b/templates/new/info.tpl new file mode 100644 index 0000000..06d0563 --- /dev/null +++ b/templates/new/info.tpl @@ -0,0 +1 @@ +{ $KEY }: { $VALUE }
diff --git a/templates/new/interval.tpl b/templates/new/interval.tpl new file mode 100644 index 0000000..b2d78fc --- /dev/null +++ b/templates/new/interval.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/new/intervalactive.tpl b/templates/new/intervalactive.tpl new file mode 100644 index 0000000..d0af3eb --- /dev/null +++ b/templates/new/intervalactive.tpl @@ -0,0 +1 @@ +{ $SECONDS } diff --git a/templates/new/layout.tpl b/templates/new/layout.tpl new file mode 100644 index 0000000..d9dea95 --- /dev/null +++ b/templates/new/layout.tpl @@ -0,0 +1,14 @@ + + + + + { $TITLE } + + { $META } + + + +{ $MAIN } + + diff --git a/templates/new/navpicture.tpl b/templates/new/navpicture.tpl new file mode 100644 index 0000000..96c6112 --- /dev/null +++ b/templates/new/navpicture.tpl @@ -0,0 +1 @@ +{ $DIRECTION } diff --git a/templates/new/nodircomment.tpl b/templates/new/nodircomment.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/new/nopictureinfo.tpl b/templates/new/nopictureinfo.tpl new file mode 100644 index 0000000..a5ead9b --- /dev/null +++ b/templates/new/nopictureinfo.tpl @@ -0,0 +1,11 @@ + +
+ + + + +
+   +
+
+ diff --git a/templates/new/orig.tpl b/templates/new/orig.tpl new file mode 100644 index 0000000..fd20746 --- /dev/null +++ b/templates/new/orig.tpl @@ -0,0 +1 @@ +Original diff --git a/templates/new/picture.tpl b/templates/new/picture.tpl new file mode 100644 index 0000000..a0bff91 --- /dev/null +++ b/templates/new/picture.tpl @@ -0,0 +1 @@ + { $FILE } - { $DATE }{ $SELECT } diff --git a/templates/new/pictureinfo.tpl b/templates/new/pictureinfo.tpl new file mode 100644 index 0000000..1c24017 --- /dev/null +++ b/templates/new/pictureinfo.tpl @@ -0,0 +1,8 @@ + + +
+ { $INFO } + { $COMMENT } +
+ + diff --git a/templates/new/refresh.tpl b/templates/new/refresh.tpl new file mode 100644 index 0000000..8b9379f --- /dev/null +++ b/templates/new/refresh.tpl @@ -0,0 +1 @@ + diff --git a/templates/new/scale.tpl b/templates/new/scale.tpl new file mode 100644 index 0000000..3e532b9 --- /dev/null +++ b/templates/new/scale.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/new/scaleactive.tpl b/templates/new/scaleactive.tpl new file mode 100644 index 0000000..22a4e75 --- /dev/null +++ b/templates/new/scaleactive.tpl @@ -0,0 +1 @@ +{ $SIZE } diff --git a/templates/new/showpicture.tpl b/templates/new/showpicture.tpl new file mode 100644 index 0000000..b97f373 --- /dev/null +++ b/templates/new/showpicture.tpl @@ -0,0 +1,30 @@ +
+
+ { $MENU } +
+ + +
+ + + + + + + { $PICTUREINFO } + + + + +
+ IMG { $NUMBER } of { $TOTAL } { $EXIFVALUES }

+ * Image { $NUMBER }

+[ Size: { $SIZES } | Slideshow: { $SLIDESHOW } ]
+ +
+
+
diff --git a/templates/new/slideshowisoff.tpl b/templates/new/slideshowisoff.tpl new file mode 100644 index 0000000..ce76936 --- /dev/null +++ b/templates/new/slideshowisoff.tpl @@ -0,0 +1 @@ +Off diff --git a/templates/new/slideshowoff.tpl b/templates/new/slideshowoff.tpl new file mode 100644 index 0000000..3c03d57 --- /dev/null +++ b/templates/new/slideshowoff.tpl @@ -0,0 +1 @@ +Off