source: tags/gsdl-2_30d-distribution/gsdl/perllib/doc.pm@ 2308

Last change on this file since 2308 was 1870, checked in by sjboddie, 23 years ago

Tidied up language support stuff.

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