X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?a=blobdiff_plain;f=pctb%2Fcommod-update-receiver;h=11064cd7d9b6897f9194116690602eebb71e3e81;hb=34c9aa9031897dada3450d014de96d68a5834039;hp=b7bf4cb80eba6f58ba954c6d484fe42d84212b10;hpb=769239e4cc9af0b88578d1b15a1b14a7cb3dc7ba;p=ypp-sc-tools.db-live.git diff --git a/pctb/commod-update-receiver b/pctb/commod-update-receiver index b7bf4cb..11064cd 100755 --- a/pctb/commod-update-receiver +++ b/pctb/commod-update-receiver @@ -36,11 +36,11 @@ use strict (qw(vars)); use POSIX; +use MIME::Entity; use Commods; $CGI::POST_MAX= 3*1024*1024; -$CGI::DISABLE_UPLOADS= 1; use CGI qw/:standard -private_tempfiles/; @@ -67,75 +67,78 @@ sub must_param ($$) { return $1; } -my $clientname= must_param('clientname',$re_any); -my $clientinfo= $clients{$clientname}; +my %o; + +$o{'clientname'}= must_param('clientname',$re_any); +my $clientinfo= $clients{$o{'clientname'}}; fail('unknown client') unless defined $clientinfo; my $clientfixes= must_param('clientfixes', "^([-0-9a-z ]*)\$"); my @clientfixes= sort grep { m/./ } split /\s+/, $clientfixes; -$clientfixes= "@clientfixes"; +$o{'clientfixes'}= "@clientfixes"; foreach my $bug (@$clientinfo) { fail("client out of date - missing bugfix \`$bug'") unless grep { $_ eq $bug } @clientfixes; } -my $clientversion= must_param('clientversion', "^(\\d[-+._0-9a-zA-Z]+)\$"); +$o{'clientversion'}= must_param('clientversion', "^(\\d[-+._0-9a-zA-Z]+)\$"); -my $ocean= must_param('ocean', $re_any); -my $island= must_param('island', $re_any); +$o{'ocean'}= must_param('ocean', $re_any); +$o{'island'}= must_param('island', $re_any); -my $arches= $oceans{$ocean}; +my $arches= $oceans{$o{'ocean'}}; fail("unknown ocean") unless $arches; my $island_found= 0; foreach my $islands (values %$arches) { - my $sources= $islands->{$island}; + my $sources= $islands->{$o{'island'}}; next unless $sources; die if $island_found; $island_found= $sources; } fail("unknown island") unless $island_found; -my $timestamp= must_param('timestamp', "^([1-9]\\d{1,20})\$"); +$o{'timestamp'}= must_param('timestamp', "^([1-9]\\d{1,20})\$"); my $now= time; defined $now or die $!; -fail("clock skew") if $timestamp >= $now; +fail("clock skew") if $o{'timestamp'} >= $now; -die if $ocean =~ m/\=/; -die if $island =~ m/\=/; +die if $o{'ocean'} =~ m/\=/; +die if $o{'island'} =~ m/\=/; my $indatafh= upload('data'); defined $indatafh or fail("data is not a file"); my $datafile= must_param('data',"^(deduped\\.tsv\\.gz)\$"); -our %done; - my $mcontent= MIME::Entity->build(To => 'yarrg-commod-updates', Type => 'multipart/mixed', Boundary => '=', Charset => 'utf-8'); -our ($servername,$serverversion,$serverfixes); -get_our_version('::server'); - -my $clientspec= "$clientname $clientversion $clientfixes"; -my $serverspec= "$servername $serverversion $serverfixes"; +get_our_version(\%o, 'server'); +foreach my $cs (qw(client server)) { + $o{"${cs}spec"}= join ' ', map { $o{$cs.$_} } qw(name version fixes); +} -foreach my $vn (qw(ocean island timestamp - clientspec clientname clientversion clientfixes - serverspec servername serverversion serverfixes)) { - my $mpart= MIME::Entity->build(Type => 'text/plain', +foreach my $vn (sort keys %o) { + my $mpart= MIME::Entity->build(Top => 0, + Type => 'text/plain', Charset => 'utf-8', - Disposition => 'inline', - Data => $$vn); + Disposition => 'attachment', + Filename => $vn, + Data => $o{$vn}); $mcontent->add_part($mpart); } -my $gunzchild= open(GZ, "-|") or die $!; +my $gunzchild= open(GZ, "-|"); defined $gunzchild or die $!; if (!$gunzchild) { open STDIN, "<&=", $indatafh or die $!; - execlp 'gunzip'; die $!; + exec 'gunzip'; die $!; } +sub bad_data ($) { fail("bad data: line $.: $_[0]"); } + +our %done; + while () { !m/\P{IsPrint}/ or die bad_data('nonprinting char(s)'); !m/\\/ or bad_data('data contains backslashes'); @@ -143,27 +146,33 @@ while () { @v==6 or bad_data('wrong number of fields'); my ($commod,$stall) = @v; defined $commods{$commod} or bad_data("unknown commodity \`$commod'"); - $stall =~ m/^\p{IsUpper}/ or bad_data("stall not capitalised"); + $stall =~ m/^\p{IsUpper}|^[0-9]/ or bad_data("stall not capitalised"); !exists $done{$commod,$stall} or bad_data("repeated data"); $done{$commod,$stall}= 1; foreach my $i (2..5) { my $f= $v[$i]; - $f =~ m/^(0|[1-9][0-9]{0,5}|\>1000)$/ or bad_data("bad field"); - ($i % 1) or ($f !~ m/\>/) or bad_data("> in price"); + $f =~ m/^(|0|[1-9][0-9]{0,5}|\>1000)$/ or bad_data("bad field $i"); + ($i % 2) or ($f !~ m/\>/) or bad_data("> in field $i price"); } } GZ->error and die $!; $?=0; close GZ; $? and fail("gunzip for check failed code $?"); -my $mdatafile= MIME::Entity->build(Type => 'application/octet-stream', +my $mdatafile= MIME::Entity->build(Top => 0, + Type => 'application/octet-stream', Disposition => 'attachment', Encoding => 'base64', - File => $datafile); + Filename => 'deduped.tsv.gz', + Path => $datafile); $mcontent->add_part($mdatafile); -open M, "|/usr/sbin/sendmail -t -oi -oee -odq" +open M, "|/usr/sbin/sendmail -t -oi -oee -odb" or fail("fork sendmail failed! ($!)"); $mcontent->print(\*M); M->error and fail("write sendmail failed! ($!)"); $?=0; close M; $? and fail("sendmail failed code $?"); + +print header(-type=>'text/plain', -charset=>'us-ascii'), + "OK\n" + or die $!;