source: trunk/gsdl/perllib/plugins/FOXPlug.pm@ 233

Last change on this file since 233 was 168, checked in by rjmcnab, 25 years ago

Initial revision.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 5.9 KB
Line 
1# plugin to process a Foxbase dbt file. This plugin provides the basic
2# functionality to read in the dbt and dbf files and process each record.
3# This general plugin should be overridden for a particular database to process
4# the appropriate fields in the file.
5
6package FOXPlug;
7
8use BasPlug;
9use util;
10use doc;
11use unicode;
12use cnseg;
13use gb;
14
15
16sub BEGIN {
17 @ISA = ('BasPlug');
18}
19
20sub new {
21 my ($class) = @_;
22 $self = new BasPlug ();
23
24 return bless $self, $class;
25}
26
27sub is_recursive {
28 my $self = shift (@_);
29
30 return 0; # this is not a recursive plugin
31}
32
33
34# return 1 if processed, 0 if not processed
35# Note that $base_dir might be "" and that $file might
36# include directories
37sub read {
38 my $self = shift (@_);
39 my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
40 my $fullname = &util::filename_cat ($base_dir, $file);
41
42 # dbt files are processed at the same time as dbf files
43 return 1 if ($fullname =~ /\.dbt$/i);
44
45 # see if this is a foxbase database
46 return 0 unless (-f $fullname && $fullname =~ /\.dbf$/i);
47
48 my ($parent_dir) = $fullname =~ /^(.*)\/[^\/]+\.dbf$/i;
49
50 # open the file
51 if (!open (FOXBASEIN, $fullname)) {
52 print STDERR "FOXPlug::read - couldn't read $fullname\n";
53 return 0;
54 }
55
56 print STDERR "FOXPlug: processing $file\n";
57
58 # read in the database header
59 my ($temp, %dbf);
60
61 # read in information about dbt file
62 if (read (FOXBASEIN, $temp, 32) < 32) {
63 print STDERR "FOXPlug::read - eof while reading database header";
64 close (FOXBASEIN);
65 return 0;
66 }
67
68 # unpack the header
69 ($dbf{'hasdbt'},
70 $dbf{'modyear'}, $dbf{'modmonth'}, $dbf{'modday'},
71 $dbf{'numrecords'}, $dbf{'headerlen'},
72 $dbf{'recordlen'}) = unpack ("CCCCVvv", $temp);
73
74 # process hasdbt
75 if ($dbf{'hasdbt'} == 131) {
76 $dbf{'hasdbt'} = 1;
77 } elsif ($dbf{'hasdbt'} == 3) {
78 $dbf{'hasdbt'} = 0;
79 } else {
80 print STDERR "FOXPlug:read $fullname doesn't seem to be a Foxbase file\n";
81 return 0;
82 }
83
84 # read in the field description
85 $dbf{'numfields'} = 0;
86 $dbf{'fieldinfo'} = [];
87 while (read (FOXBASEIN, $temp, 1) > 0) {
88 last if ($temp eq "\x0d");
89 last if (read (FOXBASEIN, $temp, 31, 1) < 31);
90
91 my %field = ();
92 $field{'name'} = $self->extracttext($temp, 11);
93 ($field{'type'}, $field{'pos'}, $field{'len'}, $field{'dp'})
94 = unpack ("x11a1VCC", $temp);
95
96 push (@{$dbf{'fieldinfo'}}, \%field);
97
98 $dbf{'numfields'} ++;
99 }
100
101 # open the dbt file if we need to
102 $dbtfullname = $fullname;
103 if ($fullname =~ /f$/) {
104 $dbtfullname =~ s/f$/t/;
105 } else {
106 $dbtfullname =~ s/F$/T/;
107 }
108 if ($dbf{'hasdbt'} && !open (DBTIN, $dbtfullname)) {
109 print STDERR "FOXPlug::read - couldn't read $dbtfullname\n";
110 close (FOXBASEIN);
111 return 0;
112 }
113
114 # read in and process each record in the database
115 my $numrecords = 0;
116 while (($numrecords < $dbf{'numrecords'}) &&
117 (read (FOXBASEIN, $temp, $dbf{'recordlen'}) == $dbf{'recordlen'})) {
118
119 # create a new record
120 my $record = [];
121
122 foreach $field (@{$dbf{'fieldinfo'}}) {
123 my $fieldvalue = "";
124
125 if ($field->{'type'} eq "M" && $dbf{'hasdbt'}) {
126 # a memo field, look up this field in the dbt file
127 my $seekpos = substr ($temp, $field->{'pos'}, $field->{'len'});
128
129 $seekpos =~ s/^\s*//;
130 $seekpos = 0 unless $seekpos =~ /^\d+$/;
131
132 $seekpos = $seekpos * 512;
133
134 if ($seekpos == 0) {
135 # there is no memo field
136
137 } elsif (seek (DBTIN, $seekpos, 0)) {
138 while (read (DBTIN, $fieldvalue, 512, length($fieldvalue)) > 0) {
139 last if ($fieldvalue =~ /\cZ/);
140 }
141
142 # remove everything after the control-Z
143 substr($fieldvalue, index($fieldvalue, "\cZ")) = "";
144
145 } else {
146 print STDERR "\nERROR - seek (to $seekpos) failed\n";
147 }
148
149 } else {
150 # a normal field
151 $fieldvalue = substr ($temp, $field->{'pos'}, $field->{'len'});
152 }
153
154 push (@$record, {%$field, 'value'=>$fieldvalue});
155 }
156
157 # process this record
158 $self->process_record ($pluginfo, $base_dir, $file, $metadata, $processor,
159 $numrecords, $record);
160
161 # finished another record...
162 $numrecords++;
163 }
164
165 # close the dbt file if we need to
166 if ($dbf{'hasdbt'}) {
167 close (DBTIN);
168 }
169
170 # close the dbf file
171 close (FOXBASEIN);
172
173 # finished processing
174 return 1;
175}
176
177
178# will extract a string from some larger string, making it
179# conform to a number of constraints
180sub extracttext {
181 my $self = shift (@_);
182 my ($text, $maxlen, $offset, $stopstr) = @_;
183 $offset = 0 unless defined $offset;
184 $stopstr = "\x00" unless defined $stopstr;
185
186 # decide where the string finishes
187 my $end = index ($text, $stopstr, $offset);
188 $end = length ($text) if $end < 0;
189 $end = $offset+$maxlen if (defined $maxlen) && ($end-$offset > $maxlen);
190
191 return "" if ($end <= $offset);
192 return substr ($text, $offset, $end-$offset);
193}
194
195
196# process_record should be overriden for a particular type
197# of database. This default version outputs an html document
198# containing all the fields in the record as a table.
199# It also assumes that the text is in utf-8.
200sub process_record {
201 my $self = shift (@_);
202 my ($pluginfo, $base_dir, $file, $metadata, $processor, $numrecords, $record) = @_;
203
204 # create a new document
205 my $doc_obj = new doc ($file, "indexed_doc");
206 my $section = $doc_obj->get_top_section();
207
208 # start of document
209 $doc_obj->add_utf8_text($section, "<table>\n");
210
211 # add each field
212 foreach $field (@$record) {
213 if (defined ($field->{'name'}) && defined ($field->{'value'})) {
214 $doc_obj->add_utf8_text($section, " <tr>\n");
215 $doc_obj->add_utf8_text($section, " <td>$field->{'name'}</td>\n");
216 $doc_obj->add_utf8_text($section, " <td>$field->{'value'}</td>\n");
217 $doc_obj->add_utf8_text($section, " </tr>\n");
218 }
219 }
220
221 # end of document
222 $doc_obj->add_utf8_text($section, "</table>\n");
223
224 # add an object id
225 $doc_obj->set_OID();
226
227 # process the document
228 $processor->process($doc_obj);
229}
230
231
2321;
Note: See TracBrowser for help on using the repository browser.