I have found a way to use wvHtml to process word documents. Anyone interested?

[email protected]
Newsgroups gmane.comp.web.htdig.devel
Message-ID <[email protected]>



Hi People,

I've just written an addon external parsing script that goes with
doc2html.pl, allowing htdig to index word documents using the wvHtml
application (part of http://sourceforge.net/projects/wvware/ )

If anyone's interested, it's attached, along with a modifed doc2html.pl
file.

(See attached file: doc2html.pl)(See attached file: word2html.pl)

Needs work, but is good enough for my purposes now.   Figured it could be
handy for someone else.

Cheers
Glen Ogilvie
doc2html.pl (application/octet-stream, 17.1 KB)
#!/usr/bin/perl
use strict;
#
# Version 3.0	4-June-2001
#
# External converter for htdig 3.1.4 or later (Perl5 or later)
# Usage: (in htdig.conf)
#
#external_parsers:	application/rtf->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			text/rtf->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/pdf->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/postscript->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/msword->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/wordperfect5.1->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/msexcel->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/vnd.ms-excel->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/vnd.ms-powerpoint->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl
#			application/x-shockwave-flash->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl \
#			application/x-shockwave-flash2-preview->text/html /opt/local/htdig-3.1.5/scripts/doc2html.pl
#
#  Uses wp2html to convert Word and WordPerfect documents into HTML, and
#  falls back to using Catdoc for Word and Catwpd for WordPerfect if 
#  Wp2html is unavailable or unable to convert.
#
#  Uses range of other converters as available.
#
#  If all else fails, attempts to read file without conversion.
#
########################################################################################
# Written by David Adams <[email protected]>.
# Based on conv_doc.pl written by Gilles Detillieux <[email protected]>,
#   which in turn was based on the parse_word_doc.pl script, written by
#   Jesse op den Brouw <[email protected]>.
########################################################################################

# Install Sys::AlarmCall if you can
eval "use Sys::AlarmCall";

########  Full paths to conversion utilities  ##########
########          YOU MUST SET THESE          ##########
########  (comment out those you don't have)  ##########

# Wp2html converts Word & Wordperfect to HTML
# (get it from: http://www.res.bbsrc.ac.uk/wp2html/)
my $WP2HTML = '';

#Catwpd for WordPerfect to text conversion
# (you don't need this if you have wp2html)
# (get it from htdig site)
my $CATWPD = '';

# rtf2html converts Rich Text Font documents to HTML
# (get it from http://www.fe.msk.ru/~vitus/catdoc/)
my $RTF2HTML = '';

# Catdoc converts MS Word to plain text
# (get it from: http://www.fe.msk.ru/~vitus/catdoc/)

#version of catdoc for Word6, Word7 & Word97 files:
my $CATDOC = '/usr/share/htdig/doc2html/word2html.pl';

#version of catdoc for Word2 files
my $CATDOC2 = $CATDOC;

#version of catdoc for Word 5.1 for MAC
my $CATDOCM = $CATDOC;

# PostScript to text converter
# (get it from the ghostscript 3.33 (or later) package)
my $CATPS = '';

# add to search path the directory which contains gs
# (edit for your environment)
$ENV{PATH} .= ":/usr/freeware/bin";

# PDF to HTML conversion script
# Full pathname of Perl script pdf2html.pl
my $PDF2HTML = '/usr/share/htdig/doc2html/pdf2html.pl';

#Microsoft Excel to HTML converter
# (get it from www.xlHtml.org)
my $XLS2HTML = '';

#MicroSoft Excel to .CSV converter
# (you don't need this if you have xlHtml)
# (if you do want it, you can get it with catdoc)
my $CATXLS = '';

#Microsoft Powerpoint to HTML converter
# (get it from www.xlHtml.org)
my $PPT2HTML = '';

#Shockwave Flash 
# (extracts links from file)
# Full pathname of Perl script swf2html.pl
my $SWF2HTML = '';

########################################################################

# Other Global Variables
my ($Success, $LOG, $Verbose, $CORE_MESS, $TMP, $RM, $ED, $Magic, $Time,
    $Count, $Prog, $Input, $MIME_type, $URL, $Name, $Efile, $Maxerr, 
    $Redir, $Emark, $EEmark, $Method);
my (%HTML_Method, %TEXT_Method, %BAD_type);


&init;			# initialise
&store_methods;		# 
&read_magic;		# Magic reveals type
&error_setup;		# re-route standard error o/p from utilities

# see if a document -> HTML converter will work:
&run('&try_html');
if ($Success) { &quit(0) }

# try a document -> text converter:
&run('&try_text');
if ($Success) { &quit(0) }

# see if a known problem
my $fail = &cannot_do;
if ($fail) { &quit($fail) }

# last-ditch attempt, try copying document
&try_plain;
if ($Success) {&quit(0)}

&quit("UNABLE to convert");

#------------------------------------------------------------------------------

sub init {

  # Doc2html log file
  $LOG = $ENV{'DOC2HTML_LOG'} || '';
  #
  if ($LOG) {
    open(STDERR,">>$LOG"); # ignore possible failure to open
  } # else O/P really does go to STDERR

  # Set to 1 for O/P to STDERR or Log file
  $Verbose = exists($ENV{'DOC2HTML_LOG'}) ? 1 : 0;

  # Mark error message produced within doc2html script
  $Emark = "!\t";
  # Mark error message produced by conversion utility
  $EEmark = "!!\t";

  # Message to STDERR if core dump detected
  $CORE_MESS = "CORE DUMPED";

  # Directory for temporary files
  $TMP = "/tmp/htdig";
  if (! -d $TMP) {
    mkdir($TMP,0700) or die "Unable to create directory \"$TMP\": $!";
  }
  # Current directory during run of script:
  chdir $TMP or warn "Cannot change directory to $TMP\n";

  # File for error output from utility
  $Efile = 'doc_err.' . $$;

  # Max. number of lines of error output from utility copied
  $Maxerr = 10;

  # System command to delete a file
  $RM = "/bin/rm -f";

  # Line editor to do substitution
  $ED = "/bin/sed -e"; 
  if ($^O eq "MSWin32") {$ED = "$^X -pe"}

  $Time = 60;	# allow 60 seconds for external utility to complete

  $Success = 0;
  $Count = 0;
  $Method = '';
  $Prog = $0;
  $Prog =~ s#^.*/##; 
  $Prog =~ s/\..*?$//;

  $Input = $ARGV[0] or die "No filename given\n";
  $MIME_type = $ARGV[1] || '?';
  $URL = $ARGV[2] || '?';

# comment usful for debuggin 
# warn "processing: $MIME_type - $URL\n";
  $Name = $URL;
  $Name =~ s#^.*/##;
  $Name =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/gie;
  
  if ($Verbose and not $LOG) { print STDERR "\n$Prog: [$MIME_type] " }
  if ($LOG) { print STDERR "$URL [$MIME_type] " }

}

#------------------------------------------------------------------------------

sub store_methods {
#	The method of dealing with each file type is set up here.
#	Edit as necessary

  my ($mime_type,$magic,$cmd,$cmdl,$type,$description);

  my $name = quotemeta($Name);

  ####Document -> HTML converters####

  # WordPerfect documents
  if ($WP2HTML) {
    $mime_type = "application/wordperfect5.1|application/msword";
    $cmd = $WP2HTML;
    $cmdl = "($cmd -q -DTitle=\"[$name]\" -c doc2html.cfg -s doc2html.sty -i $Input -O; $RM CmdLine.ovr)";
    $magic = '\377WPC';
    &store_html_method('WordPerfect (wp2html)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Word documents
  if ($WP2HTML) {
    $mime_type = "application/msword";
    $cmd = $WP2HTML;
    $cmdl = "($cmd -q -DTitle=\"[$name]\" -c doc2html.cfg -s doc2html.sty -i $Input -O; $RM CmdLine.ovr)";
    $magic = '^\320\317\021\340';
    &store_html_method('Word (wp2html)',$cmd,$cmdl,$mime_type,$magic);
  }

  # RTF documents
  if ($RTF2HTML) {
    $mime_type = "application/msword|application/rtf|text/rtf";
    $cmd = $RTF2HTML;
    # Rtf2html uses filename as title, change this:
    $cmdl = "$cmd $Input | $ED \"s#^<TITLE>$Input</TITLE>#<TITLE>[$name]</TITLE>#\"";
    $magic = '^{\134rtf';
    &store_html_method('RTF (rtf2html)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Microsoft Excel spreadsheet
  if ($XLS2HTML) {
    $mime_type = "application/msexcel|application/vnd.ms-excel";
    $cmd = $XLS2HTML;
    # xlHtml uses filename as title, change this:
    $cmdl = "$cmd -fw $Input | $ED \"s#<TITLE>$Input</TITLE>#<TITLE>[$name]</TITLE>#\"";
    $magic = '^\320\317\021\340';
    &store_html_method('Excel (xlHtml)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Microsoft Powerpoint Presentation
  if ($PPT2HTML) {
    $mime_type = "application/vnd.ms-powerpoint";
    $cmd = $PPT2HTML;
    # xlHtml uses filename as title, change this:
    $cmdl = "$cmd $Input | $ED \"s#<TITLE>$Input</TITLE>#<TITLE>[$name]</TITLE>#\"";
    $magic = '^\320\317\021\340';
    &store_html_method('Powerpoint (pptHtml)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Adobe PDF file using Perl script
  if ($PDF2HTML) {
    $mime_type = "application/pdf";
    $cmd = $PDF2HTML;
    # Replace default title (if used) with filename:
    $cmdl = "$cmd $Input $mime_type $name";
    $magic = '%PDF-|\0PDF CARO\001\000\377';
    &store_html_method('PDF (pdf2html)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Shockwave Flash file using Perl script
  if ($SWF2HTML) {
    $mime_type = "application/x-shockwave-flash";
    $cmd = $SWF2HTML;
    $cmdl = "$cmd $Input";
    $magic = '^FWS[\003-\005]';
    &store_html_method('Shockwave-Flash (swf2html)',$cmd,$cmdl,$mime_type,$magic);
  }

  ####Document -> Text converters####

  # Word6, Word7 & Word97 documents
  if ($CATDOC) {
    $mime_type = "application/msword";
    $cmd = $CATDOC;
    # -b option increases chance of success:
    $cmdl = "$cmd $Input $mime_type";
    $magic = '^\320\317\021\340';
    &store_html_method('Word (catdoc)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Word2 documents
  if ($CATDOC2) {
    $mime_type = "application/msword";
    $cmd = $CATDOC2;
    $cmdl = "$cmd -a -b -w $Input";
    $magic = '^\333\245-\000';
    &store_html_method('Word2 (catdoc)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Word 5.1 for MAC documents
  if ($CATDOCM) {
    $mime_type = "application/msword";
    $cmd = $CATDOCM;
    $cmdl = "$cmd -a -b -w $Input";
    $magic = '^\3767\000#\000\000\000\000';
    &store_html_method('MACWord (catdoc)',$cmd,$cmdl,$mime_type,$magic);
  }

  # PostScript files
  if ($CATPS) {
    $mime_type = "application/postscript";
    $cmd = $CATPS;
    # allow PS interpreter to give error messages
    $cmdl = "($cmd; $RM _temp_.???) < $Input";
    $magic = '^.{0,20}?%!|^\033%-12345.*\n%!';
    &store_text_method('PostScript (ps2ascii)',$cmd,$cmdl,$mime_type,$magic);
  }

  # Microsoft Excel file
  if ($CATXLS) {
    $mime_type = "application/vnd.ms-excel";
    $cmd = $CATXLS;
    $cmdl = "$cmd $Input";
    $magic = '^\320\317\021\340';
    &store_text_method('MS Excel (xls2csv)',$cmd,$cmdl,$mime_type,$magic);
  }

  # WordPerfect documents
  if ($CATWPD) {
    $mime_type = "application/wordperfect5.1|application/msword";
    $cmd = $CATWPD;
    $cmdl = "$cmd $Input";
    $magic = '\377WPC';
    &store_text_method('WordPerfect (catwpd)',$cmd,$cmdl,$mime_type,$magic);
  }

  ####Documents that cannot be converted####

  # wrapped encapsulated Postscript
  $type = "EPS";
  $magic = '^\305\320\323\306 \0';
  $description = 'wrapped Encapsulated Postscript';
  &store_cannot_do($type,$magic,$description);

  ## Binary (data or whatever)
  #$type = "BIN";
  #$magic = '[\000-\007\016-\037\177]'; # rather crude test!
  #$description = 'apparently binary';
  #&store_cannot_do($type,$magic,$description);

  return;
}

#------------------------------------------------------------------------------

sub read_magic {

  # Read first bytes of file to check for file type
  open(FILE, "< $Input") || die "Can't open file $Input\n";
  read FILE,$Magic,256;
  close FILE;

  return;
}

#------------------------------------------------------------------------------

sub error_setup {

  if ($Efile) {
   open SAVERR, ">&STDERR";
   if (open STDERR, "> $Efile") {
     print SAVERR " Overwriting $Efile\n" if (-s $Efile);
     $Redir = 1;
   } else { close SAVERR }
  }

}

#------------------------------------------------------------------------------

sub run {

  my $routine = shift;
  my $return;

  if (defined &alarm_call) {
    $return = alarm_call($Time, $routine);
  } else {
    eval $routine;
    $return = $@ if $@;
  }

  if ($return) { &quit($return) }

}

#------------------------------------------------------------------------------

sub try_html  {

  my($set,$cmnd,$type);

  $Success = 0;
  foreach $type (keys %HTML_Method) {
    $set = $HTML_Method{$type};
  if ($MIME_type =~ m/$set->{'mime'}/i) {
#warn "first part of if passed\n";
} 
  if ($Magic =~ m/$set->{'magic'}/s) {
#print "second part of if passed\n";
} 
#print "MIME_type = $MIME_type \n";
#print "set->{'mime'} = ".$set->{'mime'}." \n";
#print "Magic = ".$Magic." \n";
#print "set->{magic} = ".$set->{'magic'}." \n";
    if (($MIME_type =~ m/$set->{'mime'}/i) and  
        ($Magic =~ m/$set->{'magic'}/s))     { # found the method to use
#print "if passed\n";
      $Method = $type;
      my $cmnd = $set->{'cmnd'};
# warn "Processing $cmnd \n";
      if (! -x $cmnd) {
	warn "Unable to execute $cmnd for $type document\n";
	return;
      }
      if (not open(CAT, "$set->{'command'} |")) {
	warn "$cmnd doesn't want to be opened using pipe\n";
	return;
      }
      while (<CAT>) {
	# getting something, so it is working
	$Success = 1;
        if ($_ !~ m/^<!--/) { # skip comment lines inserted by converter
	  print;
	  $Count += length;
        }
      }
      close CAT;
      last;
    } 
  }
  return;
}

#------------------------------------------------------------------------------

sub try_text  {

  my($set,$cmnd,$type);

  $Success = 0;
  foreach $type (keys %TEXT_Method) {
    $set = $TEXT_Method{$type};
    if (($MIME_type =~ m/$set->{'mime'}/i) and
        ($Magic =~ m/$set->{'magic'}/s))     { # found the method to use
      $Method = $type;
      my $cmnd = $set->{'cmnd'};
      if (! -x $cmnd) { die "Unable to execute $cmnd for $type document\n" }

      # Open file via selected converter, output head, then its text:
      open(CAT, "$set->{'command'} |") or
	  die "$cmnd doesn't want to be opened using pipe\n";
      &head;
      print "<BODY>\n<PRE>\n";
      $Success = 1;
      while (<CAT>) {
	s/\255/-/g;	# replace dashes with hyphens
	# replace bell, backspace, tab. etc. with single space:
	s/[\000-\040]+/ /g;
	if (length > 1) { # if not just a single character, eg space
	  print &HTML($_), "\n";
	  $Count += length;
	}
      }
      close CAT;

      print "</PRE>\n</BODY>\n</HTML>\n";
      last;
    }

  }

  return;
}

#------------------------------------------------------------------------------

sub cannot_do  {

  my ($type,$set);

  # see if known, unconvertable type
  $Method = '';
  foreach $type (keys %BAD_type) {
    $set = $BAD_type{$type};
    if ($Magic =~ m/$set->{'magic'}/s) { # known problem
      return  "CANNOT DO $set->{'desc'} ";
    }
  }

  return 0;
}

#------------------------------------------------------------------------------

sub try_plain  {

  $Success = 0;
  ####### if ($Magic !~ m/^[\000-\007\016-\037\177]) {
  if (-T $Input) { # Looks like text, so go for it:
      $Method = 'Plain Text';
      open(FILE, "<$Input") || die "Error reading $Input\n";
      $Success = 1;
      $Method = 'Plain Text';
      &head;
      print "<BODY>\n<PRE>\n";

      while (<FILE>) {
	# replace bell, backspace, tab. etc. with single space:
	s/[\000-\040\177]+/ /g;
        if (length > 2) {
	  print &HTML($_), "\n";
	  $Count += length;
	}
      }
      close FILE;
      print "</PRE>\n</BODY>\n</HTML>\n";

  } else { $Method = '' }

  return;
}

#------------------------------------------------------------------------------

sub HTML {

  my $text = shift;

  $text =~ s/\f/\n/gs;	# replace form feed
  $text =~ s/\s+/ /g;	# replace multiple spaces, etc. with a single space
  $text =~ s/\s+$//gm;	# remove trailing spaces
  $text =~ s/&/&amp;/g;
  $text =~ s/</&lt;/g;
  $text =~ s/>/&gt;/g;

  return $text;
}

#------------------------------------------------------------------------------

sub store_html_method {

  my $type = shift;
  my $cmnd = shift;
  my $cline = shift;
  my $mime = shift;
  my $magic = shift;

  $HTML_Method{$type} = {
    'mime'	=> $mime,
    'magic'	=> $magic,
    'cmnd'	=> $cmnd,
    'command'	=> $cline,
    };

  return;
}

#------------------------------------------------------------------------------

sub store_text_method {

  my $type = shift;
  my $cmnd = shift;
  my $cline = shift;
  my $mime = shift;
  my $magic = shift;
  $TEXT_Method{$type} = {
    'mime'	=> $mime,
    'magic'	=> $magic,
    'cmnd'	=> $cmnd,
    'command'	=> $cline,
    };

  return;
}

#------------------------------------------------------------------------------

sub store_cannot_do {

  my $type = shift;
  my $magic = shift;
  my $desc = shift;

  $BAD_type{$type} = { 
    'magic' => $magic,
    'desc' => $desc,
    };

  return;

}

#------------------------------------------------------------------------------

sub head {

      print "<HTML>\n<HEAD>\n";
      print "<TITLE>[" . $Name . "]</TITLE>\n";
      print "</HEAD>\n";

}

#------------------------------------------------------------------------------

sub quit {

  if ($Redir) {	# end redirection of STDERR to temporary file
   close STDERR;
   open STDERR, ">&SAVERR";
  }    

  if ($Verbose) {
    print STDERR "$Method $Count" if ($Success);
    print STDERR "\n";
  } 
 
  my $return = shift;  
  if ($return) {
    print STDERR $Emark, $return, "\n";
    $return = 1;
  }

  chdir $TMP;
  if ($Efile && -s $Efile) {
    open EFILE, "<$Efile";
    my $c = 0;
    while (<EFILE>) {
      $c++;
      if ($c <= $Maxerr) {
        print STDERR $EEmark, $_;
      }
    }
    close EFILE;
    print STDERR $Emark, " ... (total of $c lines of error messages)\n" if ($c > $Maxerr);
  }
  unlink $Efile if ($Efile && -e $Efile);

  if (-e "core" && (-M "core" < 0)) {
    print STDERR $Emark, "$CORE_MESS\n";
  }
  exit $return;
}
word2html.pl (application/octet-stream, 1.5 KB)
#!/usr/bin/perl -w
use strict;
#
# Version 1.0	25-May-2001
# Written by David Adams <[email protected]>
#
# Uses pdftotext & pdfinfo utilities from the xpdf package
# to read an Adobe Acrobat file and produce HTML output.
#  
# Can be called directly from htdig as an external converter,
#  or may be called by doc2html.pl converter script. 
#

####--- Configuration ---####
# Full paths of pdtotext and pdfinfo
# (get them from the xpdf package at http://www.foolabs.com/xpdf/):

#### YOU MUST SET THESE  ####

my $wv = "/usr/bin/wvHtml";
#
#

#open (TEST, ">/tmp/test.txt");
#print TEST "test";
#close TEST;

my $tmpfile = "wvtext.html";
my $tmpdir = "/tmp";
if (! -x $wv) { die "Unable to execute wv" }

my $Input = $ARGV[0] || die "Usage: word2html.pl filename [mime-type] [URL]";
my $MIME_type = $ARGV[1] || '';
if ($MIME_type and ($MIME_type !~ m#^application/msword#i)) {
  die "MIME/type $MIME_type wrong";
}

my $Name = $ARGV[2] || '';
$Name =~ s#^.*/##;
$Name =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/gie;

&wv2html;
&output_html;
exit;

sub wv2html {
`$wv --targetdir=$tmpdir $Input $tmpfile >2 /dev/null`;
return;
}

sub output_html {
open (HTML, '<' . $tmpdir. '/'. $tmpfile) or die "could not open file";
print <HTML>;
close HTML;
return;
}



sub clean_pdf {
# removes odd pair of characters that may be in pdfinfo output
# Any double quotes are replaced with single

  my $text = shift;
  chomp $text;
  $text =~  s/\376\377//g;
  $text =~  s/\"/\'/g;
  return $text;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.