DAlbum 1.43 build 173

This is a printable version of the document. Original contents is available at www.delx.ca/dalbum

Table of contents

DAlbum

DAlbum is a free PHP photo album. It is small, easy to install and highly customizable at the same time. Features include slide shows, image comments, support for video and PDF files and many more.

DAlbum screenshot

See DAlbum demos:

To access administration user interface, login as user admin with password admin. Please note that your changes will be ignored in demo mode.

[ Top ]

News

8 Feb 2010. DAlbum development has been suspended

It is been years since the last update.

Lately the support forum was used by bots to send spam through private messages to the registered users. I am really sorry for the inconveniences this may have caused, and the forum is now completely disabled.

I'm still continuing to use DAlbum for my personal photo page, and with 10000+ images it manages just fine and does all I need from an online photo album.

The only new thing recently developed is a new add-on to play Flash movies, that will be available shortly. However, it is highly unlikely that there will be DAlbum 2.0. Many things have changed in the Internet since 2003, and there are many great and free web albums and CMS systems to choose from now.

Thank you very much.

16 Aug 2006

1.42 build 155. There have been many changes since 1.38, some of which include:

25 Jan 2005

1.38 build 143. The issue with Firefox incorrectly displaying DAlbum index page is (hopefully) fixed.

14 Aug 2004

1.38 build 130. Another bug fix release but there are few new features this time.

26 Jul 2004

1.37 build 127. This is mainly a bug-fix release. I have finally reinstalled PHP and my (fairly complex) DAlbum release engine, so new updates will be more frequent now.

14 Dec 2003

29 Nov 2003

22 Nov 2003

9 Nov 2003

1 Nov 2003

[ Top ]

Features

DAlbum is a personal photo album. It was designed to provide an easy and secure way to share pictures with friends and family.

The script itself includes only basic functionality for the sake of code size and simplicity. It can be easily extended with required features or embedded into an existing web-site.

It's easy to view pictures:

It's easy to install and configure:

It's easy to upload images:

Finally, it's scalable, customizable and secure:

[ Top ]

System requirements

Server

Client

[ Top ]

Installation

[ Top ]

New installation

To install DAlbum and upload digital pictures you need:

  1. Web-space. Check links for some cheap or even free options.
  2. FTP client software. Check links if you don't have any installed.

When you have your web-site and FTP client up and running, follow the next 10 steps:

  1. Download DAlbum 1.43 build 173 from dalbum143_173.zip (180kb) or dalbum143_173.tar.gz.
  2. Create a directory on your web-site. The following assumes that the created directory is /photo inside your web-root.
  3. Extract dalbum143_173.zip file into your /photo directory. The following directory structure will be created:
    Warning: Many FTP clients do not display files and directories starting with dot (like .private) by default. Please check your FTP client settings. If you can't find the setting search for show hidden files [Your FTP Client Name] for instructions.
  4. Adjust access rights so PHP has write access to /photo/.private and /photo/pictures. On *nix with PHP running as nobody, chmod these directories to 0777.
  5. Connect to www.mysite.com/photo/index.php , click 'Log in' and login as user admin with password admin.
  6. Follow 'Reindex' link to reindex you photo album. Wait a few seconds until initial reindexing is completed.
  7. Return to the main page, you should be able to see a test picture there.
  8. If the test picture did not appear please check Troubleshooting section.
  9. Change admin password in user manager (to start user manager follow 'Users' link on the main page).
  10. Upload your digital pictures to /photo/pictures and reindex again.

If you're not satisfied with default configuration settings, please check Configuration and customization section to find out how to change DAlbum settings and modify its appearance.

Or just start editing ./config/config.php if you don't feel like reading now.

You may also consider installing Bonus Pack 1 to add slide show, video and other features.

[ Top ]

Upgrade

DAlbum was specially designed to be easily updatable to newer versions. When only configuration files are customized and the other installation files are not modified, upgrading DAlbum is very fast and easy.

Upgrade can be done either automatically or manually.

Manual upgrade

To upgrade your installation manually, download a special update only distribution which does not contain any configuration files and extract it into DAlbum folder. That's all.

Automatic upgrade

If you have DAlbum 1.20 or later installed, you can upgrade DAlbum automatically:

  1. Download and extract DAlbum update utility (Win32, 110Kb) to your harddrive.
    Do not run the utility directly out of the updalbum.zip file!
  2. Run the utility, press Add button and add your DAlbum FTP site to the list.
  3. Select sites to be updated and press Update button. You can select more than one site at once.
  4. Press 'Update' button. Update utility will automatically connect to www.delx.ca/dalbum and download the latest DAlbum build. If your site is running an older version it will be updated automatically. Your configuration files will remain untouched.

