#!/bin/perl 
# -----------------------------------------------------------------
# Autor          : F. Labbe
# privat         : fred@frederic-labbe.com
# professionnal  : frederic.labbe@ch-avranches-granville.fr
#                : http://ooo2tools.free.fr/
# object         : Explore OpenOffice.org File
# Test           : ok with active perl 5.6.1.633
# Licence        : GPL
# usage (source) : perl fooox.pl
# usage (binary) :      fooox.exe
#
# Update         : 01/06/2003
# -----------------------------------------------------------------

my $fooox_version = "0.0.1 beta 8";

# -----------------------------------------------------------------
# remarque  : j'ai besoin d'un specialiste de perl/tk pour controler
#            le code.
#           : i need a perl-tk specialist to check the source code.
#
# -----------------------------------------------------------------
# todo      :
# - affichage du fichier en cours de traitement
# - Ouverture du document en cliquant sur la ligne
# - filtre sur les dates => Date Mini - Date Maxi
# - Conservation la langue utilisee lors de la re-ouverture
# -----------------------------------------------------------------
# Update    :
# 0.0.1 b 8   - Italian translation
# 0.0.1 b 7   - correction bug lors de l'affichage des repertoires
# 0.0.1 b 7   - Variable $position_x pour positionner le texte
# 0.0.1 b 7   - Dutch (NL) translation
# 0.0.1 b 7   - Slovenish (SL) translation
# 0.0.1 b 6   - Affichage du contenu en cliquant sur le document
# 0.0.1 b 6   - Suppression du content.xml apres traitement
# 0.0.1 b 5   - Recherche multi-critere sur le ET 
# 0.0.1 b 5   - Changement brique parcours arborescence :Find::File:Rule 
# 0.0.1 b 5   - filtrage sur le nom du fichier
# 0.0.1 b 5   - Affichage d'un message debut/fin de recherche
# 0.0.1 b 4   - ajout espagnol
# 0.0.1 b 4   - case insentive
# 0.0.1 b 4   - correction bug fermeture recherche repertoire
# 0.0.1 b 3   - multilangue
# 0.0.1 b 2   - recherche multi-critere sur le OU 
# -----------------------------------------------------------------

use Tk;
use Tk::DirTree;
use Tk::Photo;
use Tk::Radiobutton;
use Tk::Scrollbar;
# parcours d'arborescence.
use File::Find::Rule;
use Cwd;

# ZIP Manipulation
use Archive::Zip qw(:ERROR_CODES);
# File Manipulation
use File::Temp qw/ tempfile/;


my %info;  # stockage des informations recueillies

my $OOO_XML_CONTENT= 'content.xml';

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;"     => '<'

   );


$text_fichier="*";
# -----------------------------------------------------------------
# Creation de la fenetre
# -----------------------------------------------------------------
$fenetre = MainWindow->new(-height=>430,-width=>600);
#$fenetre->configure(-background => 'white');

$fooox_fr="Francais";
$fooox_de="Deutsch";
$fooox_gb="English";
$fooox_sp="Espagnol";
$fooox_nl="Nederlands";
$fooox_sl="Slovensko";
$fooox_it="Italiano";


# Position du texte
$position_x1="5";
# Position des zones de saisie
$position_x2="120";
# Position 1ere colonne langue
$position_x3="380";
# Position 2eme colonne langue
$position_x4="470";
$position_x5="520";

$fooox_lang="fr";
ihm();





MainLoop;

