Index: /main/trunk/greenstone2/perllib/cgiactions/baseaction.pm
===================================================================
--- /main/trunk/greenstone2/perllib/cgiactions/baseaction.pm	(revision 33182)
+++ /main/trunk/greenstone2/perllib/cgiactions/baseaction.pm	(revision 33183)
@@ -83,5 +83,5 @@
 	    my @opt_args = ();
 	    push(@opt_args,"un") if (!$authentication_enabled);
-	    push(@opt_args,@{$action_table->{$a}->{'optional-args'}});
+	    push(@opt_args,@{$action_table->{$a}->{'optional-args'}}) if $action_table->{$a}->{'optional-args'};
 
 	    if (scalar(@opt_args)>0) {
Index: /main/trunk/greenstone2/perllib/cgiactions/metadataaction.pm
===================================================================
--- /main/trunk/greenstone2/perllib/cgiactions/metadataaction.pm	(revision 33182)
+++ /main/trunk/greenstone2/perllib/cgiactions/metadataaction.pm	(revision 33183)
@@ -121,7 +121,12 @@
     my $url_encoded_metavalue = $gsdl_cgi->param("metavalue");
     my $url_decoded_metavalue = &unicode::url_decode($url_encoded_metavalue,1);
+#$gsdl_cgi->generate_message("@@@ metaaction new - DEBUG before utf82unicode: " . &unicode::debug_unicode_string($url_decoded_metavalue));
+    
     my $unicode_array = &unicode::utf82unicode($url_decoded_metavalue);
 
     $url_decoded_metavalue = join("",map(chr($_),@$unicode_array));
+
+#$gsdl_cgi->generate_message("@@@ metaaction new - DEBUG after utf82unicode: " . &unicode::debug_unicode_string($url_decoded_metavalue));
+    
     $gsdl_cgi->param("metavalue",$url_decoded_metavalue);
 
Index: /main/trunk/greenstone2/perllib/cgiactions/modmetadataaction.pm
===================================================================
--- /main/trunk/greenstone2/perllib/cgiactions/modmetadataaction.pm	(revision 33182)
+++ /main/trunk/greenstone2/perllib/cgiactions/modmetadataaction.pm	(revision 33183)
@@ -120,6 +120,25 @@
 		'optional-args'   => [ "where", "metapos", "metavalue", "metamode" ] }, # metamode is optional since remove-metadata can call any of remove_import_meta and remove_archives_meta, remove_index_meta, of which the first two accept metamode as an optional param
 
+
+	#REMOVE MULTIPLE (REMOVE ALL MATCHING METANAME AT DOCID)
+	"erase-import-metadata" => { 
+	    'compulsory-args' => [ "d", "metaname" ] },
+
+	"erase-archives-metadata" => { 
+	    'compulsory-args' => [ "d", "metaname" ] },
+
+	"erase-index-metadata" => { 
+	    'compulsory-args' => [ "d", "metaname" ] },
+	
+	"erase-live-metadata" => { 
+	    'compulsory-args' => [ "d", "metaname" ] },
+	
+	"erase-metadata" => { # generic erase-meta function. The 'where' param can be set to any combination of index|archives|import|live. docid d is still compulsory for setting index, archives and live meta
+		'compulsory-args' => [ "d", "metaname" ],
+		'optional-args'   => [ "where" ] },
+	
+	
 	#INSERT METHODS