Note: The update utility provided does NOT send ANY personal information to delx.ca site. Only version.txt and dalbum.cab are downloaded using HTTP protocol. If still in doubt, download the source code here (it's quick&dirty, mind you :) ).

Upgrade notes

Upgrading to 1.30-1.31 to 1.32

In 1.32 configuration files are moved to a separate folder ./config. DAlbum still will be able to locate your configuration in ./include directory, but it is recommended to move them into ./config manually.

If you would like to use "fit-to-window" image resizing on your site, please update your t_showimg.php file from the 1.32 distribution or from here. This updated template contains several important fixes.

Upgrading 1.06-1.22 to 1.3

When manually upgrading to version 1.3, you will need to create two new template files: include/t_index.php and include/t_showimg.php. You can download just these two templates from here.

Upgrading 1.01-1.06

Upgrade is not supported for DAlbum 1.06 and earlier - too many changes and new files have been added since. Do complete reinstall in this case.

[ Top ]

Troubleshooting

So it does not work? It will. So far no PHP 4.1+ server has been found where DAlbum could not have been started eventually. Chances are good that problem can be solved even without calling your ISP.

First of all download test.zip and extract test.php from it to DAlbum installation directory. Run the file. Several tests will be performed and the produced detailed error report helps to identify the most common configuration and permission problems. Read the error messages - they might give you a clue. Very often there is a problem with permissions or invalid configuration.

Few additional recommendations:

If you have been unable to fix the problem yourself, ask in DAlbum forum. Try to search for an existing answer first. Please give a detailed report. URL of your problem site and test.php output would be useful too.

[ Top ]

Download

DAlbum installation
dalbum143_173.zip (217.9KB)
dalbum143_173.tar.gz (161.8KB)
Full DAlbum installation package (see New Installation)
dalbum143_173_upd.zip (168.2KB)
dalbum143_173_upd.tar.gz (119KB)
Package without configuration files to update existing installations (see Upgrade)
Old versions
dalbum134_89.zip (0 bytes)Version 1.34 build 89. Full package
Documentation
dalbum_docs.zip (11.5KB)
dalbum_docs.tar.gz (6.2KB)
Printable version of this site archived.
Additional files
test.zip (28KB)
test.tar.gz (28KB)
DAlbum test script (see Troubleshooting)
templates.zip (2.9KB)
templates.tar.gz (2KB)
Default t_showimg.php and t_index.php page templates (required to upgrade DAlbum to version 1.30+ from earlier versions.)
rsnetpbm.zip (682 bytes)
rsnetpbm.tar.gz (666 bytes)
Perl script for NetPBM support in DAlbum (see FAQ)
Utilities
updalbum.zip (112.2KB)DAlbum automatic update utility (see Upgrade)
Additional stylesheets
all24css.zip (85.4KB)24 DAlbum stylesheets ( created by mrbass [at] mrbass [dot] org )
Patched DAlbum templates
slideshow.zip (7.6KB)
slideshow.tar.gz (6.6KB)
Page templates with slide show capabilities (see Slide show)
comments.zip (7.2KB)
comments.tar.gz (6.2KB)
Page templates with image comments capabilities (see Image comments)
exifline.zip (1.8KB)
exifline.tar.gz (1.5KB)
exifline.php file for Display EXIF line sample.
customimg.zip (31.3KB)
customimg.tar.gz (13.6KB)
A set of code snippets and graphics files with custom folder graphics. (see Modify folder thumbnail graphics for details)
customtypes.zip (68.5KB)
customtypes.tar.gz (64.9KB)
Page templates with support for additional file types. (see Add video support for details)
nuke.zip (8.4KB)
nuke.tar.gz (5.2KB)
PHP-Nuke module (see PHP-Nuke for details)
bonus1.zip (88.5KB)
bonus1.tar.gz (77.8KB)
Bonus pack 1. Page templates with built-in additional file types support, slide show and EXIF line
[ Top ]

Configuration

Before you begin playing with configuration it might be worth checking some of the following topics:

[ Top ]

Basics

File manager user interface

DAlbum user interface and model of operation was copied from a file manager. There is a tree of directories on the left, and thumbnails displayed on the right.

This similarity goes beyound user interface. DAlbum expects images to be stored as you probably have them already - in a system of nested directories and subdirectories.

For example:

Serving images

Album users have access to only two DAlbum pages. The first page is index page with tree view and thumbnails. The second page is displayed when user clicks on the thumbnail and shows a large version of the image.

Every image is stored in DAlbum in maximum three different sizes:

Resized image is not created if the Original is small enough (i.e. smaller than 800x600 by default). Thumbnail is created even if the Original is smaller than thumbnail size.

Images are resized in advance by album reindexing procedure. Resampling of an average 3 Megapixel image requires up to 2 seconds on PentiumIV-1.5MHz so it would not be possible to do it "on fly".

Sorting images and directories

Exactly as many file managers do, DAlbum orders images and directories in alphabetical order of their filenames. This way images produced by modern digital cameras as "IMG_0001","IMG_0002" are sorted automatically. Things get worse with custom filenames. In the example above album "Birthday 2003" is displayed above "Christmas 2002" although chronologically it must be vice versa.

Solution is obvious - either a new level of subdirectories is produced:

Or a date is added before the folder name:

Please note that only filenames will have the leading digits - it is possible to change album and image titles aftewards to produce a tree as follows:

Leading digits can also be removed automatically by using a method described in FAQ.

Another suggestion is not to use spaces and special characters in names of files and directories as these names will be used in a page url.

For example, if a directory is named "2002-Christmas-2002", the produced URL to it would be http://www.mysite.com/index.php?folder=2003-Christmas-2002. It certainly looks better than the URL for "2002 Christmas 2002" - http://www.mysite.com/index.php?folder=2002%20Christmas2%202002.

[ Top ]

What does reindexing do?

When you press 'Reindex' button on the index page, DAlbum scans all subdirectories of  /photo/pictures for .JPG, .GIF and .PNG image files.

For every found image DAlbum creates a thumbnail in _thm subdirectory, and a resized version of the image in _res subdirectory.

For example /photo/pictures/2003/Birthday directory contains 2048x1536px img001.jpg:

DAlbum creates a 128x128 thumbnail (resolution is configured in config.php) of the image as _thm/thm_img001.jpg and 800x600 resized version as _res/res_img001.jpg:

In addition to that, a skeleton of album definition file .albumdef.ini is created in every directory. This file contains various information - album name, comments, access-control directives and titles of individual images.

Convenient web-interface is provided for editing .albumdef.ini files, but you can modify it with any text editor. Please note that after making changes with an external editor you need to reindex the album manually for your settings to apply. Changes made through web-interface apply immediately.

Example of .albumdef.ini:

[Album]
; Album title, date and comments.
Title=Baby Shower party
Date=Jun 2003
Comment=
CommentHTML=This was my <b>Baby Shower</b>party

; Title image specifies album image that will be shown as album thumbnail.
; First image is default if not specified
TitleImage=pic1.jpg

; Default=1 - show this album when DAlbum is started
Default=0

; Access control - comma-separated user list or 'valid-user' for "any user"
; Empty string or 'all' allows anonymous access
Access=valid-user

; --------------- Album files --------------------------
[pic1.jpg]
Title=This is picture1
Comment=This is plain-text comment
CommentHTML=

[pic2.jpg]
Title= This is picture2
Comment=
CommentHTML=<b>HTML</b> comments are <strike>cool</strike>

You can use multi-line parameters (useful for comments) by terminating the line with "\" character. For example:

CommentHTML=\
This was my <b>Baby Shower</b>party<BR>\
This is the second line!

After reindexing, a file /photo/.private/.album_index.dat is created. This file contains photo album structure and is used every time the album tree is displayed. When album folder is renamed or other big change occurs, reindex should be done again to update this directory structure file.

In addition to /photo/.private/.album_index.dat file, a special .album_hash.dat hidden file is created in every _thm directory. This file is used to detect possible changes made to album original images and regenate corresponging thumbnails.

Notes:

  1. Files and directories starting with _ or with . are skipped by reindexing process.
  2. Thumbnails and resized images are created only if they do not exist or if the size of original image has changed. There are three possible ways to regenerate already existing thumbnails:
  3. By default resized image size is set to 50000x600. In other words, no resized image can exceed 600 pixels in height but is practically unlimited in width. This was made on purpose to support panoramic images.
  4. GIF and PNG files are not resized by default. If you need to display a map or screenshot in your album that should not be resized to preserve image quality - put it in GIF or PNG format. It is also possible to change this setting individually for each picture in .albumdef.ini file by adding Resize=1 or Resize=0 variable to the file section.
[ Top ]

Access control

Configuring access control

In default configuration anonymous access is allowed to all images and there is an administrator who can do album reindexing and/or change .albumdef.ini files. It is possible to change this configuration of course.

For example, there are three users:

and four albums:

In order to add users, login as admin (default password is admin) and proceed to user manager by clicking "Users" button. Alternatively you can manually edit the users file as described in notes below.

Then you need to modify .albumdef.ini files. Login as admin and use 'Edit' link next to the album title to open the file. Set Allowed users: field in every album as follows:

Album Allowed users:
Tremblant all
Private admin
Drinking party valid-user
Family only admin, family

After making these changes, reindex your photo album.

Note:

  1. Access control is cumulative. For example, if you have folder MyFolder accessible only to user admin, and allow anonymous access to MyFolder/SubFolder, only admin will be able to access MyFolder/SubFolder anyway.
  2. User list is contained in /photo/private/.htpasswd file. In order to modify the file you need a htpasswd command-line utility which is a part of Apache web-server. If you don't have the utility, download Win32 binary from http://users.tibus.com/support/passwd.php

Multiple administrator accounts

By default only user admin has access to album reindexing. You can change your administrators by editing config.php

$g_sAdminUsers=array("admin","friend");

Having multiple administrators can be useful if you decide to share web-space between several users. For example, user friend can create his own albums under /pictures/friend directory and user family under /pictures/family. DAlbum by itself does not contain any code to handle image upload, but you can setup FTP permissions accordingly or use Comet WebFileManager.

Please note than only first administrator has access to the user manager. The other administrators are allowed to reindex only.

Access control modes

DAlbum can authenticate users in two modes: session mode and Basic HTTP Authentication.

Session mode (default) is used when $g_bHTTPAuth is set to false in config.php. In this case users are authenticated by using a custom logon page, which will set a session cookie to authenticate a user. The good thing is that session mode works on any web-server and any PHP configuration (CGI or Apache module), and there is a nice "Log out" button. However, this mode is slower than "Basic HTTP Authentication" and does not work with browser cookies disabled.

Basic HTTP Authentication  is used when $g_bHTTPAuth is set to true in config.php. This mode currently requires Apache web server and PHP installed as Apache module. In this case users are authenticated by Apache automatically according to .htaccess files which are created by DAlbum during reindexing, and standard "Enter your password" dialog is used instead of the custom page. This method is slightly faster than the first one and works well if cookies are disabled. The drawback is that it is not possible to log out without restarting the browser.

URL login in Session mode

Starting version 1.38 it is possible to login a user from the URL with username and password separated with colon: www.delx.ca/dalbum/sample/index.php?login=user:user. Very convenient for sending links by e-mail.

Another new feature is that you can add "temporary" users who do not need a password, but are allowed to view explicitly allowed albums only.

For example, you want to send a link to DAlbum sample album "Tremblant" to a friend, but don't want to create a special user for him or to allow him to see your other personal pictures.

Now it is possible to set album access list to "user,-tremblant2222" and hurrah! - a link www.delx.ca/dalbum/sample/index.php?login=-tremblant2222 will give access to the album, and, more good news, automatically direct the user to the album "Tremblant".

Should it become necessary to revoke this url - remove "-tremblant2222" from the access list and that's it!

[ Top ]

Securing DAlbum installation

Secure DAlbum installation ensures that:

Contents:

How DAlbum creates links to images

An image pictures/folder1/test.jpg can be accessed by client browser in two ways:

This behavior is configured by $g_bDirectAccess variable in config.php.

Indirect links

When $g_bDirectAccess is set to false (default setting), all images are returned indirectly through PHP script photo.php. photo.php verifies that user has appropriate access rights to view the image and, if all is fine, returns it to client browser.

The obvious drawback of this method is that PHP script is executed every time an image is downloaded and security check is performed even if the image is publicly available.

The benefit is flexibility - DAlbum script has control of every image download and may deny access if a certain condition is true. This can be used to prevent direct linking as will be discussed in FAQ.

Another benefit of indirect linking is that images can be stored outside of your web root location. For example, if the web root is /var/www/html, images can be stored in /home/john and be accessible.

Direct links

When $g_bDirectAccess is set to true, all public images are returned with direct links and DAlbum does not get control when an image is downloaded. Private images (which are available only to authenticated users) are still returned with indirect links to enable permission check. However, when Basic HTTP Authentication is enabled, private image paths are also returned as direct links - it's up to Apache to verify access rights in this case.

Direct linking is fast: images are served by web server without calling PHP. Flexibility suffers a little as image files must be kept inside web root. Script also must know how to translate a filename (/photo/folder1/test.jpg) to a URL visible from outside (www.mysite.com/something/photo/filder1/test.jpg). This is achieved by setting $g_sAlbumsRootBrowser variable.

For example, there is a shared hosting and

From browser this pictures directory would be accessible as www.mysite.com/users/john/pictures. To let DAlbum correctly translate filename to browser URL, $g_sAlbumsRootBrowser must be set as follows:

$g_sAlbumsRootBrowser="/users/john/pictures";

This way an image /home/users/john/pictures/folder1/test.jpg will be linked as www.mysite.com/users/john/pictures/folder1/test.jpg and successfully displayed in client browser.

Securing DAlbum installation on Apache

When Apache web-server is used, DAlbum installation is relatively secure right after it is unpacked. Access security is achieved via set of .htaccess files.

The main .htaccess file located in the installation directory disables access to files starting with a dot:

Satisfy All

<Files ~ "^\.">
order allow,deny
allow from all
deny from all
</Files>

Files in .private folder contain only files starting with a dot and thus cannot not be accessed. Additional .htaccess in ./config blocks all access to this directory, and files from ./include do not contain any sensitive information nor can be used to hack the script.

The only directory that requires additional protection is ./pictures and its subdirectories. To prevent unauthorized access to private images, DAlbum reindex automatically creates .htaccess in all private folders.

Format of this .htaccess file depends on $g_sPrivateDir directory setting. If $g_sPrivateDir starts with a dot and thus contains a relative path, DAlbum creates a simple .htaccess file that blocks all HTTP access to the folder.

When$g_sPrivateDir contains absolute path, basic HTTP authentication can be used to access the image.

For example, DAlbum samples contain protected album "Tremblant" which can be accessed only by users user and admin.

$g_sPrivateDir is set to absolute path:

$g_sPrivateDir="/var/html/sample/pictures/.private";

A special variable $g_sSiteRootDir may also be required on virtual hosts to specify URL prefix from Apache perspective. In my particular hosting case the setting is:

$g_sSiteRootDir="/home/virtual/site221/fst";

but it will be different on your host, check already existing .htaccess files, Apache logs or contact your ISP to obtain this information. Quite likely your host will be satisfied with the default value which is an empty string.

Generated .htaccess file for "Tremblant" folder looks as follows:

AuthName "Photo Album"
AuthType Basic
AuthUserFile /home/virtual/site221/fst/var/html/dalbum/sample/.private/.htpasswd
Satisfy All

<Limit GET POST>
require user admin user
</Limit>
<Limit PUT DELETE>
order deny,allow
deny from all
</Limit>
<Files .albumdef.ini>
order allow,deny
deny from all
</Files>

In other words, DAlbum .htpasswd file is used for authentication by Apache and access is only granted to admin and user. You may verify it by connecting to http://www.delx.ca/dalbum/sample/pictures/Mountains/Tremblant/_res/res_IMG_2879.JPG . The username/password is user/user or admin/admin.

Basic HTTP authentication

Basic HTTP authentication can only be used if PHP is installed as Apache module on Apache web server. It cannot be used with Microsoft IIS, or if PHP is running as CGI (most ISPs have PHP installed as CGI for security reasons).

In this case there are no Login/Logoff pages any longer and standard browser "Enter password" dialog is used instead:

It speeds up the server considerably: Apache does authentication and permission checks much faster than interpreted PHP script.

Before enabling basic HTTP authentication, specify $g_sPrivateDir as absolute path, reindex and verify on one of your private albums that correct .htaccess files are created.

Then edit config.php and set:

$g_bDirectAccess=true;
...
$g_bHTTPAuth=true;

Basic HTTP authentication and PHP CGI

If all images in your album are password protected, basic HTTP authentication can be used even with PHP in CGI mode.

In order to use it follow instructions in Basic HTTP authentication and create the following .htaccess file in DAlbum root directory:

AuthName "Photo Album"
AuthType Basic
AuthUserFile /var/html/dalbum/sample/.private/.htpasswd
Satisfy All
require valid-user

<Files ~ "^\.">
order allow,deny
allow from all
deny from all
</Files>

First four lines should be taken from .htaccess files inside ./pictures directory. It is very important that AuthName and AuthUserFile are identical in all .htaccess files. AuthName for .htaccess DAlbum creates is configured in $g_sAuthName variable in config.php.

Note that username/password will be required at all times to access pictures and no anonymous access is allowed.

Securing DAlbum on Microsoft IIS

As MicrosoftIIS ignores all .htaccess files supplied with DAlbum, you need to secure your installation manually. Go to Properties of the following DAlbum subdirectories:

and disable Read, Write and Directory browsing:

As DAlbum cannot change access control rights to directories with .htaccess files and cannot share .htpasswd file with IIS, it is best to keep direct access to images switched off in config.php (these are default settings):

$g_bDirectAccess=false;
...
$g_bHTTPAuth=false;

 

[ Top ]

Uploading images

FTP

DAlbum by itself does not contain any image uploading code. In my opinion, FTP is much better suited for handling multiple uploads than any web-interface: it is faster, easier to use, allows multiple upload threads etc. When there are 100 pictures to upload, there is no other choice but FTP.

It is also questionable whether FTP is too complex for an average user. An average user typing ftp://user:pass@ftp.myserver.com in Microsoft Internet Explorer receives friendly and relatively convenient file management interface. Drag&drop can be used to move files back and forth often without realizing that upload/download is being done. Nothing new really: no web interfaces with their limitations, no security problems with PHP and file ownership etc.

PHP file managers

When FTP is not an option, a separate PHP file manager can be installed. One of the following is recommended (all are free):

You may also try searching Google or HotScripts for other file manager scripts, but the bulk majority of the free ones (I tried about 20 of them) are either too simple, or do not work, or look ugly, or require register_globals to be on, or are dangerously insecure etc. Perhaps I was not lucky enough.

In future there also will be DAlbum PHP file manager extension (available as separate download) that will respect DAlbum permission settings and color schemes.

Adding upload button

So the following assumes that either you have decided to allow users to use FTP, or have one of the PHP file managers in place.

Now you need to add 'Upload' button to the DAlbum toolbar when DAlbum is in admin mode.

The recommended solution would be to edit config/custom.php, uncomment customGetButton function and change it as follows:

 function customGetButton($id$href$text$title$nSpacer$target)
{
    
$ret=getButton($id,$href,$text,$title,$nSpacer,$target,false);;

    if (
$id=='reindex')
    {
        
// change here!
       
$uploadURL="ftp://user:password@ftp.mysite.com/public_html/photo/pictures";
        
// Add 'Upload' button after reindex
        
$ret.=getButton('upload',"$uploadURL","Upload","Upload files",2,"_new",false);
    }
    return 
$ret;
}

Change $uploadURL to point to your PHP file manager or FTP location.

[ Top ]

Configuration files

DAlbum is a relatively small and flexible script, and can be easily tailored to suit your needs. All you need to do is to edit a few configuration files.

So far there is no web-interface provided for changing these files, so please use your favorite text editor.

DAlbum configuration consists of four separate files:

There is also fifth configuration file custom.css which resides in the main directory. This file contains your custom styles and is included into all produced pages after the main stylesheet (which is configured in /config/config.php). This is useful when you're happy with one of the supplied templates but need to tweak a few colors.

It is a good idea not to modify any code beyond these configuration files. This way upgrades can be done easily or almost automatically (with the utility provided). It does not limit your freedom much. This site, for example, is also running DAlbum and only configuration files were changed - everything else was left intact.

[ Top ]

Customization

This section provides a number of DAlbum customizations and information how to add your own ones.

Usually no PHP knowledge is required to use the samples listed, but some basic programming experience would be very helpful.

[ Top ]

Allow users to add comments

The purpose of this sample is to demonstrate how to add simple image commenting system to your album. Number of image comments is displayed on the index page.

Administrator can see IP addresses of comment senders and delete unwanted messages. As comments are stored in a simple text files one line per comment, administration can also be done with a text editor over FTP.

Depending on configuration anonymous users may not be allowed to post comments or even view comments at all. Administrator may be notified by e-mail when a new comment is posted.

Please check demo for an example.

Comments are stored in .cmt files next to original album images. For example, comments for /photo/album1/picture1.jpg are stored in /photo/album1/picture1.cmt.

Instructions

If you don't feel like patching configuration files yourself, download and install already patched set of templates from comments.zip.

1. Edit your t_showimg.php page template and insert the following code snippet at the beginning of the file (after the title comments:)
  <?php
    
////////////// Image Comments customization 1 of 2 begins ///////////////
    
include(DALBUM_ROOT "/config/comments.php");

    
$nCommentsAuth=1/*   0=all users can view and post messages,
                           1=all users can view, but only authenticated can post
                           2=anonymous users do not see any comments */

    
$sAdminEmail="";  /* Put admin e-mail here. Ex. john@hotmail.com */
    
$sFromEmail="DAlbum <dalbum@mysite.com>";

     if (
DAlbum_Comments_Plugin_Send(    $nCommentsAuth,
                                        
$sAdminEmail,
                                        
$sFromEmail ))
    {
        
header("Location: " base64_decode(encodeCurrentLocation()));
        return;
    }
    
////////////// Image Comments customization 1 of 2 ends ///////////////
?>

Modify configuration variables appropriately.

Then insert the following piece of code just before '<!-- Row 3: copyright -->' line:

  <?php
////////////// Image Comments customization 2 of 2 begins ///////////////
DAlbum_Comments_Plugin_Display($nCommentsAuth);
////////////// Image Comments customization 2 of 2 ends ///////////////
?>

2. Edit your custom.php and find and uncomment customTitle function. Replace its body with the following code snippet:

 function customTitle(&$object$titleDefault)
{
    
$ret=$titleDefault;

    if (
$object->IsImage())
    {
        
$imagefname=absfname($object->m_sFullFilename);
        
$textfname=dirname_ex($imagefname) . "/" getfname($imagefname) . ".cmt";

        
$cnt=0;
        if (
file_exists($textfname))
        {
            
$f=@safe_read_file($textfname);
            foreach (
$f as $line)
                if (
strlen(trim($line)))
                    
$cnt++;
        }
        if (
$cnt)
            
$ret="<span class='imageTitle'>" $object->GetTitle() .
                 
"&nbsp;($cnt&nbsp;comments)</span>";
    }

    return 
$ret;
}

3. Edit your custom.css and append the following lines to the file:

  .imagecommentsRow
{
    /* Uncomment the next line for main_blue.css */
    /* background-color: #444444; */

    /* Uncomment the next line for main_cyan.css */
    /* background-color: #CCDDFF; */
}
table.imagecomments
{
    margin-top: 20px;
    font-size: 80%;
    border-top: 2px solid black;

    /* Uncomment the next line for main_cyan.css */
    /* color: black; */
}

table.imagecomments th
{
    padding: 10px;
}

table.imagecomments td.imagecomment
{
    border-top: 1px dashed black;
}

table.imagecomments td.imagecommentform
{
    border-top: 1px dashed black;
}

table.imagecomments td.imagecommentform table
{
    font-size: 100%;
}

You may need to adjust colors in this snippet to match your color scheme.

4. Create comments.php file in ./config directory and paste the following text:
  <?php

if (!defined('DALBUM_ROOT')) die("Security violation!");

// localization strings have been added to distribution already
/*
$lang['cCommentsImageComments']="Image comments";
$lang['cCommentsLoginToAddComments']='Please #loginbutton# to add your comments.<BR>&nbsp;';
$lang['cCommentsYourName']='Your name:';
$lang['cCommentsComment']='Comment:';
$lang['cCommentsSendButtonText']='Send';
$lang['cCommentsDeleteButtonText']='Delete';
$lang['cCommentsMailSubject']="New comment about image #image# ( Album: #album# )";
$lang['cCommentsMailBody']   ="New comment posted by #user#, IP: #ip#,".
                              "DNS: #dns#\n\n#body#\n\nPage URL: #url#\n";
$lang['cCommentsDateFormat'] ="F j, Y, g:i a";
*/

function DAlbum_Comments_Plugin_Send(   $nCommentsAuth,
                                        
$sAdminMail,
                                        
$sFromLine )
{
    global 
$lang,$sUserName,$image,$bAdminMode,$album;
    
//
    
$bShowComments=($nCommentsAuth<|| !empty($sUserName));
    
$bShowForm=($nCommentsAuth==|| !empty($sUserName));
    
$bShowLogin=($nCommentsAuth==&& empty($sUserName));

    if (!
$bShowComments || !$bShowForm)
        return 
false;

    
// $image variable is set to displayed image
    
$imagefname=absfname($image->m_sFullFilename);
    
$textfname=dirname_ex($imagefname) . "/" getfname($imagefname) . ".cmt";

    
// Add new comments
    
if (!isset($_POST['comment']))
        return 
false;

    
$arr=array();
    
$arr[]=$_POST['realname'];

    
// Add IP address
    
$ip=$_SERVER['REMOTE_ADDR'];
    if (@
$_SERVER["HTTP_X_FORWARDED_FOR"])
        
$ip=$_SERVER["HTTP_X_FORWARDED_FOR"];

    
$arr[]=$ip;

    
// Change to your preferred date format here
    
$arr[]=date($lang['cCommentsDateFormat']);

    
$body=trim($_POST['comment']);
    if (empty(
$body))
        return 
false;
    
$arr[]=$body;

    
// Notify admin by mail
    
if (!empty($sAdminMail))
    {
        
$dns=@gethostbyaddr($ip);

        
$subject strtr$lang['cCommentsMailSubject'], array(
                            
"#image#"=>$image->m_sBaseFilename,
                            
"#album#"=>$album->GetTitle() ));

        
$url="http://" $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']
                         . 
"?" . @$_SERVER['QUERY_STRING'];

        global 
$g_sCharset;

        if (
preg_match('/[^a-zA-Z0-9!@#$%&*()-{}]/',$subject))
            
$subject="=?$g_sCharset?B?".base64_encode($subject)."?=";
        else
            
$subject=$subject;


        
$headers="";
        if (!empty(
$sFromLine))
            
$headers="From: " $sFromLine."\n";

        
$headers.="Content-type: text/plain; charset=$g_sCharset\n";
        
$headers.="MIME-Version: 1.0\nX-Priority: 3 (Normal)\n";
        
$headers.="X-MSMail-Priority: Normal\n";
        
$headers.="X-Mailer: DAlbum\n";

        
$message strtr$lang['cCommentsMailBody'], array(
                            
'#user#'=>$arr[0],
                            
'#ip#'=>$arr[1],
                            
'#dns#'=>$dns,
                            
'#body#'=>$body,
                            
'#url#'=>$url));

        
mail($sAdminMail$subject$message$headers);
    }

    
