~ubuntu-branches/ubuntu/warty/swish-e/warty

« back to all changes in this revision

Viewing changes to prog-bin/DirTree.pl.in

  • Committer: Bazaar Package Importer
  • Author(s): Ludovic Drolez
  • Date: 2004-03-11 08:41:07 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040311084107-7vp0mu82blq1qjvo
Tags: 2.4.1-3
Oops ! A comment was not removed to disable interactive compilation.
Closes: Bug#237332

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!@@perlbinary@@ -w
 
2
use strict;
 
3
 
 
4
## Run this program with the -man option for documentation ##
 
5
 
 
6
 
 
7
# This is set to where Swish-e's "make install" installed the helper modules.
 
8
use lib qw( @@perlmoduledir@@ );
 
9
 
 
10
 
 
11
use File::Find;    # for recursing a directory tree
 
12
use Getopt::Long;
 
13
use Pod::Usage;
 
14
 
 
15
 
 
16
#--------------- User Configuration Section ------------------------
 
17
# Regular expression that says these files are text
 
18
# even though SWISH::Filter thinks they might be binary
 
19
 
 
20
my @not_binary_extensions = qw/
 
21
    .pl
 
22
    .pm
 
23
    .c
 
24
    .conf
 
25
    rc
 
26
/;
 
27
 
 
28
 
 
29
# Subroutine to validate file names: return true if file is ok to process
 
30
# or false to skip the file.
 
31
# The first parameter passed in is the 
 
32
 
 
33
sub check_path {
 
34
    my $path = shift;
 
35
    return 1;  # return true to process
 
36
}
 
37
 
 
38
sub check_dir {
 
39
    my $dir = shift;
 
40
    return 1;  # return true to process this directory
 
41
}
 
42
 
 
43
#-------------------- End User Config ------------------------------------
 
44
 
 
45
 
 
46
 
 
47
 
 
48
 
 
49
my $extensions = join '|', map { quotemeta } @not_binary_extensions;
 
50
my $textre = qr/($extensions)$/;
 
51
 
 
52
 
 
53
my %options;
 
54
GetOptions( \%options,
 
55
    'verbose!',
 
56
    'debug!',
 
57
    'symlinks!',
 
58
    'path',
 
59
    'man',
 
60
    'no_skip',
 
61
) || pod2usage(2);
 
62
 
 
63
pod2usage( -verbose => 2 ) if $options{man};
 
64
 
 
65
if ( $options{path} ) {
 
66
    print '@@perlmoduledir@@',"\n";
 
67
    exit;
 
68
}
 
69
 
 
70
 
 
71
pod2usage("Must supply at least one directory") unless @ARGV;
 
72
 
 
73
 
 
74
$ENV{FILTER_DEBUG} = 1 if $options{debug};
 
75
 
 
76
 
 
77
 
 
78
# See perldoc File::Find for information on following symbolic links
 
79
# and other important topics.
 
80
 
 
81
use constant DEBUG => 0;
 
82
 
 
83
# Try to load the filter module
 
84
eval { require SWISH::Filter };
 
85
my $filter = SWISH::Filter->new unless $@;
 
86
 
 
87
 
 
88
find(
 
89
    {
 
90
        wanted => \&wanted,
 
91
        no_chdir => 1,  # 5.6 feature
 
92
        follow => $options{follow_symlinks},
 
93
    },
 
94
    @ARGV,
 
95
);
 
96
 
 
97
sub wanted {
 
98
    my $path = $File::Find::name;
 
99
 
 
100
    if ( -d ) {  #stat
 
101
        if ( !check_dir( $path ) ) {
 
102
            $File::Find::prune = 1;
 
103
            warn "Skipped dir [$path] by user function check_dir()\n"
 
104
                if $options{verbose} || $options{debug};
 
105
        }
 
106
        return;
 
107
    }
 
108
 
 
109
    if ( !-r _ ) {
 
110
        warn "$File::Find::name is not readable\n";
 
111
        return;
 
112
    }
 
113
 
 
114
 
 
115
    my $mtime = (stat _ )[9];
 
116
 
 
117
    if ( !check_path( $path ) ) {
 
118
        warn "Skipped path [$path] by user function check_path()\n"
 
119
            if $options{verbose} || $options{debug};
 
120
        return;
 
121
    }
 
122
 
 
123
 
 
124
    if ( $filter ) {
 
125
        my $doc = $filter->convert(
 
126
            document    => $path,
 
127
        );
 
128
        unless ( $doc ) {
 
129
            if ( $options{no_skip} ) {
 
130
                process_file( $path, $mtime );
 
131
                return;
 
132
            }
 
133
 
 
134
            warn "Failed [$path] SWISH::Filter->convert failed.\n"
 
135
                if $options{verbose};
 
136
            return;
 
137
        }
 
138
 
 
139
 
 
140
        if ( $doc->is_binary && $path !~ /$textre/ ) {  # ignore "binary" files (not text/* mime type)
 
141
            warn "Skipping [$path] due to content type: " . $doc->content_type .": may be binary\n"
 
142
                if $options{verbose};
 
143
            return;
 
144
        }
 
145
 
 
146
        my $bytes = output_document( $path, $doc->fetch_doc, $mtime, $doc->swish_parser_type );
 
147
 
 
148
        if ( $options{verbose} ) {
 
149
            print STDERR "Indexed [$path]  ",
 
150
                ($doc->was_filtered ? "(Was filtered) " : "(Not filtered) "),
 
151
                $doc->content_type . " ",
 
152
                ($doc->swish_parser_type || '(parser unspecified)'),
 
153
                "  ($bytes bytes)",
 
154
                "\n";
 
155
        }
 
156
        return;
 
157
    }
 
158
 
 
159
 
 
160
    # Otherwise, fetch document manually
 
161
    process_file( $path, $mtime );
 
162
 
 
163
}
 
