source: main/trunk/greenstone2/bin/script/gsConvert.pl

Last change on this file was 35174, checked in by kjdon, 3 years ago

gsConvert.pl now prints out the command it will run, if verbosity > 2

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 44.8 KB
Line 
1#!/usr/bin/perl -w
2
3###########################################################################
4#
5# gsConvert.pl -- convert documents to HTML or TEXT format
6#
7# A component of the Greenstone digital library software
8# from the New Zealand Digital Library Project at the
9# University of Waikato, New Zealand.
10#
11# Copyright (C) 1999-2002 New Zealand Digital Library Project
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License as published by
15# the Free Software Foundation; either version 2 of the License, or
16# (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26#
27###########################################################################
28
29# gsConvert.pl converts documents in a range of formats to HTML or TEXT
30# by exploiting third-party programs. The sources of these are usually found
31# in the $GSDLHOME/packages directory, and the executables should live in
32# $GSDLHOME/bin/$GSDLOS (which is on the search path).
33#
34# Currently, we can convert the following formats by using external
35# conversion utilities:
36# Microsoft Word (versions 2,6,7 [==95?], 8[==97?], 9[==2000?]), RTF,
37# Adobe PDF, PostScript, MS PowerPoint (95 and 97), and MS Excel (95 and 97).
38#
39# We can try to convert any file to text with a perl implementation of the
40# UNIX strings command.
41#
42# We try to convert Postscript files to text using "gs" which is often on
43# *nix machines. We fall back to performing weak text extraction by using
44# regular expressions.
45
46BEGIN {
47 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
48 unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
49}
50
51use strict;
52
53use parsargv;
54use util;
55use FileUtils;
56use Cwd;
57
58# Are we running on WinNT or Win2000 (or later)?
59my $is_winnt_2000=eval {require Win32; return (Win32::IsWinNT()); return 0;};
60if (!defined($is_winnt_2000)) {$is_winnt_2000=0;}
61
62my $use_strings;
63my $pdf_tool;
64my $pdf_complex;
65my $pdf_nohidden;
66my $pdf_zoom;
67my $pdf_dpi;
68my $pdf_ignore_images;
69my $pdf_allow_images_only;
70my $windows_scripting;
71my $verbosity;
72my $enc;
73
74sub print_usage
75{
76 print STDERR "\n";
77 print STDERR "gsConvert.pl: Converts documents in a range of formats to html\n";
78 print STDERR " or text using third-party programs.\n\n";
79 print STDERR " usage: $0 [options] filename\n";
80 print STDERR " options:\n\t-type\tdoc|dot|pdf|ps|ppt|rtf|xls\t(input file type)\n";
81 print STDERR "\t-errlog\t<filename>\t(append err messages)\n";
82 print STDERR "\t-output\tauto|html|pretty_html|paged_pretty_html|paged_html|text|paged_text|pagedimg_jpg|pagedimg_gif|pagedimg_png|pagedimgtxt_jpg|pagedimgtxt_png\t(output file type)\n";
83 print STDERR "\t-timeout\t<max cpu seconds>\t(ulimit on unix systems)\n";
84 print STDERR "\t-use_strings\tuse strings to extract text if conversion fails\n";
85 print STDERR "\t-windows_scripting\tuse windows VB script (if available) to convert Microsoft Word and PPT documents\n";
86 print STDERR "\t-pdf_tool\tpdftohtml|xpdftools|pdfbox (not all output types are supported by every pdf_tool)\n";
87 print STDERR "\t-pdf_complex\tuse complex output when converting PDF to HTML\n";
88 print STDERR "\t-pdf_nohidden\tDon't attempt to extract hidden text from PDF files\n";
89 print STDERR "\t-pdf_ignore_images\tdon't attempt to extract images when\n";
90 print STDERR "\t\tconverting PDF to HTML\n";
91 print STDERR "\t-pdf_allow_images_only\tallow images only (continue even if no text is present when converting to HTML)\n";
92 print STDERR "\t-pdf_zoom\tfactor by which to zoom PDF (only useful if\n";
93 print STDERR "\t\t-pdf_complex is set\n";
94 print STDERR "\t-pdf_dpi\tSet the resolution in DPI of background images produced by xpdf's pdftohtml\n";
95 print STDERR "\t-verbosity\tSet verbosity to 3 to see the commands that are run\n";
96 exit(1);
97}
98
99my $faillogfile="";
100my $timeout=0;
101
102sub main
103{
104 my (@ARGV) = @_;
105 my ($input_type,$output_type);
106
107 # Dynamically figure out what the --type option can support, based on whether -windows_scripting
108 # is in use or not
109 my $default_type_re = "(doc|dot|pdf|ps|ppt|rtf|xls)";
110 #my $enhanced_type_re = "(docx?|dot|pdf|ps|pptx?|rtf|xlsx?)";
111 #my $enhanced_type_re = "(docx?|dot|pdf|ps|pptx?|rtf|xlsx?)";
112 # Currently only have VBA for Word and PPT(but no XLS)
113 my $enhanced_type_re = "(docx?|dot|pdf|ps|pptx?|rtf|xls)";
114
115 my $type_re = $default_type_re;
116
117 foreach my $a (@ARGV) {
118 if ($a =~ m/^windows_scripting$/i) {
119 $type_re = $enhanced_type_re;
120 }
121 }
122
123 # read command-line arguments
124 if (!parsargv::parse(\@ARGV,
125 "type/$type_re/", \$input_type,
126 '/errlog/.*/', \$faillogfile,
127 'output/(auto|html|text|pagedimg).*/', \$output_type, # regex includes html_multi and (paged_)pretty_html besides html, as well as pagedimgtxt_<imgext> besides pagedimg_<imgext>
128 'timeout/\d+/0',\$timeout,
129 'verbosity/\d+/1', \$verbosity,
130 'windows_scripting',\$windows_scripting,
131 'use_strings', \$use_strings,
132 'pdf_tool/(pdftohtml|pdfbox|xpdftools)/', \$pdf_tool, # the old pdftohtml tool, pdfbox extensions or the newer xpdf-tools
133 'pdf_complex', \$pdf_complex, # options for pdf_tool = pdftohtml (the old pdftohtml tool)
134 'pdf_ignore_images', \$pdf_ignore_images,
135 'pdf_allow_images_only', \$pdf_allow_images_only,
136 'pdf_nohidden', \$pdf_nohidden,
137 'pdf_zoom/\d+/2', \$pdf_zoom,
138 'pdf_dpi/\d+/96', \$pdf_dpi
139 ))
140 {
141 print_usage();
142 }
143
144 # Make sure the input file exists and can be opened for reading
145 if (scalar(@ARGV!=1)) {
146 print_usage();
147 }
148
149 my $input_filename = $ARGV[0];
150 if (!-r $input_filename) {
151 print STDERR "Error: unable to open $input_filename for reading\n";
152 exit(1);
153 }
154
155 # Deduce filenames
156 my ($tailname,$dirname,$suffix)
157 = File::Basename::fileparse($input_filename, "\\.[^\\.]+\$");
158 my $output_filestem = &FileUtils::filenameConcatenate($dirname, "$tailname");
159
160 if ($input_type eq "")
161 {
162 $input_type = lc (substr($suffix,1,length($suffix)-1));
163 }
164
165 # Change to temporary working directory
166 my $stored_dir = cwd();
167 chdir ($dirname) || die "Unable to change to directory $dirname";
168
169 # Select convert utility
170 if (!defined $input_type) {
171 print STDERR "Error: No filename extension or input type defined\n";
172 exit(1);
173 }
174 elsif ($input_type =~ m/^docx?$/ || $input_type eq "dot") {
175 print &convertDOC($input_filename, $output_filestem, $output_type);
176 print "\n";
177 }
178 elsif ($input_type eq "rtf") {
179 print &convertRTF($input_filename, $output_filestem, $output_type);
180 print "\n";
181 }
182 elsif ($input_type eq "pdf") {
183 print &convertPDF($dirname, $input_filename, $output_filestem, $output_type);
184 print "\n";
185 }
186 elsif ($input_type eq "ps") {
187 print &convertPS($dirname, $input_filename, $output_filestem, $output_type);
188 print "\n";
189 }
190 elsif ($input_type =~ m/pptx?$/) {
191 print &convertPPT($input_filename, $output_filestem, $output_type);
192 print "\n";
193 }
194 elsif ($input_type =~ m/xlsx?$/) {
195 print &convertXLS($input_filename, $output_filestem, $output_type);
196 print "\n";
197 }
198 else {
199 print STDERR "Error: Unable to convert type '$input_type'\n";
200 exit(1);
201 }
202
203 # restore to original working directory
204 chdir ($stored_dir) || die "Unable to return to directory $stored_dir";
205
206}
207
208&main(@ARGV);
209
210
211
212# Document-type conversion functions
213#
214# The following functions attempt to convert documents from their
215# input type to the specified output type. If no output type was
216# given, then they first attempt HTML, and then TEXT.
217#
218# Each returns the output type ("html" or "text") or "fail" if no
219# conversion is possible.
220
221# Convert a Microsoft word document
222
223sub convertDOC {
224 my ($input_filename, $output_filestem, $output_type) = @_;
225
226 # Many .doc files are not in fact word documents!
227 my $realtype = &find_docfile_type($input_filename);
228
229 if ($realtype eq "word6" || $realtype eq "word7"
230 || $realtype eq "word8" || $realtype eq "docx") {
231 return &convertWord678($input_filename, $output_filestem, $output_type);
232 } elsif ($realtype eq "rtf") {
233 return &convertRTF($input_filename, $output_filestem, $output_type);
234 } else {
235 return &convertAnything($input_filename, $output_filestem, $output_type);
236 }
237}
238
239# Convert a Microsoft word 6/7/8 document
240
241sub convertWord678 {
242 my ($input_filename, $output_filestem, $output_type) = @_;
243
244 my $success = 0;
245 if (!$output_type || ($output_type =~ m/html/i)){
246 if ($windows_scripting) {
247 $success = &native_doc_to_html($input_filename, $output_filestem);
248 }
249 else {
250 $success = &doc_to_html($input_filename, $output_filestem);
251 }
252 if ($success) {
253 return "html";
254 }
255 }
256 return &convertAnything($input_filename, $output_filestem, $output_type);
257}
258
259
260# Convert a Rich Text Format (RTF) file
261
262sub convertRTF {
263 my ($input_filename, $output_filestem, $output_type) = @_;
264
265 my $success = 0;
266
267 # Attempt specialised conversion to HTML
268 if (!$output_type || ($output_type =~ m/html/i)) {
269
270 if ($windows_scripting) {
271 $success = &native_doc_to_html($input_filename, $output_filestem);
272 }
273 else {
274 $success = &rtf_to_html($input_filename, $output_filestem);
275 }
276 if ($success) {
277 return "html";
278 }
279 }
280
281# rtf is so ugly that's it's not worth running strings over.
282# One day I'll write some quick'n'dirty regexps to try to extract text - jrm21
283# return &convertAnything($input_filename, $output_filestem, $output_type);
284 return "fail";
285}
286
287
288# Convert an unidentified file
289
290sub convertAnything {
291 my ($input_filename, $output_filestem, $output_type) = @_;
292
293 my $success = 0;
294
295 # Attempt simple conversion to HTML
296 if (!$output_type || ($output_type =~ m/html/i)) {
297 $success = &any_to_html($input_filename, $output_filestem);
298 if ($success) {
299 return "html";
300 }
301 }
302
303 # Convert to text
304 if (!$output_type || ($output_type =~ m/text/i)) {
305 $success = &any_to_text($input_filename, $output_filestem);
306 if ($success) {
307 return "text";
308 }
309 }
310 return "fail";
311}
312
313
314
315# Convert an Adobe PDF document
316
317sub convertPDF {
318 my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
319
320 my $success = 0;
321 $output_type =~ s/.*\-(.*)/$1/i;
322
323 #print STDERR "@@@@@@@@ Using $pdf_tool for the conversion\n";
324
325 # First determine which pdf conversion tool we're using among pdftohtml/pdfbox/xpdftools
326 # and then decide which conversion command to run based on the output type
327 # (pdfbox does not currently go through gsConvert.pl
328 # as PDFBoxConverter inherits from AutoLoadConverters)
329
330 if ($pdf_tool eq "pdftohtml" ) { # old pdftohtml tool
331 # Attempt coversion to Image
332 if ($output_type =~ m/jp?g|gif|png/i) {
333 $success = &pdfps_to_img($dirname, $input_filename, $output_filestem, $output_type);
334 if ($success){
335 return "item";
336 }
337 }
338
339 # Attempt conversion to HTML
340 # Uses the old pdftohtml that doesn't work for newer PDF versions
341 if ($output_type =~ m/^html/i) {
342 #if (!$output_type || ($output_type =~ m/^html/i)) {
343 $success = &pdf_to_html($dirname, $input_filename, $output_filestem);
344 if ($success) {
345 return "html";
346 }
347 }
348
349 # Attempt conversion to TEXT (not for Windows, but PDFPlugin/PDFv1Plugin takes care of that
350 if (!$output_type || ($output_type =~ m/text/i)) {
351 $success = &pdf_to_text($dirname, $input_filename, $output_filestem);
352
353 if ($success) {
354 return "text";
355 }
356 }
357 }
358
359 elsif ($pdf_tool eq "xpdftools" ) {
360
361 # default to paged_pretty_html output
362 if (!$output_type) {
363 $output_type = "paged_pretty_html";
364 }
365
366 # Attempt coversion to Image
367 #if ($output_type =~ m/jp?g|gif|png/i) {
368 # $success = &pdfps_to_img($dirname, $input_filename, $output_filestem, $output_type);
369 # if ($success){
370 # return "item";
371 # }
372 #}
373
374 # Attempt conversion to (paged) pretty HTML using the newer pdftohtml of Xpdftools.
375 if ($output_type =~ m/pretty_html$/i) {
376 $success = &xpdf_to_html($dirname, $input_filename, $output_filestem);
377 if ($success) {
378 return $output_type;
379 }
380 }
381
382 # Attempt conversion to TEXT
383 # Proper paged_text processing not yet implemented with xpdf
384 if ($output_type =~ m/text/i) {
385 $success = &xpdf_to_text($dirname, $input_filename, $output_filestem, $output_type);
386
387 if ($success) {
388 return "text";
389 }
390 }
391 }
392
393 return "fail";
394
395}
396
397
398# Convert an Adobe PostScript document
399
400sub convertPS {
401 my ($dirname,$input_filename, $output_filestem, $output_type) = @_;
402
403 my $success = 0;
404 $output_type =~ s/.*\-(.*)/$1/i;
405 # Attempt coversion to Image
406 if ($output_type =~ m/jp?g|gif|png/i) {
407 $success = &pdfps_to_img($dirname, $input_filename, $output_filestem, $output_type);
408 if ($success){
409 return "item";
410 }
411 }
412
413 # Attempt conversion to TEXT
414 if (!$output_type || ($output_type =~ m/text/i)) {
415 $success = &ps_to_text($input_filename, $output_filestem);
416 if ($success) {
417 return "text";
418 }
419 }
420 return "fail";
421}
422
423
424sub convertPPT {
425 my ($input_filename, $output_filestem, $output_type) = @_;
426 my $success = 0;
427
428 my $ppt_convert_type = "";
429
430 #if (!$output_type || $windows_scripting || ($output_type !~ m/html/i) || ($output_type !~ m/text/i)){
431 if ($windows_scripting && ($output_type !~ m/html/i) && ($output_type !~ m/text/i)){
432 if ($output_type =~ m/gif/i) {
433 $ppt_convert_type = "-g";
434 } elsif ($output_type =~ m/jp?g/i){
435 $ppt_convert_type = "-j";
436 } elsif ($output_type =~ m/png/i){
437 $ppt_convert_type = "-p";
438 }
439 my $vbScript = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "bin",
440 $ENV{'GSDLOS'}, "pptextract");
441 $vbScript = "CScript //Nologo \"".$vbScript.".vbs\"" if ($ENV{'GSDLOS'} =~ m/^windows$/i); # now we use the .vbs VBScript
442 # $vbScript = "pptextract" if ($ENV{'GSDLOS'} =~ m/^windows$/i); # back when the pptextract.exe VB executable was used
443
444 my $cmd = "";
445 if ($timeout) {$cmd = "ulimit -t $timeout;";}
446 # if the converting directory already exists
447 if (-d $output_filestem) {
448 print STDERR "**The conversion directory already exists\n";
449 return "item";
450 } else {
451 $cmd .= "$vbScript $ppt_convert_type \"$input_filename\" \"$output_filestem\"";
452 $cmd .= " 2>\"$output_filestem.err\""
453 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000);
454
455 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
456 if (system($cmd) !=0) {
457 print STDERR "Powerpoint VB Scripting convert failed\n";
458 } else {
459 return "item";
460 }
461 }
462 } elsif (!$output_type || ($output_type =~ m/html/i)) {
463 # Attempt conversion to HTML
464 #if (!$output_type || ($output_type =~ m/html/i)) {
465 # formulate the command
466 my $cmd = "";
467 my $full_perl_path = &util::get_perl_exec();
468 $cmd .= "\"$full_perl_path\" -S ppttohtml.pl ";
469 $cmd .= " \"$input_filename\" \"$output_filestem.html\"";
470 $cmd .= " 2>\"$output_filestem.err\""
471 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000);
472
473 # execute the command
474 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
475 $!=0;
476 if (system($cmd)!=0)
477 {
478 print STDERR "Powerpoint 95/97 converter failed $!\n";
479 } else {
480 return "html";
481 }
482 }
483
484 $success = &any_to_text($input_filename, $output_filestem);
485 if ($success) {
486 return "text";
487 }
488
489 return "fail";
490}
491
492
493sub convertXLS {
494 my ($input_filename, $output_filestem, $output_type) = @_;
495
496 my $success = 0;
497
498 # Attempt conversion to HTML
499 if (!$output_type || ($output_type =~ m/html/i)) {
500 # formulate the command
501 my $cmd = "";
502 my $full_perl_path = &util::get_perl_exec();
503 $cmd .= "\"$full_perl_path\" -S xlstohtml.pl ";
504 $cmd .= " \"$input_filename\" \"$output_filestem.html\"";
505 $cmd .= " 2>\"$output_filestem.err\""
506 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000);
507
508
509 # execute the command
510 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
511
512 $!=0;
513 if (system($cmd)!=0)
514 {
515 print STDERR "Excel 95/97 converter failed $!\n";
516 } else {
517 return "html";
518 }
519 }
520
521 $success = &any_to_text($input_filename, $output_filestem);
522 if ($success) {
523 return "text";
524 }
525
526 return "fail";
527}
528
529
530
531# Find the real type of a .doc file
532#
533# We seem to have a lot of files with a .doc extension that are .rtf
534# files or Word 5 files. This function attempts to tell the difference.
535sub find_docfile_type {
536 my ($input_filename) = @_;
537
538 if (($windows_scripting) && ($input_filename =~ m/\.docx$/)) {
539 return "docx";
540 }
541
542 open(CHK, "<$input_filename");
543 binmode(CHK);
544 my $line = "";
545 my $first = 1;
546
547 while (<CHK>) {
548
549 $line = $_;
550
551 if ($first) {
552 # check to see if this is an rtf file
553 if ($line =~ m/^\{\\rtf/) {
554 close(CHK);
555 return "rtf";
556 }
557 $first = 0;
558 }
559
560 # is this is a word 6/7/8 document?
561 if ($line =~ m/Word\.Document\.([678])/) {
562 close(CHK);
563
564 return "word$1";
565 }
566
567 }
568
569 return "unknown";
570}
571
572
573# Specific type-to-type conversions
574#
575# Each of the following functions attempts to convert a document from
576# a specific format to another. If they succeed they return 1 and leave
577# the output document(s) in the appropriate place; if they fail they
578# return 0 and delete any working files.
579
580
581# Attempt to convert a word document to html with the wv program
582sub doc_to_html {
583 my ($input_filename, $output_filestem) = @_;
584
585 my $wvware_status = 0;
586
587 # need to ensure that the path to perl is quoted (in case there's spaces in it)
588 my $launch_cmd = "\"".&util::get_perl_exec()."\" -S wvware.pl \"$input_filename\" \"$output_filestem\" \"$faillogfile\" $verbosity $timeout";
589
590# print STDERR "***** wvware launch cmd = $launch_cmd\n";
591 print STDERR "gsConvert.pl: About to run cmd $launch_cmd\n" if $verbosity >2;
592
593 $wvware_status = system($launch_cmd)/256;
594 return $wvware_status;
595}
596
597# Attempt to convert a word document to html with the word2html scripting program
598sub native_doc_to_html {
599 my ($input_filename, $output_filestem) = @_;
600
601 # build up the path to the doc-to-html conversion tool we're going to use
602 my $vbScript = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'});
603
604 if ($ENV{'GSDLOS'} =~ m/^windows$/i) {
605 # if windows scripting with docx input, use new VBscript to get the local Word install (if
606 # any) to do the conversion, since docX can't be processed by word2html's windows_scripting
607
608 if($input_filename =~ m/docx$/i) { # need to use full path to docx2html script,
609 # else script launch fails when there are error msgs
610 $vbScript = &FileUtils::filenameConcatenate($vbScript, "docx2html.vbs");
611 $vbScript = "CScript //Nologo \"$vbScript\""; # launch with CScript for error output in STDERR
612 # //Nologo flag avoids Microsoft's opening/logo msgs
613 print STDERR "About to use windows scripting to process docx file $input_filename.\n";
614 print STDERR " This may take some time. Please wait...\n";
615 }
616 else { # old doc versions. use the usual VB executable word2html for the
617 # conversion. Doesn't need full path, since bin\windows is on PATH
618 $vbScript = "word2html"; #$vbScript = "\"".&FileUtils::filenameConcatenate($vbScript, "word2html")."\"";
619 }
620 }
621 else { # not windows
622 $vbScript = "\"".&FileUtils::filenameConcatenate($vbScript, "word2html")."\"";
623 }
624
625 if (-e "$output_filestem.html") {
626 print STDERR " The conversion file:\n";
627 print STDERR " $output_filestem.html\n";
628 print STDERR " ... already exists. Skipping\n";
629 return 1;
630 }
631
632 my $cmd = "";
633 if ($timeout) {$cmd = "ulimit -t $timeout;";}
634 #$cmd .= "$vbScript \"$input_filename\" \"$output_filestem.html\"";
635 #$cmd .= "$vbScript $input_filename $output_filestem.html";
636 $cmd .= "$vbScript \"$input_filename\" \"$output_filestem.html\"";
637
638 # redirecting STDERR
639
640 $cmd .= " 2> \"$output_filestem.err\""
641 if ($ENV {'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000);
642
643 # execute the command
644 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
645
646 $!=0;
647 if (system($cmd)!=0)
648 {
649 print STDERR "Error executing $vbScript converter:$!\n";
650 if (-s "$output_filestem.err") {
651 open (ERRFILE, "<$output_filestem.err");
652
653 my $write_to_fail_log=0;
654 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
655 {$write_to_fail_log=1;}
656
657 my $line;
658 while ($line=<ERRFILE>) {
659 if ($line =~ m/\w/) {
660 print STDERR "$line";
661 print FAILLOG "$line" if ($write_to_fail_log);
662 }
663 if ($line !~ m/startup error/) {next;}
664 print STDERR " (given an invalid .DOC file?)\n";
665 print FAILLOG " (given an invalid .DOC file?)\n"
666 if ($write_to_fail_log);
667
668 } # while ERRFILE
669 close FAILLOG if ($write_to_fail_log);
670 }
671 return 0; # we can try any_to_text
672 }
673
674 # Was the conversion successful?
675 if (-s "$output_filestem.html") {
676 open(TMP, "$output_filestem.html");
677 my $line = <TMP>;
678 close(TMP);
679 if ($line && $line =~ m/html/i) {
680 &FileUtils::removeFiles("$output_filestem.err") if -e "$output_filestem.err";
681 return 1;
682 }
683 }
684
685 # If here, an error of some sort occurred
686 &FileUtils::removeFiles("$output_filestem.html") if -e "$output_filestem.html";
687 if (-e "$output_filestem.err") {
688 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile"))) {
689 open (ERRLOG,"$output_filestem.err");
690 while (<ERRLOG>) {print FAILLOG $_;}
691 close FAILLOG;
692 close ERRLOG;
693 }
694 &FileUtils::removeFiles("$output_filestem.err");
695 }
696 return 0;
697}
698
699# Attempt to convert an RTF document to html with rtftohtml
700sub rtf_to_html {
701 my ($input_filename, $output_filestem) = @_;
702
703 # formulate the command
704 my $cmd = "";
705 if ($timeout) {$cmd = "ulimit -t $timeout;";}
706 $cmd .= "rtftohtml";
707 #$cmd .= "rtf-converter";
708
709 $cmd .= " -o \"$output_filestem.html\" \"$input_filename\"";
710
711 $cmd .= " 2>\"$output_filestem.err\""
712 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000);
713
714
715 # execute the command
716 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
717
718 $!=0;
719 if (system($cmd)!=0)
720 {
721 print STDERR "Error executing rtf converter $!\n";
722 # don't currently bother printing out error log...
723 # keep going, in case it still created an HTML file...
724 }
725
726 # Was the conversion successful?
727 my $was_successful=0;
728 if (-s "$output_filestem.html") {
729 # make sure we have some content other than header
730 open (HTML, "$output_filestem.html"); # what to do if fail?
731 my $line;
732 my $past_header=0;
733 while ($line=<HTML>) {
734
735 if ($past_header == 0) {
736 if ($line =~ m/<body>/) {$past_header=1;}
737 next;
738 }
739
740 $line =~ s/<[^>]+>//g;
741 if ($line =~ m/\w/ && $past_header) { # we found some content...
742 $was_successful=1;
743 last;
744 }
745 }
746 close HTML;
747 }
748
749 if ($was_successful) {
750 &FileUtils::removeFiles("$output_filestem.err")
751 if (-e "$output_filestem.err");
752 # insert the (modified) table of contents, if it exists.
753 if (-e "${output_filestem}_ToC.html") {
754 &FileUtils::moveFiles("$output_filestem.html","$output_filestem.src");
755 my $open_failed=0;
756 open HTMLSRC, "$output_filestem.src" || ++$open_failed;
757 open TOC, "${output_filestem}_ToC.html" || ++$open_failed;
758 open HTML, ">$output_filestem.html" || ++$open_failed;
759
760 if ($open_failed) {
761 close HTMLSRC;
762 close TOC;
763 close HTML;
764 &FileUtils::moveFiles("$output_filestem.src","$output_filestem.html");
765 return 1;
766 }
767
768 # print out header info from src html.
769 while (defined($_ = <HTMLSRC>) && $_ =~ m/\w/) {
770 print HTML "$_";
771 }
772
773 # print out table of contents, making links relative
774 <TOC>; <TOC>; # ignore first 2 lines
775 print HTML scalar(<TOC>); # line 3 = "<ol>\n"
776 my $line;
777 while ($line=<TOC>) {
778 $line =~ s@</body></html>$@@i ; # only last line has this
779 # make link relative
780 $line =~ s@href=\"[^\#]+@href=\"@i;
781 print HTML $line;
782 }
783 close TOC;
784
785 # rest of html src
786 while (<HTMLSRC>) {
787 print HTML $_;
788 }
789 close HTMLSRC;
790 close HTML;
791
792 &FileUtils::removeFiles("${output_filestem}_ToC.html");
793 &FileUtils::removeFiles("${output_filestem}.src");
794 }
795 # we don't yet do anything with footnotes ($output_filestem_fn.html) :(
796 return 1; # success
797 }
798
799 if (-e "$output_filestem.err") {
800 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
801 {
802 print FAILLOG "Error - rtftohtml - couldn't extract text\n";
803 #print FAILLOG "Error - rtf-converter - couldn't extract text\n";
804 print FAILLOG " (rtf file might be too recent):\n";
805 open (ERRLOG, "$output_filestem.err");
806 while (<ERRLOG>) {print FAILLOG $_;}
807 close ERRLOG;
808 close FAILLOG;
809 }
810 &FileUtils::removeFiles("$output_filestem.err");
811 }
812
813 &FileUtils::removeFiles("$output_filestem.html") if (-e "$output_filestem.html");
814
815 return 0;
816}
817
818
819# Convert a pdf file to html with the old pdftohtml command
820# which only works for older PDF versions
821sub pdf_to_html {
822 my ($dirname, $input_filename, $output_filestem) = @_;
823
824 my $cmd = "";
825 if ($timeout) {$cmd = "ulimit -t $timeout;";}
826 my $full_perl_path = &util::get_perl_exec();
827 $cmd .= "\"$full_perl_path\" -S pdftohtml.pl -zoom $pdf_zoom";
828 $cmd .= " -c" if ($pdf_complex);
829 $cmd .= " -i" if ($pdf_ignore_images);
830 $cmd .= " -a" if ($pdf_allow_images_only);
831 $cmd .= " -hidden" unless ($pdf_nohidden);
832 $cmd .= " \"$input_filename\" \"$output_filestem\"";
833
834 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000) {
835 $cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
836 } else {
837 $cmd .= " > \"$output_filestem.err\"";
838 }
839
840 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
841 $!=0;
842 my $retval=system($cmd);
843 if ($retval!=0)
844 {
845 print STDERR "Error executing pdftohtml.pl";
846 if ($!) {print STDERR ": $!";}
847 print STDERR "\n";
848 }
849
850 # make sure the converter made something
851 if ($retval!=0 || ! -s "$output_filestem.html")
852 {
853 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
854 # print out the converter's std err, if any
855 if (-s "$output_filestem.err") {
856 open (ERRLOG, "$output_filestem.err") || die "$!";
857 print STDERR "pdftohtml error log:\n";
858 while (<ERRLOG>) {
859 print STDERR "$_";
860 }
861 close ERRLOG;
862 }
863 #print STDERR "***********output filestem $output_filestem.html\n";
864 &FileUtils::removeFiles("$output_filestem.html") if (-e "$output_filestem.html");
865 if (-e "$output_filestem.err") {
866 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
867 {
868 open (ERRLOG, "$output_filestem.err");
869 while (<ERRLOG>) {print FAILLOG $_;}
870 close ERRLOG;
871 close FAILLOG;
872 }
873 &FileUtils::removeFiles("$output_filestem.err");
874 }
875 return 0;
876 }
877
878 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
879 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
880 return 1;
881}
882
883
884# Convert a pdf file to html with the newer Xpdftools' pdftohtml
885# This generates "paged HTML" where extracted, selectable text is positioned
886# over screenshots of each page.
887# Since xpdf's pdftohtml fails if the output dir already exists and for easier
888# naming, the output files are created in a "pages" subdirectory of the tmp
889# location parent of $output_filestem instead
890sub xpdf_to_html {
891 my ($dirname, $input_filename, $output_filestem) = @_;
892
893 my $cmd = "";
894
895 # build up the path to the doc-to-html conversion tool we're going to use
896 my $xpdf_pdftohtml = &FileUtils::filenameConcatenate(_get_xpdftools_bindir(), "pdftohtml");
897
898 # We'll create the file by name $output_filestem during post-conversion processing.
899 # Note that Xpdf tools will only create its conversion products in a dir that does
900 # not yet exist. So we'll create this location as a subdir of the output_filestem's
901 # parent directory. The parent dir is the already generated tmp area for conversion. So:
902 # - tmpdir gs2build/tmp/<random-num> already exists at this stage
903 # - We'll create gs2build/tmp/<rand>/output_filestem.html later, during post-processing
904 # - For now, XPdftools will create gs2build/tmp/<rand>/pages and put its products in there.
905 my ($tailname, $tmp_dirname, $suffix)
906 = &File::Basename::fileparse($output_filestem, "\\.[^\\.]+\$");
907 $tmp_dirname = &FileUtils::filenameConcatenate($tmp_dirname, "pages");
908
909 # xpdf's pdftohtml tool also takes a zoom factor, where a zoom of 1 is 100%
910 $cmd .= "\"$xpdf_pdftohtml\"";
911 # resolution, -r in DPI of background images, see https://www.xpdfreader.com/pdftohtml-man.html
912 $cmd .= " -r $pdf_dpi" if ($pdf_dpi);
913 $cmd .= " \"$input_filename\" \"$tmp_dirname\"";
914 #$cmd .= " \"$input_filename\" \"$output_filestem\"";
915
916 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000) {
917 $cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
918 } else {
919 $cmd .= " > \"$output_filestem.err\"";
920 }
921
922 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
923 $!=0;
924 my $retval=system($cmd);
925 if ($retval!=0)
926 {
927 print STDERR "Error executing xpdf's pdftohtml tool";
928 if ($!) {print STDERR ": $!";}
929 print STDERR "\n";
930 }
931
932 # make sure the converter made something
933 if ($retval!=0 || ! -s &FileUtils::filenameConcatenate($tmp_dirname,"index.html"))
934 {
935 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
936 # print out the converter's std err, if any
937 if (-s "$output_filestem.err") {
938 open (ERRLOG, "$output_filestem.err") || die "$!";
939 print STDERR "pdftohtml error log:\n";
940 while (<ERRLOG>) {
941 print STDERR "$_";
942 }
943 close ERRLOG;
944 }
945 #print STDERR "***********output filestem $output_filestem.html\n";
946 &FileUtils::removeFiles("$tmp_dirname") if (-d "$tmp_dirname");
947 if (-e "$output_filestem.err") {
948 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
949 {
950 open (ERRLOG, "$output_filestem.err");
951 while (<ERRLOG>) {print FAILLOG $_;}
952 close ERRLOG;
953 close FAILLOG;
954 }
955 &FileUtils::removeFiles("$output_filestem.err");
956 }
957 return 0;
958 }
959
960 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
961 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
962 return 1;
963}
964
965# Returns the path to xpdf-tools's containing bin dir appropriate for this machine's OS and bitness
966sub _get_xpdftools_bindir {
967
968 # build up the path to the containing bin dir of the xpdf conversion tool we're going to use
969 my $xpdf_tools_bin = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}, "xpdf-tools", "bin");
970 return $xpdf_tools_bin;
971}
972
973# Convert a pdf file to various types of image with the convert command
974
975sub pdfps_to_img {
976 my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
977
978 # Check that ImageMagick is installed and available on the path (except for Windows 95/98)
979 if (!($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT())) {
980 my $imagick_cmd = "\"".&util::get_perl_exec()."\" -S gs-magick.pl";
981 $imagick_cmd = $imagick_cmd." --verbosity=$verbosity" if defined $verbosity;
982 print STDERR "gsConvert.pl: About to run cmd $imagick_cmd\n" if $verbosity >2;
983 my $result = `$imagick_cmd identify 2>&1`;
984
985 # Linux and Windows return different values for "program not found".
986 # Linux returns -1 and Windows 256 for "program not found". But once they're
987 # converted to signed values, it will be -1 for Linux and 1 for Windows.
988 # Whenever we test for return values other than 0, shift by 8 and perform
989 # unsigned to signed status conversion on $? to get expected range of return vals
990 # Although gs-magick.pl already shifts its $? by 8, converts it to a signed value
991 # and then exits on that, by the time we get here, we need to do it again
992 my $status = $?;
993 $status >>= 8;
994 $status = (($status & 0x80) ? -(0x100 - ($status & 0xFF)) : $status);
995 if (($ENV{'GSDLOS'} ne "windows" && $status == -1) || ($ENV{'GSDLOS'} eq "windows" && $status == 1)) {
996 # if ($status == -1 || $status == 1) #if ($status == -1 || $status == 256) {
997 #ImageMagick is not installed, thus the convert utility is not available.
998 print STDERR "*** ImageMagick is not installed, the convert utility is not available. Unable to convert PDF/PS to images. Status: $status\n";
999 return 0;
1000 }
1001 }
1002
1003 my $cmd = "";
1004 if ($timeout) {$cmd = "ulimit -t $timeout;";}
1005 $output_type =~ s/.*\_(.*)/$1/i;
1006 my $full_perl_path = &util::get_perl_exec();
1007 $cmd .= "\"$full_perl_path\" -S pdfpstoimg.pl -convert_to $output_type \"$input_filename\" \"$output_filestem\"";
1008 if ($ENV{'GSDLOS'} !~ m/^windows$/i || $is_winnt_2000) {
1009 $cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
1010 } else {
1011 $cmd .= " > \"$output_filestem.err\"";
1012 }
1013
1014 # don't include path on windows (to avoid having to play about
1015 # with quoting when GSDLHOME might contain spaces) but assume
1016 # that the PATH is set up correctly
1017 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
1018 $!=0;
1019 my $retval=system($cmd);
1020 if ($retval!=0)
1021 {
1022 print STDERR "Error executing pdfpstoimg.pl";
1023 if ($!) {print STDERR ": $!";}
1024 print STDERR "\n";
1025 }
1026
1027 #make sure the converter made something
1028 #if ($retval !=0) || ! -s "$output_filestem")
1029 if ($retval !=0)
1030 {
1031 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
1032 #print out the converter's std err, if any
1033 if (-s "$output_filestem.err") {
1034 open (ERRLOG, "$output_filestem.err") || die "$!";
1035 print STDERR "pdfpstoimg error log:\n";
1036 while (<ERRLOG>) {
1037 print STDERR "$_";
1038 }
1039 close ERRLOG;
1040 }
1041 #&FileUtils::removeFiles("$output_filestem.html") if (-e "$output_filestem.html");
1042 if (-e "$output_filestem.err") {
1043 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
1044 {
1045 open (ERRLOG, "$output_filestem.err");
1046 while (<ERRLOG>) {print FAILLOG $_;}
1047 close ERRLOG;
1048 close FAILLOG;
1049 }
1050 &FileUtils::removeFiles("$output_filestem.err");
1051 }
1052 return 0;
1053 }
1054 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
1055 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
1056 return 1;
1057}
1058
1059# Convert a PDF file to text with xpdftools' pdftotext command
1060# Works for Windows too, whereas the old pdftotxt didn't
1061sub xpdf_to_text {
1062 my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
1063
1064 my $cmd = "";
1065
1066 # build up the path to the doc-to-txt conversion tool we're going to use
1067 my $xpdf_pdftotxt = &FileUtils::filenameConcatenate(_get_xpdftools_bindir(), "pdftotext");
1068
1069 # For xpdf's pdftotxt options, see https://www.xpdfreader.com/pdftotext-man.html
1070 $cmd .= "\"$xpdf_pdftotxt\"";
1071 if($enc) {
1072 $cmd .= " -enc $enc"; # decode the bytes in the file using the designated encoding scheme
1073 } else {
1074 # as per https://www.xpdfreader.com/pdftotext-man.html
1075 # xpdf's pdftotxt defaults to using Latin-1 encoding, should we default to UTF-8?
1076 $cmd .= " -enc UTF-8"; # see https://www.xpdfreader.com/xpdfrc-man.html
1077 }
1078
1079 if ($output_type ne "paged_text") { # output_type eq "text", don't bother about page break markers
1080 $cmd .= " -nopgbrk";
1081 }
1082 # Avoid the silly solitary carriage returns (CR in Notepad) at the end
1083 # of lines that ends up as \n appended to the doc title
1084 # by setting the end of line marker to unix style solitary newline (LF or \n),
1085 # which doesn't end up in the doc title
1086 $cmd .= " -eol unix";
1087 $cmd .= " \"$input_filename\" \"$output_filestem.text\"";
1088
1089 return _run_pdf_to_text_cmd($cmd, $output_filestem);
1090}
1091
1092# Convert a PDF file to text with the pdftotext command
1093
1094sub pdf_to_text {
1095 my ($dirname, $input_filename, $output_filestem) = @_;
1096
1097 my $cmd = "pdftotext \"$input_filename\" \"$output_filestem.text\"";
1098
1099 return _run_pdf_to_text_cmd($cmd, $output_filestem);
1100}
1101
1102sub _run_pdf_to_text_cmd {
1103 my ($cmd, $output_filestem) = @_;
1104
1105 if ($ENV{'GSDLOS'} !~ m/^windows$/i) {
1106 $cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
1107 } else {
1108 $cmd .= " > \"$output_filestem.err\"";
1109 }
1110 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
1111 if (system($cmd)!=0)
1112 {
1113 print STDERR "Error executing $cmd: $!\n";
1114 &FileUtils::removeFiles("$output_filestem.text") if (-e "$output_filestem.text");
1115 }
1116
1117 # make sure there is some extracted text.
1118 if (-e "$output_filestem.text") {
1119 open (EXTR_TEXT, "$output_filestem.text") || warn "open: $!";
1120 binmode(EXTR_TEXT); # just in case...
1121 my $line="";
1122 my $seen_text=0;
1123 while (($seen_text==0) && ($line=<EXTR_TEXT>)) {
1124 if ($line=~ m/\w/) {$seen_text=1;}
1125 }
1126 close EXTR_TEXT;
1127 if ($seen_text==0) { # no text was extracted
1128 print STDERR "Error: pdftotext found no text\n";
1129 &FileUtils::removeFiles("$output_filestem.text");
1130 }
1131 }
1132
1133 # make sure the converter made something
1134 if (! -s "$output_filestem.text")
1135 {
1136 # print out the converters std err, if any
1137 if (-s "$output_filestem.err") {
1138 open (ERRLOG, "$output_filestem.err") || die "$!";
1139 print STDERR "pdftotext error log:\n";
1140 while (<ERRLOG>) {
1141 print STDERR "$_";
1142 }
1143 close ERRLOG;
1144 }
1145 # does this converter create a .out file?
1146 &FileUtils::removeFiles("$output_filestem.out") if (-e "$output_filestem.out");
1147 &FileUtils::removeFiles("$output_filestem.text") if (-e "$output_filestem.text");
1148 if (-e "$output_filestem.err") {
1149 if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
1150 {
1151 open (ERRLOG,"$output_filestem.err");
1152 while (<ERRLOG>) {print FAILLOG $_;}
1153 close ERRLOG;
1154 close FAILLOG;
1155 }
1156 &FileUtils::removeFiles("$output_filestem.err");
1157 }
1158 return 0;
1159 }
1160 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
1161 return 1;
1162}
1163
1164# Convert a PostScript document to text
1165# note - just using "ps2ascii" isn't good enough, as it
1166# returns 0 for a postscript interpreter error. ps2ascii is just
1167# a wrapper to "gs" anyway, so we use that cmd here.
1168
1169sub ps_to_text {
1170 my ($input_filename, $output_filestem) = @_;
1171
1172 my $error = "";
1173
1174 # if we're on windows we'll fall straight through without attempting
1175 # to use gs
1176 if ($ENV{'GSDLOS'} =~ m/^windows$/i) {
1177 $error = "Windows does not support gs";
1178
1179 } else {
1180 my $cmd = "";
1181 if ($timeout) {$cmd = "ulimit -t $timeout; ";}
1182 $cmd .= "gs -q -dNODISPLAY -dNOBIND -dWRITESYSTEMDICT -dSIMPLE -c save ";
1183 $cmd .= "-f ps2ascii.ps \"$input_filename\" -c quit > \"$output_filestem.text\"";
1184 #$cmd .= "pstotext -output \"$output_filestem.text\" $input_filename\"";
1185 $cmd .= " 2> $output_filestem.err";
1186
1187 print STDERR "gsConvert.pl: About to run cmd $cmd\n" if $verbosity >2;
1188 $!=0;
1189 my $retcode=system($cmd);
1190 $retcode = $? >> 8; # see man perlfunc - system for this...
1191 # if system returns -1 | 127 (couldn't start program), look at $! for message
1192
1193 if ($retcode!=0) {if ($!) {$error=$!;} else {$error="couldn't run.\n";}}
1194 elsif (! -e "$output_filestem.text") {
1195 $error="did not create output file.\n";
1196 }
1197 else
1198 { # make sure the interpreter didn't get an error. It is technically
1199 # possible for the actual text to start with this, but....
1200 open PSOUT, "$output_filestem.text";
1201 if (<PSOUT> =~ m/^Error: (.*)/) {
1202 $error="interpreter error - \"$1\"";
1203 }
1204 close PSOUT;
1205 }
1206 }
1207
1208 if ($error ne "")
1209 {
1210 print STDERR "Warning: Error executing gs: $error\n";
1211 print STDERR "Resorting to Perl regular expressions to extract text from PostScript...\n";
1212 &FileUtils::removeFiles("$output_filestem.text") if (-e "$output_filestem.text");
1213
1214 if ("$faillogfile" ne "" && defined(open (FAILLOG, ">>$faillogfile")))
1215 {
1216 print FAILLOG "gs - $error\n";
1217 if (-e "$output_filestem.err") {
1218 open(ERRLOG, "$output_filestem.err");
1219 while (<ERRLOG>) {print FAILLOG $_;}
1220 close ERRLOG;
1221 }
1222 close FAILLOG;
1223 }
1224 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
1225
1226
1227 # Fine then. We'll just do a lousy job by ourselves...
1228 # Based on 5-line regexp sed script found at:
1229 # http://snark.ptc.spbu.ru/mail-archives/lout/brown/msg00003.html
1230 #
1231 print STDERR "Stripping text from postscript\n";
1232 my $errorcode=0;
1233 open (IN, "$input_filename")
1234 || ($errorcode=1, warn "Couldn't read file: $!");
1235 open (OUT, ">$output_filestem.text")
1236 || ($errorcode=1, warn "Couldn't write file: $!");
1237 if ($errorcode) {print STDERR "errors\n";return 0;}
1238
1239 my $text=""; # this is for whole .ps file...
1240 $text = join('', <IN>); # see man perlport, under "System Resources"
1241 close IN;
1242
1243 # Make sure this is a ps file...
1244 if ($text !~ m/^%!/) {
1245 print STDERR "Bad postscript header: not '%!'\n";
1246 if ($faillogfile ne "" && defined(open(FAILLOG, ">>$faillogfile")))
1247 {
1248 print FAILLOG "Bad postscript header: not '%!'\n";
1249 close FAILLOG;
1250 }
1251 return 0;
1252 }
1253
1254 # if ps has Page data, then use it to delete all stuff before it.
1255 $text =~ s/^.*?%%Page:.*?\n//s; # treat string as single line
1256
1257 # remove all leading non-data stuff
1258 $text =~ s/^.*?\(//s;
1259
1260 # remove all newline chars for easier processing
1261 $text =~ s/\n//g;
1262
1263 # Big assumption here - assume that if any co-ordinates are
1264 # given, then we are at the end of a sentence.
1265 $text =~ s/\)-?\d+\ -?\d+/\) \(\n\)/g;
1266
1267 # special characters--
1268 $text =~ s/\(\|\)/\(\ - \)/g; # j -> em-dash?
1269
1270 # ? ps text formatting (eg italics?) ?
1271 $text =~ s/Fn\(f\)/\(\{\)/g; # f -> {
1272 $text =~ s/Fn\(g\)/\(\}\)/g; # g -> }
1273 $text =~ s/Fn\(j\)/\(\|\)/g; # j -> |
1274 # default - remove the rest
1275 $text =~ s/\ ?F.\((.+?)\)/\($1\)/g;
1276
1277 # attempt to add whitespace between words...
1278 # this is based purely on observation, and may be completely wrong...
1279 $text =~ s/([^F])[defghijkuy]\(/$1 \( /g;
1280 # eg I notice "b(" is sometimes NOT a space if preceded by a
1281 # negative number.
1282 $text =~ s/\)\d+ ?b\(/\) \( /g;
1283
1284 # change quoted braces to brackets
1285 $text =~ s/([^\\])\\\(/$1\{/g;
1286 $text =~ s/([^\\])\\\)/$1\}/g ;
1287
1288 # remove everything that is not between braces
1289 $text =~ s/\)([^\(\)])+?\(//sg ;
1290
1291 # remove any Trailer eof stuff.
1292 $text =~ s/\)[^\)]*$//sg;
1293
1294 ### ligatures have special characters...
1295 $text =~ s/\\013/ff/g;
1296 $text =~ s/\\014/fi/g;
1297 $text =~ s/\\015/fl/g;
1298 $text =~ s/\\016/ffi/g;
1299 $text =~ s/\\214/fi/g;
1300 $text =~ s/\\215/fl/g;
1301 $text =~ s/\\017/\n\* /g; # asterisk?
1302 $text =~ s/\\023/\023/g; # e acute ('e)
1303 $text =~ s/\\177/\252/g; # u"
1304# $text =~ s/ ?? /\344/g; # a"
1305
1306 print OUT "$text";
1307 close OUT;
1308 }
1309 # wrap the text - use a minimum length. ie, first space after this length.
1310 my $wrap_length=72;
1311 &FileUtils::moveFiles("$output_filestem.text", "$output_filestem.text.tmp");
1312 open INFILE, "$output_filestem.text.tmp" ||
1313 die "Couldn't open file: $!";
1314 open OUTFILE, ">$output_filestem.text" ||
1315 die "Couldn't open file for writing: $!";
1316 my $line="";
1317 while ($line=<INFILE>) {
1318 while (length($line)>0) {
1319 if (length($line)>$wrap_length) {
1320 $line =~ s/^(.{$wrap_length}[^\s]*)\s*//;
1321 print OUTFILE "$1\n";
1322 } else {
1323 print OUTFILE "$line";
1324 $line="";
1325 }
1326 }
1327 }
1328 close INFILE;
1329 close OUTFILE;
1330 &FileUtils::removeFiles("$output_filestem.text.tmp");
1331
1332 &FileUtils::removeFiles("$output_filestem.err") if (-e "$output_filestem.err");
1333 return 1;
1334}
1335
1336
1337# Convert any file to HTML with a crude perl implementation of the
1338# UNIX strings command.
1339
1340sub any_to_html {
1341 my ($input_filename, $output_filestem) = @_;
1342
1343 # First generate a text file
1344 return 0 unless (&any_to_text($input_filename, $output_filestem));
1345
1346 # create an HTML file from the text file
1347 open(TEXT, "<$output_filestem.text");
1348 open(HTML, ">$output_filestem.html");
1349
1350 print HTML "<html><head>\n";
1351 print HTML "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\">\n";
1352 print HTML "<META NAME=\"GENERATOR\" CONTENT=\"Greenstone any_to_html\">\n";
1353 print HTML "</head><body>\n\n";
1354
1355 my $line;
1356 while ($line=<TEXT>) {
1357 $line =~ s/</&lt;/g;
1358 $line =~ s/>/&gt;/g;
1359 if ($line =~ m/^\s*$/) {
1360 print HTML "<p>";
1361 } else {
1362 print HTML "<br> ", $line;
1363 }
1364 }
1365 print HTML "\n</body></html>\n";
1366
1367 close HTML;
1368 close TEXT;
1369
1370 &FileUtils::removeFiles("$output_filestem.text") if (-e "$output_filestem.text");
1371 return 1;
1372}
1373
1374# Convert any file to TEXT with a crude perl implementation of the
1375# UNIX strings command.
1376# Note - this assumes ascii charsets :( (jrm21)
1377
1378sub any_to_text {
1379 my ($input_filename, $output_filestem) = @_;
1380
1381 if (!$use_strings) {
1382 return 0;
1383 }
1384
1385 print STDERR "\n**** In any to text****\n\n";
1386 open(IN, "<$input_filename") || return 0;
1387 binmode(IN);
1388 open(OUT, ">$output_filestem.text") || return 0;
1389
1390 my ($line);
1391 my $output_line_count = 0;
1392 while (<IN>) {
1393 $line = $_;
1394
1395 # delete anything that isn't a printable character
1396 $line =~ s/[^\040-\176]+/\n/sg;
1397
1398 # delete any string less than 10 characters long
1399 $line =~ s/^.{0,9}$/\n/mg;
1400 while ($line =~ m/^.{1,9}$/m) {
1401 $line =~ s/^.{0,9}$/\n/mg;
1402 $line =~ s/\n+/\n/sg;
1403 }
1404
1405 # remove extraneous whitespace
1406 $line =~ s/\n+/\n/gs;
1407 $line =~ s/^\n//gs;
1408
1409 # output whatever is left
1410 if ($line =~ m/[^\n ]/) {
1411 print OUT $line;
1412 ++$output_line_count;
1413 }
1414 }
1415
1416 close OUT;
1417 close IN;
1418
1419 if ($output_line_count) { # try to protect against binary only formats
1420 return 1;
1421 }
1422
1423 &FileUtils::removeFiles("$output_filestem.text");
1424 return 0;
1425
1426}
Note: See TracBrowser for help on using the repository browser.