source: main/trunk/greenstone2/perllib/cgiactions/metadataaction.pm@ 21715

Last change on this file since 21715 was 21715, checked in by mdewsnip, 14 years ago

Adding some comments and error checking. By Jeffrey Ke.

File size: 27.1 KB
Line 
1###########################################################################
2#
3# metadataaction.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 2009 New Zealand Digital Library Project
9#
10# This program is free software; you can redistr te it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26package metadataaction;
27
28use strict;
29
30use cgiactions::baseaction;
31
32use dbutil;
33use ghtml;
34
35
36BEGIN {
37 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan/perl-5.8");
38 require XML::Rules;
39}
40
41
42@metadataaction::ISA = ('baseaction');
43
44
45my $action_table =
46{
47 "get-live-metadata" => { 'compulsory-args' => [ "d", "metaname" ],
48 'optional-args' => [] },
49
50 "get-metadata" => { 'compulsory-args' => [ "d", "metaname" ],
51 'optional-args' => [ "metapos" ] },
52
53 "set-live-metadata" => { 'compulsory-args' => [ "d", "metaname", "metavalue" ],
54 'optional-args' => [ ] },
55
56 "set-metadata" => { 'compulsory-args' => [ "d", "metaname", "metavalue" ],
57 'optional-args' => [ "metapos" ] },
58
59 "set-archives-metadata" => { 'compulsory-args' => [ "d", "metaname", "metavalue" ],
60 'optional-args' => [ "metapos" ]
61
62 },
63
64 "set-import-metadata" => { 'compulsory-args' => [ "metaname", "metavalue" ],
65 'optional-args' => [ "d", "f", "metamode" ]
66 # metamode can be "accumulate", "override", or "unique-id"
67 },
68
69
70 "remove-live-metadata" => { 'compulsory-args' => [ "d", "metaname" ],
71 'optional-args' => [ ] },
72
73 "remove-metadata" => { 'compulsory-args' => [ "d", "metaname" ],
74 'optional-args' => [ "metapos" ] }
75};
76
77
78sub new
79{
80 my $class = shift (@_);
81 my ($gsdl_cgi,$iis6_mode) = @_;
82
83 my $self = new baseaction($action_table,$gsdl_cgi,$iis6_mode);
84
85 return bless $self, $class;
86}
87
88
89sub get_live_metadata
90{
91 my $self = shift @_;
92
93 my $username = $self->{'username'};
94 my $collect = $self->{'collect'};
95 my $gsdl_cgi = $self->{'gsdl_cgi'};
96 my $gsdlhome = $self->{'gsdlhome'};
97
98 # Note: Not sure why get_live_metadata doesn't need the authentication check
99
100 # Obtain the collect dir
101 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
102
103 # Make sure the collection isn't locked by someone else
104 $self->lock_collection($username, $collect);
105
106 # look up additional args
107 my $docid = $self->{'d'};
108 if ((!defined $docid) || ($docid =~ m/^\s*$/)) {
109 $gsdl_cgi->generate_error("No docid (d=...) specified.");
110 }
111
112 # Generate the dbkey
113 my $metaname = $self->{'metaname'};
114 my $dbkey = "$docid.$metaname";
115
116 # To people who know $collect_tail please add some comments
117 # Obtain path to the database
118 my $collect_tail = $collect;
119 $collect_tail =~ s/^.*[\/|\\]//;
120 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
121 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", "live-$collect_tail", $index_text_directory);
122
123 # Obtain the content of the key
124 my $cmd = "gdbmget $infodb_file_path $dbkey";
125 if (open(GIN,"$cmd |") == 0) {
126 # Catch error if gdbmget failed
127 my $mess = "Failed to get metadata key: $metaname\n";
128 $mess .= "$!\n";
129
130 $gsdl_cgi->generate_error($mess);
131 }
132 else {
133 # Read everything in and concatenate them into $metavalue
134 my $metavalue = "";
135 my $line;
136 while (defined ($line=<GIN>)) {
137 $metavalue .= $line;
138 }
139 close(GIN);
140 chomp($metavalue); # Get rid off the tailing newlines
141 $gsdl_cgi->generate_ok_message("$metavalue");
142 }
143
144 # Release the lock once it is done
145 $self->unlock_collection($username, $collect);
146}
147
148
149sub get_metadata
150{
151 my $self = shift @_;
152
153 my $username = $self->{'username'};
154 my $collect = $self->{'collect'};
155 my $gsdl_cgi = $self->{'gsdl_cgi'};
156 my $gsdlhome = $self->{'gsdlhome'};
157
158 # Authenticate user if it is enabled
159 if ($baseaction::authentication_enabled) {
160 # Ensure the user is allowed to edit this collection
161 &authenticate_user($gsdl_cgi, $username, $collect);
162 }
163
164 # Obtain the collect dir
165 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
166
167 # Make sure the collection isn't locked by someone else
168 $self->lock_collection($username, $collect);
169
170 # look up additional args
171 my $docid = $self->{'d'};
172 my $metaname = $self->{'metaname'};
173 my $metapos = $self->{'metapos'};
174
175 # To people who know $collect_tail please add some comments
176 # Obtain path to the database
177 my $collect_tail = $collect;
178 $collect_tail =~ s/^.*[\/\\]//;
179 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
180 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", $collect_tail, $index_text_directory);
181
182 # Read the docid entry
183 my $doc_rec_string = &dbutil::read_infodb_entry("gdbm", $infodb_file_path, $docid);
184 my $doc_rec = &dbutil::convert_infodb_string_to_hash($doc_rec_string);
185
186 # Basically loop through and unescape_html the values
187 foreach my $k (keys %$doc_rec) {
188 my @escaped_v = ();
189 foreach my $v (@{$doc_rec->{$k}}) {
190 my $ev = &ghtml::unescape_html($v);
191 push(@escaped_v, $ev);
192 }
193 $doc_rec->{$k} = \@escaped_v;
194 }
195
196 # Obtain the specified metadata value
197 $metapos = 0 if (!defined $metapos);
198 my $metavalue = $doc_rec->{$metaname}->[$metapos];
199 $gsdl_cgi->generate_ok_message("$metavalue");
200
201 # Release the lock once it is done
202 $self->unlock_collection($username, $collect);
203}
204
205
206sub set_live_metadata
207{
208 my $self = shift @_;
209
210 my $username = $self->{'username'};
211 my $collect = $self->{'collect'};
212 my $gsdl_cgi = $self->{'gsdl_cgi'};
213 my $gsdlhome = $self->{'gsdlhome'};
214
215 # don't user authenticate for now
216 if ($baseaction::authentication_enabled) {
217 # Ensure the user is allowed to edit this collection
218 &authenticate_user($gsdl_cgi, $username, $collect);
219 }
220
221 # Obtain the collect dir
222 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
223
224 # Make sure the collection isn't locked by someone else
225 $self->lock_collection($username, $collect);
226
227 # look up additional args
228 my $docid = $self->{'d'};
229 if ((!defined $docid) || ($docid =~ m/^\s*$/)) {
230 $gsdl_cgi->generate_error("No docid (d=...) specified.");
231 }
232 my $metavalue = $self->{'metavalue'};
233
234 # Generate the dbkey
235 my $metaname = $self->{'metaname'};
236 my $dbkey = "$docid.$metaname";
237
238 # To people who know $collect_tail please add some comments
239 # Obtain path to the database
240 my $collect_tail = $collect;
241 $collect_tail =~ s/^.*[\/\\]//;
242 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
243 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", "live-$collect_tail", $index_text_directory);
244
245 # Set the new value
246 my $cmd = "gdbmset \"$infodb_file_path\" \"$dbkey\" \"$metavalue\"";
247 my $status = system($cmd);
248 if ($status != 0) {
249 # Catch error if gdbmget failed
250 my $mess = "Failed to set metadata key: $dbkey\n";
251
252 $mess .= "PATH: $ENV{'PATH'}\n";
253 $mess .= "cmd = $cmd\n";
254 $mess .= "Exit status: $status\n";
255 $mess .= "System Error Message: $!\n";
256
257 $gsdl_cgi->generate_error($mess);
258 }
259 else {
260 $gsdl_cgi->generate_ok_message("set-live-metadata successful: Key[$metaname]=$metavalue");
261 }
262
263 # Release the lock once it is done
264 $self->unlock_collection($username, $collect);
265}
266
267
268sub set_metadata
269{
270 my $self = shift @_;
271
272 my $username = $self->{'username'};
273 my $collect = $self->{'collect'};
274 my $gsdl_cgi = $self->{'gsdl_cgi'};
275 my $gsdlhome = $self->{'gsdlhome'};
276
277 # don't user authenticate for now
278 if ($baseaction::authentication_enabled) {
279 # Ensure the user is allowed to edit this collection
280 &authenticate_user($gsdl_cgi, $username, $collect);
281 }
282
283 # Obtain the collect dir
284 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
285
286 # Make sure the collection isn't locked by someone else
287 $self->lock_collection($username, $collect);
288
289 # look up additional args
290 my $docid = $self->{'d'};
291 my $metaname = $self->{'metaname'};
292 my $metapos = $self->{'metapos'};
293 my $metavalue = $self->{'metavalue'};
294
295 # To people who know $collect_tail please add some comments
296 # Obtain path to the database
297 my $collect_tail = $collect;
298 $collect_tail =~ s/^.*[\/\\]//;
299 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
300 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", $collect_tail, $index_text_directory);
301
302 # Read the docid entry
303 my $doc_rec_string = &dbutil::read_infodb_entry("gdbm", $infodb_file_path, $docid);
304 my $doc_rec = &dbutil::convert_infodb_string_to_hash($doc_rec_string);
305 foreach my $k (keys %$doc_rec) {
306 my @escaped_v = ();
307 foreach my $v (@{$doc_rec->{$k}}) {
308 if ($k eq "contains") {
309 # protect quotes in ".2;".3 etc
310 $v =~ s/\"/\\\"/g;
311 push(@escaped_v, $v);
312 }
313 else {
314 my $ev = &ghtml::unescape_html($v);
315 $ev =~ s/\"/\\\"/g;
316 push(@escaped_v, $ev);
317 }
318 }
319 $doc_rec->{$k} = \@escaped_v;
320 }
321 ## print STDERR "**** metavalue = $metavalue\n";
322
323 # Protect the quotes
324 $metavalue =~ s/\"/\\\"/g;
325
326 # Set the metadata value
327 if (defined $metapos) {
328 $doc_rec->{$metaname}->[$metapos] = $metavalue;
329 }
330 else {
331 $doc_rec->{$metaname} = [ $metavalue ];
332 }
333 ## print STDERR "**** metavalue = $metavalue\n";
334
335 # Generate the record string
336 my $serialized_doc_rec = &dbutil::convert_infodb_hash_to_string($doc_rec);
337 ## print STDERR "**** ser dr\n$serialized_doc_rec\n\n\n";
338
339 # Store it into GDBM
340 my $cmd = "gdbmset \"$infodb_file_path\" \"$docid\" \"$serialized_doc_rec\"";
341 my $status = system($cmd);
342 if ($status != 0) {
343 # Catch error if gdbmget failed
344 my $mess = "Failed to set metadata key: $docid\n";
345
346 $mess .= "PATH: $ENV{'PATH'}\n";
347 $mess .= "cmd = $cmd\n";
348 $mess .= "Exit status: $status\n";
349 $mess .= "System Error Message: $!\n";
350
351 $gsdl_cgi->generate_error($mess);
352 }
353 else {
354 my $mess = "set-document-metadata successful: Key[$docid]\n";
355 $mess .= " $metaname";
356 $mess .= "->[$metapos]" if (defined $metapos);
357 $mess .= " = $metavalue";
358
359 $gsdl_cgi->generate_ok_message($mess);
360 }
361
362 # Release the lock once it is done
363 $self->unlock_collection($username, $collect);
364}
365
366
367sub dxml_metadata
368{
369 my ($tagname, $attrHash, $contextArray, $parentDataArray, $parser) = @_;
370 my $metaname = $parser->{'parameters'}->{'metaname'};
371 my $metamode = $parser->{'parameters'}->{'metamode'};
372
373 # Find the right metadata tag and checks if we are going to override it
374 # Note: This over writes the first metadata block it encountered. If there are multiple Sections in the doc.xml, it might not behave as you would expect
375 my $name_attr = $attrHash->{'name'};
376 if (($name_attr eq $metaname) && ($metamode eq "override")) {
377 # Get the value and override the current value
378 my $metavalue = $parser->{'parameters'}->{'metavalue'};
379 $attrHash->{'_content'} = $metavalue;
380
381 # Don't want it to wipe out any other pieces of metadata
382 $parser->{'parameters'}->{'metamode'} = "done";
383 }
384
385 # raw extended
386 # Someone please write some comments on why adding ':'.$tagname => $attrHash
387 return (':'.$tagname => $attrHash, [$tagname => $attrHash]);
388}
389
390
391sub dxml_description
392{
393 my ($tagname, $attrHash, $contextArray, $parentDataArray, $parser) = @_;
394 my $metamode = $parser->{'parameters'}->{'metamode'};
395
396 # Accumulate the metadata
397 # NOTE: This appends new metadata element to all description fields.
398 # If there are multiple Sections/SubSections, the new metadata block will get appended to all of them
399 if ($metamode eq "accumulate") {
400 # tack a new metadata tag on to the end of the <Metadata>+ block
401 my $metaname = $parser->{'parameters'}->{'metaname'};
402 my $metavalue = $parser->{'parameters'}->{'metavalue'};
403
404 my $metadata_attr = { '_content' => $metavalue,
405 'name' => $metaname,
406 'mode' => "accumulate" };
407
408 my $append_metadata = [ "Metadata" => $metadata_attr ];
409 my $description_content = $attrHash->{'_content'};
410
411 push(@$description_content," ", $append_metadata ,"\n ");
412 }
413
414 # raw
415 return $tagname => $attrHash;
416}
417
418
419sub edit_xml_file
420{
421 my $self = shift @_;
422 my ($gsdl_cgi, $filename, $rules, $options) = @_;
423
424 # use XML::Rules to add it in (read in and out again)
425 my $parser = XML::Rules->new(rules => $rules,
426 style => 'filter' );
427
428 my $xml_in = "";
429 if (!open(MIN,"<$filename")) {
430 $gsdl_cgi->generate_error("Unable to read in $filename: $!");
431 }
432 else {
433 # Read all the text in
434 my $line;
435 while (defined ($line=<MIN>)) {
436 $xml_in .= $line;
437 }
438 close(MIN);
439
440 # Matched lines will get handled by the call backs
441 my $xml_out = "";
442 $parser->filter($xml_in,\$xml_out, $options);
443
444 if (!open(MOUT,">$filename")) {
445 $gsdl_cgi->generate_error("Unable to write out to $filename: $!");
446 }
447 else {
448 print MOUT $xml_out;
449 close(MOUT);
450 }
451 }
452}
453
454
455sub edit_doc_xml
456{
457 my $self = shift @_;
458 my ($gsdl_cgi, $doc_xml_filename, $metaname, $metavalue, $metapos) = @_;
459
460 # use XML::Rules to add it in (read in and out again)
461 # Set the call back functions
462 my @rules =
463 ( _default => 'raw extended',
464 'Metadata' => \&dxml_metadata,
465 'Description' => \&dxml_description );
466
467 # Sets the parameters
468 my $options = { 'metaname' => $metaname,
469 'metapos' => $metapos,
470 'metavalue' => $metavalue };
471 $self->edit_xml_file($gsdl_cgi,$doc_xml_filename,\@rules,$options);
472}
473
474
475sub set_archives_metadata
476{
477 my $self = shift @_;
478
479 my $username = $self->{'username'};
480 my $collect = $self->{'collect'};
481 my $gsdl_cgi = $self->{'gsdl_cgi'};
482 my $gsdlhome = $self->{'gsdlhome'};
483
484 # don't user authenticate for now
485 if ($baseaction::authentication_enabled) {
486 # Ensure the user is allowed to edit this collection
487 $self->authenticate_user($username, $collect);
488 }
489
490 # Obtain the collect and archive dir
491 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
492 my $archive_dir = &util::filename_cat($collect_dir,$collect,"archives");
493
494 # Make sure the collection isn't locked by someone else
495 $self->lock_collection($username, $collect);
496
497 # look up additional args
498 my $docid = $self->{'d'};
499 my $metaname = $self->{'metaname'};
500 my $metavalue = $self->{'metavalue'};
501 my $metapos = $self->{'metapos'};
502 $metapos = 0 if (!defined $metapos);
503
504 # Obtain the doc.xml path for the specified docID
505 my $arcinfo_doc_filename = &dbutil::get_infodb_file_path("gdbm", "archiveinf-doc", $archive_dir);
506 my $doc_rec_string = &dbutil::read_infodb_entry("gdbm", $arcinfo_doc_filename, $docid);
507 my $doc_rec = &dbutil::convert_infodb_string_to_hash($doc_rec_string);
508 my $doc_xml_file = $doc_rec->{'doc-file'}->[0];
509
510 # The $doc_xml_file is relative to the archives, and now let's get the full path
511 my $archives_dir = &util::filename_cat($collect_dir,$collect,"archives");
512 my $doc_xml_filename = &util::filename_cat($archives_dir,$doc_xml_file);
513
514 # Edit the doc.xml file with the specified metadata name, value and position.
515 # TODO: there is a potential problem here as this edit_doc_xml function
516 # is assuming the simple doc.xml situation where there is only one Section and no SubSections.
517 # Running import.pl -groupsize will cause this to have multiple sections in one doc.xml
518 $self->edit_doc_xml($gsdl_cgi,$doc_xml_filename,
519 $metaname,$metavalue,$metapos);
520
521 # Release the lock once it is done
522 $self->unlock_collection($username, $collect);
523}
524
525
526sub mxml_metadata
527{
528 my ($tagname, $attrHash, $contextArray, $parentDataArray, $parser) = @_;
529 my $metaname = $parser->{'parameters'}->{'metaname'};
530 my $metamode = $parser->{'parameters'}->{'metamode'};
531
532 # Find the right metadata tag and checks if we are going to override it
533 # Note: This over writes the first metadata block it encountered even if it doesn't belong to the source file we specified
534 my $name_attr = $attrHash->{'name'};
535 if (($name_attr eq $metaname) && ($metamode eq "override")) {
536 # Get the value and override the current value
537 my $metavalue = $parser->{'parameters'}->{'metavalue'};
538 $attrHash->{'_content'} = $metavalue;
539
540 # Don't want it to wipe out any other pieces of metadata
541 $parser->{'parameters'}->{'metamode'} = "done";
542 }
543
544 # raw extended
545 # Someone please write some comments on why adding ':'.$tagname => $attrHash
546 return (':'.$tagname => $attrHash, [$tagname => $attrHash]);
547}
548
549
550sub mxml_description
551{
552 my ($tagname, $attrHash, $contextArray, $parentDataArray, $parser) = @_;
553 my $metamode = $parser->{'parameters'}->{'metamode'};
554
555 # Accumulate the metadata block to the end of the description block
556 # Note: This adds metadata block to all description blocks, so if there are
557 # multiple FileSets, it will add to all of them
558 if ($metamode eq "accumulate") {
559 # tack a new metadata tag on to the end of the <Metadata>+ block
560 my $metaname = $parser->{'parameters'}->{'metaname'};
561 my $metavalue = $parser->{'parameters'}->{'metavalue'};
562
563 my $metadata_attr = { '_content' => $metavalue,
564 'name' => $metaname,
565 'mode' => "accumulate" };
566
567 my $append_metadata = [ "Metadata" => $metadata_attr ];
568 my $description_content = $attrHash->{'_content'};
569
570 push(@$description_content," ", $append_metadata ,"\n ");
571 }
572
573 # raw
574 return $tagname => $attrHash;
575}
576
577
578sub edit_metadata_xml
579{
580 my $self = shift @_;
581 my ($gsdl_cgi, $metadata_xml_filename, $metaname, $metavalue, $metamode) = @_;
582
583 # Set the call-back functions for the metadata tags
584 my @rules =
585 ( _default => 'raw extended',
586 'Metadata' => \&mxml_metadata,
587 'Description' => \&mxml_description );
588
589 # use XML::Rules to add it in (read in and out again)
590 my $parser = XML::Rules->new(rules => \@rules,
591 style => 'filter' );
592
593 my $xml_in = "";
594 if (!open(MIN,"<$metadata_xml_filename")) {
595 $gsdl_cgi->generate_error("Unable to read in $metadata_xml_filename: $!");
596 }
597 else {
598 # Read them in
599 my $line;
600 while (defined ($line=<MIN>)) {
601 $xml_in .= $line;
602 }
603 close(MIN);
604
605 # Filter with the call-back functions
606 my $xml_out = "";
607 $parser->filter($xml_in,\$xml_out, { metaname => $metaname,
608 metavalue => $metavalue,
609 metamode => $metamode } );
610
611 if (!open(MOUT,">$metadata_xml_filename")) {
612 $gsdl_cgi->generate_error("Unable to write out to $metadata_xml_filename: $!");
613 }
614 else {
615 print MOUT $xml_out;
616 close(MOUT);
617 }
618 }
619}
620
621
622sub set_import_metadata
623{
624 my $self = shift @_;
625
626 my $username = $self->{'username'};
627 my $collect = $self->{'collect'};
628 my $gsdl_cgi = $self->{'gsdl_cgi'};
629 my $gsdlhome = $self->{'gsdlhome'};
630
631 # don't user authenticate for now
632 if ($baseaction::authentication_enabled) {
633 # Ensure the user is allowed to edit this collection
634 $self->authenticate_user($username, $collect);
635 }
636
637 # Obtain the collect and archive dir
638 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
639 my $archive_dir = &util::filename_cat($collect_dir,$collect,"archives");
640
641 # Make sure the collection isn't locked by someone else
642 $self->lock_collection($username, $collect);
643
644 # look up additional args
645 # want either d= or f=
646 my $docid = $self->{'d'};
647 my $import_file = $self->{'f'};
648 if ((!defined $docid) && (!defined $import_file)) {
649 $gsdl_cgi->generate_error("No docid (d=...) or import file (f=) specified.");
650 }
651
652 # Get the parameters and set default mode to "accumulate"
653 my $metaname = $self->{'metaname'};
654 my $metavalue = $self->{'metavalue'};
655 my $metamode = $self->{'metamode'};
656 if ((!defined $metamode) || ($metamode =~ m/^\s*$/)) {
657 # make "accumulate" the default (less destructive, as won't actually
658 # delete any existing values)
659 $metamode = "accumulate";
660 }
661
662 # Obtain where the metadata.xml is from the archiveinfo-doc.gdb file
663 # If the doc oid is not specified, we assume the metadata.xml is next to the specified "f"
664 my $metadata_xml_file;
665 my $import_filename = undef;
666 if (defined $docid) {
667 my $arcinfo_doc_filename = &dbutil::get_infodb_file_path("gdbm", "archiveinf-doc", $archive_dir);
668 my $doc_rec_string = &dbutil::read_infodb_entry("gdbm", $arcinfo_doc_filename, $docid);
669 my $doc_rec = &dbutil::convert_infodb_string_to_hash($doc_rec_string);
670
671 # This now stores the full pathname
672 $import_filename = $doc_rec->{'src-file'}->[0];
673 }
674 else {
675 $import_filename = &util::filename_cat($collect_dir,$collect,$import_file);
676 }
677
678
679 # figure out correct metadata.xml file [?]
680 # Assuming the metadata.xml file is next to the source file
681 # Note: This will not work if it is using the inherited metadata from the parent folder
682 my ($import_tailname, $import_dirname)
683 = File::Basename::fileparse($import_filename);
684 my $metadata_xml_filename = &util::filename_cat($import_dirname,"metadata.xml");
685
686 # Edit the metadata.xml
687 # Note: At moment it doesn't correctly on metadata.xml with multiple FileSets
688 # "accumulate" mode will add new metadata block to all FileSets
689 # "override" mode will over write the first encountered metadata block, even if it doesn't have the right source
690 $self->edit_metadata_xml($gsdl_cgi,$metadata_xml_filename,
691 $metaname,$metavalue,$metamode);
692
693 # Release the lock once it is done
694 $self->unlock_collection($username, $collect);
695}
696
697
698sub remove_live_metadata
699{
700 my $self = shift @_;
701
702 my $username = $self->{'username'};
703 my $collect = $self->{'collect'};
704 my $gsdl_cgi = $self->{'gsdl_cgi'};
705 my $gsdlhome = $self->{'gsdlhome'};
706
707 if ($baseaction::authentication_enabled) {
708 # Ensure the user is allowed to edit this collection
709 &authenticate_user($gsdl_cgi, $username, $collect);
710 }
711
712 # Obtain the collect dir
713 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
714
715 # Make sure the collection isn't locked by someone else
716 $self->lock_collection($username, $collect);
717
718 # look up additional args
719 my $docid = $self->{'d'};
720 if ((!defined $docid) || ($docid =~ m/^\s*$/)) {
721 $gsdl_cgi->generate_error("No docid (d=...) specified.");
722 }
723
724 # Generate the dbkey
725 my $metaname = $self->{'metaname'};
726 my $dbkey = "$docid.$metaname";
727
728 # To people who know $collect_tail please add some comments
729 # Obtain the live gdbm_db path
730 my $collect_tail = $collect;
731 $collect_tail =~ s/^.*[\/\\]//;
732 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
733 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", "live-$collect_tail", $index_text_directory);
734
735 # Remove the key
736 my $cmd = "gdbmdel \"$infodb_file_path\" \"$dbkey\"";
737 my $status = system($cmd);
738 if ($status != 0) {
739 # Catch error if gdbmdel failed
740 my $mess = "Failed to set metadata key: $dbkey\n";
741
742 $mess .= "PATH: $ENV{'PATH'}\n";
743 $mess .= "cmd = $cmd\n";
744 $mess .= "Exit status: $status\n";
745 $mess .= "System Error Message: $!\n";
746
747 $gsdl_cgi->generate_error($mess);
748 }
749 else {
750 $gsdl_cgi->generate_ok_message("DB remove successful: Key[$metaname]");
751 }
752
753}
754
755
756sub remove_metadata
757{
758 my $self = shift @_;
759
760 my $username = $self->{'username'};
761 my $collect = $self->{'collect'};
762 my $gsdl_cgi = $self->{'gsdl_cgi'};
763 my $gsdlhome = $self->{'gsdlhome'};
764
765 # don't user authenticate for now
766 if ($baseaction::authentication_enabled) {
767 # Ensure the user is allowed to edit this collection
768 &authenticate_user($gsdl_cgi, $username, $collect);
769 }
770
771 # Obtain the collect dir
772 my $collect_dir = &util::filename_cat($gsdlhome, "collect");
773
774 # Make sure the collection isn't locked by someone else
775 $self->lock_collection($username, $collect);
776
777 # look up additional args
778 my $docid = $self->{'d'};
779 if ((!defined $docid) || ($docid =~ m/^\s*$/)) {
780 $gsdl_cgi->generate_error("No docid (d=...) specified.");
781 }
782 my $metaname = $self->{'metaname'};
783 my $metapos = $self->{'metapos'};
784
785 # To people who know $collect_tail please add some comments
786 # Obtain the path to the database
787 my $collect_tail = $collect;
788 $collect_tail =~ s/^.*[\/\\]//;
789 my $index_text_directory = &util::filename_cat($collect_dir,$collect,"index","text");
790 my $infodb_file_path = &dbutil::get_infodb_file_path("gdbm", $collect_tail, $index_text_directory);
791
792 # Read the docid entry
793 my $doc_rec_string = &dbutil::read_infodb_entry("gdbm", $infodb_file_path, $docid);
794 my $doc_rec = &dbutil::convert_infodb_string_to_hash($doc_rec_string);
795
796 # Basically loop through and unescape_html the values
797 foreach my $k (keys %$doc_rec) {
798 my @escaped_v = ();
799 foreach my $v (@{$doc_rec->{$k}}) {
800 if ($k eq "contains") {
801 # protect quotes in ".2;".3 etc
802 $v =~ s/\"/\\\"/g;
803 push(@escaped_v, $v);
804 }
805 else {
806 my $ev = &ghtml::unescape_html($v);
807 $ev =~ s/\"/\\\"/g;
808 push(@escaped_v, $ev);
809 }
810 }
811 $doc_rec->{$k} = \@escaped_v;
812 }
813
814 # Check to make sure the key does exist
815 if (!defined ($doc_rec->{$metaname})) {
816 $gsdl_cgi->generate_error("No metadata field \"" . $metaname . "\" in the specified document: [" . $docid . "]");
817 }
818
819 # Obtain the specified metadata pos
820 $metapos = 0 if (!defined $metapos);
821
822 # consider check key is defined before deleting?
823 # Loop through the metadata array and ignore the specified position
824 my $filtered_metadata = [];
825 my $num_metadata_vals = scalar(@{$doc_rec->{$metaname}});
826 for (my $i=0; $i<$num_metadata_vals; $i++) {
827 my $metavalue = shift(@{$doc_rec->{$metaname}});
828
829 if ($i != $metapos) {
830 push(@$filtered_metadata,$metavalue)
831 }
832 }
833 $doc_rec->{$metaname} = $filtered_metadata;
834
835 # Turn the record back to string
836 my $serialized_doc_rec = &dbutil::convert_infodb_hash_to_string($doc_rec);
837
838 # Store it back to the database
839 my $cmd = "gdbmset \"$infodb_file_path\" \"$docid\" \"$serialized_doc_rec\"";
840 my $status = system($cmd);
841 if ($status != 0) {
842 my $mess = "Failed to set metadata key: $docid\n";
843
844 $mess .= "PATH: $ENV{'PATH'}\n";
845 $mess .= "cmd = $cmd\n";
846 $mess .= "Exit status: $status\n";
847 $mess .= "System Error Message: $!\n";
848
849 $gsdl_cgi->generate_error($mess);
850 }
851 else {
852 my $mess = "DB set (with item deleted) successful: Key[$docid]\n";
853 $mess .= " $metaname";
854 $mess .= "->[$metapos]" if (defined $metapos);
855
856 $gsdl_cgi->generate_ok_message($mess);
857 }
858}
859
860
8611;
Note: See TracBrowser for help on using the repository browser.