#!/bin/perl 
# -----------------------------------------------------------------
# Autor          : F. Labbe
# privat         : fred@frederic-labbe.com
# professionnal  : frederic.labbe@ch-avranches-granville.fr
#                : http://ooo2txt.fr.st/
# object         : convert OpenOffice.org file into ascii
# Test           : ok with active perl 5.6.1.633
# usage (source) : perl ooo2txt [-j] [-f field_name] ooo_file 
# usage (binary) :      ooo2txt [-j] [-f field_name] ooo_file 
#
# version        : 28/08/2002

my $ooo2txt_version = "0.0.4";

#
#
# -----------------------------------------------------------------
# todo      :
# -f all : display all fields 
# -----------------------------------------------------------------
# Update    :
# - balise "table:number-columns-repeated" in sxc file
# -----------------------------------------------------------------
use strict;
use vars qw( $opt_j $opt_f );
use Archive::Zip qw(:ERROR_CODES);
use Getopt::Std;

$opt_j = 0;

getopts('jf:');

my %desacc = (          # pour "désaccentuer"
      "\xC3\xA8" => 'e',
      "\xC3\xA9" => 'e',
      "\xC3\xAA" => 'e',
      "\xC3\x89" => 'E',   
      "\xC3\xA0" => 'a',
      "\xC3\xA2" => 'a',
      "\xC3\x80" => 'A',
      "\xC3\xAE" => 'i',
      "\xC3\xAF" => 'i',
      "\xC3\xB4" => 'o',
      "\xC3\xB6" => 'o',
      "\xC3\xBB" => 'u',
      "\xC3\xBC" => 'u',
      "\xC3\xB9" => 'u',
      "\xC2\xA9" => '(c)',
      "\xE2\x84" => '(tm)',
      "\xC3\xA4" => 'ae',
      "\xCE\xB2" => 'ss',
      "\xE2\x80" => '-',
      "\xC3\xA7" => 'c',
      "\xE2\x82\xAC" => 'EUR',
      "&apos;"   => '\'',
      "&quot;"   => '"',
      "&gt;"     => '>',
      "&gt;"     => '<'

   );

# test si un parametre saisie
if (@ARGV < 1)
{
	die <<EOF
=>  ooo2txt $ooo2txt_version
=>  usage (source) : perl ooo2txt [-j] [-f field_name] ooo_file 
=>  usage (binary) :      ooo2txt [-j] [-f field_name] ooo_file 

=>  see http://ooo2txt.fr.st/
EOF
}
#        if -j option given, discards paths.