// Cut very long strings and quote HTML
    
for ($i=0;$i<count($arr);++$i)
    {
        if (
strlen($arr[$i])>2000)
            
$arr[$i]=substr($arr[$i],0,2000)+"...";

        
$arr[$i]=str_replace("\n",'',nl2br(quotehtml($arr[$i])));
        
$arr[$i]=str_replace("",'',$arr[$i]);
    }

    
$handle=fopen($textfname,"at");
    if (
$handle)
    {
        
$line=join(":|:",$arr)."\n";
        @
fwrite($handle,$line);
        @
fclose($handle);

        global 
$g_newDirRights;
        @
chmod($textfname,$g_newDirRights);
    }
    return 
true;
}

function 
DAlbum_Comments_Plugin_Display($nCommentsAuth)
{
    global 
$lang,$sUserName,$image,$bAdminMode,$album;

    
//
    
$bShowComments=($nCommentsAuth<|| !empty($sUserName));
    
$bShowForm=($nCommentsAuth==|| !empty($sUserName));
    
$bShowLogin=($nCommentsAuth==&& empty($sUserName));

    if (
$bShowComments)
    {
        
// $image variable is set to displayed image
        
$imagefname=absfname($image->m_sFullFilename);
        
$textfnamedirname_ex($imagefname) . "/" .
                    
getfname($imagefname) . ".cmt";

        
//////////// Image comments header begins  ////////////
        
?>
            <!-- Image comments code begin -->
            <tr>
            <td align="center" class="imagecommentsRow">
            <table class="imagecomments">
            <tr><th><?php print $lang['cCommentsImageComments']; ?></th></tr>
<?php   //////////// Image comments header ends  ////////////

        // Display existing comments

        
if (file_exists($textfname))
        {
            
$file=safe_read_file($textfname);

            
$bChanged=false;
            
$hashDelete="";
            if (
$bAdminMode && isset($_POST['deleteComment']))
                
$hashDelete=$_POST['hashComment'];

            for (
$i=0;$i<count($file);++$i)
            {
                
$line=trim($file[$i]);
                if (empty(
$line))
                    continue;

                
$linehash=md5($line);

                
// If this line was marked to delete - make it empty
                
if (!empty($hashDelete) && $hashDelete==$linehash)
                {
                    
$file[$i]="";
                    
$hashDelete="";
                    
$bChanged=true;
                    continue;
                }

                
// Display found line
                
$arr=explode(":|:",$line);
                
$name=$arr[0];
                
$ip  =$arr[1];
                
$date=$arr[2];
                
$body=$arr[3];

                
// Comment line begin
                
print '<tr><td class="imagecomment">';
                print 
"<B>$name</B>&nbsp;&nbsp;";
                if (
$bAdminMode)
                    print 
" ( IP: {$ip} ) &nbsp;";
                print 
"- $date ";

                if (
$bAdminMode)
                {
                    print 
'<form action="" method="post" style="display:inline;">';
                    print 
'<input type="submit" name="deleteComment" value="';
                    print  
$lang['cCommentsDeleteButtonText'] . '">';
                    print 
'<input type="hidden" name="hashComment"   value="'
                            
$linehash .'">';
                    print 
'</form>';
                }
                print 
"<BR>"$body;

                print 
'</td></tr>';
            }

            
// Delete empty lines
            
if ($bAdminMode && isset($_POST['deleteComment']))
            {
                
$bPrev=@ignore_user_abort(true);
                for (
$i=0;$i<count($file);++$i)
                {
                    
$handle=fopen($textfname,"wt");
                    if (
$handle)
                    {
                        foreach (
$file as $line)
                        {
                            if (!empty(
$line))
                                
fwrite($handle,trim($line)."\n");
                        }
                        
fclose($handle);

                        global 
$g_newDirRights;
                        @
chmod($textfname,$g_newDirRights);
                    }
                }
                @
ignore_user_abort($bPrev);
            }
        }
    }

    if (
$bShowLogin)
    {
        global 
$lang;
        
$loginCode=getButton('login',translateRef("login.php?url=" encodeCurrentLocation()),
                            
$lang['loginBtn'],$lang['loginBtnTitle'],0);
        
// Let the user know that he needs to login to post comments
?>
        <tr><td class="imagecomment">
        <?php print strtr($lang['cCommentsLoginToAddComments'],
                            array(
"#loginbutton#"=>$loginCode)); ?>
        </td></tr>
<?php  /////////////////////////////////////////////////////////
    
}

    if (
$bShowComments && $bShowForm)
    {
        
$sDefaultUserName="Anonymous";
        if (!empty(
$sUserName))
            
$sDefaultUserName=$sUserName;

        
////////////// "New comment" form begins //////////////
?>
<tr><td class="imagecommentform">
<form action="#commentsform" method="post">
<table cellpadding=2 cellspacing=2 border=0>
    <tr><td valign=top><a name="commentsform"></a>
        <?php print $lang['cCommentsYourName']; ?></td>
        <td valign=top>
            <input type="text" name="realname"
                   size=80 value="<?php print $sDefaultUserName?>">
        </td>
    </tr>
    <tr>
        <td valign=top><?php print $lang['cCommentsComment']; ?></td>
        <td valign=top>
            <textarea name="comment" rows=4 cols=60></textarea>
        </td>
    </tr>
    <tr>
        <td colspan=2 align=right>
            <input type="submit" value="<?php print $lang['cCommentsSendButtonText']; ?>">
        </td>
    </tr>
</table>
</form>
</td></tr>
<?php //////////// "new comment" form ends  ////////////
    
}


    if (
$nCommentsAuth<|| !empty($sUserName))
    {
        
//////////// Display footer  ////////////
?>
</table>
</td>
</tr>
<!-- Image comments end -->
<?php //////////// Footer ends ////////////
}?>

5. Secure your installation so it is not possible to download image comments file by using a URL like www.mysite.com/photo/pictures/pic1.cmt

If you're running Apache, edit .htaccess file located in DAlbum directory and append the following lines:

<Files ~ ".cmt$">
order allow,deny
deny from all
</Files>

Most likely you do not need to do anything for Microsoft IIS as no registered MIME type correspond to .cmt extension by default.

6. That's all. Modify the code above as needed.

[ Top ]

Slide show

The purpose of this sample is add slide show capabilities with user-selected time interval.

Please check demo for an example.

If you don't feel like patching configuration files yourself, download and install already patched set of templates from here.

Instructions

1. Edit your t_showimg.php page template and replace the line

  <body class="nomargins" onload="javascript: dalbum_onload();" >

with

  <body class="nomargins" onload="javascript: dalbum_onload();_slideshow();" >

2. Go to the end of t_showimg.php page template and insert the following code snippet before the last '//-->':

      <!-- Begin slideshow code -->
    function _slideshow()
    {
<?php     $nSlideShow=0;
        if (isset(
$_GET['slideshow']))
            
$nSlideShow=$_GET['slideshow'];
        if (
$nSlideShow>0)
        {
            
// Change 5 here to minimal allowed interval in seconds
            
if ($nSlideShow<5)
                
$nSlideShow=5;
            
$url=$next;
            if (empty(
$url))
            {
                
// !!! Uncomment the next line enable slide show looping
                // $url=$first;
            
}
            if (!empty(
$url))
            {
                
$delay=$nSlideShow*1000;
                
$url.="&slideshow=" $nSlideShow;
                print 
"window.setTimeout(\"window.location.replace('$url');\",$delay);";
            }
        }
?>
    }

    function onSlideshowChange(combo)
    {
        var u=window.location.href;
        var n=u.indexOf('&slideshow');
        if (n!=-1)
            u=u.substr(0,n);

        if (combo.selectedIndex>0)
            u+="&slideshow=" + combo.options[combo.selectedIndex].value;

        window.location.replace(u);
        return true;
    }
    <!-- End slideshow code -->

3. Edit your custom.php and find and uncomment customGetButton function. Replace its body with the following code snippet:

 // localization strings (may be added to standard distribution later)
if (!isset($lang['cSlideshowSlideshow']))
{
    
$lang['cSlideshowSlideshow']='-- Slide show --';
    
$lang['cSlideshowSeconds']  ='#sec# seconds';
}

function 
customGetButton($id$href$text$title$nSpacer$target)
{
    
$ret="";

    
// Display slideshow combo before 'fullscreen' button
    // and only on showimg.php page
    
if (($id=='fullscreen'||$id=='closewindow') && stristr($_SERVER['PHP_SELF'],"showimg"))
    {
        
// Add a little space before the combo
        
$ret '<span id="space_slideshow" class="buttonspace">&nbsp;&nbsp;&nbsp;</span>';

        
// Localize Slideshow: string here
        
$ret.= '<span class="slideshow">';
        
$ret.= '<form onsubmit="">';
        
$ret.= "<select onchange='onSlideshowChange(this);'>";

        
// Number of seconds/slide to be displayed in the combo-box.
        
$seconds=array(0,5,10,30,60);

        
$def=0;
        if (isset(
$_GET['slideshow']))
            
$def=$_GET['slideshow'];

        foreach (
$seconds as $s)
        {
            
$ret.="<option value=\"$s\"";
            if (
$s==$def)
                
$ret.=" selected";
            
$ret.=">";

            global 
$lang;
            if (
$s==0)
                
$ret.=$lang['cSlideshowSlideshow'];
            else
                
$ret.=strtr($lang['cSlideshowSeconds'],array("#sec#"=>$s));
            
$ret.="</option>";
        }
        
$ret.='</select></form>';
        
$ret.='</span>';

    }
    
// if we are in slideshow mode already - do not display "Fullscreen"
    
if ($id=='fullscreen' &&
        
stristr($_SERVER['PHP_SELF'],"showimg") &&
        isset(
$_GET['slideshow']))
        return 
$ret;

    
$ret.=getButton($id,$href,$text,$title,$nSpacer,$target,false);
    return 
$ret;
}

4. Edit your custom.css and append the following lines to the file:

  /* Add your custom styles here */

/* Add your custom styles here */
.slideshow form
{
    display: inline;
    vertical-align: middle;
}

.slideshow form select
{
/* You may want to uncomment code below and modify it to match to your stylesheet.

/* These settings are for main_normal.css. */
/*
    font-family:    Verdana, Arial, sans-serif;
    font-size:100%;
    color: black;
    background-color:    #E4E0D2;*/

/* These settings are for main_cyan.css */
/*
    font-family:    Verdana, Arial, sans-serif;
    font-size:100%;
    color: white;
    font-weight:     bold;
    background-color:   #064E80;
*/


/* These settings are for main_blue.css. */
/*
    font-weight:     bold;
    font-size:100%;
    color: white;
    background-color:#336699;
*/

/* These settings are for main_gray.css. */
/*
    font-family:    Tahoma, Verdana, Arial, sans-serif;
    color: #339;
    background-color:   #e6e6e6;
    font-size:100%;
*/
}

Edit the stylesheet above to uncomment or insert colors matching your stylesheet.

5. That's all. Modify the code above as needed.

[ Top ]

Display EXIF info line

The purpose of this sample is add a line with EXIF parameters (time, ISO, exposition time etc.) to the image page that will be displayed when "Show Details" mode is off.

Please check demo for an example.

Instructions

1. Edit your t_showimg.php page template and insert the following code in position where you want EXIF info to be diplayed.

  <div style="font-size:8pt;white-space:nowrap;text-align:center;">
    <?    include(DALBUM_ROOT "/config/exifline.php"); ?>
</div>

For example, to add it right below the image, insert it after image closing tag:

  <td >
    <a href="<?php template('ImageHref');?>">
    <img id="Image"
         src="<?php template('ImageSrc');?>"
         title="<?php template('ImageAlt');?>"
         <?php template('ImageWidthHeight'); ?>
         alt="">
    </a>

  <div style="font-size:8pt;white-space:nowrap;text-align:center;">
    <?    include(DALBUM_ROOT "/config/exifline.php"); ?>
</div>

  </td>

2. Create a file called exifline.php in ./config directory containing the following script (you can download the script from exifline.zip):

  <?php
//
// This module reads and prints exif details from current image
// if image details bar is not displayed (by Show Details button).
//
// Feel free to add, remove and rearrange parameters.
//
if ($image->IsImage() && // This will protect against direct include
    
!($bShowDetails && $g_bShowEXIFDetailsButton))
{
    
// Read EXIF
    
if ($g_bForceDAlbumEXIFCode || !extension_loaded('exif'))
    {
        require_once(
DALBUM_ROOT  "/include/exif.php");
        
$exif=@exif_php_read_data(absfname($image->m_sFullFilename));
    }
    else
    {
        
$exif=@exif_read_data(absfname($image->m_sFullFilename));
    }

    if (
$exif===false)
        
$exif=array();

    
$data=array();

    
// Resolution
    
if ($image->m_nX>&& $image->m_nY>0)
        
$data[]="|({$image->m_nX}x{$image->m_nY})";

    
// Date/time
    
$date="";
    if (isset(
$exif['DateTimeOriginal']))
        
$date=$exif['DateTimeOriginal'];
    if (empty(
$date) && isset($exif['DateTime']))
        
$date=$exif['DateTime'];

    if (!empty(
$date))
    {
        
$date=split(':',str_replace(' ',':',$date));
        
$date="{$date[0]}-{$date[1]}-{$date[2]} {$date[3]}:{$date[4]}:{$date[5]}";
        
$date=strftime($lang['cExiflineDateFormat'],strtotime($date));
        
$data[]="|$date";
    }

    
// ISO speed
    
$iso="";

    if (isset(
$exif['ISOSpeedRatings']))
        
$iso=$exif['ISOSpeedRatings'];
    else if (isset(
$exif['MakerNote']) && isset($exif['ModeArray']))
    {
        
// Add ISO for PowerShot cameras
        
switch (@$exif['ModeArray'][16])
        {
            case 
15$iso="auto";break;
            case 
16$iso="50";break;
            case 
17$iso="100";break;
            case 
18$iso="200";break;
            case 
19$iso="400";break;
        }
    }

    if (!empty(
$iso))
        
$data[]="{$lang['showExifISO']}|$iso";


    
// Exposure
    
if (isset($exif['ExposureTime']))
    {
        list(
$d1,$d2)=split('/',$exif['ExposureTime']);
        if (
$d1>&& $d2>0)
            
$e=$d1/$d2;
        else
            
$e=$exif['ExposureTime'];
        if (
$e<&& $e>0)
            
$e="1/" round(1/$e,0) . " s";
        else
            
$e=round($e,1) ." s";

        
$data[]=$lang['cExiflineExposure']."|".$e;
    }

    
// Aperture
    
if (isset($exif['COMPUTED']['ApertureFNumber']))
        
$data[]="{$lang['cExiflineAperture']}|{$exif['COMPUTED']['ApertureFNumber']}";

    
// Flash
    
if (isset($exif['Flash']))
    {
        
$e=$lang[($exif['Flash']&1)?'showExifFlashYes':'showExifFlashNo'];
        
$data[]="{$lang['cExiflineFlash']}|$e";
    }

    
// Combine all together into one line
    
$sExifDetails="";
    if (!empty(
$data))
    {
        foreach (
$data as $d)
        {
            list(
$name,$value)=split('\|',$d);
            if (!empty(
$sExifDetails))
                
$sExifDetails.="; ";
            
$sExifDetails.="$name$value";
        }
    }

    
// print the line
    
print $sExifDetails;
}
?>

3. Enjoy!

[ Top ]

Modify folder thumbnail graphics

The purpose of this sample is customize graphics displayed around image and folder thumbnails on index page.

By default a yellow folder image is displayed for album folders and no graphics displayed around image thumbnails. This can be completely and easily customized as described below.

Please check demo for an example. You also can download example set of graphics files and code snippets used in this demo.

Instructions

1. Create your own folder graphics in a graphics editor and split it into nine separate files:

Save these files as i_nw.gif,i_n.gif, i_ne.gif, ... , s_se.gif, blank.gif into a folder.

2. Edit you custom.php and add the customGetFolderBorders function. Modify locations and resolutions of the produced images accordingly.

 function customGetFolderBorders(&$album,&$fg,$nThmX,$nThmY)
{
   global 
$g_sThumbnailXSize,$g_sThumbnailYSize;

   
// Images in format array('URL',width,height);
   
$fg['blank']=array('custimg/bluef/bf_blank.gif',30,8);
   
$fg['nw']=array('custimg/bluef/bf_nw.gif',69,25);
   
$fg['n']=array('custimg/bluef/bf_n.gif',5,25);
   
$fg['ne']=array('custimg/bluef/bf_ne.gif',18,25);
   
$fg['w']=array('custimg/bluef/bf_w.gif',8,8);
   
$fg['e']=array('custimg/bluef/bf_e.gif',12,8);
   
$fg['sw']=array('custimg/bluef/bf_sw.gif',20,14);
   
$fg['s']=array('custimg/bluef/bf_s.gif',6,14);
   
$fg['se']=array('custimg/bluef/bf_se.gif',16,14);

   
// border around image (defined in CSS as a.fldlink .folderthumb)
   
$fg['borderx']=1;
   
$fg['bordery']=1;

   
// ensure that all folders have the same size
   
$fg['sizex']=$g_sThumbnailXSize+35;
   
$fg['sizey']=$g_sThumbnailYSize+35;

   
// return true to force DAlbum to use specified images
   
return true;
}

3. Edit your custom.css and add the following style:

  a.fldlink .folderthumb
{
    border: 1px inset #003366;
}

4. Folder thumbnail is completed! Image thumbnails can be created following the same procedure. The only difference is that function name at step 2 will be customGetImageBorders, and style name at step 3 - a.imglink .imagethumb.

[ Top ]

Add video support

The purpose of this sample is to demonstrate how to add support for non-image file types into DAlbum. In particular support for movies (AVI/MPG/Windows Media/QuickTime), audio (WAV,MP3,WMA) and PDF files is added. Support for ANY file type can be implemented by changing a few lines in ./config/customtypes.php.

Another interesting feature is custom fields (DAlbum 1.35+). Any album or image can be assigned a set of custom parameters which are stored in the .albumdef.ini file. These custom fields can be changed using web interface too.

This sample defines two custom fields: Width and Height for video files. They are mandatory for QuickTime movies and optional for AVI/MPG/Windows Media.

Please check demo site for a demonstration.

Instructions

1. Download already patched set of templates from customtypes.zip.

2. Edit your t_showimg.php page template, find the place where image is displayed and wrap it with the following lines:

  <?php if (!cCustom_DisplayCustomType($image)) { /*** customtypes sample ***/ ?>

... image code ...

  <?php }  /*** customtypes sample ***/ ?>

The result should look like follows:

  <table border="0" cellpadding="2" cellspacing="2" >
<tr id="imageWrap">
<?php if (isset($_template['ExifDetails'])) { ?>
        <td style='vertical-align: top'>
        <div class='imgDetails'>
<?php   template('ExifDetails'); ?>
        </div>
        </td>
<?php /* ExifDetails */ ?>

<td id="showimgImageCell">

  <?php if (!cCustom_DisplayCustomType($image)) { /*** customtypes sample ***/ ?>
      <a href="<?php template('ImageHref');?>">
    <img id="Image"
         src="<?php template('ImageSrc');?>"
         title="<?php template('ImageAlt');?>"
         <?php template('ImageWidthHeight'); ?>
         alt="">
    </a>

  <?php }  /*** customtypes sample ***/ ?>
  </td>
</tr>
</table>
</center>
</td></tr>

<!-- Row 3: copyright -->

2. Edit your custom.php and append the following code to the file:

 /*** customtypes sample begins ***/
require_once(DALBUM_ROOT "/config/customtypes.php");

function &
customCreateImage()
{
    return new 
CCustomTypeImage();
}
/*** customtypes sample ends ***/

3. [Optional] Edit your custom.css and append the following lines to the file:

  /* Draws a border around media player control
   The style below is suitable for main_blue.css color scheme.
*/
#MediaPlayer
{
    border: 4px #336699 solid;
    background-color: black;
    filter: progid:DXImageTransform.Microsoft.dropShadow(color='#222222', OffX='10', OffY='10')
            progid:DXImageTransform.Microsoft.BasicImage(enabled:false);
}

You may need to adjust colors in this snippet to match your color scheme. The given example is for main_blue.css stylesheet.

4. Extract ./config/customtypes.php file from the downloaded archive into your ./config directory.

5. Extract ./pictures/_icons/*.* files from the downloaded archive into _icons subfolder of your pictures directory.

6. That's all. Modify the code above as needed. To add additional file types edit ./config/customtypes.php file.

[ Top ]

Change tree icons

By default a yellow folder image is displayed for folders and a blue film icon is used for album icons. This sample demonstrates how album administrator can change tree icon for any album or folder.

For example this demo uses a special icon for Media folder.

This sample adds two custom fields to every album:

These custom fields can be set in album properties or .albumdef.ini file. The sample assumes that icon files are stored in subdirectory custimg of the main DAlbum directory.

Instructions

1. Edit you custom.php and add the following code. Modify icons location directory and other parameters as needed:

 class CExAlbumCustomIcon extends CAlbum
{
    function 
GetTreeNodeCode($myID,$nParentID,$sText,$sRef)
    {
        
$dir="custimg/";
        
$ic=$this->GetCustomField("Iconfile");
        
$icOpen=$this->GetCustomField("IconfileOpen");
        if (!empty(
$ic))
        {
            if (empty(
$icOpen))
                
$icOpen=$ic;

            
// You can change not only icon but also text, tooltip and target frame here
            // Format:
            //         d.add($myID,$nParentID,"Node text","Node URL","Tooltip","Target frame",
            //              "Closed icon", "Open icon (for folders only)");
            //
            
return "d.add($myID,$nParentID,'$sText','$sRef','','','$dir/$ic','$dir/$icOpen');\n";
        }
        return 
parent::GetTreeNodeCode($myID,$nParentID,$sText,$sRef);
    }

    
// Get list of custom field names
    
function &GetCustomFieldNames()
    {
        
$f=parent::GetCustomFieldNames();
        
$f[]="Iconfile";
        
$f[]="IconfileOpen";
        return 
$f;
    }
}

function &
customCreateAlbum()
{
    return new 
CExAlbumCustomIcon();
}

2. Reindex (you may also need to delete .private/.album_index.dat file). Now when you edit properties of any album now, set folder image icon. For example specify media.gif to display custimg/media.gif.

[ Top ]

Highlight recently modified albums

When an image gallery has several thousands images and a deep tree of folders, it may be difficult to find out what the latest changes are. This sample shows how mark new and updated albums in tree with an icon or text to make latest modifications immediately visible.

The code below adds two custom fields to every album: creation date and modification date. Creation date is set to today's date when .albumdef.ini is created. Modification date must be changed manually in album properties whenever the album is modified (it's just YYMMDD format): pictures added, important comment changes made etc. Modification date is automatically propagated up the folder tree during reindex. Folder with a new or modified subfolder gets its modification date set to the latest updated subfolder modification date.

CExAlbumModified::GetTreeNodeCode method verifies if current album has been modified during the last 10 days and displays new! text after album name for new albums and updated! - for updated albums. You can display different text or an image instead.

Instructions

1. Edit you custom.php and add the following code. Modify GetTreeNodeCode method to include preferred number of days and the method to mark modified albums.

 // Localize text strings below (these localizations will be added
// to DAlbum installation later)
if (!isset($lang['cModifiedNew']))
{
    
$lang['cModifiedNew']='new!';
    
$lang['cModifiedUpdated']='updated!';
}

class 
CExAlbumModified extends CAlbum
{
    function 
Create($sPath$parentUsers,$bCleanup$bDeleteImages=false)
    {
        
// New albums get modification time set to today's date
        
if (!file_exists(absfname($sPath."/.albumdef.ini")))
        {
            
$this->m_arrCustomFields["Modified_YYMMDD"]=
            
$this->m_arrCustomFields["Created_YYMMDD"]=date("ymd");
        }

        
// Call default implementation
        
return parent::Create($sPath,$parentUsers,$bCleanup,$bDeleteImages);
    }


    
// Get list of custom field names
    
function &GetCustomFieldNames()
    {
        
$f=parent::GetCustomFieldNames();
        
$f[]="Created_YYMMDD";
        
$f[]="Modified_YYMMDD";
        return 
$f;
    }

    
// Modify tree node text
    
function GetTreeNodeCode($myID,$nParentID,$sText,$sRef)
    {
        
// Display (Modified) or (Updated) for those modified/updated 10 days ago or less.
        // (change 10 to any number of days you wish)
        
$dateRecent=date("ymd",time()-86400*10);

        
$cur_ct=$this->GetCustomField("Created_YYMMDD");
        
$cur_mt=$this->GetCustomField("Modified_YYMMDD");

        global 
$lang;
        
$sAdd="";

        
$dr=DALBUM_BROWSERROOT;

        
// Modify tree item text
        
if ($cur_ct>$dateRecent)
        {
            
// This displays text only
            
$sAdd="&nbsp;<sup><b>".$lang['cModifiedNew']."</b></sup>";

            
// Uncomment the next 2 lines to display custimg/new.gif next to new albums
            //$sAdd="&nbsp;<sup><img src=\'{$dr}custimg/new.gif\' alt=\'\' title=\'".
            //                    $lang['cModifiedNew']."\'></sup>";
        
}
        elseif (
$cur_mt>$dateRecent)
        {
            
// This displays text only
            
$sAdd="&nbsp;<sup><b>".$lang['cModifiedUpdated']."</b></sup>";

            
// Uncomment the next 2 lines to display custimg/updated.gif next to updated albums
            //$sAdd="&nbsp;<sup><img src=\'{$dr}custimg/updated.gif\' alt=\'\' title=\'".
            //                    $lang['cModifiedUpdated']."\'></sup>";
        
}

        if (!empty(
$sAdd) && $this->m_sFolder!='/')
            
$sText.=$sAdd;

        
// Call default implementation to display updated string.
        
return parent::GetTreeNodeCode($myID,$nParentID,$sText,$sRef);
    }


    
// This function is always called during reindex AFTER subfolders are loaded
    
function ParseDetails(&$ini_array,$bAllDetails)
    {
        
parent::ParseDetails($ini_array,$bAllDetails);

        
// Get modified time for this folder
        
$cur_mt=$this->GetCustomField("Modified_YYMMDD");
        if (
strlen($cur_mt)!=6)
            
$cur_mt="000000";
        
$cur_ct=$this->GetCustomField("Created_YYMMDD");
        if (
strlen($cur_ct)!=6)
            
$cur_ct="000000";

        
// Go through all subfolders and set this folder modification time
        // to not be before any subfolder modification time
        
for ($i=0;$i<count($this->m_arrContents);++$i)
        {
            
$obj=&$this->m_arrContents[$i];
            if (!
$obj->IsImage())
            {
                
$mt=$obj->GetCustomField("Modified_YYMMDD");
                if (!empty(
$mt) && $mt>$cur_mt)
                    
$cur_mt=$mt;
            }
        }
        if (
$this->GetCustomField("Modified_YYMMDD")!=$cur_mt)
        {
            
$this->m_arrCustomFields["Modified_YYMMDD"]=$cur_mt;
            
$this->m_arrCustomFields["Created_YYMMDD"]=$cur_ct;
            
create_defaultIni($this,true);
        }
    }
}

function &
customCreateAlbum()
{
    return new 
CExAlbumModified();
}

2. Reindex (you may also need to delete .private/.album_index.dat file). When you add new albums they will be marked as "new!" in album tree and their parent albums marked as "updated!".

[ Top ]

Display a HTML page

Sometimes it is useful to display a HTML page instead of a list of image thumbnails. For example, when a root album is selected it is often preferrable to display some description text and information about the gallery instead of folders which are already available in the tree view.

This sample verifies if album folder contains text.html page, and if this file exists - it is displayed instead of list of thumbnails and folders.

With this method you can build a web-site similar to this one.

Instructions

1. Edit t_index.php page template, find the place where thumbnail view is displayed and wrap it with the following code:

  <?php
   
// ---- Display HTML page 1 begins -----
   
$fname=absfname($album->m_sFolder "text.html");
   if (
file_exists($fname))
   {
        
$sAlbHeader="";
        
$sAlbHeader.="<span class=\"title\">"$album->GetTitle() . "</span>";

        if (!empty(
$album->m_sDate))
            
$sAlbHeader.="<span class=\"date\">&nbsp; (" quotehtml($album->m_sDate) . ")</span>";

        if (
$bAdminMode && !empty($album->m_sFolder))
        {
            
$sAlbHeader.="&nbsp;&nbsp;&nbsp;";
            
$filename=quoteurl($album->m_sFolder);
            
$sAlbHeader.="<span class=\"navigationBar\" id=\"albCommands\">";
            
$sAlbHeader.=dalbumBeginToolbar("albCommands");
            
$sAlbHeader.=getButton('editdef',
                            
translateRef("editini.php?album=$filename&amp;url=".
                                    
encodeCurrentLocation()),
                            
$lang['editDefBtn'],$lang['editDefBtnTitle'],0);
            
$sAlbHeader.=dalbumEndToolbar("albCommands");
            
$sAlbHeader.="</span>";
        }

        
// Print album comment
        
$cmt=$a->GetHTMLComment();
        if (!empty(
$cmt))
        {
            
$sAlbHeader.= "<table width=\"99%\" border=0 cellspacing=0 cellpadding=0>";
            
$sAlbHeader.= "<tr><td style=\"width:100%;\"><div class=\"comnt\">$cmt</div>";
            
$sAlbHeader.= "</td></tr></table>";
        }

        print 
'<div class="albHeader">';
        print 
$sAlbHeader;
        print 
'</div>';

        print 
'<div class="textView">';
        include(
$fname);
        print 
'</div>';
   }
   else {
   
// ----- Display HTML page 1 ends -----
?>

... thumbnail view ...

  <?php
   
// -----Display HTML page 2 begins -----
   
}
   
// -----Display HTML page 2 ends -----
?>

The result should look like follows:

  <!-- Begin right pane - Album header control & ThumbView -->
<td  class="insetPane" id="thumbViewPane">

  <?php
   
// ---- Display HTML page 1 begins -----
   
$fname=absfname($album->m_sFolder "text.html");
   if (
file_exists($fname))
   {
        
$sAlbHeader="";
        
$sAlbHeader.="<span class=\"title\">"$album->GetTitle() . "</span>";

        if (!empty(
$album->m_sDate))
            
$sAlbHeader.="<span class=\"date\">&nbsp; (" quotehtml($album->m_sDate) . ")</span>";

        if (
$bAdminMode && !empty($album->m_sFolder))
        {
            
$sAlbHeader.="&nbsp;&nbsp;&nbsp;";
            
$filename=quoteurl($album->m_sFolder);
            
$sAlbHeader.="<span class=\"navigationBar\" id=\"albCommands\">";
            
$sAlbHeader.=dalbumBeginToolbar("albCommands");
            
$sAlbHeader.=getButton('editdef',
                            
translateRef("editini.php?album=$filename&amp;url=".
                                    
encodeCurrentLocation()),
                            
$lang['editDefBtn'],$lang['editDefBtnTitle'],0);
            
$sAlbHeader.=dalbumEndToolbar("albCommands");
            
$sAlbHeader.="</span>";
        }

        
// Print album comment
        
$cmt=$a->GetHTMLComment();
        if (!empty(
$cmt))
        {
            
$sAlbHeader.= "<table width=\"99%\" border=0 cellspacing=0 cellpadding=0>";
            
$sAlbHeader.= "<tr><td style=\"width:100%;\"><div class=\"comnt\">$cmt</div>";
            
$sAlbHeader.= "</td></tr></table>";
        }

        print 
'<div class="albHeader">';
        print 
$sAlbHeader;
        print 
'</div>';

        print 
'<div class="textView">';
        include(
$fname);
        print 
'</div>';
   }
   else {
   
// ----- Display HTML page 1 ends -----
?>

  <!-- Begin AlbumHeader  -->
<div class="albHeader">
<?php template('AlbumHeader'); ?>
</div>
<!-- End AlbumHeader  -->

<!-- Begin thumbView -->
<div class="thumbView">

<table cellpadding=0 cellspacing=2px border=0 width="98%" >
<?php template('ThumbView'); ?>
</table>

<div class="fldimgrow"><img src="images/transpix.gif" ...></div>
</div>
<!-- End thumbView -->

  <?php
   
// -----Display HTML page 2 begins -----
   
}
   
// -----Display HTML page 2 ends -----
?>

  <!-- End right pane table  -->

2. [Optional] Edit custom.css and append the following lines to the file:

  .textview
{
    width:100%;
    height:100%;

    margin: 0px;
    padding: 5px;

    background-color: white;
    color: black;
}

Adjust this CSS to define default colors for the displayed HTML.

3. That's all. Create text.html files in required folders and enjoy. test.html must not contain <HTML> or <BODY > tags.

Notes:

[ Top ]

Store thumbnails separately

Sometimes it may be useful to keep original image files and DAlbum generated files (image thumbnails, .albumdef.ini files etc.) in separate folders.

In this sample original images are stored in ./pictures directory, and all generated files in ./generated directory. For example, thumbnail for ./pictures/myfolder/myfile.jpg will be stored in ./generated/myfolder/myfile.jpg. This way ./pictures directory can be read-only.

This functionality is achieved by overriding customAbsfname function that converts image path relative to ./pictures directory (ex. /myfolder/myfile.jpg) to filename (./pictures/myfolder/myfile.jpg or /home/john/public_html/pictures/myfolder/myfile.jpg). Additional steps are made to ensure that .htaccess files are created in ./generated directory as well.

Instructions

1. Edit you custom.php and add the following code. Modify $g_sGeneratedRoot and $g_sGeneratedRootBrowser variables to point to correct directories. These variables are have similar meaning to $g_sAlbumsRoot and $g_sAlbumsRootBrowser, which are described in Securing DAlbum installation.

 // Folder with generated images and .albumdef.ini files
$g_sGeneratedRoot="./generated";

// This is used with direct image access
$g_sGeneratedRootBrowser=dirname_ex($g_sAlbumsRootBrowser) . "/generated";

// returns true if $filename resides under $g_sGeneratedRoot folder
function IsGeneratedLocation($name)
{
   global 
$g_sThumbnailPath$g_sResizedPath;

   
// If you prefer to store .albumdef.ini file in the same folder
   // with original images, comment or remove line
   //
   // basename(strval($name))==".albumdef.ini" ||
   //
   // below.

   
if (  strstr($name,'/' $g_sThumbnailPath '/') ||
         
substr($name,-strlen($g_sThumbnailPath))==$g_sThumbnailPath ||
         
strstr($name,'/' $g_sResizedPath '/') ||
         
substr($name,-strlen($g_sResizedPath))==$g_sResizedPath ||
         
basename(strval($name))==".albumdef.ini" ||
         
getext($name)=='cmt' )
         return 
true;

      return 
false;
}

// override URL generation for direct access. Produces
//    http://mysite.com/photo/generated/_thm/thm_pic1.jpg
// instead of
//    http://mysite.com/photo/pictures/_thm/thm_pic1.jpg)
// for generated images
function customURL($picPath)
{
    global 
$g_bHTTPAuth$g_bDirectAccess$g_sAlbumsRootBrowser;
    global 
$g_sGeneratedRootBrowser;

    if (
$g_bDirectAccess && substr(basename(strval($picPath)),0,1)!='.')
    {
        if (
$g_bHTTPAuth || !isset($_SESSION['UID']))
        {
            if (
IsGeneratedLocation($picPath))
                return 
quoteurl($g_sGeneratedRootBrowser $picPath);
            return 
quoteurl($g_sAlbumsRootBrowser $picPath);
        }
    }
    return 
'photo.php?file=' quoteurl($picPath);
}

// Handle conversion from relative filename to absolute
function customAbsfname($name)
{
    global 
$g_sAlbumsRoot,  $g_sGeneratedRoot;

    if (
IsGeneratedLocation($name))
       return 
$g_sGeneratedRoot $name;

    return 
$g_sAlbumsRoot $name;
}


class 
CExAlbumGenerated extends CAlbum
{
    function 
Create($sPath$parentUsers,$bCleanup$bDeleteImages=false)
    {
       
// Create a corresponging folder in "generated" tree
        
global $g_sGeneratedRoot,$g_sAlbumsRoot;
        if (
$g_sGeneratedRoot!=$g_sAlbumsRoot)
        {
            if (!
checkDirectory($g_sGeneratedRoot.$sPath))
            {
            global 
$g_newDirRights;
            
dalbum_mkdir($g_sGeneratedRoot.$sPath,$g_newDirRights);
            }
        }

        
// Call default implementation
        
if (!parent::Create($sPath,$parentUsers,$bCleanup,$bDeleteImages))
            return 
false;

        
// Create .htaccess in generated folder too
        
if ($g_sGeneratedRoot!=$g_sAlbumsRoot)
        {
            if (
join(",",$parentUsers)==join(",",$this->m_arrUsers))
                
delete_htaccess($g_sGeneratedRoot.$this->m_sFolder);
            else
                
create_htaccess($g_sGeneratedRoot.$this->m_sFolder,$this->m_arrUsers);
        }
        return 
true;
    }
}

function &
customCreateAlbum()
{
    return new 
CExAlbumGenerated();
}

2. Create the directory set in $g_sGeneratedRoot (./generated by default) and CHMOD it to 777.

3. Reindex. Generated files are be now stored in the new folder.

[ Top ]

Change sorting order

From time to time it may be useful to change sorting order of images and albums without actually renaming them. With this customization it possible to assign a sorting index to any image or album, and this index will take preference over a filename.

With this customization installed, every album and image will have an extra field "SortOrder" in .albumdef.ini file. This field will also be visible in album properties. Pictures with SortOrder=0 (default) go first, followed by pictures with SortOrder=1, followed by SortOrder=2 and so on.

For example, there are three albums "One", "Two", "Three". By default DAlbum sorts them alphabetically as "One", "Three", "Two". One way of ordering them correctly would be to rename albums as "01-One", "02-Two", "03-Three", but the same result can be achieved by setting:

Album "One" will have SortOrder empty which means 0.

After reindexing albums will appear in correct order as "One", "Two", "Three".

A working example can be seen in samples where album "LeMassif" was assigned SortOrder=-1 and therefore is listed before other albums.

Instructions

1. Edit you custom.php and subclass CAlbum and CImage classes by adding the following code to the bottom of the file.

 class CSortImage extends CImage
{
    function &
GetCustomFieldNames()
    {
        
$f=parent::GetCustomFieldNames();
        
$f[]="SortOrder";

        return 
$f;
    }
}

class 
CSortAlbum extends CAlbum
{
    function 
cmpAlb2($a$b)
    {
        
$ai=$a->IsImage();
        
$bi=$b->IsImage();

        
// If both are images or both are albums look at "SortOrder"
        
if ( ($ai && $bi) || (!$ai && !$bi))
        {
            
$v1=(int)trim(strval($a->GetCustomField("SortOrder")));
               
$v2=(int)trim(strval($b->GetCustomField("SortOrder")));
               if (
$v1!=$v2)
                return 
$v1-$v2;
        }

        
// No sort order preference. Try names

        // If both are images - compare filenames
        
if ($ai && $bi)
            return 
strcasecmp($a->m_sBaseFilename$b->m_sBaseFilename);

        
// Albums always go before images
        
if ($ai)
            return 
1;
        if (
$bi)
            return -
1;

        
// Both are albums - compare folders
        
return strcasecmp(basename(substr($a->m_sFolder,0,-1)), basename(substr($b->m_sFolder,0,-1)));
    }

    
// Get list of custom field names
    
function &GetCustomFieldNames()
    {
        
$f=parent::GetCustomFieldNames();
        
$f[]="SortOrder";
        return 
$f;
    }

    function 
Sort()
    {
        if (!empty(
$this->m_arrContents))
            
usort($this->m_arrContents,array(get_class($this),"cmpAlb2"));
    }
}


function &
customCreateImage()
{
    return new 
CSortImage();
}

function &
customCreateAlbum()
{
    return new 
CSortAlbum();
}

2. If you already have subclassed any of these classes before, you may need to change CAlbum/CImage strings in the code above with a subclassed name and delete duplicate customCreateImage/customCreateAlbum functions. See bonus pack source code for an example.

3. Reindex. Please note that if you change SortOrder of an album, the changes will apply only after reindex

[ Top ]

** Bonus Pack 1.2 **

This is just a pre-built set of templates that includes:

Check sample site for a demonstration.

Installation is very simple:

  1. extract bonus1.zip into your DAlbum folder (it will overwrite default templates)
  2. Reindex
  3. Modify welcome page in pictures/text.html or delete the file if you don't need the welcome page.

P.S. A little note about video files - you need to manually set resolution for Quicktime movies in album properties.

[ Top ]

Create your own

With some programming experience (in any language - PHP is very easy), you can easily create your own customizations. DAlbum code is small and simple - no need to scan megabytes of code to find out how it works. include/album.php and sometimes include/functions.php will give you enough information about the script to create your own customizations. There is no formal documentation, but there are code comments. Some more details follow.

A good customization only modifies configuration files and does not change original installation files. That makes upgrades very easy and almost automatic.

If you have created a cool DAlbum customization, custom stylesheets etc. you would like to share with other people, please send it to me or write to forum. I will be happy to add it to samples and give you credits.

Very short summary

How index.php is displayed?

  1. Include files and config/custom.php file are loaded.
  2. Complete tree of albums generated during reindex is downloaded from .private/.album_index.dat file. Root album is stored in $albRoot variable.
  3. If a folder name is specified in page URL, CAlbum object corresponding to this folder is searched using $albRoot->FindAlbum() method. Current album is stored in $album variable.
  4. $album->LoadImages() method is called to list all images in album directory and add them to album object.
  5. $album->BeforeDisplay() method is called on the current album. It's default implementation does nothing, but you can override it to do smth. useful. For example, change number or thumnbail columns or load album comments from a database.
  6. A set of template parameters is prepared (header, javascript tree code etc.) and stored them in $_template array.
  7. Page template is included from t_index.php. This page has access to all variables set by index.php page - current album ($album), root album ($albRoot) etc. Complete page including headers and footers is obtained from t_index.php - you define all page completely and it's up to you whether use or not use prepared template arguments in $_template.

How showimg.php is displayed?

  1. Include files and config/custom.php file are loaded.
  2. Complete tree of albums generated during reindex is downloaded from .private/.album_index.dat file. Root album is stored in $albRoot variable.
  3. Album containing the displayed image is found ($album), its images loaded ($album->LoadImages()) and and a CImage object ($image) correspoding to the file in URL is searched.
  4. $image->BeforeDisplay() method is called on the current image.
  5. A set of template parameters is prepared (header, navigation buttons etc.) and stored them in $_template array.
  6. Page template is included from t_showimg.php. This page has access to all variables set by showimg.php page - current album ($album), root album ($albRoot), image ($image) etc.
[ Top ]

Shared code

This new section of DAlbum web-site is dedicated to add-ins, code patches, stylesheets, hints, tutorials etc. from independent authors.

If you have something DAlbum related you want to share - please do! There are approximately 400-500 unique visitors on this web-site daily, and your work will be appreciated.

For the time being there is be no automated system for article submissions. If you have something to share, please send it to dalbum@delx.ca in a .zip file containing the following information:

In the e-mail body please specify to what section of "Shared code" your article should go. Is it a stylesheet, add-in, tutorial or smth. else.

[ Top ]

Embedding

DAlbum 1.35 and earlier could be embedded into another web-site using frames or IFRAME tags. It was also possible to build a DAlbum-centered web-site (like this one).

DAlbum version 1.36 can be embedded into another web-site without frames as well. A relatively easy to install PHP-Nuke module is provided.

Instructions

The following describes how to include DAlbum into any PHP web-page. Check this demonstration for an example.

Please note that custom embedding requires good understanding of both your site code and DAlbum code. If you just have started with PHP and have no programming experience it may be very difficult to get it all working correctly.

First of all, install original DAlbum script into a folder (for example /site/dalbum). Set configuration options, customize stylesheets, install needed add-ons. Ensure that all directories are specified with absolute pathes (ex. /var/http/site/dalbum/.private instead of default ./.private). Switch GZip off, it's up to your site to control GZip options now.

Embedding DAlbum into your page includes the following operations:

For example, you have a page /site/gallery.php, which has a box to display DAlbum interface in:

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
</head>
<body>
<h1>My page</h1>
<p>I want DAlbum to be displayed here:</p>
<table border=5 width="90%">
<tr>
<td width="100px">Menu1<BR>Menu2<BR></td>
<td >
<!-- here should appear DAlbum page -->
</td>
</tr>
</table>
</body>
</html>

Firstly, use output buffering ( ob_start() , ob_end_flush() ) to let included DAlbum code control HTTP headers and redirections:

  <?php
    ob_start
();
    
ob_implicit_flush(0);
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
</head>
<body>
<h1>My page</h1>
<p>I want DAlbum to be displayed here:</p>
<table border=5 width="90%">
<tr>
<td width="100px">Menu1<BR>Menu2<BR></td>
<td >
<!-- here should appear DAlbum page -->
</td>
</tr>
</table>
</body>
</html>
<?php
    ob_end_flush
();
?>

DAlbum script consists of multiple pages and all of them must be displayed inside your /site/gallery.php. To let DAlbum know what page to display, gallery.php will take an additional parameter - dp. To display DAlbum login page, the URL will be www.mysite.com/gallery.php?dp=login.php, to display DAlbum index page with folder "Mypics" - www.mysite.com/gallery.php?dp=index.php&folder=/Mypics/ .

To do that insert the following code into your /site/gallery.php page:

 <?php
    $dp
="index.php";
    if (isset(
$_GET['dp']))
        
$dp=$_GET['dp'];

    
// verify that page is okay - no funny stuff like .. or /
    
if (!preg_match('/^[a-zA-Z0-9]*\.php$/',$dp))
        
$dp="index.php";

    
// Set DAlbum location
    
define("DALBUM_ROOT""dalbum");
    
define("DALBUM_BROWSERROOT""/site/dalbum/");

    
// Mark that DAlbum is embedded
    
define("DALBUM_EMBEDDED""1");


    
// Call DAlbum code and save output in $_page variable
    
$_page="";
    
ob_start(create_function('$a','global $_page;$_page.=$a;'));
    include(
DALBUM_ROOT "/$dp");
    
ob_end_flush();

    if (!
strstr($_page,"<"))
    {
        
// Redirection. Only headers there - return empty page
        
ob_end_clean();
        return;
    }
    else
    {
        
// Cut the body out of the returned text
        
if (preg_match('~<body(.+?\>)(.*)</body>~ims',$_page,$arr))
        {
            
// Display it inside <DIV class="dalbumbody">
            
print "<div class='dalbumbody'><div " $arr[1];
            print  
$arr[2] . "</div></div>";
        }
        else
            print 
"<P>Internal error occured.</P><BR>$_page";
    }

    function 
customTranslateRef($ref)
    {
        if (
substr($ref,0,1)=="/")
            return 
$ref;
        if (
substr($ref,0,9)=="photo.php")
            return 
DALBUM_BROWSERROOT $ref;
        return 
basename(__FILE__) . "?dp=" strtr($ref,array("?"=>"&amp;"));
    }
?>

DALBUM_ROOT constant defines DAlbum directory location relative to current directory. As DAlbum is installed in dalbum subdirectory of the current directory, DALBUM_ROOT is set to "dalbum". There is no slash at the end of directory name.

DALBUM_BROWSEROOT constant defines how DAlbum directory is visible from the browser. "/site/dalbum/" means that a URL to images/page.gif in DAlbum installation directory should be displayed as /site/dalbum/images/page.gif. There is a mandatory slash at the end of this name.

Then required page is included and output stored in $_page variable for processing. Processing includes removal of HTML header, and replacing <body> tag with <div class="dalbumbody"> to limit stylesheet effect to DAlbum box only.

Function customTranlateRef translates DAlbum references to itself to refer to your gallery.php instead. For instance index.php?folder=/Mypics/ is translated to gallery.php?dp=index.php&folder=/Mypics/. Please note that photo.php references are not translated - returned page is an image and we don't need any HTML wrapping there.

DAlbum stylesheet also needs to be modified - originally it includes definitions for BODY and A tags which are probably defined already in the existing site stylesheet. PHP-Nuke module shows an example of automatic stylesheet conversion script that translates

body {} to .dalbumbody {}
body.centered {} to .dalbumbody div.centered {}
a.mystyle, b {} to .dalbumbody a.mystyle, .dalbumbody b {}

throughout the stylesheet automatically. It also replaces relative font-sizes (such as 70%) to absolute sizes. The last step is required if site uses tables for layout as relative font sizes do not work properly with nested tables.

Include this modified stylesheet into your gallery.php page headers together with DAlbum javascript files:

  <head>
...
<link rel="stylesheet" href="dalbum/modified_stylesheet.css" type="text/css" >
<link rel="stylesheet" href="dalbum/custom.css" type="text/css" >
<script src="dalbum/dtree.js" type="text/javascript"></script>
<script src="dalbum/dalbum.js" type="text/javascript"></script>
...
</head>

Also edit your /site/dalbum/config/t_showimg.php page template and comment out call to dalbum_showimg_resize Javascript function at the bottom of the file:

  //    dalbum_showimg_resize('showimgPagetable','Image','imageRow','imageWrap',
//                            <?php template('ImageSizeX');?>,
//                            <?php template('ImageSizeY');?>,
//                            '<?php template("BrowserFitMethod");?>');

To prevent your DAlbum installation from being used directly, add the following code into your /site/dalbum/config/custom.php:

  if (!defined("DALBUM_EMBEDDED") && !defined("DALBUM_PHOTO_PAGE"))
    die("Error: DAlbum can only be used as module.");

This is especially important if you do not use DAlbum built-in authentication and rely on your site code to verify user identity.

[ Top ]

PHP-Nuke

DAlbum PHP-Nuke module enables embedding the script into PHP-Nuke content management system as a module.

You can even use PHP-Nuke authentication if you like.

Instructions

  1. Download PHP-Nuke module from here.
  2. Create a subdirectory "DAlbum" in PHP-Nuke "modules" directory. Extract add-on files there. You may change the subdirectory name if you like.
  3. CHMOD modules/DAlbum/cache to 777. It will be used for stylesheet caching.
  4. Extract original DAlbum installation into modules/DAlbum/script.
  5. Go to www.mysite.com/modules/DAlbum/script/index.php - you have a standalone installation now. Configure stylesheets, config.php and other settings.
  6. Ensure that all directories are specified with absolute pathes (ex. /var/http/site/dalbum/.private instead of default ./.private).
  7. Switch GZip compression off.
  8. It would also be a good idea to reduce the number of columns in thumbnail view to eliminate horisontal scroll bars.
  9. Edit modules/DAlbum/script/config/custom.php and append contents of custom.inc to this file.
  10. By default original DAlbum authentication (login/logoff pages and .htpasswd file) will be used, but you can uncomment two functions in custom.php to use PHP-Nuke authentication instead. In this case PHP-Nuke registered users will be treated by DAlbum as user "user" and PHP-Nuke administrators - as user "admin". You can put more detailed authentication there and parse PHP-Nuke cookies if you like.
  11. Append my_header.php to your html/include/my_header.php. Modify module name there if it's not "DAlbum".
  12. Edit your config/t_showimg.php page template and comment out call to dalbum_showimg_resize Javascript function at the bottom of the file:

      //    dalbum_showimg_resize('showimgPagetable','Image','imageRow','imageWrap',
    //                            <?php template('ImageSizeX');?>,
    //                            <?php template('ImageSizeY');?>,
    //                            '<?php template("BrowserFitMethod");?>');

  13. That's about it. Change page templates and stylesheets to match your site contents.
[ Top ]

FAQ

  1. How to order images and galleries?
  2. How to disable creation of resized images?
  3. How to set folder title image without displaying the image inside?
  4. How to configure DAlbum to use ImageMagick on Microsoft IIS?
  5. How to use NetPBM for image resizing?
  6. How to prevent direct image linking (hot linking)

How to order images and galleries?

Albums and images are sorted alphabetically by their filenames. For example, images "first.jpg", "Second.jpg", "Third.jpg" and "Fourth.jpg" will be sorted as follows:

  1. Fourth.jpg
  2. Second.jpg
  3. Third.jpg
  4. first.jpg

To change the order of images, rename them as 001-first.jpg, 002-Second.jpg, 003-Third.jpg and 004-Fourth.jpg correspondingly. There are many utilities available which can simplify the renaming process - check Batch Renaming.

To hide the leading digits from your users without manually editing every image caption in .albumdef.ini, uncomment and modify filename2title function in your custom.php file as follows:

function filename2title($filename)
{
    return ereg_replace( "^[0-9]+-", "", getfname($filename) );
}
This way your album users will see your images as "first", "Second", "Third" and "Fourth" and in appropriate order.

You can also define your own sorting method by overriding CAlbum::Sort method in derived class.

This example adds DescendingOrder custom field to albums. When it is set to "1" in album properties, album contents will be sorted in descending order:

 class CExAlbumSortOrder extends CAlbum
{
    
// Get list of custom field names
    
function &GetCustomFieldNames()
    {
        
$f=parent::GetCustomFieldNames();
        
$f[]="DescendingOrder";
        return 
$f;
    }

    function 
cmpAlbDesc($a$b)
    {
        if (
$a->IsImage())
        {
            if (
$b->IsImage())
                return -
strcasecmp($a->m_sBaseFilename$b->m_sBaseFilename);
            return 
1;
        }
        if (
$b->IsImage())
            return -
1;

        return -
strcasecmp(basename(substr($a->m_sFolder,0,-1)),
                           
basename(substr($b->m_sFolder,0,-1)));
    }

    function 
Sort()
    {
       if (
$this->GetCustomField("DescendingOrder")>0)
          
usort($this->m_arrContents,array(get_class($this),"cmpAlbDesc"));
       else
          
usort($this->m_arrContents,array(get_class($this),"cmpAlb"));
    }
}

function &
customCreateAlbum()
{
    return new 
CExAlbumSortOrder();
}

How to disable creation of resized images?

DAlbum does not create a resized image if the original image is smaller than resized image size. Edit your config.php file and set

$g_sResizedXSize=50000;
$g_sResizedYSize=50000;

How to configure DAlbum to use ImageMagick on Microsoft IIS

  1. Set
    $g_sResizeMethod="IM";
    in config.php
  2. Edit $g_sConvertPath variable in config.php and set it to location where ImageMagick is installed. For example
    $g_sConvertPath="c:/ImageMagick/convert.exe";
    Remember to replace all backslashes with forward slashes.
  3. You need to give IIS user account access rights to your C:\WINNT\SYSTEM32\Cmd.exe. The best way to do it is go to your IIS Admin, select reindex.php and set it to run as another user (not IUSR_xxx). More secure solution would be to disable anonymous access to reindex.php completely and set authentication on. Then you will be asked for username and password for Windows account every time you reindex the photo album.
  4. In order to run DAlbum test you will need to configure test.php account the same way as reindex.php in step 3.
  5. Ensure that temp directory is writeable by the same account.

How to set folder title image without displaying the image inside?

Create a file named:

inside your folder. This file should be smaller or equal to your configured thumbnail size (default 128x128 pixels).

How to use NetPBM for image resizing?

If your host has NetPBM graphics software package installed, you can use it to create thumbnails and resized images:

  1. Download and extract rsnetpbm.pl from rsnetpbm.zip into DAlbum root directory. You may need to edit this file and set directory where NetBMP package is installed. CHMOD rsnetpbm.pl to be not executable (ex. 444).
  2. Edit your config.php file as follows:
     // Force command-line image resizing</span>
    $g_sResizeMethod="IM";

    ...

    // Change it to location of your Perl interpreter if necessary</span>
    $g_sConvertPath="/usr/bin/perl";
    $g_sThumbnailImArg="$g_sConvertPath ./rsnetpbm.pl #src# #target# ".
                         
    "$g_sThumbnailQuality $g_sThumbnailXSize $g_sThumbnailYSize";
    $g_sResizedImArg  ="$g_sConvertPath ./rsnetpbm.pl #src# #target# ".
                         
    "$g_sResizedQuality $g_sResizedXSize $g_sResizedYSize";
  3. Reindex.

Using a similar approach any command-line image resizing toolkit can be used with DAlbum.

How to prevent direct image linking (hot linking)

As your public images can be accessed by using a URL (ex. www.mysite.com/photo/photo.php?file=/folder1/test.jpg), your site may become subject to direct linking. This happens when somebody posts URL of your image on another site or forum and hundreds of people suck your bandwidth without even visiting your site.

To disable direct linking to your images, edit your config.php and ensure that the following variables are set as follows:

$g_bDirectAccess=false;
...
$g_bHTTPAuth=false;

This way DAlbum code is called every time an image is downloaded.

Then add the following code snippet to custom.php:

 DisableDirectLinking();

function 
DisableDirectLinking()
{
    
$ip=$_SERVER['REMOTE_ADDR'];
    if (@
$_SERVER["HTTP_X_FORWARDED_FOR"])
        
$ip=$_SERVER["HTTP_X_FORWARDED_FOR"];
    
$sCookieValue=md5($_SERVER['HTTP_HOST'].$ip);

    if (
stristr($_SERVER['PHP_SELF'],"photo.php"))
    {
        if (!isset(
$_COOKIE['DAlbum_Connection']) ||
             
$_COOKIE['DAlbum_Connection']!=$sCookieValue)
        {
            
// Check referrer. If referrer is our domain -
            // allow access even if cookie is not set
            
if (isset($_SERVER['HTTP_REFERER']))
            {
                
$ref=parse_url($_SERVER['HTTP_REFERER']);
                
$sHost=basename($ref['host'] );
                if (isset(
$_SERVER['HTTP_HOST']) &&
                    
strcasecmp($_SERVER['HTTP_HOST'],$sHost)==0)
                    return;
            }
            
hdr("404 Not found");
            exit();
        }
    }
    else
    {
        
// Set cookie for one hour.
        
setcookie("DAlbum_Connection",$sCookieValue,time()+3600);
    }
}

This code forces all DAlbum pages except photo.php to set a one-hour cookie on every visit. If there is a direct link to photo.php, the cookie will not be set and "404 Page not found" error returned to client. Page referer check is also performed to enable users with disabled cookies to browse your site.

 

 

[ Top ]

History

9 Nov 2003

1 Nov 2003

29 Oct 2003

1.34 (28 Oct 2003)

1.33 (22 Oct 2003)

1.32 (18 Oct 2003)

1.31 (01 Oct 2003)

1.3 (29 Sep 2003)

1.22sp7

1.22sp6

1.22sp5

1.22sp4

1.22sp3

1.22sp2

1.22

1.21

1.20

1.10

1.09

1.08

Valid HTML 4.01!

1.07

1.06

1.05

1.04

1.03

First public release

[ Top ]

Copyrights and thanks

Credits

Thanks

Financial support of the following sites is very much appreciated:

Special thanks to mrbass, andy and Anthony Bautista for help in development, great suggestions and huge number of found bugs.

Many thanks to the all people listed above, DAlbum forum users and all those who sent me their feedback for hints and ideas.

And also thanks to all of you who rated this script!

Copyright notice

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

[ Top ]