sub ihm
{

if ($fooox_lang eq "fr")
{	

# -----------------------------------------------------------------
# Message Francais
# -----------------------------------------------------------------
$fooox_ou="OU";
$fooox_et="ET";
$fooox_fin="FIN";
$fooox_chercher="Chercher";
$fooox_recherche="Recherche...";
$fooox_file="Fichier :";
$fooox_rep="Repertoire :";
$fooox_browse="Repertoire";
$fooox_chaine="Chaine :";
$fooox_title="Recherche de documents OpenOffice.org";
}

# -----------------------------------------------------------------
# -----------------------------------------------------------------
# Message anglais
# -----------------------------------------------------------------
if ($fooox_lang eq "gb")
{	
$fooox_ou="OR";
$fooox_et="AND";
$fooox_fin="END";
$fooox_recherche="Searching...";
$fooox_chercher="Find";
$fooox_file="File :";
$fooox_rep="Directory :";
$fooox_browse="Browse";
$fooox_chaine="String :";
$fooox_title="Find OpenOffice.org File";
}
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# Message allemand
# -----------------------------------------------------------------
if ($fooox_lang eq "de" )
{	
	$fooox_ou="ODER";
	$fooox_recherche="Suchen...";
	$fooox_et="UND";
	$fooox_fin="ENDE";
	$fooox_chercher="Finden";
	$fooox_file="Datei :";
	$fooox_rep="Pfad :";
	$fooox_browse="Browse";
	$fooox_chaine="String :";
	$fooox_title="OpenOffice.org Datei Finden";
}	
# -----------------------------------------------------------------	
# -----------------------------------------------------------------
# Message espagnol
# -----------------------------------------------------------------
if ($fooox_lang eq "sp" )
{	
	$fooox_ou="O";
	$fooox_et="Y";
	$fooox_fin="FIN";
	$fooox_recherche="Searching...";
	$fooox_chercher="Buscar";
	$fooox_file="Fichero :";
	$fooox_rep="Repertorio :";
	$fooox_browse="Repertorio";
	$fooox_chaine="Cadena :";
	$fooox_title="Búsqueda de documentos OpenOffice.org";
}
# -----------------------------------------------------------------
# Message NL
# -----------------------------------------------------------------
if ($fooox_lang eq "nl" )
{	
	$fooox_ou="OF";
	$fooox_et="EN";
	$fooox_fin="EINDE";
	$fooox_recherche="Zoeken...";
	$fooox_recherche="Bezig met Zoeken...";
	$fooox_chercher="Zoeken";
	$fooox_file="Bestand :";
	$fooox_rep="Map :";
	$fooox_browse="Bladeren";
	$fooox_chaine="String :";
	$fooox_chaine="Woord of Uitdrukking :";
	$fooox_title="Vind OpenOffice.org Bestand"; 
}
# -----------------------------------------------------------------
# Message SL
# -----------------------------------------------------------------
if ($fooox_lang eq "sl" )
{	
	$fooox_ou="ALI";
	$fooox_et="IN";
	$fooox_fin="KONEC";
	$fooox_recherche="Datoteka...";
	$fooox_chercher="Najdi";
	$fooox_file="Datoteka :";
	$fooox_rep="Mapa :";
	$fooox_browse="Poisci";
	$fooox_chaine="Niz :";
	$fooox_title="Poisci OpenOffice.org datoteko";
}
# -----------------------------------------------------------------
# Message ITALIAN
# -----------------------------------------------------------------
if ($fooox_lang eq "it" )
{	
	$fooox_ou="O";
	$fooox_et="E";
	$fooox_fin="FINE";
	$fooox_recherche="Sto cercando...";
	$fooox_chercher="Cerca";
	$fooox_file="File :";
	$fooox_rep="Cartella :";
	$fooox_browse="Cartella";
	$fooox_chaine="Stringa :";
	$fooox_title="Cerca Documenti OpenOffice.org";
}
	
$fenetre->title($fooox_title);
# -----------------------------------------------------------------
# Affichage du Logo FOOoX 
# -----------------------------------------------------------------
# Declaration de l'image
# -----------------------------------------------------------------
  my $photo_fooox = $fenetre->Photo( -file   => './fooox.gif');
# -----------------------------------------------------------------
# Affichage de l'image
# -----------------------------------------------------------------
$fenetre->Label(-image => $photo_fooox)->place(-x => 370, -y => 1);
# -----------------------------------------------------------------
# Affichage de la version
# -----------------------------------------------------------------
$fenetre->Label(-text => "Version : $fooox_version")->place(-x=>10,-y=>10);
$fenetre->Label(-text => "http://oootools.free.fr/")->place(-x=>150,-y=>10);
$fenetre->Label(-text => $fooox_rep  ,          
                -width=>10,
                -anchor=>'w')->place(-x=>$position_x1,-y=>80);

$fenetre->Entry(-textvariable => \$curr_dir, 
                -width=>40)->place(-x=>$position_x2,-y=>80);

$fenetre->Button(-text => $fooox_browse, 
                 -command => \&repertoire,
                 -width=>10,
                 -anchor=>'c')->place(-x=>$position_x3,-y =>80);

%lib=(ou=>'ou', et=>'et');

# -----------------------------------------------------------------
# Radio bouton OU ET
# -----------------------------------------------------------------
$var = 'ou';    
$radio_bouton="|";
$fenetre->Radiobutton(-text =>$fooox_ou,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$radio_bouton,
            -width=>5,
            -anchor=>'c',
            -value => '|',
            )->place(-x=>$position_x2, -y => 160);

$fenetre->Radiobutton(-text =>$fooox_et,
            -relief => 'groove',
            -variable => \$radio_bouton,
            -value => '&&',
            -width=>5,
            -anchor=>'c',
            )->place(-x=>($position_x2+80), -y=> 160);
 
# -----------------------------------------------------------------
# Radio bouton LANGUE            
# -----------------------------------------------------------------
$fenetre->Radiobutton(-text =>$fooox_de,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,
            -value => 'de',
            -anchor=>'w',            
            )->place(-x=>$position_x3, -y => 120);
$fenetre->Radiobutton(-text =>$fooox_gb,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,    
            -anchor=>'w',                                
            -value => 'gb',
            )->place(-x=>$position_x3, -y => 150);
$fenetre->Radiobutton(-text =>$fooox_fr,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -anchor=>'w',                        
            -value => 'fr',
            )->place(-x=>$position_x3, -y => 180);
$fenetre->Radiobutton(-text =>$fooox_sp,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width=>8,           
            -anchor=>'w',                        
            -value => 'sp',
            )->place(-x=>$position_x4, -y => 120);
$fenetre->Radiobutton(-text =>$fooox_nl,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -anchor=>'w',                        
            -value => 'nl',
            )->place(-x=>$position_x4, -y => 150); 	
$fenetre->Radiobutton(-text =>$fooox_sl,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -anchor=>'w',                        
            -value => 'sl',
            )->place(-x=>$position_x4, -y => 180);  
$fenetre->Radiobutton(-text =>$fooox_it,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -anchor=>'w',                        
            -value => 'it',
            )->place(-x=>$position_x3, -y => 210);                          

# -----------------------------------------------------------------
# Bouton FIN
# -----------------------------------------------------------------
$fenetre->Button(-text => $fooox_fin, 
               -command => sub { exit; },
               -width=>5,
               -anchor=>'c')
               ->place(-x=>$position_x2, -y =>200);



# -----------------------------------------------------------------
# Bouton Chercher
# -----------------------------------------------------------------               
$fenetre->Button(-text => $fooox_chercher, 
               -command => \&fooox_cherche,
               -width=>8,
               -anchor=>'c')->place(-x=>($position_x2+80), -y => 200);
                                              
                                             
$fenetre->Label(-text => $fooox_file,
		-width=>10,
                -anchor=>'w')->place(-x=>$position_x1,-y=>40);
$Fichier=$fenetre->Entry(-textvariable => \$text_fichier)->place(-x=>$position_x2,-y=>40 );        
                                 
                                                                                                           
$fenetre->Label(-text => $fooox_chaine,
                -width=>30,
                -anchor=>'w')->place(-x=>$position_x1,-y=>120);
$chaine=$fenetre->Entry( -textvariable => \$text_chaine,-width=>40)->place(-x=>$position_x2,-y=>120 );
                                
# -----------------------------------------------------------------
# fenetre affichage resultat
# -----------------------------------------------------------------
$zone2 = $fenetre->Frame->place(-x=>$position_x1,-y=>240);
# -----------------------------------------------------------------
# Scroll barre du resultat
# -----------------------------------------------------------------
$defil_v = $fenetre->Scrollbar();
# Tableau anonyme du widget liste
$liste = $fenetre->Listbox();



# Configure chaque liste pour appeler &defiler_listes
$liste->configure(-yscrollcommand => [ \&defiler_listes, $defil_v,$liste, "liste" ]);
	  $liste->bind('<Button-1>',
		sub{
# -----------------------------------------------------------------
# Procedure lorsque l'on clique sur le chemin du fichier
# -----------------------------------------------------------------
			@selection = $liste->curselection();
			foreach (@selection)
			{
				#print("ligne selectionne : $_  $chemin[$_]\n");
				$chemin_complet=$chemin[$_];
				ooo2txt($chemin_complet);
				affiche_contenu();
			}
		    } # fin sub
		  );	
#	}
# Configure la barre pour faire défiler chaque liste
$defil_v->configure(-command => sub { #foreach $liste (@$listes) 
				#	{
                                       		$liste->yview(@_);
                                 #       }
                                     }
                   );

# -----------------------------------------------------------------
# Place la barre et les listes
# -----------------------------------------------------------------
$defil_v->place(-x =>$position_x1, -y => 240,-height=>170);
# -----------------------------------------------------------------
#
# -----------------------------------------------------------------
  $liste->place(-x =>($position_x1+20), -y => 240, -width => 520);

	
} 
# -----------------------------------------------------------------
# FIN ihm
# -----------------------------------------------------------------
sub fooox_cherche {
	
	#$fenetre->Label(-text => $fooox_recherche,
	#	-width=>10,
        #       -anchor=>'w')->place(-x=>($position_x2+140),-y=>200);
# -------------------------------------------------------------------
# Traverse desired filesystems
# -------------------------------------------------------------------
# on eclate $texte_chaine pour recuperer les mots recherches.
    $liste->delete(0,'end');
       # -------------------------------------------------------------------
       # Prepare regex pour le OU et le ET
       # -------------------------------------------------------------------
         @mot = split(/ /, $text_chaine); 
    
         $index=0;
         $monregex="";
         $monregex_et="";
         $contenu = "";
         
         while ($mot[$index] ne "") 
         {
           if ($index >0 )  
           { 
              $monregex = $monregex . $radio_bouton;
              $monregex_et = $monregex_et ." ". $radio_bouton . " \$contenu =~ /" . $mot[$index] ."/";
           #print (" * $monregex_et - \n");
           }
	   else
           {
              $monregex_et = "\$contenu =~ /".$mot[$index]."/";
           }
           $monregex = $monregex . $mot[$index] ;
           $index++;
         }
           #print (" REGEX : ET : $monregex_et - OU : $monregex \n");

	
 my $rule  = File::Find::Rule->new;
 my @files = File::Find::Rule->file()
                              ->name( $text_fichier )
                              ->in( $curr_dir );           
 
 @file = find( file => name => $text_fichier, start => $curr_dir);
 
 $index=0;
 $indice=0;
 @chemin="";
 foreach my $file (@files) 
 {
	wanted($file);
 }

  $recup=$Fichier->get();


$fenetre->Label(-text => $fooox_fin,
		-width=>10,
                -anchor=>'w')->place(-x=>($position_x2+150),-y=>210);
}


