2 # Mail robot for processing of PCI ID submissions
3 # (c) 2001--2002 Martin Mares <mj@ucw.cz>
4 # 2008 Michal Vaner <vorner@ucw.cz>
14 use PciIds::Notifications;
24 'emulate!' => \$emulate,
26 'orig=s' => \$original,
27 'author=s' => \$author
28 ) || die "Usage: mailbot [--patch] [--emulate] [--debug] [--orig <name>] [--author <mailaddr>]";
34 my $tables = PciIds::DBQ::new( connectDb() );
36 my $hasAuth = $tables->dbh()->prepare( 'SELECT id FROM users WHERE email = ?' );
37 my $addAuth = $tables->dbh()->prepare( "INSERT INTO users (email, passwd) VALUES(?, '')" );
38 my $hasItem = $tables->dbh()->prepare( "SELECT 1 FROM locations WHERE id = ?" );
39 my $addItem = $tables->dbh()->prepare( "INSERT INTO locations (id, parent) VALUES (?, ?)" );
40 my $addComment = $tables->dbh()->prepare( "INSERT INTO history (owner, location, discussion, nodename, nodenote) VALUES (?, ?, ?, ?, ?)" );
44 $hasAuth->execute( $mail );
45 if( my( $id ) = $hasAuth->fetchrow_array ) {
48 tlog( "mailbot: Creating user $mail" );
49 $addAuth->execute( $mail );
50 my $nid = $dbh->last_insert_id( undef, undef, undef, undef );
51 tlog( "mailbot: User ($mail) id: $nid" );
56 sub submitItem( $$$$$ ) {
57 my( $id, $name, $description, $text, $author ) = @_;
59 $id =~ s/(.{8})(.*)/$1\\$2/;
60 $id =~ s/(.{4})(.*)/$1\\$2/;
62 $hasItem->execute( $id );
63 unless( $hasItem->fetchrow_array ) {
64 tlog( "mailbot: Item created (empty) $id" );
66 $parent =~ s/\/[^\/]*//;
67 $addItem->execute( $id, $parent );
70 $addComment->execute( $author, $id, $text, $name, $description );
71 my $hid = $tables->last();
72 tlog( "mailbot: Comment created $hid $id ".logEscape( $name )." ".logEscape( $description )." ".logEscape( $text ) );
73 notify( $tables, $id, $hid, $created ? 2 : 1, $created ? 0 : 1 );
77 $hdr = new Mail::Header;
79 $hdr->mail_from(COERCE);
80 $hdr->read(*STDIN{IO});
82 $mfrom = $hdr->get('Mail-From');
84 ($mfrom =~ /^MAILER-DAEMON@/i) && blackhole("From mailer daemon");
85 $mfrom =~ s/ .*// or blackhole("Malformed envelope sender");
86 ($reply = $hdr->get('Reply-To')) || ($reply = $hdr->get('From')) ||
87 blackhole("Don't know who should I reply to");
89 if ($reply =~ /<(\S*)>/) {
91 } elsif ($reply =~ /^\S+$/) {
92 $reply_plain = $reply;
94 $reply_plain = $mfrom;
96 $reply_plain =~ tr/\n'"\\//d;
97 $msgid = $hdr->get('Message-Id');
99 my $subj = $hdr->get('Subject');
101 if ($subj =~ /^IDS: (.*)/) {
104 $author = $reply_plain;
107 $tprefix = "tmp/mbot-$$";
110 mkdir($tprefix, 0777) || error("Cannot create tmpdir");
111 chdir($tprefix) || error("Cannot chdir to tmpdir");
113 open(TEMP, ">patch") || error("Cannot create tmpfile");
114 if ($debug || $reply eq "") {
115 open(LOG, ">&STDOUT") || error ("Cannot create outfile");
117 open(LOG, ">log") || error ("Cannot create outfile");
121 print LOG "Got mail from $reply, will reply to $reply_plain.\n";
122 print LOG "Scanning mail for patch.\n";
124 print LOG "Scanning STDIN for patch.\n";
136 if (/^\s*$/ || !/^[ +\@-]/) {
142 /^@@ -\d+,(\d+) \+\d+,(\d+) @@/ || error("Malformed patch");
145 while ($old || $new) {
148 if (/^ /) { $old--; $new--; }
149 elsif (/^-/) { $old--; }
150 elsif (/^\+/) { $new--; }
151 else { error("Malformed patch"); }
152 if ($old<0 || $new<0) { error("Malformed patch"); }
158 error("No patch found");
163 `rm -rf $tprefix` unless $debug;
169 my $reason = shift @_;
170 print STDERR "Blackholed: $reason\n";
176 my $reason = shift @_;
177 print LOG "$reason\n";
184 print LOG "Patch found.\n";
185 print LOG "Searching for original pci.ids version.\n";
186 foreach $orig (($original eq "") ? glob("$home/origs/*") : ("../../$original")) {
187 print LOG "Trying $orig\n";
190 print LOG `/usr/bin/patch <patch --no-backup -o pci.ids -r pci.rej $orig`;
192 print LOG "Failed.\n";
194 print LOG "Patch succeeded.\n";
195 print LOG "Parsing patched file.\n";
196 print LOG `$home/tools/ids_to_dbdump <$orig 2>&1 >orig.db.unsorted`;
197 $? && error("Error parsing original ID database");
198 print LOG `sort +1 <orig.db.unsorted >orig.db`;
199 $? && error("Error sorting original ID database");
200 print LOG `$home/tools/ids_to_dbdump <pci.ids 2>&1 >new.db.unsorted`;
201 $? && error("Error parsing the patched pci.ids file");
202 print LOG `sort +1 <new.db.unsorted >new.db`;
203 $? && error("Error sorting the patched pci.ids file");
204 print LOG "Finding ID differences.\n";
205 `diff -U0 new.db orig.db >diffs`;
206 if ($? > 256) { error("Diff failed. Why?"); }
207 elsif (!$?) { error("No ID changes encountered."); }
208 open(DIFF, "diffs") || error("Cannot open the diff");
209 $subject = undef if $subject eq '';
210 my $authorId = getAuthor( $author );
211 my $live = (!$emulate && !$debug);
214 /^(\+\+\+|---)/ && next;
216 ($tt,$id,$name,$stat,$cmt) = split /\t/;
217 if ($tt =~ /^\+(.*)/) {
218 defined $seen{$id} && next;
220 } elsif ($tt =~ /^-(.*)/) {
222 } else { error("Internal bug #23"); }
223 print LOG "$id\t$name\t$cmt\n";
224 submitItem( $id, $name, $cmt, $subject, $authorId ) if $live;
229 `echo >>$home/log/mailbot.log "## $time $reply"`;
230 `cat result >>$home/log/mailbot.log`;
236 error("Unable to find any version of pci.ids the patch applies to.");
241 my $reason = shift @_;
242 my $sendmail_opts = "-fmj+iderr\@ucw.cz '$reply_plain' mj+idecho\@ucw.cz";
243 if ($debug || $reply eq "") {
247 open(MAIL, ">&STDOUT") || die;
248 print MAIL "SENDMAIL $sendmail_opts\n";
249 } elsif (!open MAIL, "|/usr/sbin/sendmail $sendmail_opts") {
250 print STDERR "Unable to ask mailer for replying!!!\n";
251 print LOG "Unable to ask mailer for replying!!!\n";
254 print MAIL "From: The PCI ID Robot <mj+iderr\@ucw.cz>\n";
255 print MAIL "To: $reply\n";
256 print MAIL "Subject: IDbot: $reason\n";
257 print MAIL "In-Reply-To: $msgid\n" if $msgid ne "";
260 This is an automatic reply from the PCI ID Mail Robot. If you want to contact
261 the administrator of the robot, please write to pciids-devel\@lists.sourceforge.net.
265 if ($reason eq "OK") {
266 print MAIL "Your submission has been accepted.\n\n";
269 Your submission has been rejected. Please make sure that the mail you've sent
270 is a unified diff (output of diff -u) against the latest pci.ids file, that
271 the diff is not reversed and that your mailer doesn't damage long lines
272 and doesn't change tabs to spaces or vice versa. Also, we don't accept MIME
273 attachments in base64 encoding yet. If you are unable to fix your problems,
274 just use the Web interface at http://pciids.sf.net/ or submit the patch
275 to pciids-devel\@lists.sourceforge.net where it will be processed manually.
276 See the log below for additional information.
281 print MAIL "--- Processing Log ---\n\n";
282 if (open L, "<log") {
283 while (<L>) { print MAIL "$_"; }
286 print MAIL "\n--- End ---\n";
293 s/([^a-zA-Z0-9.!*,_-])/'%'.unpack('H2',$1)/ge;