attempt to support utf8 better
[mkgallery.git] / mkgallery.pl
index f7ef6c3e7ef4ff41411a9b379e9b42e4e8269310..8bed35cb1d594efd3fdb17cb7703751757ddb198 100755 (executable)
@@ -6,7 +6,7 @@ my $version='$Id$';
 # Makes use of modified "slideshow" javascript by Samuel Birch
 # http://www.phatfusion.net/slideshow/
 
-# Copyright (c) 2006-2008 Eugene G. Crosser
+# Copyright (c) 2006-2013 Eugene G. Crosser
 
 #  This software is provided 'as-is', without any express or implied
 #  warranty.  In no event will the authors be held liable for any damages
@@ -35,14 +35,15 @@ use Image::Info qw/image_info dim/;
 use Term::ReadLine;
 use Getopt::Long;
 use Encode;
-use encoding 'utf-8';
+use UUID;
+use utf8;
 binmode(STDOUT, ":utf8");
 
 my $haveimagick = eval { require Image::Magick; };
 { package Image::Magick; }     # to make perl compiler happy
 
-my $haverssxml = eval { require XML::RSS; };
-{ package XML::RSS; }          # to make perl compiler happy
+my $havegeoloc = eval { require Image::ExifTool::Location; };
+{ package Image::ExifTool::Location; } # to make perl compiler happy
 
 my @sizes = (160, 640, 1600);
 my $incdir = ".gallery2";
@@ -50,11 +51,9 @@ my $incdir = ".gallery2";
 ######################################################################
 
 my $incpath;
-my $rssobj;
 my $debug = 0;
 my $asktitle = 0;
 my $noasktitle = 0;
-my $rssfile = "";
 
 charset("utf-8");
 
@@ -63,33 +62,26 @@ unless (GetOptions(
                'incpath'=>\$incpath,
                'asktitle'=>\$asktitle,
                'noasktitle'=>\$noasktitle,
-               'rssfile=s'=>\$rssfile,
                'debug'=>\$debug)) {
        &help;
 }
 
-if ($rssfile && ! $haverssxml) {
-       print STDERR "You need to get XML::RSS from CPAN to use --rssfile\n";
-       exit 1;
-}
-
 my $term = new Term::ReadLine "Edit Title";
+binmode($term->IN, ':utf8');
 
 FsObj->new(getcwd)->iterate;
