summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2015-01-13 23:35:48 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2015-01-13 23:35:48 +0100
commit5172ecf855078938b00e9ac7f8dee2c2676f6e53 (patch)
tree586d6285d6d2aeb66a7a2458e01541ed78c8e174
downloadPublic-5172ecf855078938b00e9ac7f8dee2c2676f6e53.tar.gz
Public-5172ecf855078938b00e9ac7f8dee2c2676f6e53.tar.zst
Public-5172ecf855078938b00e9ac7f8dee2c2676f6e53.zip
Commit initial
-rwxr-xr-xcmdtemp68
-rwxr-xr-xcolor-bash53
-rwxr-xr-xcomptes446
-rwxr-xr-xexecurl44
-rwxr-xr-xgen_html_documents135
-rwxr-xr-xgit-latexdiff28
-rwxr-xr-xinterrogations739
-rwxr-xr-xmails_iprof53
-rwxr-xr-xmutt_check_attachment75
-rwxr-xr-xparse_bibtex_html172
-rwxr-xr-xremove_attachements149
-rwxr-xr-xunicode_chars45
12 files changed, 2007 insertions, 0 deletions
diff --git a/cmdtemp b/cmdtemp
new file mode 100755
index 0000000..37bcc82
--- /dev/null
+++ b/cmdtemp
@@ -0,0 +1,68 @@
1#!/usr/bin/env bash
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24# cmdtemp
25# List commands
26# cmdtemp <n>
27# Execute command number <n>
28# cmdtemp <-n>
29# Delete command number <n>
30# cmdtemp <...>
31# Save command
32
33
34function is_negative() {
35 s=$(echo $1 | tr -d 0-9)
36 if [ "$s" == "-" ]; then
37 return 0
38 else
39 return 1
40 fi
41}
42
43function is_integer() {
44 s=$(echo $1 | tr -d 0-9)
45 if [ -z "$s" ]; then
46 return 0
47 else
48 return 1
49 fi
50}
51
52if [ $# -eq 0 ]; then
53 cat -n $HOME/.cmdtemp
54 exit
55fi
56
57if is_integer "$1"; then
58 ligne="$1"
59 shift
60 commande=`awk "FNR == $ligne" $HOME/.cmdtemp`
61 echo "*** "$commande
62 eval $commande
63elif is_negative "$1"; then
64 s=$(echo $1 | tr -d '-')
65 sed -i -e $s"d" $HOME/.cmdtemp
66else
67 echo "$*" >> $HOME/.cmdtemp
68fi
diff --git a/color-bash b/color-bash
new file mode 100755
index 0000000..0331293
--- /dev/null
+++ b/color-bash
@@ -0,0 +1,53 @@
1#!/usr/bin/env bash
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24
25echo " Bg | Fg"
26printf -- '-%.0s' {1..122} ; echo ""
27for((bg=40;bg<=47;bg++)); do
28 for int in 0 60; do
29 for b in 0 1 4 7 9; do
30 if [ $bg -gt 40 -a "(" $b = 7 -o $b = 9 -o $b = 4 ")" ]; then
31 continue
32 fi
33
34 if [ $b = "0" ]; then
35 echo -en "\033[0m""ESC[$((${bg}+${int}))m"
36 if [ $int = 0 ]; then
37 echo -n " "
38 fi
39 echo -n "| "
40 else
41 echo -en " | "
42 fi
43
44 for((fg=30;fg<=37;fg++)); do
45 echo -en "\033[$((${bg}+${int}))m\033[${b};${fg}m [${b};${fg}m"
46 echo -en "\033[$((${bg}+${int}))m\033[${b};$((${fg}+60))m [${b};$((${fg}+60))m"
47 done
48
49 echo -e "\033[0m"
50 done
51 done
52 printf -- '-%.0s' {1..122} ; echo ""
53done
diff --git a/comptes b/comptes
new file mode 100755
index 0000000..0fbacf2
--- /dev/null
+++ b/comptes
@@ -0,0 +1,446 @@
1#!/usr/bin/en perl
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24use Switch;
25use strict;
26
27my $file = "comptes.data";
28
29my @actions=('Ajouter un participant');
30my %participants = ();
31my @transactions = ();
32my @descriptions = ();
33my $evenement_def;
34my $remboursements = "";
35
36if($#ARGV==0) {
37 open FILE, $ARGV[0] || die "Impossible de lire le fichier";
38 $evenement_def = <FILE>;
39 chomp($evenement_def);
40 while(my $noms = <FILE>) {
41 if($noms eq "\n") { last; }
42 my ($numero,$nom) = split(/ /,$noms,2);
43 chomp($nom);
44 $participants{$nom} = $numero;
45 }
46 while(my $transaction = <FILE>) {
47 if($transaction eq "\n") { last; }
48 chomp($transaction);
49 push(@transactions,$transaction);
50 my $description = <FILE>;
51 chomp($description);
52 push(@descriptions,$description);
53 }
54 $file = $ARGV[0];
55}
56
57GLOBALE: while(1) {
58 if(keys(%participants)>0) {
59 $actions[1]="Ajouter une dépense";
60 $actions[2]="Enregistrer";
61 }
62 if(scalar(@transactions)>0) {
63 $actions[3]="Voir les dépenses de quelqu'un";
64 $actions[2]="Enregistrer";
65 $actions[4]="Equilibrage";
66 $actions[5]="Voir une transaction";
67 }
68
69 my $action;
70 while(1) {
71 my $i = 1;
72 my $var;
73 my @vart = ( @actions, 'Sortir' );
74 my $message = '';
75 foreach $var ( @vart ) {
76 $message .= $i++.') '.$var."\n";
77 }
78 print $message;
79 $var = <STDIN>;
80 chop($var);
81 if(/\D/ || $var < 1 || $var > $i) {
82 print "Mauvaise entrée\n";
83 next;
84 }
85 $action = $vart[$var-1];
86 last;
87 }
88 switch ($action) {
89 case "Ajouter un participant" {
90 print "Nom du participant\n";
91 my $participant = <STDIN>;
92 chomp($participant);
93 $participants{$participant} = keys(%participants)+1;
94 }
95 case "Ajouter une dépense" {
96 print "Qui a payé ?\n";
97 my $paye;
98 while(1) {
99 my $i = 1;
100 my $var;
101 my @vart = ( keys(%participants), "Annuler" );
102 foreach $var ( @vart ) {
103 print $i++.') '.$var."\n";
104 }
105 $var = <STDIN>;
106 chop($var);
107 if(/\D/ || $var < 1 || $var > $i) {
108 print "Mauvaise entrée\n";
109 next;
110 }
111 $paye = $vart[$var-1];
112 last;
113 }
114 if($paye eq "Annuler") {
115 next GLOBALE;
116 }
117 print "Quoi ?\n";
118 my $description = <STDIN>;
119 chomp($description);
120 print "Combien ?\n";
121 my $prix = <STDIN>;
122 chomp($prix);
123 print "Pour qui ?\n";
124 my $repartition = "";
125 my $total_parts = 0;
126 DESTS: while(1) {
127 my $dest;
128 while(1) {
129 my $i = 1;
130 my $var;
131 my @vart = ( keys(%participants), "Ajouter à tous", "Fini" );
132 foreach $var ( @vart ) {
133 print $i++.') '.$var."\n";
134 }
135 $var = <STDIN>;
136 chop($var);
137 if(/\D/ || $var < 1 || $var > $i) {
138 print "Mauvaise entrée\n";
139 next;
140 }
141 $dest = $vart[$var-1];
142 last;
143 }
144 switch($dest) {
145 case "Fini" {
146 if($repartition eq "") { print "Annulé\n"; }
147 elsif($total_parts == 0) {
148 print "Le nombre total de parts est nul, il faut en ajouter !\n";
149 next DESTS;
150 }
151 else {
152 push(@transactions, $participants{$paye}.' '.$prix.$repartition);
153 push(@descriptions, $description);
154 }
155 last DESTS;
156 }
157 case "Ajouter à tous" {
158 print "Nombre de parts ?\n";
159 my $parts = <STDIN>;
160 chomp($parts);
161 if(!($parts == 0)) {
162 foreach my $participant (keys(%participants)) {
163 $repartition .= ' '.$participants{$participant}.':'.scalar($parts);
164 $total_parts += scalar($parts);
165 }
166 }
167 }
168 else {
169 print "Nombre de parts ?\n";
170 my $parts = <STDIN>;
171 chomp($parts);
172 if(!($parts == 0)) {
173 $repartition .= ' '.$participants{$dest}.':'.scalar($parts);
174 $total_parts += scalar($parts);
175 }
176 }
177 }
178 }
179 }
180 case "Voir les dépenses de quelqu'un" {
181 my $personne;
182 while(1) {
183 my $i = 1;
184 my $var;
185 my @vart = ( keys(%participants), "Annuler" );
186 foreach $var ( @vart ) {
187 print $i++.') '.$var."\n";
188 }
189 $var = <STDIN>;
190 chop($var);
191 if(/\D/ || $var < 1 || $var > $i) {
192 print "Mauvaise entrée\n";
193 next;
194 }
195 $personne = $vart[$var-1];
196 last;
197 }
198 if($personne eq "Annuler") {
199 next GLOBALE;
200 }
201 my $depenses = 0;
202 my $frais = 0;
203 foreach my $transaction (@transactions) {
204 my @table_trans = split(/ /,$transaction);
205 my $payeur = shift(@table_trans);
206 my $prix = shift(@table_trans);
207 if($payeur == $participants{$personne}) {
208 $depenses += $prix;
209 }
210 my $parts = 0;
211 my $frac = 0;
212 my $repartition;
213 foreach $repartition (@table_trans) {
214 my ($pers,$part) = split(/:/,$repartition);
215 if($pers == $participants{$personne}) {
216 $frac += $part;
217 }
218 $parts += $part;
219 }
220 $frais += $prix*$frac/$parts;
221 }
222 print $personne." a payé ".$depenses." EUR\n";
223 print "et a pour ".sprintf("%.2f",$frais)." EUR de frais au total.\n";
224 print "Il a donc un solde de ".sprintf("%.2f",$depenses-$frais)." EUR\n";
225 my $pause = <STDIN>;
226 }
227 case "Voir une transaction" {
228 my $transaction;
229 while(1) {
230 my $i = 1;
231 my $var;
232 my @vart = ( @descriptions, "Annuler" );
233 foreach $var ( @vart ) {
234 print $i++.') '.$var."\n";
235 }
236 $var = <STDIN>;
237 chop($var);
238 if(/\D/ || $var < 1 || $var > $i) {
239 print "Mauvaise entrée\n";
240 next;
241 }
242 $transaction = $var-1;
243 last;
244 }
245 my @table_trans = split(/ /,$transactions[$transaction]);
246 my $payeur = shift(@table_trans);
247 my $prix = shift(@table_trans);
248 my $Tparts = 0;
249 my $repartition;
250 my %parts;
251 foreach my $pers (keys(%participants)) {
252 if($payeur == $participants{$pers}) {
253 print $descriptions[$transaction]." (payé par ".$pers."), ".$prix." EUR\n";
254 last
255 }
256 }
257 foreach $repartition (@table_trans) {
258 my ($pers,$part) = split(/:/,$repartition);
259 $Tparts += $part;
260 $parts{$pers} += $part;
261 }
262 foreach my $pers (keys(%participants)) {
263 if(!exists $parts{$participants{$pers}}) {
264 next;
265 }
266 print $pers.", ".$parts{$participants{$pers}}." part(s), soit ". $prix*$parts{$participants{$pers}}/$Tparts." EUR\n";
267 }
268 my $pause = <STDIN>;
269 }
270 case "Enregistrer" {
271 print "Nom de l'événement ?";
272 if(!($evenement_def eq "")) {
273 print " [".$evenement_def."]";
274 }
275 print "\n";
276 my $evenement = <STDIN>;
277 chomp($evenement);
278 if($evenement eq "") {
279 $evenement = $evenement_def;
280 }
281 open FILE, ">".$file;
282 print FILE $evenement."\n";
283 my $key;
284 foreach $key (keys(%participants)) {
285 print FILE $participants{$key}." ".$key."\n";
286 }
287 print FILE "\n";
288 for(my $i=0;$i<scalar(@transactions);$i++) {
289 print FILE $transactions[$i]."\n";
290 print FILE $descriptions[$i]."\n";
291 }
292 print FILE "\n";
293 print FILE $remboursements;
294 close FILE;
295 }
296 case "Equilibrage" {
297 my %Tdepenses = ();
298 my %Tfrais = ();
299 my %Tsolde = ();
300 $remboursements = "";
301 foreach my $Ttransaction (@transactions) {
302 my @Ttable_trans = split(/ /,$Ttransaction);
303 my $Tpayeur = shift(@Ttable_trans);
304 my $Tprix = shift(@Ttable_trans);
305 $Tdepenses{$Tpayeur} = $Tdepenses{$Tpayeur} + $Tprix;
306 my $Tparts = 0;
307 my $Tfrac = 0;
308 my $Trepartition;
309 foreach $Trepartition (@Ttable_trans) {
310 my ($Tpers,$Tpart) = split(/:/,$Trepartition);
311 $Tparts += $Tpart;
312 }
313 foreach $Trepartition (@Ttable_trans) {
314 my ($Tpers,$Tpart) = split(/:/,$Trepartition);
315 $Tfrais{$Tpers} = $Tfrais{$Tpers} + $Tprix*$Tpart/$Tparts;
316 }
317 }
318 foreach my $Tpersonne (keys(%participants)) {
319 my $numero = $participants{$Tpersonne};
320 $Tsolde{$Tpersonne} = sprintf("%.2f",$Tdepenses{$numero}-$Tfrais{$numero});
321 print $Tpersonne." a un solde de ".$Tsolde{$Tpersonne}." EUR\n";
322 }
323 my $pause = <STDIN>;
324 print "Y-a-t-il des remboursements plus aisés ?\n";
325 my $ouinon;
326 while(1) {
327 my $i = 1;
328 my $var;
329 my @vart = ( "Oui", "Non" );
330 foreach $var ( @vart ) {
331 print $i++.') '.$var."\n";
332 }
333 $var = <STDIN>;
334 chop($var);
335 if(/\D/ || $var < 1 || $var > $i) {
336 print "Mauvaise entrée\n";
337 next;
338 }
339 $ouinon = $vart[$var-1];
340 last;
341 }
342 AISE: while($ouinon eq "Oui") {
343 print "Qui ?\n";
344 my $personne;
345 while(1) {
346 my $i = 1;
347 my $var;
348 my @vart = ( keys(%participants), "Fini" );
349 foreach $var ( @vart ) {
350 print $i++.') '.$var."\n";
351 }
352 $var = <STDIN>;
353 chop($var);
354 if(/\D/ || $var < 1 || $var > $i) {
355 print "Mauvaise entrée\n";
356 next;
357 }
358 $personne = $vart[$var-1];
359 last;
360 }
361 if($personne eq "Fini") { last AISE; }
362 print "Avec qui ?\n";
363 my $personneb;
364 while(1) {
365 my $i = 1;
366 my $var;
367 my @vart = ( keys(%participants), "Annuler" );
368 foreach $var ( @vart ) {
369 print $i++.') '.$var."\n";
370 }
371 $var = <STDIN>;
372 chop($var);
373 if(/\D/ || $var < 1 || $var > $i) {
374 print "Mauvaise entrée\n";
375 next;
376 }
377 $personneb = $vart[$var-1];
378 last;
379 }
380 if($personneb eq "Annuler") { next AISE; }
381 if($Tsolde{$personne}*$Tsolde{$personneb}<0) {
382 my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb;
383 my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb;
384 my $inf = (abs($Tsolde{$personne})<abs($Tsolde{$personneb}))?abs($Tsolde{$personne}):abs($Tsolde{$personneb});
385 $remboursements .= $pers_inf." doit ".$inf." EUR à ".$pers_sup."\n";
386 $Tsolde{$pers_inf} += $inf;
387 $Tsolde{$pers_sup} -= $inf;
388 }
389 }
390 # Une boucle pour détecter si on a des couples qui s'annulent mutuellement
391 COUPLE: foreach my $personne (keys(%participants)) {
392 if($Tsolde{$personne} == 0) { next; }
393 foreach my $personneb (keys(%participants)) {
394 if($Tsolde{$personneb} + $Tsolde{$personne} != 0) { next; }
395 my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb;
396 my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb;
397 my $val = abs($Tsolde{$personne});
398 $remboursements .= $pers_inf." doit ".$val." EUR à ".$pers_sup."\n";
399 $Tsolde{$pers_inf} += $val;
400 $Tsolde{$pers_sup} -= $val;
401 next COUPLE;
402 }
403 }
404 REMB: while(1) {
405 # On supprime les 0, et on fait deux hashs
406 my %Tneg = ();
407 my %Tpos = ();
408 foreach my $personne (keys(%Tsolde)) {
409 if($Tsolde{$personne} == 0) { delete $Tsolde{$personne}; }
410 elsif($Tsolde{$personne} < 0) { $Tneg{$personne} = $Tsolde{$personne}; }
411 elsif($Tsolde{$personne} > 0) { $Tpos{$personne} = $Tsolde{$personne}; }
412 }
413 if(keys(%Tneg) == 0) {
414 last REMB;
415 }
416 foreach my $neg (sort { $Tneg{$a} cmp $Tneg{$b} } keys %Tneg) {
417 my $max = 0;
418 my $positif = 0;
419 foreach my $pos (sort { $Tpos{$a} cmp $Tpos{$b} } keys %Tpos) {
420 if($Tpos{$pos} + $Tneg{$neg}>0) {
421 $positif = $pos;
422 last;
423 }
424 $max = $pos;
425 }
426 if(!($max eq 0)) {
427 $remboursements .= $neg." doit ".$Tsolde{$max}." EUR à ".$max."\n";
428 $Tsolde{$neg} += $Tsolde{$max};
429 delete $Tsolde{$max};
430 }
431 else {
432 $remboursements .= $neg." doit ".-$Tsolde{$neg}." EUR à ".$positif."\n";
433 $Tsolde{$positif} += $Tsolde{$neg};
434 delete $Tsolde{$neg};
435 }
436 next REMB;
437 }
438 }
439 print $remboursements;
440 my $pause = <STDIN>;
441 }
442 case "Sortir" {
443 last GLOBALE;
444 }
445 }
446}
diff --git a/execurl b/execurl
new file mode 100755
index 0000000..655d208
--- /dev/null
+++ b/execurl
@@ -0,0 +1,44 @@
1#!/usr/bin/env bash
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24
25# To be used together with remove_attachements script in procmail and urlview to
26# visualize and keep some attachements once they are removed from the email
27# Example urlview updated configuration:
28# 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\\ ]+(\\ |\\)?)+)
29# COMMAND execurl
30
31export chemin=x"$1"
32if [ "${chemin:0:8}" = "xfile://" ]; then
33 fichier="${1:7}"
34 fichierlu="${fichier//\\ / }"
35 if [ ! -f "$fichierlu" ]; then
36 exec run-mailcap "${fichierlu//.attachements/Mail/.attachements}"
37 else
38 exec run-mailcap "$fichierlu"
39 fi
40elif [ "${chemin:0:11}" = "xkeepdir://" ]; then
41 mv "${1:10}" "$HOME/Mail/.attachements/"
42else
43 exec w3m "$1"
44fi
diff --git a/gen_html_documents b/gen_html_documents
new file mode 100755
index 0000000..eb361ce
--- /dev/null
+++ b/gen_html_documents
@@ -0,0 +1,135 @@
1#!/usr/bin/env perl
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24use strict;
25use File::Basename;
26
27sub parse_config_file {
28 my ($config_line, $Name, $Value, $Config);
29 (my $File, $Config) = @_;
30 if (!open (CONFIG, "$File")) {
31 print "ERROR: Config file not found : $File";
32 exit(0);
33 }
34 my $multiline = 0;
35
36 while (<CONFIG>) {
37 $config_line=$_;
38 chop ($config_line);
39 $config_line =~ s/^\s*//;
40 $config_line =~ s/\s*$//;
41 if ( ($config_line !~ /^#/) && ($config_line ne "") ){
42 if ($multiline) {
43 $$Config{$Name} =~ s/\\$//;
44 $$Config{$Name} .= $config_line;
45 } else {
46 ($Name, $Value) = split (/\s*=\s*/, $config_line);
47 $Value =~ s/^~/$ENV{"HOME"}/;
48 $$Config{$Name} = $Value;
49 }
50 $multiline = ($$Config{$Name} =~ /\\$/);
51 }
52 }
53 close(CONFIG);
54}
55
56my %Config;
57&parse_config_file ($ENV{"HOME"}."/.gen_html_documents.rc", \%Config);
58
59my $entete = $Config{"entete"};
60my $avant = $Config{"avant"};
61my $milieu = $Config{"milieu"};
62my $apres = $Config{"apres"};
63my $html = $Config{"html"};
64
65my @ignore = split (/\s*,\s*/, $Config{"ignore"});
66my @ext = split (/\s*,\s*/, $Config{"ext"});
67
68my $documents = $Config{"documents"};
69my $droot = $Config{"dossier_web"};
70
71$Config{"dossiers"} =~ s/^"//;
72$Config{"dossiers"} =~ s/"$//;
73my %dossiers = split (/"?\s*,\s*"?/, $Config{"dossiers"});
74
75my ($dossier,$description);
76
77open F, ">".$milieu;
78
79while(($dossier,$description) = each(%dossiers)) {
80 opendir(DIR, $documents.$dossier) || warn $documents.$dossier." coulnd't be opened\n";
81 my @content = grep {$_ !~ /^\.\.?$/} readdir(DIR);
82 my @sorted = sort { lc($a) cmp lc($b) } @content;
83 closedir(DIR);
84
85 print F "<h3>".$description."</h3>\n";
86 print F "<ul>\n";
87 foreach my $subpath (grep { -d $documents.$dossier.'/'.$_} @sorted) {
88 subparse($dossier,$subpath,4);
89 }
90 foreach my $file (grep { -f $documents.$dossier.'/'.$_} @sorted) {
91 my($filename, $directories, $suffix) = fileparse($file,qr/\.[^\.]*/);
92 next if(!in_array(\@ext,lc($suffix)));
93 $filename =~ tr/_/ /;
94 print F "<li><a href='".$droot.$dossier.'/'.$file."'>".$filename."</a></li>\n";
95 }
96 print F "</ul>\n";
97 }
98
99sub subparse {
100 my $path = shift;
101 my $dossier = shift;
102 my $rang = shift;
103
104 opendir(DIR, $documents.$path."/".$dossier);
105 my @content = grep {$_ !~ /^\.\.?$/} readdir(DIR);
106 my @sorted = sort { lc($a) cmp lc($b) } @content;
107 closedir(DIR);
108
109 return if(in_array(\@ignore,$dossier));
110 my $dossierspace = $dossier;
111 $dossierspace =~ tr/_/ /;
112 print F "<li>".$dossierspace."\n";
113 print F "<ul>\n";
114 foreach my $subpath (grep { -d $documents.$path."/".$dossier.'/'.$_} @sorted) {
115 subparse($path."/".$dossier,$subpath,$rang+1);
116 }
117 foreach my $file (grep { -f $documents.$path."/".$dossier.'/'.$_} @sorted) {
118 my($filename, $directories, $suffix) = fileparse($file,qr/\.[^\.]*/);
119 next if(!in_array(\@ext,lc($suffix)));
120 $filename =~ tr/_/ /;
121 print F "<li><a href='".$droot.$path.'/'.$dossier.'/'.$file."'>".$filename."</a></li>\n";
122 }
123 print F "</ul></li>\n";
124 }
125
126sub in_array {
127 my ($arr,$search_for) = @_;
128 my %items = map {$_ => 1} @$arr; # create a hash out of the array values
129 return (exists($items{$search_for}))?1:0;
130 }
131
132close F;
133
134exec "cat $entete $avant $milieu $apres 1> $html" or die "$!\n";
135exec "chmod -R go=rX,u=rwX $documents"
diff --git a/git-latexdiff b/git-latexdiff
new file mode 100755
index 0000000..5d26d1b
--- /dev/null
+++ b/git-latexdiff
@@ -0,0 +1,28 @@
1#!/usr/bin/env bash
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24
25extension="${3##*.}"
26if [ $extension = "tex" ]; then
27 latexdiff "$1" "$2" > diff_$3
28fi \ No newline at end of file
diff --git a/interrogations b/interrogations
new file mode 100755
index 0000000..19c97e3
--- /dev/null
+++ b/interrogations
@@ -0,0 +1,739 @@
1#!/usr/local/bin/perl
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24use Switch;
25use strict;
26
27my @table = ();
28my @interros = ();
29my @tablequestion = ();
30my @points = ();
31my %corr_nom ;
32my $interro_courante = 0;
33my $fichier = "notes.dat";
34if($#ARGV == 0) {
35 $fichier = $ARGV[0];
36}
37
38sub ajout_interro {
39 print "Nom de l'interrogation\n";
40 my $interro = <STDIN>;
41 chomp($interro);
42 push(@interros,$interro);
43 push(@tablequestion,[]);
44 push(@table,[]);
45 push(@points,[]);
46 foreach my $key (keys %corr_nom) {
47 push(@{ $corr_nom{$key} }, "Absent" );
48 }
49}
50
51sub ajout_eleve {
52 print "Nom\n";
53 my $nom = <STDIN>;
54 chomp($nom);
55 print "Prénom\n";
56 my $prenom = <STDIN>;
57 chomp($prenom);
58 $corr_nom{$prenom."\n".$nom} = ();
59 for my $i (0..$#interros) {
60 push(@{ $corr_nom{$prenom."\n".$nom} }, "Absent" );
61 }
62}
63
64sub definir_exos {
65 my $interro = shift;
66 my $nbexos = "a";
67 while($nbexos =~ m/\D/) {
68 print "Nombre d'exercices\n";
69 $nbexos = <STDIN>;
70 chomp($nbexos);
71 if($nbexos =~ /\D/) {
72 print "Mauvaise entrée\n";
73 }
74 }
75 if($nbexos == "") {
76 $nbexos = 0;
77 }
78 push(@{ $table[$interro] }, $nbexos);
79 if($nbexos == 0) {
80 push(@{ $tablequestion[$interro] }, "");
81 }
82 for(my $i = 1; $i <= $nbexos; $i++) {
83 my $questions = "a";
84 while($questions =~ m/\D/) {
85 print "Nombre de questions dans l'exercice ",$i,"\n";
86 $questions = <STDIN>;
87 chomp($questions);
88 if($questions =~ /\D/) {
89 print "Mauvaise entrée\n";
90 }
91 }
92 if($questions eq "") {
93 $questions = 0;
94 }
95 if($questions > 1) {
96 push(@{ $table[$interro] }, $questions);
97 for(my $j = 1; $j <= $questions; $j++) {
98 my $ssquestions = "a";
99 while($ssquestions =~ m/\D/) {
100 print "Nombre de sous-questions dans la question ",$i,".",$j,"\n";
101 $ssquestions = <STDIN>;
102 chomp($ssquestions);
103 if($ssquestions =~ /\D/) {
104 print "Mauvaise entrée\n";
105 }
106 }
107 if($ssquestions eq "") {
108 $ssquestions = 0;
109 }
110 if($ssquestions > 1) {
111 push(@{ $table[$interro] }, $j.".".$ssquestions);
112 for(my $k = 1; $k<= $ssquestions; $k++) {
113 push(@{ $tablequestion[$interro] }, $i.".".$j.".".$k);
114 }
115 }
116 else {
117 push(@{ $tablequestion[$interro] }, $i.".".$j);
118 }
119 }
120 }
121 else {
122 push(@{ $tablequestion[$interro] }, $i);
123 }
124 }
125}
126
127sub entrer_notes {
128 my $interro = shift;
129 my $eleve = shift;
130 my @boucle;
131 if($eleve) {
132 @boucle = ($eleve);
133 }
134 else {
135 @boucle = sort sort_alpha keys %corr_nom;
136 }
137 foreach my $key (@boucle) {
138 my $keyt = $key;
139 $keyt =~ s/\n/ /;
140 print $keyt." (mettre A pour indiquer une absence)\n";
141 my @int;
142 if(ref($corr_nom{$key}[$interro]) eq 'ARRAY') {
143 @int = @{$corr_nom{$key}[$interro]};
144 }
145 $corr_nom{$key}[$interro] = ();
146 Interro: for my $i (0..$#{$tablequestion[$interro]}) {
147 my $pourcentage = "a";
148 my $def = 0;
149 if(!@int && $i == 0) {
150 $def = "A";
151 }
152 if(scalar(@int) > 0) {
153 $def = $int[$i];
154 }
155 while($pourcentage =~ m/\D/ || $pourcentage > 100) {
156 if($tablequestion[$interro][$i] =~ m/\D/ ) {
157 print "Pourcentage pour la question ".$tablequestion[$interro][$i]." [".$def."]\n";
158 }
159 else {
160 print "Pourcentage pour l'exercice ".$tablequestion[$interro][$i]." [".$def."]\n";
161 }
162 $pourcentage = <STDIN>;
163 chomp($pourcentage);
164 if($pourcentage eq "") {
165 $pourcentage = $def;
166 }
167 if($pourcentage =~ m/^a$/i) {
168 $corr_nom{$key}[$interro] = "Absent";
169 last Interro;
170 }
171 if($pourcentage =~ /\D/ || $pourcentage > 100) {
172 print "Il faut un pourcentage entre 0 et 100\n";
173 }
174 }
175 push(@{ $corr_nom{$key}[$interro] },$pourcentage);
176 }
177 }
178}
179
180sub entrer_bareme {
181 my $interro = shift;
182 foreach my $nomquestion ( @{ $tablequestion[$interro] } ) {
183 my $point = "a";
184 while($point =~ /[^\d\.]/) {
185 if($nomquestion =~ m/\D/ ) {
186 print "Points pour la question ".$nomquestion."\n";
187 }
188 else {
189 print "Points pour l'exercice ".$nomquestion."\n";
190 }
191 $point = <STDIN>;
192 chomp($point);
193 if($point =~ /[^\d\.]/) {
194 print "Il faut donner un nombre de points\n";
195 }
196 }
197 if($point eq "") {
198 $point = 0;
199 }
200 push(@{ $points[$interro] },$point);
201 }
202}
203
204sub sauver {
205 open FILE, ">".$fichier;
206 foreach my $i (0..$#table) {
207 print FILE $interros[$i]."\n";
208 print FILE "@{ $table[$i] }\n";
209 print FILE "@{ $tablequestion[$i] }\n";
210 print FILE "@{ $points[$i] }\n";
211 }
212 print FILE "\n";
213 foreach my $ligne (keys(%corr_nom)) {
214 print FILE $ligne."\n";
215 foreach my $lig (@{ $corr_nom{$ligne} }) {
216 if($lig eq "Absent") {
217 print FILE "! \n";
218 }
219 else {
220 print FILE "* @$lig\n";
221 }
222 }
223 }
224 print FILE "\n";
225 close FILE;
226}
227
228sub charger {
229 open FILE, $fichier;
230 while(my $int = <FILE>) {
231 if($int eq "\n") { last };
232 chomp($int);
233 push(@interros,$int);
234 $int = <FILE>;
235 chomp($int);
236 push(@table, [ split(/ /, $int) ] );
237 $int = <FILE>;
238 chomp($int);
239 push(@tablequestion, [ split(/ /, $int) ] );
240 $int = <FILE>;
241 chomp($int);
242 push(@points, [ split(/ /, $int) ] );
243
244 }
245 my $int = <FILE>;
246 while(1) {
247 if($int eq "\n") { last };
248 my $intn = <FILE>;
249 chomp($intn);
250 my $key = $int.$intn;
251 $corr_nom{$key} = ();
252 while($intn = <FILE>) {
253 if($intn =~ m/^\*/) {
254 chomp($intn);
255 push(@{ $corr_nom{$key} }, [ split(/ /, substr($intn,2)) ] );
256 }
257 elsif($intn =~ m/^!/) {
258 push(@{ $corr_nom{$key} }, "Absent" );
259 }
260 else {
261 $int = $intn;
262 last;
263 }
264 }
265 }
266 close FILE;
267}
268
269sub sort_alpha {
270 my @p_na = split(/\n/,$a);
271 my @p_nb = split(/\n/,$b);
272 return $p_na[1] cmp $p_nb[1] || $p_na[0] cmp $p_nb[0];
273}
274
275sub export_latex {
276 print "Fichier ?\n";
277 my $f_export = <STDIN>;
278 chomp($f_export);
279 if($f_export eq "") { return 0 };
280 open FILE, ">".$f_export;
281 print FILE "\\documentclass[landscape]{article}\n";
282 print FILE "\\usepackage[T1]{fontenc}\n";
283 print FILE "\\usepackage[utf8]{inputenc}\n";
284 print FILE "\\usepackage{geometry}\n";
285 print FILE "\\geometry{margin=1cm}\n";
286 print FILE "\\begin{document}\n";
287 for my $interro (0..$#table) {
288 print FILE "\\begin{tabular}{|l|";
289 my @exosansq = grep(/^[1-9]\d*$/,@{ $tablequestion[$interro] });
290 print FILE "c|"x (scalar(@{ $tablequestion[$interro] })+$table[$interro][0] - scalar(@exosansq));
291 print FILE "|c|}\n";
292 my @ign = ();
293 my @pts = ();
294 my @max = ();
295 my @min = ();
296 my @somme = ();
297 print FILE "\\multicolumn{",(scalar(@{ $tablequestion[$interro] })+$table[$interro][0] - scalar(@exosansq) + 2),"}{c}{\\Large ".$interros[$interro]."}\\\\\n";
298 if($table[$interro][0] > 0) {
299 print FILE "\\hline\n\t ";
300 for(my $i = 1; $i <= $table[$interro][0]; $i++) {
301 my @b = grep(/^$i/,@{ $tablequestion[$interro] });
302 if(scalar(@b) == 1) {
303 print FILE "& Exercice $i ";
304 }
305 else {
306 print FILE "& \\multicolumn{",scalar(@b)+1,"}{c|}{Exercice ",$i,"} ";
307 }
308 }
309 print FILE "& Total ";
310 print FILE "\\\\\n";
311 print FILE "\\hline\n\t";
312 my $rank = -1;
313 for(my $i = 1; $i <= $table[$interro][0]; $i++) {
314 my @b = grep(/^$i(\D|$)/,@{ $tablequestion[$interro] });
315 for(my $j = 1; $j <= scalar(@b); $j++) {
316 my @c = grep(/^$i\.$j(\D|$)/,@{ $tablequestion[$interro] });
317 $rank += scalar(@c);
318 if(scalar(@c) == 1) {
319 print FILE "& $j) ";
320 }
321 elsif(scalar(@c) > 0) {
322 print FILE "& \\multicolumn{",scalar(@c),"}{c|}{",$j,")} ";
323 }
324 elsif($j == 1) {
325 $rank +=1;
326 push(@ign,$rank+$i-1);
327 #print FILE "& ";
328 }
329 }
330 print FILE "& Total ";
331 push(@pts,$rank);
332 }
333 print FILE "& \\\\\n";
334 }
335 print FILE "\\hline\n\t";
336 print FILE "points ";
337 my $totalexo = 0;
338 my $total = 0;
339 my $nq = 0;
340 for my $i (0.. $#{ $points[$interro] }) {
341 print FILE "& $points[$interro][$i] ";
342 push(@min,$points[$interro][$i]);
343 push(@max,0);
344 push(@somme,0);
345 $totalexo += $points[$interro][$i];
346 $total += $points[$interro][$i];
347 $nq++;
348 if((grep {$_ == $i} @pts) > 0) {
349 if($nq > 1) {
350 print FILE "& $totalexo ";
351 }
352 push(@min,$totalexo);
353 push(@max,0);
354 push(@somme,0);
355 $totalexo = 0;
356 $nq = 0;
357 }
358 }
359 print FILE "& $total ";
360 push(@min,$total);
361 push(@max,0);
362 push(@somme,0);
363 print FILE "\\\\\n";
364 print FILE "\\hline\n\t";
365 print FILE "\\hline\n\t";
366
367 my @sortednotes = sort sort_alpha (keys %corr_nom);
368 #print "@sortednotes";
369 #my $somme = 0;
370 my $nombre_eleves = 0;
371 for my $i (0.. $#sortednotes) {
372 my $np = $sortednotes[$i];
373 $np =~ s/\n/ /;
374 print FILE $np;
375 my @ligne = @{ $corr_nom{$sortednotes[$i]} };
376 if($ligne[$interro] eq "Absent") {
377 print FILE "& \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0]+1,"}{c|}{Absent}";
378 }
379 else {
380 my @ligneo = @{ $ligne[$interro] };
381 my $totalexo = 0;
382 my $total = 0;
383 $nombre_eleves++;
384 my $k = 0;
385 my $nq = 0;
386 foreach my $l (0.. $#ligneo ) {
387 my $val = sprintf("%.0f",4.*$ligneo[$l]*$points[$interro][$l]/100)/4;
388 print FILE "& ",$val;
389 if($min[$k] > $val) {
390 $min[$k] = $val;
391 }
392 if($max[$k] < $val) {
393 $max[$k] = $val;
394 }
395 $somme[$k] += $val;
396 $k++;
397 $nq++;
398 $totalexo += $val;
399 $total += $val;
400 if((grep {$_ == $l} @pts) > 0) {
401 if($min[$k] > $totalexo) {
402 $min[$k] = $totalexo;
403 }
404 if($max[$k] < $totalexo) {
405 $max[$k] = $totalexo;
406 }
407 $somme[$k] += $totalexo;
408 if($nq > 1) {
409 print FILE "& $totalexo ";
410 }
411 $k++;
412 $totalexo = 0;
413 $nq = 0;
414 }
415 }
416 print FILE "& $total ";
417 if($min[$k] > $total) {
418 $min[$k] = $total;
419 }
420 if($max[$k] < $total) {
421 $max[$k] = $total;
422 }
423 $somme[$k] += $total;
424 $k++;
425 }
426 print FILE "\\\\\n";
427 print FILE "\\hline\n\t";
428 }
429 print FILE "\\hline\n\t";
430 print FILE "Moyenne";
431 for my $l (0.. $#somme) {
432 next if((grep {$_ == $l} @ign) > 0);
433 print FILE "& ".sprintf("%.0f",4.*$somme[$l]/$nombre_eleves)/4;
434 }
435 print FILE "\\\\\n";
436 print FILE "\\hline\n\t";
437 print FILE "Min";
438 for my $l (0.. $#min) {
439 next if((grep {$_ == $l} @ign) > 0);
440 print FILE "& $min[$l]";
441 }
442 print FILE "\\\\\n";
443 print FILE "\\hline\n\t";
444 print FILE "Max";
445 for my $l (0.. $#max) {
446 next if((grep {$_ == $l} @ign) > 0);
447 print FILE "& $max[$l]";
448 }
449 #print FILE "Moyenne & \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0],"}{c||}{ }";
450 #my $moyenne = sprintf("%.0f",4.*$somme/$nombre_eleves)/4;
451 #print FILE " & $moyenne\\\\\n";
452 print FILE "\\\\\n";
453 print FILE "\\hline\n\t";
454 print FILE "\\end{tabular}\n";
455 print FILE "\\vfill\n";
456 print FILE "\\newpage\n";
457 }
458 print FILE "\\end{document}\n";
459 close FILE;
460}
461
462sub export_csv {
463 my $interro = shift;
464 print "Fichier ?\n";
465 my $f_export = <STDIN>;
466 chomp($f_export);
467 if($f_export eq "") { return 0 };
468 open FILE, ">".$f_export;
469 for my $interro (0..$#table) {
470 print FILE "; ".$interros[$interro]."\n";
471 my @pts = ();
472 my @ign = ();
473 my @max = ();
474 my @min = ();
475 my @somme = ();
476 if($table[$interro][0] > 0) {
477 for(my $i = 1; $i <= $table[$interro][0]; $i++) {
478 my @b = grep(/^$i/,@{ $tablequestion[$interro] });
479 if(scalar(@b) == 1) {
480 print FILE "; Exercice $i ";
481 }
482 else {
483 print FILE "; Exercice $i","; "x scalar(@b);
484 }
485 }
486 print FILE "; Total \n";
487 my $rank = -1;
488 for(my $i = 1; $i <= $table[$interro][0]; $i++) {
489 my @b = grep(/^$i(\D|$)/,@{ $tablequestion[$interro] });
490 for(my $j = 1; $j <= scalar(@b); $j++) {
491 my @c = grep(/^$i\.$j(\D|$)/,@{ $tablequestion[$interro] });
492 $rank += scalar(@c);
493 if(scalar(@c) == 1) {
494 print FILE "; $j) ";
495 }
496 elsif(scalar(@c) > 0) {
497 my $char = "a";
498 for my $num (0..$#c) {
499 print FILE "; $j) ".$char.") ";
500 $char++;
501 }
502 #print FILE "; $j) ","; "x (scalar(@c)-1);
503 }
504 elsif($j == 1) {
505 $rank += 1;
506 push(@ign,$rank+$i-1);
507 #print FILE "; ";
508 }
509 }
510 print FILE "; Total ";
511 push(@pts,$rank);
512 }
513 print FILE "; \n";
514 }
515 print FILE "points ";
516 my $totalexo = 0;
517 my $total = 0;
518 my $nq = 0;
519 for my $i (0.. $#{ $points[$interro] }) {
520 print FILE "; $points[$interro][$i] ";
521 push(@min,$points[$interro][$i]);
522 push(@max,0);
523 push(@somme,0);
524 $totalexo += $points[$interro][$i];
525 $total += $points[$interro][$i];
526 $nq++;
527 if((grep {$_ == $i} @pts) > 0) {
528 if($nq > 1) {
529 print FILE "; $totalexo ";
530 }
531 push(@min,$totalexo);
532 push(@max,0);
533 push(@somme,0);
534 $totalexo = 0;
535 $nq = 0;
536 }
537 }
538 print FILE "; $total ";
539 push(@min,$total);
540 push(@max,0);
541 push(@somme,0);
542 print FILE "\n";
543
544 my @sortednotes = sort sort_alpha (keys %corr_nom);
545 #print "@sortednotes";
546 #my $somme = 0;
547 my $nombre_eleves = 0;
548 for my $i (0.. $#sortednotes) {
549 my $np = $sortednotes[$i];
550 $np =~ s/\n/ /;
551 print FILE $np;
552 my @ligne = @{ $corr_nom{$sortednotes[$i]} };
553 if($ligne[$interro] eq "Absent") {
554 print FILE "; Absent","; "x (scalar(@{ $tablequestion[$interro] })+$table[$interro][0]);
555 }
556 else {
557 my @ligneo = @{ $ligne[$interro] };
558 my $totalexo = 0;
559 my $total = 0;
560 $nombre_eleves++;
561 my $k = 0;
562 my $nq = 0;
563 foreach my $l (0.. $#ligneo ) {
564 my $val = sprintf("%.0f",4.*$ligneo[$l]*$points[$interro][$l]/100)/4;
565 print FILE "; ",$val;
566 if($min[$k] > $val) {
567 $min[$k] = $val;
568 }
569 if($max[$k] < $val) {
570 $max[$k] = $val;
571 }
572 $somme[$k] += $val;
573 $k++;
574 $totalexo += $val;
575 $total += $val;
576 $nq++;
577 if((grep {$_ == $l} @pts) > 0) {
578 if($nq > 1) {
579 print FILE "; $totalexo ";
580 }
581 if($min[$k] > $totalexo) {
582 $min[$k] = $totalexo;
583 }
584 if($max[$k] < $totalexo) {
585 $max[$k] = $totalexo;
586 }
587 $somme[$k] += $totalexo;
588 $k++;
589 $totalexo = 0;
590 $nq = 0;
591 }
592 }
593 print FILE "; $total ";
594 if($min[$k] > $total) {
595 $min[$k] = $total;
596 }
597 if($max[$k] < $total) {
598 $max[$k] = $total;
599 }
600 $somme[$k] += $total;
601 $k++;
602 }
603 print FILE "\n";
604 }
605 print FILE "Moyenne";
606 for my $l (0.. $#somme) {
607 next if((grep {$_ == $l} @ign) > 0);
608 print FILE "; ".sprintf("%.0f",4.*$somme[$l]/$nombre_eleves)/4;
609 }
610 print FILE "\n";
611 print FILE "Min";
612 for my $l (0.. $#min) {
613 next if((grep {$_ == $l} @ign) > 0);
614 print FILE "; $min[$l]";
615 }
616 print FILE "\n";
617 print FILE "Max";
618 for my $l (0.. $#max) {
619 next if((grep {$_ == $l} @ign) > 0);
620 print FILE "; $max[$l]";
621 }
622 #print FILE "Moyenne & \\multicolumn{",scalar(@{ $tablequestion[$interro] })+$table[$interro][0],"}{c||}{ }";
623 #my $moyenne = sprintf("%.0f",4.*$somme/$nombre_eleves)/4;
624 #print FILE " & $moyenne\\\\\n";
625 print FILE "\n";
626 print FILE "\n\n\n";
627 }
628 close FILE;
629}
630
631if(-e $fichier) {
632 &charger();
633}
634
635sub choisir_interro() {
636 while(1) {
637 my $i = 1;
638 my $var;
639 my $message = '';
640 foreach $var ( @interros ) {
641 $message .= $i++.') '.$var."\n";
642 }
643 print $message;
644 $var = <STDIN>;
645 chop($var);
646 if(/\D/ || $var < 1 || $var > $i) {
647 print "Mauvaise entrée\n";
648 next;
649 }
650 $interro_courante = $var-1;
651 last;
652 }
653}
654
655sub editer_eleve() {
656 my $eleve;
657 while(1) {
658 open COL, "| column";
659 my $i = 1;
660 my @eleves = sort sort_alpha keys(%corr_nom);
661 foreach my $eleve_l (@eleves) {
662 my $eleve_lm = $eleve_l;
663 $eleve_lm =~ s/\n/ /;
664 print COL $i++.") ".$eleve_lm."\n";
665 }
666 print COL $i.") Annuler\n";
667 close COL;
668 my $var = <STDIN>;
669 chop($var);
670 if(/\D/ || $var < 1 || $var > $i) {
671 print "Mauvaise entrée\n";
672 next;
673 }
674 elsif( $var == $i ) {
675 return;
676 }
677 $eleve = $eleves[$var-1];
678 last;
679 }
680 my $notes_c = ${$corr_nom{$eleve}}[$interro_courante];
681 if($notes_c == "Absent") {
682 print "Absent à ".$interros[$interro_courante]."\n";
683 }
684 &entrer_notes($interro_courante,$eleve);
685}
686
687sub quitter() {
688 exit 0;
689}
690
691my @actions = ("Ajouter une interro", "Ajouter un élève");
692my @actions_f = (\&ajout_interro,
693 \&ajout_eleve,
694 \&choisir_interro,
695 \&editer_eleve,
696 \&definir_exos,
697 \&entrer_bareme,
698 \&entrer_notes,
699 \&sauver,
700 \&export_latex,
701 \&export_csv,
702 \&quitter,
703 );
704while(1) {
705 if(scalar(@interros)>0) {
706 $actions[2] = "Choisir une interro";
707 $actions[3] = "Éditer les notes d'un élève";
708 $actions[4] = "Définir les exercices de l'interro";
709 $actions[5] = "Définir le barême de l'interro";
710 $actions[6] = "Entrer les notes de l'interro";
711 $actions[7] = "Sauvegarder";
712 $actions[8] = "Exporter en LaTeX";
713 $actions[9] = "Exporter en CSV";
714 }
715
716
717 my $action;
718 while(1) {
719 my $i = 1;
720 my $var;
721 my @vart = ( @actions, 'Quitter' );
722 my $message = 'Interro sélectionnée : '.$interros[$interro_courante]."\n";
723 foreach $var ( @vart ) {
724 $message .= $i++.') '.$var."\n";
725 }
726 print $message;
727 $var = <STDIN>;
728 chop($var);
729 if(/\D/ || $var < 1 || $var > $i) {
730 print "Mauvaise entrée\n";
731 next;
732 }
733 $action = $actions_f[$var-1];
734 last;
735 }
736 &{$action}($interro_courante);
737}
738
739#&export_latex();
diff --git a/mails_iprof b/mails_iprof
new file mode 100755
index 0000000..04f2603
--- /dev/null
+++ b/mails_iprof
@@ -0,0 +1,53 @@
1#!/usr/bin/env sh
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24if [ "$*" = "" ]; then
25 echo "`basename $0` academie login password"
26 echo "où academie est remplacé dans:"
27 echo "https://bv.ac-academie.fr/iprof/ServletIprof"
28 exit 1
29fi
30
31iPROF="https://bv.ac-$1.fr/iprof/ServletIprof"
32login="$2"
33mdp="$3"
34
35numu=`curl $iPROF 2>/dev/null | grep numu| sed -e "s/.*value='\(.*\)'.*/\1/"`
36
37session=`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/"`
38
39curl -d 'codeTraitement=CourrierE' $iPROF';'$session 2>/dev/null 1>&2
40
41M=`mktemp`
42
43curl -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
44
45Nouveau=`wc -l $M | cut -d" " -f1`
46Ancien=`wc -l $HOME/.iprof | cut -d" " -f1`
47
48if [ "x"$Nouveau != "x"$Ancien ];then
49 echo "Du nouveau sur I-prof"
50 rm $HOME/.iprof
51 cp $M $HOME/.iprof
52fi
53rm -f $M
diff --git a/mutt_check_attachment b/mutt_check_attachment
new file mode 100755
index 0000000..f99112f
--- /dev/null
+++ b/mutt_check_attachment
@@ -0,0 +1,75 @@
1#!/bin/bash
2
3## Original script adapted from source: http://wiki.mutt.org/?ConfigTricks/CheckAttach
4##
5## Adapted by Ismaël Bouya (http://www.normalesup.org/~bouya/) to make it so
6## that retrying to send the email shortly after will work
7##
8## Edit muttrc to have this line:
9## set sendmail = "/usr/local/bin/mutt_check_attachment_before_send.sh /usr/lib/sendmail -oem -oi"
10##
11
12
13## Attachment keywords that the message body will be searched for:
14KEYWORDS='attach|joint|voici|voil'
15
16## Check that sendmail or other program is supplied as first argument.
17if [ ! -x "$1" ]; then
18 echo "Usage: $0 </path/to/mailprog> <args> ..."
19 echo "e.g.: $0 /usr/sbin/sendmail -oem -oi"
20 exit 2
21fi
22
23## Save msg in file to re-use it for multiple tests.
24TMPFILE=`mktemp -t mutt_checkattach.XXXXXX` || exit 2
25cat > "$TMPFILE"
26
27## Define test for multipart message.
28function multipart {
29# grep -q '^Content-Type: multipart' "$TMPFILE"
30 grep -q '^Content-Disposition: attachment' "$TMPFILE"
31}
32
33## Define test for keyword search.
34function word-attach {
35 grep -v '^>' "$TMPFILE" | grep -E -i -q "$KEYWORDS"
36}
37
38## Header override.
39function header-override {
40 grep -i -E "^X-attached: *none *$" "$TMPFILE"
41}
42
43function ask {
44 terminal=`tty`
45 dialog --yesno "Envoyer malgré la pièce jointe manquante ?" 5 30 < $terminal > $terminal
46 }
47
48#Verifie qu'on a essayé de l'envoyer y'a moins d'une minute
49function file_last {
50 if [ ! -e $HOME/.mutt_attach ]; then
51 return 0
52 fi
53 valeur=`echo \`date +%s\`-\`stat -c %Y $HOME/.mutt_attach\`'<60' | bc`
54 return $valeur
55}
56## FINAL DECISION:
57if multipart || ! word-attach || header-override || ! file_last ; then
58 "$@" < "$TMPFILE"
59 EXIT_STATUS=$?
60 if [ ! -s $HOME/.mutt_attach ]; then
61 rm -f $HOME/.mutt_attach
62 fi
63else
64 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."
65 echo "You can also send the email again in the next minute."
66 EXIT_STATUS=1
67 touch $HOME/.mutt_attach
68fi
69
70## Delete the temporary file.
71rm -f "$TMPFILE"
72
73## That's all folks.
74exit $EXIT_STATUS
75
diff --git a/parse_bibtex_html b/parse_bibtex_html
new file mode 100755
index 0000000..5e54729
--- /dev/null
+++ b/parse_bibtex_html
@@ -0,0 +1,172 @@
1#!/usr/bin/env perl
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24
25use BibTeX::Parser;
26use IO::File;
27use utf8;
28use strict;
29use open ':utf8';
30
31sub parse_config_file {
32 my ($config_line, $Name, $Value, $Config);
33 (my $File, $Config) = @_;
34 if (!open (CONFIG, "$File")) {
35 print "ERROR: Config file not found : $File";
36 exit(0);
37 }
38 my $multiline = 0;
39
40 while (<CONFIG>) {
41 $config_line=$_;
42 chop ($config_line);
43 $config_line =~ s/^\s*//;
44 $config_line =~ s/\s*$//;
45 if ( ($config_line !~ /^#/) && ($config_line ne "") ){
46 if ($multiline) {
47 $$Config{$Name} =~ s/\\$//;
48 $$Config{$Name} .= $config_line;
49 } else {
50 ($Name, $Value) = split (/\s*=\s*/, $config_line);
51 $Value =~ s/^~/$ENV{"HOME"}/;
52 $$Config{$Name} = $Value;
53 }
54 $multiline = ($$Config{$Name} =~ /\\$/);
55 }
56 }
57 close(CONFIG);
58}
59
60my %Config;
61&parse_config_file ($ENV{"HOME"}."/.parse_bibtex_html.rc", \%Config);
62
63my $biblio = $Config{"biblio"};
64my $entete = $Config{"entete"};
65my $avant = $Config{"avant"};
66my $milieu = $Config{"milieu"};
67my $apres = $Config{"apres"};
68my $html = $Config{"html"};
69
70my $dossier = $Config{"dossier"};
71my $dossierweb = $Config{"dossier_web"};
72
73# http://webdesign.about.com/library/bl_htmlcodes.htm
74sub echap {
75 my $t = shift or return;
76 $t =~ s/&/&amp;/g;
77 $t =~ s/</&lt;/g;
78 $t =~ s/>/&gt;/g;
79
80 $t =~ s/--/&mdash;/g;
81
82 $t =~ s/{?\\'a}?/&aacute;/g;
83 $t =~ s/{?\\`a}?/&agrave;/g;
84 $t =~ s/{?\\"a}?/&auml;/g;
85
86 $t =~ s/{?\\r A}?/&Aring;/g;
87
88 $t =~ s/{?\\'e}?/&eacute;/g;
89 $t =~ s/{?\\`e}?/&egrave;/g;
90 $t =~ s/{?\\'E}?/&Eacute;/g;
91 $t =~ s/{?\\"e}?/&euml;/g;
92
93 $t =~ s/{?\\\^i}?/&icirc;/g;
94 $t =~ s/{?\\"i}?/&iuml;/g;
95
96 $t =~ s/{?\\"o}?/&ouml;/g;
97 $t =~ s/{?\\"o}?/&ouml;/g;
98 $t =~ s/{?\\=o}?/&#333;/g;
99 $t =~ s/{?\\o}?/&oslash;/g;
100
101 $t =~ s/{?\\"u}?/&uuml;/g;
102 $t =~ s/{?\\'u}?/&uacute;/g;
103
104 $t =~ s/{?\\~n}?/&ntilde;/g;
105
106 $t =~ s/{?\\c{?c}?}? ?/&ccedil;/g;
107 $t =~ s/{?\\'{?c}?}? ?/&#263;/g;
108
109 $t =~ s/{?\\v{? ?s}?}? ?/&#353;/g;
110
111 $t =~ s/{?\^({[^}]+}|.)}?/<sup>$1<\/sup>/g;
112 $t =~ s/{(.*)}/$1/g;
113 return $t;
114}
115
116open F, ">".$milieu;
117opendir(DIR, $dossier);
118my @FILES = readdir(DIR);
119my $fh = IO::File->new($biblio);
120my $parser = BibTeX::Parser->new($fh);
121print F "\t<ul>\n";
122my %liste = ();
123
124while (my $entry = $parser->next ) {
125 if ($entry->parse_ok) {
126 my $type = $entry->type;
127 my $title = $entry->field("title");
128 my $key = $entry->key;
129 my @authors = $entry->author;
130# my @editors = $entry->editor;
131 my $auth = "";
132 my @authors_sort = ();
133 foreach my $author (@authors) {
134 $auth .= (($author->first)?$author->first. " ":"") .(($author->von)?$author->von." ":"") . (($author->last)?$author->last:"") . ", ";
135 push(@authors_sort,$author->last);
136 }
137 @authors_sort = sort {lc $a cmp lc $b} @authors_sort;
138 my $cle_sort = shift(@authors_sort);
139 $auth = substr $auth, 0 , -2;
140 my $suffix = '(\.|_)';
141 my @match = grep(/^$key$suffix/,@FILES);
142 my $i = 1;
143 my $chaine = "\t\t<li>";
144 $auth = echap $auth;
145 $title = echap $title;
146 if($auth =~ m/\\/ || $title =~ m/\\/) {
147 warn "Unparsed item : $auth, $title";
148 }
149 $chaine .= "<span class='biblio_titre'>".$title."</span><br />".$auth."<br />\n";
150 @match = sort {lc $a cmp lc $b} @match;
151 foreach my $item (@match) {
152 $chaine .= "\t\t\t<a href='".$dossierweb.$item."'>fichier ".$i++."</a> \n";
153 }
154 $chaine .="\t\t\t<a id='".$key."' href='#".$key."' class='bibtex'>BibTeX</a>\n";
155 my $raw = $entry->raw_bibtex;
156 $raw =~ s/&/&amp;/g;
157 $chaine .= "\t\t\t<pre class='bibtex'>".$raw."</pre>\n";
158 $chaine .= "\t\t\t</li>\n";
159 $liste{$cle_sort." ".$key} = $chaine;
160 } else {
161 warn "Error parsing file: " . $entry->error;
162 }
163 }
164
165foreach my $key (sort keys %liste) {
166 print F $liste{$key};
167}
168
169print F "\t\t</ul>";
170close F;
171
172exec "cat $entete $avant $milieu $apres 1> $html" or die "$!\n";
diff --git a/remove_attachements b/remove_attachements
new file mode 100755
index 0000000..b5243ab
--- /dev/null
+++ b/remove_attachements
@@ -0,0 +1,149 @@
1#!/usr/bin/env perl
2# Inspired by Aaron . Ciuffo (at gmail)
3
4# The MIT License (MIT)
5#
6# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24# THE SOFTWARE.
25
26
27use strict;
28
29use Email::MIME;
30use DateTime;
31use Digest::MD5 qw(md5_hex);
32
33use vars qw(
34 $filter_attachments_file
35 $email $email_parsed
36 @email_parts
37 @new_email_parts
38 $mail_was_modified
39 @removed_files
40);
41
42@removed_files = ();
43@new_email_parts = ();
44$mail_was_modified = 0;
45my @mailr = ();
46my $premiere = 1;
47my $premiere_ligne;
48foreach( <STDIN> ) {
49 my $ligne = $_;
50 if($ligne =~ m/^From/ && $premiere) {
51 $premiere_ligne = $ligne;
52 next;
53 }
54 $premiere = 0;
55 if($ligne =~ m/^Content-Disposition: attachment; filename/) {
56 my $fichier = $ligne;
57 chomp($fichier);
58 if($ligne =~ m/^Content-Disposition: attachment; filename\*/) {
59 $fichier =~ s/^.*filename\*.*''([^\s]*)\s?.*$/\1/;
60 $fichier =~ s/%2E/./g;
61 $fichier =~ s/%20/_/g;
62 $fichier =~ s/%//g;
63 $ligne =~ s/filename\*.*''([^ \n\r\t]*)/filename="$fichier"/;
64 }
65 else {
66 $fichier =~ s/^.*filename="?(.*[^"])"?.*$/\1/;
67 $fichier =~ s/ /_/g;
68 $fichier =~ s/[^-a-zA-Z0-9_.]/_/g;
69 $ligne =~ s/filename=.*$/filename="$fichier"/;
70 }
71 }
72 push(@mailr,$ligne);
73}
74$email = join( '',@mailr );
75
76$filter_attachments_file = $ENV{HOME}."/.attachements/".DateTime->now(time_zone => 'local')->strftime('%Y%m%d_%H%M%S')."_".substr(md5_hex($email),0,5)."/" ;
77
78$email_parsed = Email::MIME->new( $email );
79if($email_parsed->content_type =~m[^multipart/encrypted]) {
80 print STDOUT $premiere_ligne;
81 print STDOUT $email_parsed->as_string;
82 exit;
83}
84
85my @parts = $email_parsed->parts;
86my $extension = "text/";
87$email_parsed->walk_parts(sub {
88 my ($part) = @_;
89 if ($part->content_type =~m[text/plain]i){
90 $extension = "text/plain";
91 return;
92 }
93});
94
95sub parse_parts {
96 my ($part) = @_;
97 if($part->content_type =~ m[$extension]i or $part->content_type =~ m[application/pgp-signature]i or !$part->content_type) {
98 push( @new_email_parts, $part);
99 }
100 elsif ($part->content_type =~ m[multipart/mixed]i) {
101 foreach( $part->subparts ) {
102 parse_parts($_);
103 }
104 }
105 else {
106 if(length($part->body) == 0) {
107 return;
108 }
109 if(!$mail_was_modified) {
110 mkdir $filter_attachments_file;
111 $mail_was_modified = 1;
112 push( @removed_files, "keepdir://".$filter_attachments_file);
113 }
114 my $fichier = $part->filename(1);
115 $fichier =~ s/ /\\ /g;
116 push( @removed_files, "file://".$filter_attachments_file.$fichier." ".$part->content_type );
117 open(my $out, '>:raw', $filter_attachments_file.$part->filename(1));
118 print $out $part->body;
119 close($out);
120 }
121}
122foreach( $email_parsed->subparts ) {
123 parse_parts($_);
124}
125
126if ($mail_was_modified)
127{
128 my $remove_string = "The following attachments were removed:";
129 $remove_string = $remove_string."\n".$_ foreach (@removed_files);
130 $remove_string = $email_parsed->debug_structure."\n".$remove_string;
131 push (@new_email_parts, Email::MIME->create(
132 attributes => {
133 content_type => "text/plain",
134 disposition => "attachment",
135 charset => "US-ASCII",
136 filename => "removed_attachments.txt"
137 },
138 body => $remove_string,
139 ) );
140 $email_parsed->parts_set( \@new_email_parts );
141 $email_parsed->content_type_set( 'multipart/mixed' );
142 $email = $email_parsed->as_string;
143
144}
145
146print STDOUT $premiere_ligne;
147print STDOUT $email;
148
149
diff --git a/unicode_chars b/unicode_chars
new file mode 100755
index 0000000..25f4522
--- /dev/null
+++ b/unicode_chars
@@ -0,0 +1,45 @@
1#!/usr/bin/env python3
2# The MIT License (MIT)
3#
4# Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23
24import sys
25import unicodedata
26
27string = sys.stdin.readline().strip()
28for char in string:
29 print("U+%04x" % ord(char), end="")
30 if (ord(char) < 31):
31 print()
32 else:
33 print(" " + char + " ", end="")
34 try:
35 print(unicodedata.name(char), "["+unicodedata.category(char)+"]")
36 decomposition = unicodedata.decomposition(char).split(" ")
37 if len(decomposition) > 1:
38 for subchar in decomposition:
39 try:
40 unicode_char = chr(int(subchar, 16))
41 print(" U+%s" % subchar, unicodedata.name(unicode_char))
42 except ValueError:
43 print(" " + subchar)
44 except:
45 pass