r89719 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r89718‎ | r89719 | r89720 >
Date:04:50, 8 June 2011
Author:nagelp
Status:resolved (Comments)
Tags:
Comment:
Switched to Notificator::checkEmailAddress() again, after discovering that Sanitizer::validateEmail() is not available in any released MW version; Lots of whitespace changes (ran stylize.php and limited line length to <100).
Modified paths:
  • /trunk/extensions/Notificator/Notificator.body.php (modified) (history)
  • /trunk/extensions/Notificator/Notificator.i18n.php (modified) (history)
  • /trunk/extensions/Notificator/Notificator.php (modified) (history)
  • /trunk/extensions/Notificator/SpecialNotificator.php (modified) (history)
  • /trunk/extensions/Notificator/diff-in-mail.css (modified) (history)

Diff [purge]

Index: trunk/extensions/Notificator/Notificator.body.php
@@ -1,105 +1,170 @@
22 <?php
33
4 -if (!defined('MEDIAWIKI')) {
 4+if ( !defined( 'MEDIAWIKI' ) ) {
55 echo "Not a valid entry point";
6 - exit(1);
 6+ exit( 1 );
77 }
88
99 class Notificator {
1010
11 -public static function notificator_Render($parser, $receiver = '', $receiverLabel = '') {
 11+public static function notificator_Render( $parser, $receiver = '', $receiverLabel = '' ) {
 12+
1213 global $wgScript, $wgTitle;
1314
14 - if(! $receiverLabel) {
 15+ if ( ! $receiverLabel ) {
1516 $receiverLabel = $receiver;
1617 }
1718
1819 // Check that the database table is in place
19 - if(! Notificator::checkDatabaseTableExists()) {
20 - $output = '<span class="error">' . wfMsg('notificator-db-table-does-not-exist') . '</span>';
21 - return array($output, 'noparse' => true, 'isHTML' => true);
 20+ if ( ! Notificator::checkDatabaseTableExists() ) {
 21+ $output = '<span class="error">' .
 22+ wfMsg( 'notificator-db-table-does-not-exist' ) . '</span>';
 23+ return array( $output, 'noparse' => true, 'isHTML' => true );
2224 }
2325
2426 // Check whether the parameter is a valid e-mail address or not
25 - if($receiver && Sanitizer::validateEmail($receiver)) {
 27+ if ( $receiver && Notificator::checkEmailAddress( $receiver ) ) {
2628 // Valid e-mail address available, so just show a button
27 - $output = '<form action="' . $wgScript . '/Special:Notificator" method="post" enctype="multipart/form-data">
 29+ $output = '<form action="' . $wgScript .
 30+ '/Special:Notificator" method="post" enctype="multipart/form-data">
2831 <input type="hidden" name="pageId" value="' . $wgTitle->getArticleID() . '" />
2932 <input type="hidden" name="revId" value="' . $wgTitle->getLatestRevID() . '" />
3033 <input type="hidden" name="receiver" value="' . $receiver . '" />
31 -<input type="submit" value="' . wfMsg('notify-address-or-name', htmlspecialchars($receiverLabel)) . '" />
 34+<input type="submit" value="' .
 35+wfMsg( 'notify-address-or-name', htmlspecialchars( $receiverLabel ) ) . '" />
3236 </form>';
3337 } else {
3438 // No valid e-mail address available, show text entry field and button
35 - $output = '<form action="' . $wgScript . '/Special:Notificator" method="post" enctype="multipart/form-data">
 39+ $output = '<form action="' . $wgScript .
 40+ '/Special:Notificator" method="post" enctype="multipart/form-data">
3641 <input type="hidden" name="pageId" value="' . $wgTitle->getArticleID() . '" />
3742 <input type="hidden" name="revId" value="' . $wgTitle->getLatestRevID() . '" />
38 -<input type="text" name="receiver" value="' . wfMsg('e-mail-address') . '" onfocus="if (this.value == \'' . wfMsg('e-mail-address') . '\') {this.value=\'\'}" />
39 -<input type="submit" value="' . wfMsg('notify') . '" />
 43+<input type="text" name="receiver" value="' . wfMsg( 'e-mail-address' ) .
 44+'" onfocus="if (this.value == \'' . wfMsg( 'e-mail-address' ) .
 45+'\') {this.value=\'\'}" />
 46+<input type="submit" value="' . wfMsg( 'notify' ) . '" />
4047 </form>';
4148 }
4249
43 - return $parser->insertStripItem($output, $parser->mStripState);
 50+ return $parser->insertStripItem( $output, $parser->mStripState );
4451 }
4552
4653 private function checkDatabaseTableExists() {
47 - $dbr = wfGetDB(DB_SLAVE);
48 - $res = $dbr->tableExists('notificator');
 54+ $dbr = wfGetDB( DB_SLAVE );
 55+ $res = $dbr->tableExists( 'notificator' );
4956 return $res;
5057 }
5158
5259 private function getDiffCss() {
5360 $ret = '';
54 - $file = fopen(dirname(__FILE__) . '/diff-in-mail.css', 'r');
55 - while(!feof($file)) {
56 - $ret = $ret . fgets($file, 4096);
 61+ $file = fopen( dirname( __FILE__ ) . '/diff-in-mail.css', 'r' );
 62+ while ( !feof( $file ) ) {
 63+ $ret = $ret . fgets( $file, 4096 );
5764 }
58 - fclose ($file);
 65+ fclose ( $file );
5966 return $ret;
6067 }
6168
62 -public static function getLastNotifiedRevId($pageId, $revId, $receiver) {
 69+public static function checkEmailAddress( $string ) {
 70+// from http://www.linuxjournal.com/article/9585
 71+ $isValid = true;
 72+ $atIndex = strrpos( $string, "@" );
 73+ if ( is_bool( $atIndex ) && !$atIndex ) {
 74+ $isValid = false;
 75+ } else {
 76+ $domain = substr( $string, $atIndex + 1 );
 77+ $local = substr( $string, 0, $atIndex );
 78+ $localLen = strlen( $local );
 79+ $domainLen = strlen( $domain );
 80+ if ( $localLen < 1 || $localLen > 64 ) {
 81+ // local part length exceeded
 82+ $isValid = false;
 83+ }
 84+ else if ( $domainLen < 1 || $domainLen > 255 ) {
 85+ // domain part length exceeded
 86+ $isValid = false;
 87+ }
 88+ else if ( $local[0] == '.' || $local[$localLen -1] == '.' ) {
 89+ // local part starts or ends with '.'
 90+ $isValid = false;
 91+ }
 92+ else if ( preg_match( '/\\.\\./', $local ) ) {
 93+ // local part has two consecutive dots
 94+ $isValid = false;
 95+ }
 96+ else if ( !preg_match( '/^[A-Za-z0-9\\-\\.]+$/', $domain ) ) {
 97+ // character not valid in domain part
 98+ $isValid = false;
 99+ }
 100+ else if ( preg_match( '/\\.\\./', $domain ) ) {
 101+ // domain part has two consecutive dots
 102+ $isValid = false;
 103+ }
 104+ else if ( !preg_match( '/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
 105+ str_replace( "\\\\", "", $local ) ) ) {
 106+ // character not valid in local part unless
 107+ // local part is quoted
 108+ if ( !preg_match( '/^"(\\\\"|[^"])+"$/', str_replace( "\\\\", "", $local ) ) ) {
 109+ $isValid = false;
 110+ }
 111+ }
 112+ if ( $isValid && !( checkdnsrr( $domain, "MX" ) || checkdnsrr( $domain, "A" ) ) ) {
 113+ // domain not found in DNS
 114+ $isValid = false;
 115+ }
 116+ }
 117+ return $isValid;
 118+}
 119+
 120+public static function getLastNotifiedRevId( $pageId, $revId, $receiver ) {
63121 // Returns -1 if any parameter is missing
64 - // Returns -2 if the database revId is the same as the given revId (= notified already)
 122+ // Returns -2 if the database revId is the same as the given revId
 123+ // (= notified already)
65124 // Returns revId from the database - if there is no record, return 0
66125
67 - if (! $pageId || ! $revId || ! $receiver) {
 126+ if ( ! $pageId || ! $revId || ! $receiver ) {
68127 return -1;
69128 }
70129
71130 // Get $oldRevId from database
72 - $dbr = wfGetDB(DB_SLAVE);
73 - $res = $dbr->select('notificator', // table
74 - 'rev_id', // vars (columns of the table)
75 - array('page_id' => (int)$pageId, 'receiver_email' => $receiver) // conds
76 - );
 131+ $dbr = wfGetDB( DB_SLAVE );
 132+ $res = $dbr->select(
 133+ 'notificator', // table
 134+ 'rev_id', // vars (columns of the table)
 135+ array( // conds
 136+ 'page_id' => (int)$pageId,
 137+ 'receiver_email' => $receiver
 138+ )
 139+ );
77140
78 - $row = $dbr->fetchRow($res);
 141+ $row = $dbr->fetchRow( $res );
79142
80143 $oldRevId = $row[rev_id];
81144
82 - if(! $oldRevId) {
 145+ if ( ! $oldRevId ) {
83146 $oldRevId = 0;
84 - } elseif ($oldRevId == $revId) {
 147+ } elseif ( $oldRevId == $revId ) {
85148 $oldRevId = -2;
86149 }
87150
88151 return $oldRevId;
89152 }
90153
91 -public static function getNotificationDiffHtml($oldRevId, $revId) {
92 - $oldRevisionObj = Revision::newFromId($oldRevId);
93 - $newRevisionObj = Revision::newFromId($revId);
 154+public static function getNotificationDiffHtml( $oldRevId, $revId ) {
 155+ $oldRevisionObj = Revision::newFromId( $oldRevId );
 156+ $newRevisionObj = Revision::newFromId( $revId );
94157
95 - if($oldRevisionObj->getTitle() != $newRevisionObj->getTitle()) {
96 - return '<span class="error">' . wfMsg('revs-not-from-same-title') . '</span>';
 158+ if ( $oldRevisionObj->getTitle() != $newRevisionObj->getTitle() ) {
 159+ return '<span class="error">' .
 160+ wfMsg( 'revs-not-from-same-title' ) . '</span>';
97161 }
98162
99163 $titleObj = $oldRevisionObj->getTitle();
100164
101 - $differenceEngineObj = new DifferenceEngine($titleObj, $oldRevId, $revId);
 165+ $differenceEngineObj = new DifferenceEngine( $titleObj, $oldRevId, $revId );
102166
103 - $notificationDiffHtml = '<style media="screen" type="text/css">' . Notificator::getDiffCss() . '</style><table class="diff">
 167+ $notificationDiffHtml = '<style media="screen" type="text/css">' .
 168+ Notificator::getDiffCss() . '</style><table class="diff">
104169 <col class="diff-marker" />
105170 <col class="diff-content" />
106171 <col class="diff-marker" />
@@ -110,41 +175,51 @@
111176 return $notificationDiffHtml;
112177 }
113178
114 -public static function sendNotificationMail($receiver, $mailSubject, $notificationText) {
 179+public static function sendNotificationMail( $receiver, $mailSubject, $notificationText ) {
115180 global $ngFromAddress;
116181 $headers = 'From: ' . $ngFromAddress . "\r\n" .
117182 'X-Mailer: PHP/' . phpversion() . "\r\n" .
118183 'MIME-Version: 1.0' . "\r\n" .
119184 'Content-type: text/html; charset=utf-8' . "\r\n";
120 - $encodedMailSubject = mb_encode_mimeheader($mailSubject,"UTF-8", "B", "\n");
 185+ $encodedMailSubject = mb_encode_mimeheader( $mailSubject, "UTF-8", "B", "\n" );
121186
122 - return mail($receiver, $encodedMailSubject, $notificationText, $headers);
 187+ return mail( $receiver, $encodedMailSubject, $notificationText, $headers );
123188 }
124189
125 -public static function recordNotificationInDatabase($pageId, $revId, $receiver) {
126 - $lastNotifiedRevId = Notificator::getLastNotifiedRevId($pageId, $revId, $receiver);
127 - if($lastNotifiedRevId > 0) {
128 - $dbw = wfGetDB(DB_MASTER);
129 - $res = $dbw->update('notificator', // table
130 - array('rev_id' => (int)$revId), // vars (columns of the table)
131 - array('page_id' => (int)$pageId, 'receiver_email' => $receiver) // conds
132 - );
 190+public static function recordNotificationInDatabase( $pageId, $revId, $receiver ) {
 191+ $lastNotifiedRevId = Notificator::getLastNotifiedRevId( $pageId, $revId, $receiver );
 192+ if ( $lastNotifiedRevId > 0 ) {
 193+ $dbw = wfGetDB( DB_MASTER );
 194+ $res = $dbw->update(
 195+ 'notificator', // table
 196+ array( // vars (columns of the table)
 197+ 'rev_id' => (int)$revId
 198+ ),
 199+ array( // conds
 200+ 'page_id' => (int)$pageId,
 201+ 'receiver_email' => $receiver
 202+ )
 203+ );
133204 return $res;
134 - } elseif($lastNotifiedRevId == 0) {
135 - $dbw = wfGetDB(DB_MASTER);
136 - $res = $dbw->insert('notificator', // table
137 - array('page_id' => (int)$pageId,
138 - 'rev_id' => (int)$revId,
139 - 'receiver_email' => $receiver) // "$a"
140 - );
 205+ } elseif ( $lastNotifiedRevId == 0 ) {
 206+ $dbw = wfGetDB( DB_MASTER );
 207+ $res = $dbw->insert(
 208+ 'notificator', // table
 209+ array( // "$a"
 210+ 'page_id' => (int)$pageId,
 211+ 'rev_id' => (int)$revId,
 212+ 'receiver_email' => $receiver
 213+ )
 214+ );
141215 return $res;
142 - } elseif($lastNotifiedRevId < 0) {
 216+ } elseif ( $lastNotifiedRevId < 0 ) {
143217 return false;
144218 }
145219 }
146220
147 -public static function getReturnToText($linkToPage, $pageTitle) {
148 - return '<p style="margin-top: 2em;">' . wfMsg('return-to') . ' <a href="' . $linkToPage . '">' . $pageTitle . '</a>.';
 221+public static function getReturnToText( $linkToPage, $pageTitle ) {
 222+ return '<p style="margin-top: 2em;">' .
 223+ wfMsg( 'return-to' ) . ' <a href="' . $linkToPage . '">' . $pageTitle . '</a>.';
149224 }
150225
151226 }
Index: trunk/extensions/Notificator/diff-in-mail.css
@@ -46,4 +46,4 @@
4747 table.diff td div {
4848 word-wrap: break-word;
4949 overflow: auto;
50 -}
 50+}
Index: trunk/extensions/Notificator/Notificator.i18n.php
@@ -2,11 +2,11 @@
33
44 $aliases = array();
55 $messages = array();
6 -
 6+
77 $aliases['en'] = array(
88 'Notificator' => array( 'Notificator' ),
99 );
10 -
 10+
1111 $messages['en'] = array(
1212 'notificator' => 'Notificator',
1313 'notificator-description' => 'Notifies someone by e-mail about changes to a page when a button on that page gets clicked.',
Index: trunk/extensions/Notificator/Notificator.php
@@ -1,8 +1,8 @@
22 <?php
33
4 -if (!defined('MEDIAWIKI')) {
 4+if ( !defined( 'MEDIAWIKI' ) ) {
55 echo "Not a valid entry point";
6 - exit(1);
 6+ exit( 1 );
77 }
88
99 $wgExtensionCredits['parserhook'][] = array(
@@ -14,8 +14,8 @@
1515 'url' => "http://www.mediawiki.org/wiki/Extension:Notificator",
1616 );
1717
18 -$wgAutoloadClasses['Notificator'] = dirname(__FILE__) . '/Notificator.body.php';
19 -$wgAutoloadClasses['SpecialNotificator'] = dirname(__FILE__) . '/SpecialNotificator.php';
 18+$wgAutoloadClasses['Notificator'] = dirname( __FILE__ ) . '/Notificator.body.php';
 19+$wgAutoloadClasses['SpecialNotificator'] = dirname( __FILE__ ) . '/SpecialNotificator.php';
2020
2121 $wgHooks['LoadExtensionSchemaUpdates'][] = 'notificator_AddDatabaseTable';
2222 $wgHooks['ParserTestTables'][] = 'notificator_ParserTestTables';
@@ -31,21 +31,21 @@
3232
3333 function notificator_AddDatabaseTable() {
3434 global $wgExtNewTables;
35 - $wgExtNewTables[] = array('notificator', dirname( __FILE__ ) . '/Notificator.sql');
 35+ $wgExtNewTables[] = array( 'notificator', dirname( __FILE__ ) . '/Notificator.sql' );
3636 return true;
3737 }
3838
39 -function notificator_ParserTestTables(&$tables) {
 39+function notificator_ParserTestTables( &$tables ) {
4040 $tables[] = 'notificator';
4141 return true;
4242 }
4343
44 -function notificator_Setup(&$parser) {
45 - $parser->setFunctionHook('notificator', 'Notificator::notificator_Render');
 44+function notificator_Setup( &$parser ) {
 45+ $parser->setFunctionHook( 'notificator', 'Notificator::notificator_Render' );
4646 return true;
4747 }
4848
49 -function notificator_Magic(&$magicWords, $langCode) {
 49+function notificator_Magic( &$magicWords, $langCode ) {
5050 $magicWords['notificator'] = array( 0, 'notificator' );
5151 return true;
5252 }
Index: trunk/extensions/Notificator/SpecialNotificator.php
@@ -1,8 +1,8 @@
22 <?php
33
4 -if (!defined('MEDIAWIKI')) {
 4+if ( !defined( 'MEDIAWIKI' ) ) {
55 echo "Not a valid entry point";
6 - exit(1);
 6+ exit( 1 );
77 }
88
99 class SpecialNotificator extends SpecialPage {
@@ -11,63 +11,73 @@
1212 parent::__construct( 'Notificator' );
1313 }
1414
15 -function execute($par) {
 15+function execute( $par ) {
1616 global $wgRequest, $wgOut, $wgUser;
1717
1818 $this->setHeaders();
1919
2020 # Get request data from, e.g.
21 - $pageId = $wgRequest->getText('pageId');
22 - $revId = $wgRequest->getText('revId');
23 - $receiver = $wgRequest->getText('receiver');
 21+ $pageId = $wgRequest->getText( 'pageId' );
 22+ $revId = $wgRequest->getText( 'revId' );
 23+ $receiver = $wgRequest->getText( 'receiver' );
2424
25 - if(! $pageId || ! $revId || ! $receiver ) {
26 - $output = '<span class="error">' . wfMsg('special-page-accessed-directly') . '</span>';
 25+ if ( ! $pageId || ! $revId || ! $receiver ) {
 26+ $output = '<span class="error">' . wfMsg( 'special-page-accessed-directly' ) . '</span>';
2727 } else {
28 - $titleObj = Title::newFromID($pageId);
 28+ $titleObj = Title::newFromID( $pageId );
2929 $pageTitle = $titleObj->getFullText();
3030 $linkToPage = $titleObj->getFullURL();
3131
32 - if(! Sanitizer::validateEmail($receiver)) {
33 - $output = '<span class="error">' . wfMsg('e-mail-address-invalid') . ' ' . wfMsg('notification-not-sent') . '</span>';
34 - $output .= Notificator::getReturnToText($linkToPage, $pageTitle);
35 - $wgOut->addHTML($output);
 32+ if ( ! Notificator::checkEmailAddress( $receiver ) ) {
 33+ $output = '<span class="error">' . wfMsg( 'e-mail-address-invalid' ) . ' ' .
 34+ wfMsg( 'notification-not-sent' ) . '</span>';
 35+ $output .= Notificator::getReturnToText( $linkToPage, $pageTitle );
 36+ $wgOut->addHTML( $output );
3637 return;
3738 }
3839
39 - $oldRevId = Notificator::getLastNotifiedRevId($pageId, $revId, $receiver);
 40+ $oldRevId = Notificator::getLastNotifiedRevId( $pageId, $revId, $receiver );
4041
41 - if($oldRevId >= 0) {
42 - if($oldRevId > 0) {
 42+ if ( $oldRevId >= 0 ) {
 43+ if ( $oldRevId > 0 ) {
4344 // Receiver has been notified before - send the diff to the last notified revision
44 - $mailSubjectPrefix = '[' . wfMsg('change-tag') . '] ';
 45+ $mailSubjectPrefix = '[' . wfMsg( 'change-tag' ) . '] ';
4546
46 - $wgOut->addModules('mediawiki.legacy.diff');
47 - $diff = Notificator::getNotificationDiffHtml($oldRevId, $revId);
48 - $notificationText = wfMsg('notification-text-changes', htmlspecialchars($wgUser->getName()), '<a href="' . $linkToPage . '">' . $pageTitle . '</a>') . '<div style="margin-top: 1em;">' . $diff . '</div>';
 47+ $wgOut->addModules( 'mediawiki.legacy.diff' );
 48+ $diff = Notificator::getNotificationDiffHtml( $oldRevId, $revId );
 49+ $notificationText = wfMsg( 'notification-text-changes',
 50+ htmlspecialchars( $wgUser->getName() ), '<a href="' . $linkToPage . '">' .
 51+ $pageTitle . '</a>' ) . '<div style="margin-top: 1em;">' . $diff . '</div>';
4952 } else {
5053 // Receiver has never been notified about this page - so don't send a diff, just the link
51 - $mailSubjectPrefix = '[' . wfMsg('new-tag') . '] ';
52 - $notificationText = wfMsg('notification-text-new', htmlspecialchars($wgUser->getName()), '<a href="' . $linkToPage . '">' . $pageTitle . '</a>');
 54+ $mailSubjectPrefix = '[' . wfMsg( 'new-tag' ) . '] ';
 55+ $notificationText = wfMsg( 'notification-text-new',
 56+ htmlspecialchars( $wgUser->getName() ), '<a href="' . $linkToPage . '">' .
 57+ $pageTitle . '</a>' );
5358 }
54 - $mailSubject = htmlspecialchars($mailSubjectPrefix . $pageTitle);
 59+ $mailSubject = htmlspecialchars( $mailSubjectPrefix . $pageTitle );
5560
56 - if (Notificator::sendNotificationMail($receiver, $mailSubject, $notificationText)) {
57 - $output = '<strong>' . wfMsg('following-e-mail-sent-to', htmlspecialchars($receiver)) . '</strong><div style="margin-top: 1em;"><h3>' . wfMsg('subject') . ' ' . $mailSubject . '</h3><p>' . $notificationText . '</p></div>';
58 - Notificator::recordNotificationInDatabase($pageId, $revId, $receiver);
 61+ if ( Notificator::sendNotificationMail( $receiver, $mailSubject, $notificationText ) ) {
 62+ $output = '<strong>' . wfMsg( 'following-e-mail-sent-to',
 63+ htmlspecialchars( $receiver ) ) . '</strong><div style="margin-top: 1em;"><h3>' .
 64+ wfMsg( 'subject' ) . ' ' . $mailSubject . '</h3><p>' . $notificationText .
 65+ '</p></div>';
 66+ Notificator::recordNotificationInDatabase( $pageId, $revId, $receiver );
5967 } else {
60 - $output = '<span class="error">' . wfMsg('error-sending-e-mail', htmlspecialchars($receiver)) . '</span>';
 68+ $output = '<span class="error">' . wfMsg( 'error-sending-e-mail',
 69+ htmlspecialchars( $receiver ) ) . '</span>';
6170 }
62 - } elseif($oldRevId == -1) {
63 - $output = '<span class="error">' . wfMsg('error-parameter-missing') . '</span>';
64 - } elseif($oldRevId == -2) {
65 - $output = '<strong>' . wfMsg('notified-already', htmlspecialchars($receiver)) . ' ' . wfMsg('notification-not-sent') . '</strong>';
 71+ } elseif ( $oldRevId == -1 ) {
 72+ $output = '<span class="error">' . wfMsg( 'error-parameter-missing' ) . '</span>';
 73+ } elseif ( $oldRevId == -2 ) {
 74+ $output = '<strong>' . wfMsg( 'notified-already', htmlspecialchars( $receiver ) ) .
 75+ ' ' . wfMsg( 'notification-not-sent' ) . '</strong>';
6676 }
6777
68 - $output .= Notificator::getReturnToText($linkToPage, $pageTitle);
 78+ $output .= Notificator::getReturnToText( $linkToPage, $pageTitle );
6979 }
7080
71 - $wgOut->addHTML($output);
 81+ $wgOut->addHTML( $output );
7282 }
7383
7484 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r90507Dumped own checkEmailAddress() function again, now using User::isValidEmailAd...nagelp02:47, 21 June 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r89637Initial commit of new extension Notificatornagelp09:20, 7 June 2011

Comments

#Comment by Nikerabbit (talk | contribs)   10:40, 17 August 2011

Please don't mix style and other code changes in the future.

#Comment by Patrick Nagel (talk | contribs)   11:11, 17 August 2011

Agreed, that was a bad decision.

Status & tagging log