164
 
 
165
sub process_file {
 
166
    my ( $path, $mtime ) = @_;
 
167
 
 
168
    unless ( open FH, $path ) {
 
169
        warn "Failed to open '$path': $!\n";
 
170
        return;
 
171
    }
 
172
    local $/ = undef;
 
173
    my $content = <FH>;
 
174
    close FH;
 
175
 
 
176
    my $bytes = output_document( $path, \$content, $mtime );
 
177
 
 
178
    if ( $options{verbose} ) {
 
179
        print STDERR "Indexed [$path] (not processed with SWISH:Filter)  ($bytes bytes)\n";
 
180
    }
 
181
 
 
182
}
 
183
 
 
184
 
 
185
sub output_document {
 
186
    my ( $path, $content_ref, $mtime, $parser_type ) = @_;
 
187
 
 
188
    # Get the length of the content - have to worry about multi-byte content
 
189
    # ugly and maybe expensive, but perhaps more portable than "use bytes"
 
190
    my $bytecount = length pack 'C0a*', $$content_ref;
 
191
 
 
192
    my $header = "Path-Name: $path\nContent-Length: $bytecount\nLast-Mtime: $mtime\n";
 
193
    $header .= "Document-Type: $parser_type\n" if $parser_type;
 
194
 
 
195
    print $header . "\n" . $$content_ref;
 
196
}
 
197
 
 
198
__END__
 
199
 
 
200
=head1 NAME
 
201
 
 
202
DirTree.pl - program to fetch local documents for Swish-e
 
203
 
 
204
=head1 SYNOPSIS
 
205
 
 
206
DirTree.pl [options] directory <directory...> | swish-e -S prog -i stdin
 
207
 
 
208
  Options:
 
209
    -verbose        Display processing info
 
210
    -debug          Enable debugging (including SWISH::Filter debugging)
 
211
    -man            Display documentation
 
212
    -path           Display location lib path set at installation
 
213
    -no_skip        Process documents even if filtering fails
 
214
    -symlinks       Follow symbolic links.  Default is to NOT follow symlinks
 
215
 
 
216
=head1 DESCRIPTION
 
217
 
 
218
DirTree.pl is an example Perl script that can be used with Swish-e to
 
219
fetch documents from the local file system.  It works somewhat like
 
220
Swish-e's default -S fs input method (reading from the file system).
 
221
DirTree.pl will attempt to load the SWISH::Filter module for use in filtering
 
222
documents (e.g. PDF or MS Word).
 
223
 
 
224
DirTree.pl is a thin wrapper around Perl's File::Find module.  Before modifying
 
225
this script for your own use please read the documentation for File::Find:
 
226
 
 
227
    $ perldoc File::Find
 
228
 
 
229
IMPORTANT: By default DirTree.pl will attempt to index all files in the
 
230
directories and sub-directories supplied.  It's expected that you will
 
231
customize this script for your own needs.
 
232
 
 
233
When using -S prog many of the features available to select or exclude
 
234
files that can be specified in the swish-e config file will have no effect.
 
235
It's expected that checks on files will be added to the DirTree.pl program.
 
236
This is much more powerful and allows more control, but requires more work
 
237
to setup.
 
238
 
 
239
There are two skeleton functions at the top of DirTree.pl that can be modified
 
240
for filtering what gets indexed: check_path() and check_dir().  Both are passed
 
241
in the path or directory name as their only parameter.  Return FALSE to skip
 
242
the given path or directory.
 
