1<?php 2/* User interface for viewing and editing bug details */ 3 4use App\Repository\BugRepository; 5use App\Repository\CommentRepository; 6use App\Repository\ObsoletePatchRepository; 7use App\Repository\PackageRepository; 8use App\Repository\PatchRepository; 9use App\Utils\Captcha; 10use App\Repository\PullRequestRepository; 11use App\Repository\ReasonRepository; 12 13// Obtain common includes 14require_once '../include/prepend.php'; 15 16// Start session 17session_start(); 18 19$obsoletePatchRepository = $container->get(ObsoletePatchRepository::class); 20$patchRepository = $container->get(PatchRepository::class); 21 22$email = null; 23 24// Handle preview 25if (isset($_REQUEST['id']) && $_REQUEST['id'] == 'preview') { 26 $bug_id = 'PREVIEW'; 27 $bug = $_SESSION['bug_preview']; 28 $bug['submitted'] = time(); 29 $bug['modified'] = null; 30 $bug['votes'] = 0; 31 $bug['assign'] = ''; 32 33 if (!$bug) { 34 redirect('index.php'); 35 } 36} else { 37 // Bailout early if no/invalid bug id is passed 38 if (empty($_REQUEST['id']) || !((int) $_REQUEST['id'])) { 39 redirect('index.php'); 40 } else { 41 $bug_id = (int) $_REQUEST['id']; 42 } 43} 44 45// Init common variables 46$errors = []; 47 48// Set edit mode 49$edit = isset($_REQUEST['edit']) ? (int) $_REQUEST['edit'] : 0; 50 51// Authenticate 52bugs_authenticate($user, $pw, $logged_in, $user_flags); 53 54$is_trusted_developer = ($user_flags & BUGS_TRUSTED_DEV); 55$is_security_developer = ($user_flags & (BUGS_TRUSTED_DEV | BUGS_SECURITY_DEV)); 56 57// Handle unsubscription 58if (isset($_GET['unsubscribe'])) { 59 $unsubcribe = (int) $_GET['unsubscribe']; 60 61 $hash = isset($_GET['t']) ? $_GET['t'] : false; 62 63 if (!$hash) { 64 redirect("bug.php?id={$bug_id}"); 65 } 66 unsubscribe($bug_id, $hash); 67 $_GET['thanks'] = 9; 68} 69 70// Subscription / Unsubscription 71if (isset($_POST['subscribe_to_bug']) || isset($_POST['unsubscribe_to_bug'])) { 72 73 // Check if session answer is set, then compare it with the post captcha value. 74 // If it's not the same, then it's an incorrect password. 75 if (!$logged_in) { 76 if (!isset($_SESSION['answer'])) { 77 $errors[] = 'Please enable cookies so the Captcha system can work'; 78 } elseif ($_POST['captcha'] != $_SESSION['answer']) { 79 $errors[] = 'Incorrect Captcha'; 80 } 81 } 82 83 if (empty($errors)) { 84 if ($logged_in && !empty($auth_user->email)) { 85 $email = $auth_user->email; 86 } else { 87 $email = isset($_POST['in']['commentemail']) ? $_POST['in']['commentemail'] : ''; 88 } 89 if ($email == '' || !is_valid_email($email, $logged_in)) { 90 $errors[] = 'You must provide a valid email address.'; 91 } else { 92 // Unsubscribe 93 if (isset($_POST['unsubscribe_to_bug'])) { 94 // Generate the hash 95 unsubscribe_hash($bug_id, $email); 96 $thanks = 8; 97 } 98 else // Subscribe 99 { 100 $dbh->prepare('REPLACE INTO bugdb_subscribe SET bug_id = ?, email = ?')->execute([$bug_id, $email]); 101 $thanks = 7; 102 } 103 redirect("bug.php?id={$bug_id}&thanks={$thanks}"); 104 } 105 } 106 // If we get here, display errors 107 response_header('Error in subscription'); 108 display_bug_error($errors); 109 response_footer(); 110 exit; 111} 112 113// Delete comment 114if ($edit == 1 && $is_trusted_developer && isset($_GET['delete_comment'])) { 115 $delete_comment = (int) $_GET['delete_comment']; 116 $addon = ''; 117 118 if ($delete_comment) { 119 delete_comment($bug_id, $delete_comment); 120 $addon = '&thanks=1'; 121 } 122 redirect("bug.php?id=$bug_id&edit=1$addon"); 123} 124 125// captcha is not necessary if the user is logged in 126if (!$logged_in) { 127 $captcha = $container->get(Captcha::class); 128} 129 130$trytoforce = isset($_POST['trytoforce']) ? (int) $_POST['trytoforce'] : 0; 131 132// fetch info about the bug into $bug 133if (!isset($bug)) { 134 $bugRepository = $container->get(BugRepository::class); 135 $bug = $bugRepository->findOneById($bug_id); 136} 137 138// DB error 139if (is_object($bug)) { 140 response_header('DB error'); 141 display_bug_error($bug); 142 response_footer(); 143 exit; 144} 145 146// Bug not found with passed id 147if (!$bug) { 148 response_header('No Such Bug'); 149 display_bug_error("No such bug #{$bug_id}"); 150 response_footer(); 151 exit; 152} 153 154$show_bug_info = bugs_has_access($bug_id, $bug, $pw, $user_flags); 155if ($edit == 2 && !$show_bug_info && $pw && verify_bug_passwd($bug_id, bugs_get_hash($pw))) { 156 $show_bug_info = true; 157} 158 159if (isset($_POST['ncomment'])) { 160 /* Bugs blocked to user comments can only be commented by the team */ 161 if ($bug['block_user_comment'] == 'Y' && $logged_in != 'developer') { 162 response_header('Adding comments not allowed'); 163 display_bug_error("You're not allowed to add a comment to bug #{$bug_id}"); 164 response_footer(); 165 exit; 166 } 167} 168 169/* Just developers can change private/block_user_comment options */ 170if (!empty($_POST['in'])) { 171 if ($user_flags & BUGS_DEV_USER) { 172 $block_user = isset($_POST['in']['block_user_comment']) ? 'Y' : 'N'; 173 } 174 if ($is_security_developer) { 175 $is_private = isset($_POST['in']['private']) ? 'Y': 'N'; 176 } 177} 178 179$block_user = isset($block_user) ? $block_user : $bug['block_user_comment']; 180$is_private = isset($is_private) ? $is_private : $bug['private']; 181 182// Handle any updates, displaying errors if there were any 183$RESOLVE_REASONS = $FIX_VARIATIONS = $pseudo_pkgs = []; 184 185$project = $bug['project']; 186 187// Only fetch stuff when it's really needed 188if ($edit && $edit < 3) { 189 $packageRepository = $container->get(PackageRepository::class); 190 $pseudo_pkgs = $packageRepository->findEnabled(); 191} 192 193// Fetch RESOLVE_REASONS array 194if ($edit === 1) { 195 $reasonRepository = $container->get(ReasonRepository::class); 196 list($RESOLVE_REASONS, $FIX_VARIATIONS) = $reasonRepository->findByProject($project); 197} 198 199if (isset($_POST['ncomment']) && !isset($_POST['preview']) && $edit == 3) { 200 // Submission of additional comment by others 201 202 // Bug is private (just should be available to trusted developers and to reporter) 203 if (!$is_security_developer && $bug['private'] == 'Y') { 204 response_header('Private report'); 205 display_bug_error("The bug #{$bug_id} is not available to public, if you are the original reporter use the Edit tab"); 206 response_footer(); 207 exit; 208 } 209 210 // Check if session answer is set, then compare it with the post captcha value. 211 // If it's not the same, then it's an incorrect password. 212 if (!$logged_in) { 213 if (!isset($_SESSION['answer'])) { 214 $errors[] = 'Please enable cookies so the Captcha system can work'; 215 } elseif ($_POST['captcha'] != $_SESSION['answer']) { 216 $errors[] = 'Incorrect Captcha'; 217 } 218 } 219 220 $ncomment = trim($_POST['ncomment']); 221 if (!$ncomment) { 222 $errors[] = 'You must provide a comment.'; 223 } 224 225 // primitive spam detection 226 if ($message = is_spam($ncomment)) { 227 $errors[] = $message; 228 } 229 if (is_spam($_POST['in']['commentemail'])) { 230 $errors[] = "Please do not SPAM our bug system."; 231 } 232 if (is_spam_user($_POST['in']['commentemail'])) { 233 $errors[] = "Please do not SPAM our bug system."; 234 } 235 236 if (!$errors) { 237 do { 238 if (!$logged_in) { 239 240 if (!is_valid_email($_POST['in']['commentemail'], $logged_in)) { 241 $errors[] = 'You must provide a valid email address.'; 242 response_header('Add Comment - Problems'); 243 break; // skip bug comment addition 244 } 245 246 $_POST['in']['name'] = ''; 247 } else { 248 $_POST['in']['commentemail'] = $auth_user->email; 249 $_POST['in']['name'] = $auth_user->name; 250 } 251 252 $res = bugs_add_comment($bug_id, $_POST['in']['commentemail'], $_POST['in']['name'], $ncomment, 'comment'); 253 254 mark_related_bugs($_POST['in']['commentemail'], $_POST['in']['name'], $ncomment); 255 256 } while (false); 257 258 $from = spam_protect($_POST['in']['commentemail'], 'text'); 259 } else { 260 $from = ''; 261 } 262} elseif (isset($_POST['ncomment']) && isset($_POST['preview']) && $edit == 3) { 263 $ncomment = trim($_POST['ncomment']); 264 265 // primitive spam detection 266 if ($message = is_spam($ncomment)) { 267 $errors[] = $message; 268 } 269 270 $from = $_POST['in']['commentemail']; 271 if (is_spam_user($from)) { 272 $errors[] = "Please do not SPAM our bug system."; 273 } 274 275} elseif (isset($_POST['in']) && !isset($_POST['preview']) && $edit == 2) { 276 // Edits submitted by original reporter for old bugs 277 278 if (!$show_bug_info || !verify_bug_passwd($bug_id, bugs_get_hash($pw))) { 279 $errors[] = 'The password you supplied was incorrect.'; 280 } 281 282 // Bug is private (just should be available to trusted developers, original reporter and assigned dev) 283 if (!$show_bug_info && $bug['private'] == 'Y') { 284 response_header('Private report'); 285 display_bug_error("The bug #{$bug_id} is not available to public"); 286 response_footer(); 287 exit; 288 } 289 290 // Just trusted dev can change the package name of a Security related bug to another package 291 if ($bug['private'] == 'Y' && !$is_security_developer 292 && $bug['bug_type'] == 'Security' 293 && $_POST['in']['bug_type'] != $bug['bug_type']) { 294 295 $errors[] = 'You cannot change the bug type of a Security bug!'; 296 } 297 298 $ncomment = trim($_POST['ncomment']); 299 if (!$ncomment) { 300 $errors[] = 'You must provide a comment.'; 301 } 302 303 // check that they aren't being bad and setting a status they aren't allowed to (oh, the horrors.) 304 if (isset($_POST['in']['status']) 305 && isset($state_types[$_POST['in']['status']]) 306 && $_POST['in']['status'] != $bug['status'] && $state_types[$_POST['in']['status']] != 2) { 307 $errors[] = 'You aren\'t allowed to change a bug to that state.'; 308 } 309 310 // check that they aren't changing the mail to a php.net address (gosh, somebody might be fooled!) 311 if (preg_match('/^(.+)@php\.net/i', $_POST['in']['email'], $m)) { 312 if ($user != $m[1] || $logged_in != 'developer') { 313 $errors[] = 'You have to be logged in as a developer to use your php.net email address.'; 314 $errors[] = 'Tip: log in via another browser window then resubmit the form in this window.'; 315 } 316 } 317 318 // primitive spam detection 319 if ($ncomment && $message = is_spam($ncomment)) { 320 $errors[] = $message; 321 } 322 323 if (!empty($_POST['in']['email']) && 324 $bug['email'] != $_POST['in']['email'] 325 ) { 326 $from = $_POST['in']['email']; 327 } else { 328 $from = $bug['email']; 329 } 330 331 if (is_spam_user($from)) { 332 $errors[] = "Please do not SPAM our bug system."; 333 } 334 335 if (!$errors && !($errors = incoming_details_are_valid($_POST['in'], false))) { 336 // Allow the reporter to change the bug type to 'Security', hence mark 337 // the report as private 338 if ($bug['private'] == 'N' && $_POST['in']['bug_type'] == 'Security' 339 && $_POST['in']['bug_type'] != $bug['bug_type']) { 340 341 $is_private = $_POST['in']['private'] = 'Y'; 342 } 343 344 $dbh->prepare(" 345 UPDATE bugdb 346 SET 347 sdesc = ?, 348 status = ?, 349 package_name = ?, 350 bug_type = ?, 351 php_version = ?, 352 php_os = ?, 353 email = ?, 354 ts2 = NOW(), 355 private = ? 356 WHERE id={$bug_id} 357 ")->execute([ 358 $_POST['in']['sdesc'], 359 $_POST['in']['status'], 360 $_POST['in']['package_name'], 361 $_POST['in']['bug_type'], 362 $_POST['in']['php_version'], 363 $_POST['in']['php_os'], 364 $from, 365 $is_private 366 ]); 367 368 // Add changelog entry 369 $changed = bug_diff($bug, $_POST['in']); 370 if (!empty($changed)) { 371 $log_comment = bug_diff_render_html($changed); 372 373 if (!empty($log_comment)) { 374 $res = bugs_add_comment($bug_id, $from, '', $log_comment, 'log'); 375 } 376 } 377 378 // Add normal comment 379 if (!empty($ncomment)) { 380 $res = bugs_add_comment($bug_id, $from, '', $ncomment, 'comment'); 381 382 mark_related_bugs($from, '', $ncomment); 383 } 384 } 385} elseif (isset($_POST['in']) && isset($_POST['preview']) && $edit == 2) { 386 $ncomment = trim($_POST['ncomment']); 387 $from = isset($_POST['in']['commentemail']) ? $_POST['in']['commentemail'] : ''; 388 389 // primitive spam detection 390 if ($message = is_spam($ncomment)) { 391 $errors[] = $message; 392 } 393 if (is_spam_user($from)) { 394 $errors[] = "Please do not SPAM our bug system."; 395 } 396 397} elseif (isset($_POST['in']) && is_array($_POST['in']) && !isset($_POST['preview']) && $edit == 1) { 398 // Edits submitted by developer 399 400 // Bug is private (just should be available to trusted developers, submitter and assigned dev) 401 if (!$show_bug_info && $bug['private'] == 'Y') { 402 response_header('Private report'); 403 display_bug_error("The bug #{$bug_id} is not available to public"); 404 response_footer(); 405 exit; 406 } 407 408 if ($logged_in != 'developer') { 409 $errors[] = 'You have to login first in order to edit the bug report.'; 410 } 411 $comment_name = $auth_user->name; 412 if (empty($_POST['ncomment'])) { 413 $ncomment = ''; 414 } else { 415 $ncomment = trim($_POST['ncomment']); 416 } 417 418 // primitive spam detection 419 if ($ncomment && $message = is_spam($ncomment)) { 420 $errors[] = $message; 421 } 422 423 // Just trusted dev can set CVE-ID 424 if ($is_security_developer && !empty($_POST['in']['cve_id'])) { 425 // Remove the CVE- prefix 426 $_POST['in']['cve_id'] = preg_replace('/^\s*CVE-/i', '', $_POST['in']['cve_id']); 427 } 428 if (empty($_POST['in']['cve_id'])) { 429 $_POST['in']['cve_id'] = $bug['cve_id']; 430 } 431 432 if ($bug['private'] == 'N' && $bug['private'] != $is_private) { 433 if ($_POST['in']['bug_type'] != 'Security') { 434 $errors[] = 'Only Security bugs can be marked as private.'; 435 } 436 } 437 438 global $state_types; 439 $allowed_state_types = array_filter($state_types, function ($var) { 440 return $var !== 0; 441 }); 442 // Require comment for open bugs only 443 if (empty($_POST['in']['status']) || !isset($allowed_state_types[$_POST['in']['status']])) { 444 $errors[] = "You must provide a status"; 445 } else { 446 if ($_POST['in']['status'] == 'Not a bug' && 447 !in_array($bug['status'], ['Not a bug', 'Closed', 'Duplicate', 'No feedback', 'Wont fix']) && 448 strlen(trim($ncomment)) == 0 449 ) { 450 $errors[] = "You must provide a comment when marking a bug 'Not a bug'"; 451 } elseif (!empty($_POST['in']['resolve'])) { 452 if (!$trytoforce && isset($RESOLVE_REASONS[$_POST['in']['resolve']]) && 453 $RESOLVE_REASONS[$_POST['in']['resolve']]['status'] == $bug['status']) 454 { 455 $errors[] = 'The bug is already marked "'.$bug['status'].'". (Submit again to ignore this.)'; 456 } elseif (!$errors) { 457 if ($_POST['in']['status'] == $bug['status']) { 458 $_POST['in']['status'] = $RESOLVE_REASONS[$_POST['in']['resolve']]['status']; 459 } 460 if (isset($FIX_VARIATIONS) && isset($FIX_VARIATIONS[$_POST['in']['resolve']][$bug['package_name']])) { 461 $reason = $FIX_VARIATIONS[$_POST['in']['resolve']][$bug['package_name']]; 462 } else { 463 $reason = isset($RESOLVE_REASONS[$_POST['in']['resolve']]) ? $RESOLVE_REASONS[$_POST['in']['resolve']]['message'] : ''; 464 } 465 466 // do a replacement on @svn@ to the likely location of SVN for this package 467 if ($_POST['in']['resolve'] == 'trysvn') { 468 switch ($bug['package_name']) { 469 case 'Documentation' : 470 case 'Web Site' : 471 case 'Bug System' : 472 case 'PEPr' : 473 $errors[] = 'Cannot use "try svn" with ' . $bug['package_name']; 474 break; 475 case 'PEAR' : 476 $reason = str_replace('@svn@', 'pear-core', $reason); 477 $ncomment = "$reason\n\n$ncomment"; 478 break; 479 default : 480 $reason = str_replace('@svn@', $bug['package_name'], $reason); 481 $ncomment = "$reason\n\n$ncomment"; 482 break; 483 } 484 } else { 485 $ncomment = "$reason\n\n$ncomment"; 486 } 487 } 488 } 489 } 490 491 $from = $auth_user->email; 492 493 if (!$errors && !($errors = incoming_details_are_valid($_POST['in']))) { 494 $query = 'UPDATE bugdb SET'; 495 496 // Update email only if it's passed 497 if ($bug['email'] != $_POST['in']['email'] && !empty($_POST['in']['email'])) { 498 $query .= " email='{$_POST['in']['email']}',"; 499 } 500 501 // Changing the package to 'Security related' should mark the bug as private automatically 502 if ($bug['bug_type'] != $_POST['in']['bug_type']) { 503 if ($_POST['in']['bug_type'] == 'Security' && $_POST['in']['status'] != 'Closed') { 504 $is_private = $_POST['in']['private'] = 'Y'; 505 } 506 } 507 508 if ($logged_in != 'developer') { 509 // don't reset assigned status 510 $_POST['in']['assign'] = $bug['assign']; 511 } 512 if (!empty($_POST['in']['assign']) && $_POST['in']['status'] == 'Open') { 513 $status = 'Assigned'; 514 } elseif (empty($_POST['in']['assign']) && $_POST['in']['status'] == 'Assigned') { 515 $status = 'Open'; 516 } else { 517 $status = $_POST['in']['status']; 518 } 519 520 // Assign automatically when closed 521 if ($status == 'Closed' && $_POST['in']['assign'] == '') { 522 $_POST['in']['assign'] = $auth_user->handle; 523 } 524 525 $dbh->prepare($query . " 526 sdesc = ?, 527 status = ?, 528 package_name = ?, 529 bug_type = ?, 530 assign = ?, 531 php_version = ?, 532 php_os = ?, 533 block_user_comment = ?, 534 cve_id = ?, 535 private = ?, 536 ts2 = NOW() 537 WHERE id = {$bug_id} 538 ")->execute([ 539 $_POST['in']['sdesc'], 540 $status, 541 $_POST['in']['package_name'], 542 $_POST['in']['bug_type'], 543 $_POST['in']['assign'], 544 $_POST['in']['php_version'], 545 $_POST['in']['php_os'], 546 $block_user, 547 $_POST['in']['cve_id'], 548 $is_private 549 ]); 550 551 // Add changelog entry 552 $changed = bug_diff($bug, $_POST['in']); 553 if (!empty($changed)) { 554 $log_comment = bug_diff_render_html($changed); 555 556 if (!empty($log_comment)) { 557 $res = bugs_add_comment($bug_id, $from, $comment_name, $log_comment, 'log'); 558 } 559 } 560 561 // Add normal comment 562 if (!empty($ncomment)) { 563 $res = bugs_add_comment($bug_id, $from, $comment_name, $ncomment, 'comment'); 564 565 mark_related_bugs($from, $comment_name, $ncomment); 566 } 567 } 568} elseif (isset($_POST['in']) && isset($_POST['preview']) && $edit == 1) { 569 $ncomment = trim($_POST['ncomment']); 570 $from = $auth_user->email; 571} elseif (isset($_POST['in'])) { 572 $errors[] = 'Invalid edit mode.'; 573 $ncomment = ''; 574} else { 575 $ncomment = ''; 576} 577 578if (isset($_POST['in']) && !isset($_POST['preview']) && !$errors) { 579 mail_bug_updates($bug, $_POST['in'], $from, $ncomment, $edit, $bug_id); 580 redirect("bug.php?id=$bug_id&thanks=$edit"); 581} 582 583switch (txfield('bug_type', $bug, isset($_POST['in']) ? $_POST['in'] : null)) 584{ 585 case 'Feature/Change Request': 586 $bug_type = 'Request'; 587 break; 588 case 'Documentation Problem': 589 $bug_type = 'Doc Bug'; 590 break; 591 case 'Security': 592 $bug_type = 'Sec Bug'; 593 break; 594 default: 595 case 'Bug': 596 $bug_type = 'Bug'; 597 break; 598} 599 600response_header( 601 $show_bug_info ? "{$bug_type} #{$bug_id} :: " . htmlspecialchars($bug['sdesc']) : "You must be logged in", 602 ($bug_id != 'PREVIEW') ? " 603 <link rel='alternate' type='application/rss+xml' title='{$bug['package_name']} Bug #{$bug['id']} - RDF' href='rss/bug.php?id={$bug_id}'> 604 <link rel='alternate' type='application/rss+xml' title='{$bug['package_name']} Bug #{$bug['id']} - RSS 2.0' href='rss/bug.php?id={$bug_id}&format=rss2'> 605 " : '' 606); 607 608// DISPLAY BUG 609$thanks = (isset($_GET['thanks'])) ? (int) $_GET['thanks'] : 0; 610switch ($thanks) 611{ 612 case 1: 613 case 2: 614 echo '<div class="success">The bug was updated successfully.</div>'; 615 break; 616 case 3: 617 echo '<div class="success">Your comment was added to the bug successfully.</div>'; 618 break; 619 case 4: 620 $bug_url = "{$site_method}://{$site_url}{$basedir}/bug.php?id={$bug_id}"; 621 echo '<div class="success"> 622 Thank you for your help! 623 If the status of the bug report you submitted changes, you will be notified. 624 You may return here and check the status or update your report at any time.<br> 625 The URL for your bug report is: <a href="'.$bug_url.'">'.$bug_url.'</a>. 626 </div>'; 627 break; 628 case 6: 629 echo '<div class="success">Thanks for voting! Your vote should be reflected in the statistics below.</div>'; 630 break; 631 case 7: 632 echo '<div class="success">Your subscribe request has been processed.</div>'; 633 break; 634 case 8: 635 echo '<div class="success">Your unsubscribe request has been processed, please check your email.</div>'; 636 break; 637 case 9: 638 echo '<div class="success">You have successfully unsubscribed.</div>'; 639 break; 640 case 10: 641 echo '<div class="success">Your vote has been updated.</div>'; 642 break; 643 644 default: 645 break; 646} 647 648display_bug_error($errors); 649 650if (!$show_bug_info) { 651 echo '<div id="bugheader"></div>'; 652} else{ 653?> 654<div id="bugheader"> 655 <table id="details"> 656 <tr id="title"> 657 <th class="details" id="number"><a href="bug.php?id=<?php echo $bug_id, '">', $bug_type , '</a> #' , $bug_id; ?></th> 658 <td id="summary" colspan="5"><?php echo htmlspecialchars($bug['sdesc']); ?></td> 659 </tr> 660 <tr id="submission"> 661 <th class="details">Submitted:</th> 662 <td style="white-space: nowrap;"><?php echo format_date($bug['submitted']); ?></td> 663 <th class="details">Modified:</th> 664 <td style="white-space: nowrap;"><?php echo ($bug['modified']) ? format_date($bug['modified']) : '-'; ?></td> 665 <td rowspan="6"> 666 667<?php if ($bug['votes']) { ?> 668 <table id="votes"> 669 <tr><th class="details">Votes:</th><td><?php echo $bug['votes'] ?></td></tr> 670 <tr><th class="details">Avg. Score:</th><td><?php printf("%.1f ± %.1f", $bug['average'], $bug['deviation']); ?></td></tr> 671 <tr><th class="details">Reproduced:</th><td><?php printf("%d of %d (%.1f%%)", $bug['reproduced'], $bug['tried'], $bug['tried'] ? ($bug['reproduced'] / $bug['tried']) * 100 : 0); ?></td></tr> 672<?php if ($bug['reproduced']) { ?> 673 <tr><th class="details">Same Version:</th><td><?php printf("%d (%.1f%%)", $bug['samever'], ($bug['samever'] / $bug['reproduced']) * 100); ?></td></tr> 674 <tr><th class="details">Same OS:</th><td><?php printf("%d (%.1f%%)", $bug['sameos'], ($bug['sameos'] / $bug['reproduced']) * 100); ?></td></tr> 675<?php } ?> 676 </table> 677<?php } ?> 678 679 </td> 680 </tr> 681 682 <tr id="submitter"> 683 <th class="details">From:</th> 684 <td><?php echo ($bug['status'] !== 'Spam') ? spam_protect(htmlspecialchars($bug['email'])) : 'Hidden because of SPAM'; ?></td> 685 <th class="details">Assigned:</th> 686<?php if (!empty($bug['assign'])) { ?> 687 <td><a href="search.php?cmd=display&assign=<?php echo urlencode($bug['assign']), '">', htmlspecialchars($bug['assign']); ?></a> (<a href="https://people.php.net/<?php echo urlencode($bug['assign']); ?>">profile</a>)</td> 688<?php } else { ?> 689 <td><?php echo htmlspecialchars($bug['assign']); ?></td> 690<?php } ?> 691 </tr> 692 693 <tr id="categorization"> 694 <th class="details">Status:</th> 695 <td><?php echo htmlspecialchars($bug['status']); ?></td> 696 <th class="details">Package:</th> 697 <td><a href="search.php?cmd=display&package_name[]=<?php echo urlencode($bug['package_name']), '">', htmlspecialchars($bug['package_name']); ?></a><?php echo $bug['project'] == 'pecl' ? ' (<a href="https://pecl.php.net/package/'. htmlspecialchars($bug['package_name']) . '" target="_blank">PECL</a>)' : ''; ?></td> 698 </tr> 699 700 <tr id="situation"> 701 <th class="details">PHP Version:</th> 702 <td><?php echo htmlspecialchars($bug['php_version']); ?></td> 703 <th class="details">OS:</th> 704 <td><?php echo htmlspecialchars($bug['php_os']); ?></td> 705 </tr> 706 707 <tr id="private"> 708 <th class="details">Private report:</th> 709 <td><?php echo $bug['private'] == 'Y' ? 'Yes' : 'No'; ?></td> 710 <th class="details">CVE-ID:</th> 711 <td><?php if (!empty($bug['cve_id'])) { printf('<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-%s" target="_blank">%1$s</a>', htmlspecialchars($bug['cve_id'])); } else { ?><em>None</em><?php } ?></td> 712 </tr> 713 </table> 714</div> 715 716<?php 717} 718 719if ($bug_id !== 'PREVIEW') { 720 echo '<div class="controls">', "\n", 721 control(0, 'View'), 722 ($bug['private'] == 'N' ? control(3, 'Add Comment') : ''), 723 control(1, 'Developer'), 724 (!$email || $bug['email'] == $email? control(2, 'Edit') : ''), 725 '</div>', "\n"; 726?> 727<div class="clear"></div> 728 729<?php if ($show_bug_info && !$edit && canvote($thanks, $bug['status'])) { ?> 730<form id="vote" method="post" action="vote.php"> 731 <div class="sect"> 732 <fieldset> 733 <legend>Have you experienced this issue?</legend> 734 <div> 735 <input type="radio" id="rep-y" name="reproduced" value="1" onchange="show('canreproduce')"> <label for="rep-y">yes</label> 736 <input type="radio" id="rep-n" name="reproduced" value="0" onchange="hide('canreproduce')"> <label for="rep-n">no</label> 737 <input type="radio" id="rep-d" name="reproduced" value="2" onchange="hide('canreproduce')" checked="checked"> <label for="rep-d">don't know</label> 738 </div> 739 </fieldset> 740 <fieldset> 741 <legend>Rate the importance of this bug to you:</legend> 742 <div> 743 <label for="score-5">high</label> 744 <input type="radio" id="score-5" name="score" value="2"> 745 <input type="radio" id="score-4" name="score" value="1"> 746 <input type="radio" id="score-3" name="score" value="0" checked="checked"> 747 <input type="radio" id="score-2" name="score" value="-1"> 748 <input type="radio" id="score-1" name="score" value="-2"> 749 <label for="score-1">low</label> 750 </div> 751 </fieldset> 752 </div> 753 <div id="canreproduce" class="sect" style="display: none"> 754 <fieldset> 755 <legend>Are you using the same PHP version?</legend> 756 <div> 757 <input type="radio" id="ver-y" name="samever" value="1"> <label for="ver-y">yes</label> 758 <input type="radio" id="ver-n" name="samever" value="0" checked="checked"> <label for="ver-n">no</label> 759 </div> 760 </fieldset> 761 <fieldset> 762 <legend>Are you using the same operating system?</legend> 763 <div> 764 <input type="radio" id="os-y" name="sameos" value="1"> <label for="os-y">yes</label> 765 <input type="radio" id="os-n" name="sameos" value="0" checked="checked"> <label for="os-n">no</label> 766 </div> 767 </fieldset> 768 </div> 769 <div id="submit" class="sect"> 770 <input type="hidden" name="id" value="<?php echo $bug_id?>"> 771 <input type="submit" value="Vote"> 772 </div> 773</form> 774<br clear="all"> 775<?php } 776 777} // if ($bug_id != 'PREVIEW') { 778 779// 780// FIXME! Do not wrap here either. Re-use the comment display function! 781// 782 783if (isset($_POST['preview']) && !empty($ncomment)) { 784 $preview = '<div class="comment">'; 785 $preview .= "<strong>[" . format_date(time()) . "] "; 786 $preview .= spam_protect(htmlspecialchars($from)); 787 $preview .= "</strong>\n<pre class=\"note\">"; 788 $comment = wordwrap($ncomment, 72); 789 $preview .= make_ticket_links(addlinks($comment)); 790 $preview .= "</pre>\n"; 791 $preview .= '</div>'; 792} else { 793 $preview = ''; 794} 795 796if ($edit == 1 || $edit == 2) { ?> 797 798<form id="update" action="bug.php?id=<?php echo $bug_id; ?>&edit=<?php echo $edit; ?>" method="post"> 799 800<?php 801 if ($edit == 2) { 802?> 803 <div class="explain"> 804 <?php if (!isset($_POST['in'])) { ?> 805 Welcome back! If you're the original bug submitter, here's 806 where you can edit the bug or add additional notes.<br> 807 If this is not your bug, you can 808 <a href="bug.php?id=<?php echo $bug_id; ?>&edit=3">add a comment by following this link</a>.<br> 809 If this is your bug, but you forgot your password, <a href="bug-pwd-finder.php?id=<?php echo $bug_id; ?>">you can retrieve your password here</a>.<br> 810 <?php } ?> 811 812 <table> 813 <tr> 814 <td class="details">Passw<span class="accesskey">o</span>rd:</td> 815 <td><input type="password" name="pw" value="<?php echo htmlspecialchars($pw); ?>" size="10" maxlength="20" accesskey="o"></td> 816 <?php if (!$show_bug_info) { ?> 817 <td><input type="submit" value="Submit"></td> 818 <?php } ?> 819 </tr> 820 </table> 821 </div> 822<?php 823 } elseif ($logged_in == 'developer') { 824?> 825 <div class="explain"> 826 Welcome back, <?php echo $user; ?>! 827 (Not <?php echo $user; ?>? <a href="logout.php">Log out.</a>) 828 </div> 829<?php 830 } else { 831?> 832 <div class="explain"> 833 Welcome! If you don't have a Git account, you can't do anything here.<br> 834 You can <a href="bug.php?id=<?php echo $bug_id; ?>&edit=3">add a comment by following this link</a> 835 or if you reported this bug, you can <a href="bug.php?id=<?php echo $bug_id; ?>&edit=2">edit this bug over here</a>. 836 <div class="details"> 837 <label for="svnuser">php.net Username:</label> 838 <input type="text" id="svnuser" name="user" value="<?php echo htmlspecialchars($user); ?>" size="10" maxlength="20"> 839 <label for="svnpw">php.net Password:</label> 840 <input type="password" id="svnpw" name="pw" value="<?php echo htmlspecialchars($pw); ?>" size="10"> 841 <!--<label for="save">Remember:</label><input style="vertical-align:middle;" type="checkbox" id="save" name="save" <?php echo !empty($_POST['save']) ? 'checked="checked"' : ''; ?>>--> 842 <?php if (!$show_bug_info) { ?> 843 <input type="submit" value="Submit"> 844 <?php } ?> 845 </div> 846 </div> 847<?php 848 } 849 850 echo $preview; 851?> 852 <table> 853 854<?php 855 if ($edit == 1 && $show_bug_info) { /* Developer Edit Form */ 856 if (isset($RESOLVE_REASONS) && $RESOLVE_REASONS) { 857?> 858 <tr> 859 <th class="details"><label for="in" accesskey="c">Qui<span class="accesskey">c</span>k Fix:</label></th> 860 <td colspan="3"> 861 <select name="in[resolve]" id="in"> 862 <?php show_reason_types((isset($_POST['in']) && isset($_POST['in']['resolve'])) ? $_POST['in']['resolve'] : -1, 1); ?> 863 </select> 864 865<?php if (isset($_POST['in']) && !empty($_POST['in']['resolve'])) { ?> 866 <input type="hidden" name="trytoforce" value="1"> 867<?php } ?> 868 869 <small>(<a href="quick-fix-desc.php">description</a>)</small> 870 </td> 871 </tr> 872<?php 873 } 874 875 if ($is_security_developer) { ?> 876 <tr> 877 <th class="details">CVE-ID:</th> 878 <td colspan="3"> 879 <input type="text" size="15" maxlength="15" name="in[cve_id]" value="<?php echo field('cve_id'); ?>" id="cve_id"> 880 </td> 881 </tr> 882 <tr> 883 <th class="details"></th> 884 <td colspan="3"> 885 <input type="checkbox" name="in[private]" value="Y" <?php print $is_private == 'Y' ? 'checked="checked"' : ''; ?>> Private report (Normal user should not see it) 886 </td> 887 </tr> 888<?php } ?> 889 <tr> 890 <th class="details"></th> 891 <td colspan="3"> 892 <input type="checkbox" name="in[block_user_comment]" value="Y" <?php print $block_user == 'Y' ? 'checked="checked"' : ''; ?>> Block user comment 893 </td> 894 </tr> 895<?php } ?> 896 897<?php if ($show_bug_info) { ?> 898 899 <tr> 900 <th class="details">Status:</th> 901 <td <?php echo (($edit != 1) ? 'colspan="3"' : '' ); ?>> 902 <select name="in[status]"> 903 <?php show_state_options(isset($_POST['in']) && isset($_POST['in']['status']) ? $_POST['in']['status'] : '', $edit, $bug['status'], $bug['assign']); ?> 904 </select> 905 906<?php if ($edit == 1) { ?> 907 </td> 908 <th class="details">Assign to:</th> 909 <td> 910 <input type="text" size="10" maxlength="16" name="in[assign]" value="<?php echo field('assign'); ?>" id="assigned_user"> 911<?php } ?> 912 913 <input type="hidden" name="id" value="<?php echo $bug_id ?>"> 914 <input type="hidden" name="edit" value="<?php echo $edit ?>"> 915 <input type="submit" value="Submit"> 916 </td> 917 </tr> 918 <tr> 919 <th class="details">Package:</th> 920 <td colspan="3"> 921 <select name="in[package_name]"> 922 <?php show_package_options(isset($_POST['in']) && isset($_POST['in']['package_name']) ? $_POST['in']['package_name'] : '', 0, $bug['package_name']); ?> 923 </select> 924 </td> 925 </tr> 926 <tr> 927 <th class="details">Bug Type:</th> 928 <td colspan="3"> 929 <select name="in[bug_type]"> 930 <?php show_type_options($bug['bug_type'], /* deprecated */ true); ?> 931 </select> 932 </td> 933 </tr> 934 <tr> 935 <th class="details">Summary:</th> 936 <td colspan="3"> 937 <input type="text" size="60" maxlength="80" name="in[sdesc]" value="<?php echo ($bug['status'] !== 'Spam') ? field('sdesc') : 'Hidden because of SPAM'; ?>"> 938 </td> 939 </tr> 940 <tr> 941 <th class="details">From:</th> 942 <td colspan="3"> 943 <?php echo ($bug['status'] !== 'Spam') ? spam_protect(field('email')) : 'Hidden because of SPAM'; ?> 944 </td> 945 </tr> 946 <tr> 947 <th class="details">New email:</th> 948 <td colspan="3"> 949 <input type="text" size="40" maxlength="40" name="in[email]" value="<?php echo isset($_POST['in']) && isset($_POST['in']['email']) ? htmlspecialchars($_POST['in']['email']) : ''; ?>"> 950 </td> 951 </tr> 952 <tr> 953 <th class="details">PHP Version:</th> 954 <td><input type="text" size="20" maxlength="100" name="in[php_version]" value="<?php echo field('php_version'); ?>"></td> 955 <th class="details">OS:</th> 956 <td><input type="text" size="20" maxlength="32" name="in[php_os]" value="<?php echo field('php_os'); ?>"></td> 957 </tr> 958 </table> 959 960 <p style="margin-bottom: 0em;"> 961 <label for="ncomment" accesskey="m"><b>New<?php if ($edit == 1) echo "/Additional"; ?> Co<span class="accesskey">m</span>ment:</b></label> 962 </p> 963 <?php 964 if ($bug['block_user_comment'] == 'Y' && $logged_in != 'developer') { 965 echo 'Further comment on this bug is unnecessary.'; 966 } elseif ($bug['status'] === 'Spam' && $logged_in != 'developer') { 967 echo 'This bug has a SPAM status, so no additional comments are needed.'; 968 } else { 969 ?> 970 <textarea cols="80" rows="8" name="ncomment" id="ncomment" wrap="soft"><?php echo htmlspecialchars($ncomment); ?></textarea> 971 <?php 972 } 973 ?> 974 975 <p style="margin-top: 0em"> 976 <input type="submit" name="preview" value="Preview"> <input type="submit" value="Submit"> 977 </p> 978 979</form> 980 981<?php } // if ($show_bug_info) 982} // if ($edit == 1 || $edit == 2) 983?> 984 985<?php 986 if ($edit == 3 && $bug['private'] == 'N') { 987 988 if ($bug['status'] === 'Spam') { 989 echo 'This bug has a SPAM status, so no additional comments are needed.'; 990 response_footer(); 991 exit; 992 } 993 994?> 995 996 <form name="comment" id="comment" action="bug.php" method="post"> 997 998<?php if ($logged_in) { ?> 999 <div class="explain"> 1000 <h1> 1001 <a href="patch-add.php?bug_id=<?php echo $bug_id; ?>">Click Here to Submit a Patch</a> 1002 <input type="submit" name="subscribe_to_bug" value="Subscribe"> 1003 <input type="submit" name="unsubscribe_to_bug" value="Unsubscribe"> 1004 </h1> 1005 </div> 1006<?php } ?> 1007 1008<?php if (!isset($_POST['in'])) { ?> 1009 1010 <div class="explain"> 1011 Anyone can comment on a bug. Have a simpler test case? Does it 1012 work for you on a different platform? Let us know!<br> 1013 Just going to say 'Me too!'? Don't clutter the database with that please 1014 1015<?php 1016 if (canvote($thanks, $bug['status'])) { 1017 echo ' — but make sure to <a href="bug.php?id=' , $bug_id , '">vote on the bug</a>'; 1018 } 1019?>! 1020 </div> 1021 1022<?php } 1023 1024echo $preview; 1025 1026if (!$logged_in) { 1027 $_SESSION['answer'] = $captcha->getAnswer(); 1028?> 1029 <table> 1030 <tr> 1031 <th class="details">Y<span class="accesskey">o</span>ur email address:<br><strong>MUST BE VALID</strong></th> 1032 <td class="form-input"> 1033 <input type="text" size="40" maxlength="40" name="in[commentemail]" value="<?php echo isset($_POST['in']['commentemail']) ? htmlspecialchars($_POST['in']['commentemail'], ENT_COMPAT, 'UTF-8') : ''; ?>" accesskey="o"> 1034 </td> 1035 </tr> 1036 <tr> 1037 <th>Solve the problem:<br><?php echo htmlspecialchars($captcha->getQuestion()); ?></th> 1038 <td class="form-input"><input type="text" name="captcha"></td> 1039 </tr> 1040 <tr> 1041 <th class="details">Subscribe to this entry?</th> 1042 <td class="form-input"> 1043 <input type="submit" name="subscribe_to_bug" value="Subscribe"> 1044 <input type="submit" name="unsubscribe_to_bug" value="Unsubscribe"> 1045 </td> 1046 </tr> 1047 </table> 1048</div> 1049<?php } ?> 1050 1051 <div> 1052 <input type="hidden" name="id" value="<?php echo $bug_id; ?>"> 1053 <input type="hidden" name="edit" value="<?php echo $edit; ?>"> 1054 1055 <?php 1056 if ($bug['block_user_comment'] == 'Y' && $logged_in != 'developer') { 1057 echo 'Further comment on this bug is unnecessary.'; 1058 } elseif ($bug['status'] === 'Spam' && $logged_in != 'developer') { 1059 echo 'This bug has a SPAM status, so no additional comments are needed.'; 1060 } else { 1061 ?> 1062 <textarea cols="80" rows="10" name="ncomment" wrap="soft"><?php echo htmlspecialchars($ncomment); ?></textarea> 1063 <?php 1064 } 1065 ?> 1066 1067 <br><input type="submit" name="preview" value="Preview"> <input type="submit" value="Submit"> 1068 </div> 1069 1070 </form> 1071 1072<?php } ?> 1073 1074<?php 1075 1076// Display original report 1077if ($bug['ldesc']) { 1078 if (!$show_bug_info) { 1079 echo 'This bug report is marked as private.'; 1080 } else if ($bug['status'] !== 'Spam') { 1081 output_note(0, $bug['submitted'], $bug['email'], $bug['ldesc'], 'comment', $bug['reporter_name'], false); 1082 } else { 1083 echo 'The original report has been hidden, due to the SPAM status.'; 1084 } 1085} 1086 1087// Display patches 1088if ($show_bug_info && $bug_id != 'PREVIEW' && $bug['status'] !== 'Spam') { 1089 $p = $patchRepository->findAllByBugId($bug_id); 1090 $revs = []; 1091 echo "<h2>Patches</h2>\n"; 1092 1093 foreach ($p as $patch) { 1094 $revs[$patch['patch']][] = [$patch['revision'], $patch['developer']]; 1095 } 1096 1097 foreach ($revs as $name => $revisions) 1098 { 1099 $obsolete = $obsoletePatchRepository->findObsoletingPatches($bug_id, $name, $revisions[0][0]); 1100 $style = !empty($obsolete) ? ' style="background-color: yellow; text-decoration: line-through;" ' : ''; 1101 $url_name = urlencode($name); 1102 $clean_name = clean($name); 1103 $formatted_date = format_date($revisions[0][0]); 1104 $submitter = spam_protect($revisions[0][1]); 1105 1106 echo <<< OUTPUT 1107<a href="patch-display.php?bug_id={$bug_id}&patch={$url_name}&revision=latest" {$style}>{$clean_name}</a> 1108(last revision {$formatted_date} by {$submitter}) 1109<br> 1110OUTPUT; 1111 } 1112 echo "<p><a href='patch-add.php?bug_id={$bug_id}'>Add a Patch</a></p>"; 1113 1114 $pullRequestRepository = $container->get(PullRequestRepository::class); 1115 $pulls = $pullRequestRepository->findAllByBugId($bug_id); 1116 echo "<h2>Pull Requests</h2>\n"; 1117 1118 require "{$ROOT_DIR}/templates/listpulls.php"; 1119 echo "<p><a href='gh-pull-add.php?bug_id={$bug_id}'>Add a Pull Request</a></p>"; 1120} 1121 1122// Display comments 1123$commentRepository = $container->get(CommentRepository::class); 1124$bug_comments = is_int($bug_id) ? $commentRepository->findByBugId($bug_id) : []; 1125 1126if ($show_bug_info && is_array($bug_comments) && count($bug_comments) && $bug['status'] !== 'Spam') { 1127 $history_tabs = [ 1128 'type_all' => 'All', 1129 'type_comment' => 'Comments', 1130 'type_log' => 'Changes', 1131 'type_svn' => 'Git/SVN commits', 1132 'type_related' => 'Related reports' 1133 ]; 1134 1135 if (!isset($_COOKIE['history_tab']) || !isset($history_tabs[$_COOKIE['history_tab']])) { 1136 $active_history_tab = 'type_all'; 1137 } else { 1138 $active_history_tab = $_COOKIE['history_tab']; 1139 } 1140 echo '<h2 style="border-bottom:2px solid #666;margin-bottom:0;padding:5px 0;">History</h2>', 1141 "<div id='comment_filter' class='controls comments'>"; 1142 1143 foreach ($history_tabs as $id => $label) 1144 { 1145 $class_extra = ($id == $active_history_tab) ? 'active' : ''; 1146 echo "<span id='{$id}' class='control {$class_extra}' onclick='do_comment(this);'>{$label}</span>"; 1147 } 1148 1149 echo ' </div> 1150 '; 1151 1152 echo "<div id='comments_view' style='clear:both;'>\n"; 1153 foreach ($bug_comments as $row) { 1154 output_note($row['id'], $row['added'], $row['email'], $row['comment'], $row['comment_type'], $row['comment_name'], !($active_history_tab == 'type_all' || ('type_' . $row['comment_type']) == $active_history_tab)); 1155 } 1156 echo "</div>\n"; 1157} 1158 1159if ($bug_id == 'PREVIEW') { 1160?> 1161 1162<form action="report.php?package=<?php htmlspecialchars($_SESSION['bug_preview']['package_name']); ?>" method="post"> 1163<?php foreach($_SESSION['bug_preview'] as $k => $v) { 1164 if ($k !== 'ldesc') { 1165 if ($k === 'ldesc_orig') { 1166 $k = 'ldesc'; 1167 } 1168 echo "<input type='hidden' name='in[", htmlspecialchars($k, ENT_QUOTES), "]' value='", htmlentities($v, ENT_QUOTES, 'UTF-8'), "'>"; 1169 } 1170} 1171 echo "<input type='hidden' name='captcha' value='", htmlspecialchars($_SESSION['captcha'], ENT_QUOTES), "'>"; 1172?> 1173 <input type='submit' value='Send bug report'> <input type='submit' name='edit_after_preview' value='Edit'> 1174</form> 1175 1176<?php } 1177 1178$bug_JS = <<< bug_JS 1179<script src='js/util.js'></script> 1180<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'></script> 1181<script src="js/jquery.cookie.js"></script> 1182<script> 1183function do_comment(nd) 1184{ 1185 $('#comment_filter > .control.active').removeClass("active"); 1186 $(nd).addClass("active"); 1187 1188 $.cookie('history_tab', nd.id, { expires: 365 }); 1189 1190 if (nd.id == 'type_all') { 1191 $('#comments_view > .comment:hidden').show('slow'); 1192 } else { 1193 $('#comments_view > .comment').each(function(i) { 1194 if ($(this).hasClass(nd.id)) { 1195 $(this).show('slow'); 1196 } else { 1197 $(this).hide('slow'); 1198 } 1199 }); 1200 } 1201 return false; 1202} 1203</script> 1204bug_JS; 1205 1206if ($edit == 1) { 1207 $bug_JS .= ' 1208<script src="js/jquery.autocomplete-min.js"></script> 1209<script src="js/userlisting.php"></script> 1210<script src="js/search.js"></script> 1211 '; 1212 1213} 1214 1215response_footer($bug_JS); 1216 1217// Helper functions 1218 1219function mark_related_bugs($from, $comment_name, $ncomment) 1220{ 1221 global $bug_id; 1222 1223 $related = get_ticket_links($ncomment); 1224 1225 /** 1226 * Adds a new comment on the related bug pointing to the current report 1227 */ 1228 foreach ($related as $bug) { 1229 bugs_add_comment($bug, $from, $comment_name, 1230 'Related To: Bug #'. $bug_id, 'related'); 1231 } 1232} 1233 1234function link_to_people($email, $text) 1235{ 1236 $domain = strstr($email, "@"); 1237 if ($domain == "@php.net") { 1238 $username = strstr($email, "@", true); 1239 return '<a href="//people.php.net/' . urlencode($username) . '">' . $text . '</a>'; 1240 } 1241 return $text; 1242} 1243 1244function output_note($com_id, $ts, $email, $comment, $comment_type, $comment_name, $is_hidden = false) 1245{ 1246 global $edit, $bug_id, $dbh, $is_trusted_developer, $logged_in; 1247 1248 $display = (!$is_hidden) ? '' : 'style="display:none;"'; 1249 1250 echo "<div class='comment type_{$comment_type}' {$display}>"; 1251 echo '<a name="' , urlencode($ts) , '"> </a>'; 1252 echo "<strong>[" , format_date($ts) , "] "; 1253 echo link_to_people($email, spam_protect(htmlspecialchars($email))) , "</strong>\n"; 1254 1255 switch ($comment_type) 1256 { 1257 case 'log': 1258 echo "<div class='log_note'>{$comment}</div>"; 1259 break; 1260 1261 default: 1262 // Delete comment action only for trusted developers 1263 echo ($edit == 1 && $com_id !== 0 && $is_trusted_developer) ? "<a href='bug.php?id={$bug_id}&edit=1&delete_comment={$com_id}'>[delete]</a>\n" : ''; 1264 1265 $comment = make_ticket_links(addlinks($comment)); 1266 echo "<pre class='note'>{$comment}\n</pre>\n"; 1267 } 1268 1269 echo '</div>'; 1270} 1271 1272function delete_comment($bug_id, $com_id) 1273{ 1274 global $dbh; 1275 1276 $dbh->prepare("DELETE FROM bugdb_comments WHERE bug='{$bug_id}' AND id='{$com_id}'")->execute(); 1277} 1278 1279function control($num, $desc) 1280{ 1281 global $bug_id, $edit; 1282 1283 $str = "<span id='control_{$num}' class='control"; 1284 if ($edit == $num) { 1285 $str .= " active'>{$desc}"; 1286 } else { 1287 $str .= "'><a href='bug.php?id={$bug_id}" . (($num) ? "&edit={$num}" : '') . "'>{$desc}</a>"; 1288 } 1289 return "{$str}</span>\n"; 1290} 1291 1292function canvote($thanks, $status) 1293{ 1294 return ($thanks != 4 && $thanks != 6 && $status != 'Closed' && $status != 'Not a bug' && $status != 'Duplicate'); 1295} 1296