/** * Send an email notice about bug aditions and edits * * @param * * @return void */ function mail_bug_updates($bug, $in, $from, $ncomment, $edit = 1, $id = false) { global $tla, $bug_types, $siteBig, $site_method, $site_url, $basedir; $text = array(); $headers = array(); $changed = bug_diff($bug, $in); $from = str_replace(array("\n", "\r"), '', $from); /* Default addresses */ list($mailto, $mailfrom, $Bcc, $params) = get_package_mail(oneof(@$in['package_name'], $bug['package_name']), $id, oneof(@$in['bug_type'], $bug['bug_type'])); $headers[] = array(' ID', $bug['id']); switch ($edit) { case 4: $headers[] = array(' Patch added by', $from); $from = "\"{$from}\" <{$mailfrom}>"; break; case 3: $headers[] = array(' Comment by', $from); $from = "\"{$from}\" <{$mailfrom}>"; break; case 2: $from = spam_protect(txfield('email', $bug, $in), 'text'); $headers[] = array(' User updated by', $from); $from = "\"{$from}\" <{$mailfrom}>"; break; default: $headers[] = array(' Updated by', $from); } $fields = array('email' => 'Reported by', 'sdesc' => 'Summary', 'status' => 'Status', 'bug_type' => 'Type', 'package_name' => 'Package', 'php_os' => 'Operating System', 'php_version' => 'PHP Version', 'assign' => 'Assigned To', 'block_user_comment' => 'Block user comment', 'private' => 'Private report', 'cve_id' => 'CVE-ID'); foreach ($fields as $name => $desc) { $prefix = ' '; if (isset($changed[$name])) { $headers[] = array("-{$desc}", $changed[$name]['from']); $prefix = '+'; } /* only fields that are set get added. */ if ($f = txfield($name, $bug, $in)) { if ($name == 'email') { $f = spam_protect($f, 'text'); } $foo = isset($changed[$name]['to']) ? $changed[$name]['to'] : $f; $headers[] = array($prefix . $desc, $foo); } } /* Make header output aligned */ $maxlength = 0; $actlength = 0; foreach ($headers as $v) { $actlength = strlen($v[0]) + 1; $maxlength = $maxlength < $actlength ? $actlength : $maxlength; } /* Align header content with headers (if a header contains more than one line, wrap it intelligently) */ $header_text = ''; $spaces = str_repeat(' ', $maxlength + 1); foreach ($headers as $v) { $hcontent = wordwrap($v[1], 72 - $maxlength, "\n{$spaces}"); // wrap and indent $hcontent = rtrim($hcontent); // wordwrap may add spacer to last line $header_text .= str_pad($v[0] . ':', $maxlength) . " {$hcontent}\n"; } if ($ncomment) { $ncomment = preg_replace('#<div class="changeset">(.*)</div>#sUe', "ltrim(strip_tags('\\1'))", $ncomment); $text[] = " New Comment:\n\n{$ncomment}"; } $old_comments = get_old_comments($bug['id'], empty($ncomment)); $old_comments = preg_replace('#<div class="changeset">(.*)</div>#sUe', "ltrim(strip_tags('\\1'))", $old_comments); $text[] = $old_comments; #$wrapped_text = wordwrap(join("\n", $text), 72); $wrapped_text = join("\n", $text); /* user text with attention, headers and previous messages */ $user_text = <<<USER_TEXT ATTENTION! Do NOT reply to this email! To reply, use the web interface found at {$site_method}://{$site_url}{$basedir}/bug.php?id={$bug['id']}&edit=2 {$header_text} {$wrapped_text} USER_TEXT; /* developer text with headers, previous messages, and edit link */ $dev_text = <<<DEV_TEXT Edit report at {$site_method}://{$site_url}{$basedir}/bug.php?id={$bug['id']}&edit=1 {$header_text} {$wrapped_text} -- Edit this bug report at {$site_method}://{$site_url}{$basedir}/bug.php?id={$bug['id']}&edit=1 DEV_TEXT; if (preg_match('/.*@php\\.net\\z/', $bug['email'])) { $user_text = $dev_text; } // Defaults $subj = $bug_types[$bug['bug_type']]; $sdesc = txfield('sdesc', $bug, $in); /* send mail if status was changed, there is a comment, private turned on/off or the bug type was changed to/from Security */ if (empty($in['status']) || $in['status'] != $bug['status'] || $ncomment != '' || isset($in['private']) && $in['private'] != $bug['private'] || isset($in['bug_type']) && $in['bug_type'] != $bug['bug_type'] && ($in['bug_type'] == 'Security' || $bug['bug_type'] == 'Security')) { if (isset($in['bug_type']) && $in['bug_type'] != $bug['bug_type']) { $subj = $bug_types[$bug['bug_type']] . '->' . $bug_types[$in['bug_type']]; } $old_status = $bug['status']; $new_status = $bug['status']; if (isset($in['status']) && $in['status'] != $bug['status'] && $edit != 3) { /* status changed */ $new_status = $in['status']; $subj .= " #{$bug['id']} [{$tla[$old_status]}->{$tla[$new_status]}]"; } elseif ($edit == 4) { /* patch */ $subj .= " #{$bug['id']} [PATCH]"; } elseif ($edit == 3) { /* comment */ $subj .= " #{$bug['id']} [Com]"; } else { /* status did not change and not comment */ $subj .= " #{$bug['id']} [{$tla[$bug['status']]}]"; } // the user gets sent mail with an envelope sender that ignores bounces bugs_mail($bug['email'], "{$subj}: {$sdesc}", $user_text, "From: {$siteBig} Bug Database <{$mailfrom}>\n" . "Bcc: {$Bcc}\n" . "X-PHP-Bug: {$bug['id']}\n" . "X-PHP-Site: {$siteBig}\n" . "In-Reply-To: <bug-{$bug['id']}@{$site_url}>"); // Spam protection $tmp = $edit != 3 ? $in : $bug; $tmp['new_status'] = $new_status; $tmp['old_status'] = $old_status; foreach (array('bug_type', 'php_version', 'package_name', 'php_os') as $field) { $tmp[$field] = strtok($tmp[$field], "\r\n"); } // but we go ahead and let the default sender get used for the list bugs_mail($mailto, "{$subj}: {$sdesc}", $dev_text, "From: {$from}\n" . "X-PHP-Bug: {$bug['id']}\n" . "X-PHP-Site: {$siteBig}\n" . "X-PHP-Type: {$tmp['bug_type']}\n" . "X-PHP-Version: {$tmp['php_version']}\n" . "X-PHP-Category: {$tmp['package_name']}\n" . "X-PHP-OS: {$tmp['php_os']}\n" . "X-PHP-Status: {$tmp['new_status']}\n" . "X-PHP-Old-Status: {$tmp['old_status']}\n" . "In-Reply-To: <bug-{$bug['id']}@{$site_url}>", $params); } /* if a developer assigns someone else, let that other person know about it */ if ($edit == 1 && $in['assign'] && $in['assign'] != $bug['assign']) { $email = $in['assign'] . '@php.net'; // If the developer assigns him self then skip if ($email == $from) { return; } bugs_mail($email, $subj . txfield('sdesc', $bug, $in), "{$in['assign']} you have just been assigned to this bug by {$from}\n\n{$dev_text}", "From: {$from}\n" . "X-PHP-Bug: {$bug['id']}\n" . "In-Reply-To: <bug-{$bug['id']}@{$site_url}>"); } }
// If the report already has the status of the resolution, bounce over to the main bug form // which shows the appropriate error message. if ($status == $bug['status']) { redirect("bug.php?id={$bug_id}&edit=1&in[resolve]={$reason}"); } // Standard items $in = array('status' => $status, 'bug_type' => $bug['bug_type'], 'php_version' => $bug['php_version'], 'php_os' => $bug['php_os'], 'assign' => $bug['assign']); // Assign automatically when closed if ($status == 'Closed' && $in['assign'] == '') { $in['assign'] = $auth_user->handle; } // Update bug $dbh->prepare("\n\tUPDATE bugdb\n\tSET\n\t\tstatus = ?,\n\t\tassign = ?,\n\t\tts2 = NOW()\n\tWHERE id = ?\n")->execute(array($status, $in['assign'], $bug_id)); // Add changelog entry if (!PEAR::isError($res)) { $changed = bug_diff($bug, $in); if (!empty($changed)) { $log_comment = bug_diff_render_html($changed); if (!empty($log_comment)) { $res = bugs_add_comment($bug_id, $auth_user->email, $auth_user->name, $log_comment, 'log'); } } } // Add possible comment if (!PEAR::isError($res) && !empty($ncomment)) { $res = bugs_add_comment($bug_id, $auth_user->email, $auth_user->name, $ncomment, 'comment'); } // Send emails if (!PEAR::isError($res)) { mail_bug_updates($bug, $in, $auth_user->email, $ncomment); redirect("bug.php?id={$bug_id}&thanks=1");
$_POST['in']['assign'] = $bug['assign']; } if (!empty($_POST['in']['assign']) && $_POST['in']['status'] == 'Open') { $status = 'Assigned'; } elseif (empty($_POST['in']['assign']) && $_POST['in']['status'] == 'Assigned') { $status = 'Open'; } else { $status = $_POST['in']['status']; } // Assign automatically when closed if ($status == 'Closed' && $_POST['in']['assign'] == '') { $_POST['in']['assign'] = $auth_user->handle; } $dbh->prepare($query . "\n\t\t\t\tsdesc = ?, \n\t\t\t\tstatus = ?, \n\t\t\t\tpackage_name = ?,\n\t\t\t\tbug_type = ?,\n\t\t\t\tassign = ?,\n\t\t\t\tphp_version = ?,\n\t\t\t\tphp_os = ?,\n\t\t\t\tblock_user_comment = ?,\n\t\t\t\tcve_id = ?,\n\t\t\t\tprivate = ?,\n\t\t\t\tts2 = NOW()\n\t\t\tWHERE id = {$bug_id}\n\t\t")->execute(array($_POST['in']['sdesc'], $status, $_POST['in']['package_name'], $_POST['in']['bug_type'], $_POST['in']['assign'], $_POST['in']['php_version'], $_POST['in']['php_os'], $block_user, $_POST['in']['cve_id'], $is_private)); // Add changelog entry $changed = bug_diff($bug, $_POST['in']); if (!empty($changed)) { $log_comment = bug_diff_render_html($changed); if (!empty($log_comment)) { $res = bugs_add_comment($bug_id, $from, $comment_name, $log_comment, 'log'); } } // Add normal comment if (!empty($ncomment)) { $res = bugs_add_comment($bug_id, $from, $comment_name, $ncomment, 'comment'); mark_related_bugs($from, $comment_name, $ncomment); } } } elseif (isset($_POST['in']) && isset($_POST['preview']) && $edit == 1) { $ncomment = trim($_POST['ncomment']); $from = $auth_user->email;
$link->id = $id; $link->delete(); if (isset($_POST['in']['fixed_versions']) && !in_array($status, array('Bogus', 'Wont fix', 'No Feedback'))) { foreach ($_POST['in']['fixed_versions'] as $rid) { $link->id = $id; $link->roadmap_id = $rid; $link->insert(); } } $current = $dbh->getAll('SELECT roadmap_version FROM bugdb_roadmap_link l, bugdb_roadmap b WHERE l.id = ? AND b.id = l.roadmap_id', array($id)); } else { $current = $previous; } $changed = bug_diff($bug, $_POST['in'], $previous, $current); if (!empty($changed)) { $ncomment = bug_diff_render_html($changed) . $ncomment; } if (!empty($ncomment)) { $query = 'INSERT INTO bugdb_comments' . ' (bug, email, ts, comment, reporter_name, handle, active) VALUES (?, ?, NOW(), ?, ?, ?, 1)'; $dbh->query($query, array($id, $from, $ncomment, $comment_name, $auth_user->handle)); } localRedirect('bug.php?id=' . $id); exit; } } elseif (isset($_POST['in']) && isset($_POST['preview']) && $edit == 1) { $ncomment = trim($_POST['ncomment']); $from = $auth_user->email; } elseif (isset($_POST['in'])) { $errors[] = 'Invalid edit mode.';