--- /dev/null
+#!/usr/bin/env bash
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# cmdtemp
+# List commands
+# cmdtemp <n>
+# Execute command number <n>
+# cmdtemp <-n>
+# Delete command number <n>
+# cmdtemp <...>
+# Save command
+
+
+function is_negative() {
+ s=$(echo $1 | tr -d 0-9)
+ if [ "$s" == "-" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+function is_integer() {
+ s=$(echo $1 | tr -d 0-9)
+ if [ -z "$s" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+if [ $# -eq 0 ]; then
+ cat -n $HOME/.cmdtemp
+ exit
+fi
+
+if is_integer "$1"; then
+ ligne="$1"
+ shift
+ commande=`awk "FNR == $ligne" $HOME/.cmdtemp`
+ echo "*** "$commande
+ eval $commande
+elif is_negative "$1"; then
+ s=$(echo $1 | tr -d '-')
+ sed -i -e $s"d" $HOME/.cmdtemp
+else
+ echo "$*" >> $HOME/.cmdtemp
+fi
--- /dev/null
+#!/usr/bin/env bash
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+echo " Bg | Fg"
+printf -- '-%.0s' {1..122} ; echo ""
+for((bg=40;bg<=47;bg++)); do
+ for int in 0 60; do
+ for b in 0 1 4 7 9; do
+ if [ $bg -gt 40 -a "(" $b = 7 -o $b = 9 -o $b = 4 ")" ]; then
+ continue
+ fi
+
+ if [ $b = "0" ]; then
+ echo -en "\033[0m""ESC[$((${bg}+${int}))m"
+ if [ $int = 0 ]; then
+ echo -n " "
+ fi
+ echo -n "| "
+ else
+ echo -en " | "
+ fi
+
+ for((fg=30;fg<=37;fg++)); do
+ echo -en "\033[$((${bg}+${int}))m\033[${b};${fg}m [${b};${fg}m"
+ echo -en "\033[$((${bg}+${int}))m\033[${b};$((${fg}+60))m [${b};$((${fg}+60))m"
+ done
+
+ echo -e "\033[0m"
+ done
+ done
+ printf -- '-%.0s' {1..122} ; echo ""
+done
--- /dev/null
+#!/usr/bin/en perl
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use Switch;
+use strict;
+
+my $file = "comptes.data";
+
+my @actions=('Ajouter un participant');
+my %participants = ();
+my @transactions = ();
+my @descriptions = ();
+my $evenement_def;
+my $remboursements = "";
+
+if($#ARGV==0) {
+ open FILE, $ARGV[0] || die "Impossible de lire le fichier";
+ $evenement_def = <FILE>;
+ chomp($evenement_def);
+ while(my $noms = <FILE>) {
+ if($noms eq "\n") { last; }
+ my ($numero,$nom) = split(/ /,$noms,2);
+ chomp($nom);
+ $participants{$nom} = $numero;
+ }
+ while(my $transaction = <FILE>) {
+ if($transaction eq "\n") { last; }
+ chomp($transaction);
+ push(@transactions,$transaction);
+ my $description = <FILE>;
+ chomp($description);
+ push(@descriptions,$description);
+ }
+ $file = $ARGV[0];
+}
+
+GLOBALE: while(1) {
+ if(keys(%participants)>0) {
+ $actions[1]="Ajouter une dépense";
+ $actions[2]="Enregistrer";
+ }
+ if(scalar(@transactions)>0) {
+ $actions[3]="Voir les dépenses de quelqu'un";
+ $actions[2]="Enregistrer";
+ $actions[4]="Equilibrage";
+ $actions[5]="Voir une transaction";
+ }
+
+ my $action;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( @actions, 'Sortir' );
+ my $message = '';
+ foreach $var ( @vart ) {
+ $message .= $i++.') '.$var."\n";
+ }
+ print $message;
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $action = $vart[$var-1];
+ last;
+ }
+ switch ($action) {
+ case "Ajouter un participant" {
+ print "Nom du participant\n";
+ my $participant = <STDIN>;
+ chomp($participant);
+ $participants{$participant} = keys(%participants)+1;
+ }
+ case "Ajouter une dépense" {
+ print "Qui a payé ?\n";
+ my $paye;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( keys(%participants), "Annuler" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $paye = $vart[$var-1];
+ last;
+ }
+ if($paye eq "Annuler") {
+ next GLOBALE;
+ }
+ print "Quoi ?\n";
+ my $description = <STDIN>;
+ chomp($description);
+ print "Combien ?\n";
+ my $prix = <STDIN>;
+ chomp($prix);
+ print "Pour qui ?\n";
+ my $repartition = "";
+ my $total_parts = 0;
+ DESTS: while(1) {
+ my $dest;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( keys(%participants), "Ajouter à tous", "Fini" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $dest = $vart[$var-1];
+ last;
+ }
+ switch($dest) {
+ case "Fini" {
+ if($repartition eq "") { print "Annulé\n"; }
+ elsif($total_parts == 0) {
+ print "Le nombre total de parts est nul, il faut en ajouter !\n";
+ next DESTS;
+ }
+ else {
+ push(@transactions, $participants{$paye}.' '.$prix.$repartition);
+ push(@descriptions, $description);
+ }
+ last DESTS;
+ }
+ case "Ajouter à tous" {
+ print "Nombre de parts ?\n";
+ my $parts = <STDIN>;
+ chomp($parts);
+ if(!($parts == 0)) {
+ foreach my $participant (keys(%participants)) {
+ $repartition .= ' '.$participants{$participant}.':'.scalar($parts);
+ $total_parts += scalar($parts);
+ }
+ }
+ }
+ else {
+ print "Nombre de parts ?\n";
+ my $parts = <STDIN>;
+ chomp($parts);
+ if(!($parts == 0)) {
+ $repartition .= ' '.$participants{$dest}.':'.scalar($parts);
+ $total_parts += scalar($parts);
+ }
+ }
+ }
+ }
+ }
+ case "Voir les dépenses de quelqu'un" {
+ my $personne;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( keys(%participants), "Annuler" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $personne = $vart[$var-1];
+ last;
+ }
+ if($personne eq "Annuler") {
+ next GLOBALE;
+ }
+ my $depenses = 0;
+ my $frais = 0;
+ foreach my $transaction (@transactions) {
+ my @table_trans = split(/ /,$transaction);
+ my $payeur = shift(@table_trans);
+ my $prix = shift(@table_trans);
+ if($payeur == $participants{$personne}) {
+ $depenses += $prix;
+ }
+ my $parts = 0;
+ my $frac = 0;
+ my $repartition;
+ foreach $repartition (@table_trans) {
+ my ($pers,$part) = split(/:/,$repartition);
+ if($pers == $participants{$personne}) {
+ $frac += $part;
+ }
+ $parts += $part;
+ }
+ $frais += $prix*$frac/$parts;
+ }
+ print $personne." a payé ".$depenses." EUR\n";
+ print "et a pour ".sprintf("%.2f",$frais)." EUR de frais au total.\n";
+ print "Il a donc un solde de ".sprintf("%.2f",$depenses-$frais)." EUR\n";
+ my $pause = <STDIN>;
+ }
+ case "Voir une transaction" {
+ my $transaction;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( @descriptions, "Annuler" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $transaction = $var-1;
+ last;
+ }
+ my @table_trans = split(/ /,$transactions[$transaction]);
+ my $payeur = shift(@table_trans);
+ my $prix = shift(@table_trans);
+ my $Tparts = 0;
+ my $repartition;
+ my %parts;
+ foreach my $pers (keys(%participants)) {
+ if($payeur == $participants{$pers}) {
+ print $descriptions[$transaction]." (payé par ".$pers."), ".$prix." EUR\n";
+ last
+ }
+ }
+ foreach $repartition (@table_trans) {
+ my ($pers,$part) = split(/:/,$repartition);
+ $Tparts += $part;
+ $parts{$pers} += $part;
+ }
+ foreach my $pers (keys(%participants)) {
+ if(!exists $parts{$participants{$pers}}) {
+ next;
+ }
+ print $pers.", ".$parts{$participants{$pers}}." part(s), soit ". $prix*$parts{$participants{$pers}}/$Tparts." EUR\n";
+ }
+ my $pause = <STDIN>;
+ }
+ case "Enregistrer" {
+ print "Nom de l'événement ?";
+ if(!($evenement_def eq "")) {
+ print " [".$evenement_def."]";
+ }
+ print "\n";
+ my $evenement = <STDIN>;
+ chomp($evenement);
+ if($evenement eq "") {
+ $evenement = $evenement_def;
+ }
+ open FILE, ">".$file;
+ print FILE $evenement."\n";
+ my $key;
+ foreach $key (keys(%participants)) {
+ print FILE $participants{$key}." ".$key."\n";
+ }
+ print FILE "\n";
+ for(my $i=0;$i<scalar(@transactions);$i++) {
+ print FILE $transactions[$i]."\n";
+ print FILE $descriptions[$i]."\n";
+ }
+ print FILE "\n";
+ print FILE $remboursements;
+ close FILE;
+ }
+ case "Equilibrage" {
+ my %Tdepenses = ();
+ my %Tfrais = ();
+ my %Tsolde = ();
+ $remboursements = "";
+ foreach my $Ttransaction (@transactions) {
+ my @Ttable_trans = split(/ /,$Ttransaction);
+ my $Tpayeur = shift(@Ttable_trans);
+ my $Tprix = shift(@Ttable_trans);
+ $Tdepenses{$Tpayeur} = $Tdepenses{$Tpayeur} + $Tprix;
+ my $Tparts = 0;
+ my $Tfrac = 0;
+ my $Trepartition;
+ foreach $Trepartition (@Ttable_trans) {
+ my ($Tpers,$Tpart) = split(/:/,$Trepartition);
+ $Tparts += $Tpart;
+ }
+ foreach $Trepartition (@Ttable_trans) {
+ my ($Tpers,$Tpart) = split(/:/,$Trepartition);
+ $Tfrais{$Tpers} = $Tfrais{$Tpers} + $Tprix*$Tpart/$Tparts;
+ }
+ }
+ foreach my $Tpersonne (keys(%participants)) {
+ my $numero = $participants{$Tpersonne};
+ $Tsolde{$Tpersonne} = sprintf("%.2f",$Tdepenses{$numero}-$Tfrais{$numero});
+ print $Tpersonne." a un solde de ".$Tsolde{$Tpersonne}." EUR\n";
+ }
+ my $pause = <STDIN>;
+ print "Y-a-t-il des remboursements plus aisés ?\n";
+ my $ouinon;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( "Oui", "Non" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $ouinon = $vart[$var-1];
+ last;
+ }
+ AISE: while($ouinon eq "Oui") {
+ print "Qui ?\n";
+ my $personne;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( keys(%participants), "Fini" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $personne = $vart[$var-1];
+ last;
+ }
+ if($personne eq "Fini") { last AISE; }
+ print "Avec qui ?\n";
+ my $personneb;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( keys(%participants), "Annuler" );
+ foreach $var ( @vart ) {
+ print $i++.') '.$var."\n";
+ }
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $personneb = $vart[$var-1];
+ last;
+ }
+ if($personneb eq "Annuler") { next AISE; }
+ if($Tsolde{$personne}*$Tsolde{$personneb}<0) {
+ my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb;
+ my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb;
+ my $inf = (abs($Tsolde{$personne})<abs($Tsolde{$personneb}))?abs($Tsolde{$personne}):abs($Tsolde{$personneb});
+ $remboursements .= $pers_inf." doit ".$inf." EUR à ".$pers_sup."\n";
+ $Tsolde{$pers_inf} += $inf;
+ $Tsolde{$pers_sup} -= $inf;
+ }
+ }
+ # Une boucle pour détecter si on a des couples qui s'annulent mutuellement
+ COUPLE: foreach my $personne (keys(%participants)) {
+ if($Tsolde{$personne} == 0) { next; }
+ foreach my $personneb (keys(%participants)) {
+ if($Tsolde{$personneb} + $Tsolde{$personne} != 0) { next; }
+ my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb;
+ my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb;
+ my $val = abs($Tsolde{$personne});
+ $remboursements .= $pers_inf." doit ".$val." EUR à ".$pers_sup."\n";
+ $Tsolde{$pers_inf} += $val;
+ $Tsolde{$pers_sup} -= $val;
+ next COUPLE;
+ }
+ }
+ REMB: while(1) {
+ # On supprime les 0, et on fait deux hashs
+ my %Tneg = ();
+ my %Tpos = ();
+ foreach my $personne (keys(%Tsolde)) {
+ if($Tsolde{$personne} == 0) { delete $Tsolde{$personne}; }
+ elsif($Tsolde{$personne} < 0) { $Tneg{$personne} = $Tsolde{$personne}; }
+ elsif($Tsolde{$personne} > 0) { $Tpos{$personne} = $Tsolde{$personne}; }
+ }
+ if(keys(%Tneg) == 0) {
+ last REMB;
+ }
+ foreach my $neg (sort { $Tneg{$a} cmp $Tneg{$b} } keys %Tneg) {
+ my $max = 0;
+ my $positif = 0;
+ foreach my $pos (sort { $Tpos{$a} cmp $Tpos{$b} } keys %Tpos) {
+ if($Tpos{$pos} + $Tneg{$neg}>0) {
+ $positif = $pos;
+ last;
+ }
+ $max = $pos;
+ }
+ if(!($max eq 0)) {
+ $remboursements .= $neg." doit ".$Tsolde{$max}." EUR à ".$max."\n";
+ $Tsolde{$neg} += $Tsolde{$max};
+ delete $Tsolde{$max};
+ }
+ else {
+ $remboursements .= $neg." doit ".-$Tsolde{$neg}." EUR à ".$positif."\n";
+ $Tsolde{$positif} += $Tsolde{$neg};
+ delete $Tsolde{$neg};
+ }
+ next REMB;
+ }
+ }
+ print $remboursements;
+ my $pause = <STDIN>;
+ }
+ case "Sortir" {
+ last GLOBALE;
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/env bash
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+# To be used together with remove_attachements script in procmail and urlview to
+# visualize and keep some attachements once they are removed from the email
+# Example urlview updated configuration:
+# REGEXP ((((http|https|ftp|gopher)|mailto):(//)?[^ <>"\t]*|(www|ftp)[0-9]?\.[-a-z0-9.]+)[^ .,;\t\n\r<">\):]?[^, <>"\t]*[^ .,;\t\n\r<">\):]|(file|keepdir)://([^\t\n\r\\ ]+(\\ |\\)?)+)
+# COMMAND execurl
+
+export chemin=x"$1"
+if [ "${chemin:0:8}" = "xfile://" ]; then
+ fichier="${1:7}"
+ fichierlu="${fichier//\\ / }"
+ if [ ! -f "$fichierlu" ]; then
+ exec run-mailcap "${fichierlu//.attachements/Mail/.attachements}"
+ else
+ exec run-mailcap "$fichierlu"
+ fi
+elif [ "${chemin:0:11}" = "xkeepdir://" ]; then
+ mv "${1:10}" "$HOME/Mail/.attachements/"
+else
+ exec w3m "$1"
+fi
--- /dev/null
+#!/usr/bin/env perl
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use strict;
+use File::Basename;
+
+sub parse_config_file {
+ my ($config_line, $Name, $Value, $Config);
+ (my $File, $Config) = @_;
+ if (!open (CONFIG, "$File")) {
+ print "ERROR: Config file not found : $File";
+ exit(0);
+ }
+ my $multiline = 0;
+
+ while (<CONFIG>) {
+ $config_line=$_;
+ chop ($config_line);
+ $config_line =~ s/^\s*//;
+ $config_line =~ s/\s*$//;
+ if ( ($config_line !~ /^#/) && ($config_line ne "") ){
+ if ($multiline) {
+ $$Config{$Name} =~ s/\\$//;
+ $$Config{$Name} .= $config_line;
+ } else {
+ ($Name, $Value) = split (/\s*=\s*/, $config_line);
+ $Value =~ s/^~/$ENV{"HOME"}/;
+ $$Config{$Name} = $Value;
+ }
+ $multiline = ($$Config{$Name} =~ /\\$/);
+ }
+ }
+ close(CONFIG);
+}
+
+my %Config;
+&parse_config_file ($ENV{"HOME"}."/.gen_html_documents.rc", \%Config);
+
+my $entete = $Config{"entete"};
+my $avant = $Config{"avant"};
+my $milieu = $Config{"milieu"};
+my $apres = $Config{"apres"};
+my $html = $Config{"html"};
+
+my @ignore = split (/\s*,\s*/, $Config{"ignore"});
+my @ext = split (/\s*,\s*/, $Config{"ext"});
+
+my $documents = $Config{"documents"};
+my $droot = $Config{"dossier_web"};
+
+$Config{"dossiers"} =~ s/^"//;
+$Config{"dossiers"} =~ s/"$//;
+my %dossiers = split (/"?\s*,\s*"?/, $Config{"dossiers"});
+
+my ($dossier,$description);
+
+open F, ">".$milieu;
+
+while(($dossier,$description) = each(%dossiers)) {
+ opendir(DIR, $documents.$dossier) || warn $documents.$dossier." coulnd't be opened\n";
+ my @content = grep {$_ !~ /^\.\.?$/} readdir(DIR);
+ my @sorted = sort { lc($a) cmp lc($b) } @content;
+ closedir(DIR);
+
+ print F "<h3>".$description."</h3>\n";
+ print F "<ul>\n";
+ foreach my $subpath (grep { -d $documents.$dossier.'/'.$_} @sorted) {
+ subparse($dossier,$subpath,4);
+ }
+ foreach my $file (grep { -f $documents.$dossier.'/'.$_} @sorted) {
+ my($filename, $directories, $suffix) = fileparse($file,qr/\.[^\.]*/);
+ next if(!in_array(\@ext,lc($suffix)));
+ $filename =~ tr/_/ /;
+ print F "<li><a href='".$droot.$dossier.'/'.$file."'>".$filename."</a></li>\n";
+ }
+ print F "</ul>\n";
+ }
+
+sub subparse {
+ my $path = shift;
+ my $dossier = shift;
+ my $rang = shift;
+
+ opendir(DIR, $documents.$path."/".$dossier);
+ my @content = grep {$_ !~ /^\.\.?$/} readdir(DIR);
+ my @sorted = sort { lc($a) cmp lc($b) } @content;
+ closedir(DIR);
+
+ return if(in_array(\@ignore,$dossier));
+ my $dossierspace = $dossier;
+ $dossierspace =~ tr/_/ /;
+ print F "<li>".$dossierspace."\n";
+ print F "<ul>\n";
+ foreach my $subpath (grep { -d $documents.$path."/".$dossier.'/'.$_} @sorted) {
+ subparse($path."/".$dossier,$subpath,$rang+1);
+ }
+ foreach my $file (grep { -f $documents.$path."/".$dossier.'/'.$_} @sorted) {
+ my($filename, $directories, $suffix) = fileparse($file,qr/\.[^\.]*/);
+ next if(!in_array(\@ext,lc($suffix)));
+ $filename =~ tr/_/ /;
+ print F "<li><a href='".$droot.$path.'/'.$dossier.'/'.$file."'>".$filename."</a></li>\n";
+ }
+ print F "</ul></li>\n";
+ }
+
+sub in_array {
+ my ($arr,$search_for) = @_;
+ my %items = map {$_ => 1} @$arr; # create a hash out of the array values
+ return (exists($items{$search_for}))?1:0;
+ }
+
+close F;
+
+exec "cat $entete $avant $milieu $apres 1> $html" or die "$!\n";
+exec "chmod -R go=rX,u=rwX $documents"
--- /dev/null
+#!/usr/bin/env bash
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+extension="${3##*.}"
+if [ $extension = "tex" ]; then
+ latexdiff "$1" "$2" > diff_$3
+fi
\ No newline at end of file
--- /dev/null
+#!/usr/local/bin/perl
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use Switch;
+use strict;
+
+my @table = ();
+my @interros = ();
+my @tablequestion = ();
+my @points = ();
+my %corr_nom ;
+my $interro_courante = 0;
+my $fichier = "notes.dat";
+if($#ARGV == 0) {
+ $fichier = $ARGV[0];
+}
+
+sub ajout_interro {
+ print "Nom de l'interrogation\n";
+ my $interro = <STDIN>;
+ chomp($interro);
+ push(@interros,$interro);
+ push(@tablequestion,[]);
+ push(@table,[]);
+ push(@points,[]);
+ foreach my $key (keys %corr_nom) {
+ push(@{ $corr_nom{$key} }, "Absent" );
+ }
+}
+
+sub ajout_eleve {
+ print "Nom\n";
+ my $nom = <STDIN>;
+ chomp($nom);
+ print "Prénom\n";
+ my $prenom = <STDIN>;
+ chomp($prenom);
+ $corr_nom{$prenom."\n".$nom} = ();
+ for my $i (0..$#interros) {
+ push(@{ $corr_nom{$prenom."\n".$nom} }, "Absent" );
+ }
+}
+
+sub definir_exos {
+ my $interro = shift;
+ my $nbexos = "a";
+ while($nbexos =~ m/\D/) {
+ print "Nombre d'exercices\n";
+ $nbexos = <STDIN>;
+ chomp($nbexos);
+ if($nbexos =~ /\D/) {
+ print "Mauvaise entrée\n";
+ }
+ }
+ if($nbexos == "") {
+ $nbexos = 0;
+ }
+ push(@{ $table[$interro] }, $nbexos);
+ if($nbexos == 0) {
+ push(@{ $tablequestion[$interro] }, "");
+ }
+ for(my $i = 1; $i <= $nbexos; $i++) {
+ my $questions = "a";
+ while($questions =~ m/\D/) {
+ print "Nombre de questions dans l'exercice ",$i,"\n";
+ $questions = <STDIN>;
+ chomp($questions);
+ if($questions =~ /\D/) {
+ print "Mauvaise entrée\n";
+ }
+ }
+ if($questions eq "") {
+ $questions = 0;
+ }
+ if($questions > 1) {
+ push(@{ $table[$interro] }, $questions);
+ for(my $j = 1; $j <= $questions; $j++) {
+ my $ssquestions = "a";
+ while($ssquestions =~ m/\D/) {
+ print "Nombre de sous-questions dans la question ",$i,".",$j,"\n";
+ $ssquestions = <STDIN>;
+ chomp($ssquestions);
+ if($ssquestions =~ /\D/) {
+ print "Mauvaise entrée\n";
+ }
+ }
+ if($ssquestions eq "") {
+ $ssquestions = 0;
+ }
+ if($ssquestions > 1) {
+ push(@{ $table[$interro] }, $j.".".$ssquestions);
+ for(my $k = 1; $k<= $ssquestions; $k++) {
+ push(@{ $tablequestion[$interro] }, $i.".".$j.".".$k);
+ }
+ }
+ else {
+ push(@{ $tablequestion[$interro] }, $i.".".$j);
+ }
+ }
+ }
+ else {
+ push(@{ $tablequestion[$interro] }, $i);
+ }
+ }
+}
+
+sub entrer_notes {
+ my $interro = shift;
+ my $eleve = shift;
+ my @boucle;
+ if($eleve) {
+ @boucle = ($eleve);
+ }
+ else {
+ @boucle = sort sort_alpha keys %corr_nom;
+ }
+ foreach my $key (@boucle) {
+ my $keyt = $key;
+ $keyt =~ s/\n/ /;
+ print $keyt." (mettre A pour indiquer une absence)\n";
+ my @int;
+ if(ref($corr_nom{$key}[$interro]) eq 'ARRAY') {
+ @int = @{$corr_nom{$key}[$interro]};
+ }
+ $corr_nom{$key}[$interro] = ();
+ Interro: for my $i (0..$#{$tablequestion[$interro]}) {
+ my $pourcentage = "a";
+ my $def = 0;
+ if(!@int && $i == 0) {
+ $def = "A";
+ }
+ if(scalar(@int) > 0) {
+ $def = $int[$i];
+ }
+ while($pourcentage =~ m/\D/ || $pourcentage > 100) {
+ if($tablequestion[$interro][$i] =~ m/\D/ ) {
+ print "Pourcentage pour la question ".$tablequestion[$interro][$i]." [".$def."]\n";
+ }
+ else {
+ print "Pourcentage pour l'exercice ".$tablequestion[$interro][$i]." [".$def."]\n";
+ }
+ $pourcentage = <STDIN>;
+ chomp($pourcentage);
+ if($pourcentage eq "") {
+ $pourcentage = $def;
+ }
+ if($pourcentage =~ m/^a$/i) {
+ $corr_nom{$key}[$interro] = "Absent";
+ last Interro;
+ }
+ if($pourcentage =~ /\D/ || $pourcentage > 100) {
+ print "Il faut un pourcentage entre 0 et 100\n";
+ }
+ }
+ push(@{ $corr_nom{$key}[$interro] },$pourcentage);
+ }
+ }
+}
+
+sub entrer_bareme {
+ my $interro = shift;
+ foreach my $nomquestion ( @{ $tablequestion[$interro] } ) {
+ my $point = "a";
+ while($point =~ /[^\d\.]/) {
+ if($nomquestion =~ m/\D/ ) {
+ print "Points pour la question ".$nomquestion."\n";
+ }
+ else {
+ print "Points pour l'exercice ".$nomquestion."\n";
+ }
+ $point = <STDIN>;
+ chomp($point);
+ if($point =~ /[^\d\.]/) {
+ print "Il faut donner un nombre de points\n";
+ }
+ }
+ if($point eq "") {
+ $point = 0;
+ }
+ push(@{ $points[$interro] },$point);
+ }
+}
+
+sub sauver {
+ open FILE, ">".$fichier;
+ foreach my $i (0..$#table) {
+ print FILE $interros[$i]."\n";
+ print FILE "@{ $table[$i] }\n";
+ print FILE "@{ $tablequestion[$i] }\n";
+ print FILE "@{ $points[$i] }\n";
+ }
+ print FILE "\n";
+ foreach my $ligne (keys(%corr_nom)) {
+ print FILE $ligne."\n";
+ foreach my $lig (@{ $corr_nom{$ligne} }) {
+ if($lig eq "Absent") {
+ print FILE "! \n";
+ }
+ else {
+ print FILE "* @$lig\n";
+ }
+ }
+ }
+ print FILE "\n";
+ close FILE;
+}
+
+sub charger {
+ open FILE, $fichier;
+ while(my $int = <FILE>) {
+ if($int eq "\n") { last };
+ chomp($int);
+ push(@interros,$int);
+ $int = <FILE>;
+ chomp($int);
+ push(@table, [ split(/ /, $int) ] );
+ $int = <FILE>;
+ chomp($int);
+ push(@tablequestion, [ split(/ /, $int) ] );
+ $int = <FILE>;
+ chomp($int);
+ push(@points, [ split(/ /, $int) ] );
+
+ }
+ my $int = <FILE>;
+ while(1) {
+ if($int eq "\n") { last };
+ my $intn = <FILE>;
+ chomp($intn);
+ my $key = $int.$intn;
+ $corr_nom{$key} = ();
+ while($intn = <FILE>) {
+ if($intn =~ m/^\*/) {
+ chomp($intn);
+ push(@{ $corr_nom{$key} }, [ split(/ /, substr($intn,2)) ] );
+ }
+ elsif($intn =~ m/^!/) {
+ push(@{ $corr_nom{$key} }, "Absent" );
+ }
+ else {
+ $int = $intn;
+ last;
+ }
+ }
+ }
+ close FILE;
+}
+
+sub sort_alpha {
+ my @p_na = split(/\n/,$a);
+ my @p_nb = split(/\n/,$b);
+ return $p_na[1] cmp $p_nb[1] || $p_na[0] cmp $p_nb[0];
+}
+
+sub export_latex {
+ print "Fichier ?\n";
+ my $f_export = <STDIN>;
+ chomp($f_export);
+ if($f_export eq "") { return 0 };
+ open FILE, ">".$f_export;
+ print FILE "\\documentclass[landscape]{article}\n";
+ print FILE "\\usepackage[T1]{fontenc}\n";
+ print FILE "\\usepackage[utf8]{inputenc}\n";
+ print FILE "\\usepackage{geometry}\n";
+ print FILE "\\geometry{margin=1cm}\n";
+ print FILE "\\begin{document}\n";
+ for my $interro (0..$#table) {
+ print FILE "\\begin{tabular}{|l|";
+ my @exosansq = grep(/^[1-9]\d*$/,@{ $tablequestion[$interro] });
+ print FILE "c|"x (scalar(@{ $tablequestion[$interro] })+$table[$interro][0] - scalar(@exosansq));
+ print FILE "|c|}\n";
+ my @ign = ();
+ my @pts = ();
+ my @max = ();
+ my @min = ();
+ my @somme = ();
+ print FILE "\\multicolumn{",(scalar(@{ $tablequestion[$interro] })+$table[$interro][0] - scalar(@exosansq) + 2),"}{c}{\\Large ".$interros[$interro]."}\\\\\n";
+ if($table[$interro][0] > 0) {
+ print FILE "\\hline\n\t ";
+ for(my $i = 1; $i <= $table[$interro][0]; $i++) {
+ my @b = grep(/^$i/,@{ $tablequestion[$interro] });
+ if(scalar(@b) == 1) {
+ print FILE "& Exercice $i ";
+ }
+ else {
+ print FILE "& \\multicolumn{",scalar(@b)+1,"}{c|}{Exercice ",$i,"} ";
+ }
+ }
+ print FILE "& Total ";
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ my $rank = -1;
+ for(my $i = 1; $i <= $table[$interro][0]; $i++) {
+ my @b = grep(/^$i(\D|$)/,@{ $tablequestion[$interro] });
+ for(my $j = 1; $j <= scalar(@b); $j++) {
+ my @c = grep(/^$i\.$j(\D|$)/,@{ $tablequestion[$interro] });
+ $rank += scalar(@c);
+ if(scalar(@c) == 1) {
+ print FILE "& $j) ";
+ }
+ elsif(scalar(@c) > 0) {
+ print FILE "& \\multicolumn{",scalar(@c),"}{c|}{",$j,")} ";
+ }
+ elsif($j == 1) {
+ $rank +=1;
+ push(@ign,$rank+$i-1);
+ #print FILE "& ";
+ }
+ }
+ print FILE "& Total ";
+ push(@pts,$rank);
+ }
+ print FILE "& \\\\\n";
+ }
+ print FILE "\\hline\n\t";
+ print FILE "points ";
+ my $totalexo = 0;
+ my $total = 0;
+ my $nq = 0;
+ for my $i (0.. $#{ $points[$interro] }) {
+ print FILE "& $points[$interro][$i] ";
+ push(@min,$points[$interro][$i]);
+ push(@max,0);
+ push(@somme,0);
+ $totalexo += $points[$interro][$i];
+ $total += $points[$interro][$i];
+ $nq++;
+ if((grep {$_ == $i} @pts) > 0) {
+ if($nq > 1) {
+ print FILE "& $totalexo ";
+ }
+ push(@min,$totalexo);
+ push(@max,0);
+ push(@somme,0);
+ $totalexo = 0;
+ $nq = 0;
+ }
+ }
+ print FILE "& $total ";
+ push(@min,$total);
+ push(@max,0);
+ push(@somme,0);
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ print FILE "\\hline\n\t";
+
+ my @sortednotes = sort sort_alpha (keys %corr_nom);
+ #print "@sortednotes";
+ #my $somme = 0;
+ my $nombre_eleves = 0;
+ for my $i (0.. $#sortednotes) {
+ my $np = $sortednotes[$i];
+ $np =~ s/\n/ /;
+ print FILE $np;
+ my @ligne = @{ $corr_nom{$sortednotes[$i]} };
+ if($ligne[$interro] eq "Absent") {
+ print FILE "& \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0]+1,"}{c|}{Absent}";
+ }
+ else {
+ my @ligneo = @{ $ligne[$interro] };
+ my $totalexo = 0;
+ my $total = 0;
+ $nombre_eleves++;
+ my $k = 0;
+ my $nq = 0;
+ foreach my $l (0.. $#ligneo ) {
+ my $val = sprintf("%.0f",4.*$ligneo[$l]*$points[$interro][$l]/100)/4;
+ print FILE "& ",$val;
+ if($min[$k] > $val) {
+ $min[$k] = $val;
+ }
+ if($max[$k] < $val) {
+ $max[$k] = $val;
+ }
+ $somme[$k] += $val;
+ $k++;
+ $nq++;
+ $totalexo += $val;
+ $total += $val;
+ if((grep {$_ == $l} @pts) > 0) {
+ if($min[$k] > $totalexo) {
+ $min[$k] = $totalexo;
+ }
+ if($max[$k] < $totalexo) {
+ $max[$k] = $totalexo;
+ }
+ $somme[$k] += $totalexo;
+ if($nq > 1) {
+ print FILE "& $totalexo ";
+ }
+ $k++;
+ $totalexo = 0;
+ $nq = 0;
+ }
+ }
+ print FILE "& $total ";
+ if($min[$k] > $total) {
+ $min[$k] = $total;
+ }
+ if($max[$k] < $total) {
+ $max[$k] = $total;
+ }
+ $somme[$k] += $total;
+ $k++;
+ }
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ }
+ print FILE "\\hline\n\t";
+ print FILE "Moyenne";
+ for my $l (0.. $#somme) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "& ".sprintf("%.0f",4.*$somme[$l]/$nombre_eleves)/4;
+ }
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ print FILE "Min";
+ for my $l (0.. $#min) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "& $min[$l]";
+ }
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ print FILE "Max";
+ for my $l (0.. $#max) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "& $max[$l]";
+ }
+ #print FILE "Moyenne & \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0],"}{c||}{ }";
+ #my $moyenne = sprintf("%.0f",4.*$somme/$nombre_eleves)/4;
+ #print FILE " & $moyenne\\\\\n";
+ print FILE "\\\\\n";
+ print FILE "\\hline\n\t";
+ print FILE "\\end{tabular}\n";
+ print FILE "\\vfill\n";
+ print FILE "\\newpage\n";
+ }
+ print FILE "\\end{document}\n";
+ close FILE;
+}
+
+sub export_csv {
+ my $interro = shift;
+ print "Fichier ?\n";
+ my $f_export = <STDIN>;
+ chomp($f_export);
+ if($f_export eq "") { return 0 };
+ open FILE, ">".$f_export;
+ for my $interro (0..$#table) {
+ print FILE "; ".$interros[$interro]."\n";
+ my @pts = ();
+ my @ign = ();
+ my @max = ();
+ my @min = ();
+ my @somme = ();
+ if($table[$interro][0] > 0) {
+ for(my $i = 1; $i <= $table[$interro][0]; $i++) {
+ my @b = grep(/^$i/,@{ $tablequestion[$interro] });
+ if(scalar(@b) == 1) {
+ print FILE "; Exercice $i ";
+ }
+ else {
+ print FILE "; Exercice $i","; "x scalar(@b);
+ }
+ }
+ print FILE "; Total \n";
+ my $rank = -1;
+ for(my $i = 1; $i <= $table[$interro][0]; $i++) {
+ my @b = grep(/^$i(\D|$)/,@{ $tablequestion[$interro] });
+ for(my $j = 1; $j <= scalar(@b); $j++) {
+ my @c = grep(/^$i\.$j(\D|$)/,@{ $tablequestion[$interro] });
+ $rank += scalar(@c);
+ if(scalar(@c) == 1) {
+ print FILE "; $j) ";
+ }
+ elsif(scalar(@c) > 0) {
+ my $char = "a";
+ for my $num (0..$#c) {
+ print FILE "; $j) ".$char.") ";
+ $char++;
+ }
+ #print FILE "; $j) ","; "x (scalar(@c)-1);
+ }
+ elsif($j == 1) {
+ $rank += 1;
+ push(@ign,$rank+$i-1);
+ #print FILE "; ";
+ }
+ }
+ print FILE "; Total ";
+ push(@pts,$rank);
+ }
+ print FILE "; \n";
+ }
+ print FILE "points ";
+ my $totalexo = 0;
+ my $total = 0;
+ my $nq = 0;
+ for my $i (0.. $#{ $points[$interro] }) {
+ print FILE "; $points[$interro][$i] ";
+ push(@min,$points[$interro][$i]);
+ push(@max,0);
+ push(@somme,0);
+ $totalexo += $points[$interro][$i];
+ $total += $points[$interro][$i];
+ $nq++;
+ if((grep {$_ == $i} @pts) > 0) {
+ if($nq > 1) {
+ print FILE "; $totalexo ";
+ }
+ push(@min,$totalexo);
+ push(@max,0);
+ push(@somme,0);
+ $totalexo = 0;
+ $nq = 0;
+ }
+ }
+ print FILE "; $total ";
+ push(@min,$total);
+ push(@max,0);
+ push(@somme,0);
+ print FILE "\n";
+
+ my @sortednotes = sort sort_alpha (keys %corr_nom);
+ #print "@sortednotes";
+ #my $somme = 0;
+ my $nombre_eleves = 0;
+ for my $i (0.. $#sortednotes) {
+ my $np = $sortednotes[$i];
+ $np =~ s/\n/ /;
+ print FILE $np;
+ my @ligne = @{ $corr_nom{$sortednotes[$i]} };
+ if($ligne[$interro] eq "Absent") {
+ print FILE "; Absent","; "x (scalar(@{ $tablequestion[$interro] })+$table[$interro][0]);
+ }
+ else {
+ my @ligneo = @{ $ligne[$interro] };
+ my $totalexo = 0;
+ my $total = 0;
+ $nombre_eleves++;
+ my $k = 0;
+ my $nq = 0;
+ foreach my $l (0.. $#ligneo ) {
+ my $val = sprintf("%.0f",4.*$ligneo[$l]*$points[$interro][$l]/100)/4;
+ print FILE "; ",$val;
+ if($min[$k] > $val) {
+ $min[$k] = $val;
+ }
+ if($max[$k] < $val) {
+ $max[$k] = $val;
+ }
+ $somme[$k] += $val;
+ $k++;
+ $totalexo += $val;
+ $total += $val;
+ $nq++;
+ if((grep {$_ == $l} @pts) > 0) {
+ if($nq > 1) {
+ print FILE "; $totalexo ";
+ }
+ if($min[$k] > $totalexo) {
+ $min[$k] = $totalexo;
+ }
+ if($max[$k] < $totalexo) {
+ $max[$k] = $totalexo;
+ }
+ $somme[$k] += $totalexo;
+ $k++;
+ $totalexo = 0;
+ $nq = 0;
+ }
+ }
+ print FILE "; $total ";
+ if($min[$k] > $total) {
+ $min[$k] = $total;
+ }
+ if($max[$k] < $total) {
+ $max[$k] = $total;
+ }
+ $somme[$k] += $total;
+ $k++;
+ }
+ print FILE "\n";
+ }
+ print FILE "Moyenne";
+ for my $l (0.. $#somme) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "; ".sprintf("%.0f",4.*$somme[$l]/$nombre_eleves)/4;
+ }
+ print FILE "\n";
+ print FILE "Min";
+ for my $l (0.. $#min) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "; $min[$l]";
+ }
+ print FILE "\n";
+ print FILE "Max";
+ for my $l (0.. $#max) {
+ next if((grep {$_ == $l} @ign) > 0);
+ print FILE "; $max[$l]";
+ }
+ #print FILE "Moyenne & \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0],"}{c||}{ }";
+ #my $moyenne = sprintf("%.0f",4.*$somme/$nombre_eleves)/4;
+ #print FILE " & $moyenne\\\\\n";
+ print FILE "\n";
+ print FILE "\n\n\n";
+ }
+ close FILE;
+}
+
+if(-e $fichier) {
+ &charger();
+}
+
+sub choisir_interro() {
+ while(1) {
+ my $i = 1;
+ my $var;
+ my $message = '';
+ foreach $var ( @interros ) {
+ $message .= $i++.') '.$var."\n";
+ }
+ print $message;
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $interro_courante = $var-1;
+ last;
+ }
+}
+
+sub editer_eleve() {
+ my $eleve;
+ while(1) {
+ open COL, "| column";
+ my $i = 1;
+ my @eleves = sort sort_alpha keys(%corr_nom);
+ foreach my $eleve_l (@eleves) {
+ my $eleve_lm = $eleve_l;
+ $eleve_lm =~ s/\n/ /;
+ print COL $i++.") ".$eleve_lm."\n";
+ }
+ print COL $i.") Annuler\n";
+ close COL;
+ my $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ elsif( $var == $i ) {
+ return;
+ }
+ $eleve = $eleves[$var-1];
+ last;
+ }
+ my $notes_c = ${$corr_nom{$eleve}}[$interro_courante];
+ if($notes_c == "Absent") {
+ print "Absent à ".$interros[$interro_courante]."\n";
+ }
+ &entrer_notes($interro_courante,$eleve);
+}
+
+sub quitter() {
+ exit 0;
+}
+
+my @actions = ("Ajouter une interro", "Ajouter un élève");
+my @actions_f = (\&ajout_interro,
+ \&ajout_eleve,
+ \&choisir_interro,
+ \&editer_eleve,
+ \&definir_exos,
+ \&entrer_bareme,
+ \&entrer_notes,
+ \&sauver,
+ \&export_latex,
+ \&export_csv,
+ \&quitter,
+ );
+while(1) {
+ if(scalar(@interros)>0) {
+ $actions[2] = "Choisir une interro";
+ $actions[3] = "Éditer les notes d'un élève";
+ $actions[4] = "Définir les exercices de l'interro";
+ $actions[5] = "Définir le barême de l'interro";
+ $actions[6] = "Entrer les notes de l'interro";
+ $actions[7] = "Sauvegarder";
+ $actions[8] = "Exporter en LaTeX";
+ $actions[9] = "Exporter en CSV";
+ }
+
+
+ my $action;
+ while(1) {
+ my $i = 1;
+ my $var;
+ my @vart = ( @actions, 'Quitter' );
+ my $message = 'Interro sélectionnée : '.$interros[$interro_courante]."\n";
+ foreach $var ( @vart ) {
+ $message .= $i++.') '.$var."\n";
+ }
+ print $message;
+ $var = <STDIN>;
+ chop($var);
+ if(/\D/ || $var < 1 || $var > $i) {
+ print "Mauvaise entrée\n";
+ next;
+ }
+ $action = $actions_f[$var-1];
+ last;
+ }
+ &{$action}($interro_courante);
+}
+
+#&export_latex();
--- /dev/null
+#!/usr/bin/env sh
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+if [ "$*" = "" ]; then
+ echo "`basename $0` academie login password"
+ echo "où academie est remplacé dans:"
+ echo "https://bv.ac-academie.fr/iprof/ServletIprof"
+ exit 1
+fi
+
+iPROF="https://bv.ac-$1.fr/iprof/ServletIprof"
+login="$2"
+mdp="$3"
+
+numu=`curl $iPROF 2>/dev/null | grep numu| sed -e "s/.*value='\(.*\)'.*/\1/"`
+
+session=`curl -d 'codeTraitement=Authentification&typeConnexion=ENS&codeProfil=E&numu='$numu'&login='$login'&motDePasse='$mdp $iPROF 2>/dev/null | grep "value='CourrierE'" | sed -e "s/.*action='\/iprof\/ServletIprof\;\([^']*\)'.*/\1/"`
+
+curl -d 'codeTraitement=CourrierE' $iPROF';'$session 2>/dev/null 1>&2
+
+M=`mktemp`
+
+curl -d 'codeThemeEnCours=tous&codeTraitement=CourrierE&numu='$numu'&messageID=&action=&typeDossier=recu&dossierEnCours=ca' $iPROF';'$session 2>/dev/null | grep "document.f_message.messageID.value" | sed -e "s/.*messageID.value='<\([^>]*\)>'.*texteSouligne\">\([^<]*\)<.*texte\"[^>]*>\([^<]*\)<.*/\1 \3/g" >> $M
+
+Nouveau=`wc -l $M | cut -d" " -f1`
+Ancien=`wc -l $HOME/.iprof | cut -d" " -f1`
+
+if [ "x"$Nouveau != "x"$Ancien ];then
+ echo "Du nouveau sur I-prof"
+ rm $HOME/.iprof
+ cp $M $HOME/.iprof
+fi
+rm -f $M
--- /dev/null
+#!/bin/bash
+
+## Original script adapted from source: http://wiki.mutt.org/?ConfigTricks/CheckAttach
+##
+## Adapted by Ismaël Bouya (http://www.normalesup.org/~bouya/) to make it so
+## that retrying to send the email shortly after will work
+##
+## Edit muttrc to have this line:
+## set sendmail = "/usr/local/bin/mutt_check_attachment_before_send.sh /usr/lib/sendmail -oem -oi"
+##
+
+
+## Attachment keywords that the message body will be searched for:
+KEYWORDS='attach|joint|voici|voil'
+
+## Check that sendmail or other program is supplied as first argument.
+if [ ! -x "$1" ]; then
+ echo "Usage: $0 </path/to/mailprog> <args> ..."
+ echo "e.g.: $0 /usr/sbin/sendmail -oem -oi"
+ exit 2
+fi
+
+## Save msg in file to re-use it for multiple tests.
+TMPFILE=`mktemp -t mutt_checkattach.XXXXXX` || exit 2
+cat > "$TMPFILE"
+
+## Define test for multipart message.
+function multipart {
+# grep -q '^Content-Type: multipart' "$TMPFILE"
+ grep -q '^Content-Disposition: attachment' "$TMPFILE"
+}
+
+## Define test for keyword search.
+function word-attach {
+ grep -v '^>' "$TMPFILE" | grep -E -i -q "$KEYWORDS"
+}
+
+## Header override.
+function header-override {
+ grep -i -E "^X-attached: *none *$" "$TMPFILE"
+}
+
+function ask {
+ terminal=`tty`
+ dialog --yesno "Envoyer malgré la pièce jointe manquante ?" 5 30 < $terminal > $terminal
+ }
+
+#Verifie qu'on a essayé de l'envoyer y'a moins d'une minute
+function file_last {
+ if [ ! -e $HOME/.mutt_attach ]; then
+ return 0
+ fi
+ valeur=`echo \`date +%s\`-\`stat -c %Y $HOME/.mutt_attach\`'<60' | bc`
+ return $valeur
+}
+## FINAL DECISION:
+if multipart || ! word-attach || header-override || ! file_last ; then
+ "$@" < "$TMPFILE"
+ EXIT_STATUS=$?
+ if [ ! -s $HOME/.mutt_attach ]; then
+ rm -f $HOME/.mutt_attach
+ fi
+else
+ echo "No file was attached but a search of the message text suggests there should be one. Add a header \"X-attached: none\" to override this check if no attachment is intended."
+ echo "You can also send the email again in the next minute."
+ EXIT_STATUS=1
+ touch $HOME/.mutt_attach
+fi
+
+## Delete the temporary file.
+rm -f "$TMPFILE"
+
+## That's all folks.
+exit $EXIT_STATUS
+
--- /dev/null
+#!/usr/bin/env perl
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+use BibTeX::Parser;
+use IO::File;
+use utf8;
+use strict;
+use open ':utf8';
+
+sub parse_config_file {
+ my ($config_line, $Name, $Value, $Config);
+ (my $File, $Config) = @_;
+ if (!open (CONFIG, "$File")) {
+ print "ERROR: Config file not found : $File";
+ exit(0);
+ }
+ my $multiline = 0;
+
+ while (<CONFIG>) {
+ $config_line=$_;
+ chop ($config_line);
+ $config_line =~ s/^\s*//;
+ $config_line =~ s/\s*$//;
+ if ( ($config_line !~ /^#/) && ($config_line ne "") ){
+ if ($multiline) {
+ $$Config{$Name} =~ s/\\$//;
+ $$Config{$Name} .= $config_line;
+ } else {
+ ($Name, $Value) = split (/\s*=\s*/, $config_line);
+ $Value =~ s/^~/$ENV{"HOME"}/;
+ $$Config{$Name} = $Value;
+ }
+ $multiline = ($$Config{$Name} =~ /\\$/);
+ }
+ }
+ close(CONFIG);
+}
+
+my %Config;
+&parse_config_file ($ENV{"HOME"}."/.parse_bibtex_html.rc", \%Config);
+
+my $biblio = $Config{"biblio"};
+my $entete = $Config{"entete"};
+my $avant = $Config{"avant"};
+my $milieu = $Config{"milieu"};
+my $apres = $Config{"apres"};
+my $html = $Config{"html"};
+
+my $dossier = $Config{"dossier"};
+my $dossierweb = $Config{"dossier_web"};
+
+# http://webdesign.about.com/library/bl_htmlcodes.htm
+sub echap {
+ my $t = shift or return;
+ $t =~ s/&/&/g;
+ $t =~ s/</</g;
+ $t =~ s/>/>/g;
+
+ $t =~ s/--/—/g;
+
+ $t =~ s/{?\\'a}?/á/g;
+ $t =~ s/{?\\`a}?/à/g;
+ $t =~ s/{?\\"a}?/ä/g;
+
+ $t =~ s/{?\\r A}?/Å/g;
+
+ $t =~ s/{?\\'e}?/é/g;
+ $t =~ s/{?\\`e}?/è/g;
+ $t =~ s/{?\\'E}?/É/g;
+ $t =~ s/{?\\"e}?/ë/g;
+
+ $t =~ s/{?\\\^i}?/î/g;
+ $t =~ s/{?\\"i}?/ï/g;
+
+ $t =~ s/{?\\"o}?/ö/g;
+ $t =~ s/{?\\"o}?/ö/g;
+ $t =~ s/{?\\=o}?/ō/g;
+ $t =~ s/{?\\o}?/ø/g;
+
+ $t =~ s/{?\\"u}?/ü/g;
+ $t =~ s/{?\\'u}?/ú/g;
+
+ $t =~ s/{?\\~n}?/ñ/g;
+
+ $t =~ s/{?\\c{?c}?}? ?/ç/g;
+ $t =~ s/{?\\'{?c}?}? ?/ć/g;
+
+ $t =~ s/{?\\v{? ?s}?}? ?/š/g;
+
+ $t =~ s/{?\^({[^}]+}|.)}?/<sup>$1<\/sup>/g;
+ $t =~ s/{(.*)}/$1/g;
+ return $t;
+}
+
+open F, ">".$milieu;
+opendir(DIR, $dossier);
+my @FILES = readdir(DIR);
+my $fh = IO::File->new($biblio);
+my $parser = BibTeX::Parser->new($fh);
+print F "\t<ul>\n";
+my %liste = ();
+
+while (my $entry = $parser->next ) {
+ if ($entry->parse_ok) {
+ my $type = $entry->type;
+ my $title = $entry->field("title");
+ my $key = $entry->key;
+ my @authors = $entry->author;
+# my @editors = $entry->editor;
+ my $auth = "";
+ my @authors_sort = ();
+ foreach my $author (@authors) {
+ $auth .= (($author->first)?$author->first. " ":"") .(($author->von)?$author->von." ":"") . (($author->last)?$author->last:"") . ", ";
+ push(@authors_sort,$author->last);
+ }
+ @authors_sort = sort {lc $a cmp lc $b} @authors_sort;
+ my $cle_sort = shift(@authors_sort);
+ $auth = substr $auth, 0 , -2;
+ my $suffix = '(\.|_)';
+ my @match = grep(/^$key$suffix/,@FILES);
+ my $i = 1;
+ my $chaine = "\t\t<li>";
+ $auth = echap $auth;
+ $title = echap $title;
+ if($auth =~ m/\\/ || $title =~ m/\\/) {
+ warn "Unparsed item : $auth, $title";
+ }
+ $chaine .= "<span class='biblio_titre'>".$title."</span><br />".$auth."<br />\n";
+ @match = sort {lc $a cmp lc $b} @match;
+ foreach my $item (@match) {
+ $chaine .= "\t\t\t<a href='".$dossierweb.$item."'>fichier ".$i++."</a> \n";
+ }
+ $chaine .="\t\t\t<a id='".$key."' href='#".$key."' class='bibtex'>BibTeX</a>\n";
+ my $raw = $entry->raw_bibtex;
+ $raw =~ s/&/&/g;
+ $chaine .= "\t\t\t<pre class='bibtex'>".$raw."</pre>\n";
+ $chaine .= "\t\t\t</li>\n";
+ $liste{$cle_sort." ".$key} = $chaine;
+ } else {
+ warn "Error parsing file: " . $entry->error;
+ }
+ }
+
+foreach my $key (sort keys %liste) {
+ print F $liste{$key};
+}
+
+print F "\t\t</ul>";
+close F;
+
+exec "cat $entete $avant $milieu $apres 1> $html" or die "$!\n";
--- /dev/null
+#!/usr/bin/env perl
+# Inspired by Aaron . Ciuffo (at gmail)
+
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+use strict;
+
+use Email::MIME;
+use DateTime;
+use Digest::MD5 qw(md5_hex);
+
+use vars qw(
+ $filter_attachments_file
+ $email $email_parsed
+ @email_parts
+ @new_email_parts
+ $mail_was_modified
+ @removed_files
+);
+
+@removed_files = ();
+@new_email_parts = ();
+$mail_was_modified = 0;
+my @mailr = ();
+my $premiere = 1;
+my $premiere_ligne;
+foreach( <STDIN> ) {
+ my $ligne = $_;
+ if($ligne =~ m/^From/ && $premiere) {
+ $premiere_ligne = $ligne;
+ next;
+ }
+ $premiere = 0;
+ if($ligne =~ m/^Content-Disposition: attachment; filename/) {
+ my $fichier = $ligne;
+ chomp($fichier);
+ if($ligne =~ m/^Content-Disposition: attachment; filename\*/) {
+ $fichier =~ s/^.*filename\*.*''([^\s]*)\s?.*$/\1/;
+ $fichier =~ s/%2E/./g;
+ $fichier =~ s/%20/_/g;
+ $fichier =~ s/%//g;
+ $ligne =~ s/filename\*.*''([^ \n\r\t]*)/filename="$fichier"/;
+ }
+ else {
+ $fichier =~ s/^.*filename="?(.*[^"])"?.*$/\1/;
+ $fichier =~ s/ /_/g;
+ $fichier =~ s/[^-a-zA-Z0-9_.]/_/g;
+ $ligne =~ s/filename=.*$/filename="$fichier"/;
+ }
+ }
+ push(@mailr,$ligne);
+}
+$email = join( '',@mailr );
+
+$filter_attachments_file = $ENV{HOME}."/.attachements/".DateTime->now(time_zone => 'local')->strftime('%Y%m%d_%H%M%S')."_".substr(md5_hex($email),0,5)."/" ;
+
+$email_parsed = Email::MIME->new( $email );
+if($email_parsed->content_type =~m[^multipart/encrypted]) {
+ print STDOUT $premiere_ligne;
+ print STDOUT $email_parsed->as_string;
+ exit;
+}
+
+my @parts = $email_parsed->parts;
+my $extension = "text/";
+$email_parsed->walk_parts(sub {
+ my ($part) = @_;
+ if ($part->content_type =~m[text/plain]i){
+ $extension = "text/plain";
+ return;
+ }
+});
+
+sub parse_parts {
+ my ($part) = @_;
+ if($part->content_type =~ m[$extension]i or $part->content_type =~ m[application/pgp-signature]i or !$part->content_type) {
+ push( @new_email_parts, $part);
+ }
+ elsif ($part->content_type =~ m[multipart/mixed]i) {
+ foreach( $part->subparts ) {
+ parse_parts($_);
+ }
+ }
+ else {
+ if(length($part->body) == 0) {
+ return;
+ }
+ if(!$mail_was_modified) {
+ mkdir $filter_attachments_file;
+ $mail_was_modified = 1;
+ push( @removed_files, "keepdir://".$filter_attachments_file);
+ }
+ my $fichier = $part->filename(1);
+ $fichier =~ s/ /\\ /g;
+ push( @removed_files, "file://".$filter_attachments_file.$fichier." ".$part->content_type );
+ open(my $out, '>:raw', $filter_attachments_file.$part->filename(1));
+ print $out $part->body;
+ close($out);
+ }
+}
+foreach( $email_parsed->subparts ) {
+ parse_parts($_);
+}
+
+if ($mail_was_modified)
+{
+ my $remove_string = "The following attachments were removed:";
+ $remove_string = $remove_string."\n".$_ foreach (@removed_files);
+ $remove_string = $email_parsed->debug_structure."\n".$remove_string;
+ push (@new_email_parts, Email::MIME->create(
+ attributes => {
+ content_type => "text/plain",
+ disposition => "attachment",
+ charset => "US-ASCII",
+ filename => "removed_attachments.txt"
+ },
+ body => $remove_string,
+ ) );
+ $email_parsed->parts_set( \@new_email_parts );
+ $email_parsed->content_type_set( 'multipart/mixed' );
+ $email = $email_parsed->as_string;
+
+}
+
+print STDOUT $premiere_ligne;
+print STDOUT $email;
+
+
--- /dev/null
+#!/usr/bin/env python3
+# The MIT License (MIT)
+#
+# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import sys
+import unicodedata
+
+string = sys.stdin.readline().strip()
+for char in string:
+ print("U+%04x" % ord(char), end="")
+ if (ord(char) < 31):
+ print()
+ else:
+ print(" " + char + " ", end="")
+ try:
+ print(unicodedata.name(char), "["+unicodedata.category(char)+"]")
+ decomposition = unicodedata.decomposition(char).split(" ")
+ if len(decomposition) > 1:
+ for subchar in decomposition:
+ try:
+ unicode_char = chr(int(subchar, 16))
+ print(" U+%s" % subchar, unicodedata.name(unicode_char))
+ except ValueError:
+ print(" " + subchar)
+ except:
+ pass