PX : code

Simple Picture Gallery Manager by spajot
Rating: 5.00
Download this code


<?php

#
#  Official website: http://spgm.sourceforge.net
#
#  SPGM (Simple Picture Gallery Manager), a basic and configurable PHP script
#  to display picture galleries on the web
#  Copyright (C) 2002, Sylvain Pajot <spajot@users.sourceforge.net>
#
#  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


###### Toggles #############
define("MODE_DEBUG"false); // toggles debug mode
define("MODE_WARNING"true); // toggles warning mode
define("REGISTER_GLOBALS"true); // toggle for register_globals mode
                                  // must match the php.ini configuration

define("DIR_GAL""gal/");  // the gallery base directory  (relative path from "pik2gen.php3" location)
define("DIR_CONF""gal/");
define("DIR_LANG""lang/");
define("DIR_THEMES""themes/");
define("FILE_GAL_CAPTION""gallery.msg"); // default caption file for a gallery
define("FILE_THEME""spgm.thm");           // theme file
define("FILE_CONF""spgm.conf");           // config file
define("FILE_LANG""lang");                // language file short name (without extension)
define("PREF_THUMB""_thb_");              // prefix for thumbnail pictures
define("EXT_PIC_CAPTION"".cmt");          // file extension for pictures comment

define("PARAM_NAME_GALID""g");
define("PARAM_NAME_PICID""p");
define("PARAM_NAME_PAGE""pg");
define("PARAM_NAME_FILTER""f");
define("PARAM_NAME_FROMPAGE""frpg");
define("PARAM_VALUE_FILTER_NEW""n");

define("CLASS_TABLE_MAIN_TITLE""table_main_title");
define("CLASS_TD_MAIN_TITLE""td_main_title");
define("CLASS_TD_MAIN_TITLE_SPGM_LINK""td_main_title_spgm_link");
define("CLASS_A_SPGM_LINK""a_spgm_link");
define("CLASS_TABLE_GALITEM""table_galitem");
define("CLASS_TD_GALITEM_ICON""td_galitem_icon");
define("CLASS_TD_GALITEM_TITLE""td_galitem_title");
define("CLASS_TD_GALITEM_CAPTION""td_galitem_caption");
define("CLASS_TABLE_PICTURE""table_picture");
define("CLASS_TD_PICTURE_NAVI""td_picture_navi");
define("CLASS_TD_ZOOM_FACTORS""td_zoom_factors");
define("ID_PICTURE""picture");
define("CLASS_BUTTON_ZOOM_FACTORS""button_zoom_factors");
define("CLASS_TD_PICTURE_PIC""td_picture_pic");
define("ID_PICTURE_NAVI""pic_navi");
define("CLASS_TD_PICTURE_CAPTION""td_picture_caption");
define("CLASS_TABLE_THUMBNAILS""table_thumbnails");
define("CLASS_TD_THUMBNAILS_THUMB""td_thumbnails_thumb");
define("CLASS_TD_THUMBNAILS_THUMB_SELECTED""td_thumbnails_thumb_selected");
define("CLASS_TD_THUMBNAILS_NAVI""td_thumbnails_navi");
define("CLASS_DIV_THUMBNAILS_CAPTION""div_thumbnails_caption");
define("CLASS_SPAN_FILTERS""span_filters");
define("CLASS_IMG_PICTURE""img_picture");
define("CLASS_IMG_THUMBNAIL""img_thumbnail");
define("CLASS_IMG_THUMBNAIL_SELECTED""img_thumbnail_selected");
define("CLASS_IMG_FOLDER""img_folder");
define("CLASS_IMG_PICTURE_PREV""img_picture_prev");
define("CLASS_IMG_PICTURE_NEXT""img_picture_next");
define("CLASS_IMG_THMBNAVI_PREV""img_thmbnavi_prev");
define("CLASS_IMG_THMBNAVI_NEXT""img_thmbnavi_next");
define("CLASS_IMG_NEW""img_new");
define("CLASS_DIV_GALHEADER""div_galheader");
    
define("ERRMSG_UNKNOWN_GALLERY""unknow gallery");
define("ERRMSG_UNKNOWN_PICTURE""unknown picture");
define("ERRMSG_NON_VALID_NUMBER_OF_PICTURES""invalid number of picture");
define("ERRMSG_INVALID_VALUE""invalid value");
define("WARNMSG_FILE_INSUFFICIENT_PERMISSIONS""insufficient permissions (644 required)");
define("WARNMSG_DIR_INSUFFICIENT_PERMISSIONS""insufficient permissions (755 required)");

define("INFINITE""oo");



/* multi-language support... */
define("PATTERN_SPGM_LINK"">SPGM_LINK<");
define("PATTERN_CURRENT_PAGE"">CURRENT_PAGE<");
define("PATTERN_NB_PAGES"">NB_PAGES<");
define("PATTERN_CURRENT_PIC"">CURRENT_PIC<");
define("PATTERN_NB_PICS"">NB_PICS<");

$text_spgm_link "a gallery generated by ".PATTERN_SPGM_LINK;
$text_thumb_navi  "Page ".PATTERN_CURRENT_PAGE." of ".PATTERN_NB_PAGES;
$text_filter "filter";
$text_filter_new "new";
$text_filter_all "all";
$text_pic_navi "Picture ".PATTERN_CURRENT_PIC." of ".PATTERN_NB_PICS;
$text_new_pictures "new pictures";
$text_new_picture "new picture";
$text_new_gallery "new gallery";
$text_picture "picture";
$text_pictures "pictures";
$text_root_gallery "Main gallery";



$display_default_wrappers false;
$document_self basename($PHP_SELF);