sub wanted 
{
    my ($fichier) = @_;
    $chemin_complet=$fichier;
    # -------------------------------------------------------------------  
    # on recupere le texte du document
    # -------------------------------------------------------------------  
    ooo2txt($chemin_complet);
        
    # ------------------------------------------------------------------- 
    # Regarde si le document contient $texte_chaine
    # normalement $contenu ne doit contenir que le texte du document
    # -------------------------------------------------------------------

    # -------------------------------------------------------------------  
    # on passe le texte en minuscule + regex
    # -------------------------------------------------------------------  	
    $contenu = lc($contenu);
	    
    $monregex = lc($monregex);
    # TEST DU OU 
    #print("radio : $radio_bouton - $monregex - $monregex_et - $contenu\n");
    if (
        ( $contenu =~ /$monregex/ && $radio_bouton == "|" ) ||
        (  eval($monregex_et) and $radio_bouton == "&&") 
       )
    { 
    # ------------------------------------------------------------------- 
    # Affiche fichier car contient $texte_chaine
    # -------------------------------------------------------------------  
      $liste->insert('end', "$chemin_complet");
      # ------------------------------------------------------------------- 
      # Stocke le chemin dans le tableau $chemin[]
      # -------------------------------------------------------------------  
      $chemin[$indice]=$chemin_complet;
      $indice++;
    } # Fin du regex
} # fin de la procedure wanted

