This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * |
||
4 | * |
||
5 | * Created on June 06, 2011 |
||
6 | * |
||
7 | * Copyright © 2011 Sam Reed |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or modify |
||
10 | * it under the terms of the GNU General Public License as published by |
||
11 | * the Free Software Foundation; either version 2 of the License, or |
||
12 | * (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU General Public License along |
||
20 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
22 | * http://www.gnu.org/copyleft/gpl.html |
||
23 | * |
||
24 | * @file |
||
25 | */ |
||
26 | |||
27 | /** |
||
28 | * @ingroup API |
||
29 | */ |
||
30 | class ApiFeedContributions extends ApiBase { |
||
31 | |||
32 | /** |
||
33 | * This module uses a custom feed wrapper printer. |
||
34 | * |
||
35 | * @return ApiFormatFeedWrapper |
||
36 | */ |
||
37 | public function getCustomPrinter() { |
||
38 | return new ApiFormatFeedWrapper( $this->getMain() ); |
||
39 | } |
||
40 | |||
41 | public function execute() { |
||
42 | $params = $this->extractRequestParams(); |
||
43 | |||
44 | $config = $this->getConfig(); |
||
45 | if ( !$config->get( 'Feed' ) ) { |
||
46 | $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' ); |
||
47 | } |
||
48 | |||
49 | $feedClasses = $config->get( 'FeedClasses' ); |
||
50 | if ( !isset( $feedClasses[$params['feedformat']] ) ) { |
||
51 | $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' ); |
||
52 | } |
||
53 | |||
54 | if ( $params['showsizediff'] && $this->getConfig()->get( 'MiserMode' ) ) { |
||
55 | $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' ); |
||
56 | } |
||
57 | |||
58 | $msg = wfMessage( 'Contributions' )->inContentLanguage()->text(); |
||
59 | $feedTitle = $config->get( 'Sitename' ) . ' - ' . $msg . |
||
60 | ' [' . $config->get( 'LanguageCode' ) . ']'; |
||
61 | $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL(); |
||
62 | |||
63 | $target = $params['user'] == 'newbies' |
||
64 | ? 'newbies' |
||
65 | : Title::makeTitleSafe( NS_USER, $params['user'] )->getText(); |
||
66 | |||
67 | $feed = new $feedClasses[$params['feedformat']] ( |
||
68 | $feedTitle, |
||
69 | htmlspecialchars( $msg ), |
||
70 | $feedUrl |
||
71 | ); |
||
72 | |||
73 | $pager = new ContribsPager( $this->getContext(), [ |
||
74 | 'target' => $target, |
||
75 | 'namespace' => $params['namespace'], |
||
76 | 'year' => $params['year'], |
||
77 | 'month' => $params['month'], |
||
78 | 'tagFilter' => $params['tagfilter'], |
||
79 | 'deletedOnly' => $params['deletedonly'], |
||
80 | 'topOnly' => $params['toponly'], |
||
81 | 'newOnly' => $params['newonly'], |
||
82 | 'hideMinor' => $params['hideminor'], |
||
83 | 'showSizeDiff' => $params['showsizediff'], |
||
84 | ] ); |
||
85 | |||
86 | $feedLimit = $this->getConfig()->get( 'FeedLimit' ); |
||
87 | if ( $pager->getLimit() > $feedLimit ) { |
||
88 | $pager->setLimit( $feedLimit ); |
||
89 | } |
||
90 | |||
91 | $feedItems = []; |
||
92 | if ( $pager->getNumRows() > 0 ) { |
||
93 | $count = 0; |
||
94 | $limit = $pager->getLimit(); |
||
95 | foreach ( $pager->mResult as $row ) { |
||
96 | // ContribsPager selects one more row for navigation, skip that row |
||
97 | if ( ++$count > $limit ) { |
||
98 | break; |
||
99 | } |
||
100 | $item = $this->feedItem( $row ); |
||
101 | if ( $item !== null ) { |
||
102 | $feedItems[] = $item; |
||
103 | } |
||
104 | } |
||
105 | } |
||
106 | |||
107 | ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); |
||
108 | } |
||
109 | |||
110 | protected function feedItem( $row ) { |
||
111 | // This hook is the api contributions equivalent to the |
||
112 | // ContributionsLineEnding hook. Hook implementers may cancel |
||
113 | // the hook to signal the user is not allowed to read this item. |
||
114 | $feedItem = null; |
||
115 | $hookResult = Hooks::run( |
||
116 | 'ApiFeedContributions::feedItem', |
||
117 | [ $row, $this->getContext(), &$feedItem ] |
||
118 | ); |
||
119 | // Hook returned a valid feed item |
||
120 | if ( $feedItem instanceof FeedItem ) { |
||
121 | return $feedItem; |
||
122 | // Hook was canceled and did not return a valid feed item |
||
123 | } elseif ( !$hookResult ) { |
||
124 | return null; |
||
125 | } |
||
126 | |||
127 | // Hook completed and did not return a valid feed item |
||
128 | $title = Title::makeTitle( intval( $row->page_namespace ), $row->page_title ); |
||
129 | if ( $title && $title->userCan( 'read', $this->getUser() ) ) { |
||
130 | $date = $row->rev_timestamp; |
||
131 | $comments = $title->getTalkPage()->getFullURL(); |
||
132 | $revision = Revision::newFromRow( $row ); |
||
133 | |||
134 | return new FeedItem( |
||
135 | $title->getPrefixedText(), |
||
136 | $this->feedItemDesc( $revision ), |
||
137 | $title->getFullURL( [ 'diff' => $revision->getId() ] ), |
||
138 | $date, |
||
139 | $this->feedItemAuthor( $revision ), |
||
0 ignored issues
–
show
|
|||
140 | $comments |
||
141 | ); |
||
142 | } |
||
143 | |||
144 | return null; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * @param Revision $revision |
||
149 | * @return string |
||
150 | */ |
||
151 | protected function feedItemAuthor( $revision ) { |
||
152 | return $revision->getUserText(); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * @param Revision $revision |
||
157 | * @return string |
||
158 | */ |
||
159 | protected function feedItemDesc( $revision ) { |
||
160 | if ( $revision ) { |
||
161 | $msg = wfMessage( 'colon-separator' )->inContentLanguage()->text(); |
||
162 | $content = $revision->getContent(); |
||
163 | |||
164 | if ( $content instanceof TextContent ) { |
||
165 | // only textual content has a "source view". |
||
166 | $html = nl2br( htmlspecialchars( $content->getNativeData() ) ); |
||
167 | } else { |
||
168 | // XXX: we could get an HTML representation of the content via getParserOutput, but that may |
||
169 | // contain JS magic and generally may not be suitable for inclusion in a feed. |
||
170 | // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method. |
||
171 | // Compare also FeedUtils::formatDiffRow. |
||
172 | $html = ''; |
||
173 | } |
||
174 | |||
175 | return '<p>' . htmlspecialchars( $revision->getUserText() ) . $msg . |
||
176 | htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) . |
||
177 | "</p>\n<hr />\n<div>" . $html . '</div>'; |
||
178 | } |
||
179 | |||
180 | return ''; |
||
181 | } |
||
182 | |||
183 | public function getAllowedParams() { |
||
184 | $feedFormatNames = array_keys( $this->getConfig()->get( 'FeedClasses' ) ); |
||
185 | |||
186 | $ret = [ |
||
187 | 'feedformat' => [ |
||
188 | ApiBase::PARAM_DFLT => 'rss', |
||
189 | ApiBase::PARAM_TYPE => $feedFormatNames |
||
190 | ], |
||
191 | 'user' => [ |
||
192 | ApiBase::PARAM_TYPE => 'user', |
||
193 | ApiBase::PARAM_REQUIRED => true, |
||
194 | ], |
||
195 | 'namespace' => [ |
||
196 | ApiBase::PARAM_TYPE => 'namespace' |
||
197 | ], |
||
198 | 'year' => [ |
||
199 | ApiBase::PARAM_TYPE => 'integer' |
||
200 | ], |
||
201 | 'month' => [ |
||
202 | ApiBase::PARAM_TYPE => 'integer' |
||
203 | ], |
||
204 | 'tagfilter' => [ |
||
205 | ApiBase::PARAM_ISMULTI => true, |
||
206 | ApiBase::PARAM_TYPE => array_values( ChangeTags::listDefinedTags() ), |
||
207 | ApiBase::PARAM_DFLT => '', |
||
208 | ], |
||
209 | 'deletedonly' => false, |
||
210 | 'toponly' => false, |
||
211 | 'newonly' => false, |
||
212 | 'hideminor' => false, |
||
213 | 'showsizediff' => [ |
||
214 | ApiBase::PARAM_DFLT => false, |
||
215 | ], |
||
216 | ]; |
||
217 | |||
218 | if ( $this->getConfig()->get( 'MiserMode' ) ) { |
||
219 | $ret['showsizediff'][ApiBase::PARAM_HELP_MSG] = 'api-help-param-disabled-in-miser-mode'; |
||
220 | } |
||
221 | |||
222 | return $ret; |
||
223 | } |
||
224 | |||
225 | protected function getExamplesMessages() { |
||
226 | return [ |
||
227 | 'action=feedcontributions&user=Example' |
||
228 | => 'apihelp-feedcontributions-example-simple', |
||
229 | ]; |
||
230 | } |
||
231 | } |
||
232 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.