source: trunk/gsdl/perllib/doc.pm@ 2846

Last change on this file since 2846 was 2846, checked in by sjboddie, 22 years ago

* empty log message *

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1###########################################################################
2#
3# doc.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) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute 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
26# base class to hold documents
27
28package doc;
29
30BEGIN {
31 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
32 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/dynamic/lib/site_perl/5.005/i686-linux");
33}
34
35use unicode;
36use util;
37use ghtml;
38##use hashdoc;
39
40# the document type may be indexed_doc, nonindexed_doc, or
41# classification
42
43my $OIDcount = 0;
44
45sub new {
46 my $class = shift (@_);
47 my ($source_filename, $doc_type) = @_;
48
49 my $self = bless {'associated_files'=>[],
50 'subsection_order'=>[],
51 'next_subsection'=>1,
52 'subsections'=>{},
53 'metadata'=>[],
54 'text'=>"",
55 'OIDtype'=>"hash"}, $class;
56
57 $self->set_source_filename ($source_filename) if defined $source_filename;
58 $self->set_doc_type ($doc_type) if defined $doc_type;
59
60 return $self;
61}
62
63# clone the $self object
64sub duplicate {
65 my $self = shift (@_);
66
67 my $newobj = {};
68
69 foreach $k (keys %$self) {
70 $newobj->{$k} = &clone ($self->{$k});
71 }
72
73 bless $newobj, ref($self);
74 return $newobj;
75}
76
77sub clone {
78 my ($from) = @_;
79 my $type = ref ($from);
80
81 if ($type eq "HASH") {
82 my $to = {};
83 foreach $key (keys %$from) {
84 $to->{$key} = &clone ($from->{$key});
85 }
86 return $to;
87 } elsif ($type eq "ARRAY") {
88 my $to = [];
89 foreach $v (@$from) {
90 push (@$to, &clone ($v));
91 }
92 return $to;
93 } else {
94 return $from;
95 }
96}
97
98sub set_OIDtype {
99 my $self = shift (@_);
100 my ($type) = @_;
101
102 if ($type eq "incremental") {
103 $self->{'OIDtype'} = $type;
104 } else {
105 $self->{'OIDtype'} = "hash";
106 }
107}
108
109sub set_source_filename {
110 my $self = shift (@_);
111 my ($source_filename) = @_;
112
113 $self->set_metadata_element ($self->get_top_section(),
114 "gsdlsourcefilename",
115 $source_filename);
116}
117
118# returns the source_filename as it was provided
119sub get_source_filename {
120 my $self = shift (@_);
121
122 return $self->get_metadata_element ($self->get_top_section(), "gsdlsourcefilename");
123}
124
125sub set_doc_type {
126 my $self = shift (@_);
127 my ($doc_type) = @_;
128
129 $self->set_metadata_element ($self->get_top_section(),
130 "gsdldoctype",
131 $doc_type);
132}
133
134# returns the source_filename as it was provided
135# the default of "indexed_doc" is used if no document
136# type was provided
137sub get_doc_type {
138 my $self = shift (@_);
139
140 my $doc_type = $self->get_metadata_element ($self->get_top_section(), "gsdldoctype");
141 return $doc_type if (defined $doc_type);
142 return "indexed_doc";
143}
144
145sub _escape_text {
146 my ($text) = @_;
147
148 # special characters in the gml encoding
149 $text =~ s/&/&/g; # this has to be first...
150 $text =~ s/</&lt;/g;
151 $text =~ s/>/&gt;/g;
152 $text =~ s/\"/&quot;/g;
153
154 return $text;
155}
156
157sub buffer_section_xml {
158 my $self = shift (@_);
159 my ($section) = @_;
160
161 my $section_ptr = $self->_lookup_section ($section);
162 return "" unless defined $section_ptr;
163
164 my $all_text = "<Section>\n";
165 $all_text .= " <Description>\n";
166
167 # output metadata
168 foreach my $data (@{$section_ptr->{'metadata'}}) {
169 my $escaped_value = &_escape_text($data->[1]);
170 $all_text .= ' <Metadata name="' . $data->[0] . '">' . $escaped_value . "</Metadata>\n";
171 }
172
173 $all_text .= " </Description>\n";
174
175 # output the text
176 $all_text .= " <Content>\n";
177 $all_text .= &_escape_text($section_ptr->{'text'});
178 $all_text .= " </Content>\n";
179
180 # output all the subsections
181 foreach my $subsection (@{$section_ptr->{'subsection_order'}}) {
182 $all_text .= $self->buffer_section_xml("$section.$subsection");
183 }
184
185 $all_text .= "</Section>\n";
186
187 # make sure no nasty control characters have snuck through
188 # (XML::Parser will barf on anything it doesn't consider to be
189 # valid UTF-8 text, including things like \c@, \cC etc.)
190 $all_text =~ s/[\x00-\x07\x14-\x1F]//g;
191
192 return $all_text;
193}
194
195sub output_section {
196 my $self = shift (@_);
197 my ($handle, $section) = @_;
198
199 print $handle $self->buffer_section_xml($section);
200}
201
202# look up the reference to the a particular section
203sub _lookup_section {
204 my $self = shift (@_);
205 my ($section) = @_;
206
207 my ($num);
208 my $sectionref = $self;
209
210 while (defined $section && $section ne "") {
211 ($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
212 $num =~ s/^0+(\d)/$1/; # remove leading 0s
213 $section = "" unless defined $section;
214
215 if (defined $num && defined $sectionref->{'subsections'}->{$num}) {
216 $sectionref = $sectionref->{'subsections'}->{$num};
217 } else {
218 return undef;
219 }
220 }
221
222 return $sectionref;
223}
224
225# calculate OID by hashing the contents of the document
226sub _calc_OID {
227 my $self = shift (@_);
228 my ($filename) = @_;
229
230 my $osexe = &util::get_os_exe();
231
232 my $hashfile_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",
233 $ENV{'GSDLOS'},"hashfile$osexe");
234 my $result = "NULL";
235
236 if (-e "$hashfile_exe") {
237# $result = `\"$hashfile_exe\" \"$filename\"`;
238 $result = `hashfile$osexe \"$filename\"`;
239 ($result) = $result =~ /:\s*([0-9a-f]+)/i;
240
241 } else {
242 print STDERR "doc::_calc_OID $hashfile_exe could not be found\n";
243 }
244
245 return "HASH$result";
246}
247
248# methods dealing with OID, not groups of them.
249
250# if $OID is not provided one is calculated
251sub set_OID {
252 my $self = shift (@_);
253 my ($OID) = @_;
254
255 # if an OID wasn't provided claculate one
256 if (!defined $OID) {
257 $OID = "NULL";
258
259 if ($self->{'OIDtype'} eq "incremental") {
260 $OID = "D" . $OIDcount;
261 $OIDcount ++;
262
263 } else {
264 # "hash" OID - feed file to hashfile.exe
265 my $filename = $self->get_source_filename();
266 if (defined($filename) && -e $filename) {
267
268 $OID = $self->_calc_OID ($filename);
269
270 } else {
271 $filename = &util::get_tmp_filename();
272 if (!open (OUTFILE, ">$filename")) {
273 print STDERR "doc::set_OID could not write to $filename\n";
274 } else {
275 $self->output_section('OUTFILE', $self->get_top_section(),
276 undef, 1);
277 close (OUTFILE);
278 }
279
280 $OID = $self->_calc_OID ($filename);
281 &util::rm ($filename);
282 }
283 }
284 }
285 $self->set_metadata_element ($self->get_top_section(), "Identifier", $OID);
286}
287
288# this uses hashdoc (embedded c thingy) which is faster but still
289# needs a little work to be suffiently stable
290sub ___set_OID {
291 my $self = shift (@_);
292 my ($OID) = @_;
293
294 # if an OID wasn't provided then calculate hash value based on document
295 if (!defined $OID)
296 {
297 my $hash_text = $self->buffer_section_gml($self->get_top_section(),
298 undef, 1);
299 my $hash_len = length($hash_text);
300
301 $OID = &hashdoc::buffer($hash_text,$hash_len);
302 }
303
304 $self->set_metadata_element ($self->get_top_section(), "Identifier", $OID);
305}
306
307# returns the OID for this document
308sub get_OID {
309 my $self = shift (@_);
310 my $OID = $self->get_metadata_element ($self->get_top_section(), "Identifier");
311 return $OID if (defined $OID);
312 return "NULL";
313}
314
315sub delete_OID {
316 my $self = shift (@_);
317
318 $self->set_metadata_element ($self->get_top_section(), "Identifier", "NULL");
319}
320
321
322# methods for manipulating section names
323
324# returns the name of the top-most section (the top
325# level of the document
326sub get_top_section {
327 my $self = shift (@_);
328
329 return "";
330}
331
332# returns a section
333sub get_parent_section {
334 my $self = shift (@_);
335 my ($section) = @_;
336
337 $section =~ s/(^|\.)\d+$//;
338
339 return $section;
340}
341
342# returns the first child section (or the end child
343# if there isn't any)
344sub get_begin_child {
345 my $self = shift (@_);
346 my ($section) = @_;
347
348 my $section_ptr = $self->_lookup_section($section);
349 return "" unless defined $section_ptr;
350
351 if (defined $section_ptr->{'subsection_order'}->[0]) {
352 return "$section.$section_ptr->{'subsection_order'}->[0]";
353 }
354
355 return $self->get_end_child ($section);
356}
357
358# returns the next child of a parent section
359sub get_next_child {
360 my $self = shift (@_);
361 my ($section) = @_;
362
363 my $parent_section = $self->get_parent_section($section);
364 my $parent_section_ptr = $self->_lookup_section($parent_section);
365 return undef unless defined $parent_section_ptr;
366
367 my ($section_num) = $section =~ /(\d+)$/;
368 return undef unless defined $section_num;
369
370 my $i = 0;
371 my $section_order = $parent_section_ptr->{'subsection_order'};
372 while ($i < scalar(@$section_order)) {
373 last if $section_order->[$i] eq $section_num;
374 $i++;
375 }
376
377 $i++; # the next child
378 if ($i < scalar(@$section_order)) {
379 return $section_order->[$i] if $parent_section eq "";
380 return "$parent_section.$section_order->[$i]";
381 }
382
383 # no more sections in this level
384 return undef;
385}
386
387# returns a reference to a list of children
388sub get_children {
389 my $self = shift (@_);
390 my ($section) = @_;
391
392 my $section_ptr = $self->_lookup_section($section);
393 return [] unless defined $section_ptr;
394
395 my @children = @{$section_ptr->{'subsection_order'}};
396
397 map {$_ = "$section.$_"; $_ =~ s/^\.+//;} @children;
398 return \@children;
399}
400
401# returns the child section one past the last one (which
402# is coded as "0")
403sub get_end_child {
404 my $self = shift (@_);
405 my ($section) = @_;
406
407 return $section . ".0" unless $section eq "";
408 return "0";
409}
410
411# returns the next section in book order
412sub get_next_section {
413 my $self = shift (@_);
414 my ($section) = @_;
415
416 return undef unless defined $section;
417
418 my $section_ptr = $self->_lookup_section($section);
419 return undef unless defined $section_ptr;
420
421 # first try to find first child
422 if (defined $section_ptr->{'subsection_order'}->[0]) {
423 return $section_ptr->{'subsection_order'}->[0] if ($section eq "");
424 return "$section.$section_ptr->{'subsection_order'}->[0]";
425 }
426
427 do {
428 # try to find sibling
429 my $next_child = $self->get_next_child ($section);
430 return $next_child if (defined $next_child);
431
432 # move up one level
433 $section = $self->get_parent_section ($section);
434 } while $section =~ /\d/;
435
436 return undef;
437}
438
439sub is_leaf_section {
440 my $self = shift (@_);
441 my ($section) = @_;
442
443 my $section_ptr = $self->_lookup_section($section);
444 return 1 unless defined $section_ptr;
445
446 return (scalar (@{$section_ptr->{'subsection_order'}}) == 0);
447}
448
449# methods for dealing with sections
450
451# returns the name of the inserted section
452sub insert_section {
453 my $self = shift (@_);
454 my ($before_section) = @_;
455
456 # get the child to insert before and its parent section
457 my $parent_section = "";
458 my $before_child = "0";
459 my @before_section = split (/\./, $before_section);
460 if (scalar(@before_section) > 0) {
461 $before_child = pop (@before_section);
462 $parent_section = join (".", @before_section);
463 }
464
465 my $parent_section_ptr = $self->_lookup_section($parent_section);
466 if (!defined $parent_section_ptr) {
467 print STDERR "doc::insert_section couldn't find parent section " .
468 "$parent_section\n";
469 return;
470 }
471
472 # get the next section number
473 my $section_num = $parent_section_ptr->{'next_subsection'}++;
474
475 my $i = 0;
476 while ($i < scalar(@{$parent_section_ptr->{'subsection_order'}}) &&
477 $parent_section_ptr->{'subsection_order'}->[$i] ne $before_child) {
478 $i++;
479 }
480
481 # insert the section number into the order list
482 splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 0, $section_num);
483
484 # add this section to the parent section
485 my $section_ptr = {'subsection_order'=>[],
486 'next_subsection'=>1,
487 'subsections'=>{},
488 'metadata'=>[],
489 'text'=>""};
490 $parent_section_ptr->{'subsections'}->{$section_num} = $section_ptr;
491
492 # work out the full section number
493 my $section = $parent_section;
494 $section .= "." unless $section eq "";
495 $section .= $section_num;
496
497 return $section;
498}
499
500# creates a pre-named section
501sub create_named_section {
502 my $self = shift (@_);
503 my ($mastersection) = @_;
504
505 my ($num);
506 my $section = $mastersection;
507 my $sectionref = $self;
508
509 while ($section ne "") {
510 ($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
511 $num =~ s/^0+(\d)/$1/; # remove leading 0s
512 $section = "" unless defined $section;
513
514 if (defined $num) {
515 if (!defined $sectionref->{'subsections'}->{$num}) {
516 push (@{$sectionref->{'subsection_order'}}, $num);
517 $sectionref->{'subsections'}->{$num} = {'subsection_order'=>[],
518 'next_subsection'=>1,
519 'subsections'=>{},
520 'metadata'=>[],
521 'text'=>""};
522 if ($num >= $sectionref->{'next_subsection'}) {
523 $sectionref->{'next_subsection'} = $num + 1;
524 }
525 }
526 $sectionref = $sectionref->{'subsections'}->{$num};
527
528 } else {
529 print STDERR "doc::create_named_section couldn't create section ";
530 print STDERR "$mastersection\n";
531 last;
532 }
533 }
534}
535
536# returns a reference to a list of subsections
537sub list_subsections {
538 my $self = shift (@_);
539 my ($section) = @_;
540
541 my $section_ptr = $self->_lookup_section ($section);
542 if (!defined $section_ptr) {
543 print STDERR "doc::list_subsections couldn't find section $section\n";
544 return [];
545 }
546
547 return [@{$section_ptr->{'subsection_order'}}];
548}
549
550sub delete_section {
551 my $self = shift (@_);
552 my ($section) = @_;
553
554# my $section_ptr = {'subsection_order'=>[],
555# 'next_subsection'=>1,
556# 'subsections'=>{},
557# 'metadata'=>[],
558# 'text'=>""};
559
560 # if this is the top section reset everything
561 if ($section eq "") {
562 $self->{'subsection_order'} = [];
563 $self->{'subsections'} = {};
564 $self->{'metadata'} = [];
565 $self->{'text'} = "";
566 return;
567 }
568
569 # find the parent of the section to delete
570 my $parent_section = "";
571 my $child = "0";
572 my @section = split (/\./, $section);
573 if (scalar(@section) > 0) {
574 $child = pop (@section);
575 $parent_section = join (".", @section);
576 }
577
578 my $parent_section_ptr = $self->_lookup_section($parent_section);
579 if (!defined $parent_section_ptr) {
580 print STDERR "doc::delete_section couldn't find parent section " .
581 "$parent_section\n";
582 return;
583 }
584
585 # remove this section from the subsection_order list
586 my $i = 0;
587 while ($i < scalar (@{$parent_section_ptr->{'subsection_order'}})) {
588 if ($parent_section_ptr->{'subsection_order'}->[$i] eq $child) {
589 splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 1);
590 last;
591 }
592 $i++;
593 }
594
595 # remove this section from the subsection hash
596 if (defined ($parent_section_ptr->{'subsections'}->{$child})) {
597 undef $parent_section_ptr->{'subsections'}->{$child};
598 }
599}
600
601#--
602# methods for dealing with metadata
603
604# set_metadata_element and get_metadata_element are for metadata
605# which should only have one value. add_meta_data and get_metadata
606# are for metadata which can have more than one value.
607
608# returns the first metadata value which matches field
609sub get_metadata_element {
610 my $self = shift (@_);
611 my ($section, $field) = @_;
612 my ($data);
613
614 my $section_ptr = $self->_lookup_section($section);
615 if (!defined $section_ptr) {
616 print STDERR "doc::get_metadata_element couldn't find section " .
617 "$section\n";
618 return;
619 }
620
621 foreach $data (@{$section_ptr->{'metadata'}}) {
622 return $data->[1] if (scalar(@$data) >= 2 && $data->[0] eq $field);
623 }
624
625 return undef; # was not found
626}
627
628
629# returns a list of the form [value1, value2, ...]
630sub get_metadata {
631 my $self = shift (@_);
632 my ($section, $field) = @_;
633 my ($data);
634
635 my $section_ptr = $self->_lookup_section($section);
636 if (!defined $section_ptr) {
637 print STDERR "doc::get_metadata couldn't find section " .
638 "$section\n";
639 return;
640 }
641
642 my @metadata = ();
643 foreach $data (@{$section_ptr->{'metadata'}}) {
644 push (@metadata, $data->[1]) if ($data->[0] eq $field);
645 }
646
647 return \@metadata;
648}
649
650# returns a list of the form [[field,value],[field,value],...]
651sub get_all_metadata {
652 my $self = shift (@_);
653 my ($section) = @_;
654
655 my $section_ptr = $self->_lookup_section($section);
656 if (!defined $section_ptr) {
657 print STDERR "doc::get_all_metadata couldn't find section " .
658 "$section\n";
659 return;
660 }
661
662 return $section_ptr->{'metadata'};
663}
664
665# $value is optional
666sub delete_metadata {
667 my $self = shift (@_);
668 my ($section, $field, $value) = @_;
669
670 my $section_ptr = $self->_lookup_section($section);
671 if (!defined $section_ptr) {
672 print STDERR "doc::delete_metadata couldn't find section " .
673 "$section\n";
674 return;
675 }
676
677 my $i = 0;
678 while ($i < scalar (@{$section_ptr->{'metadata'}})) {
679 if (($section_ptr->{'metadata'}->[$i]->[0] eq $field) &&
680 (!defined $value || $section_ptr->{'metadata'}->[$i]->[1] eq $value)) {
681 splice (@{$section_ptr->{'metadata'}}, $i, 1);
682 } else {
683 $i++;
684 }
685 }
686}
687
688sub delete_all_metadata {
689 my $self = shift (@_);
690 my ($section) = @_;
691
692 my $section_ptr = $self->_lookup_section($section);
693 if (!defined $section_ptr) {
694 print STDERR "doc::delete_all_metadata couldn't find section " .
695 "$section\n";
696 return;
697 }
698
699 $section_ptr->{'metadata'} = [];
700}
701
702sub set_metadata_element {
703 my $self = shift (@_);
704 my ($section, $field, $value) = @_;
705
706 $self->set_utf8_metadata_element ($section, $field,
707 &unicode::ascii2utf8(\$value));
708}
709
710# set_utf8_metadata_element assumes the text has already been
711# converted to the UTF-8 encoding.
712sub set_utf8_metadata_element {
713 my $self = shift (@_);
714 my ($section, $field, $value) = @_;
715
716 $self->delete_metadata ($section, $field);
717 $self->add_utf8_metadata ($section, $field, $value);
718}
719
720
721# add_metadata assumes the text is in (extended) ascii form. For
722# text which hash been already converted to the UTF-8 format use
723# add_utf8_metadata.
724sub add_metadata {
725 my $self = shift (@_);
726 my ($section, $field, $value) = @_;
727
728 $self->add_utf8_metadata ($section, $field,
729 &unicode::ascii2utf8(\$value));
730}
731
732# add_utf8_metadata assumes the text has already been converted
733# to the UTF-8 encoding.
734sub add_utf8_metadata {
735 my $self = shift (@_);
736 my ($section, $field, $value) = @_;
737
738 my $section_ptr = $self->_lookup_section($section);
739 if (!defined $section_ptr) {
740 print STDERR "doc::add_utf8_metadata couldn't find section " .
741 "$section\n";
742 return;
743 }
744 if (!defined $value) {
745 print STDERR "doc::add_utf8_metadata undefined value for $field\n";
746 return;
747 }
748 if (!defined $field) {
749 print STDERR "doc::add_utf8_metadata undefined metadata type \n";
750 return;
751 }
752
753 push (@{$section_ptr->{'metadata'}}, [$field, $value]);
754}
755
756
757# methods for dealing with text
758
759# returns the text for a section
760sub get_text {
761 my $self = shift (@_);
762 my ($section) = @_;
763
764 my $section_ptr = $self->_lookup_section($section);
765 if (!defined $section_ptr) {
766 print STDERR "doc::get_text couldn't find section " .
767 "$section\n";
768 return "";
769 }
770
771 return $section_ptr->{'text'};
772}
773
774# returns the (utf-8 encoded) length of the text for a section
775sub get_text_length {
776 my $self = shift (@_);
777 my ($section) = @_;
778
779 my $section_ptr = $self->_lookup_section($section);
780 if (!defined $section_ptr) {
781 print STDERR "doc::get_text_length couldn't find section " .
782 "$section\n";
783 return 0;
784 }
785
786 return length ($section_ptr->{'text'});
787}
788
789sub delete_text {
790 my $self = shift (@_);
791 my ($section) = @_;
792
793 my $section_ptr = $self->_lookup_section($section);
794 if (!defined $section_ptr) {
795 print STDERR "doc::delete_text couldn't find section " .
796 "$section\n";
797 return;
798 }
799
800 $section_ptr->{'text'} = "";
801}
802
803# add_text assumes the text is in (extended) ascii form. For
804# text which has been already converted to the UTF-8 format
805# use add_utf8_text.
806sub add_text {
807 my $self = shift (@_);
808 my ($section, $text) = @_;
809
810 # convert the text to UTF-8 encoded unicode characters
811 # and add the text
812 $self->add_utf8_text($section, &unicode::ascii2utf8(\$text));
813}
814
815
816# add_utf8_text assumes the text to be added has already
817# been converted to the UTF-8 encoding. For ascii text use
818# add_text
819sub add_utf8_text {
820 my $self = shift (@_);
821 my ($section, $text) = @_;
822
823 my $section_ptr = $self->_lookup_section($section);
824 if (!defined $section_ptr) {
825 print STDERR "doc::add_utf8_text couldn't find section " .
826 "$section\n";
827 return;
828 }
829
830 $section_ptr->{'text'} .= $text;
831}
832
833
834# methods for dealing with associated files
835
836# a file is associated with a document, NOT a section.
837# if section is defined it is noted in the data structure
838# only so that files associated from a particular section
839# may be removed later (using delete_section_assoc_files)
840sub associate_file {
841 my $self = shift (@_);
842 my ($real_filename, $assoc_filename, $mime_type, $section) = @_;
843 $mime_type = &ghtml::guess_mime_type ($real_filename) unless defined $mime_type;
844
845 # remove all associated files with the same name
846 $self->delete_assoc_file ($assoc_filename);
847
848 push (@{$self->{'associated_files'}},
849 [$real_filename, $assoc_filename, $mime_type, $section]);
850}
851
852# returns a list of associated files in the form
853# [[real_filename, assoc_filename, mimetype], ...]
854sub get_assoc_files {
855 my $self = shift (@_);
856
857 return $self->{'associated_files'};
858}
859
860sub delete_section_assoc_files {
861 my $self = shift (@_);
862 my ($section) = @_;
863
864 my $i=0;
865 while ($i < scalar (@{$self->{'associated_files'}})) {
866 if (defined $self->{'associated_files'}->[$i]->[3] &&
867 $self->{'associated_files'}->[$i]->[3] eq $section) {
868 splice (@{$self->{'associated_files'}}, $i, 1);
869 } else {
870 $i++;
871 }
872 }
873}
874
875sub delete_assoc_file {
876 my $self = shift (@_);
877 my ($assoc_filename) = @_;
878
879 my $i=0;
880 while ($i < scalar (@{$self->{'associated_files'}})) {
881 if ($self->{'associated_files'}->[$i]->[1] eq $assoc_filename) {
882 splice (@{$self->{'associated_files'}}, $i, 1);
883 } else {
884 $i++;
885 }
886 }
887}
888
889sub reset_nextsection_ptr {
890 my $self = shift (@_);
891 my ($section) = @_;
892
893 my $section_ptr = $self->_lookup_section($section);
894 $section_ptr->{'next_subsection'} = 1;
895}
896
8971;
Note: See TracBrowser for help on using the repository browser.