8544e054f191765555bd07ab55a749e5e7d21ec6
[ipfire-2.x.git] / src / pakfire / lib / functions.pl
1 #!/usr/bin/perl -w
2
3 require "/opt/pakfire/etc/pakfire.conf";
4 require "/var/ipfire/general-functions.pl";
5
6 use File::Basename;
7 use File::Copy;
8 use LWP::UserAgent;
9 use HTTP::Response;
10 use HTTP::Headers;
11 use HTTP::Message;
12 use HTTP::Request;
13 use Net::Ping;
14
15 package Pakfire;
16
17 # GPG Keys
18 my $myid = "64D96617";                  # Our own gpg-key paks@ipfire.org
19 my $trustid = "65D0FD58";               # gpg-key of CaCert
20
21 # A small color-hash :D
22 my %color;
23         $color{'normal'}      = "\033[0m"; 
24         $color{'black'}       = "\033[0;30m";
25         $color{'darkgrey'}    = "\033[1;30m";
26         $color{'blue'}        = "\033[0;34m";
27         $color{'lightblue'}   = "\033[1;34m";
28         $color{'green'}       = "\033[0;32m";
29         $color{'lightgreen'}  = "\033[1;32m";
30         $color{'cyan'}        = "\033[0;36m";
31         $color{'lightcyan'}   = "\033[1;36m";
32         $color{'red'}         = "\033[0;31m";
33         $color{'lightred'}    = "\033[1;31m";
34         $color{'purple'}      = "\033[0;35m";
35         $color{'lightpurple'} = "\033[1;35m";
36         $color{'brown'}       = "\033[0;33m";
37         $color{'lightgrey'}   = "\033[0;37m";
38         $color{'yellow'}      = "\033[1;33m";
39         $color{'white'}       = "\033[1;37m";
40 our $enable_colors = 1;
41
42 my $final_data;
43 my $total_size;
44 my $bfile;
45
46 my %pakfiresettings = ();
47 &General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings);
48
49 sub message {
50         my $message = shift;
51                 
52         logger("$message");
53         if ( $enable_colors == 1 ) {
54                 if ("$message" =~ /ERROR/) {
55                         $message = "$color{'red'}$message$color{'normal'}";
56                 } elsif ("$message" =~ /INFO/) {
57                         $message = "$color{'cyan'}$message$color{'normal'}";
58                 } elsif ("$message" =~ /WARN/) {
59                         $message = "$color{'yellow'}$message$color{'normal'}";
60                 } elsif ("$message" =~ /RESV/) {
61                         $message = "$color{'purple'}$message$color{'normal'}";
62                 } elsif ("$message" =~ /INST/) {
63                         $message = "$color{'green'}$message$color{'normal'}";
64                 } elsif ("$message" =~ /REMV/) {
65                         $message = "$color{'lightred'}$message$color{'normal'}";
66                 } elsif ("$message" =~ /UPGR/) {
67                         $message = "$color{'lightblue'}$message$color{'normal'}";
68                 }
69         }
70         print "$message\n";
71         
72 }
73
74 sub logger {
75         my $log = shift;
76         if ($log) {
77                 system("echo \"`date`: $log\" >> /var/log/pakfire.log");
78                 #system("logger -t pakfire \"$log\"");
79         }
80 }
81
82 sub usage {
83   &Pakfire::message("Usage: pakfire <install|remove> [options] <pak(s)>");
84   &Pakfire::message("               <update> - Contacts the servers for new lists of paks.");
85   &Pakfire::message("               <upgrade> - Installs the latest version of all paks.");
86   &Pakfire::message("               <list> - Outputs a short list with all available paks.");
87   &Pakfire::message("");
88   &Pakfire::message("       Global options:");
89   &Pakfire::message("               --non-interactive --> Enables the non-interactive mode.");
90   &Pakfire::message("                                     You won't see any question here.");
91   &Pakfire::message("                              -y --> Short for --non-interactive.");
92   &Pakfire::message("                     --no-colors --> Turns off the wonderful colors.");
93   &Pakfire::message("");
94   exit 1;
95 }
96
97 sub pinghost {
98         my $host = shift;
99         
100         $p = Net::Ping->new();
101   if ($p->ping($host)) {
102         logger("PING INFO: $host is alive");
103         return 1;
104   } else {
105                 logger("PING INFO: $host is unreachable");
106                 return 0;
107         }
108   $p->close();
109 }
110
111 sub fetchfile {
112         my $getfile = shift;
113         my $gethost = shift;
114         my (@server, $host, $proto, $file, $allok, $i);
115         
116         logger("DOWNLOAD STARTED: $getfile") unless ($bfile =~ /^counter\?.*/);
117         use File::Basename;
118         $bfile = basename("$getfile");
119
120         $i = 0; 
121         while (($allok == 0) && $i < 5) {
122                 $i++;
123                 
124                 if ("$gethost" eq "") {
125                         @server = selectmirror();
126                         $proto = $server[0];
127                         $host = $server[1];
128                         $file = "$server[2]/$getfile";
129                 } else {
130                         $host = $gethost;
131                         $file = $getfile;
132                 }
133                 
134                 $proto = "HTTP" unless $proto;
135                 
136                 unless ($bfile =~ /^counter\?.*/) {
137                         logger("DOWNLOAD INFO: Host: $host ($proto) - File: $file");
138                 }
139
140                 my $ua = LWP::UserAgent->new;
141                 $ua->agent("Pakfire/$Conf::version");
142                 $ua->timeout(5);
143                 
144                 my %proxysettings=();
145                 &General::readhash("${General::swroot}/proxy/advanced/settings", \%proxysettings);
146
147                 if ($proxysettings{'UPSTREAM_PROXY'}) {
148                         logger("DOWNLOAD INFO: Upstream proxy: \"$proxysettings{'UPSTREAM_PROXY'}\"") unless ($bfile =~ /^counter\?.*/); 
149                         if ($proxysettings{'UPSTREAM_USER'}) {
150                                 $ua->proxy("http","http://$proxysettings{'UPSTREAM_USER'}:$proxysettings{'UPSTREAM_PASSWORD'}@"."$proxysettings{'UPSTREAM_PROXY'}/");
151                                 logger("DOWNLOAD INFO: Logging in with: \"$proxysettings{'UPSTREAM_USER'}\" - \"$proxysettings{'UPSTREAM_PASSWORD'}\"") unless ($bfile =~ /^counter\?.*/);
152                         } else {
153                                 $ua->proxy("http","http://$proxysettings{'UPSTREAM_PROXY'}/");
154                         }
155                 }
156
157                 $final_data = undef;
158                 my $url = "http://$host/$file";
159                 my $response;
160                 
161                 unless ($bfile =~ /^counter\?.*/) {
162                         my $result = $ua->head($url);
163                         my $remote_headers = $result->headers;
164                         $total_size = $remote_headers->content_length;
165                         logger("DOWNLOAD INFO: $file has size of $total_size bytes");
166                         
167                         $response = $ua->get($url, ':content_cb' => \&callback );
168                         message("");
169                 } else {
170                         $response = $ua->get($url);
171                 }
172                 
173                 my $code = $response->code();
174                 my $log = $response->status_line;
175                 logger("DOWNLOAD INFO: HTTP-Status-Code: $code - $log");
176                 
177                 if ( $code eq "500" ) {
178                         message("Giving up: There was no chance to get the file \"$getfile\" from any available server.\nThere was an error on the way. Please fix it.");
179                         return 1;
180                 }
181                 
182                 if ($response->is_success) {
183                         unless ($bfile =~ /^counter\?.*/) {
184                                 if (open(FILE, ">$Conf::tmpdir/$bfile")) {
185                                         print FILE $final_data;
186                                         close(FILE);
187                                         logger("DOWNLOAD INFO: File received. Start checking signature...");
188                                         if (system("gpg --verify \"$Conf::tmpdir/$bfile\" &>/dev/null") eq 0) {
189                                                 logger("DOWNLOAD INFO: Signature of $bfile is fine.");
190                                                 move("$Conf::tmpdir/$bfile","$Conf::cachedir/$bfile");
191                                         } else {
192                                                 message("DOWNLOAD ERROR: The downloaded file ($file) wasn't verified by IPFire.org. Sorry - Exiting...");
193                                                 exit 1;
194                                         }
195                                         logger("DOWNLOAD FINISHED: $file");
196                                         $allok = 1;
197                                         return 0;
198                                 } else {
199                                         logger("DOWNLOAD ERROR: Could not open $Conf::cachedir/$bfile for writing.");
200                                 }
201                         } else {
202                                 return 0;
203                         }
204                 }       else {
205                         logger("DOWNLOAD ERROR: $log");
206                 }
207         }
208         message("DOWNLOAD ERROR: There was no chance to get the file \"$getfile\" from any available server.\nMay be you should run \"pakfire update\" to get some new servers.");
209         return 1;
210 }
211
212 sub getmirrors {
213         use File::Copy;
214
215         logger("MIRROR: Trying to get a mirror list.");
216         
217         if ( -e "$Conf::dbdir/lists/server-list.db" ) {
218                 my @stat = stat("$Conf::dbdir/lists/server-list.db");
219                 my $time = time();
220                 $age = $time - $stat[9];
221         } else {
222                 # Force an update.
223                 $age = "86401";
224         }
225         
226         if ("$age" gt "86400") {
227                 fetchfile("$Conf::version/lists/server-list.db", "$Conf::mainserver");
228                 move("$Conf::cachedir/server-list.db", "$Conf::dbdir/lists/server-list.db");
229         }
230 }
231
232 sub getcoredb {
233         use File::Copy;
234
235         logger("CORE: Trying to get a core list.");
236         
237         if ( -e "$Conf::dbdir/lists/core-list.db" ) {
238                 my @stat = stat("$Conf::dbdir/lists/core-list.db");
239                 my $time = time();
240                 $age = $time - $stat[9];
241         } else {
242                 # Force an update.
243                 $age = "3601";
244         }
245         
246         if ("$age" gt "3600") {
247                 fetchfile("lists/core-list.db", "");
248                 move("$Conf::cachedir/core-list.db", "$Conf::dbdir/lists/core-list.db");
249         }
250 }
251
252
253 sub selectmirror {
254         ### Check if there is a current server list and read it.
255         #   If there is no list try to get one.
256         my $count = 0;
257         while (!(open(FILE, "<$Conf::dbdir/lists/server-list.db")) && ($count lt 5)) {
258                 $count++;
259                 getmirrors();
260         }
261         if ($count == 5) {
262                 message("MIRROR ERROR: Could not find or download a server list");
263                 exit 1;
264         }
265         my @lines = <FILE>;
266         close(FILE);
267
268         ### Count the number of the servers in the list
269         my $scount = 0;
270         my @newlines;
271         foreach (@lines) {
272                 if ("$_" =~ /.*;.*;.*;/ ) {
273                         push(@newlines,$_);
274                         $scount++;
275                 }
276         }
277         logger("MIRROR INFO: $scount servers found in list");
278         
279         ### Choose a random server and test if it is online
280         #   If the check fails try a new server.
281         #   This will never give up.
282         my $found = 0;
283         my $servers = 0;
284         while ($found == 0) {
285                 $server = int(rand($scount) + 1);
286                 $servers = 0;
287                 my ($line, $proto, $path, $host);
288                 my @templine;
289                 foreach $line (@newlines) {
290                         $servers++;
291                         if ($servers eq $server) {
292                                 @templine = split(/\;/, $line);
293                                 $proto = $templine[0];
294                                 $host = $templine[1];
295                                 $path = $templine[2];
296                                 if (pinghost("$host")) {
297                                         $found = 1;
298                                         return ($proto, $host, $path);
299                                 }
300                         }
301                 }
302         }
303 }
304
305 sub dbgetlist {
306         ### Update the database if the file is older than one day.
307         #   If you pass &Pakfire::dbgetlist(force) the list will be downloaded.
308         #   Usage is always with an argument.
309         my $force = shift;
310         my $age;
311         
312         use File::Copy;
313         
314         if ( -e "$Conf::dbdir/lists/packages_list.db" ) {
315                 my @stat = stat("$Conf::dbdir/lists/packages_list.db");
316                 my $time = time();
317                 $age = $time - $stat[9];
318         } else {
319                 # Force an update.
320                 $age = "3601";
321         }
322         
323         if (("$age" gt "3600") || ("$force" eq "force")) {
324                 fetchfile("lists/packages_list.db", "");
325                 move("$Conf::cachedir/packages_list.db", "$Conf::dbdir/lists/packages_list.db");
326         }
327 }
328
329 sub dblist {
330         ### This subroutine lists the packages.
331         #   You may also pass a filter: &Pakfire::dblist(filter) 
332         #   Usage is always with two arguments.
333         #   filter may be: all, notinstalled, installed
334         my $filter = shift;
335         my $forweb = shift;
336         my @meta;
337         my @updatepaks;
338         my $file;
339         my $line;
340         my $prog;
341         my ($name, $version, $release);
342         my @templine;
343         
344         ### Make sure that the list is not outdated. 
345         dbgetlist("noforce");
346
347         open(FILE, "<$Conf::dbdir/lists/packages_list.db");
348         my @db = <FILE>;
349         close(FILE);
350
351         if ("$filter" eq "upgrade") {
352                 getcoredb();
353                 eval(`grep "core_" $Conf::dbdir/lists/core-list.db`);
354                 if ("$core_release" gt "$Conf::core_mine") {
355                         if ("$forweb" eq "forweb") {
356                                 print "<option value=\"core\">Core-Update -- $Conf::version -- Release: $Conf::core_mine -> $core_release</option>\n";
357                         } else {
358                                 my $command = "Core-Update $Conf::version\nRelease: $Conf::core_mine -> $core_release\n";
359                                 if ("$Pakfire::enable_colors" eq "1") {
360                                         print "$color{'lila'}$command$color{'normal'}\n";
361                                 } else {
362                                         print "$command\n";
363                                 }
364                         }
365                 }
366         
367                 opendir(DIR,"$Conf::dbdir/meta");
368                 my @files = readdir(DIR);
369                 closedir(DIR);
370                 foreach $file (@files) {
371                         next if ( $file eq "." );
372                         next if ( $file eq ".." );
373                         open(FILE, "<$Conf::dbdir/meta/$file");
374                         @meta = <FILE>;
375                         close(FILE);
376                         foreach $line (@meta) {
377                                 @templine = split(/\: /,$line);
378                                 if ("$templine[0]" eq "Name") {
379                                         $name = $templine[1];
380                                         chomp($name);
381                                 } elsif ("$templine[0]" eq "ProgVersion") {
382                                         $version = $templine[1];
383                                         chomp($version);
384                                 } elsif ("$templine[0]" eq "Release") {
385                                         $release = $templine[1];
386                                         chomp($release);
387                                 }
388                         }
389                         foreach $prog (@db) {
390                                 @templine = split(/\;/,$prog);
391                                 if (("$name" eq "$templine[0]") && ("$release" < "$templine[2]" )) {
392                                         push(@updatepaks,$name);
393                                         if ("$forweb" eq "forweb") {
394                                                 print "<option value=\"$name\">Update: $name -- Version: $version -> $templine[1] -- Release: $release -> $templine[2]</option>\n";
395                                         } else {
396                                                 my $command = "Update: $name\nVersion: $version -> $templine[1]\nRelease: $release -> $templine[2]\n";
397                                                 if ("$Pakfire::enable_colors" eq "1") {
398                                                         print "$color{'lila'}$command$color{'normal'}\n";
399                                                 } else {
400                                                         print "$command\n";
401                                                 }
402                                         }
403                                 }
404                         }
405                 }
406                 return @updatepaks;
407         } else {
408                 my $line;
409                 my $use_color;
410                 my @templine;
411                 my $count;
412                 foreach $line (sort @db) {
413                         next unless ($line =~ /.*;.*;.*;/ );
414                         $use_color = "";
415                         $count++;
416                         @templine = split(/\;/,$line);
417                         if ("$filter" eq "notinstalled") {
418                                 next if ( -e "$Conf::dbdir/installed/meta-$templine[0]" );
419                         } elsif ("$filter" eq "installed") {
420                                 next unless ( -e "$Conf::dbdir/installed/meta-$templine[0]" );
421                         }
422                         if ("$forweb" eq "forweb") {
423                                 print "<option value=\"$templine[0]\">$templine[0]-$templine[1]-$templine[2]</option>\n";
424                         } else {
425                                 if ("$Pakfire::enable_colors" eq "1") {
426                                         if (&isinstalled("$templine[0]")) {
427                                                 $use_color = "$color{'red'}" 
428                                         } else {
429                                                 $use_color = "$color{'green'}"
430                                         }
431                                 }
432                                 print "${use_color}Name: $templine[0]\nProgVersion: $templine[1]\nRelease: $templine[2]$color{'normal'}\n\n";
433                         }
434                 }
435                 print "$count packages total.\n" unless ("$forweb" eq "forweb");
436         }
437 }
438
439 sub resolvedeps {
440         my $pak = shift;
441         
442         getmetafile("$pak");
443         
444         message("PAKFIRE RESV: $pak: Resolving dependencies...");
445         
446         open(FILE, "<$Conf::dbdir/meta/meta-$pak");
447         my @file = <FILE>;
448         close(FILE);
449         
450         my $line;
451         my (@templine, @deps, @tempdeps, @all);
452         foreach $line (@file) {
453                 @templine = split(/\: /,$line);
454                 if ("$templine[0]" eq "Dependencies") {
455                         @deps = split(/ /, $templine[1]);
456                 }
457         }
458         chomp (@deps);
459         foreach (@deps) {
460                 if ($_) {
461                   my $return = &isinstalled($_);
462                   if ($return eq 0) {
463                         message("PAKFIRE RESV: $pak: Dependency is already installed: $_");
464                   } else {
465                         message("PAKFIRE RESV: $pak: Need to install dependency: $_");
466                                 push(@tempdeps,$_);
467                                 push(@all,$_);
468                         } 
469                 }
470         }
471
472         foreach (@tempdeps) {
473                 if ($_) {
474                         my @newdeps = resolvedeps("$_");
475                         foreach(@newdeps) {
476                                 unless (($_ eq " ") || ($_ eq "")) {
477                                         my $return = &isinstalled($_);
478                                         if ($return eq 0) {
479                                                 message("PAKFIRE RESV: $pak: Dependency is already installed: $_");
480                                         } else {
481                                                 message("PAKFIRE RESV: $pak: Need to install dependency: $_");
482                                                 push(@all,$_);
483                                         }
484                                 }
485                         }
486                 }
487         }
488         message("");
489         chomp (@all);
490         return @all;
491 }
492
493 sub cleanup {
494         my $dir = shift;
495         my $path;
496         
497         logger("CLEANUP: $dir");
498         
499         if ( "$dir" eq "meta" ) {
500                 $path = "$Conf::dbdir/meta";
501         } elsif ( "$dir" eq "tmp" ) {
502                 $path = "$Conf::tmpdir";
503         }
504         chdir("$path");
505         opendir(DIR,".");
506         my @files = readdir(DIR);
507         closedir(DIR);
508         foreach (@files) {
509           unless (($_ eq ".") || ($_ eq "..")) {
510                    system("rm -rf $_");
511                 }
512         }
513 }
514
515 sub getmetafile {
516         my $pak = shift;
517         
518         unless ( -e "$Conf::dbdir/meta/meta-$pak") {
519                 fetchfile("meta/meta-$pak", "");
520                 move("$Conf::cachedir/meta-$pak", "$Conf::dbdir/meta/meta-$pak");
521         }
522         
523         open(FILE, "<$Conf::dbdir/meta/meta-$pak");
524         my @line = <FILE>;
525         close(FILE);
526         
527         open(FILE, ">$Conf::dbdir/meta/meta-$pak");
528         foreach (@line) {
529                 my $string = $_;
530                 $string =~ s/\r\n/\n/g;
531                 print FILE $string;
532         }
533         close(FILE);
534         return 1;
535 }
536
537 sub getsize {
538         my $pak = shift;
539         
540         getmetafile("$pak");
541         
542         open(FILE, "<$Conf::dbdir/meta/meta-$pak");
543         my @file = <FILE>;
544         close(FILE);
545         
546         my $line;
547         my @templine;
548         foreach $line (@file) {
549                 @templine = split(/\: /,$line);
550                 if ("$templine[0]" eq "Size") {
551                         chomp($templine[1]);
552                         return $templine[1];
553                 }
554         }
555         return 0;
556 }
557
558 sub decryptpak {
559         my $pak = shift;
560         
561         cleanup("tmp");
562         
563         my $file = getpak("$pak", "noforce");
564         
565         logger("DECRYPT STARTED: $pak");
566         my $return = system("cd $Conf::tmpdir/ && gpg -d --batch --quiet --no-verbose --status-fd 2 --output - < $Conf::cachedir/$file 2>/dev/null | tar x");
567         $return %= 255;
568         logger("DECRYPT FINISHED: $pak - Status: $return");
569         if ($return != 0) { exit 1; }
570 }
571
572 sub getpak {
573         my $pak = shift;
574         my $force = shift;
575
576         getmetafile("$pak");
577         
578         open(FILE, "<$Conf::dbdir/meta/meta-$pak");
579         my @file = <FILE>;
580         close(FILE);
581         
582         my $line;
583         my $file;
584         my @templine;
585         foreach $line (@file) {
586                 @templine = split(/\: /,$line);
587                 if ("$templine[0]" eq "File") {
588                         chomp($templine[1]);
589                         $file = $templine[1];
590                 }
591         }
592         
593         unless ($file) {
594                 message("No filename given in meta-file. Please phone the developers.");
595                 exit 1;
596         }
597         
598         unless ( "$force" eq "force" ) {
599                 if ( -e "$Conf::cachedir/$file" ) {
600                         return $file;
601                 }
602         }
603         
604         fetchfile("paks/$file", "");
605         return $file;
606 }
607
608 sub setuppak {
609         my $pak = shift;
610         
611         message("PAKFIRE INST: $pak: Decrypting...");
612         decryptpak("$pak");
613         
614         message("PAKFIRE INST: $pak: Copying files and running post-installation scripts...");
615         my $return = system("cd $Conf::tmpdir && NAME=$pak ./install.sh >> $Conf::logdir/install-$pak.log 2>&1");
616         $return %= 255;
617         if ($pakfiresettings{'UUID'} ne "off") {
618                 fetchfile("cgi-bin/counter?ver=$Conf::version&uuid=$Conf::uuid&ipak=$pak&return=$return", "$Conf::mainserver");
619         }
620         if ($return == 0) {
621           move("$Conf::tmpdir/ROOTFILES", "$Conf::dbdir/rootfiles/$pak");
622           cleanup("tmp");
623           copy("$Conf::dbdir/meta/meta-$pak","$Conf::dbdir/installed/");
624                 message("PAKFIRE INST: $pak: Finished.");
625                 message("");
626         } else {
627                 message("PAKFIRE ERROR: Returncode: $return. Sorry. Please search our forum to find a solution for this problem.");
628                 exit $return;
629         }
630         return $return;
631 }
632
633 sub upgradecore {
634         getcoredb();
635         eval(`grep "core_" $Conf::dbdir/lists/core-list.db`);
636         if ("$core_release" gt "$Conf::core_mine") {
637                 message("CORE UPGR: Upgrading from release $Conf::core_mine to $core_release");
638                 
639                 my @seq = `seq $Conf::core_mine $core_release`;
640                 shift @seq;
641                 my $release;
642                 foreach $release (@seq) {
643                         chomp($release);
644                         getpak("core-upgrade-$release");
645                 }
646                 
647                 foreach $release (@seq) {
648                         chomp($release);
649                         upgradepak("core-upgrade-$release");
650                 }
651                 
652                 system("echo $core_release > $Conf::coredir/mine");
653                 
654         } else {
655                 message("CORE ERROR: No new upgrades available. You are on release $Conf::core_mine.");
656         }
657 }
658
659 sub isinstalled {
660         my $pak = shift;
661         if ( open(FILE,"<$Conf::dbdir/installed/meta-$pak") ) {
662                 close(FILE);
663                 return 0;
664         } else {
665                 return 1;
666         }
667 }
668
669 sub upgradepak {
670         my $pak = shift;
671
672         message("PAKFIRE UPGR: $pak: Decrypting...");
673         decryptpak("$pak");
674
675         message("PAKFIRE UPGR: $pak: Upgrading files and running post-upgrading scripts...");
676         my $return = system("cd $Conf::tmpdir && NAME=$pak ./update.sh >> $Conf::logdir/update-$pak.log 2>&1");
677         $return %= 255;
678         if ($pakfiresettings{'UUID'} ne "off") {
679                 fetchfile("cgi-bin/counter?ver=$Conf::version&uuid=$Conf::uuid&upak=$pak&return=$return", "$Conf::mainserver");
680         }
681         if ($return == 0) {
682           move("$Conf::tmpdir/ROOTFILES", "$Conf::dbdir/rootfiles/$pak");
683           cleanup("tmp");
684                 copy("$Conf::dbdir/meta/meta-$pak","$Conf::dbdir/installed/");
685                 message("PAKFIRE UPGR: $pak: Finished.");
686                 message("");
687         } else {
688                 message("PAKFIRE ERROR: Returncode: $return. Sorry. Please search our forum to find a solution for this problem.");
689                 exit $return;
690         }
691         return $return;
692 }
693
694 sub removepak {
695         my $pak = shift;
696
697         message("PAKFIRE REMV: $pak: Decrypting...");
698         decryptpak("$pak");
699
700         message("PAKFIRE REMV: $pak: Removing files and running post-removing scripts...");
701         my $return = system("cd $Conf::tmpdir && NAME=$pak ./uninstall.sh >> $Conf::logdir/uninstall-$pak.log 2>&1");
702         $return %= 255;
703         if ($pakfiresettings{'UUID'} ne "off") {
704                 fetchfile("cgi-bin/counter?ver=$Conf::version&uuid=$Conf::uuid&dpak=$pak&return=$return", "$Conf::mainserver");
705         }
706         if ($return == 0) {
707           open(FILE, "<$Conf::dbdir/rootfiles/$pak");
708                 my @file = <FILE>;
709                 close(FILE);
710                 foreach (@file) {
711                   my $line = $_;
712                   chomp($line);
713                         system("echo \"Removing: $line\" >> $Conf::logdir/uninstall-$pak.log 2>&1");
714                         system("cd / && rm -rf $line >> $Conf::logdir/uninstall-$pak.log 2>&1");
715                 }
716           unlink("$Conf::dbdir/rootfiles/$pak");
717           unlink("$Conf::dbdir/installed/meta-$pak");
718           cleanup("tmp");
719                 message("PAKFIRE REMV: $pak: Finished.");
720                 message("");
721         } else {
722                 message("PAKFIRE ERROR: Returncode: $return. Sorry. Please search our forum to find a solution for this problem.");
723                 exit $return;
724         }
725         return $return;
726 }
727
728 sub beautifysize {
729         my $size = shift;
730         #$size = $size / 1024;
731         my $unit;
732         
733         if ($size > 1023*1024) {
734           $size = ($size / (1024*1024));
735           $unit = "MB";
736         } elsif ($size > 1023) {
737           $size = ($size / 1024);
738           $unit = "KB";
739         } else {
740           $unit = "B";
741         }
742         $size = sprintf("%.2f" , $size);
743         my $string = "$size $unit";
744         return $string;
745 }
746
747 sub makeuuid {
748         unless ( -e "$Conf::dbdir/uuid" ) {
749                 open(FILE, "</proc/sys/kernel/random/uuid");
750                 my @line = <FILE>;
751                 close(FILE);
752                 
753                 open(FILE, ">$Conf::dbdir/uuid");
754                 foreach (@line) {
755                         print FILE $_;
756                 }
757                 close(FILE);
758         }
759 }
760
761 sub senduuid {
762         if ($pakfiresettings{'UUID'} ne "off") {
763                 unless("$Conf::uuid") {
764                         $Conf::uuid = `cat $Conf::dbdir/uuid`;
765                 }
766                 logger("Sending my uuid: $Conf::uuid");
767                 fetchfile("cgi-bin/counter?ver=$Conf::version&uuid=$Conf::uuid", "$Conf::mainserver");
768                 system("rm -f $Conf::tmpdir/counter* 2>/dev/null");
769         }
770 }
771
772 sub checkcryptodb {
773         logger("CRYPTO INFO: Checking GnuPG Database");
774         my $ret = system("gpg --list-keys | grep -q $myid");
775         unless ( "$ret" eq "0" ) {
776                 message("CRYPTO WARN: The GnuPG isn't configured corectly. Trying now to fix this.");
777                 message("CRYPTO WARN: It's normal to see this on first execution.");
778                 my $command = "gpg --keyserver pgp.mit.edu --always-trust --status-fd 2";
779                 system("$command --recv-key $myid >> $Conf::logdir/gnupg-database.log 2>&1");
780                 system("$command --recv-key $trustid >> $Conf::logdir/gnupg-database.log 2>&1");
781         } else {
782                 logger("CRYPTO INFO: Database is okay");
783         }
784 }
785
786 sub callback {
787    my ($data, $response, $protocol) = @_;
788    $final_data .= $data;
789    print progress_bar( length($final_data), $total_size, 30, '=' );
790 }
791
792 sub progress_bar {
793     my ( $got, $total, $width, $char ) = @_;
794     my $show_bfile;
795     $width ||= 30; $char ||= '=';
796     my $len_bfile = length $bfile;
797     if ("$len_bfile" >= "17") {
798                         $show_bfile = substr($bfile,0,17)."...";
799                 } else {
800                         $show_bfile = $bfile;
801                 }       
802                 $progress = sprintf("%.2f%%", 100*$got/+$total);
803     sprintf "$color{'lightgreen'}%-20s %7s |%-${width}s| %10s$color{'normal'}\r",$show_bfile, $progress, $char x (($width-1)*$got/$total). '>', beautifysize($got);
804 }
805
806 1;