# ------------------------------------------------------------------- 
# converti le fichier en ascii 
# -------------------------------------------------------------------  
sub ooo2txt
{
    $contenu="";
    my ($chemin_complet) = @_;
if ( $chemin_complet =~ /^.*\.sxw$|^.*\.SXW$|^.*\.sxc$|^.*\.SXC$|^.*\.sxi$|^.*\.SXI$|^.*\.sxd$|^.*\.SXD$/  ) 
    {
        
	# -------------------------------------------------------------------   
	# Recherche Occurence
	# -------------------------------------------------------------------    
	$contenu="";
	$ligne="";
        my $zip = Archive::Zip->new();
        my $zipName = $chemin_complet;
        # -----------------------------------------------------------------
        # Ouverture du ZIP donc du fichier OpenOffice.org
        # -----------------------------------------------------------------
        if (open(CONTROL, $zipName))
        {
           my $status = $zip->read( $zipName );
           die "Read of $zipName failed\n" if $status != AZ_OK;

           my $ooo_filename="content.xml";
        
           # -----------------------------------------------------------------
           # On dezippe le 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;

	   # -----------------------------------------------------------------
	   # On recupere le contenu de content.xml
	   # -----------------------------------------------------------------
           if (open(FICHIER, $ooo_filename))
           {
                my $ligne= <FICHIER>;
                while ($ligne ne "")
                {
	         $contenu .= $ligne;
                 $ligne = <FICHIER>;
                }  
           } 
           close (FICHIER);
           unlink $ooo_filename or die $!;
	     # -----------------------------------------------------------------
	     # on vire les balises XML via regex pour ne garder que le texte
	     # -----------------------------------------------------------------
	      
	     $contenu =~ s/<\?xml[^>]+>//g;
             $contenu =~ s/<!DOCTYPE[^>]+>//g;
             $contenu =~ s/<office:[^>]+>//g;
             $contenu =~ s/<\/office:[^>]+>//g;
             $contenu =~ s/<text:p[^>]+>/\n/g;
             # table
	     $contenu =~ s/<table:table-row>/|/g;
	     $contenu =~ s/<\/text:p><\/table:table-cell>/|/g;
	     $contenu =~ s/<\/table:table-row>/\n/g;
	     # saut de ligne
	     $contenu =~ s/<\/text:p>/\n/g;
	     $contenu =~ s/<\/text:h>/\n/g;
	     $contenu =~ s/<text:line-break\/>/\n/g;
		        
             #suppression des balises sans texte
	     $contenu =~ s/<text:[^>]+>//g;
		       
	     #suppression des fermetures de balises sans texte
	     $contenu =~ s/<\/text[^>]+>//g;
	     $contenu =~ s/<\/style:[^>]+>//g;
	     $contenu =~ s/<style:[^>]+>//g;
	     $contenu =~ s/<table:[^>]+>//g;
	     $contenu =~ s/<\/table:[^>]+>//g;
	     $contenu =~ s/<draw:[^>]+>//g;
	     $contenu =~ s/<\/draw:[^>]+>//g;
         
           } # Fin ouverture du fichier $ooo_filename
      } # fin if sur type de fichier
} # Fin procedure ooo2txt

