[Bins] Bug#308317: please support customized date strings

Martin Michlmayr tbm at cyrius.com
Tue May 10 00:24:53 BST 2005


* <tbm at cyrius.com> [2005-05-09 22:13]:
> > occurance of a date string is mentioned there so I'll later try to add
> > that to my patch.
> Looking at that now.

OK, here is a complete patch.

It introduces a new variable "dateString" which allows you to specify
the date string to be used (following date(1)).  It then converts the
%fields and %intlSubs into functions - this is needed to gain access
to $configHash and therefore to the value of "dateString".
$configHash has to be passed to these functions now, so a number of
functions had to be modified in order to do that.  Nothing major,
though.

This new "dateString" is used in two places:

 1. GENERATED_DATE will use it and a new DATE (without the leading
    "on") has been introduced.
 2. the "Transform" function for the EXIF date will now also follow
    dateString by default; this introduced a dependency on
    str2time from Date::Parse (packaged as libtimedate-perl in Debian)
    to parse the string from EXIF, but if that's a problem I can
    probably get rid of this dependency (but it would make the code
    uglier).

I also rewrote most of the "Transform" functionality.  This is now
cleaner and allows more than just reg ex substitution.  It also warns
the user if the eval fails.

Comments?



diff -urN bins-1.1.27~/bins bins-1.1.27/bins
--- bins-1.1.27~/bins	2005-05-09 22:05:59.370115208 +0100
+++ bins-1.1.27/bins	2005-05-10 00:15:19.951327536 +0100
@@ -69,6 +69,9 @@
 use XML::Handler::YAWriter;
 use Text::Iconv;
 
+# Date parsing
+use Date::Parse;
+
 #use XML::Handler::XMLWriter;
 #use XML::Grove::AsString;
 #use XML::Handler::Composer;
@@ -130,6 +133,9 @@
 			      # static-files directory.
 			      # The name should be unique for the entire album.
 
+   dateString => "%c",        # Specify the format of date strings; this
+                              # accepts all formats supported by date(1).
+
    excludeBackgroundImage => 1, # If set to 1, the image with the name given
                                 # in backgroundImage will be excluded from
 				# the current directory.
@@ -404,12 +410,12 @@
 $defaultConfig{fileActiveSizeNames} = \@fileActiveSizeNames;
 
 # Fields to display (in the list order) under the picture. These
-# fields are defined in the %fields hash below.
+# fields are defined in the getFields function below.
 my @mainFields = ("description", "people", "location", "date",
 		       "event");
-# Fields to display (in the list order) in the details page. These
-# fields are defined in the %fields hash below.
 
+# Fields to display (in the list order) in the details page. These
+# fields are in the getFields function below.
 my @secondaryFields = (
 		       # DigiCam
 		       _("BINS-SECTION DigiCam Info"),
@@ -472,7 +478,7 @@
 		       "BINS-SECTION end", # close the last section
 );
 
-my %fields =
+sub getFields {
   # The key is the string used as the name in the picture
   #   description file.
   # Name corresponds to the string displayed under the picture.
@@ -481,7 +487,9 @@
   # The value of the EXIF structure is only used if no value
   #   is present in the picture description file.
   # Transform is a Perl operator used to convert an exif value
-  #   to the desired format to display.
+  #   to the desired format to display.  It is evaluated as
+  #   normal Perl code and the result has to be in $_.
+  my %fields =
   (
    "title" =>
    { Name => _("Title"),
@@ -498,12 +506,13 @@
    "date" =>
    { Name => _("Date"),
      EXIF => "DateTimeOriginal",
-     Transform => 's%^(\d+):(\d+):(\d+) (.*)$%$3/$2/$1 $4%', # french date
-   },
+     Transform => '$_ = strftime $configHash->{dateString}, gmtime str2time "$_"',
+   # Alternatively, you could use regex substitution:
    # English version is yyyy:mm:dd hh:mm:ss to yyyy/mm/dd hh:mm:ss :
-   # "s%^(\\d+):(\\d+):(\\d+) (.*)$%\$1/\$2/\$3 \$4%",
+   # Transform => 's%^(\\d+):(\\d+):(\\d+) (.*)$%\$1/\$2/\$3 \$4%',
    # French version is yyyy:mm:dd hh:mm:ss to dd/mm/yyyy hh:mm:ss :
-   # 's%^(\d+):(\d+):(\d+) (.*)$%$3/$2/$1 $4%',
+   # Transform => 's%^(\d+):(\d+):(\d+) (.*)$%$3/$2/$1 $4%',
+   },
 
    "event" =>
    { Name => _("Event"),
@@ -777,7 +786,9 @@
      EXIF => "",
      #Tip => _(""),
    },
-);
+  );
+  return \%fields;
+}
 
 my @priorityExifTags = ();  # the field in this list are taken from
                             # the desc file, even if they are present