my $zip = Archive::Zip->new();
my $zipName = shift(@ARGV);
if (open(CONTROL, $zipName))
{
        my $status = $zip->read( $zipName );
        die "Read of $zipName failed\n" if $status != AZ_OK;

        my $ooo_filename="content.xml";
        
        $status = $opt_j 
                ? $zip->extractMemberWithoutPaths($ooo_filename)
                : $zip->extractMember($ooo_filename);
        die "Extracting $ooo_filename from $zipName failed\n" if $status != AZ_OK;

        if (open(FICHIER, $ooo_filename))
        {
                my $ligne= <FICHIER>;
                while ($ligne ne "")
                {
                #
                        $ligne =~ s/<\?xml[^>]+>//g;
                        $ligne =~ s/<!DOCTYPE[^>]+>//g;
                        $ligne =~ s/<office:[^>]+>//g;
                        $ligne =~ s/<\/office:[^>]+>//g;
        

		        # -f parameter => display only fields content
		        if (length($opt_f) > 0)
		        {
				# je supprime tout ce qui est avant la balise de champ et j'ecris le nom du champ :
				my $compteur="0";
		                $compteur = $ligne =~ s/^.*<text:text-input text:description="$opt_f">/$opt_f : /g ;
				if ($compteur > 0) 
				{
				    # print("substitution ok : $compteur ");	
		                    # tout ce qui est apres la valeur du champ est apres la balise donc j efface
				    $ligne =~ s/<\/text:text-input>.*$//g;
				}
				else
				{
				    $ligne = "";
				}
				                
		        }
		        else
		        {
		      
		                # numerotation automatique
		                $ligne =~ s/<text:tab-stop\/>/............./g;         
		        
		                # remplace <text:???????>
		                # cherche :
		                # <text:   et
		                # [^>]     n'importe quel caractere sauf > et
		                # >+       1 seul fois >   
		                # Il s'agit de la zone de texte donc je remplace
		                # par \n pour lisibilité 
		                #$ligne =~ s/<text:p[^>]+>/\n/g;

                                my $ligne_length=length($ligne);

                                #
                                #cellule repetees
                                #

                                my $repeat_pos=0;
				while ($repeat_pos<$ligne_length)
				{
		                	my $repeat_col_begin = index($ligne,"table:number-columns-repeated=",$repeat_pos);
					if ( $repeat_col_begin > 0)
					{
						# must repeat
					        my $repeat_col_end = index($ligne,"\"",$repeat_col_begin+31);	
					        my $col_end_balise = index($ligne,">",$repeat_col_end);
						my $longueur = $repeat_col_end - $repeat_col_begin-31;
						my $nb = substr($ligne,$repeat_col_begin+31,$longueur);
						# what must be repeated
						my $repeat_str="XX";
	   		                        my $repeat_str_pos_begin= index($ligne,"value=",$repeat_col_end);
						#if found, offset = +7 (value=")
						if ($repeat_str_pos_begin>0){$repeat_str_pos_begin=$repeat_str_pos_begin+7;}
						if ($repeat_str_pos_begin>0 and $repeat_str_pos_begin <= $col_end_balise)
						{
		   		                        my $repeat_str_pos_end = index($ligne,"\"",$repeat_str_pos_begin);
							my $repeat_length=$repeat_str_pos_end-$repeat_str_pos_begin;
							$repeat_str = substr($ligne,$repeat_str_pos_begin,$repeat_length );
							my $repeat_string=($repeat_str."|") x ($nb-1);

							#print("REPETER $repeat_str - $nb fois - $repeat_string\n");
							
							substr($ligne,$col_end_balise+1,0)=$repeat_string;
						}
#						print("XX $repeat_col_begin - $repeat_col_end - $longueur - $nb - $repeat_str_pos_begin -  $repeat_str_pos_end x  -  $col_end_balise * - $repeat_str \n");
					
						$repeat_pos=$col_end_balise;
					} # end if $repeat_col_begin 
					else
					{
						$repeat_pos=$ligne_length;
					}
				} # end while


                		# table
		                $ligne =~ s/<table:table-row>/|/g;
		                $ligne =~ s/<\/text:p><\/table:table-cell>/|/g;
		                $ligne =~ s/<\/table:table-row>/\n/g;
		
		                # saut de ligne
		                $ligne =~ s/<\/text:p>/\n/g;
		                $ligne =~ s/<\/text:h>/\n/g;
		                $ligne =~ s/<text:line-break\/>/\n/g;
		        
                		#suppression des balises sans texte
		                $ligne =~ s/<text:[^>]+>//g;
		        
		                #suppression des fermetures de balises sans texte
		                $ligne =~ s/<\/text[^>]+>//g;
		                $ligne =~ s/<\/style:[^>]+>//g;
		                $ligne =~ s/<style:[^>]+>//g;
		                $ligne =~ s/<table:[^>]+>//g;
		                $ligne =~ s/<\/table:[^>]+>//g;
		                $ligne =~ s/<draw:[^>]+>//g;
		                $ligne =~ s/<\/draw:[^>]+>//g;
	        
        		        my $accents = join '|', map {quotemeta} keys %desacc;
		                $ligne =~ s/($accents)/$desacc{$1}/g;
		        
        
		                $ligne =~ s/\342\200\231\302/\040/g;
		                # traitement de calc
		                $ligne =~ s/<number:[^>]+>/\n/g;
		                $ligne =~ s/<\/number[^>]+>//g;
		        }
		        printf ("%s",$ligne);
		        $ligne = <FICHIER>;
        
	     }
    }

    close (FICHIER);
    unlink $ooo_filename or die $!;

}
else
{
print ("
File $zipName not found.

=>  ooo2txt v$ooo2txt_version
=>  usage (source) : perl ooo2txt [-j] [-f field_name] ooo_file 
=>  usage (binary) :      ooo2txt [-j] [-f field_name] ooo_file 

=>  see http://ooo2txt.fr.st/
");

}
