Bitfields for rev deleted

Requirements
We sometimes need to remove specific revisions from public view:
 * Copyright infringement inserted into histories
 * Libel/etc inserted into histories
 * People put their own personal information in by mistake (name, IP address, etc)
 * Vandals put other people's personal information in maliciously

Additionally:
 * Often we need only suppress the content; continuing to show the comment and username is useful in providing context for those viewing the history later.
 * However, sometimes material that needs to be removed is in the comment or user_text fields.
 * With a large field of admins, we may also need to suppress material from access by admins as well as the broad public.

Bitfield values for rev_deleted
Current code contains some limited support for indicating that revisions should be hidden if rev_deleted is set. This field is already present in the database, and is an 8-bit TINYINT.

This field size is suitable for a small bitfield to provide slightly more options than the simple boolean on/off originally envisioned.

Proposed values:


 * 0 - normal, all-visible
 * 1 - content visible only to admins
 * 2 - summary visible only to admins
 * 4 - username visible only to admins
 * 8 - steward-only: regular admins can't view or undelete either


 * What about restricting anons and non-autoconfirmeds, too? Rob Church (talk) 01:21, 12 April 2006 (UTC)
 * I can't see the usefulness for this. Data should be hidden in case of copyright infringement/personal infos/etc. There's no reason to restrict these data just to anonymous or autoconfirmed users. --84.221.209.77 14:57, 3 December 2006 (UTC)
 * Well, Gmaxwell liked the idea on this very talk page. Titoxd (?!?) 04:23, 18 January 2007 (UTC)

Export issues
The export format may require modification to deal with this properly; marked revisions should be included, with their unwanted parts excised and marked as such.



Code changes, secure by default?
Some Revision getter methods will now return bogus empty data if there are deletion markings for that field:
 * getUser, getUserText, getComment, getText

Those fields can be retrieved in all cases using a new 'raw' getter:
 * getRawUser, getRawUserText, getRawComment, getRawText

I've set it up this way as a more secure default: calling functions that don't know to check for permissions will have the restricted data hidden from them. Currently the main violators of such an arrangement will be things that read data directly out of the recentchanges table, or from the revision table without using the Revision wrapper class.

isDeleted now takes a bitfield constant, so you can ask it which fields to check against.

A new Revision method, userCan, also takes a bitfield and checks if $wgUser is of sufficient privilege to access the given field(s).

Linker now has some convenience methods which take a revision parameter, do permission checks and set appropriate formatting:
 * revComment (wraps commentBlock)
 * revUserLink (wraps makeUserLink, another new method for making basic userpage-or-contribs links)

Methods to be sure are safe:
 * Page view
 * Page oldid edit
 * Transclusion (by disabling rev_deleted for top revs, this is OK)
 * Edit rollback
 * Undo
 * Null edit stuff (like moves/protects)
 * Special:undelete
 * Recentchanges
 * RSS feeds
 * Object caching (diffs)

Changes to logging table
It would be useful to extend this to logs as well. This requires a log_deleted column. Often, vandals with innappropriate names are blocked or they create pages with such names which are deleted. These contents appear again in logs and recent changes.

This obviously requires a schema change, but allows for the same methods of hiding to be used everywhere. However, speciallog will need permission checks sprinkled everywhere, do-able, but annoying.

Changes to recentchanges table
When an revision or log event is partially hidden, the recentchanges entry must also be dealt with. There are two approaches to going about this:
 * Hack, simply modify the value of the recentchanges data entries to things like "user removed". This would generate funky links, always hide things from Sysops/Oversights and interfere with the current CheckUser extension. Though checkuser may soon have its own table, this is still an issue for those using an older version of the extension, and this interference is not something most people would likely expect.
 * Add rc_deleted. This obviously requires a schema change, but allows for the same methods of hiding to be used everywhere. However, changeslist will need permission checks sprinkled everywhere, do-able, but annoying.

Changes to filearchive table
The addition of fa_deleted will be useful to futher suppress deleted images. In the future, when the FileStore conversion is made, all images will use this table, just with different directory grouping ("old" as well as "deleted"), which will allow for hiding of images without having to delete them first as well as having the fa_deleted flag persist upon restoration

Innappropriate usernames
Adding an option to special:blockip to hide the name from public areas (block list, userlist and block log) is also needed for libel or personal info containing usernames. This can be accomplished by adding ipb_deleted to the block table and adding a JOIN to the listuser query.

Interaction with current deletion system
If the archive system is to be kept, the addition of ar_deleted is required in order to maintain the visibility bitfield for revisions, and more importantly to secure revisions "hidded from other Sysops". Otherwise, deleting pages causes this to fall off. This requires some permission checks in specialundelete.

Revision deletion is useful for removing severely innappropriate comments/names from revisions or hiding the text without causing misleading diffs or attribution issues. The current deletion system will still be useful for elimating entire pages, red linking them and possible maintainence db sweeps to delete out old items to save space.

Interface