get(ObsoletePatchRepository::class);
$patchRepository = $container->get(PatchRepository::class);
$email = null;
// Handle preview
if (isset($_REQUEST['id']) && $_REQUEST['id'] == 'preview') {
$bug_id = 'PREVIEW';
$bug = $_SESSION['bug_preview'];
$bug['submitted'] = time();
$bug['modified'] = null;
$bug['votes'] = 0;
$bug['assign'] = '';
if (!$bug) {
redirect('index.php');
}
} else {
// Bailout early if no/invalid bug id is passed
if (empty($_REQUEST['id']) || !((int) $_REQUEST['id'])) {
redirect('index.php');
} else {
$bug_id = (int) $_REQUEST['id'];
}
}
// Init common variables
$errors = [];
// Set edit mode
$edit = isset($_REQUEST['edit']) ? (int) $_REQUEST['edit'] : 0;
// Authenticate
bugs_authenticate($user, $pw, $logged_in, $user_flags);
$is_trusted_developer = ($user_flags & BUGS_TRUSTED_DEV);
$is_security_developer = ($user_flags & (BUGS_TRUSTED_DEV | BUGS_SECURITY_DEV));
// Handle unsubscription
if (isset($_GET['unsubscribe'])) {
$unsubcribe = (int) $_GET['unsubscribe'];
$hash = isset($_GET['t']) ? $_GET['t'] : false;
if (!$hash) {
redirect("bug.php?id={$bug_id}");
}
unsubscribe($bug_id, $hash);
$_GET['thanks'] = 9;
}
// Subscription / Unsubscription
if (isset($_POST['subscribe_to_bug']) || isset($_POST['unsubscribe_to_bug'])) {
// Check if session answer is set, then compare it with the post captcha value.
// If it's not the same, then it's an incorrect password.
if (!$logged_in) {
if (!isset($_SESSION['answer'])) {
$errors[] = 'Please enable cookies so the Captcha system can work';
} elseif ($_POST['captcha'] != $_SESSION['answer']) {
$errors[] = 'Incorrect Captcha';
}
}
if (empty($errors)) {
if ($logged_in && !empty($auth_user->email)) {
$email = $auth_user->email;
} else {
$email = isset($_POST['in']['commentemail']) ? $_POST['in']['commentemail'] : '';
}
if ($email == '' || !is_valid_email($email, $logged_in)) {
$errors[] = 'You must provide a valid email address.';
} else {
// Unsubscribe
if (isset($_POST['unsubscribe_to_bug'])) {
// Generate the hash
unsubscribe_hash($bug_id, $email);
$thanks = 8;
}
else // Subscribe
{
$dbh->prepare('REPLACE INTO bugdb_subscribe SET bug_id = ?, email = ?')->execute([$bug_id, $email]);
$thanks = 7;
}
redirect("bug.php?id={$bug_id}&thanks={$thanks}");
}
}
// If we get here, display errors
response_header('Error in subscription');
display_bug_error($errors);
response_footer();
exit;
}
// Delete comment
if ($edit == 1 && $is_trusted_developer && isset($_GET['delete_comment'])) {
$delete_comment = (int) $_GET['delete_comment'];
$addon = '';
if ($delete_comment) {
delete_comment($bug_id, $delete_comment);
$addon = '&thanks=1';
}
redirect("bug.php?id=$bug_id&edit=1$addon");
}
// captcha is not necessary if the user is logged in
if (!$logged_in) {
$captcha = $container->get(Captcha::class);
}
$trytoforce = isset($_POST['trytoforce']) ? (int) $_POST['trytoforce'] : 0;
// fetch info about the bug into $bug
if (!isset($bug)) {
$bugRepository = $container->get(BugRepository::class);
$bug = $bugRepository->findOneById($bug_id);
}
// DB error
if (is_object($bug)) {
response_header('DB error');
display_bug_error($bug);
response_footer();
exit;
}
// Bug not found with passed id
if (!$bug) {
response_header('No Such Bug');
display_bug_error("No such bug #{$bug_id}");
response_footer();
exit;
}
$show_bug_info = bugs_has_access($bug_id, $bug, $pw, $user_flags);
if ($edit == 2 && !$show_bug_info && $pw && verify_bug_passwd($bug_id, bugs_get_hash($pw))) {
$show_bug_info = true;
}
if (isset($_POST['ncomment'])) {
/* Bugs blocked to user comments can only be commented by the team */
if ($bug['block_user_comment'] == 'Y' && $logged_in != 'developer') {
response_header('Adding comments not allowed');
display_bug_error("You're not allowed to add a comment to bug #{$bug_id}");
response_footer();
exit;
}
}
/* Just developers can change private/block_user_comment options */
if (!empty($_POST['in'])) {
if ($user_flags & BUGS_DEV_USER) {
$block_user = isset($_POST['in']['block_user_comment']) ? 'Y' : 'N';
}
if ($is_security_developer) {
$is_private = isset($_POST['in']['private']) ? 'Y': 'N';
}
}
$block_user = isset($block_user) ? $block_user : $bug['block_user_comment'];
$is_private = isset($is_private) ? $is_private : $bug['private'];
// Handle any updates, displaying errors if there were any
$RESOLVE_REASONS = $FIX_VARIATIONS = $pseudo_pkgs = [];
$project = $bug['project'];
// Only fetch stuff when it's really needed
if ($edit && $edit < 3) {
$packageRepository = $container->get(PackageRepository::class);
$pseudo_pkgs = $packageRepository->findEnabled();
}
// Fetch RESOLVE_REASONS array
if ($edit === 1) {
$reasonRepository = $container->get(ReasonRepository::class);
list($RESOLVE_REASONS, $FIX_VARIATIONS) = $reasonRepository->findByProject($project);
}
if (isset($_POST['ncomment']) && !isset($_POST['preview']) && $edit == 3) {
// Submission of additional comment by others
// Bug is private (just should be available to trusted developers and to reporter)
if (!$is_security_developer && $bug['private'] == 'Y') {
response_header('Private report');
display_bug_error("The bug #{$bug_id} is not available to public, if you are the original reporter use the Edit tab");
response_footer();
exit;
}
// Check if session answer is set, then compare it with the post captcha value.
// If it's not the same, then it's an incorrect password.
if (!$logged_in) {
response_header('Developers only');
display_bug_error('Only developers are allowed to comment; if you are the original reporter use the Edit tab');
response_footer();
exit;
}
$ncomment = trim($_POST['ncomment']);
if (!$ncomment) {
$errors[] = 'You must provide a comment.';
}
// primitive spam detection
if ($message = is_spam($ncomment)) {
$errors[] = $message;
}
if (is_spam($_POST['in']['commentemail'])) {
$errors[] = "Please do not SPAM our bug system.";
}
if (is_spam_user($_POST['in']['commentemail'])) {
$errors[] = "Please do not SPAM our bug system.";
}
if (!$errors) {
do {
if (!$logged_in) {
if (!is_valid_email($_POST['in']['commentemail'], $logged_in)) {
$errors[] = 'You must provide a valid email address.';
response_header('Add Comment - Problems');
break; // skip bug comment addition
}
$_POST['in']['name'] = '';
} else {
$_POST['in']['commentemail'] = $auth_user->email;
$_POST['in']['name'] = $auth_user->name;
}
$res = bugs_add_comment($bug_id, $_POST['in']['commentemail'], $_POST['in']['name'], $ncomment, 'comment');
mark_related_bugs($_POST['in']['commentemail'], $_POST['in']['name'], $ncomment);
} while (false);
$from = spam_protect($_POST['in']['commentemail'], 'text');
} else {
$from = '';
}
} elseif (isset($_POST['ncomment']) && isset($_POST['preview']) && $edit == 3) {
$ncomment = trim($_POST['ncomment']);
// primitive spam detection
if ($message = is_spam($ncomment)) {
$errors[] = $message;
}
$from = $_POST['in']['commentemail'];
if (is_spam_user($from)) {
$errors[] = "Please do not SPAM our bug system.";
}
} elseif (isset($_POST['in']) && !isset($_POST['preview']) && $edit == 2) {
// Edits submitted by original reporter for old bugs
if (!$show_bug_info || !verify_bug_passwd($bug_id, bugs_get_hash($pw))) {
$errors[] = 'The password you supplied was incorrect.';
}
// Bug is private (just should be available to trusted developers, original reporter and assigned dev)
if (!$show_bug_info && $bug['private'] == 'Y') {
response_header('Private report');
display_bug_error("The bug #{$bug_id} is not available to public");
response_footer();
exit;
}
// Just trusted dev can change the package name of a Security related bug to another package
if ($bug['private'] == 'Y' && !$is_security_developer
&& $bug['bug_type'] == 'Security'
&& $_POST['in']['bug_type'] != $bug['bug_type']) {
$errors[] = 'You cannot change the bug type of a Security bug!';
}
$ncomment = trim($_POST['ncomment']);
if (!$ncomment) {
$errors[] = 'You must provide a comment.';
}
// check that they aren't being bad and setting a status they aren't allowed to (oh, the horrors.)
if (isset($_POST['in']['status'])
&& isset($state_types[$_POST['in']['status']])
&& $_POST['in']['status'] != $bug['status'] && $state_types[$_POST['in']['status']] != 2) {
$errors[] = 'You aren\'t allowed to change a bug to that state.';
}
// check that they aren't changing the mail to a php.net address (gosh, somebody might be fooled!)
if (preg_match('/^(.+)@php\.net/i', $_POST['in']['email'], $m)) {
if ($user != $m[1] || $logged_in != 'developer') {
$errors[] = 'You have to be logged in as a developer to use your php.net email address.';
$errors[] = 'Tip: log in via another browser window then resubmit the form in this window.';
}
}
// primitive spam detection
if ($ncomment && $message = is_spam($ncomment)) {
$errors[] = $message;
}
if (!empty($_POST['in']['email']) &&
$bug['email'] != $_POST['in']['email']
) {
$from = $_POST['in']['email'];
} else {
$from = $bug['email'];
}
if (is_spam_user($from)) {
$errors[] = "Please do not SPAM our bug system.";
}
if (!$errors && !($errors = incoming_details_are_valid($_POST['in'], false))) {
// Allow the reporter to change the bug type to 'Security', hence mark
// the report as private
if ($bug['private'] == 'N' && $_POST['in']['bug_type'] == 'Security'
&& $_POST['in']['bug_type'] != $bug['bug_type']) {
$is_private = $_POST['in']['private'] = 'Y';
}
$dbh->prepare("
UPDATE bugdb
SET
sdesc = ?,
status = ?,
package_name = ?,
bug_type = ?,
php_version = ?,
php_os = ?,
email = ?,
ts2 = NOW(),
private = ?
WHERE id={$bug_id}
")->execute([
$_POST['in']['sdesc'],
$_POST['in']['status'],
$_POST['in']['package_name'],
$_POST['in']['bug_type'],
$_POST['in']['php_version'],
$_POST['in']['php_os'],
$from,
$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, '', $log_comment, 'log');
}
}
// Add normal comment
if (!empty($ncomment)) {
$res = bugs_add_comment($bug_id, $from, '', $ncomment, 'comment');
mark_related_bugs($from, '', $ncomment);
}
}
} elseif (isset($_POST['in']) && isset($_POST['preview']) && $edit == 2) {
$ncomment = trim($_POST['ncomment']);
$from = isset($_POST['in']['commentemail']) ? $_POST['in']['commentemail'] : '';
// primitive spam detection
if ($message = is_spam($ncomment)) {
$errors[] = $message;
}
if (is_spam_user($from)) {
$errors[] = "Please do not SPAM our bug system.";
}
} elseif (isset($_POST['in']) && is_array($_POST['in']) && !isset($_POST['preview']) && $edit == 1) {
// Edits submitted by developer
// Bug is private (just should be available to trusted developers, submitter and assigned dev)
if (!$show_bug_info && $bug['private'] == 'Y') {
response_header('Private report');
display_bug_error("The bug #{$bug_id} is not available to public");
response_footer();
exit;
}
if ($logged_in != 'developer') {
$errors[] = 'You have to login first in order to edit the bug report.';
}
$comment_name = $auth_user->name;
if (empty($_POST['ncomment'])) {
$ncomment = '';
} else {
$ncomment = trim($_POST['ncomment']);
}
// primitive spam detection
if ($ncomment && $message = is_spam($ncomment)) {
$errors[] = $message;
}
// Just trusted dev can set CVE-ID
if ($is_security_developer && !empty($_POST['in']['cve_id'])) {
// Remove the CVE- prefix
$_POST['in']['cve_id'] = preg_replace('/^\s*CVE-/i', '', $_POST['in']['cve_id']);
}
if (empty($_POST['in']['cve_id'])) {
$_POST['in']['cve_id'] = $bug['cve_id'];
}
if ($bug['private'] == 'N' && $bug['private'] != $is_private) {
if ($_POST['in']['bug_type'] != 'Security') {
$errors[] = 'Only Security bugs can be marked as private.';
}
}
global $state_types;
$allowed_state_types = array_filter($state_types, function ($var) {
return $var !== 0;
});
// Require comment for open bugs only
if (empty($_POST['in']['status']) || !isset($allowed_state_types[$_POST['in']['status']])) {
$errors[] = "You must provide a status";
} else {
if ($_POST['in']['status'] == 'Not a bug' &&
!in_array($bug['status'], ['Not a bug', 'Closed', 'Duplicate', 'No feedback', 'Wont fix']) &&
strlen(trim($ncomment)) == 0
) {
$errors[] = "You must provide a comment when marking a bug 'Not a bug'";
} elseif (!empty($_POST['in']['resolve'])) {
if (!$trytoforce && isset($RESOLVE_REASONS[$_POST['in']['resolve']]) &&
$RESOLVE_REASONS[$_POST['in']['resolve']]['status'] == $bug['status'])
{
$errors[] = 'The bug is already marked "'.$bug['status'].'". (Submit again to ignore this.)';
} elseif (!$errors) {
if ($_POST['in']['status'] == $bug['status']) {
$_POST['in']['status'] = $RESOLVE_REASONS[$_POST['in']['resolve']]['status'];
}
if (isset($FIX_VARIATIONS) && isset($FIX_VARIATIONS[$_POST['in']['resolve']][$bug['package_name']])) {
$reason = $FIX_VARIATIONS[$_POST['in']['resolve']][$bug['package_name']];
} else {
$reason = isset($RESOLVE_REASONS[$_POST['in']['resolve']]) ? $RESOLVE_REASONS[$_POST['in']['resolve']]['message'] : '';
}
// do a replacement on @svn@ to the likely location of SVN for this package
if ($_POST['in']['resolve'] == 'trysvn') {
switch ($bug['package_name']) {
case 'Documentation' :
case 'Web Site' :
case 'Bug System' :
case 'PEPr' :
$errors[] = 'Cannot use "try svn" with ' . $bug['package_name'];
break;
case 'PEAR' :
$reason = str_replace('@svn@', 'pear-core', $reason);
$ncomment = "$reason\n\n$ncomment";
break;
default :
$reason = str_replace('@svn@', $bug['package_name'], $reason);
$ncomment = "$reason\n\n$ncomment";
break;
}
} else {
$ncomment = "$reason\n\n$ncomment";
}
}
}
}
$from = $auth_user->email;
if (!$errors && !($errors = incoming_details_are_valid($_POST['in']))) {
$query = 'UPDATE bugdb SET';
// Update email only if it's passed
if ($bug['email'] != $_POST['in']['email'] && !empty($_POST['in']['email'])) {
$query .= " email='{$_POST['in']['email']}',";
}
// Changing the package to 'Security related' should mark the bug as private automatically
if ($bug['bug_type'] != $_POST['in']['bug_type']) {
if ($_POST['in']['bug_type'] == 'Security' && $_POST['in']['status'] != 'Closed') {
$is_private = $_POST['in']['private'] = 'Y';
}
}
if ($logged_in != 'developer') {
// don't reset assigned status
$_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 . "
sdesc = ?,
status = ?,
package_name = ?,
bug_type = ?,
assign = ?,
php_version = ?,
php_os = ?,
block_user_comment = ?,
cve_id = ?,
private = ?,
ts2 = NOW()
WHERE id = {$bug_id}
")->execute([
$_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;
} elseif (isset($_POST['in'])) {
$errors[] = 'Invalid edit mode.';
$ncomment = '';
} else {
$ncomment = '';
}
if (isset($_POST['in']) && !isset($_POST['preview']) && !$errors) {
mail_bug_updates($bug, $_POST['in'], $from, $ncomment, $edit, $bug_id);
redirect("bug.php?id=$bug_id&thanks=$edit");
}
switch (txfield('bug_type', $bug, isset($_POST['in']) ? $_POST['in'] : null))
{
case 'Feature/Change Request':
$bug_type = 'Request';
break;
case 'Documentation Problem':
$bug_type = 'Doc Bug';
break;
case 'Security':
$bug_type = 'Sec Bug';
break;
default:
case 'Bug':
$bug_type = 'Bug';
break;
}
response_header(
$show_bug_info ? "{$bug_type} #{$bug_id} :: " . htmlspecialchars($bug['sdesc']) : "You must be logged in",
($bug_id != 'PREVIEW') ? "
" : ''
);
// DISPLAY BUG
$thanks = (isset($_GET['thanks'])) ? (int) $_GET['thanks'] : 0;
switch ($thanks)
{
case 1:
case 2:
echo '
The bug was updated successfully.
';
break;
case 3:
echo '
Your comment was added to the bug successfully.
';
break;
case 4:
$bug_url = "{$site_method}://{$site_url}{$basedir}/bug.php?id={$bug_id}";
echo '
Thank you for your help!
If the status of the bug report you submitted changes, you will be notified.
You may return here and check the status or update your report at any time.
The URL for your bug report is: '.$bug_url.'.
';
break;
case 6:
echo '
Thanks for voting! Your vote should be reflected in the statistics below.
';
break;
case 7:
echo '
Your subscribe request has been processed.
';
break;
case 8:
echo '
Your unsubscribe request has been processed, please check your email.