Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package Marica::Base::Rapports::export_raw_data ;
- use utf8 ;
- use strict ;
- use POSIX 'setsid';
- use Time::HiRes qw(gettimeofday tv_interval);
- use Apache2::Const -compile => qw(OK REDIRECT) ;
- sub handler {
- binmode(STDOUT, ":utf8") ;
- my $r = shift ;
- my $req = Apache2::Request->new($r) ;
- #récupérer les arguments
- my ( %args, @args ) ;
- @args = $req->param ;
- for (@args) {
- $args{$_} = Encode::decode_utf8( $req->param($_) ) ;
- #nix those sql injection/htmlcode attacks!
- $args{$_} =~ tr/<>;/-/ ;
- #les double-quotes viennent interférer avec le html
- $args{$_} =~ tr/"/'/ ;
- }
- my $id_client = $r->pnotes('session')->{id_client} ;
- my $content = '<h1 style="text-align: center;">' . _( 'Exportation des données', $r ) . '</h1>' ;
- #nom du répertoire de collecte des fichiers/données/documents dans /base/listing
- my $token_id = map +(0..9,"a".."z","A".."Z")[rand(10+26*2)], 1..32 ;
- my $recipient_dir = $r->document_root() . '/base/listing/' . $r->pnotes('session')->{_session_id} ;
- my $result_file_name = $r->pnotes('session')->{_session_id} ;
- my $final_file_name = '' ;
- #effacer les listings précédents de la session pour démarrer propre
- #il faut le faire avant de lancer le fork, sinon le test -e détecte le fichier précédent encore présent
- $ENV{'PATH'} = '/bin:/usr/bin' ;
- delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
- my @args = ( 'rm', '-r', $r->document_root() . '/base/listing/' . $r->pnotes('session')->{_session_id} ) ;
- system(@args) == 0 or warn "system @args failed: $?" ;
- my @args = ( 'rm', $r->document_root() . '/base/listing/' . $r->pnotes('session')->{_session_id} . '.tar.gz' ) ;
- system(@args) == 0 or warn "system @args failed: $?" ;
- if ( defined $args{go_for_it} ) {
- $ENV{'PATH'} = '/bin:/usr/bin' ;
- delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
- $r->content_type('text/html; charset=utf-8') ;
- $r->print('<!DOCTYPE html><html lang = "fr"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>' . $r->hostname . '</title></head><body><h3>Building tar file</h3><p>*') ;
- $r->rflush ; #clear the request buffer
- my $t0 = [gettimeofday];
- #on sélectionne la base qui va bien
- my @databases = $r->dir_config->get('db_name') ;
- my $demo_user_name = $r->dir_config('demo_username') ;
- my $database = ( $r->pnotes('session')->{username} =~ /$demo_user_name/ ) ? $databases[1] : $databases[0] ;
- #on fait un fork pour lancer le long process
- #le fork crée le .tar.gz à télécharger
- $SIG{CHLD} = 'IGNORE';
- defined (my $kid = fork) or die "Cannot fork: $!\n" ;
- if ($kid) {
- #print "Parent $$ has finished, kid's PID: $kid\n" ;
- } else {
- # chdir to '/' stops the process from preventing an unmount
- chdir '/' or die "Can't chdir to /: $!" ;
- open STDIN, '/dev/null' or die "Can't read /dev/null: $!" ;
- open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!" ;
- open STDERR, '>/tmp/log' or die "Can't write to /tmp/log: $!" ;
- setsid or die "Can't start a new session: $!" ;
- my $oldfh = select STDERR ;
- local $| = 1 ;
- select $oldfh ;
- # warn "started\n" ;
- #créer les répertoires de stockage
- mkdir $recipient_dir ;
- mkdir '/tmp/marica_data' ;
- #dump du schéma de la base
- my @args = ('pg_dump', '-s', '-f', $recipient_dir . '/marica.out', $database) ;
- system(@args) == 0 or warn "system @args failed: $?" ;
- #la commande d'exportation des données du client ressemble à ça:
- #psql -f /home/lib/Marica/Base/Procedures/Reversibility/export_raw_data.sql -v id_client=13 -v database=marica postgres
- #on crée provisoirement les fichiers data dans /tmp/marica_data
- @args = ('psql', '-f', '/home/lib/Marica/Base/Procedures/Reversibility/export_raw_data.sql', '-v', 'id_client=' . $r->pnotes('session')->{id_client}, '-v', 'database=' . $database, 'postgres') ;
- system(@args) == 0 or warn "system @args failed: $!" ;
- #if faut les déplacer dans $recipient_dir
- @args = ('mv', '/tmp/marica_data', $recipient_dir . '/data') ;
- system(@args) == 0 or warn "system @args failed: $!" ;
- #copier le fichier create_db.sh et remplacer =id_client par la bonne valeur
- my $id_client = $r->pnotes('session')->{id_client} ;
- my $script ;
- open (my $fh_in, "<:encoding(UTF-8)", '/home/lib/Marica/Base/Procedures/Reversibility/create_db.sh') or die "Can't open create_db.sh : $!" ;
- while ( <$fh_in> ) {
- $script .= $_;
- }
- $script =~ s/=id_client/=$id_client/ ;
- close $fh_in ;
- #création du fichier pour le client
- my $out_file = $recipient_dir . '/create_db.sh' ;
- open (my $fh_out, ">:encoding(UTF-8)", $out_file) or warn "Can't open $out_file : $!" ;
- #ajouter le BOM pour que les tableurs s'ouvrent avec le bon encodage (utf8)
- #on peut aussi utiliser chr(65279);
- #MS-Office a besoin de ça pour identifier l'encodage
- print $fh_out chr(0xFEFF) ;
- print $fh_out $script ;
- close $fh_out ;
- #copier le fichier import_raw_data.sql
- @args = ('cp', '/home/lib/Marica/Base/Procedures/Reversibility/import_raw_data.sql', $recipient_dir) ;
- system(@args) == 0 or warn "system @args failed: $!" ;
- #création du fichier tar compressé
- my $temp_name = $result_file_name . '.tmp' ;
- @args = ( 'tar', '-czf', $r->document_root() . '/base/listing/' . $temp_name, $recipient_dir) ;
- system(@args) == 0 or warn "system @args failed: $!" ;
- #renommer proprement le fichier tar pour détection par la boucle do { }
- $final_file_name = $result_file_name . '.tar.gz' ;
- rename $r->document_root() . '/base/listing/' . $temp_name , $r->document_root() . '/base/listing/' . $final_file_name ;
- CORE::exit(0); # terminate the process
- } # if ($kid)
- #pendant que le fork travaille, on vérifie si le fichier .tar.gz final existe
- #tant qu'il n'est pas présent, on envoie un nouvel élément toutes les secondes
- my $i = 1 ;
- do {
- my $final_result = $r->document_root() . '/base/listing/' . $result_file_name . '.tar.gz' ;
- $i = 0 if -e $final_result ;
- $r->print('*') ;
- $r->rflush; #clear the request buffer
- sleep( 1 ) ;
- } while ( $i ) ;
- $r->print( '</p>' ) ;
- $r->rflush; #clear the request buffer
- my $t1 = [gettimeofday] ;
- my $t0_t1 = tv_interval $t0, $t1 ;
- my $file_size = -s $r->document_root() . '/base/listing/' . $result_file_name . '.tar.gz' ;
- $content = '<pre>
- using db : ' . $database . '
- recipient_dir : ' . $recipient_dir . '
- file size : ' . $file_size . '
- interval : ' . $t0_t1 . '
- </pre>' ;
- my $download_link = '<a href="/base/listing/' . $result_file_name . '.tar.gz">Télécharger ' . $result_file_name . '.tar.gz</a>' ;
- my $download_zone = '
- <h3>Lien</h3>
- <p>' . $download_link . '
- </p></body>' ;
- $content .= $download_zone ;
- $r->print( $content ) ;
- return Apache2::Const::OK ;
- } else {
- $content .= presentation($r) ;
- } # if ( defined $args{go_for_it} )
- $r->content_type('text/html; charset=utf-8') ;
- $r->no_cache(1) ;
- print $content ;
- return Apache2::Const::OK ;
- }
- 1 ;
- sub presentation {
- my $r = shift ;
- my $content = '<h2>Instructions</h2>' ;
- $content .= '<p>Cette procédure crée un fichier contenant toutes les données stockées dans la base pour votre compte</p>' ;
- $content .= '<p>Ce fichier est une archive tar contenant :</p>' ;
- $content .= '
- <ul>
- <li>le fichier create_db.sh qui crée la base de données Postgresql pour accueillir les données (nommée "import_raw_data")</li>
- <li>le fichier marica.out contenant le schema de la base de données</li>
- <li>le fichier import.sql qui importe les données</li>
- <li>le répertoire data qui contient les données (séparateur de données "TAB")</li>
- </ul>' ;
- $content .= '<h3>Utilisation</h3>
- <ul>
- <li>Créer le répertoire /tmp/marica</li>
- <li>Extraire de l\'archive tar les 4 éléments ci-dessus, et les placer dans /tmp/marica </li>
- <li>Rendre create_db.sh executable</li>
- <li>Executer create_db.sh en tant que super-utilisateur</li>
- </ul>' ;
- my $form = '
- <form action=export_raw_data method=POST>
- <p><input type=submit value="Exporter les données"><input type=hidden name=go_for_it value=0></p>
- </form>
- ' ;
- $content .= $form ;
- return $content ;
- } #sub presentation
Advertisement
Add Comment
Please, Sign In to add comment