//$display_thumbnails_with_pic = true; // disable in the conf (see load_conf)
$new_status_duration 30;
$thumbnails_per_page 10;
$thumbnails_per_row 5;
$subgal_display_level INFINITE;
$sort_gallery_by_name false;
$display_captions_with_thumbnails false;
$zoom_factors = array();
$theme "default";
$file_header "";
$file_footer "";
$html_header_stylesheet "spgm_style.css";
$html_header_favicon "";
$html_header_title "Simple Picture Gallery Manager";
$html_header_meta_author "";
$html_header_meta_description "A picture gallery generated by SPGM";
$html_header_meta_keywords "picture, gallery, manager, simple, PHP, online";
$html_header_meta_content_type "text/html; charset=iso-8859-1";


$file_icon_gal "";
$file_icon_pic_new "";
$file_icon_pic_prev "";
$file_icon_pic_next "";
$file_icon_navi_prev "";
$file_icon_navi_next "";


// $language

################## DISPLAY INFO FUNCTIONS #####################################
function display_header() {
  
  global 
$theme;
  global 
$file_header;
  global 
$file_footer;
  global 
$html_header_stylesheet;
  global 
$html_header_favicon;
  global 
$html_header_title;
  global 
$html_header_meta_author;
  global 
$html_header_meta_description;
  global 
$html_header_meta_keywords;
  global 
$html_header_meta_content_type;
  
  global 
$display_default_wrappers;
  
  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_HEADER<br>\n";
  }
  
  if (
      
$file_header != "" && check_perms($file_header)
      && 
$file_footer != "" && check_perms($file_footer)
      ) {
    
$html_header_stylesheet DIR_THEMES.$theme."/".$html_header_stylesheet;
    include(
$file_header);
  }
  else {
    
// to display the footer file anyway
    
$display_default_wrappers true;
    
    print 
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
    print 
"<html>\n";
    print 
"<head>\n";
    print 
"  <link rel=\"Stylesheet\" href=\"".DIR_THEMES.$theme."/".$html_header_stylesheet."\">\n";
    print 
"  <title>$html_header_title</title>\n";
    print 
"  <meta name=\"Author\" Content=\"$html_header_meta_author;\">\n";
    print 
"  <meta name=\"Description\" content=\"$html_header_meta_description\">\n";
    print 
"  <meta name=\"Keywords\" content=\"$html_header_meta_keywords\">\n";
    print 
"  <meta http-equiv=\"Content-Type\" content=\"$html_header_meta_content_type\">\n";
    print 
"</head>\n";
    print 
"<body bgcolor=\"#ffffff\">\n";
    print 
"<table border=0 align=\"center\">\n";
    print 
"<tr>\n";
    print 
"  <td>\n";  
  } 
}

################################################################################
function display_footer() {
  
  global 
$theme;
  global 
$file_footer;
  global 
$display_default_wrappers;

  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_FOOTER<br>\n";
  }
  
  if (
$display_default_wrappers == false) {
    include(
$file_footer);
  }
  else {
      print 
"  </td>\n";
      print 
"</tr>\n";
      print 
"</table>\n";
    print 
"</body>\n";
    print 
"</html>\n";
  }
}


###############################################################################
function display_main_title() {
    
  global 
$html_header_title;
  global 
$text_spgm_link;

  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_MAIN_TITLE<br>\n";
  }  
  
  print 
"<table border=0 align=\"center\" cellpadding=0 cellspacing=0 class=\"".CLASS_TABLE_MAIN_TITLE."\">\n";
  print 
"<tr>\n";
  print 
"  <td class=\"".CLASS_TD_MAIN_TITLE."\">$html_header_title</td>\n";
  print 
"</tr>\n";
  print 
"<tr>\n";
  print 
"  <td class=\"".CLASS_TD_MAIN_TITLE_SPGM_LINK."\" align=\"right\">\n";
  
  
// multi-language support
  
$text_spgm_link ereg_replace(PATTERN_SPGM_LINK"<a href=\"http://spgm.sourceforge.net\" class=\"".CLASS_A_SPGM_LINK."\">SPGM</a>"$text_spgm_link);

  print 
"  $text_spgm_link</td>\n";
  print 
"</tr>\n";
  print 
"</table>\n";
  print 
"<br><br>\n";
}


###############################################################################
function error($msg) {
  print 
"<div style=\"color: #ff0000; font_family: helvetica, arial; font-size:12pt; font-weight: bold;\">$msg</div>\n";
  
display_footer();
  exit(-
1);
}


################################################################################
# Checks if a file or directory is "new" 
function is_new($filename) {
    
  global 
$new_status_duration;

  if (
MODE_DEBUG) {
    print 
"<p>function IS_NEW<br>\n";
    print 
"filename: $filename<br>\n";
  }

  if (! 
file_exists($filename)) return false;
  return (
filemtime($filename) > (time()-$new_status_duration*24*3600));
}

################################################################################
# Checks for permissions on either pictures, galleries, config files, etc... 

function check_perms($filename) {
    
  if (
MODE_DEBUG) {
    print 
"<p>function CHECK_PERMS<br>\n";
    print 
"filename: $filename<br>\n";
  }    
    
  if (! 
file_exists($filename)) return false;
    
  
$fileperms fileperms($filename);
  
$isreadable $fileperms 4;
  if ( 
is_file($filename) ) {
    
// pictures, thumbnails, config files and comments only need to be readable
    
if (! $isreadable) {
      if (
MODE_WARNING) print "$filename: ".WARNMSG_DIR_INSUFFICIENT_PERMISSIONS;
    }
    return 
$isreadable;    
  }
  else if ( 
is_dir($filename) ) {
    
// galleries need to be both readable and executable
    
$isexecutable $fileperms 1;
    if (! 
$isreadable || ! $isexecutable)
      if (
MODE_WARNING) print "$filename: ".WARNMSG_DIR_INSUFFICIENT_PERMISSIONS;
    return ( 
$isreadable && $isexecutable); // ($dirperms & 5) == 5 ?
  
}
  
  
// default behavior: the filename does not exist
  
return false;
}

################################################################################
# Checks if the filname exists, refers to a picture associated to a thumbnail 
# and is granted the necessary access rigths

