Index: trunk/gsdl/perllib/plugins/OpenDocumentPlug.pm
===================================================================
--- trunk/gsdl/perllib/plugins/OpenDocumentPlug.pm	(revision 10997)
+++ trunk/gsdl/perllib/plugins/OpenDocumentPlug.pm	(revision 10997)
@@ -0,0 +1,287 @@
+###########################################################################
+#
+# OpenDocumentPlug.pm -- The Open Document plugin
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+package OpenDocumentPlug;
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and viceversa
+
+use XMLPlug;
+use XML::XPath;
+use XML::XPath::XMLParser;
+use Cwd;
+use util;
+use ghtml;
+
+sub BEGIN {
+    @OpenDocumentPlug::ISA = ('XMLPlug');
+}
+
+
+#our @filesAssoc = ();
+our @filesProcess = ( "content.xml" , "meta.xml" );
+#XML plug has this so we need it too
+our ($self);
+
+my $arguments = [
+		 { 'name' => "process_exp",
+		   'desc' => "{BasPlug.process_exp}",
+		   'type' => "regexp",
+		   'deft' =>  &get_default_process_exp() }
+		 ];
+my $options = { 'name'     => "OpenDocumentPlug",
+		'desc'     => "{OpenDocumentPlug.desc}",
+		'abstract' => "no",
+		'inherits' => "yes" };
+
+sub get_default_process_exp { return q^(?i)\.o(?:d|t)(?:t|s|p|g)$^; }
+
+sub new {
+    my ($class) = shift (@_);
+    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
+    push(@$pluginlist, $class);
+
+    if(defined $arguments){ push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});}
+    if(defined $options) { push(@{$hashArgOptLists->{"OptList"}},$options)};
+
+    my $self = (defined $hashArgOptLists)? new XMLPlug($pluginlist,$inputargs,$hashArgOptLists): new XMLPlug($pluginlist,$inputargs);
+
+    $self->{'section'} = "";
+    $self->{'office:meta'} = "";
+    
+    return bless $self, $class;
+}
+
+
+sub xml_doctype {
+    my $self = shift(@_);
+    my ($expat, $name, $sysid, $pubid, $internal) = @_;
+    die "The only valid doctype is manifest, $name is not valid" if ($name ne "manifest:manifest");
+}
+
+# Called for every start tag. The $_ variable will contain a copy of the
+# tag and the %_ variable will contain the element's attributes.
+sub xml_start_tag {
+    my $self = shift(@_);
+    my ($expat, $element) = @_;
+    my %atts  = %_;
+    $self->{'office:meta'} = $element if $self->{'office:meta'} eq "Start";
+    if($element eq 'office:text') {
+	$self->{'collectedText'} = "";
+    }elsif($element eq 'office:meta') {
+	$self->{'collectedText'} = "";
+	$self->{'office:meta'} = "Start";
+    }elsif($element eq 'meta:document-statistic'){
+	foreach my $att (keys %atts) {
+	    $self->{'doc_obj'}->add_utf8_metadata("",$att,$atts{$att});
+	}
+	
+    }
+}
+
+sub xml_end_tag {
+    my $self = shift(@_);
+    my ($expat, $element) = @_;
+    
+    if($element eq 'office:text') {
+	$self->{'doc_obj'}->add_utf8_text("",$self->{'collectedText'});
+	$self->{'collectedText'} = "";
+    }elsif($element eq $self->{'office:meta'}) {
+	if( $self->{'collectedText'} ne "") {
+	    $self->{'doc_obj'}->add_utf8_metadata("",$self->{'office:meta'},$self->{'collectedText'});
+	    $self->{'doc_obj'}->add_utf8_metadata("","Title",$self->{'collectedText'}) if $self->{'office:meta'} =~ m/:title$/;
+	    $self->{'doc_obj'}->add_utf8_metadata("","Language",$self->{'collectedText'}) if $self->{'office:meta'} =~ m/:language$/;
+	    $self->{'doc_obj'}->add_utf8_metadata("","GENERATOR",$self->{'collectedText'}) if $self->{'office:meta'} =~ m/:generator$/;
+	    
+    	}
+	$self->{'collectedText'} = "";
+        $self->{'office:meta'} = "Start";
+    }elsif($element eq 'office:meta'){
+	$self->{'office:meta'} = "";
+    }elsif($element eq 'office:body'){
+	#some documents have text in other places that should probably be indexed if we can't find any doc text
+	if( $self->{'collectedText'} ne "" && $self->{'doc_obj'}->get_text("") eq "") {
+	    $self->{'doc_obj'}->add_utf8_text("",$self->{'collectedText'});
+	}
+    }
+}
+
+sub xml_text {
+    my $self = shift(@_);
+    my ($expat) = @_;
+    
+    if($_ =~ m/\w/i) {
+	$self->{'collectedText'} .= "<br/>" if $self->{'collectedText'} ne "";
+	$self->{'collectedText'} .= "$_";
+    }
+}
+
+#trap start and end document so we do not get our doc_obj closed too soon
+sub xml_start_document {}
+sub xml_end_document {}
+
+sub read {
+    # $self must be global to work with XML callback routines.
+    $self = shift (@_);  
+   
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
+
+    my $filename = $file;
+    $filename = &util::filename_cat ($base_dir, $file) if $base_dir =~ /\w/;
+
+    if ($self->{'block_exp'} ne "" && $filename =~ /$self->{'block_exp'}/) {
+	$self->{'num_blocked'} ++;
+	return 0;
+    }
+    if ($filename !~ /$self->{'process_exp'}/ || !-f $filename) {
+	return undef;
+    }
+
+    $file =~ s/^[\/\\]+//; # $file often begins with / so we'll tidy it up
+    $self->{'file'} = $file;
+    $self->{'filename'} = $filename;
+    $self->{'processor'} = $processor;
+    $self->{'metadata'} = $metadata;
+    $self->{'gli'} = $gli;
+    
+    
+    eval{
+	my ($file_only) = $file =~ /([^\\\/]*)$/;
+	my $tmpdir = &util::get_tmp_filename ();
+	&util::mk_all_dir ($tmpdir);
+	
+	$self->open_document();
+	
+	# save current working directory
+	my $cwd = getcwd();
+	chdir ($tmpdir) || die "Unable to change to $tmpdir";
+	&util::cp ($filename, $tmpdir);
+	
+	$self->unzip ("\"$file_only\"");
+	
+	foreach my $xmlFile (@OpenDocumentPlug::filesProcess) {
+	    print getcwd();
+	    print $xmlFile;
+	    $self->parse_file($xmlFile);
+	}
+		
+	$self->close_document($filename,$file_only);
+	
+	chdir ($cwd) || die "Unable to change back to $cwd";
+	&util::rm_r ($tmpdir);
+	
+    };
+    
+    if ($@) {
+
+	# parsefile may either croak somewhere in XML::Parser (e.g. because
+	# the document is not well formed) or die somewhere in XMLPlug or a
+	# derived plugin (e.g. because we're attempting to process a
+	# document whose DOCTYPE is not meant for this plugin). For the
+	# first case we'll print a warning and continue, for the second
+	# we'll just continue quietly
+
+	print STDERR "**** Error is: $@\n";
+
+	my ($msg) = $@ =~ /Carp::croak\(\'(.*?)\'\)/;
+	if (defined $msg) {	
+	    my $outhandle = $self->{'outhandle'};
+	    my $plugin_name = ref ($self);
+	    print $outhandle "$plugin_name failed to process $file ($msg)\n";
+	}
+
+	# reset ourself for the next document
+	print STDERR "<ProcessingError n='$file'>\n" if ($gli);
+	return -1; # error during processing
+    }
+
+    return 1;
+}
+
+sub unzip {
+    my $self = shift (@_);
+    my ($file) = @_;
+
+    system ("unzip $file");
+    &util::rm ($file) if -e $file;
+}
+
+sub close_document() {
+    my $self = shift(@_);
+    my ($filename,$file_only) = @_;
+  
+    my $doc_obj = $self->{'doc_obj'};  
+
+    my $mimetype = $self->get_mimetype();
+    
+    $doc_obj->associate_file($filename, $file_only, $mimetype, "");
+    $doc_obj->associate_file("Thumbnails/thumbnail.png", "thumbnail.png", "image/png", "");
+    my $doc_ext = $filename;
+    $doc_ext =~ s/.*\.od(.)/od$1/;
+    
+    # We use set instead of add here because we only want one value
+    $doc_obj->set_utf8_metadata_element("", "FileFormat", "Open Document");
+
+    #setup to doclink thingi
+    my $doclink = "<a href=\"_httpcollection_/index/assoc/[archivedir]/$file_only\">";
+    $doc_obj->add_utf8_metadata ("", "srclink",  $doclink); 
+    $doc_obj->add_utf8_metadata ("", "srcicon",  "<img border=\"0\" align=\"absmiddle\" src=\"_httpcollection_/index/assoc/[archivedir]/thumbnail.png\" alt=\"View the Open document\" title=\"View the Open document\">"); 
+    $doc_obj->add_utf8_metadata ("", "/srclink", "</a>"); 
+    $doc_obj->add_utf8_metadata ("", "Source", &ghtml::dmsafe($file_only));
+    $doc_obj->set_utf8_metadata_element("", "FileSize", (-s $filename));
+     
+    # add a Title if none has been found yet
+    $self->title_fallback($doc_obj,"",$file_only);
+   
+    # add an OID
+    $doc_obj->set_OID();
+    
+    $doc_obj->add_utf8_metadata("", "Plugin", "$self->{'plugin_type'}");
+
+    # process the document
+    $self->{'processor'}->process($doc_obj);
+    
+    $self->{'num_processed'} ++;
+    return 1;
+}
+
+sub get_mimetype(){
+    my $filename = "mimetype";
+    if (!open (FILEIN,"<$filename")){
+   	print STDERR "Warning: unable to open the $filename\n";
+	return "Unknown OpenDocument Format";
+    }
+    else {
+	my $text = "";
+	while (defined (my $line = <FILEIN>)) {
+	   $text .= $line;   
+	}
+	return $text;
+    }
+}
+1;
+
+
+
+
