Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -898,6 +898,7 @@ |
899 | 899 | 'prefs-watchlist-days-max', |
900 | 900 | 'prefs-watchlist-edits', |
901 | 901 | 'prefs-watchlist-edits-max', |
| 902 | + 'prefs-watchlist-token', |
902 | 903 | 'prefs-misc', // continue checking if used from here on (r49916) |
903 | 904 | 'prefs-resetpass', |
904 | 905 | 'prefs-email', |
— | — | @@ -918,6 +919,7 @@ |
919 | 920 | 'recentchangesdays-max', |
920 | 921 | 'recentchangescount', |
921 | 922 | 'prefs-help-recentchangescount', |
| 923 | + 'prefs-help-watchlist-token', |
922 | 924 | 'savedprefs', |
923 | 925 | 'timezonelegend', |
924 | 926 | 'localtime', |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -160,6 +160,7 @@ |
161 | 161 | when the Go button is pressed in addition to the main namespace. |
162 | 162 | * (bug 19900) The "listgrouprights-key" message is now wrapped in a div with |
163 | 163 | class "mw-listgrouprights-key" |
| 164 | +* (bug 471) Allow RSS feeds for watchlist, using an opt-in security token |
164 | 165 | |
165 | 166 | === Bug fixes in 1.16 === |
166 | 167 | |
Index: trunk/phase3/includes/HTMLForm.php |
— | — | @@ -462,22 +462,25 @@ |
463 | 463 | $html = Xml::tags( 'tr', array( 'class' => "mw-htmlform-field-$fieldType" ), |
464 | 464 | $html ) . "\n"; |
465 | 465 | |
466 | | - // Help text |
| 466 | + $helptext = null; |
467 | 467 | if ( isset( $this->mParams['help-message'] ) ) { |
468 | 468 | $msg = $this->mParams['help-message']; |
469 | | - |
470 | | - $text = wfMsgExt( $msg, 'parseinline' ); |
471 | | - |
472 | | - if( !wfEmptyMsg( $msg, $text ) ) { |
473 | | - $row = Xml::tags( 'td', array( 'colspan' => 2, 'class' => 'htmlform-tip' ), |
474 | | - $text ); |
475 | | - |
476 | | - $row = Xml::tags( 'tr', null, $row ); |
477 | | - |
478 | | - $html .= "$row\n"; |
| 469 | + $helptext = wfMsgExt( $msg, 'parseinline' ); |
| 470 | + if ( wfEmptyMsg( $msg, $helptext ) ) { |
| 471 | + # Never mind |
| 472 | + $helptext = null; |
479 | 473 | } |
| 474 | + } elseif ( isset( $this->mParams['help'] ) ) { |
| 475 | + $helptext = $this->mParams['help']; |
480 | 476 | } |
481 | 477 | |
| 478 | + if ( !is_null( $helptext ) ) { |
| 479 | + $row = Xml::tags( 'td', array( 'colspan' => 2, 'class' => 'htmlform-tip' ), |
| 480 | + $helptext ); |
| 481 | + $row = Xml::tags( 'tr', null, $row ); |
| 482 | + $html .= "$row\n"; |
| 483 | + } |
| 484 | + |
482 | 485 | return $html; |
483 | 486 | } |
484 | 487 | |
Index: trunk/phase3/includes/api/ApiQueryWatchlist.php |
— | — | @@ -56,11 +56,20 @@ |
57 | 57 | |
58 | 58 | $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist'); |
59 | 59 | |
60 | | - if (!$wgUser->isLoggedIn()) |
| 60 | + $params = $this->extractRequestParams(); |
| 61 | + |
| 62 | + if (!is_null($params['user']) && !is_null($params['token'])) { |
| 63 | + $user = User::newFromName($params['user']); |
| 64 | + $token = $user->getOption('watchlisttoken'); |
| 65 | + if ($token == '' || $token != $params['token']) { |
| 66 | + $this->dieUsage('Incorrect watchlist token provided', 'bad_wltoken'); |
| 67 | + } |
| 68 | + } elseif (!$wgUser->isLoggedIn()) { |
61 | 69 | $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin'); |
| 70 | + } else { |
| 71 | + $user = $wgUser; |
| 72 | + } |
62 | 73 | |
63 | | - $params = $this->extractRequestParams(); |
64 | | - |
65 | 74 | if (!is_null($params['prop']) && is_null($resultPageSet)) { |
66 | 75 | |
67 | 76 | $prop = array_flip($params['prop']); |
— | — | @@ -122,7 +131,7 @@ |
123 | 132 | 'recentchanges' |
124 | 133 | )); |
125 | 134 | |
126 | | - $userId = $wgUser->getId(); |
| 135 | + $userId = $user->getId(); |
127 | 136 | $this->addWhere(array ( |
128 | 137 | 'wl_namespace = rc_namespace', |
129 | 138 | 'wl_title = rc_title', |
— | — | @@ -147,7 +156,8 @@ |
148 | 157 | $this->dieUsage("Incorrect parameter - mutually exclusive values may not be supplied", 'show'); |
149 | 158 | } |
150 | 159 | |
151 | | - // Check permissions |
| 160 | + // Check permissions. FIXME: should this check $user instead of |
| 161 | + // $wgUser? |
152 | 162 | global $wgUser; |
153 | 163 | if((isset($show['patrolled']) || isset($show['!patrolled'])) && !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol()) |
154 | 164 | $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied'); |
— | — | @@ -162,15 +172,19 @@ |
163 | 173 | $this->addWhereIf('rc_patrolled = 0', isset($show['!patrolled'])); |
164 | 174 | $this->addWhereIf('rc_patrolled != 0', isset($show['patrolled'])); |
165 | 175 | } |
166 | | - |
167 | | - if(!is_null($params['user']) && !is_null($params['excludeuser'])) |
168 | | - $this->dieUsage('user and excludeuser cannot be used together', 'user-excludeuser'); |
169 | | - if(!is_null($params['user'])) |
170 | | - $this->addWhereFld('rc_user_text', $params['user']); |
171 | | - if(!is_null($params['excludeuser'])) |
172 | | - $this->addWhere('rc_user_text != ' . $this->getDB()->addQuotes($params['excludeuser'])); |
173 | 176 | |
| 177 | + # Ignore extra user conditions if we're using token mode, since the |
| 178 | + # user was already manually specified. |
| 179 | + if(is_null($params['user']) || is_null($params['token'])) { |
| 180 | + if(!is_null($params['user']) && !is_null($params['excludeuser'])) |
| 181 | + $this->dieUsage('user and excludeuser cannot be used together', 'user-excludeuser'); |
| 182 | + if(!is_null($params['user'])) |
| 183 | + $this->addWhereFld('rc_user_text', $params['user']); |
| 184 | + if(!is_null($params['excludeuser'])) |
| 185 | + $this->addWhere('rc_user_text != ' . $this->getDB()->addQuotes($params['excludeuser'])); |
| 186 | + } |
174 | 187 | |
| 188 | + |
175 | 189 | # This is an index optimization for mysql, as done in the Special:Watchlist page |
176 | 190 | $this->addWhereIf("rc_timestamp > ''", !isset ($params['start']) && !isset ($params['end']) && $wgDBtype == 'mysql'); |
177 | 191 | |
— | — | @@ -321,6 +335,9 @@ |
322 | 336 | 'patrolled', |
323 | 337 | '!patrolled', |
324 | 338 | ) |
| 339 | + ), |
| 340 | + 'token' => array ( |
| 341 | + ApiBase :: PARAM_TYPE => 'string' |
325 | 342 | ) |
326 | 343 | ); |
327 | 344 | } |
— | — | @@ -339,7 +356,8 @@ |
340 | 357 | 'show' => array ( |
341 | 358 | 'Show only items that meet this criteria.', |
342 | 359 | 'For example, to see only minor edits done by logged-in users, set show=minor|!anon' |
343 | | - ) |
| 360 | + ), |
| 361 | + 'token' => "Give a security token (settable in preferences) to allow access to another user's watchlist" |
344 | 362 | ); |
345 | 363 | } |
346 | 364 | |
Index: trunk/phase3/includes/api/ApiFeedWatchlist.php |
— | — | @@ -75,6 +75,11 @@ |
76 | 76 | 'wllimit' => (50 > $wgFeedLimit) ? $wgFeedLimit : 50 |
77 | 77 | ); |
78 | 78 | |
| 79 | + if (!is_null($params['wluser'])) |
| 80 | + $fauxReqArr['wluser'] = $params['wluser']; |
| 81 | + if (!is_null($params['wltoken'])) |
| 82 | + $fauxReqArr['wltoken'] = $params['wltoken']; |
| 83 | + |
79 | 84 | // Check for 'allrev' parameter, and if found, show all revisions to each page on wl. |
80 | 85 | if ( ! is_null ( $params['allrev'] ) ) $fauxReqArr['wlallrev'] = ''; |
81 | 86 | |
— | — | @@ -152,7 +157,13 @@ |
153 | 158 | ApiBase :: PARAM_MIN => 1, |
154 | 159 | ApiBase :: PARAM_MAX => 72, |
155 | 160 | ), |
156 | | - 'allrev' => null |
| 161 | + 'allrev' => null, |
| 162 | + 'wluser' => array ( |
| 163 | + ApiBase :: PARAM_TYPE => 'user' |
| 164 | + ), |
| 165 | + 'wltoken' => array ( |
| 166 | + ApiBase :: PARAM_TYPE => 'string' |
| 167 | + ) |
157 | 168 | ); |
158 | 169 | } |
159 | 170 | |
— | — | @@ -160,7 +171,9 @@ |
161 | 172 | return array ( |
162 | 173 | 'feedformat' => 'The format of the feed', |
163 | 174 | 'hours' => 'List pages modified within this many hours from now', |
164 | | - 'allrev' => 'Include multiple revisions of the same page within given timeframe.' |
| 175 | + 'allrev' => 'Include multiple revisions of the same page within given timeframe.', |
| 176 | + 'wluser' => "The user whose watchlist you want (must be accompanied by wltoken if it's not you)", |
| 177 | + 'wltoken' => 'Security token that requested user set in their preferences' |
165 | 178 | ); |
166 | 179 | } |
167 | 180 | |
Index: trunk/phase3/includes/Preferences.php |
— | — | @@ -746,7 +746,7 @@ |
747 | 747 | } |
748 | 748 | |
749 | 749 | static function watchlistPreferences( $user, &$defaultPreferences ) { |
750 | | - global $wgUseRCPatrol; |
| 750 | + global $wgUseRCPatrol, $wgEnableAPI; |
751 | 751 | ## Watchlist ##################################### |
752 | 752 | $defaultPreferences['watchlistdays'] = |
753 | 753 | array( |
— | — | @@ -800,6 +800,17 @@ |
801 | 801 | 'section' => 'watchlist/advancedwatchlist', |
802 | 802 | 'label-message' => 'tog-watchlisthideliu', |
803 | 803 | ); |
| 804 | + if ( $wgEnableAPI ) { |
| 805 | + # Some random gibberish as a proposed default |
| 806 | + $hash = sha1( mt_rand() . microtime( true ) ); |
| 807 | + $defaultPreferences['watchlisttoken'] = |
| 808 | + array( |
| 809 | + 'type' => 'text', |
| 810 | + 'section' => 'watchlist/advancedwatchlist', |
| 811 | + 'label-message' => 'prefs-watchlist-token', |
| 812 | + 'help' => wfMsgHtml( 'prefs-help-watchlist-token', $hash ) |
| 813 | + ); |
| 814 | + } |
804 | 815 | |
805 | 816 | if ( $wgUseRCPatrol ) { |
806 | 817 | $defaultPreferences['watchlisthidepatrolled'] = |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -1700,6 +1700,7 @@ |
1701 | 1701 | 'prefs-watchlist-days-max' => '(maximum 7 days)', |
1702 | 1702 | 'prefs-watchlist-edits' => 'Maximum number of changes to show in expanded watchlist:', |
1703 | 1703 | 'prefs-watchlist-edits-max' => '(maximum number: 1000)', |
| 1704 | +'prefs-watchlist-token' => 'Watchlist token', |
1704 | 1705 | 'prefs-misc' => 'Misc', |
1705 | 1706 | 'prefs-resetpass' => 'Change password', |
1706 | 1707 | 'prefs-email' => 'E-mail options', |
— | — | @@ -1720,6 +1721,9 @@ |
1721 | 1722 | 'recentchangesdays-max' => '(maximum $1 {{PLURAL:$1|day|days}})', |
1722 | 1723 | 'recentchangescount' => 'Number of edits to show by default:', |
1723 | 1724 | 'prefs-help-recentchangescount' => 'This includes recent changes, page histories, and logs.', |
| 1725 | +'prefs-help-watchlist-token' => "Filling in this field with a secret key will generate an RSS feed for your watchlist. |
| 1726 | +Anyone who knows the key in this field will be able to read your watchlist, so choose a secure value. |
| 1727 | +Here's a randomly-generated value you can use: $1", |
1724 | 1728 | 'savedprefs' => 'Your preferences have been saved.', |
1725 | 1729 | 'timezonelegend' => 'Time zone:', |
1726 | 1730 | 'localtime' => 'Local time:', |