sub affiche_contenu
{
# -----------------------------------------------------------------
# Fenetre affichage contenu du document
# -----------------------------------------------------------------
	my $accents = join '|', map {quotemeta} keys %desacc;
	$contenu    =~ s/($accents)/$desacc{$1}/g;
$fenetre_contenu = MainWindow->new(-height=>430,-width=>600);
$fenetre_contenu->title($chemin_complet);
$fenetre_contenu_ligne = $fenetre_contenu->Scrolled("Listbox", 
						-scrollbars =>"se",
						-width =>50, 
						-height =>20)->pack();
$fenetre_contenu->Button(-text => 'Ok',
	   -command => sub { $fenetre_contenu->withdraw() })->pack(-side => 'left');
        @contenu_ligne = split(/\n/, $contenu); 
	foreach $contenu_ligne (@contenu_ligne)
	{
	  if ($contenu_ligne ne "")
	  {
           $fenetre_contenu_ligne->insert('end',$contenu_ligne);
	  }
	}
}


sub repertoire 
{
  
  my $top = new MainWindow;
  $top->withdraw;

my $t = $top->Toplevel;
$t->title("$fooox_rep");

my $ok = 0; # flag: "1" means OK, "-1" means cancelled

# Create Frame widget before the DirTree widget, so it's always visible
# if the window gets resized.

my $f = $t->Frame->pack(-fill => "x", -side => "bottom");

#$curr_dir = Cwd::cwd();
$curr_dir="/";
my $d;
$d = $t->Scrolled('DirTree',
		  -scrollbars => 'osoe',
		  -width => 35,
		  -height => 20,
		  -selectmode => 'browse',
		  -exportselection => 1,
		  -browsecmd => sub { $curr_dir = shift },
	

		  # With this version of -command a double-click will
		  # select the directory
		  -command   => sub { $ok = 1 },

		  # With this version of -command a double-click will
		  # open a directory. Selection is only possible with
		  # the Ok button.
		  #-command   => sub { $d->opencmd($_[0]) },
		 )->pack(-fill => "both", -expand => 1);
		 
# Set the initial directory
$curr_dir="/";
#$d->chdir($curr_dir);
$f->Button(-text => 'Ok',
	   -command => sub { $t->withdraw() })->pack(-side => 'left');



}


# Cette méthode est appelée lorsqu'une liste est parcourue avec le clavier
# La barre reflètera les changements et fera défiler les autres listes.
sub defiler_listes {
  my ($barre, $parcouru, $lsts, @args) = @_;
  $barre->set(@args); # indique à la barre ce qu'il faut afficher
  my ($haut, $bas) = $parcouru->yview();
  foreach $liste (@$lsts) {
    $liste->yview(moveto => $haut); # ajuste chaque liste
  }
}

