Index: trunk/extensions/Lockdown/Lockdown.php |
— | — | @@ -20,8 +20,10 @@ |
21 | 21 | * - transcluding as template (can't really be fixed without disabling inclusion for specific namespaces; |
22 | 22 | * that could be done by adding a hook to Parser::fetchTemplate) |
23 | 23 | * - Special:export (easily fixed using $wgSpecialPageLockdown) |
24 | | -* - the search page may show excerpts from hidden pages. |
25 | | -* - supplying oldid=<revisionfromhiddenpage> may work in somve versions of mediawiki. Same with diff, etc. |
| 24 | +* - the search page may find text and show excerpts from hidden pages (should be fixed from MediaWiki 1.16). |
| 25 | +* Some search messages may reveal the page existance by producing links to it (MediaWiki:searchsubtitle, |
| 26 | +* MediaWiki:noexactmatch, MediaWiki:searchmenu-exists, MediaWiki:searchmenu-new...). |
| 27 | +* - supplying oldid=<revisionfromhiddenpage> may work in some versions of mediawiki. Same with diff, etc. |
26 | 28 | * |
27 | 29 | * NOTE: you cannot GRANT access to things forbidden by $wgGroupPermissions. You can only DENY access |
28 | 30 | * granted there. |
— | — | @@ -34,8 +36,8 @@ |
35 | 37 | |
36 | 38 | $wgExtensionCredits['other'][] = array( |
37 | 39 | 'path' => __FILE__, |
38 | | - 'name' => 'Lockdown', |
39 | | - 'author' => 'Daniel Kinzler', |
| 40 | + 'name' => 'Lockdown', |
| 41 | + 'author' => array( 'Daniel Kinzler', 'Platonides'), |
40 | 42 | 'url' => 'http://mediawiki.org/wiki/Extension:Lockdown', |
41 | 43 | 'description' => 'Per namespace group permissions', |
42 | 44 | 'descriptionmsg' => 'lockdown-desc', |
— | — | @@ -48,6 +50,9 @@ |
49 | 51 | |
50 | 52 | $wgHooks['userCan'][] = 'lockdownUserCan'; |
51 | 53 | $wgHooks['MediaWikiPerformAction'][] = 'lockdownMediawikiPerformAction'; |
| 54 | +$wgHooks['SearchableNamespaces'][] = 'lockdownSearchableNamespaces'; |
| 55 | +$wgHooks['SearchGetNearMatchComplete'][] = 'lockdownSearchGetNearMatchComplete'; |
| 56 | +$wgHooks['SearchEngineReplacePrefixesComplete'][] = 'lockdownSearchEngineReplacePrefixesComplete'; |
52 | 57 | |
53 | 58 | function lockdownUserCan( $title, $user, $action, &$result ) { |
54 | 59 | global $wgNamespacePermissionLockdown, $wgSpecialPageLockdown, $wgWhitelistRead; |
— | — | @@ -129,3 +134,73 @@ |
130 | 135 | if ( $match ) return true; |
131 | 136 | else return false; |
132 | 137 | } |
| 138 | + |
| 139 | +function lockdownSearchableNamespaces($arr) { |
| 140 | + global $wgUser, $wgNamespacePermissionLockdown; |
| 141 | + $ugroups = $wgUser->getEffectiveGroups(); |
| 142 | + |
| 143 | + foreach ( $arr as $ns => $name ) { |
| 144 | + $groups = @$wgNamespacePermissionLockdown[$ns]['read']; |
| 145 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown['*']['read']; |
| 146 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown[$ns]['*']; |
| 147 | + |
| 148 | + if ( $groups === NULL ) continue; |
| 149 | + |
| 150 | + if ( ( count( $groups ) == 0 ) || !array_intersect($ugroups, $groups) ) { |
| 151 | + unset( $arr[$ns] ); |
| 152 | + } |
| 153 | + } |
| 154 | + return true; |
| 155 | +} |
| 156 | + |
| 157 | +function lockdownTitle(&$title) { |
| 158 | + if ( is_object($title) ) { |
| 159 | + global $wgUser, $wgNamespacePermissionLockdown; |
| 160 | + $ugroups = $wgUser->getEffectiveGroups(); |
| 161 | + |
| 162 | + $groups = @$wgNamespacePermissionLockdown[$title->getNamespace()]['read']; |
| 163 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown['*']['read']; |
| 164 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown[$title->getNamespace()]['*']; |
| 165 | + |
| 166 | + if ( $groups === NULL ) continue; |
| 167 | + |
| 168 | + if ( ( count( $groups ) == 0 ) || !array_intersect($ugroups, $groups) ) { |
| 169 | + $title = null; |
| 170 | + return false; |
| 171 | + } |
| 172 | + } |
| 173 | + return true; |
| 174 | +} |
| 175 | + |
| 176 | +#Stop a Go search for a hidden title to send you to the login required page. Will show a no such page message instead. |
| 177 | +function lockdownSearchGetNearMatchComplete($searchterm, $title) { |
| 178 | + return lockdownTitle( $title ); |
| 179 | +} |
| 180 | + |
| 181 | +#Protect against namespace prefixes, explicit ones and <searchall> ('all:'-queries). |
| 182 | +function lockdownSearchEngineReplacePrefixesComplete($searchEngine, $query, $parsed) { |
| 183 | + global $wgUser, $wgNamespacePermissionLockdown; |
| 184 | + if ( $searchEngine->namespaces === null ) { #null means all namespaces. |
| 185 | + $searchEngine->namespaces = array_keys( SearchEngine::searchableNamespaces() ); #Use the namespaces... filtered |
| 186 | + return true; |
| 187 | + } |
| 188 | + |
| 189 | + $ugroups = $wgUser->getEffectiveGroups(); |
| 190 | + |
| 191 | + foreach ( $searchEngine->namespaces as $key => $ns ) { |
| 192 | + $groups = @$wgNamespacePermissionLockdown[$ns]['read']; |
| 193 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown['*']['read']; |
| 194 | + if ( $groups === NULL ) $groups = @$wgNamespacePermissionLockdown[$ns]['*']; |
| 195 | + |
| 196 | + if ( $groups === NULL ) continue; |
| 197 | + |
| 198 | + if ( ( count( $groups ) == 0 ) || !array_intersect($ugroups, $groups) ) { |
| 199 | + unset( $searchEngine->namespaces[$key] ); |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + if (count($searchEngine->namespaces) == 0) { |
| 204 | + $searchEngine->namespaces = array_keys( SearchEngine::searchableNamespaces() ); |
| 205 | + } |
| 206 | + return true; |
| 207 | +} |