diff bins_edit @ 0:a84c32f131df 1.1.29

Import vendor version
author Peter Gervai <grin@grin.hu>
date Wed, 15 Oct 2008 23:28:56 +0200
parents
children 3021deef1599
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bins_edit	Wed Oct 15 23:28:56 2008 +0200
@@ -0,0 +1,436 @@
+#!/usr/bin/perl -w
+
+#    bins_edit for BINS Photo Album version 1.1.29
+#    Copyright (C) 2001-2004 Jérôme Sautret (Jerome@Sautret.org)
+#
+#    $Id: bins_edit,v 1.21 2004/10/24 13:19:16 jerome Exp $
+#
+#    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; see the file COPYING.  If not, write to
+#    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+#    Boston, MA 02111-1307, USA.
+
+#    Type "bins_edit -h" on command line for usage information.
+
+use strict;
+
+use Getopt::Long;
+use IO::File;
+use UNIVERSAL qw(isa);
+
+# XML parsing & writing
+use XML::Grove;
+use XML::Grove::Builder;
+use XML::Grove::Path;
+use XML::Grove::PerlSAX;
+use XML::Parser::PerlSAX;
+#use XML::Handler::XMLWriter;
+use XML::Handler::YAWriter;
+use Text::Iconv;
+use HTML::Entities;
+
+my $verbose = 1;
+my $html=0;
+
+my $localEncoding;
+$localEncoding = `locale charmap`;
+if ($? != 0 ) {
+  $localEncoding = "LATIN1";
+}
+else {
+if (! $localEncoding or ($localEncoding eq "ANSI_X3.4-1968")) {
+  chop($localEncoding);
+  # ANSI is unspeakably primitive, promote it.
+  $localEncoding = "LATIN1";
+  print "Forcing encoding to $localEncoding\n" if ($verbose >=2);
+}
+}
+my $converter = Text::Iconv->new($localEncoding, "UTF-8");
+
+# decode HTML entites which doesn't exist in XML
+sub decodeEntites{
+  my $s = shift;
+
+  my %entities = (
+		 AElig	=> 'Æ',	# capital AE diphthong (ligature)
+		 Aacute	=> 'Á',	# capital A, acute accent
+		 Acirc	=> 'Â',	# capital A, circumflex accent
+		 Agrave	=> 'À',	# capital A, grave accent
+		 Aring	=> 'Å',	# capital A, ring
+		 Atilde	=> 'Ã',	# capital A, tilde
+		 Auml	=> 'Ä',	# capital A, dieresis or umlaut mark
+		 Ccedil	=> 'Ç',	# capital C, cedilla
+		 ETH	=> 'Ð',	# capital Eth, Icelandic
+		 Eacute	=> 'É',	# capital E, acute accent
+		 Ecirc	=> 'Ê',	# capital E, circumflex accent
+		 Egrave	=> 'È',	# capital E, grave accent
+		 Euml	=> 'Ë',	# capital E, dieresis or umlaut mark
+		 Iacute	=> 'Í',	# capital I, acute accent
+		 Icirc	=> 'Î',	# capital I, circumflex accent
+		 Igrave	=> 'Ì',	# capital I, grave accent
+		 Iuml	=> 'Ï',	# capital I, dieresis or umlaut mark
+		 Ntilde	=> 'Ñ',	# capital N, tilde
+		 Oacute	=> 'Ó',	# capital O, acute accent
+		 Ocirc	=> 'Ô',	# capital O, circumflex accent
+		 Ograve	=> 'Ò',	# capital O, grave accent
+		 Oslash	=> 'Ø',	# capital O, slash
+		 Otilde	=> 'Õ',	# capital O, tilde
+		 Ouml	=> 'Ö',	# capital O, dieresis or umlaut mark
+		 THORN	=> 'Þ',	# capital THORN, Icelandic
+		 Uacute	=> 'Ú',	# capital U, acute accent
+		 Ucirc	=> 'Û',	# capital U, circumflex accent
+		 Ugrave	=> 'Ù',	# capital U, grave accent
+		 Uuml	=> 'Ü',	# capital U, dieresis or umlaut mark
+		 Yacute	=> 'Ý',	# capital Y, acute accent
+		 aacute	=> 'á',	# small a, acute accent
+		 acirc	=> 'â',	# small a, circumflex accent
+		 aelig	=> 'æ',	# small ae diphthong (ligature)
+		 agrave	=> 'à',	# small a, grave accent
+		 aring	=> 'å',	# small a, ring
+		 atilde	=> 'ã',	# small a, tilde
+		 auml	=> 'ä',	# small a, dieresis or umlaut mark
+		 ccedil	=> 'ç',	# small c, cedilla
+		 eacute	=> 'é',	# small e, acute accent
+		 ecirc	=> 'ê',	# small e, circumflex accent
+		 egrave	=> 'è',	# small e, grave accent
+		 eth	=> 'ð',	# small eth, Icelandic
+		 euml	=> 'ë',	# small e, dieresis or umlaut mark
+		 iacute	=> 'í',	# small i, acute accent
+		 icirc	=> 'î',	# small i, circumflex accent
+		 igrave	=> 'ì',	# small i, grave accent
+		 iuml	=> 'ï',	# small i, dieresis or umlaut mark
+		 ntilde	=> 'ñ',	# small n, tilde
+		 oacute	=> 'ó',	# small o, acute accent
+		 ocirc	=> 'ô',	# small o, circumflex accent
+		 ograve	=> 'ò',	# small o, grave accent
+		 oslash	=> 'ø',	# small o, slash
+		 otilde	=> 'õ',	# small o, tilde
+		 ouml	=> 'ö',	# small o, dieresis or umlaut mark
+		 szlig	=> 'ß',	# small sharp s, German (sz ligature)
+		 thorn	=> 'þ',	# small thorn, Icelandic
+		 uacute	=> 'ú',	# small u, acute accent
+		 ucirc	=> 'û',	# small u, circumflex accent
+		 ugrave	=> 'ù',	# small u, grave accent
+		 uuml	=> 'ü',	# small u, dieresis or umlaut mark
+		 yacute	=> 'ý',	# small y, acute accent
+		 yuml	=> 'ÿ',	# small y, dieresis or umlaut mark
+
+		 # Some extra Latin 1 chars that are listed in the HTML3.2 draft (21-May-96)
+		 copy   => '©',	# copyright sign
+		 reg    => '®',	# registered sign
+		 nbsp   => "\240", # non breaking space
+
+		 # Additional ISO-8859/1 entities listed in rfc1866 (section 14)
+		 iexcl  => '¡',
+		 cent   => '¢',
+		 pound  => '£',
+		 curren => '¤',
+		 yen    => '¥',
+		 brvbar => '¦',
+		 sect   => '§',
+		 uml    => '¨',
+		 ordf   => 'ª',
+		 laquo  => '«',
+		 'not'   => '¬', # not is a keyword in perl
+		 shy    => '­',
+		 macr   => '¯',
+		 deg    => '°',
+		 plusmn => '±',
+		 sup1   => '¹',
+		 sup2   => '²',
+		 sup3   => '³',
+		 acute  => '´',
+		 micro  => 'µ',
+		 para   => '¶',
+		 middot => '·',
+		 cedil  => '¸',
+		 ordm   => 'º',
+		 raquo  => '»',
+		 frac14 => '¼',
+		 frac12 => '½',
+		 frac34 => '¾',
+		 iquest => '¿',
+		 'times' => '×', # times is a keyword in perl
+		 divide => '÷',
+		);
+
+  while (my($entity, $char) = each(%entities)) {
+    $s =~ s/\&$entity\;/$char/g;
+  }
+  return $s;
+}
+
+sub charac_indent{
+  my $n = shift(@_);
+  my $s="\n";
+  for (1..$n){
+    $s .= "   ";
+  }
+  return XML::Grove::Characters->new ( Data => $s );
+}
+
+sub setField{
+  my $field = shift(@_);  # field to add or modify
+  my $value = shift(@_);  # value to set to field
+  my $fileType  = shift(@_);  # type of file (iamge or album)
+  my $document  = shift(@_);  # XML document as a Grove
+
+  if (! $html) {
+    $value = encode_entities($value, '\00-\31<&"');
+  }
+
+  my $characters =
+    XML::Grove::Characters->new( Data =>
+				 decodeEntites($value));
+  #my $characters = XML::Grove::Characters->new ( Data => $value );
+
+  my $fieldName;
+  my $fieldValue;
+  foreach my $element
+    (@{$document->at_path('/'.$fileType.'/description')->{Contents}}) {
+      if (isa($element, 'XML::Grove::Element') && $element->{Name} eq "field") {
+	$fieldName = $element->{Attributes}{'name'};
+	$fieldValue = "";
+	if ($fieldName eq $field) {
+	  print "  Modifying field '$fieldName' to '$value'... "
+	    if ($verbose >= 3);
+	  @{$element->{Contents}} = ( charac_indent(3),
+				      $characters,
+				      charac_indent(2));
+	  print "OK.\n" if ($verbose >= 3);
+	  return;
+	}
+      }
+    }
+
+  print "  Adding field '$field' with value '$value'... " if ($verbose >= 2);
+  my $element = XML::Grove::Element->new ( Name => 'field',
+					   Contents => [charac_indent(3),
+							$characters,
+							charac_indent(2)],
+					   Attributes => {"name" => $field});
+  push @{$document->at_path('/'.$fileType.'/description')->{Contents}},
+    (charac_indent(2), $element, charac_indent(1));
+
+  print "OK.\n" if ($verbose >= 2);
+}
+
+sub setFields{
+  my $file   = shift(@_);
+  my $fields = shift(@_);
+  my $album  = shift(@_);  # type of file (0 if image or 1 if album)
+  my $document;
+
+  my $fileType;
+  if ($album) {
+    $fileType = "album";
+  } else{
+    $fileType = "image";
+  }
+
+  if (-e $file) {
+    # Get XML document as a Grove
+    print " Reading file '$file'... " if ($verbose >= 2);
+    my $grove_builder = XML::Grove::Builder->new;
+    my $parser = XML::Parser::PerlSAX->new ( Handler => $grove_builder );
+    $document = $parser->parse ( Source => { SystemId => $file } );
+    print "OK.\n" if ($verbose >= 2);
+  } else {
+    print " Creating file '$file'... " if ($verbose >= 2);
+    my @elements;
+    push @elements, (charac_indent(1),
+		     XML::Grove::Element->new ( Name => 'description',
+						Contents => [charac_indent(1)]),
+		     charac_indent(1),
+		     XML::Grove::Element->new ( Name => 'bins',
+						Contents => [charac_indent(1)]),
+		    );
+    if (!$album) {
+      push @elements, ( charac_indent(1),
+			XML::Grove::Element->new ( Name => 'exif',
+						   Contents =>
+						   [charac_indent(1)]),
+		      );
+    }
+    push @elements, charac_indent(0);
+    my $element =
+      XML::Grove::Element->new ( Name => $fileType,
+				 Contents => \@elements);
+    $document = XML::Grove::Document->new ( Contents => [ $element ] );
+    print "OK.\n" if ($verbose >= 3);
+  }
+
+  my $fieldName;
+  my $fieldValue;
+  while ( ($fieldName, $fieldValue) = each(%$fields) ) {
+    if (defined $fieldValue) {
+      setField($fieldName, $fieldValue, $fileType, $document);
+    }
+  }
+
+  print " Writing file '$file'... " if ($verbose >= 2);
+  # Write the Grove to the desc file
+  my $fileHandler = new IO::File;
+  open($fileHandler, '>', $file)
+    or die("Cannot open file $file to write Exif tag ($!)");
+  binmode($fileHandler, ":utf8") if $^V ge v5.8.0;
+
+  my $my_handler = new XML::Handler::YAWriter( 'Output' => $fileHandler,
+					 #      'Escape' => {
+					#		    '--'  => '&mdash;',
+							    #'&'   => '&amp;',
+					#		   },
+					       'Encoding' => "UTF-8",
+					     );
+#  my $my_handler = XML::Handler::XMLWriter->new( Output => $fileHandler,
+#  						 Newlines => 0);
+  $document->parse(DocumentHandler => $my_handler);
+  close ($fileHandler) || bail ("can't close $file ($!)");
+  print "OK.\n" if ($verbose >= 2);
+}
+
+sub copyleft{
+print "\nbins_edit for BINS Photo Album 1.1.29 (http://bins.sautret.org/)\n";
+print "Copyright © 2001-2004 Jérôme Sautret (Jerome\@Sautret.org)\n";
+print "This is free software with ABSOLUTELY NO WARRANTY.\n";
+print "See COPYING file for details.\n\n";
+}
+
+sub usage{
+  my $exit=shift; # should we exit after usage information ?
+  copyleft();
+
+  print <<EoF ;
+bins_edit is a script to set fields in XML pictures description files for BINS.
+
+usage:
+bins_edit [-a|--album] [-m|--html]
+          [-t|--title title] [-e|--event event] [-l|--location location]
+          [-p|--people people] [-y|--date date] [-d|--description description]
+	  [--longdesc longDescription] [--shortdesc shortDesription]
+          [--sample pictureFileName]
+          [-g|--generic tag=value]
+          [-h|--help] [-v|--verbose] [-q|--quiet] file [files...]
+
+EoF
+
+  if ($exit){
+    print "Type bins_edit --help for complete help.\n";
+    exit ($exit);
+  }
+}
+
+
+sub help{
+  usage(0);
+  print <<EoF ;
+Options:
+  -t, --title, -e, --event event, -l, --location,
+  -p, --people, -y, --date, -d, --description :
+                   these switchs are used to set a value to a picture 
+                   desciption field.
+  -t, --title, --longdesc, --shortdesc, --sample :
+                   these switchs are used to set a value to an album
+                   desciption field (with --album option)
+  -a, --album :    edit album description.
+                   (default is editing image description)
+                   In this case, the file parameter must be the
+                   source directory of the album.
+                   Only the --title, --longdesc, --shortdesc and --sample
+                   switchs have sense with this option.
+  -m, --html :     input value will be considering as HTML code, thus,
+                   no HTML encoding will be done.
+  -v, --verbose :  this switch can appear several times to increase
+                   verbosity level.
+  -q, --quiet :    suppress output
+
+If filenames have no .xml suffix, it is added, so you can directly give
+picture names on the command line.
+Spaces and other special characters (even newlines) can be used in values
+given as parameters as long as they are enclosed between quotes.
+
+Examples:
+Set the title of the Image.jpg file to "My picture":
+bins_edit -t "My picture" Image.jpg
+
+Set the title and location of all JPEG pictures in the directory:
+bins_edit --title Holiday --location Paris *.jpg
+
+Use of HTML values:
+bins_edit --html --description '<b>BINS</b> is cool' file.jpg
+
+Set the title short description and sample image of the album 
+in the current directory (note the dot as final parameter):
+bins_edit -a -t "My Album" --sample image.jpg --shortdesc "This is my album" .
+
+EoF
+
+  exit 1;
+}
+
+
+sub main{
+  my %values;
+  my $album = 0;  # 1 if it a album description file
+
+
+  # process args
+  Getopt::Long::Configure("bundling");
+  GetOptions('t|title:s'       => \$values{title},
+	     'e|event:s'       => \$values{event},
+	     'l|location:s'    => \$values{location},
+	     'p|people:s'      => \$values{people},
+	     'y|date:s'        => \$values{date},
+	     'd|description:s' => \$values{description},
+	     'longdesc:s'      => \$values{longdesc},
+	     'shortdesc:s'     => \$values{shortdesc},
+	     'sample:s'        => \$values{sampleimage},
+	     'g|generic=s%'    => \%values,
+	     'm|html'          => \$html,
+	     'a|album'         => \$album,
+	     'v|verbose+'      => \$verbose,
+	     'q|quiet'         => sub { $verbose = 0 },
+	     'h|help'          => sub { help() },
+	     'copyright'       => sub { copyleft() },
+	    )
+    or usage(1);
+
+  my @files;
+  if ($#ARGV < 0) {
+    if ($album) {
+      @files = (".");
+    } else {
+      print "No files specified.\n";
+      usage(1)
+    }
+  } else {
+    @files = @ARGV;
+  }
+
+  copyleft() if ($verbose >=2);
+
+  foreach my $file (@files) {
+    if ($album) {
+      $file .= "/album.xml";
+    }
+    if ($file !~ m/.xml$/) {
+      $file .= ".xml";
+    }
+    print "Processing file '$file'... " if ($verbose >= 1);
+    print "\n" if ($verbose >= 2);
+    setFields($file, \%values, $album);
+    print "OK.\n" if ($verbose == 1);
+  }
+}
+
+main();