#! perl -w # Plugin for TWiki Collaboration Platform, http://TWiki.org/ # # Copyright (C) 2003 Martin@Cleaver.org # Copyright (C) 2000-2003 Andrea Sterbini, a.sterbini@flashnet.it # Copyright (C) 2001-2003 Peter Thoeny, peter@thoeny.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details, published at # http://www.gnu.org/copyleft/gpl.html # # ========================= # NB. requires Cairo or later to provide # beforeAttachmentSaveHandler ( $attachRefHash, $topic, $web ) 1.010? # Requires wvHtml, part of wvware # Has hardcoded paths use strict; # ========================= package TWiki::Plugins::MsOfficeAttachmentsAsHTMLPlugin; # ========================= use vars qw( $web $topic $user $installWeb $VERSION $pluginName $debug $xslDoc $replacementNote %converters $subdir $attachdir ); $VERSION = '1.010'; $pluginName = 'MsOfficeAttachmentsAsHTMLPlugin'; # Name of this Plugin my %converters = ( 'doc' => { 'HTML' => \&convertDocToHTML, }, 'xls' => { 'TML' => \&convertXlsToTML, 'HTML' => \¬Supported }, ); # ========================= sub initPlugin { ( $topic, $web, $user, $installWeb ) = @_; # check for Plugins.pm versions if( $TWiki::Plugins::VERSION < 1.010 ) { TWiki::Func::writeWarning( "Version mismatch between $pluginName and Plugins.pm" ); return 0; } # Get plugin debug flag $debug = TWiki::Func::getPreferencesFlag( "\U$pluginName\E_DEBUG" ); $replacementNote = TWiki::Prefs::getPreferencesValue("\U$pluginName\E_REPLACEMENTNOTE" ) || 'This text was automatically generated from the attachment $attachment' ."\n".'%INCLUDE{%ATTACHURL%/$convertedAttachmentPath}%'."\n"; $subdir = "_".$pluginName; # Plugin correctly initialized TWiki::Func::writeDebug( "- TWiki::Plugins::${pluginName}::initPlugin( $web.$topic ) is OK" ) if $debug; return 1; } # ========================= sub beforeAttachmentSaveHandler { ### my ( $attachmentAttr, $topic, $web ) = @_; # do not uncomment, use $_[0], $_[1]... instead my $attachmentAttr = $_[0]; my $topic = $_[1]; my $web = $_[2]; writeDebug( "- ${pluginName}::beforeSaveHandler( $_[2].$_[1])"); writeDebug("attributes: $attachmentAttr"); foreach my $attribute (keys %$attachmentAttr) { writeDebug("$attribute = ". $attachmentAttr->{$attribute}); } my $attachmentName = $attachmentAttr->{"attachment"}; writeDebug("Hmm. Got a $attachmentName"); $attachmentName =~ m!\.(.+)!; my $ext = $1; my $targetFormat = "TML"; writeDebug("Got a file $attachmentName of extension type '$ext'; looking for a '$targetFormat' converter"); use Data::Dumper; writeDebug (Dumper(\%converters)); my $converter = $converters{$ext}{$targetFormat}; writeDebug("converter=$converter"); unless ($converter) { writeDebug("Not converting - we have only converters for ". Dumper(\%converters)); return; } my $outputDir = TWiki::Func::getPubDir()."/$web/$topic/".$subdir; unless (-d $outputDir) { mkdir ($outputDir) || writeDebug("Couldn't make $outputDir"); } # Can't call this an .XLS.TML file - as such double extension names would be an illegal INCLUDE in Cairo my $outputFile = $attachmentName."2$targetFormat"; writeDebug("Converting $attachmentName to $outputFile in $outputDir"); eval { my $errors = &$converter($attachmentAttr->{"tmpFilename"}, $attachmentName, $outputDir, $outputFile); TWiki::Func::writeWarning("$web.$topic ".$attachmentAttr->{"user"}." ".$errors); }; TWiki::Func::writeWarning("$! $@") if ($@); writeDebug("Inserting include to render file $attachmentName to be that stored at $outputFile"); my $convertedAttachmentPath = $subdir."/".$outputFile; replaceTextWithIncludeFromAttachment($attachmentName, $convertedAttachmentPath); # Now, how do I give the user an error? # This handler is called by TWiki::Store::saveAttachment just before the save action. # New hook in TWiki::Plugins $VERSION = '1.010?' } sub writeDebug { my ($s) = @_; TWiki::Func::writeDebug($s); # if $debug; } sub convertXlsToTML { my ($postedFile, $attachmentName, $outputDir, $outputFile) = @_; my $errors = ""; use Spreadsheet::ParseExcel; #NB. This in turn requires OLE::Storage_Lite use Spreadsheet::ParseExcel::Simple; my $xls = Spreadsheet::ParseExcel::Simple->read("$postedFile"); my $targetFile = $outputDir.'/'.$outputFile; my $sheetcount = 0; writeDebug ("Outputting $targetFile"); open ( OUT, ">$targetFile") || return "cannot create file $targetFile"; # SMELL = no exception handling or error checking. print OUT "---+ Sheet $attachmentName\n"; foreach my $sheet ($xls->sheets) { $sheetcount++; print OUT "\n---++ Sheet $sheetcount\n\n"; while ($sheet->has_data) { my @cells = $sheet->next_row; foreach (@cells) { $_ =~ s!\n!
!g; # Strip any NLs that would break TML tables } print OUT '| '.join(' | ', @cells) . " |\n"; } close OUT; print OUT "\n"; } writeDebug("after writing $targetFile"); return $errors; } sub convertDocToHTML { # to HTML my ($postedFile, $attachmentName, $outputDir, $outputFile) = @_; my $errors = ""; my $convertedAttachmentFile = $attachmentName.".html"; my $cmd = "/usr/bin/wvHtml --targetdir=$outputDir $postedFile $outputFile"; writeDebug($cmd); my $x = `$cmd 2>&1`; writeDebug($x); # $errors .= $x; # return $x if ($x); writeDebug("after"); } sub replaceTextWithIncludeFromAttachment { my ($attachmentName, $convertedAttachmentPath) = @_; my $oopsUrl = TWiki::Func::setTopicEditLock( $web, $topic, 1 ); if( $oopsUrl ) { my $err = "can't get lock on $web.$topic text\n"; writeDebug($err); return; } my $text = $replacementNote; $text =~ s/\$attachment/$attachmentName/; $text =~ s/\$convertedAttachmentPath/$convertedAttachmentPath/; $oopsUrl = TWiki::Func::saveTopicText( $web, $topic, $text ); # save topic text TWiki::Func::setTopicEditLock( $web, $topic, 0 ); # unlock topic if( $oopsUrl ) { my $err = "can't unlock on $web.$topic text\n"; writeDebug("$err - $oopsUrl"); } writeDebug("Ok. writing $web.$topic\n"); return; } # This does not work, but is left here for the curious user sub convertToWikiTML { my ($filename, $xslDoc) = @_; my $errors = ""; my $cmd = "/usr/bin/wvWare -x /usr/share/wv/wvXml.xml $filename > /tmp/xml"; #Unsafe writeDebug($cmd); my $x = `$cmd 2>`; writeDebug($x); $errors .= $x; return $x if ($x); my $cmd2 = "/usr/bin/xsltproc $xslDoc /tmp/xml > /tmp/xmlAsWiki.txt"; writeDebug($cmd2); $x = `$cmd2 2>`; writeDebug($x); return $x if ($x); return $errors; } sub notSupported { return "Not supported"; } # ========================= 1;