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