#!/usr/bin/env perl use v5.10.1; use strict; use warnings; use DBI; use File::Basename; use Digest::MD5 qw(md5_hex); use Digest::SHA qw(sha1_hex sha224_hex sha256_hex sha384_hex sha512_hex); #Return number of good solutions my $exit = 0; my $root = dirname(__FILE__); chdir($root); # First, read PHP configuration to extract some settings my $profile; my $submission_dir; open my $conf, "<", "$root/onyx/config/root.xml"; for my $p (<$conf>) { if ($p =~ /<(?:option|var) name="(.*)">(.*)<\/(?:option|var)>/) { $profile = $2 if ($1 eq "profile"); $submission_dir = $2 if ($1 eq "submission_dir"); } } close $conf; my $end_time = 1999999999; if (-f "$root/misc/challenge_started") { open my $conf, "<", "$root/misc/challenge_started"; $end_time = <$conf>; close $conf; chomp($end_time); $end_time += 14400; } die("TIME expired!") if time() > $end_time; die("No DB profile found") if ! $profile; die("submission_dir is not a directory") if ! $submission_dir || ! -d $submission_dir; # Read db settings my %db_settings; open my $dbprof, "<", "$root/onyx/db/$profile.profile.php"; while (<$dbprof>) { if (/\$___profile\[['"](.+)['"]\] = ['"](.+)['"]/) { $db_settings{$1} = $2; } } close $dbprof; my $dbh; # List all files to treat opendir(my $dh, $submission_dir) || die "Can't opendir submission_dir: $!"; for my $f (readdir $dh) { if ($f =~ /^([0-9]+)-([0-9]+)-([a-zA-Z0-9_]+)$/) { my $good = -1; my $team = $1; my $theme = $2; my $exercice = $3; open my $fh, "<", "$submission_dir/$f"; my $solution = <$fh>; close $fh; $dbh = DBI->connect("DBI:mysql:database=$db_settings{db};host=$db_settings{host};port=3306", $db_settings{user}, $db_settings{pass}, {'RaiseError' => 1, 'PrintError' => 1}) or die $DBI::errstr if !$dbh; query($dbh, "INSERT INTO exercice_tries (id_exercice, id_team, time) VALUES ('$exercice', $team, CURRENT_TIMESTAMP);"); my $sth = query($dbh, "SELECT format, value FROM exercice_keys WHERE id_exercice = ".$dbh->quote($exercice)); # Check solutions while (my $row = get_row($sth)) { $good = 1 if ($good == -1); my $type = @$row[0]; my $sol = @$row[1]; my $tmp_solution = $solution; if ($type eq "md5") { $tmp_solution = md5_hex($solution); } elsif ($type eq "sha1") { $tmp_solution = sha1_hex($solution); } elsif ($type eq "sha224") { $tmp_solution = sha224_hex($solution); } elsif ($type eq "sha256") { $tmp_solution = sha256_hex($solution); } elsif ($type eq "sha384") { $tmp_solution = sha384_hex($solution); } elsif ($type eq "sha512") { $tmp_solution = sha512_hex($solution); } elsif ($type ne "raw") { warn "$type not implemented"; } say STDERR "check: $sol vs $tmp_solution"; if ($sol ne $tmp_solution) { $good = 0; last; } } # Register solve if ($good == -1) { say STDERR localtime().": Exercice $exercice doesn't exist ; given by team $team in theme $theme."; } elsif ($good == 1) { # Check if the exercice exists $sth = query($dbh, "SELECT `require` FROM exercices E WHERE E.id_theme = $theme AND E.id = ".$dbh->quote($exercice)); if ($sth->rows) { my $row = get_row($sth); # Check if the team has solved dependancies $sth = query($dbh, "SELECT S.id FROM solved S WHERE S.id_exercice = ".$dbh->quote(@$row[0])) if @$row[0]; if (! @$row[0] || $sth->rows) { # Check if the team has not already solved this exercice $sth = query($dbh, "SELECT S.id FROM solved S WHERE S.id_exercice = ".$dbh->quote($exercice)); if (! $sth->rows) { say "resetresetreset:TEAM$team,$theme:SYNCSYN:TEAM$team:SYNC:HOME:SYNC:all:DS"; say STDERR localtime().": Team $team solve exercice $exercice in $theme"; query($dbh, "INSERT INTO solved (id_team, id_exercice, time) VALUES ($team, ".$dbh->quote($exercice).", CURRENT_TIMESTAMP);"); $exit++; } else { warn localtime().": Team $team try to solve exercice $exercice in $theme but ALREADY solved it"; } } else { warn localtime().": Team $team try to solve exercice $exercice in $theme but has NOT SOLVED required exercice ".@$row[0]; } } else { warn localtime().": Team $team try to solve exercice $exercice in $theme but does not exist"; } } else { say "resetresetreset:TEAM$team,$theme:SYNCSYN"; say STDERR localtime().": Team $team didn't give the correct answer for exercice $exercice."; } # Remove the file unlink("$submission_dir/$f"); } } closedir $dh; $dbh->disconnect() if $dbh; exit( $exit > 126 ? 126 : $exit ); sub query { my $sth = $_[0]->prepare($_[1]); $sth->execute(); die($_[0]->errstr) if (!$sth); return $sth; } sub get_row { return $_[0]->fetchrow_arrayref(); }