@@ -801,8 +812,10 @@
 		  });
 $defaultConfig{colorsSubs} = \%colorsSubs;
 
-# Strings to translate in the HTML template pages (if I18N is used)
-my %intlSubs = (  STRING_THUMBNAILS   => _("thumbnails"),
+sub getIntlSubs{
+    my $configHash = shift;
+    # Strings to translate in the HTML template pages (if I18N is used)
+    my %intlSubs = (  STRING_THUMBNAILS   => _("thumbnails"),
 		  STRING_IMAGELIST    => _("Image List"),
 		  STRING_HOME => _("Home"),
 		  STRING_UP   => _("Up one album"),
@@ -822,10 +835,13 @@
 		  BINS_VERSION             => "1.1.27",
 		  ENCODING                 => $defaultConfig{htmlEncoding},
 		  GENERATED_DATE       => _("on ").
-		                          local2html(strftime("%c", localtime)),
+		                          local2html(strftime($configHash->{dateString},
+		                          localtime)),
 		  BINS_ID =>
 		  '<!--$Id: bins,v 1.162 2004/10/24 18:04:07 jerome Exp $-->',
 	       );
+    return \%intlSubs;
+}
 
 # @knownImageExtentions defines file extensions that BINS can handle as
 # input image. BINS _should_ handle all input format of ImageMagick
@@ -880,6 +896,8 @@
 sub trimWhiteSpace;
 sub stringToBool;
 sub ignoreSet;
+sub getFields;
+sub getIntlSubs;
 
 sub generateThumbnailPages;
 sub generateThumbEntry;
@@ -1314,6 +1332,7 @@
     $subsHash{HOME_LINK} = $configHash->{homeURL};
     $subsHash{ALBUM_THUMB} = $configHash->{treePreview};
     $subsHash{PATH_SHOW_ICON} = $configHash->{pathShowIcon};
+    $subsHash{DATE} = strftime($configHash->{dateString}, localtime);
 
     renderTemplate("tree", $albumdir."tree.html",
 		 \%subsHash, $configHash);
@@ -2026,7 +2045,7 @@
 	my $atLeastOneField = 0;
 	my $tagValue;
 
-	$tablesubs{DESC_TABLE} = getDescTable(%imageInfo);
+	$tablesubs{DESC_TABLE} = getDescTable(\%imageInfo, $configHash);
 
 	if ($configHash->{defaultSize} >= 0){
 	  $tablesubs{THUMB_DEFAULT_SIZE} =
@@ -2059,6 +2078,7 @@
     $finalsubs{HOME_LINK} = $configHash->{homeURL};
     $finalsubs{FEEDBACK_LINK} = $configHash->{feedbackMail};
     $finalsubs{PATH_SHOW_ICON} = $configHash->{pathShowIcon};
+    $finalsubs{DATE} = strftime($configHash->{dateString}, localtime);
 
     renderTemplate("imagelist", $albumdir.$album."imagelist.html",
 		 \%finalsubs, $configHash);
@@ -2263,6 +2283,7 @@
     $templateParameters{HOME_LINK} = $configHash->{homeURL};
     $templateParameters{FEEDBACK_LINK} = $configHash->{feedbackMail};
     $templateParameters{PATH_SHOW_ICON} = $configHash->{pathShowIcon};
+    $templateParameters{DATE} = strftime($configHash->{dateString}, localtime);
 
     renderTemplate("subalbum", $albumdir.$album."index.html",
 		   \%templateParameters, $configHash);
@@ -2563,6 +2584,7 @@
   $subsHash{HOME_LINK} = $configHash->{homeURL};
   $subsHash{FEEDBACK_LINK} = $configHash->{feedbackMail};
   $subsHash{PATH_SHOW_ICON} = $configHash->{pathShowIcon};
+  $subsHash{DATE} = strftime($configHash->{dateString}, localtime);
   if ($albumHashRef->{numSubAlbums} == 0){
     $subsHash{FIRST_PAGE} = "index.html";
   }else{
@@ -2658,7 +2680,7 @@
       $sectionTitle = $tagName;
       $sectionTitle =~ s/^BINS-SECTION //;
     }else{
-      $tagValue = $fields{$tagName};
+      $tagValue = getFields($configHash)->{$tagName};
       if ($imageInfo->{$tagName}) {
 	my %row = (FIELD_NAME => $tagValue->{'Name'},
 		   FIELD_VALUE => local2html($imageInfo->{$tagName})
@@ -2701,10 +2723,11 @@
   $subs_hash{HOME_LINK} = $configHash->{homeURL};
   $subs_hash{FEEDBACK_LINK} = $configHash->{feedbackMail};
   $subs_hash{PATH_SHOW_ICON} = $configHash->{pathShowIcon};
+  $subs_hash{DATE} = strftime($configHash->{dateString}, localtime);
   $subs_hash{CUSTOM_CSS} = $configHash->{customStyleSheet};
 
   my @array;
-  push @array, {NAV_NAME => $intlSubs{STRING_BACKTOTHEIMAGE},
+  push @array, {NAV_NAME => getIntlSubs($configHash)->{STRING_BACKTOTHEIMAGE},
                 NAV_LINK => "javascript:history.back();",
                 NAV_ICON => "back.png",
 		NAV_ID => "back"};
@@ -3281,7 +3304,7 @@
   $subs_hash{ALBUM_PATH_LINKS} =
     pathLinks($album, $title, @{$albumHashRef->{parentDirNames}});
   $subs_hash{TITLE} = $title;
-  $subs_hash{DESC_TABLE} = getDescTable(%{$imageHashRef});
+  $subs_hash{DESC_TABLE} = getDescTable(\%{$imageHashRef}, $configHash);
   $subs_hash{DETAILS_LINK} = $imageHashRef->{detailsLink};
   $subs_hash{STRING_DETAILS} = _("Additional information on the picture");
 
@@ -3295,6 +3318,7 @@
     getRootDir($album)."static.".$configHash->{templateStyle};
   $subs_hash{HOME_LINK} = $configHash->{homeURL};
   $subs_hash{FEEDBACK_LINK} = $configHash->{feedbackMail};
+  $subs_hash{DATE} = strftime($configHash->{dateString}, localtime);
   if ($configHash->{backgroundImage}) {
       # Do not set this if not configured, so that template
       # can check for whether defined.
@@ -3336,14 +3360,14 @@
 }
 
 sub getDescTable{
-  my (%hash) = @_;
+  my ($hashref, $configHash) = @_;
 
   my @descTable;
   foreach my $tagName (@mainFields) {
-    if ($hash{$tagName}) {
-      my $value=$hash{$tagName};
+    if (${%$hashref}{$tagName}) {
+      my $value=${%$hashref}{$tagName};
       $value =~ s/'/&#39;/g  ; # in case it's used in javascript code
-      push @descTable, {DESC_FIELD_NAME => $fields{$tagName}->{'Name'},
+      push @descTable, {DESC_FIELD_NAME => getFields($configHash)->{$tagName}->{'Name'},
 			DESC_FIELD_VALUE => $value,
 		       };
     }
@@ -3474,7 +3498,7 @@
   %{$templateParameters} =
     (%{$templateParameters},
      %{$configHash->{colorsSubs}{$configHash->{colorStyle}}},
-     %intlSubs,
+     %{getIntlSubs($configHash)},
     );
 
   # open the html template
@@ -3581,7 +3605,7 @@
   if (-e $descFile) {
     beVerboseN("  Reading desc file $descFile.", 3);
     $document = getXMLAsGrove($descFile);
-    %descHash   = getDescXML($document);
+    %descHash   = getDescXML($document, $configHash);
     #$descHash{descFileName} =  uri_escape($descFile, '^-A-Za-z0-9/_\.');
     $configHash = getConfigXML($document, '/image/bins', $configHash);
     %exifHash   = getExifXML($document, \@priorityList);
@@ -3606,7 +3630,7 @@
 # Given an XML doc as a Grove, returns
 # fields from that images description file.
 sub getDescXML{
-  my $document = shift(@_);
+  my ($document, $configHash) = @_;
   my $fieldName;
   my $fieldValue;
   my %descHash;
@@ -3619,7 +3643,7 @@
 	  && $element->{Name} eq "field") {
 	$fieldName = $element->{Attributes}{'name'};
 	$fieldValue = "";
-	if (grep (/^$fieldName$/, keys(%fields))) {
+	if (grep (/^$fieldName$/, keys(%{getFields($configHash)}))) {
 	  beVerbose("    Reading field '$fieldName':", 3);
 	  foreach my $characters (@{$element->{Contents}}) {
 	    #if (UNIVERSAL::isa($characters, 'XML::Grove::Characters')) {
@@ -4045,19 +4069,26 @@
     }
 
     # add value to desc Hash if field is void
-    foreach my $field (keys(%fields)) {
-      my $fieldExif = $fields{$field}->{'EXIF'};
+    foreach my $field (keys(%{getFields($configHash)})) {
+      my $fieldExif = getFields($configHash)->{$field}->{'EXIF'};
       if ((! $descHash->{$field}) && $fieldExif && $exifHash->{$fieldExif}) {
 	beVerboseN("  Using '$field' from EXIF data: ".
  		   $exifHash->{$fieldExif}, 3);
 
-	$descHash->{$field} = $exifHash->{$fieldExif};
-	if ($fields{$field}->{'Transform'}) {
-	  beVerbose("  Evaluating ".
-		    "$descHash->{$field} =~ ".$fields{$field}->{'Transform'}.
-		    " to ", 4);
-	  eval '$descHash->{$field} =~ '.$fields{$field}->{'Transform'};
-	  beVerboseN("'$descHash->{$field}'.", 4);
+	my $func = getFields($configHash)->{$field}->{'Transform'};
+	if ($func) {
+	  $_ = $exifHash->{$fieldExif};
+	  beVerbose("  Evaluating '$func' from '$_'", 4);
+	  eval $func;
+	  if ($@) {
+	    beVerboseN("", 4);
+	    print("Error: evaluation of transformation for $field failed.\n");
+	    exit 2;
+	  }
+	  $descHash->{$field} = $_;
+	  beVerboseN(" to '$descHash->{$field}'.", 4);
+	} else {
+	  $descHash->{$field} = $exifHash->{$fieldExif};
 	}
       }
     }
diff -urN bins-1.1.27~/doc/bins.sgml bins-1.1.27/doc/bins.sgml
--- bins-1.1.27~/doc/bins.sgml	2005-05-09 22:05:59.374114600 +0100
+++ bins-1.1.27/doc/bins.sgml	2005-05-09 23:54:20.467798136 +0100
@@ -430,6 +430,15 @@
 	    </varlistentry>
 
 	    <varlistentry>
+	      <term>dateString</term>
+	      <listitem>
+		<para>Specify the format of date strings.  This variable
+		accepts all formats supported by <command>date(1)</command>.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
 	      <term>defaultSize</term>
 	      <listitem>
 		<para>Size to use when user clicks directly on the


-- 
Martin Michlmayr
http://www.cyrius.com/


More information about the Bins mailing list