Index: trunk/extensions/EtherpadLite/EtherpadLite.i18n.php |
— | — | @@ -14,5 +14,5 @@ |
15 | 15 | $messages['en'] = array( |
16 | 16 | 'etherpadlite-desc' => 'Adds <eplite> parser tag to embed one or many Etherpad Lite pads (which are hosted on local or external Etherpad Lite server/s) on pages', |
17 | 17 | 'etherpadlite-invalid-pad-url' => '"$1" is not a valid Etherpad Lite URL or pad name.', |
18 | | - 'etherpadlite-url-is-not-whitelisted' => '"$1" is not in the whitelist of allowed Etherpad Lite servers.', |
| 18 | + 'etherpadlite-url-is-not-whitelisted' => '"$1" is not in the whitelist of allowed Etherpad Lite servers. The allowed servers are as follows: $2', |
19 | 19 | ); |
Index: trunk/extensions/EtherpadLite/EtherpadLite.php |
— | — | @@ -92,6 +92,9 @@ |
93 | 93 | # Attention: |
94 | 94 | # Urls are case-sensitively tested against values in the array. |
95 | 95 | # They must exactly match including any trailing "/" character. |
| 96 | +# |
| 97 | +# Warning: Allowing all urls (not setting a whitelist) |
| 98 | +# may be a security concern. |
96 | 99 | $wgEtherpadLiteUrlWhitelist = array(); |
97 | 100 | |
98 | 101 | # https://www.mediawiki.org/wiki/Manual:Tag_extensions |
— | — | @@ -140,30 +143,19 @@ |
141 | 144 | # id= is the pad name (also known as pad id) and is user input in <eplite id= > tag from MediaWiki page |
142 | 145 | |
143 | 146 | $src = ( isset( $args['src'] ) ) ? $args['src'] : $wgEtherpadLiteDefaultPadUrl; |
| 147 | + # Sanitizer::cleanUrl just does some normalization, somewhat not needed. |
| 148 | + $src = Sanitizer::cleanUrl( $src ); |
144 | 149 | |
145 | | - # Anything from a parser tag should use Content lang for message, |
146 | | - # since the cache doesn't vary by user language: do not use wfMsgForContent but wfMsgForContent |
147 | 150 | if ( count( $wgEtherpadLiteUrlWhitelist ) && !in_array( $src, $wgEtherpadLiteUrlWhitelist ) ) { |
148 | | - return wfMsgForContent( 'etherpadlite-url-is-not-whitelisted', htmlspecialchars( $src ) ); |
| 151 | + $listOfAllowed = $parser->getFunctionLang()->listToText( $wgEtherpadLiteUrlWhitelist ); |
| 152 | + return wfEtherpadLiteError( 'etherpadlite-url-is-not-whitelisted', |
| 153 | + array( $src, $listOfAllowed ) |
| 154 | + ); |
149 | 155 | } |
150 | 156 | |
151 | | - if ( !Http::isValidURI( $src ) ) { |
152 | | - return wfMsgForContent( 'etherpadlite-invalid-pad-url', htmlspecialchars( $src ) ); |
153 | | - } else { |
154 | | - $args['src'] = Sanitizer::cleanUrl ( $src ); |
155 | | - } |
156 | | - |
157 | | - # let's use the MediaWiki santizer for our user attributes |
158 | | - |
159 | | - $sanitizedAttributes = Sanitizer::validateAttributes( $args, array ( "width", "height", "id", "src" ) ); |
| 157 | + # Append the id to end of url. Strip off trailing / if present before appending one. |
| 158 | + $url = preg_replace( "/\/+$/", "", $src ) . "/" . $args['id']; |
160 | 159 | |
161 | | - $url = Sanitizer::cleanUrl( preg_replace( "/\/+$/", "", $sanitizedAttributes['src'] ) . "/" . $sanitizedAttributes['id'] ); |
162 | | - |
163 | | - # just check again with the pad id appended |
164 | | - |
165 | | - if ( !Http::isValidURI( $url ) ) { |
166 | | - return wfMsgForContent( 'etherpadlite-invalid-pad-url', htmlspecialchars( $url ) ); |
167 | | - } |
168 | 160 | |
169 | 161 | # preset the pad username from MediaWiki username or IP |
170 | 162 | # this not strict, as the pad username can be overwritten in the pad |
— | — | @@ -171,6 +163,10 @@ |
172 | 164 | # attention: |
173 | 165 | # 1. we must render the page for each visiting user to get their username |
174 | 166 | # 2. the pad username can currently be overwritten when editing the pad |
| 167 | + # |
| 168 | + # Future todo might be to make the adding of username optional |
| 169 | + # since disabling of cache has a significant performance impact |
| 170 | + # on larger sites. |
175 | 171 | |
176 | 172 | $parser->disableCache(); |
177 | 173 | |
— | — | @@ -183,19 +179,44 @@ |
184 | 180 | "userName" => rawurlencode( $wgUser->getName() ), |
185 | 181 | ) |
186 | 182 | ); |
187 | | - |
| 183 | + |
| 184 | + # @todo One could potentially stuff other css in the width argument |
| 185 | + # since ; isn't checked for. Since overall css is checked for allowed |
| 186 | + # rules, this isn't super big deal. |
188 | 187 | $iframeAttributes = array( |
189 | | - "style" => "width:" . $sanitizedAttributes['width'] . ";" . |
190 | | - "height:" . $sanitizedAttributes['height'], |
191 | | - "class" => "eplite-iframe-" . $sanitizedAttributes['id'] , |
| 188 | + "style" => "width:" . $args['width'] . ";" . |
| 189 | + "height:" . $args['height'], |
| 190 | + "class" => "eplite-iframe-" . $args['id'] , |
192 | 191 | "src" => Sanitizer::cleanUrl( $url ), |
193 | 192 | ); |
194 | 193 | |
| 194 | + $sanitizedAttributes = Sanitizer::validateAttributes( $iframeAttributes, array ( "style", "class", "src" ) ); |
| 195 | + |
| 196 | + if ( !isset( $sanitizedAttributes['src'] ) ) { |
| 197 | + // The Sanitizer decided that the src attribute was no good. |
| 198 | + // (aka used a protocol that isn't in the whitelist) |
| 199 | + return wfEtherpadLiteError( 'etherpadlite-invalid-pad-url', $src ); |
| 200 | + } |
| 201 | + |
195 | 202 | $output = Html::rawElement( |
196 | 203 | 'iframe', |
197 | | - Sanitizer::validateAttributes( $iframeAttributes, array ( "style", "class", "src" ) ) |
| 204 | + $sanitizedAttributes |
198 | 205 | ); |
199 | 206 | |
200 | 207 | wfDebug( "EtherpadLite:wfEtherpadLiteRender $output\n" ); |
201 | | - return array( $output ); |
| 208 | + return $output; |
202 | 209 | } |
| 210 | +/** |
| 211 | + * Output an error message, all wraped up nicely. |
| 212 | + * @param String $errorName The system message that this error is |
| 213 | + * @param String|Array $param Error parameter (or parameters) |
| 214 | + * @return String Html that is the error. |
| 215 | + */ |
| 216 | +function wfEtherpadLiteError( $errorName, $param ) { |
| 217 | + // Anything from a parser tag should use Content lang for message, |
| 218 | + // since the cache doesn't vary by user language: do not use wfMsgForContent but wfMsgForContent |
| 219 | + // The ->parse() part makes everything safe from an escaping standpoint. |
| 220 | + return Html::rawElement( 'span', array( 'class' => 'error' ), |
| 221 | + wfMessage( $errorName )->inContentLanguage()->params( $param )->parse() |
| 222 | + ); |
| 223 | +} |