Index: trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php |
— | — | @@ -33,9 +33,9 @@ |
34 | 34 | 'lqt_new_thread' => 'Start a new discussion', |
35 | 35 | 'lqt_invalid_subject' => 'The subject you entered is invalid. |
36 | 36 | It may: |
37 | | -* Contain invalid characters, such as []{}<>, |
38 | 37 | * Be too long, or |
39 | 38 | * Conflict with interwiki prefixes or namespace names.', |
| 39 | + 'lqt_empty_subject' => 'You must enter a subject.', |
40 | 40 | 'lqt_subject_change_forbidden' => 'You cannot change the subject for this thread because you are not allowed to move pages.', |
41 | 41 | 'lqt_in_response_to' => 'In reply to $1 by $2, above:', |
42 | 42 | 'lqt_edited_notice' => 'Edited', |
Index: trunk/extensions/LiquidThreads/classes/Threads.php |
— | — | @@ -201,16 +201,47 @@ |
202 | 202 | return self::incrementedTitle( $base, NS_LQT_THREAD ); |
203 | 203 | } |
204 | 204 | |
| 205 | + // This will attempt to replace invalid characters and sequences in a title with |
| 206 | + // a safe replacement (_, currently). |
| 207 | + public static function makeTitleValid( $text ) { |
| 208 | + static $rxTc; |
| 209 | + |
| 210 | + if ( is_callable( array( 'Title', 'getTitleInvalidRegex' ) ) ) { |
| 211 | + $rxTc = Title::getTitleInvalidRegex(); |
| 212 | + } elseif (!$rxTc) { // Back-compat |
| 213 | + $rxTc = '/' . |
| 214 | + # Any character not allowed is forbidden... |
| 215 | + '[^' . Title::legalChars() . ']' . |
| 216 | + # URL percent encoding sequences interfere with the ability |
| 217 | + # to round-trip titles -- you can't link to them consistently. |
| 218 | + '|%[0-9A-Fa-f]{2}' . |
| 219 | + # XML/HTML character references produce similar issues. |
| 220 | + '|&[A-Za-z0-9\x80-\xff]+;' . |
| 221 | + '|&#[0-9]+;' . |
| 222 | + '|&#x[0-9A-Fa-f]+;' . |
| 223 | + '/S'; |
| 224 | + } |
| 225 | + |
| 226 | + $text = preg_replace( $rxTc, '_', $text ); |
| 227 | + |
| 228 | + return $text; |
| 229 | + } |
| 230 | + |
205 | 231 | /** Keep trying titles starting with $basename until one is unoccupied. */ |
206 | 232 | public static function incrementedTitle( $basename, $namespace ) { |
207 | 233 | $i = 2; |
208 | 234 | |
209 | | - $replacements = array_fill_keys( array( '[', ']', '{', '}', '|' ), '_' ); |
210 | | - $basename = strtr( $basename, $replacements ); |
| 235 | + // Try to make the title valid. |
| 236 | + $basename = Threads::makeTitleValid( $basename ); |
211 | 237 | |
212 | 238 | $t = Title::makeTitleSafe( $namespace, $basename ); |
213 | 239 | while ( !$t || $t->exists() || |
214 | 240 | in_array( $t->getPrefixedDBkey(), self::$occupied_titles ) ) { |
| 241 | + |
| 242 | + if (!$t) { |
| 243 | + throw new MWException( "Error in creating title for basename $basename" ); |
| 244 | + } |
| 245 | + |
215 | 246 | $t = Title::makeTitleSafe( $namespace, $basename . ' (' . $i . ')' ); |
216 | 247 | $i++; |
217 | 248 | } |
Index: trunk/extensions/LiquidThreads/classes/View.php |
— | — | @@ -273,27 +273,31 @@ |
274 | 274 | throughout the edit cycle, since the article doesn't exist yet anyways. |
275 | 275 | */ |
276 | 276 | |
277 | | - // Stuff that might break the save |
| 277 | + // Check if we actually want a subject, pull the submitted subject, and validate it. |
| 278 | + $subject_expected = ( $edit_type == 'new' || $thread && $thread->isTopmostThread() ); |
| 279 | + $subject = $this->request->getVal( 'lqt_subject_field', '' ); |
278 | 280 | $valid_subject = true; |
279 | | - $failed_rename = false; |
280 | 281 | |
281 | | - $subject = $this->request->getVal( 'lqt_subject_field', '' ); |
282 | | - |
283 | 282 | if ( $edit_type == 'summarize' && $edit_applies_to->summary() ) { |
284 | 283 | $article = $edit_applies_to->summary(); |
285 | 284 | } elseif ( $edit_type == 'summarize' ) { |
286 | 285 | $t = $this->newSummaryTitle( $edit_applies_to ); |
287 | 286 | $article = new Article( $t ); |
288 | | - } elseif ( $thread == null ) { |
289 | | - if ( $subject && is_null( Title::makeTitleSafe( NS_LQT_THREAD, $subject ) ) ) { |
| 287 | + } elseif ( !$thread ) { |
| 288 | + if ( !$subject ) { |
290 | 289 | // Dodgy title |
| 290 | + $t = $this->scratchTitle(); |
291 | 291 | $valid_subject = false; |
292 | | - $t = $this->scratchTitle(); |
293 | | - } else { |
294 | | - if ( $edit_type == 'new' ) { |
295 | | - $t = $this->newScratchTitle( $subject ); |
296 | | - } elseif ( $edit_type == 'reply' ) { |
297 | | - $t = $this->newReplyTitle( $subject, $edit_applies_to ); |
| 292 | + } else { |
| 293 | + try { |
| 294 | + if ( $edit_type == 'new' ) { |
| 295 | + $t = $this->newScratchTitle( $subject ); |
| 296 | + } elseif ( $edit_type == 'reply' ) { |
| 297 | + $t = $this->newReplyTitle( $subject, $edit_applies_to ); |
| 298 | + } |
| 299 | + } catch( MWException $excep ) { |
| 300 | + $t = $this->scratchTitle(); |
| 301 | + $valid_subject = false; |
298 | 302 | } |
299 | 303 | } |
300 | 304 | $article = new Article( $t ); |
— | — | @@ -303,15 +307,21 @@ |
304 | 308 | |
305 | 309 | $e = new EditPage( $article ); |
306 | 310 | |
307 | | - |
308 | | - // Find errors. |
309 | | - if (!$valid_subject && $subject) { |
| 311 | + // Display an error if a subject is specified but it's invalid |
| 312 | + if ( $subject_expected && $this->request->wasPosted() && !$valid_subject ) { |
| 313 | + if ( !$subject ) { |
| 314 | + $msg = 'lqt_empty_subject'; |
| 315 | + } else { |
| 316 | + $msg = 'lqt_invalid_subject'; |
| 317 | + } |
| 318 | + |
310 | 319 | $e->editFormPageTop .= |
311 | 320 | Xml::tags( 'div', array( 'class' => 'error' ), |
312 | | - wfMsgExt( 'lqt_invalid_subject', 'parse' ) ); |
| 321 | + wfMsgExt( $msg, 'parse' ) ); |
313 | 322 | } |
314 | 323 | |
315 | | - if ( (!$valid_subject && $subject) || $failed_rename ) { |
| 324 | + // Quietly force a preview if no subject has been specified. |
| 325 | + if ( (!$valid_subject && $subject) || ($subject_expected && !$subject) ) { |
316 | 326 | // Dirty hack to prevent saving from going ahead |
317 | 327 | global $wgRequest; |
318 | 328 | $wgRequest->setVal( 'wpPreview', true ); |
— | — | @@ -339,7 +349,7 @@ |
340 | 350 | $wgMemc->set( $key, 1, 3600 ); |
341 | 351 | } |
342 | 352 | |
343 | | - if ( $edit_type == 'new' ) { |
| 353 | + if ( $subject_expected ) { |
344 | 354 | wfLoadExtensionMessages( 'LiquidThreads' ); |
345 | 355 | // This is a top-level post; show the subject line. |
346 | 356 | $db_subject = $thread ? $thread->subjectWithoutIncrement() : ''; |