#!/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
#
# version        : 10/05/2003
# -----------------------------------------------------------------

my $fooox_version = "0.0.1 beta 4";

# -----------------------------------------------------------------
# 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      :
# - recherche multi-critere sur le ET
# - affichage du fichier en cours de traitement
# - Ouverture du document en cliquant sur la ligne
# -----------------------------------------------------------------
# Update    :
# 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;
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="*";
$fenetre = MainWindow->new(-height=>420,-width=>600);

$fooox_fr="Francais";
$fooox_de="Deutsch";
$fooox_gb="English";
$fooox_sp="Espagnol";



$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_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_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_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_chercher="Buscar";
	$fooox_file="Fichero :";
	$fooox_rep="Repertorio :";
	$fooox_browse="Repertorio";
	$fooox_chaine="Cadena :";
	$fooox_title="Búsqueda de documentos 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 => 350, -y => 1);
# -----------------------------------------------------------------
# Affichage de la version
# -----------------------------------------------------------------
$fenetre->Label(-text => "Version : $fooox_version")->place(-x=>10,-y=>10);
$fenetre->Label(-text => $fooox_rep  ,          
                -width=>10,
                -anchor=>'w')->place(-x=>10,-y=>80);

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

$fenetre->Button(-text => $fooox_browse, 
                 -command => \&repertoire,
                 -width=>10,
                 -anchor=>'c')->place(-x=>350,-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 => 80, -y => 160);

$fenetre->Radiobutton(-text =>$fooox_et,
            -relief => 'groove',
            -variable => \$radio_bouton,
            -value => '&',
            -width=>5,
            -anchor=>'c',
            )->place(-x => 140, -y=> 160);
 
# -----------------------------------------------------------------
# Radio bouton LANGUE            
# -----------------------------------------------------------------
$fenetre->Radiobutton(-text =>$fooox_de,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,
            -value => 'de',
            )->place(-x => 350, -y => 120);
$fenetre->Radiobutton(-text =>$fooox_gb,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -value => 'gb',
            )->place(-x => 350, -y => 150);
$fenetre->Radiobutton(-text =>$fooox_fr,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width =>8,            
            -value => 'fr',
            )->place(-x => 350, -y => 180);
$fenetre->Radiobutton(-text =>$fooox_sp,
            -relief => 'groove',
            -state  => 'active',
            -variable => \$fooox_lang,
            -command => \&ihm,
            -width=>8,           
            -value => 'sp',
            )->place(-x => 440, -y => 120);
 	

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



# -----------------------------------------------------------------
# Bouton Chercher
# -----------------------------------------------------------------               
$fenetre->Button(-text => $fooox_chercher, 
               -command => \&fooox_cherche,
               -width=>8,
               -anchor=>'c')->place(-x => 160, -y => 200);
                                              
                                             
$fenetre->Label(-text => $fooox_file,
		-width=>10,
                -anchor=>'w')->place(-x=>10,-y=>40);
$Fichier=$fenetre->Entry(-textvariable => \$text_fichier)->place(-x=>80,-y=>40 );        
                                 
                                                                                                           
$fenetre->Label(-text => $fooox_chaine,
                -width=>10,
                -anchor=>'w')->place(-x=>10,-y=>120);
$chaine=$fenetre->Entry( -textvariable => \$text_chaine,-width=>40)->place(-x=>80,-y=>120 );
                                
# -----------------------------------------------------------------                                
# fenetre affichage resultat
# -----------------------------------------------------------------
$zone2 = $fenetre->Frame->place(-x=>10,-y=>240);
# -----------------------------------------------------------------
# Scroll barre du resultat
# -----------------------------------------------------------------
$defil_v = $fenetre->Scrollbar();
# Tableau anonyme de deux widgets listes
$listes = [ $fenetre->Listbox()];
# Configure chaque liste pour appeler &defiler_listes
foreach $liste (@$listes) 
	{
	  $liste->configure(-yscrollcommand => [ \&defiler_listes, $defil_v,$liste, $listes ]);
	}
# 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 => 10, -y => 240,-height=>170);
foreach $liste (@$listes) {
  $liste->place(-x => 40, -y => 240, -width => 520);
}	
	
} 
# -----------------------------------------------------------------
# FIN ihm
# -----------------------------------------------------------------
sub fooox_cherche {
	
# -------------------------------------------------------------------
# Traverse desired filesystems
# -------------------------------------------------------------------
# on eclate $texte_chaine pour recuperer les mots recherches.
            foreach $liste (@$listes) 
         {
	    $liste->delete(0,'end');
	 }
         @mot = split(/ /, $text_chaine); 
    
         $index=0;
         $monregex="";
   #      print ("texte ; $text_chaine");
         
         while ($mot[$index] ne "") 
         {
           if ($index >0 )  { $monregex = $monregex . $radio_bouton;}
           $monregex = $monregex . $mot[$index] ;
           $index++;
          		#print (" a * $mot[$index] - \n");
         }
        #print ("reg $monregex\n");

File::Find::find({wanted => \&wanted, no_chdir=>1}, $curr_dir );	


  $recup=$Fichier->get();

}


sub wanted 
{
    $fichier=$_;
    $chemin_complet=$File::Find::name;
    $chemin=$File::Find::dir;
    
# -------------------------------------------------------------------    
# Test Si Fichier OpenOffice.org
# -------------------------------------------------------------------    
  
if (-f $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);
	     # -----------------------------------------------------------------
	     # 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
        
        # -------------------------------------------------------------------    
	# 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);
	    
	   if ($contenu =~ /$monregex/)
	   { 
	    # -------------------------------------------------------------------    
            # Affiche fichier car contient $texte_chaine
	    # -------------------------------------------------------------------  
          
	    foreach $liste (@$listes) 
            {
	       $liste->insert('end', "$File::Find::name");
	    }
	    
	   } # Fin du regex

    } # fin du fichier on passe au suivant
} # fin de la procedure wanted
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();

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');
#$f->Button(-text => 'Cancel',
#	   -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
  }
}