function is_picture($picture_filename$galid) {

  
$picture_path DIR_GAL."$galid/$picture_filename";
  
$thumbnail_path DIR_GAL."$galid/".PREF_THUMB."$picture_filename";
  
  if (
MODE_DEBUG) {
    print 
"<p>function IS_PICTURE<br>\n";
    print 
"basename: $picture_filename<br>\n";
    print 
"path: $galid<br>\n";
    print 
"filename: $picture_path<br>\n";
    print 
"thumbname: $thumbnail_path<br>\n";
  }
 
  
// check filename patterns
  
if ( 
      
eregi("^".PREF_THUMB."*"$picture_filename) || (
      ! 
eregi(".jpg$"$picture_filename)
      && ! 
eregi(".png$"$picture_filename)
      && ! 
eregi(".gif$"$picture_filename)
      ) )
    return 
false
   
  
// does it exist, is it a regular file and does it have the expected permissions ?
  
if (! check_perms($picture_path) ) {
    return 
false;
  }
  
  
// an associated thumbnail is required... same job again !
  
if (! check_perms($thumbnail_path) ) {
    return 
false;
  }
  
  return 
true;
}

##############################################################################
# Checks if the directory corresponding the gallery is well-formed, exists 
# and is granted the necessary access rights

function is_gallery($galid) {
    
  
$picspath DIR_GAL.$galid;
    
  if (
MODE_DEBUG) {
    print 
"<p>function IS_GALLERY<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"picspath: $picspath<br>\n";
  }
  
  
// searching for hazardous patterns
  
if ( ereg("^/"$galid) || ereg("\.\."$galid) || ereg("/$"$galid) ) {
    return 
false;
  }
  
  
// does it exist, is it a directory and does it have the expected permissions ?
  
if (! check_perms($picspath) ) {
    if (
MODE_WARNING) print "$picspath: ".WARNMSG_FILE_INSUFFICIENT_PERMISSIONS;
    return 
false;
  }
  
  return 
true;
}


################################################################################
# Loads a theme
function load_theme($theme) {

    global 
$file_icon_gal;
    global 
$file_icon_pic_new;
    global 
$file_icon_pic_prev;
    global 
$file_icon_pic_next;
    global 
$file_icon_navi_prev;
    global 
$file_icon_navi_next;
    global 
$html_header_stylesheet;
    
    if (
MODE_DEBUG) {
      print 
"<p>function LOAD_THEME<br>\n";
      print 
"theme: $theme<br>\n";    
    }
    
    if ( 
check_perms(DIR_THEMES.$theme."/".FILE_THEME) ) {
      include(
DIR_THEMES.$theme."/".FILE_THEME);
  }
  else if (
MODE_WARNING) print "unable to load ".DIR_THEMES.$theme."/".FILE_THEME.": ".WARNMSG_FILE_INSUFFICIENT_PERMISSIONS."<br>";
  
//TODO say "inexistant or unsufficient permissions"
  
  //$html_header_stylesheet = DIR_THEMES.$theme."/".$html_header_stylesheet;
    
}

################################################################################
# Loads textual ressources from an SPGM language file.

function load_lang($lang) {

  global 
$text_spgm_link;
  global 
$text_thumb_navi;
  global 
$text_filter;
  global 
$text_filter_new;
  global 
$text_filter_all;
  global 
$text_pic_navi;
  global 
$text_picture;
  global 
$text_pictures;
  global 
$text_new_pictures;
  global 
$text_new_picture;
  global 
$text_new_gallery;
  global 
$text_root_gallery;

  if (
MODE_DEBUG) {
    print 
"<p>funtion LOAD_LANG<br>\n";
    print 
"lang: $lang<br>\n";
  }

  if (
$lang != "") {
    
$filename_lang DIR_LANG.FILE_LANG.".".$lang;
    if (
file_exists($filename_lang) ) {
      if ( 
check_perms($filename_lang) ) {
        include(
$filename_lang);
      }
    }
    else if (
MODE_WARNING) print "No support for language $lang => default: english";
  }
}


################################################################################
# Loads config files from the possible different locations.
# To allow properties inheritance, it includes all the config file from the 
# top level gallery to the gallery itself.
# TODO: support for INI files (PHP4) ?

function load_config($galid) {
    
  
//global $display_thumbnails_with_pic;
  
global $file_header;
  global 
$file_footer;
  global 
$theme;
  global 
$new_status_duration;
  global 
$thumbnails_per_page;
  global 
$thumbnails_per_row;
  global 
$subgal_display_level;
  global 
$sort_gallery_by_name;
  global 
$display_captions_with_thumbnails;
  global 
$zoom_factors;
  global 
$html_header_favicon;
  global 
$html_header_title;
  global 
$html_header_meta_author;
  global 
$html_header_meta_description;
  global 
$html_header_meta_keywords;
  global 
$html_header_meta_content_type;

    
  if (
MODE_DEBUG) {
    print 
"<p>funtion LOAD_CONFIG<br>\n";
    print 
"galid: $galid<br>\n";
  }
      
    
  if ( 
is_gallery($galid) ) {
      
      
// always load the default config file
      
$filename_conf DIR_CONF.FILE_CONF;
      
      if ( 
check_perms($filename_conf) ) {
          include(
$filename_conf);
      }
    
      
// now, include all the possible config files
      
if ( $galid != "" ) {
      
$array_path explode("/"$galid);
      
$nb_levels count($array_path);
      
$path ""// grows inside the follwing loop ("gal1" -> "gal1/gal2"...)
      
for ($i=0$i<$nb_levels$i++) { // use "foreach ($array_path as $dir_name) {" in PHP4
        
$path .= $array_path[$i]."/";
        
$filename_conf DIR_GAL.$path.FILE_CONF;
        if ( 
check_perms($filename_conf) ) {
          include(
$filename_conf);
        }
      }
    }
  }
  
  
load_lang($lang);
  
load_theme($theme); 
  
post_initialization_check();

}


