#!/usr/bin/perl -w # use strict; use POSIX qw(strftime ceil); use Getopt::Long; use Cwd; use HTML::Macro; use vars qw($opt_H $opt_L $opt_P $opt_a $opt_c $opt_k $opt_l $opt_r $opt_s $opt_x); use vars qw(%inodes $depth $dirsep); use vars qw($grandtotal); use vars qw(%Dircount %Kids %Dirinfo @City_Session); use vars qw($mainloop $pageloop $levelloop $ifp); use vars qw($thumbnail_ext $require_ext); use vars qw($template_dir $include_dir $db_dir $si_dir); use vars qw($DetailsPerSummary $TotalSummaryPages $maxfieldlength); use vars qw($DetailsItemIndex $ItemsPerDetailsPage $TotalDetailsPages); use vars qw($country $title $template_summary $template_details $template_si); use vars qw($breakpoint $summarybreak); use vars qw($lastmodified $cprtyear $firstbreak); #use vars qw(@urlpath @directory); use vars qw($opt_quiet); $| = 1; #print < \$title, "c|country=s" => \$country, "st|summarytemplate=s" => \$template_summary, "dt|detailstemplate=s" => \$template_details, "b|breakpoint=i" => \$breakpoint, "sb|summarybreakpoint=i" => \$summarybreak, "dir|directory=s" => \@directory, "u|urlpath=s" => \@urlpath, "db|database" => \$opt_db, "si|subjectindex=s" => \$subjectindex, "verbose" => \$opt_verbose, "h|help" => \$opt_help, "q|quiet" => \$opt_quiet ); &init(); $TotalDetailsPages=1; $DetailsItemIndex=0; $DetailsPerSummary=$summarybreak; $ItemsPerDetailsPage=$breakpoint; if ($result != 1 || $opt_help) { &Usage; } if (!defined $country) { print ">>Country missing!\n"; &Usage; } # Default to traversing current directory if no files specified if (!@directory) { my $currentdir = cwd(); push(@directory, $currentdir); @urlpath=(); push(@urlpath, ""); } if ($#directory != $#urlpath) { print ">> every directory must have a correpsonding urlpath prefix!\n"; &Usage; } # ===== PROGRAM START ######### print "===============START===============\n"; if ($subjectindex) { #use db instead } else { &process_dir(@directory, @urlpath); } if ($opt_db) { &create_database(); } else { if ($subjectindex) { &doSubjectIndexHTML($subjectindex); } else { $firstbreak=1; &calculatePage(""); $TotalSummaryPages=ceil($TotalDetailsPages/$DetailsPerSummary); &doSummaryHTML(); &doDetailsHTML(); } } print "\n=> Completed.\n"; #========== PROGRAM END =============== sub process_dir { my ($directory, $urlpath)=@_; my ($input_dir, $input_url); my $i=0; foreach my $dir (@directory) { print "Currently in: $dir\n"; print "--------------\n"; $dir =~ s|/$||; $input_dir=$dir; $input_url=$urlpath[$i]; $input_url =~ s|/$||; %inodes = (); # clear this at the start of each traversal $grandtotal += traverse($dir, $input_dir, $input_url); $i++; } print "Total \t $grandtotal\tfiles\n\n"; } sub traverse { my ($fn, $input_dir, $input_url) = @_;#$_[0]; my $total = 0; my $total_thisdir=0; my $thumbnail=""; my $thumbnail_bakup=""; my ($parent, $dirname); local $depth = $depth + 1; my @s = ($opt_L || $opt_H && $depth == 1) ? stat $fn : lstat $fn; # If we can't stat the file, return silently return 0 unless @s; if ($s[1] && !$opt_l) { # Check to see whether we've been here before (dev/inode is unique) if ($inodes{$s[0]}{$s[1]}) { return 0; } $inodes{$s[0]}{$s[1]} = 1; } # Do recursion if (opendir(DIR, $fn)) { foreach (readdir(DIR)) { my $subdir = ($fn =~ /$dirsep$/o) ? "$fn$_" : "$fn$dirsep$_"; # For regular files or links, tally them up if (-f $subdir) { my ($filename, $extension); $filename=$subdir; $filename =~ s|.*/||; # get the file extension $extension=$filename; $extension=~s|.*\.||; # increase the count if it is jpg if ($extension =~ /$require_ext/i) { $total_thisdir++; if (!$thumbnail_bakup) { $thumbnail_bakup = $filename; $thumbnail_bakup =~ s|$require_ext$|$thumbnail_ext|i; } } elsif ( (!$thumbnail) && ($extension =~ /$thumbnail_ext/i) ) { $thumbnail=$filename; } } elsif (-d $subdir) { if (!$opt_quiet) { print "Processing ... $subdir\n" unless /^\.{1,2}$/; } # Don't try to traverse '.' or '..' $total += traverse($subdir, $input_dir, $input_url) unless /^\.{1,2}$/; } } closedir DIR; if ( ( $total > 0 ) || ($total_thisdir>0) ) { $dirname=$fn; $dirname=~s|$input_dir||; # Total for all subdirectories $Dircount{$dirname}{total_allsubdir} += $total+$total_thisdir; # Total for this directory $Dircount{$dirname}{total_thisdir} += $total_thisdir; #Link (my $link=$dirname) =~ s|^/||; $Dirinfo{$dirname}{link}="$input_url/$link"; #Thumbnail if ($thumbnail) { $Dirinfo{$dirname}{thumbnail}="$input_url/$link/$thumbnail"; } else { $Dirinfo{$dirname}{thumbnail}="$input_url/$link/$thumbnail_bakup"; } $total+=$total_thisdir; if ($dirname) { ($parent = $dirname) =~ s|/[^/]+$||; # dirname # the following is to prevent the duplicated entries # from replacing an exisitng one my($match, $found, $item); foreach $item (@{ $Kids{$parent} }) { if ($dirname eq $item) { $match = $item; # must save $found = 1; last; } } if ($found) { ## do something with $match } else { ## unfound push @{ $Kids{$parent} }, $dirname; } #print "= traverse $dirname= - $total * parent=$parent\n"; } } } else { print STDERR "$0: could not read directory $fn: $!\n"; } return $total; } sub calculatePage { # find out in which details page the directory entry should be # # my($root) = $_[0]; local $depth = $depth + 1; # the details page where the entry is to be located if ($DetailsItemIndex > $ItemsPerDetailsPage-2) { $TotalDetailsPages++; $DetailsItemIndex=0; $Dirinfo{$root}{details_page} = $TotalDetailsPages; } else { my $dircount = $Dircount{$root}{total_thisdir}; if ($dircount>0) { $DetailsItemIndex++; } $Dirinfo{$root}{details_page} = $TotalDetailsPages; } # generate the page break for the use in DoDetails to create # multiple detailsx.html files if ($DetailsItemIndex > $ItemsPerDetailsPage-2) { $Dirinfo{$root}{page_break} = $TotalDetailsPages; if (!($TotalDetailsPages % $DetailsPerSummary)) { $Dirinfo{$root}{summary_break} = $TotalDetailsPages / $DetailsPerSummary ; push @City_Session, $root; $firstbreak=1; } else { $Dirinfo{$root}{summary_break} = 0; } } else { $Dirinfo{$root}{page_break} = 0; $Dirinfo{$root}{summary_break} = 0; if ($firstbreak && $root) { push @City_Session, $root; $firstbreak=0; } } # recursively down the structure if ($Kids{$root}) { # not a bachelor node my @Kids = @{ $Kids{$root} }; my $kid; for $kid (sort @Kids) { calculatePage($kid); } } } sub doSummaryHTML { # my ($what, $out, $templatefile, $breakpoint)=@_; print "Creating $TotalSummaryPages Summary files: "; open(FILE,">index.html") or die ("Cannot create index.html!"); print FILE ''; close(FILE) or die ("Cannot close file!"); # set up the HTML Macro handler and put all the global vars $ifp = HTML::Macro->new(); $ifp->set ('total', $grandtotal); $ifp->set ('country', $country); $ifp->set ('lastmodified', $lastmodified); $ifp->set ('copyrightyear', $cprtyear); $ifp->set ('totalpages', $TotalSummaryPages); $ifp->push_incpath($template_dir); # set up the loops for entries in the table $mainloop = $ifp->new_loop ('mainloop', 'i'); $mainloop->push_hash ({'i' => $TotalDetailsPages}); $levelloop = $mainloop-> new_loop ('levelloop', 'level', 'numfile', 'page', 'field1'); $firstbreak=1; displaySummary(""); $pageloop = $ifp->new_loop ('pageloop', 'page', 'pagelink'); for (my $i=1; $i<=$TotalSummaryPages; $i++) { $pageloop->push_array("Page $i", "index$i.html") if $i != $TotalSummaryPages; } my $result = $ifp->process ($template_summary); open(FILE,">index$TotalSummaryPages.html") or die ("Cannot create summary file!");; print FILE $result; close(FILE) or die ("Cannot close file!"); print "."; print "Done\n"; } # sub doHTML sub displaySummary { my($root, $prefix, $width) = (shift, shift || '', shift || 0); my ($total, $subtotal, $page, @field, $field, $field1, $field2, $field3, $tmpfield); local $depth = $depth + 1; if ($Kids{$root}) { # not a bachelor node my @Kids = @{ $Kids{$root} }; for my $kid (sort @Kids) { $total = $Dircount{$kid}{total_allsubdir}; $subtotal= $Dircount{$kid}{total_thisdir}; my $pagenum = $Dirinfo{$kid}{details_page}; @field=split(/\//, $kid); $page="details$pagenum.html"; # print "@field\n"; # print "depth=$depth - kid=$kid - Page=$page - Total=$subtotal\n"; # print "+++!$depth ===$field[1] $field[2], $page\n"; if ($depth==1) { # avoid linebreak after the field title if (!$firstbreak) { $levelloop-> push_array(0, 0, 0, 0); } $field1=$field[1]; $firstbreak=0; } if ($depth==2) { $field1=$field[2]; } if ($depth==3) { $field1=$field[3]; } # this fix up the beginning of next page where the mains # (e.g. city, types etc) are missing if ($depth <=3 ) { if ($firstbreak) { my $mykid=""; for (my $i=1; $i < $depth; $i++) { $mykid.="/$field[$i]"; $levelloop-> push_array($i, $Dircount{$mykid}{total_allsubdir}, $page, $field[$i]); } $firstbreak=0; } $field1=~s|_| |g; $levelloop-> push_array($depth, $total, $page, $field1); } # output to files my $current_page = $Dirinfo{$kid}{summary_break}; if (($current_page != 0) && ($current_page != $TotalSummaryPages) ) { $pageloop = $ifp->new_loop ('pageloop', 'page', 'pagelink'); for (my $i=1; $i<=$TotalSummaryPages; $i++) { $pageloop->push_array("Page $i", "index$i.html") if $i != $current_page; } my $output_summary="index$current_page.html"; my $result = $ifp->process ($template_summary); open(FILE,">$output_summary") or die ("Cannot create summary file!"); print FILE $result; close(FILE) or die ("Cannot close file!"); print "."; print ":" if !( $current_page % 5); $ifp = HTML::Macro->new(); $ifp->set ('total', $grandtotal); $ifp->set ('country', $country); $ifp->set ('lastmodified', $lastmodified); $ifp->set ('copyrightyear', $cprtyear); $ifp->set ('totalpages', $TotalSummaryPages); $ifp->push_incpath($template_dir); # set up the loops for entries in the table $mainloop = $ifp->new_loop ('mainloop', 'i'); $mainloop->push_hash ({'i' => $TotalSummaryPages}); $levelloop = $mainloop-> new_loop ('levelloop', 'level', 'numfile', 'page', 'field1'); $firstbreak=1; } displaySummary($kid); } } } sub doDetailsHTML { # my ($what, $out, $templatefile, $breakpoint)=@_; print "Creating $TotalDetailsPages Details files: "; # set up the HTML Macro handler and put all the global vars $ifp = HTML::Macro->new(); $ifp->set ('total', $grandtotal); $ifp->set ('country', $country); $ifp->set ('lastmodified', $lastmodified); $ifp->set ('copyrightyear', $cprtyear); $ifp->set ('totalpages', $TotalDetailsPages); $ifp->push_incpath($template_dir); # set up the loops for entries in the table $mainloop = $ifp->new_loop ('mainloop', 'i'); $mainloop->push_hash ({'i' => $TotalDetailsPages}); $levelloop = $mainloop-> new_loop ('levelloop', 'level', 'numfile', 'field1', 'link', 'thumbnail'); $firstbreak=1; displayDetails(""); generate_navlist($TotalDetailsPages); my $result = $ifp->process ($template_details); open(FILE,">details$TotalDetailsPages.html") or die ("Cannot create details file!");; print FILE $result; close(FILE) or die ("Cannot close file!"); print "."; print "Done\n"; } # sub doDetailsHTML sub displayDetails { my($root, $prefix, $width) = (shift, shift || '', shift || 0); my ($subtotal, $total, $output_details, @field, $field, $field1, $field2, $field3, $tmpfield); local $depth = $depth + 1; if ($Kids{$root}) { # not a bachelor node my @Kids = @{ $Kids{$root} }; for my $kid (sort @Kids) { $total = $Dircount{$kid}{total_allsubdir}; $subtotal= $Dircount{$kid}{total_thisdir}; my $extra_field=""; my $link = $Dirinfo{$kid}{link}; my $thumbnail = $Dirinfo{$kid}{thumbnail}; @field=split(/\//, $kid); # print "@field\n"; # print "$kid - Page=$Pages{$kid} - Total=$subtotal\n"; # print "+++!$depth ===$field[1] $field[2], $page\n"; # print "$total - $subtotal - $pagenum\n"; if ($depth==1) { # avoid linebreak after the field title if (!$firstbreak) { $levelloop-> push_array(0, 0, 0, 0, 0); } $field1=$field[1]; $firstbreak=0; } if ($depth==2) { $field1=$field[2]; } if ($depth==3) { $field1=$field[3]; } my $mydepth=$depth; # concatenate all the remaining fields together if ($depth>=4) { $field1=""; for (my $i=4; $i<=$depth; $i++) { $field1.="$field[$i]
"; } $mydepth=4; } else { # if the directory structure is less than 4 level # but has images in it, then output extra line if ($subtotal > 0) { $extra_field="details"; } } # this fix up the beginning of next page where the mains # (e.g. city, types etc) are missing if ($firstbreak) { my $mykid = ""; for (my $i=1; $i < $depth; $i++) { $mykid.="/$field[$i]"; $levelloop-> push_array($i, $Dircount{$mykid}{total_allsubdir}, $field[$i], $link, $thumbnail); } $firstbreak=0; } $field1=~s|_| |g; $levelloop-> push_array($mydepth, $total, $field1, $link, $thumbnail); # generate extra line with thumbnail for the level <4 # ie. the "details" field line if ($extra_field) { $levelloop-> push_array(4, $subtotal, $extra_field, $link, $thumbnail); } # output to files my $current_page = $Dirinfo{$kid}{page_break}; if (($current_page != 0) && ($current_page != $TotalDetailsPages) ) { generate_navlist($current_page); $output_details="details$current_page.html"; my $result = $ifp->process ($template_details); open(FILE,">$output_details") or die ("Cannot create details file!"); print FILE $result; close(FILE) or die ("Cannot close file!"); print "."; print ":" if !( $current_page % 5); $ifp = HTML::Macro->new(); $ifp->set ('country', $country); $ifp->set ('lastmodified', $lastmodified); $ifp->set ('copyrightyear', $cprtyear); $ifp->set ('totalpages', $TotalDetailsPages); $ifp->push_incpath($template_dir); $mainloop = $ifp->new_loop ('mainloop', 'i'); $mainloop->push_hash ({'i' => $TotalDetailsPages}); $levelloop = $mainloop-> new_loop ('levelloop', 'level', 'numfile', 'field1', 'link', 'thumbnail'); $firstbreak=1; } # multiple pages displayDetails($kid); } #for each kid } # if parent } sub mydebug { my $root = $_[0]; # print "==$root\n"; if ($Kids{$root}) { # not a bachelor node for my $kid (sort @{ $Kids{$root} }) { print "--$kid | "; print "$Dircount{$kid}{total_allsubdir} $Dircount{$kid}{total_thisdir}\n"; # print "::: $Dirinfo{$kid}{details_page} $Dirinfo{$kid}{page_break} $Dirinfo{$kid}{summary_break}\n"; mydebug($kid); } } } sub generate_navlist { my $current_page=$_[0]; if ($TotalDetailsPages>1) { my ($this, $previous, $next); my ($previous_txt, $next_txt, $this_txt); my ($begin, $end); $this=$current_page; $previous = $this-1 > 0 ? $this-1 : 0; $next = $this+1 <= $TotalDetailsPages? $this+1 : 0; #print " previous=$previous - this=$this - next=$next\n"; $previous_txt="details$previous.html"; $next_txt="details$next.html"; $ifp->set('prevok',$previous); $ifp->set('nextok',$next); $ifp->set('previous',$previous_txt); $ifp->set('next',$next_txt); $pageloop = $ifp->new_loop ('pageloop', 'current', 'page', 'pagelink'); $begin = $this-10 > 0 ? $this-10 : 1; $end = $this+9 <= $TotalDetailsPages ? $this+9:$TotalDetailsPages; for (my $i=$begin; $i<$this; $i++) { $pageloop->push_array($this, $i, "details$i.html"); } $this_txt.=$this; $pageloop->push_array($this, $this, "details$this.html"); for (my $i=$this+1; $i<=$end; $i++) { $pageloop->push_array($this, $i, "details$i.html"); } } } sub Usage { print < 3 summary pages. (default: 10) -dir, --directory=DIRECTORY directory of interest. can be used multiple times, need a urlpath prefix for each entry. (default: current directory if -dir is not used) -u, --urlpath=HTMLPART prefix to give complete url address. one for each directory. (default: empty string if -dir is not used) -q, --quiet quiet, remove excessive output. -h, --help print this help. -db, --createdatabase create database of the content. -si, --subjectindex=SUBJECT create subject index of SUBJECT (e.g. ivories). ---------------------------------------------------------------- To be implemented: -t, --title=STRING title of the page. -o 'outfile - default index.html index1.html ... indexn.html' -thumbnail_ext 'default - gif' -pic_ext 'default - jpg' -output_directory ---------------------------------------------------------------- Example: To generate normal summary and details pairs: $0 -country='france'\\ -dir "/raid1/cdroms/webready/france"\\ -urlpath "/raid1cdroms/france/"\\ -dir "/raid2/newimages/htdocs/bycountry/france/"\\ -u="/htdocs/bycountry/france/" To create or refresh database: $0 -db\\ -country='sicily'\\ -dir "/raid1/cdroms/webready/sicily"\\ -u "/raid1cdroms/sicily/"\\ -dir "/raid2/newimages/htdocs/bycountry/sicily/"\\ -u "/htdocs/bycountry/sicily/" To get a list of subject index $0 -c="france" -si="glass,church" EndUsage exit(0); } sub doSubjectIndexHTML { my ($subjectindex)=@_; #what, $out, $templatefile, $breakpoint)=@_; %Dircount = (); #total_allsubdir, total_thisdir %Dirinfo = (); # link, thumbnail, details_page, pagebreak %Kids = (); # used for traverse the directory tree structure &read_database($subjectindex); print "Creating Subject Index files: "; # set up the HTML Macro handler and put all the global vars $ifp = HTML::Macro->new(); $ifp->set ('total', $grandtotal); $ifp->set ('country', $country); $ifp->set ('subject', $subjectindex); $ifp->set ('lastmodified', $lastmodified); $ifp->set ('copyrightyear', $cprtyear); $ifp->set ('totalpages', $TotalDetailsPages); $ifp->push_incpath($template_dir); # set up the loops for entries in the table $mainloop = $ifp->new_loop ('mainloop', 'row');#, 'field', 'link', 'thumbnail'); $mainloop->push_array($grandtotal);#, $field[1], $link, $thumbnail); $levelloop = $mainloop->new_loop ('levelloop', 'numfield', 'class', 'field', 'link', 'thumbnail', 'colspan'); &tableheader(); $firstbreak=1; displaySubjectIndex(""); my $result = $ifp->process ($template_si); open(FILE,">$si_dir/$subjectindex.$country.html") or die ("Cannot create subject index file!"); print FILE $result; close(FILE) or die ("Cannot close file!"); print "."; print "Done\n"; } # sub doSubjectIndexHTML sub displaySubjectIndex { my($root, $prefix, $width) = (shift, shift || '', shift || 0); my ($total_this, $total_allsub); # my $output_details, @field, $field, $field1, $field2, $field3, $tmpfield); my ($numfields, $class, @fields, $dir); my ($link, $thumbnail); if ($Kids{$root}) { # not a bachelor node my @Kids = @{ $Kids{$root} }; for my $kid (sort @Kids) { $total_allsub = $Dircount{$kid}{total_allsubdir}; $total_this = $Dircount{$kid}{total_thisdir}; $link = $Dirinfo{$kid}{link}; $thumbnail = $Dirinfo{$kid}{thumbnail}; $dir=$kid; $numfields=@fields=split(/\//, $dir); for (my $i=1; $i<=$maxfieldlength-$numfields; $i++) { $dir.="/=>"; } $numfields=@fields=split(/\//, $dir); $mainloop->push_array($total_allsub);#, $field[1], $link, $thumbnail); $levelloop = $mainloop-> new_loop ('levelloop', 'numfield', 'class', 'field', 'link', 'thumbnail', 'colspan'); $class="details"; for (my $i=1; $i < $maxfieldlength; $i++) { my $cell; $cell="$fields[$i]"; $cell=~s|_| |g; $levelloop-> push_array(2, $class, $cell, "", "", ""); } $levelloop->push_array(3, $class, "$total_this images", $link, "", ""); displaySubjectIndex($kid); } } } sub read_database { my ($subjectindex)=@_; my $databasefile; my $total_img=0; my $total_entry=0; $databasefile="$db_dir/database_$country.txt"; open(DATABASE, $databasefile) or die ("Database File 'database_$country.txt' does not exist!"); print "Reading records from $country Database: Done\n"; my @si_array = split(/,/, $subjectindex); while (my $line = ) { my $match=1; foreach my $si (@si_array) { if ($line !~ /$si/) { $match=0; } #else { print $si;} } if ($match) {#($line =~ /$subjectindex/) { my ($dir, $img_this, $img_all, $thumb, $weblink) = split(/, /, $line); #print "$dir\n"; if ($dir && $img_this>0 ) { # print "$dir, $img_this, $img_all\n"; # my $fields=$dir; # $fields=~s|/*$subjectindex||; my @myfields=split(/\//, $dir); my $numfields=@myfields; if ($numfields>$maxfieldlength) { $maxfieldlength=$numfields; } # $dir="/$subjectindex"; # for (my $i=$numfields-1; $i>0; $i--) { # $dir.="/$myfields[$i]"; # } # print "===$dir\n"; # if ($img_this != $img_all) {print "$fields $img_this, $img_all\n"; } $total_entry++; $total_img+=$img_this; push @{ $Kids{""} }, $dir; $Dircount{$dir}{total_thisdir} = $img_this; $Dircount{$dir}{total_allsubdir} = $img_all; $Dirinfo{$dir}{link}=$weblink; $Dirinfo{$dir}{thumbnail}=$thumb; } } # if ($line match) } close(DATABASE) or die ("Cannot close file!"); print "Total $total_img images found "; print "in $total_entry directories\n\n"; } # sub read_database sub create_database { print "Creating `$country` Database File: Done\n"; open (DATABASE, ">$db_dir/database_$country.txt") or die ("Cannot write database!"); print DATABASE "$country - Total \t $grandtotal \t files\n"; print DATABASE "directory, #images_thisdir, #images_allsubdir, thumbnail, weblink\n"; print DATABASE "=========, ===============, =================, =========, =======\n"; &print_record(""); close (DATABASE) or die ("Cannot close file!"); print "Regenerating Combined Databases: Done\n\n"; opendir(DBDIR, "$db_dir") or die ("Cannot open DB Dir!"); my @alldbfiles = grep /^database_.*\.txt$/, readdir DBDIR; open(OUT, ">$db_dir/database_all.txt") or die ("Cannot create database_all.txt!"); foreach my $file (@alldbfiles) { if ($file =~ /database_all.txt/) { next; } open(IN, "$db_dir/$file") or die ("Cannot open $file!\n");; while () { print OUT $_; } close(IN) or die ("Cannot close file!"); # print $file."\n"; } close(OUT) or die ("Cannot close file!"); } sub print_record { my $root = $_[0]; if ($Kids{$root}) { # not a bachelor node for my $kid (sort @{ $Kids{$root} }) { # my $kid = $tmpkid; # $kid =~ s|^/||; # # $kid =~ s|/|, |g; print DATABASE "$kid, $Dircount{$kid}{total_thisdir}, $Dircount{$kid}{total_allsubdir}, "; print DATABASE "$Dirinfo{$kid}{thumbnail}, $Dirinfo{$kid}{link}\n"; # print "::: $Dirinfo{$kid}{details_page} $Dirinfo{$kid}{page_break} $Dirinfo{$kid}{summary_break}\n"; print_record($kid); } } } sub tableheader { my @tbheader1 = ("City", "Type", "Location", "Details"); my @tbheader2 = ("Total # images");#, "Thumbnail"); my $t1len=@tbheader1; my $t2len=@tbheader2; my $headerloop; my $cellloop; # print "$maxfieldlength $t1len $t2len\n"; $headerloop = $ifp->new_loop ('headerloop', 'row');#, 'field', 'link', 'thumbnail'); $headerloop->push_array($grandtotal);#, $field[1], $link, $thumbnail); $cellloop = $headerloop->new_loop ('cellloop', 'field', 'colspan'); for (my $i=0; $i<$t1len-1; $i++) { my $mytbheader=$tbheader1[$i]; $cellloop-> push_array($mytbheader, "1"); # print $mytbheader; } $cellloop-> push_array($tbheader1[$t1len-1], $maxfieldlength-$t1len); foreach my $mytbheader (@tbheader2) { $cellloop-> push_array($mytbheader, "1"); # print $mytbheader; } }