-if ($rssobj) { $rssobj->{'rss'}->save($rssobj->{'file'}); }
 
 sub help {
 
        print STDERR <<__END__;
 usage: $0 [options]
  --help:        print help message and exit
- --incpath:     do not try to find .gallery2 diretory upstream, use
+ --incpath:     do not try to find .gallery2 directory upstream, use
                 specified path (absolute or relavive).  Use with causion.
  --debug:       print a lot of debugging info to stdout as you run
  --asktitle:    ask to edit album titles even if there are ".title" files
  --noasktitle:  don't ask to enter album titles even where ".title"
                 files are absent.  Use partial directory names as titles.
- --rssfile=...:        build RSS feed for newly added "albums", give name of rss file
 __END__
 
        exit 1;
@@ -117,11 +109,10 @@ sub new {
                $class = $this;
                my $root=shift;
                $self = {
-                               -depth=>0,
                                -root=>$root,
                                -fullpath=>$root,
                        };
-               # fill in -inc, -rss, -relpath
+               # fill in -inc, -relpath
                initpaths($self); # we are not blessed yet, so cheat.
        }
        bless $self, $class;
@@ -159,6 +150,7 @@ sub initpaths {
                                        $pos=index($inc,'/',$pos+1)) {
                        $dp++;
                }
+               $self->{-depth} = $dp;
                for ($pos=length($fullpath);$dp>0 && $pos>0;
                                        $pos=rindex($fullpath,'/',$pos-1)) {
                        $dp--;
@@ -169,88 +161,13 @@ sub initpaths {
                $self->{-relpath} = $relpath;
                $self->{-toppath} = substr($fullpath,0,$pos);
                #print "rel=$relpath, top=$self->{-toppath}, inc=$inc\n";
-               initrss($self);
        } else {
                $self->{-inc} = 'NO-.INCLUDE-IN-PATH/'; # won't work anyway
-               $self->{-rss} = '';
                $self->{-relpath} = '';
+               $self->{-depth} = 0;
        }
 }
 
-sub initrss {
-       my $self=shift;         # this is not a method but we cheat
-       my $fullpath=$self->{-fullpath};
-       my $toppath=$self->{-toppath};
-       my $inc=$self->{-inc}.$incdir.'/';
-       my $conffile=$toppath.'/'.$incdir.'/rss.conf';
-       my $CONF;
-
-       if ($rssfile) {
-               if (open($CONF,">".$conffile)) {
-                       print $CONF "file: ",$rssfile,"\n";
-                       close($CONF);
-               } else {
-                       print STDERR "could not open $conffile: $!\n";
-               }
-       } else {
-               if (open($CONF,$conffile)) {
-                       my $ln=<$CONF>;
-                       close($CONF);
-                       chop $ln;
-                       my ($k,$v)=split(':', $ln);
-                       $k =~ s/^\s*//;
-                       $k =~ s/\s*$//;
-                       $v =~ s/^\s*//;
-                       $v =~ s/\s*$//;
-                       if ($k eq 'file') {
-                               $rssfile=$v;
-                       }
-               }
-       }
-
-       return unless ($rssfile);
-
-       $rssobj->{'file'} = $self->{-toppath}.'/'.$rssfile;
-       $rssobj->{'rss'} = new XML::RSS (version=>'2.0');
-       if ( -f $rssobj->{'file'} ) {
-               $rssobj->{'rss'}->parsefile($rssobj->{'file'});
-               my $itemstodel = @{$rssobj->{'rss'}->{'items'}} - 15;
-               while ($itemstodel-- > 0) {
-                       pop(@{$rssobj->{'rss'}->{'items'}})
-               }
-               $rssobj->{'rss'}->save($rssobj->{'file'});
-       } else {
-               my $link;
-               my $p1;
-               my $p2;
-               for ($p1=0,$p2=length($toppath);
-                               substr($rssfile,$p1,3) eq '../' && $p2>0;
-                               $p1+=3,$p2=rindex($toppath,'/',$p2-1)) {;}
-               $link=substr($toppath,$p2);
-               $link =~ s%^/%%;
-               $link .= '/' if ($link);
-               while (($p1=index($rssfile,'/',$p1+1)) >= 0) {
-                       $link = '../'.$link;
-               }
-               
-               $rssobj->{'rss'}->channel(
-                       title=>'Gallery',
-                       link=>$link,
-                       description=>'Gallery Feed',
-                       #language=>$language,
-                       #rating=>$rating,
-                       #copyright=>$copyright,
-                       #pubDate=>$pubDate,
-                       #lastBuildDate=>$lastBuild,
-                       #docs=>$docs,
-                       #managingEditor=>$editor,
-                       #webMaster=>$webMaster
-               );
-               $rssobj->{'rss'}->save($rssobj->{'file'});
-       }
-       $self->{-rss} = $rssobj->{'rss'};
-}
-
 sub iterate {
        my $self = shift;
        my $fullpath .= $self->{-fullpath};
@@ -365,6 +282,16 @@ sub isimg {
        my $self = shift;
        my $fullpath = $self->{-fullpath};
        return 0 unless ( -f $fullpath );
+
+       if ($havegeoloc) {
+               my $exif = new Image::ExifTool;
+               $exif->ExtractInfo($fullpath);
+               my ($la,$lo) = $exif->GetLocation();
+               if ($la && $lo) {
+                       $self->{-geoloc} = [$la,$lo];
+               }
+       }
+
        my $info = image_info($fullpath);
        if (my $error = $info->{error}) {
                if (($error !~ "Unrecognized file format") &&
@@ -430,8 +357,10 @@ sub edittitle {
        my $self = shift;
        my $fullpath = $self->{-fullpath};
        my $title;
+       my $titleimage;
        my $T;
-       if (open($T,'<'.$fullpath.'/.title')) {
+       my $TI;
+       if (open($T,'<:encoding(utf8)', $fullpath.'/.title')) {
                $title = <$T>;
                $title =~ s/[\r\n]*$//;
                close($T);
@@ -443,7 +372,7 @@ sub edittitle {
                print $OUT "Enter title for $fullpath\n";
                $title = $term->readline($prompt.' >',$title);
                $term->addhistory($title) if ($title);
-               if (open($T,'>'.$fullpath.'/.title')) {
+               if (open($T,'>:encoding(utf8)', $fullpath.'/.title')) {
                        print $T $title,"\n";
                        close($T);
                }
@@ -452,6 +381,13 @@ sub edittitle {
                $title=$self->{-relpath};
        }
        $self->{-title}=$title;
+       if (open($TI,'<:encoding(utf8)', $fullpath.'/.titleimage')) {
+               $titleimage = <$TI>;
+               $titleimage =~ s/[\r\n]*$//;
+               close($TI);
+               #print STDERR "found title image \"",$titleimage,"\"\n";
+               $self->{-titleimage}=$titleimage;
+       }
        print "title in $fullpath is $title\n" if ($debug);
 }
 
@@ -549,11 +485,10 @@ sub makeaux {
                                $toggletext = 'Play-&gt;';
                        }
                        my $F;
-                       unless (open($F,'>'.$fn)) {
+                       unless (open($F,'>:encoding(utf8)', $fn)) {
                                warn "cannot open \"$fn\": $!";
                                next;
                        }
-                       binmode($F, ":utf8");
                        if ($refresh eq 'slide') {
                                print $F start_html(
                                        -encoding=>"utf-8",
@@ -594,7 +529,7 @@ sub makeaux {
        my $fn = sprintf("%s/.html/%s-info.html",$dn,$name);
        if (isnewer($self->{-fullpath},$fn)) {
                my $F;
-               unless (open($F,'>'.$fn)) {
+               unless (open($F,'>:encoding(utf8)', $fn)) {
                        warn "cannot open \"$fn\": $!";
                        return;
                }
@@ -629,25 +564,17 @@ sub startindex {
        my $block = $self->{-fullpath}.'/.noindex';
        $fn = '/dev/null' if ( -f $block );
        my $IND;
-       unless (open($IND,'>'.$fn)) {
+       unless (open($IND,'>:encoding(utf8)', $fn)) {
                warn "cannot open $fn: $!";
                return;
        }
-       binmode($IND, ":utf8");
        $self->{-IND} = $IND;
 
        my $inc = $self->{-inc}.$incdir.'/';
        my $title = $self->{-title};
-       my $rsslink="";
-       if ($rssobj) {
-               $rsslink=Link({-rel=>'alternate',
-                               -type=>'application/rss+xml',
-                               -title=>'RSS',
-                               -href=>$self->{-inc}.$rssfile});
-       }
+       my $titleimage = $self->{-titleimage};  
        print $IND start_html(-title => $title,
                        -encoding=>"utf-8",
-                       -head=>$rsslink,
                        -style=>[
                                {-src=>$inc."gallery.css"},
                                {-src=>$inc."custom.css"},
@@ -667,7 +594,7 @@ sub startindex {
                                -id => 'indexContainer'}),
                "\n";
        my $EVL;
-       if (open($EVL,$self->{-toppath}.'/'.$incdir.'/header.pl')) {
+       if (open($EVL, '<:encoding(utf8)', $self->{-toppath}.'/'.$incdir.'/header.pl')) {
                my $prm;
                while (<$EVL>) {
                        $prm .= $_;
@@ -677,6 +604,8 @@ sub startindex {
                        -version        => $version,
                        -depth          => $self->{-depth},
                        -title          => $title,
+                       -titleimage     => $titleimage,
+                       -path           => $self->{-fullpath},
                        -breadcrumbs    => "breadcrumbs unimplemented",
                );
                print $IND eval $prm,"\n";
@@ -684,8 +613,14 @@ sub startindex {
                print STDERR "could not open ",
                        $self->{-toppath}.'/'.$incdir.'/header.pl',
                        " ($!), reverting to default header";
-               print $IND a({-href=>"../index.html"},"UP"),"\n",
-                       h1({-class=>'title'},$title),"\n",
+               print $IND a({-href=>"../index.html"},"UP"),"\n";
+               if ($titleimage) {
+                       print $IND img({-src=>$titleimage,
+                                       -class=>'titleimage',
+                                       -alt=>'Title Image'}),"\n";
+               }
+               print $IND h1({-class=>'title'},$title),
+                       br({-clear=>'all'}),"\n";
        }
 }
 
@@ -695,7 +630,7 @@ sub endindex {
 
        print $IND end_div;
        my $EVL;
-       if (open($EVL,$self->{-toppath}.'/'.$incdir.'/footer.pl')) {
+       if (open($EVL, '<:encoding(utf8)', $self->{-toppath}.'/'.$incdir.'/footer.pl')) {
                my $prm;
                while (<$EVL>) {
                        $prm .= $_;
@@ -705,6 +640,7 @@ sub endindex {
                        -version        => $version,
                        -depth          => $self->{-depth},
                        -title          => $self->{-title},
+                       -titleimage     => $self->{-titleimage},
                        -breadcrumbs    => "breadcrumbs unimplemented",
                );
                print $IND eval $prm,"\n";
@@ -717,20 +653,6 @@ sub endindex {
 
        close($IND) if ($IND);
        undef $self->{-IND};
-       if ($rssobj) {
-               my $rsstitle=sprintf "%s [%d images, %d subalbums]",
-                               $self->{-title},
-                               $self->{-numofimgs},
-                               $self->{-numofsubs};
-               my $rsslink=$rssobj->{'rss'}->channel('link').
-                       $self->{-relpath}."index.html";
-               $rssobj->{'rss'}->add_item(
-                       title           => $self->{-title},
-                       link            => $rsslink,
-                       description     => $rsstitle,
-                       pubDate         => time2str(time),
-               );
-       }
 }
 
 sub startsublist {
@@ -783,20 +705,28 @@ sub img_entry {
        $self->{-parent}->{-numofimgs}++;
 
        print $IND a({-name=>$name}),"\n",
-               start_table({-class=>'slide'}),start_Tr,start_td,"\n",
-               div({-class=>'slidetitle'},
+               start_table({-class=>'slide'}),start_Tr,start_td,"\n";
+       print $IND div({-class=>'slidetitle'},
                        "\n ",a({-href=>".html/$name-info.html",
                                -title=>'Image Info: '.$name,
                                -class=>'infoBox'},
                                $title),"\n"),"\n",
-               div({-class=>'slideimage'},
-                       "\n ",a({-href=>".html/$name-static.html",
+               start_div({-class=>'slideimage'});
+       if ($self->{-geoloc}) {
+               my ($la,$lo) = @{$self->{-geoloc}};
+               print $IND a({-href=>"http://maps.google.com/".
+                                               "?q=$la,$lo&ll=$la,$lo",
+                               -title=>"$la,$lo",
+                               -class=>'geoloc'},
+                               div({-class=>'geoloc'},"")),"\n";
+       }
+       print $IND a({-href=>".html/$name-static.html",
                                -title=>$title,
                                -class=>'showImage',
                                -rel=>'i'.$name},
                                img({-src=>$thumb,
                                     -class=>'thumbnail',
-                                    -alt=>$title})),"\n"),"\n",
+                                    -alt=>$title})),"\n",end_div,
                start_div({-class=>'varimages',-id=>'i'.$name,-title=>$title}),"\n";
        foreach my $sz(@sizes) {
                my $src=$self->{$sz}->{'url'};