################################################################################
function post_initialization_check() {

  global 
$new_status_duration;
  global 
$thumbnails_per_page;
  global 
$thumbnails_per_row;
  global 
$subgal_display_level;
  
  if (
MODE_DEBUG) {
    print 
"<p>funtion POST_INITIALIZATION_CHECK<br>\n";
  }    
 
 
  if (! 
ereg("^[1-9][0-9]*$"$thumbnails_per_page)
      || (
$thumbnails_per_page 1) )
    
error("thumbnails_per_page: ".ERRMSG_NON_VALID_NUMBER_OF_PICTURES);
  
  if (! 
ereg("^[1-9][0-9]*$"$thumbnails_per_row)
      || (
$thumbnails_per_row 1) )
    
error("thumbnails_per_row: ".ERRMSG_NON_VALID_NUMBER_OF_PICTURES);
  
  if (
$subgal_display_level != INFINITE)
    if (! 
ereg("^[1-9][0-9]*$"$subgal_display_level)
        || (
$subgal_display_level 1) )
      
error("subgal_display_level: ".ERRMSG_NON_VALID_NUMBER_OF_PICTURES);
  
  if (! 
ereg("^[1-9][0-9]*$"$new_status_duration)
      || (
$new_status_duration 1) )
    
error("new_status_duration: ".ERRMSG_NON_VALID_NUMBER_OF_PICTURES);

}



################################################################################
# returns an array containing info about the number of pictures in a given gallery
# $array[0] = total number of pictures 
# $array[1] = number of new pictures

function count_pictures($galid) {
  
$nbpics_total 0;
  
$nbpics_new 0;
  
$galdir DIR_GAL.$galid;

  if (
MODE_DEBUG) {
    print 
"<p>function COUNT_PICTURES<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"nbpics_total: $nbpics_total<br>\n";
    print 
"galdir: $galdir<br>\n";
  }

  
$dir = @opendir($galdir);
  if (! 
$dir) return -1;
  
  while (
$file readdir($dir)) {
    if ( 
is_picture($file$galid) ) {
      
$nbpics_total++;
      if (
is_new($galdir."/".$file) ) $nbpics_new++;
    }
  }
  
closedir($dir);
  
$nbpics_info[0] = $nbpics_total;
  
$nbpics_info[1] = $nbpics_new;
  return 
$nbpics_info;
}



################################################################################
# Creates a sorted array of the thumbnails to diplay for a given gallery
# $galid - the gallery ID (must be always valid)
# $filter - the filter that defines the pictures to include in the list
# returns: a sorted array containing the thumbnails' basenames of the gallery

function create_pics_array($galid$filter) {

  
$picpath DIR_GAL.$galid."/";
  
$dir=opendir($picpath);

  if (
MODE_DEBUG) {
    print 
"<p>function CREATE_ARRAY_PICS<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"filter: $filter<br>\n";
    print 
"picpath: $picpath<br>\n";
  }
  

  while (
$file readdir($dir)) {
    if ( 
is_picture($file$galid) ) {
      if (
$filter == PARAM_VALUE_FILTER_NEW) {
        if ( 
is_new($picpath.$file) )
          
$pics[count($pics)] = $file;
      }
      else 
$pics[count($pics)] = $file;
    }
  }
  
closedir($dir);

  
// lexicographical sort
  // TODO: need to add some more possibilities here
  
if (count($pics) > 0sort($pics);

  return 
$pics;
}


################################################################################
function generate_thumbnails_navi($currentpg$nbpg$galid) {

  global 
$theme;
  global 
$file_icon_navi_next;
  global 
$file_icon_navi_prev;
  global 
$document_self;
  global 
$text_thumb_navi;

  if (
MODE_DEBUG) {
    print 
"<p>function GENERATE_THUMBNAILS_NAVI<br>\n";
    print 
"currentpg: $currentpg<br>\n";
    print 
"nbpg: $nbpg<br>\n";
    print 
"galid: $galid<br>\n";
  }
  
  
$filename_arrow_next DIR_THEMES.$theme."/".$file_icon_navi_next;
  
$filename_arrow_prev DIR_THEMES.$theme."/".$file_icon_navi_prev;
  
$b_arrow_next check_perms($filename_arrow_next);
  
$b_arrow_prev check_perms($filename_arrow_prev);  
  if (
$b_arrow_next && $b_arrow_prev) {
    
$arrow_next "<img src=\"$filename_arrow_next\" border=\"0\" align=\"middle\" alt=\"Navi icon next\" class=\"".CLASS_IMG_THMBNAVI_NEXT."\">";
    
$arrow_prev "<img src=\"$filename_arrow_prev\" border=\"0\" align=\"middle\" alt=\"Navi icon previous\" class=\"".CLASS_IMG_THMBNAVI_PREV."\">";
  }
  else {
    
$arrow_next ">>";
    
$arrow_prev "<<";
  }

  
// multi-language support
  
$text_thumb_navi ereg_replace(PATTERN_CURRENT_PAGE"$currentpg"$text_thumb_navi);
  
$text_thumb_navi ereg_replace(PATTERN_NB_PAGES"$nbpg"$text_thumb_navi);
  print 
" $text_thumb_navi - ";
  
  
// display the left arrow
  
if ($currentpg 1) {
    
$previouspg $currentpg 1;
    print 
"<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PAGE."=$previouspg\">$arrow_prev</a> ";
  }

  
// display the page numbers
  
for ($i 1$i <= $nbpg$i++) {
    if (
$i != $currentpg)
      print 
"<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PAGE."=$i\" class=\"navi\">$i</a> ";
    else print 
"$i "// don't make it an anchor if this is the current page
  
}
  
  
// display the right arrow
  
if ($currentpg $nbpg) {
    
$nextpg $currentpg 1;
    print 
"<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PAGE."=$nextpg\">$arrow_next</a> ";
  }
}

################################################################################ 
function display_filter_toggle($galid$filter$hasnew) {

  global 
$document_self;
  global 
$text_filter;
  global 
$text_filter_new;
  global 
$text_filter_all;
    
  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_FILTER_TOGGLE<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"filter: $filter<br>\n";
    print 
"hasnew: $hasnew<br>\n";
  }    
    
  if (
$hasnew) {
    if (
ereg(PARAM_VALUE_FILTER_NEW$filter) ) {
      
$togglelabel .= "<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid\">";
      
$togglelabel .= "$text_filter_all</a>";
    }
    else {
      
$togglelabel .= "<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_FILTER."=";
      
$togglelabel .= PARAM_VALUE_FILTER_NEW."\">$text_filter_new</a>";
    }
    print 
" <span class=\"".CLASS_SPAN_FILTERS."\">[$text_filter> ".$togglelabel."]</span>\n";
  }
}