243
 
 
244
Here's two examples:
 
245
 
 
246
    # Skip all .wav files.
 
247
    sub check_path {
 
248
        my $path = shift;
 
249
        return if $path =~ /\.wav$/;  # return false if ends in .wav?
 
250
        return 1;  # otherwise return true
 
251
    }
 
252
 
 
253
    # Skip all directories that start with a dot (hidden dirs)
 
254
    sub check_dir {
 
255
        my $dir = shift;
 
256
        return ! m[^\.];  # return true if does not start with a dot
 
257
    }
 
258
 
 
259
Those are called for each file or directory processed.  The File::Find module also
 
260
provides a preprocess option where all the files and directories in a directory are
 
261
passed in as a list to a subroutine.  This list can be filtered and passed back to
 
262
File::Find.  This would be useful if, say, you wanted to skip a directory if a file
 
263
"noindex" existed in the directory.  See perldoc File::Find for details.
 
264
 
 
265
=head2 Filtering
 
266
 
 
267
Filtering is the process of converting a document that swish-e cannot index into
 
268
a document that swish-e can index.
 
269
 
 
270
The SWISH::Filter module is used for filtering documents.  SWISH::Filter is
 
271
part of the swish-e distribution and was installed at the same time Swish-e was
 
272
installed.  SWISH::Filter uses "helper" programs to do the actual filtering.
 
273
For example, to filter PDF files you would need to have the Xpdf package
 
274
installed (included with the Windows version of Swish-e).  When SWISH::Filter
 
275
is first loaded it determines which filters are available.
 
276
 
 
277
SWISH::Filter uses the MIME::Types module to convert a file name into a MIME
 
278
type (e.g. .doc => application/msword) and that type is used to determine what
 
279
filter to use, if any.  Filters convert the document to a new MIME type (e.g. the MS Word
 
280
filter might convert the document to text/html or text/plain).
 
281
 
 
282
Binary Files
 
283
 
 
284
After Filtering, this program (DirTree.pl) then checks to see if the file is a binary
 
285
file.  This is a very simple test that simply looks for "text/" at the start
 
286
of the MIME type.  Clearly, this is incorrect for man MIME types.  For example,
 
287
if you were indexing Perl scripts of type "application/x-perl" this program
 
288
would think the file was binary and not index it.
 
289
 
 
290
At the top of the program is a list of file endings that tell DirTree.pl that
 
291
they should be indexed even if their MIME type does not start with "text/".
 
292
 
 
293
Another problem is some files will not map to a MIME type.  The best solution
 
294
is to add the file ending and MIME type to your mime.types file.  But, if you just
 
295
want to index any file that does not have a MIME type use the -no_skip option.
 
296
 
 
297
 
 
298
=head1 REQUIREMENTS
 
299
 
 
300
To use the SWISH::Filter module you will need the helper applications installed.
 
301
Check with your OS packages or Google for sources.
 
302
 
 
303
    PDF conversion requires the Xpdf package
 
304
    MS Word conversion requires the Catdoc package
 
305
 
 
306
The Windows version of Swish-e includes Xpdf and Catdoc packages.
 
307
 
 
308
For content type matching install the Perl Mime::Types module.
 
309
 
 
310
=head1 OPTIONS
 
311
 
 
312
A few options may be passed to DirTree.pl
 
313
 
 
314
=over 8
 
315
 
 
316
=item B<-verbose>
 
317
 
 
318
Produces information about each file as it is processed.
 
319
 
 
320
=item B<-debug>
 
321
 
 
322
Enables detailed debugging.  SWISH::Filter debugging is also enabled.
 
323
 
 
324
=item B<-no_skip>
 
325
 
 
326
When set documents that fail processing with SWISH::Filter will still
 
327
be processed.  Typically this means documents where a content-type could be determined.
 
328
Make sure you have the Mime::Types module installed.
 
329
 
 
330
=item B<-symlinks>
 
331
 
 
332
When specified will recurse into directories that are symbolic links.
 
333
The default is to NOT recurse into symbolic links.  This options sets the "follow"
 
334
option in the File::Find module.
 
335
 
 
336
=back
 
337
 
 
338
=head1 BUGS
 
339
 
 
340
May not work well on multi-byte input files.
 
341
 
 
342
In order to work on Windows (where two chars are used to terminate lines)
 
343
this program reads the ENTIRE file into memory so that an accurate byte count 
 
344
can be made.  Therefore, it's probably a good idea not to index files that are too big.
 
345
 
 
346
 
 
347
=head1 SUPPORT
 
348
 
 
349
Contact the Swish-e discussion list.  See:
 
350
 
 
351
    http://swish-e.org
 
352
 
 
353
 
 
354