-    "insert-metadata" => { 
+	"insert-metadata" => {
 		'compulsory-args' => [ "d", "metaname", "metavalue" ],
 		'optional-args'   => [ ] }
@@ -2255,5 +2274,5 @@
     if ($status != 0) {
         # Catch error if gdbmdel failed
-	my $mess = "Failed to set metadata key: $dbkey\n";
+	my $mess = "Failed to delete metadata key: $dbkey\n";
 	
 	$mess .= "PATH: $ENV{'PATH'}\n";
@@ -2448,4 +2467,341 @@
 
     # Release the lock once it is done
+    $self->unlock_collection($username, $collect);
+}
+
+#################################################################################
+# ERASE META METHODS: ERASE ALL VALUES FOR MATCHING METANAME AT SPECIFIED DOCID #
+#################################################################################
+
+sub erase_metadata
+{
+    my $self = shift @_;
+
+    my $where = $self->{'where'};
+    # when $where is unspecified, following behaviour of sub remove_metadata by defaulting to erasing metadata from index
+    if(!$where || ($where =~ m/^\s*$/)) {
+	$self->erase_index_metadata(@_); # call the full version of set_index_meta for the default behaviour
+	return;
+    }
+
+    my $username  = $self->{'username'};
+    my $collect   = $self->{'collect'};
+    my $gsdl_cgi  = $self->{'gsdl_cgi'};
+
+    if ($baseaction::authentication_enabled) {
+	# Ensure the user is allowed to edit this collection	
+	$self->authenticate_user($username, $collect); #&authenticate_user($gsdl_cgi, $username, $collect);
+    }
+
+    # Make sure the collection isn't locked by someone else
+    $self->lock_collection($username, $collect);
+
+    # check which directories need to be processed, specified in $where as 
+    # any combination of import|archives|index|live
+    if($where =~ m/import/) {
+	$self->_erase_import_metadata(@_);	    
+    }
+    if($where =~ m/archives/) {
+	$self->_erase_archives_metadata(@_);	    
+    } 
+    if($where =~ m/index/) {
+	$self->_erase_index_metadata(@_);	    
+    }
+
+    # Release the lock once it is done
+    $self->unlock_collection($username, $collect);
+}
+
+# the internal version, without authentication
+sub _erase_index_metadata
+{    
+    my $self = shift @_;
+
+    my $collect   = $self->{'collect'};
+    my $gsdl_cgi  = $self->{'gsdl_cgi'};
+#    my $gsdlhome  = $self->{'gsdlhome'};
+    my $infodbtype = $self->{'infodbtype'};
+	
+    # Obtain the collect dir
+    my $site = $self->{'site'};
+    my $collect_dir = $gsdl_cgi->get_collection_dir($site);
+    ## my $collect_dir = &util::filename_cat($gsdlhome, "collect");
+
+        # look up additional args
+    my $docid     = $self->{'d'};
+    if ((!defined $docid) || ($docid =~ m/^\s*$/)) {
+      $gsdl_cgi->generate_error("No docid (d=...) specified.");
+    }
+    my $metaname  = $self->{'metaname'};
+    my $metapos   = undef;
+    my $metavalue = undef;
+
+    # To people who know $collect_tail please add some comments
+    # -> In collection groups, I think collect_tailname is the subcollection name,
+    # e.g. colgroup-name/col-tail-name
+    # Obtain the path to the database
+    my $collect_tail = $collect;
+    $collect_tail =~ s/^.*[\/|\\]//;
+    my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
+    my $infodb_file_path = &dbutil::get_infodb_file_path($infodbtype, $collect_tail, $index_text_directory);
+
+    # Read the docid entry
+    my $doc_rec = &dbutil::read_infodb_entry($infodbtype, $infodb_file_path, $docid);
+
+    # Check to make sure the key does exist
+    if (defined ($doc_rec->{$metaname})) {        
+
+	$doc_rec->{$metaname} = [];
+
+	## Use the dbutil set_entry method instead of assuming the database is gdbm
+	my $status = &dbutil::set_infodb_entry($infodbtype, $infodb_file_path, $docid, $doc_rec);
+
+	if ($status != 0) {
+	    my $mess = "Failed to erase metadata key: $docid\n";
+	    
+	    $mess .= "PATH: $ENV{'PATH'}\n";
+	    $mess .= "Exit status: $status\n";
+	    $mess .= "System Error Message: $!\n";
+	    
+	    $gsdl_cgi->generate_error($mess);
+	}
+	else {
+	    my $mess = "DB set (with item deleted) successful: Key[$docid]\n";
+	    $mess .= "  $metaname";
+	    $mess .= "->[$metapos]" if (defined $metapos);
+	    $mess .= " ($metavalue)" if (defined $metavalue);
+	    
+	    $gsdl_cgi->generate_ok_message($mess);
+	}
+    }
+    else { # no such metaname. Is it really an error?
+	$gsdl_cgi->generate_ok_message("Can't erase. No metadata field \"" . $metaname . "\" in the specified document: [" . $docid . "]");
+    }
+    #return $status; # in case calling functions have a use for this
+}
+
+sub erase_index_metadata
+{
+    my $self = shift @_;
+
+    my $username  = $self->{'username'};
+    my $collect   = $self->{'collect'};
+    my $gsdl_cgi  = $self->{'gsdl_cgi'};
+#    my $gsdlhome  = $self->{'gsdlhome'};
+	
+    if ($baseaction::authentication_enabled) {
+	# Ensure the user is allowed to edit this collection	
+	$self->authenticate_user($username, $collect); #&authenticate_user($gsdl_cgi, $username, $collect);
+    }
+
+    # Obtain the collect dir
+	my $site = $self->{'site'};
+	my $collect_dir = $gsdl_cgi->get_collection_dir($site);
+    ## my $collect_dir = &util::filename_cat($gsdlhome, "collect");
+
+    # Make sure the collection isn't locked by someone else
+    $self->lock_collection($username, $collect);
+
+    $self->_erase_index_metadata(@_);
+
+    # Release the lock once it is done
+    $self->unlock_collection($username, $collect);
+}
+
+
+# Given a metaname, removes ALL metadata with that metaname at the provided docid
+sub _erase_archives_metadata
+{
+	my $self = shift @_;
+
+	my $collect   = $self->{'collect'};
+	my $gsdl_cgi  = $self->{'gsdl_cgi'};
+#	my $gsdlhome  = $self->{'gsdlhome'};
+	my $infodbtype = $self->{'infodbtype'};
+	
+	my $site = $self->{'site'};
+		
+	# Obtain the collect and archive dir   
+	my $collect_dir = $gsdl_cgi->get_collection_dir($site);	
+	
+	my $archive_dir = &util::filename_cat($collect_dir,$collect,"archives");
+
+	# look up additional args
+	my ($docid, $docid_secnum) = ($self->{'d'} =~ m/^(.*?)(\..*)?$/);
+	
+	my $metaname = $self->{'metaname'};
+
+	# metapos, metavalue and metamode are never provided and therefore all undefined for erase_archives_metadata
+	my $metapos = undef;
+	my $metavalue = undef;
+	my $metamode = "override"; # when override and no metapos or metaval, all values for metaname will be affected
+
+	my $arcinfo_doc_filename = &dbutil::get_infodb_file_path($infodbtype, "archiveinf-doc", $archive_dir);
+	my $doc_rec = &dbutil::read_infodb_entry($infodbtype, $arcinfo_doc_filename, $docid);
+
+	# This now stores the full pathname
+	my $doc_filename = $doc_rec->{'doc-file'}->[0];	
+
+	my $status = $self->remove_from_doc_xml($gsdl_cgi, &util::filename_cat($archive_dir, $doc_filename), $metaname, $metapos, $metavalue, $docid_secnum, $metamode);
+	
+	if ($status == 0) 
+	{
+		my $mess = "\nerase-archives-metadata successful: \nKey[$docid]\n";
+		$mess .= "  $metaname";
+		$gsdl_cgi->generate_ok_message($mess);	
+	}
+	else 
+	{
+		my $mess .= "Failed to erase archives metadata key: $docid\n";
+		$mess .= "Exit status: $status\n";
+		$mess .= "System Error Message: $!\n";
+		$mess .= "-" x 20 . "\n";
+		
+		$gsdl_cgi->generate_error($mess);
+	}
+	
+	#return $status; # in case calling functions have a use for this
+}
+
+# practically identical to remove_archives_metadata
+sub erase_archives_metadata
+{
+	my $self = shift @_;
+
+	my $username  = $self->{'username'};
+	my $collect   = $self->{'collect'};
+	my $gsdl_cgi  = $self->{'gsdl_cgi'};
+	
+	if ($baseaction::authentication_enabled) 
+	{
+	    # Ensure the user is allowed to edit this collection		
+	    $self->authenticate_user($username, $collect); #&authenticate_user($gsdl_cgi, $username, $collect);	
+	}
+
+	# Make sure the collection isn't locked by someone else
+	$self->lock_collection($username, $collect);
+
+	$self->_erase_archives_metadata(@_);
+
+	# Release the lock once it is done
+	$self->unlock_collection($username, $collect);
+}
+
+sub _erase_import_metadata
+{
+	my $self = shift @_;
+
+	my $collect   = $self->{'collect'};
+	my $gsdl_cgi  = $self->{'gsdl_cgi'};
+#	my $gsdlhome  = $self->{'gsdlhome'};
+	my $infodbtype = $self->{'infodbtype'};
+	
+	# Obtain the collect dir
+	## my $collect_dir = &util::filename_cat($gsdlhome, "collect");
+	my $site = $self->{'site'};
+	my $collect_dir = $gsdl_cgi->get_collection_dir($site);
+	
+	## my $collect_dir = &util::filename_cat($gsdlhome, "collect");
+	my $archive_dir = &util::filename_cat($collect_dir,$collect,"archives");
+
+	# look up additional args
+	my $docid = $self->{'d'};
+	if ((!defined $docid) || ($docid =~ m/^\s*$/)) 
+	{
+		$gsdl_cgi->generate_error("No docid (d=...) specified.\n");
+	}
+	
+	my $metaname = $self->{'metaname'};
+	my $metapos = undef;
+	my $metavalue = undef;
+	my $metamode = "override";
+
+	# Obtain where the metadata.xml is from the archiveinfo-doc.gdb file
+	# If the doc oid is not specified, we assume the metadata.xml is next to the specified "f"
+	my $metadata_xml_file;
+	my $import_filename = undef;
+	if (defined $docid) 
+	{
+		my $arcinfo_doc_filename = &dbutil::get_infodb_file_path($infodbtype, "archiveinf-doc", $archive_dir);
+		my $doc_rec = &dbutil::read_infodb_entry($infodbtype, $arcinfo_doc_filename, $docid);
+
+		# This now stores the full pathname
+		$import_filename = $doc_rec->{'src-file'}->[0];	
+		$import_filename = &util::placeholders_to_abspath($import_filename);
+	}
+
+	if((!defined $import_filename) || ($import_filename =~ m/^\s*$/))
+	{
+		$gsdl_cgi->generate_error("There is no metadata\n");
+	}
+	
+	# figure out correct metadata.xml file [?]
+	# Assuming the metadata.xml file is next to the source file
+	# Note: This will not work if it is using the inherited metadata from the parent folder
+	my ($import_tailname, $import_dirname) = File::Basename::fileparse($import_filename);
+	my $metadata_xml_filename = &util::filename_cat($import_dirname,"metadata.xml");
+	
+	$self->remove_from_metadata_xml($gsdl_cgi, $metadata_xml_filename, $metaname, $metapos, $metavalue, $import_tailname, $metamode); # metamode=override, means all values of metaname are affected
+	
+	my $mess = "erase-import-metadata successful: Key[$docid] -> $metadata_xml_filename\n";
+	$mess .= "  $metaname";
+	$mess .= " = $metavalue\n";
+	
+	$gsdl_cgi->generate_ok_message($mess);
+
+	#return $status; # in case calling functions have a use for this
+}
+
+sub erase_import_metadata
+{
+	my $self = shift @_;
+	
+	my $username = $self->{'username'};
+	my $collect   = $self->{'collect'};
+	my $gsdl_cgi  = $self->{'gsdl_cgi'};
+	
+	if ($baseaction::authentication_enabled) {
+	    # Ensure the user is allowed to edit this collection		
+	    $self->authenticate_user($username, $collect); #&authenticate_user($gsdl_cgi, $username, $collect);
+	}
+
+	# Make sure the collection isn't locked by someone else
+	$self->lock_collection($username, $collect);
+	
+	$self->_erase_import_metadata(@_);
+
+	# Release the lock once it is done
+	$self->unlock_collection($username, $collect);
+
+}
+
+# removes all meta with matching metaname for the specified docid from the live metadata index
+sub _erase_live_metadata
+{
+    my $self = shift @_;
+    # At present, _remove_live_metadata doesn't take metaval or metapos either and therefore has the desired effect
+    $self->_remove_live_metadata(@_);
+
+}
+
+sub erase_live_metadata
+{
+    my $self = shift @_;
+
+    my $username  = $self->{'username'};
+    my $collect   = $self->{'collect'};
+    my $gsdl_cgi  = $self->{'gsdl_cgi'};
+    my $gsdlhome  = $self->{'gsdlhome'};
+	
+    if ($baseaction::authentication_enabled) {
+	# Ensure the user is allowed to edit this collection	
+	$self->authenticate_user($username, $collect); #&authenticate_user($gsdl_cgi, $username, $collect);
+    }
+
+    # Make sure the collection isn't locked by someone else
+    $self->lock_collection($username, $collect);
+
+    $self->_erase_live_metadata(@_);
+
     $self->unlock_collection($username, $collect);
 }