################################################################################
# Prerequisite: is_gallery($galid) == true

function display_gallery_header($galid$filter) {
    
  global 
$theme;
  global 
$file_icon_gal;
  global 
$document_self;
  global 
$text_new_pictures;
  global 
$text_root_gallery;
  
  if (
MODE_DEBUG) {
    print 
"<p>function IS_GALLERY<br>\n";
    print 
"galid: $galid<br>\n";
  }
  
  
$arraygal explode("/"$galid);

  
// display "header"
  
if ( check_perms(DIR_THEMES.$theme."/".$file_icon_gal) ) {
    
$link "<img src=\"".DIR_THEMES.$theme."/".$file_icon_gal."\" border=\"0\" ";
    
$link .= "align=\"middle\" HSPACE=7 alt=\"Gallery icon\" class=\"".CLASS_IMG_FOLDER."\">";
  }
  else 
$link $text_root_gallery

  print 
"<div class=\"".CLASS_DIV_GALHEADER."\">";
  print 
"<a href=\"".$document_self."?\" class=\"".CLASS_TD_GALITEM_TITLE."\">$link</a>";

  
// display each gallery of the hierarchy
  
$linkgal "$arraygal[0]"// to avoid the first "/"
  
for ($i=0$i<count($arraygal)-1$i++) {
    
$labelgal ereg_replace("_"" "$arraygal[$i]);
    print 
" &gt;&gt; ";
    print 
"<a href=\"".$document_self."?".PARAM_NAME_GALID."=$linkgal\" ";
      print 
"class=\"".CLASS_DIV_GALHEADER."\">$labelgal</a>";
    
$linkgal .= "/".$arraygal[$i+1];
  }
  
$labelgal ereg_replace("_"" "$arraygal[$i]);
  print 
" >> $labelgal";
  
  
// status ?
  
if ($filter == PARAM_VALUE_FILTER_NEW) print " ($text_new_pictures)";
  print 
"\n</div>\n";
}


################################################################################
# Recursive function to display all galleries as a hierarchy

