Index: trunk/phase3/includes/specials/SpecialBlockip.php |
— | — | @@ -394,6 +394,16 @@ |
395 | 395 | return array('ipb_expiry_invalid'); |
396 | 396 | } |
397 | 397 | |
| 398 | + if( $this->BlockHideName ) { |
| 399 | + if( !$userId ) { |
| 400 | + // IP users should not be hidden |
| 401 | + $this->BlockHideName = false; |
| 402 | + } else if( $expiry !== 'infinity' ) { |
| 403 | + // Bad expiry. |
| 404 | + return array('ipb_expiry_temp'); |
| 405 | + } |
| 406 | + } |
| 407 | + |
398 | 408 | if( $this->BlockHideName && $expiry != 'infinity' ) { |
399 | 409 | // Bad expiry. |
400 | 410 | return array('ipb_expiry_temp'); |
— | — | @@ -410,10 +420,12 @@ |
411 | 421 | # Should this be privately logged? |
412 | 422 | $suppressLog = (bool)$this->BlockHideName; |
413 | 423 | if ( wfRunHooks('BlockIp', array(&$block, &$wgUser)) ) { |
414 | | - |
| 424 | + # Try to insert block. Is there a conflicting block? |
415 | 425 | if ( !$block->insert() ) { |
| 426 | + # Show form unless the user is already aware of this... |
416 | 427 | if ( !$this->BlockReblock ) { |
417 | 428 | return array( 'ipb_already_blocked' ); |
| 429 | + # Otherwise, try to update the block... |
418 | 430 | } else { |
419 | 431 | # This returns direct blocks before autoblocks/rangeblocks, since we should |
420 | 432 | # be sure the user is blocked by now it should work for our purposes |
— | — | @@ -421,16 +433,31 @@ |
422 | 434 | if( $block->equals( $currentBlock ) ) { |
423 | 435 | return array( 'ipb_already_blocked' ); |
424 | 436 | } |
425 | | - $suppressLog = $suppressLog || (bool)$currentBlock->mHideName; |
| 437 | + # If the name was hidden and the blocking user cannot hide |
| 438 | + # names, then don't allow any block changes... |
| 439 | + if( $currentBlock->mHideName && !$wgUser->isAllowed('hideuser') ) { |
| 440 | + return array( 'hookaborted' ); |
| 441 | + } |
426 | 442 | $currentBlock->delete(); |
427 | 443 | $block->insert(); |
| 444 | + # If hiding/unhiding a name, this should go in the private logs |
| 445 | + $suppressLog = $suppressLog || (bool)$currentBlock->mHideName; |
428 | 446 | $log_action = 'reblock'; |
| 447 | + # Unset _deleted fields if requested |
| 448 | + if( $currentBlock->mHideName && !$this->BlockHideName ) { |
| 449 | + $this->unsuppressUserName( $this->BlockAddress, $userId ); |
| 450 | + } |
429 | 451 | } |
430 | 452 | } else { |
431 | 453 | $log_action = 'block'; |
432 | 454 | } |
433 | 455 | wfRunHooks('BlockIpComplete', array($block, $wgUser)); |
434 | 456 | |
| 457 | + # Set *_deleted fields if requested |
| 458 | + if( $this->BlockHideName ) { |
| 459 | + $this->suppressUserName( $this->BlockAddress, $userId ); |
| 460 | + } |
| 461 | + |
435 | 462 | if ( $this->BlockWatchUser && |
436 | 463 | # Only show watch link when this is no range block |
437 | 464 | $block->mRangeStart == $block->mRangeEnd) { |
— | — | @@ -454,10 +481,58 @@ |
455 | 482 | |
456 | 483 | # Report to the user |
457 | 484 | return array(); |
| 485 | + } else { |
| 486 | + return array('hookaborted'); |
458 | 487 | } |
459 | | - else |
460 | | - return array('hookaborted'); |
461 | 488 | } |
| 489 | + |
| 490 | + private function suppressUserName( $name, $userId ) { |
| 491 | + $op = '|'; // bitwise OR |
| 492 | + return $this->setUsernameBitfields( $name, $userId, $op ); |
| 493 | + } |
| 494 | + |
| 495 | + private function unsuppressUserName( $name, $userId ) { |
| 496 | + $op = '&'; // bitwise AND |
| 497 | + return $this->setUsernameBitfields( $name, $userId, $op ); |
| 498 | + } |
| 499 | + |
| 500 | + private function setUsernameBitfields( $name, $userId, $op ) { |
| 501 | + if( $op !== '|' && $op !== '&' ) |
| 502 | + return false; // sanity check |
| 503 | + // Typically, the user should have a handful of edits. |
| 504 | + // Disallow hiding users with many edits for performance. |
| 505 | + if( User::edits($userId) > 3000 ) { |
| 506 | + return false; |
| 507 | + } |
| 508 | + $dbw = wfGetDB( DB_MASTER ); |
| 509 | + $delUser = Revision::DELETED_USER | Revision::DELETED_RESTRICTED; |
| 510 | + # To suppress, we OR the current bitfields with Revision::DELETED_USER |
| 511 | + # to put a 1 in the username *_deleted bit. To unsuppress we AND the |
| 512 | + # current bitfields with the inverse of Revision::DELETED_USER. The |
| 513 | + # username bit is made to 0 (x & 0 = 0), while others are unchanged (x & 1 = x). |
| 514 | + # The same goes for the sysop-restricted *_deleted bit. |
| 515 | + if( $op == '&' ) $delUser = "~{$delUser}"; |
| 516 | + # Hide name from live edits |
| 517 | + $dbw->update( 'revision', array("rev_deleted = rev_deleted $op $delUser"), |
| 518 | + array('rev_user' => $userId), __METHOD__ ); |
| 519 | + # Hide name from deleted edits |
| 520 | + $dbw->update( 'archive', array("ar_deleted = ar_deleted $op $delUser"), |
| 521 | + array('ar_user_text' => $userId), __METHOD__ ); |
| 522 | + # Hide name from logs |
| 523 | + $dbw->update( 'logging', array("log_deleted = log_deleted $op $delUser"), |
| 524 | + array('log_user' => $userId), __METHOD__ ); |
| 525 | + # Hide name from RC |
| 526 | + $dbw->update( 'recentchanges', array("rc_deleted = rc_deleted $op $delUser"), |
| 527 | + array('rc_user_text' => $name), __METHOD__ ); |
| 528 | + # Hide name from live images |
| 529 | + $dbw->update( 'oldimage', array("oi_deleted = oi_deleted $op $delUser"), |
| 530 | + array('oi_user_text' => $name), __METHOD__ ); |
| 531 | + # Hide name from deleted images |
| 532 | + $dbw->update( 'filearchive', array("fa_deleted = fa_deleted $op $delUser"), |
| 533 | + array('fa_user_text' => $name), __METHOD__ ); |
| 534 | + # Done! |
| 535 | + return true; |
| 536 | + } |
462 | 537 | |
463 | 538 | /** |
464 | 539 | * UI entry point for blocking |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -2631,7 +2631,7 @@ |
2632 | 2632 | 'ipboptions' => '2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,infinite:infinite', # display1:time1,display2:time2,... |
2633 | 2633 | 'ipbotheroption' => 'other', |
2634 | 2634 | 'ipbotherreason' => 'Other/additional reason:', |
2635 | | -'ipbhidename' => 'Hide username from the block log, active block list and user list', |
| 2635 | +'ipbhidename' => 'Hide username from edits and lists', |
2636 | 2636 | 'ipbwatchuser' => "Watch this user's user and talk pages", |
2637 | 2637 | 'ipballowusertalk' => 'Allow this user to edit own talk page while blocked', |
2638 | 2638 | 'ipb-change-block' => 'Re-block the user with these settings', |