function generate_gal($galid$from_level) {

  global 
$theme;
  global 
$subgal_display_level;
  global 
$file_icon_pic_new;
  global 
$file_icon_gal;
  global 
$thumbnails_per_page;
  global 
$sort_gallery_by_name;
  global 
$document_self;
  global 
$text_filter_new;
  global 
$text_new_gallery;
  global 
$text_picture;
  global 
$text_pictures;
  global 
$text_new_pictures;
  global 
$text_new_picture;
  
$galdir DIR_GAL.$galid;  
  
  if (
MODE_DEBUG) {
    print 
"function GENERATE_GAL<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"from_level: $from_level<br>\n";
    print 
"galdir: $galdir\n";
  }
 
 
  
  if ( 
is_gallery($galid) ) $dir = @opendir($galdir);
  else 
error("$galid: ".ERRMSG_UNKNOWN_GALLERY);
 
  
$offset "";
 
  
// check for super gallery.
  
if ($galid == "") {
    
$super_gallery "";
  }
  else {
    
$super_gallery $galid."/";
    for (
$i=0$i $from_level$i++)
      
$offset .= "          ";
  }
  
  if (
check_perms(DIR_THEMES.$theme."/".$file_icon_pic_new)) { 
    
$string_new_gallery "<img src=\"".DIR_THEMES.$theme."/".$file_icon_pic_new."\" align=\"middle\" border=\"0\" alt=\"New picture icon\" class=\"".CLASS_IMG_NEW."\">";
    
$string_new_pictures "$string_new_gallery";
    
$string_new_picture "$string_new_gallery";
  }
  else {
    
$string_new_gallery "<span style=\"color: #ffd600\">$text_new_gallery</span>"
    
$string_new_pictures "<span style=\"color: #ffd600\">$text_new_pictures</span>";
    
$string_new_picture "<span style=\"color: #ffd600\">$text_new_picture</span>";
  }

  while (
$file readdir($dir)) {
    
// need management for unreadable dirs
    
if ($file != "." && $file != ".." && is_dir(DIR_GAL.$super_gallery.$file))
      
$gals[count($gals)] = $file;
  }
  if (
$sort_gallery_by_name == true)
    if (
count($gals) > 0)
      
sort($gals);

  
$max count($gals);
  for (
$i=0$i<$max$i++) {
    
$file $gals[$i]; //*
    
$sub_galid $super_gallery.$file//*
    
$gallery_name ereg_replace("_"" "$file);
    
$nbpics_info count_pictures($sub_galid);
    
$nb_pics $nbpics_info[0];
    
$nb_new_pics $nbpics_info[1];
 
    
// should never happen
    
if ($nb_pics || $nb_new_pics 0)
      
error(ERRMSG_NON_VALID_NUMBER_OF_PICTURES);
   
    else {
      if (
$thumbnails_per_page 0$page "&".PARAM_NAME_PAGE."=1";
      if (
$nb_pics == 0$substr_nb_pictures "";
      else {
        if (
$nb_pics 1$substr_nb_pictures "[ $nb_pics $text_pictures";
        else 
$substr_nb_pictures "[ $nb_pics $text_picture";
        
$allnew = ($nb_pics == $nb_new_pics);
        if (
$allnew)
          
$substr_nb_pictures "$string_new_gallery ".$substr_nb_pictures;
        if (
$nb_new_pics>0  && !$allnew) {
          
$substr_nb_pictures .= " ($nb_new_pics <a href=\"".$document_self."?".PARAM_NAME_GALID."=$sub_galid&".PARAM_NAME_FILTER."=".PARAM_VALUE_FILTER_NEW."\">";
          if (
$nb_new_pics == 1$substr_nb_pictures .= "$string_new_picture</a>)";
          else 
$substr_nb_pictures .= "$string_new_pictures</a>)";
        }
        
$substr_nb_pictures .= " ]";
      }
      print 
"<table border=\"0\" class=\"".CLASS_TABLE_GALITEM."\">\n";
      print 
"<tr>\n";
        
      
// display the folder icon
      
print "  <td rowspan=2 valign=\"top\" class=\"".CLASS_TD_GALITEM_ICON."\">\n";
      if ( 
check_perms(DIR_THEMES.$theme."/".$file_icon_gal) )
        print 
"  $offset<a href=\"".$document_self."?".PARAM_NAME_GALID."=$sub_galid\" class=\"".CLASS_TD_GALITEM_TITLE."\"><img src=\"".DIR_THEMES.$theme."/".$file_icon_gal."\" border=\"0\" align=\"middle\" HSPACE=7 VSPACE=7 alt=\"Gallery icon\" class=\"".CLASS_IMG_FOLDER."\"></a>\n";
      else print 
"$offset>>"// TODO: display some kind of ASCIIart ?
      
print "  </td>\n";
        
      
// display the gallery title
      
print "  <td class=\"".CLASS_TD_GALITEM_TITLE."\">\n";       
      print 
"  <a href=\"".$document_self."?".PARAM_NAME_GALID."=$sub_galid\" class=\"".CLASS_TD_GALITEM_TITLE."\">$gallery_name</a> $substr_nb_pictures \n";
      print 
"  </td>\n";
      print 
"</tr>\n";
        
      
// display the gallery caption
      
print "<tr>\n";
      print 
"  <td class=\"".CLASS_TD_GALITEM_CAPTION."\">\n";
      
$msg_file $galdir."/".$file."/".FILE_GAL_CAPTION;
      if (
check_perms($msg_file)) { // check perms
        
print "  ";
        include(
$msg_file);
      }
      print 
"  </td>\n";
      print 
"</tr>\n";
      print 
"</table>\n";
    }
 
    
// TODO check this: one test ?
    
if ($subgal_display_level == INFINITEgenerate_gal($sub_galid$from_level+1);
    else if (
$from_level $subgal_display_levelgenerate_gal($sub_galid$from_level+1);
  } 
// endfor 
  
closedir($dir);
}

################################################################################
function display_pic($galid$pcid$frpg$filter) {

  global 
$theme;
  
//global $display_thumbnails_with_pic;
  
global $file_icon_pic_prev;
  global 
$file_icon_pic_next;
  global 
$thumbnails_per_page;
  global 
$zoom_factors;
  global 
$document_self;
  global 
$text_pic_navi;
 
  
$pics create_pics_array($galid$filter);
  
$nb_pics count($pics);
  
$picture_path DIR_GAL.$galid."/";
  
$picture_name $pics[$pcid];
  
$picture_url $picture_path.$picture_name;  
  
$picture_msg $picture_url.EXT_PIC_CAPTION;
  
$gallery_name ereg_replace("_"" "$galid);
  
$gallery_name ereg_replace("/"" >> "$gallery_name);
  if (
$thumbnails_per_page != 0) {
    
$nb_pages $nb_pics $thumbnails_per_page;
    if (
$nb_pages > (int)($nb_pics $thumbnails_per_page))
      
$nb_pages = (int)++$nb_pages;
    if (
$frpg == ""$frpg = (int)($pcid/$thumbnails_per_page)+1// **
    
else if (($frpg 1) || ($frpg $nb_pages))
      
error("display_pic: Wrong parameters have been passed...");
  }
  
  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_PIC<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"picture_name: $picture_name<br>\n";
    print 
"picture_path: $picture_path<br>\n";
    print 
"picture_url: $picture_url<br>\n";
    print 
"picture_msg: $picture_msg<br>\n";
  }
  
  
  
  
  
// TODO error handling: clarify this
  
if (($pcid 0) || ($pcid $nb_pics-1) || $pcid == "")
    
error(ERRMSG_UNKNOWN_PICTURE);

  if (! 
is_gallery($galid) )
    
error(ERRMSG_UNKNOWN_GALLERY);


  if ( 
is_picture($picture_name$galid) ) {
    
$dim getimagesize($picture_url);
    
$previous $pcid 1;
    
$next $pcid 1;
        
    
// always display the gallery header
    
display_gallery_header($galid$filter);   

    
///////////////////////////////////////////
      // thumbnails are only displayed if wanted
      //if ($display_thumbnails_with_pic) {
      //////////////////////////////////////////
      
display_thumbnails($galid$pcid$frpg$filter);
      
// to avoid a call to the function above with false parameters if 
        // the visitor clicks on a previous/next picture arrow. It will 
        // be reinitialized to the page corresponding to the picture (**)
        
$frpg ""
    
//////////////////////////////////////////
    //}
    //else {
      //  $nbpics_info = count_pictures($galid);
      //  display_filter_toggle($galid, $filter, ($nbpics_info[1] > 0) );
      //}
      //////////////////////////////////////////
    
      // display the previous/next arrow section

    
if (check_perms(DIR_THEMES.$theme."/".$file_icon_pic_next)
        && 
check_perms(DIR_THEMES.$theme."/".$file_icon_pic_prev)) {
      
$string_next_pic "<img src=\"".DIR_THEMES.$theme."/".$file_icon_pic_next."\" border=\"0\" align=\"middle\" alt=\"Next picture icon\" class=\"".CLASS_IMG_PICTURE_NEXT."\">";
      
$string_prev_pic "<img src=\"".DIR_THEMES.$theme."/".$file_icon_pic_prev."\" border=\"0\" align=\"middle\" alt=\"Previous picture icon\" class=\"".CLASS_IMG_PICTURE_PREV."\">";
    }
    else {
      
$string_next_pic ">>";
      
$string_prev_pic "<<";
    }

    print 
"<br><br>\n";
    print 
"<table border=\"0\" cellspacing=0 align=\"center\" class=\"".CLASS_TABLE_PICTURE."\">\n";
    print 
"<tr>\n";
    print 
"  <td align=\"center\" class=\"".CLASS_TD_PICTURE_NAVI."\"><A NAME=\"pic\" id=\"".ID_PICTURE_NAVI."\"></a>\n";
    if (
$previous >= 0) print "  <a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PICID."=$previous&amp;".PARAM_NAME_FROMPAGE."=$frpg&amp;".PARAM_NAME_FILTER."=$filter#pic\">$string_prev_pic</a> ";
   
    
//multi-language support
    
$text_pic_navi ereg_replace(PATTERN_CURRENT_PIC"$next"$text_pic_navi);
    
$text_pic_navi ereg_replace(PATTERN_NB_PICS"$nb_pics"$text_pic_navi);
    print 
" $text_pic_navi ";

    if (
$next $nb_pics)print "<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PICID."=$next&amp;".PARAM_NAME_FROMPAGE."=$frpg&amp;".PARAM_NAME_FILTER."=$filter#pic\">$string_next_pic</a>\n";
    print 
"  </td>\n";
 
    
// Client side zoom buttons 
    
if (count($zoom_factors) > 0) { 
      print 
"</tr>\n<tr>\n  <td class=\"".CLASS_TD_ZOOM_FACTORS."\" align=\"center\">\n";
      for (
$i=0$i<count($zoom_factors); $i++) {
        
$new_height = (int)($dim[1]*$zoom_factors[$i]/100);
        
$new_width = (int)($dim[0]*$zoom_factors[$i]/100);
        print 
"<input type=\"button\" class=\"".CLASS_BUTTON_ZOOM_FACTORS."\" value=\" ".$zoom_factors[$i]."% \" ";
        print 
"onClick=\"document.getElementById('".ID_PICTURE."').setAttribute('height', $new_height); ";
        print 
"document.getElementById('".ID_PICTURE."').setAttribute('width', $new_width); ";
        print 
"document.getElementById('".ID_PICTURE_NAVI."').scrollIntoView();\">\n";
      }
      print 
"\n  </td>\n";
    }

    print 
"</tr>\n";
    
      
//if (! $display_thumbnails_with_pic)
      //  // should the visitor go back to the previous thumb page or the picture's one
    //  print "<tr><td align=\"center\">[ <a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&".PARAM_NAME_PAGE."=$frpg&".PARAM_NAME_FILTER."=$filter\">back to thumnails</a> ]</td></tr>\n";
    
      // Eventually display the picture
    
print "<tr>\n";
    print 
"  <td align=\"center\" class=\"".CLASS_TD_PICTURE_PIC."\">";
    print 
"<img id=\"".ID_PICTURE."\" src=\"$picture_url\" WIDTH=\"$dim[0]\" HEIGHT=\"$dim[1]\" alt=\"Picture ($picture_url)\" class=\"".CLASS_IMG_PICTURE."\">";
    print 
"  </td>\n";
    print 
"</tr>\n";
    print 
"<tr>\n";
    
      
// display the caption
    
print "  <td align=\"center\" class=\"".CLASS_TD_PICTURE_CAPTION."\">\n";
    if ( 
check_perms($picture_msg) ) {
      include(
$picture_msg);
    }
    else print 
" "// HTML 4.01 compliance
    
print "  </td>\n";
    print 
"</tr>\n";
    print 
"</table>\n";
  }
  else
    
error(ERRMSG_UNKNOWN_PICTURE);

}

################################################################################
function display_gal($galid$page$filter) {

  if (
MODE_DEBUG) {
    print 
"<p>function DISPLAY_GAL<br>\n";
    print 
"galid: $galid<br>\n";
    print 
"page: $page<br>\n";
    print 
"filter: $filter<br>\n";
  }
  
  if (! 
is_gallery($galid) )
    
error(ERRMSG_UNKNOWN_GALLERY);
  else {
    
// if a gallery is specified, display galleries stuff
    
if ( ! empty($galid) ) {
      if (
$page == ""$page 1;
      
display_gallery_header($galid$filter);
      
display_thumbnails($galid""$page$filter);      
      
// extra vertical padding before displaying the subgalleries
      
print "<br>";
    }
    
generate_gal($galid1);
  }
}


################################################################################
function display_thumbnails($galid$picid$page$filter) {
  global 
$theme;
  global 
$file_icon_pic_new;
  global 
$thumbnails_per_page;
  global 
$thumbnails_per_row;
  global 
$display_captions_with_thumbnails;
  global 
$document_self;
  global 
$text_filter_new;

  
$picspath DIR_GAL.$galid."/";
  
$pics create_pics_array($galid$filter);
  
$nbpics count($pics);
  if (
$picid == ""$picid = -1// to make sure the picture information are not highlighted
  
if ($thumbnails_per_page == 0) {
    
$offset_start 0;
    
$offset_stop $nbpics;
    
$frompg "";
  }
  else {
    
$nbpg $nbpics $thumbnails_per_page;
    if (
$nbpg > (int)($nbpics $thumbnails_per_page)) $nbpg = (int)++$nbpg;
    if (! isset(
$page) ) {
      
$offset_start 0;
      
$frompg 1;
    }
    else {
      if ((
$page == "") || ($page 1) || ($page $nbpg)) $page 1;
      
$offset_start = ($page-1)*$thumbnails_per_page;
      
$frompg $page;
    }
    
$offset_stop $offset_start $thumbnails_per_page;    
  }
  
// TODO if ($offset_start > $nbpics) { print"Trop de pages"; exit(-1); }
  
if ($offset_stop $nbpics$offset_stop $nbpics;
 
  if (
MODE_DEBUG) {
    print 
"function DISPLAY_THUMBNAILS<br>\n";
    print 
"picpath: $picpath<br>\n";
    print 
"nbpics: $nbpics<br>\n";
    print 
"picid: $picid<br>\n";
    print 
"startpg: $offset_start<br>\n";
    print 
"stoppg: $offset_stop<br>\n";
    print 
"frompg: $frompg<br>\n";
    print 
"nbpg: $nbpg<br>\n";
    print 
"page: $page<br>\n";
  }


 
  print 
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\" class=\"".CLASS_TABLE_THUMBNAILS."\">\n";
  print 
"<tr>\n";
  
  
$counter 0;
  
  for (
$i $offset_start$i $offset_stop$i++) {
    
$picture_name $pics[$i];
    
$picurl $picspath.$picture_name;
    
$thumbname PREF_THUMB.$pics[$i];
    
$thumburl $picspath.$thumbname;
    
$captionname $picurl.EXT_PIC_CAPTION;
    
$picdim getimagesize($picurl);
    
$thumbdim getimagesize($thumburl);
    
$picsize = (int) (filesize($picurl) / 1024);
    
$picindex $i 1// index that is displayed
    
$class_td_thumbnail_thumb CLASS_TD_THUMBNAILS_THUMB;
    
$class_img_thumbnail CLASS_IMG_THUMBNAIL;
    if (
$i == $picid) {
      
$class_td_thumbnail_thumb CLASS_TD_THUMBNAILS_THUMB_SELECTED;
      
$class_img_thumbnail CLASS_IMG_THUMBNAIL_SELECTED;
    }
    if ( 
is_new($picurl) && $filter != PARAM_VALUE_FILTER_NEW )
      if (
check_perms(DIR_THEMES.$theme."/".$file_icon_pic_new)) $string_new "<center><img src=\"".DIR_THEMES.$theme."/".$file_icon_pic_new."\" align=\"middle\" alt=\"New picture icon\" class=\"".CLASS_IMG_NEW."\"></center>";
      else 
$string_new "<center><span style=\"color: #ffd600\">$text_filter_new</span></center>";   

    
// new line
    
if ( ($counter++ % $thumbnails_per_row) == 0)
      if (
$counter 1) print "</tr>\n<tr>\n"// test for HTML 4.01 compatibility
    
    // TODO: valign=top does not work when there are new pictures amongst old ones 
    
print "  <td align=\"center\" valign=\"top\" class=\"$class_td_thumbnail_thumb\" nowrap>\n";
    print 
"  $string_new\n";
    print 
"<a href=\"".$document_self."?".PARAM_NAME_GALID."=$galid&amp;".PARAM_NAME_PICID."=$i";
      print 
"&amp;".PARAM_NAME_FROMPAGE."=$frompg&amp;".PARAM_NAME_FILTER."=$filter#pic\"$border_class>\n";
    print 
"  <img src=\"$thumburl\" WIDTH=\"$thumbdim[0]\" ";
      print 
"HEIGHT=\"$thumbdim[1]\" alt=\"Thumbnail ($thumburl)\" class=\"$class_img_thumbnail\"></a><br>\n";
    print 
"  [ $picdim[0]x$picdim[1] - $picsize KB ]";
   
    
// display caption along with the thumbnail 
    
if ($display_captions_with_thumbnails == true) {
      if (
check_perms($captionname)) {
        print 
"\n  <div class=\"".CLASS_DIV_THUMBNAILS_CAPTION."\">";
        include(
$captionname);
        print 
"</div>\n";
      }
    }

    print 
"  </td>\n";
  }
  
  
// navi bar generation
  
if ($nbpics 0) {
    print 
"</tr>\n";
    print 
"<tr>\n";
    print 
"  <td colspan=\"$thumbnails_per_row\" class=\"".CLASS_TD_THUMBNAILS_NAVI."\" align=\"right\">";
    
// display "thumbnail navi" if all the thumbs are not displayed on the same page
    
if ($thumbnails_per_page 0generate_thumbnails_navi($page$nbpg$galid);
    
// toggles
    
$nbpics_info count_pictures($galid);
    
display_filter_toggle($galid$filter, ($nbpics_info[1] > 0) );
  }
  
  
// for HTML 4.01 compatibility ...
  // if there are no thumbnails, then format the <td> markup correctly
  
if ($counter == 0) print "  <td>\n";
  
  print 
"  </td>\n";
  print 
"</tr>\n";
  print 
"</table>\n";
  
}



#############
# Main
#############

$param_galid "";
$param_picid "";
$param_page "";
$param_filter "";
$param_frompage "";

if (
REGISTER_GLOBALS) {
  
$var_galid PARAM_NAME_GALID;
  
$var_picid PARAM_NAME_PICID;
  
$var_page PARAM_NAME_PAGE;
  
$var_filter PARAM_NAME_FILTER;
  
$var_frompage PARAM_NAME_FROMPAGE;

  
$param_galid = $$var_galid;
  
$param_picid = $$var_picid;
  
$param_page = $$var_page;
  
$param_filter = $$var_filter;
  
$param_frompage = $$var_frompage;
}
else {
  
$param_galid $_GET[PARAM_NAME_GALID];
  
$param_picid $_GET[PARAM_NAME_PICID];
  
$param_page $_GET[PARAM_NAME_PAGE];
  
$param_filter $_GET[PARAM_NAME_FILTER];
  
$param_frompage $_GET[PARAM_NAME_FROMPAGE];
}

load_config($param_galid);
// the header which may rely on the config is now loaded
display_header();

if (! isset(
$param_galid) ) {
  
// the gallery is not specified -> generate the gallery "tree"
  
display_main_title();
  
generate_gal(""0);
}
else {
  if (! isset(
$param_picid) ) {
    
// we've got a gallery but no picture -> display thumbnails
    
display_main_title();
    
display_gal($param_galid$param_page$param_filter);
  }
  else {
    
display_main_title();
    
display_pic($param_galid$param_picid$param_frompage$param_filter);
  }
}

display_footer();

?>

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.