From: Brion Vibber
Date: Sat, 18 Dec 2004 03:47:11 +0000 (+0000)
Subject: (bug 454) Merge e-notif 2.00
X-Git-Tag: 1.5.0alpha1~1090
X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=798270581d38271fa87b2744fa157f77f2d2db80;p=lhc%2Fweb%2Fwiklou.git
(bug 454) Merge e-notif 2.00
From http://bugzilla.wikipedia.org/attachment.cgi?id=171&action=view
and extra files from http://www.tgries.de/mw/cvs15+enea200-minus-cvs.tgz
Undid a couple minor bits like the broken changing of minoreditletter.
Have not yet made general corrections/reworkings. Since this changes
the user and watchlist tables, you must run the updaters (installer or
update.php) on an existing database.
---
diff --git a/README b/README
index 73056dd093..33aa184e70 100644
--- a/README
+++ b/README
@@ -59,6 +59,10 @@ Documentation and discussion on new features may be found at:
http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide
http://meta.wikipedia.org/wiki/MediaWiki_development
+Documentation about the E-Mail notification can be found on:
+
+ http://meta.wikipedia.org/Enotif
+
If you are setting up your own wiki based on this software, it is highly
recommended that you subscribe to mediawiki-l:
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index ab17213a63..d41040b27f 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -3,6 +3,111 @@
Security reminder: MediaWiki does not require PHP's register_globals
setting since version 1.2.0. If you have it on, turn it *off* if you can.
+== Version Enotif+Eauthent EN+EA v2.00/CVS, 14.12.2004 ==
+written by Thomas Gries, Berlin and Markus Arndt, Munich
+
+Executive summary for the impatient reader:
+
+Enotif adds e-mail notification to MediaWiki and sends e-mails
+to watching users when a watch-listed page or user_talk page is changed
+http://bugzilla.wikipedia.org/show_bug.cgi?id=454
+Visit the complete documentation on http://meta.wikipedia.org/Enotif
+
+Eauthent is a mechanism to use a temporary one-time password cycle
+to check whether the email address a user has entered is a valid one.
+http://bugzilla.wikipedia.org/show_bug.cgi?id=866
+Visit the complete documentation on http://meta.wikipedia.org/Eauthent
+
+The current patch has only been checked for (see DefaultSettings.php):
+
+- php mail()
+ ( = not using PEAR:Mail() module --- I do not know anyone who uses that)
+ $wgSMTP = false;
+- MySQL database
+ ( = not using PostgreSQL --- I do not know anyone who uses that)
+ $wgDBtype = "mysql";
+ $wgSearchType = "MyISAM";
+
+- STILL TODO:
+ NEW (newpageletter) and CORR (minoreditletter) markers needs
+ corresponding "spacers"
+
+- table user_newtalk dropped; changes on usertalk pages and their
+ notifications are now fully handled via existing table watchlist
+ The user interface and behavious is unchanged to previous version.
+- updaters.inc for compatibility with older mediawiki tables:
+ the conversion script converts existing user_newtalk entries
+ watchlist table entries
+ (user_newtalk) id ==> (watchlist) NS_USER_TALK:namefromId(id) timestamp=1
+- minor bug fixes:
+ updated marker now correctly shown on watchlist page
+ watching users number display with enhanced RC view + RCUseModStyle
+- wfUrlencode() instead of rawurlencode() in enotif mails
+- duplicate enotif code moved from UserTalkUpdate.php and
+ merged into UserMailer.php and using usermailer() solely
+- fixed an enotif mail text error for user names with spaces
+- fixed missing part for suppressing watching user number
+
+v1.36:
+magic watchlist shows and counts now only the content page, notwithstanding
+the content and talk page are stored separately in watchlist.
+* bug fixed: rawurlencode for pagetitles in enotif mails
+* bug fixed: link to userpages of anonymous user are correct now
+
+* Enotif v1.34
+ bugs fixed regarding missing $oldid parameter
+
+* v1.33
+* Details:
+ Implements almost all enotif options as user preferences.
+ These are only shown on the user preference page, if they are globally
+ enabled by the corresponding admin option in DefaultSettings.php.
+ Added admin feature to let enotifs appear to come from the page editor.
+ This facilitates automatic mail sorting and anti-spam filtering; feature was
+ originally proposed by Nick Triantos, thank you !
+ Page editor's email address is however only shown, if this user enabled
+ the option "reveal my email address" in user preferences. Otherwise,
+ the enotifs appear to come from WikiAdmin as usual (tricky to program,
+ but simply trust the algorithm. or look into UserMailer.php and
+ UserTalkPage.php).
+
+* Changes from previous enotif versions
+* v1.31 is an improved version with many security and also cosmetic changes
+ applied after two first reviews by Brion Vibber. v1.31 is basically the same as
+ the older Enotif v1.30 and v1.22 versions.
+
+ Added UseMod style for recent changes view so that only the most recent
+ change of any page is listed. The (diff) and (hist) still allow to retrieve the
+ older versions at users' discretion, but the RC view is much cleaner for
+ trusted environments such as medium-size companies or family wikis.
+
+* Enotif v1.30 redesign after review by Brion Vibber 25.10.2003
+
+* v1.22 "updated (since my last visit)" also shown for users without stored
+ email address in preferences, so that they can see, what watched pages
+ have changed.
+* show "updated (since my last visit)" markers in RC, history and watchlist
+* Systemvariables to suppress updated marker in all views
+* show number of watching users in RC and on bottom of articles in
+ classic skin and in monobook skin
+* Systemvariables in DefaultSettings.php to enable or disable features
+* v1.21 now suppresses displaying the marker "updated (since my last visit)"
+ in recent changes view for the older (already visited) versions of watched
+ pages - i.e. page versions before the enotif was sent do not bear that
+ marker any longer.
+* enotif mails come with a link to the diff view between current and last
+ visited version of the watching user.
+*database structure is changed automatically when installing via the
+ recommended way (starting index.php and re-using the old database name).
+ run php /maintenance/update.php
+ OR see /maintenance/archives/patch-email-notification.sql and apply the
+ command
+ ALTER TABLE watchlist
+ ADD (wl_notificationtimestamp varchar(14) binary NOT NULL default '0');
+ manually to your database, which does not harm the non notification versions
+
+*adding a page x to the watchlist does automatically add a watch
+ for the accompanying talk_page talk:x and vice versa;
== MediaWiki 1.4 BETA ==
diff --git a/config/index.php b/config/index.php
index c5c65c5276..efed31fa6c 100644
--- a/config/index.php
+++ b/config/index.php
@@ -80,7 +80,7 @@ header( "Content-type: text/html; charset=utf-8" );
MediaWiki is
Copyright (C) 2001-2004 by Magnus Manske, Brion Vibber, Lee Daniel Crocker,
- Tim Starling, Erik Möller, Gabriel Wicke and others.
+ Tim Starling, Erik Möller, Gabriel Wicke, Thomas Gries and others.
@@ -387,6 +387,12 @@ if ( $conf->Shm == 'memcached' && $conf->MCServers ) {
$errs["MCServers"] = "Please specify at least one server if you wish to use memcached";
}
+/* default values for installation */
+$conf->Email =importRequest("Email", "email_enabled");
+$conf->Emailuser=importRequest("Emailuser", "emailuser_enabled");
+$conf->Enotif =importRequest("Enotif", "enotif_allpages");
+$conf->Eauthent =importRequest("Eauthent", "eauthent_enabled");
+
if( $conf->posted && ( 0 == count( $errs ) ) ) {
do { /* So we can 'continue' to end prematurely */
$conf->Root = ($conf->RootPW != "");
@@ -636,7 +642,8 @@ if( count( $errs ) ) {
This will be used as the return address for password reminders and
may be displayed in some error conditions so visitors can get in
- touch with you.
+ touch with you. It is also be used as the default sender address of e-mail
+ notifications (enotifs).
@@ -733,6 +740,87 @@ if( count( $errs ) ) {
use Turck shared memory if the wiki will be running on a single Apache server.
+
E-mail, e-mail notification and authentification setup
+
+
+
+
+
Select one:
+
+
+
+
+
+
+
+ Use this to disable all e-mail functions (send a password reminder, user-to-user e-mail and e-mail notification),
+ if sending e-mails on your server doesn't work.
+
+
+
+
Select one:
+
+
+
+
+
+
+
+ Use this to disable only the user-to-user e-mail function (EmailUser).
+
+
+
+
Select one:
+
+
+
+
+
+
+
+
+
E-mail notification";
+ ?>
+ sends a notification e-mail to a user, when the user_talk page is changed
+ and/or when watch-listed pages are changed, depending on the above settings.
+ When testing this feature, be reminded, that obviously an e-mail address must be present in your preferences
+ and that your own changes never trigger notifications to be sent to yourself.
+
+
Users get corresponding options to select or deselect in their users' preferences.
+ The user options are not shown on the preference page, if e-mail notification is disabled.
+
+
There are additional options for fine tuning in /includes/DefaultSettings.php .
+
+
+
+
+
Select one:
+
+
+
+
+
+
+
+
E-mail address authentication";
+ ?>
+ uses a scheme to authenticate e-mail addresses of the users. The user who initially enters or who changes his/her stored e-mail address
+ gets a one-time temporary password mailed to that address. The user can use the original password as long as wanted, however, the stored e-mail address
+ is only authenticated at the moment when the user logs in with the one-time temporary password.
+
+
The e-mail address stays authenticated as long as the user does not change it; the time of authentication is indicated
+ on the user preference page.
+
+
If the option is enabled, only authenticated e-mail addresses can receive EmailUser mails and/or
+ e-mail notification mails.
+
+
+
+
Database config
@@ -853,6 +941,30 @@ function writeLocalSettings( $conf ) {
$turck = '#';
}
+ if ( $conf->Email == 'email_enabled' ) {
+ $enableemail = 'true';
+ $enableuseremail = ( $conf->Emailuser == 'emailuser_enabled' ) ? 'true' : 'false' ;
+ $eauthent = ( $conf->Eauthent == 'eauthent_enabled' ) ? 'true' : 'false' ;
+ switch ( $conf->Enotif ) {
+ case 'enotif_usertalk':
+ $enotifusertalk = 'true';
+ $enotifwatchlist = 'false';
+ break;
+ case 'enotif_allpages':
+ $enotifusertalk = 'true';
+ $enotifwatchlist = 'true';
+ break;
+ default:
+ $enotifusertalk = 'false';
+ $enotifwatchlist = 'false';
+ }
+ } else {
+ $enableuseremail = 'false';
+ $enableemail = 'false';
+ $eauthent = 'false';
+ $enotifusertalk = 'false';
+ $enotifwatchlist = 'false';
+ }
$file = @fopen( "/dev/urandom", "r" );
if ( $file ) {
@@ -912,9 +1024,21 @@ if ( \$wgCommandLineMode ) {
\$wgUploadPath = \"\$wgScriptPath/images\";
\$wgUploadDirectory = \"\$IP/images\";
+\$wgEnableEmail = $enableemail;
+\$wgEnableUserEmail = $enableuseremail;
+
\$wgEmergencyContact = \"{$slconf['EmergencyContact']}\";
\$wgPasswordSender = \"{$slconf['PasswordSender']}\";
+## For a detailed description of the following switches see
+## http://meta.wikimedia.org/Enotif and http://meta.wikimedia.org/Eauthent
+## There are many more options for fine tuning available see
+## /includes/DefaultSettings.php
+## UPO means: this is also a user preference option
+\$wgEmailNotificationForUserTalkPages = $enotifusertalk; # UPO
+\$wgEmailNotificationForWatchlistPages = $enotifwatchlist; # UPO
+\$wgEmailAuthentication = $eauthent;
+
\$wgDBserver = \"{$slconf['DBserver']}\";
\$wgDBname = \"{$slconf['DBname']}\";
\$wgDBuser = \"{$slconf['DBuser']}\";
diff --git a/includes/Article.php b/includes/Article.php
index d6f71c523d..870238220c 100644
--- a/includes/Article.php
+++ b/includes/Article.php
@@ -681,6 +681,7 @@ class Article {
function view() {
global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgLang;
global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol;
+ global $wgEnotif;
$sk = $wgUser->getSkin();
$fname = 'Article::view';
@@ -806,6 +807,10 @@ class Article {
$this->viewUpdates();
wfProfileOut( $fname );
+
+ include_once( "UserMailer.php" );
+ $wgEnotif = new EmailNotification ();
+ $wgEnotif->Clear( $wgUser->getID(), $this->mTitle->getDBkey(), $this->mTitle->getNamespace() );
}
/**
@@ -878,9 +883,10 @@ class Article {
array( 'cur_namespace' => $talkns, 'cur_title' => $ttl ), $fname );
# standard deferred updates
- $this->editUpdates( $text );
+ $this->editUpdates( $text, $summary, $isminor, $now );
- $this->showArticle( $text, wfMsg( 'newarticle' ) );
+ $oldid = 0; # new article
+ $this->showArticle( $text, wfMsg( 'newarticle' ), false, $isminor, $now, $summary, $oldid );
}
@@ -1094,7 +1100,7 @@ class Article {
}
}
# standard deferred updates
- $this->editUpdates( $text );
+ $this->editUpdates( $text, $summary, $minor, $now );
$urls = array();
@@ -1117,7 +1123,7 @@ class Article {
$u->doUpdate();
}
- $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor );
+ $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor, $me2, $now, $summary, $oldid );
}
return $good;
}
@@ -1126,8 +1132,8 @@ class Article {
* After we've either updated or inserted the article, update
* the link tables and redirect to the new page.
*/
- function showArticle( $text, $subtitle , $sectionanchor = '' ) {
- global $wgOut, $wgUser, $wgLinkCache;
+ function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid ) {
+ global $wgOut, $wgUser, $wgLinkCache, $wgEnotif;
$wgLinkCache = new LinkCache();
# Select for update
@@ -1149,6 +1155,13 @@ class Article {
else
$r = '';
$wgOut->redirect( $this->mTitle->getFullURL( $r ).$sectionanchor );
+
+ # this call would better fit into RecentChange::notifyEdit and RecentChange::notifyNew .
+ # this will be improved later (to-do)
+
+ include_once( "UserMailer.php" );
+ $wgEnotif = new EmailNotification ();
+ $wgEnotif->NotifyOnPageChange( $wgUser->getID(), $this->mTitle->getDBkey(), $this->mTitle->getNamespace(),$now, $summary, $me2, $oldid );
}
/**
@@ -1857,12 +1870,10 @@ class Article {
# talk page
global $wgUser;
-
if ($this->mTitle->getNamespace() == NS_USER_TALK &&
- $this->mTitle->getText() == $wgUser->getName())
- {
- $wgUser->setNewtalk(0);
- $wgUser->saveNewtalk();
+ $this->mTitle->getText() == $wgUser->getName()) {
+ require_once( 'UserTalkUpdate.php' );
+ $u = new UserTalkUpdate( 0, $this->mTitle->getNamespace(), $this->mTitle->getDBkey(), false, false, false );
}
}
@@ -1872,7 +1883,7 @@ class Article {
* @private
* @param string $text
*/
- function editUpdates( $text ) {
+ function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange) {
global $wgDeferredUpdateList, $wgDBname, $wgMemc;
global $wgMessageCache, $wgUser;
@@ -1897,15 +1908,13 @@ class Article {
$u = new SearchUpdate( $id, $title, $text );
array_push( $wgDeferredUpdateList, $u );
- # If this is another user's talk page, save a
- # newtalk notification for them
+ # If this is another user's talk page,
+ # create a watchlist entry for this page
if ($this->mTitle->getNamespace() == NS_USER_TALK &&
- $shortTitle != $wgUser->getName())
- {
- $other = User::newFromName($shortTitle);
- $other->setNewtalk(1);
- $other->saveNewtalk();
+ $shortTitle != $wgUser->getName()) {
+ require_once( 'UserTalkUpdate.php' );
+ $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle, $summary, $minoredit, $timestamp_of_pagechange);
}
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
index 96575d730d..96a91d492c 100644
--- a/includes/ChangesList.php
+++ b/includes/ChangesList.php
@@ -79,6 +79,10 @@ class ChangesList {
if ( $rcObj->watched ) $link = ''.$link.'' ;
$r .= $link ;
+ if ($rcObj->notificationtimestamp) {
+ $r .= wfMsg( 'updatedmarker' );
+ }
+
# Diff
$r .= ' (' ;
$r .= $rcObj->difflink ;
@@ -97,6 +101,10 @@ class ChangesList {
$r .= $wgContLang->emphasize( ' ('.$rc_comment.')' );
}
+ if ($rcObj->numberofWatchingusers > 0) {
+ $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rcObj->numberofWatchingusers));
+ }
+
$r .= " \n" ;
return $r ;
}
@@ -158,9 +166,9 @@ class ChangesList {
else $r .= ' ' ;
$r .= ' ' ; # Minor
if ( $unpatrolled ) {
- $r .= "!";
+ $r .= '!';
} else {
- $r .= " ";
+ $r .= ' ';
}
# Timestamp
@@ -172,6 +180,10 @@ class ChangesList {
if ( $block[0]->watched ) $link = ''.$link.'' ;
$r .= $link ;
+ if ($block[0]->notificationtimestamp) {
+ $r .= wfMsg( 'updatedmarker' );
+ }
+
$curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
# Changes
@@ -187,6 +199,10 @@ class ChangesList {
}
$r .= $users ;
+
+ if ($block[0]->numberofWatchingusers > 0) {
+ $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($block[0]->numberofWatchingusers));
+ }
$r .= " \n" ;
# Sub-entries
@@ -210,9 +226,9 @@ class ChangesList {
}
if ( $rcObj->unpatrolled ) {
- $r .= "!";
+ $r .= '!';
} else {
- $r .= " ";
+ $r .= ' ';
}
$r .= ' ' ;
@@ -271,7 +287,7 @@ class ChangesList {
* Either returns the line, or caches it for later use
*/
function recentChangesLine( &$rc, $watched = false ) {
- global $wgUser ;
+ global $wgUser;
$usenew = $wgUser->getOption( 'usenewrc' );
if ( $usenew )
$line = $this->recentChangesLineNew ( $rc, $watched ) ;
@@ -280,6 +296,7 @@ class ChangesList {
return $line ;
}
+
function recentChangesLineOld( &$rc, $watched = false ) {
$fname = 'Skin::recentChangesLineOld';
wfProfileIn( $fname );
@@ -350,9 +367,9 @@ class ChangesList {
$s .= ') . . ';
# M, N and ! (minor, new and unpatrolled)
- if ( $rc_minor ) { $s .= ' '.$message["minoreditletter"].''; }
- if ( $rc_type == RC_NEW ) { $s .= ''.$message["newpageletter"].''; }
- if ( $unpatrolled ) { $s .= ' !'; }
+ if ( $rc_minor ) { $s .= ' '.$message["minoreditletter"].''; }
+ if ( $rc_type == RC_NEW ) { $s .= ''.$message["newpageletter"].''; }
+ if ( !$rc_patrolled ) { $s .= ' !'; }
# Article link
# If it's a new article, there is no diff link, but if it hasn't been
@@ -365,6 +382,11 @@ class ChangesList {
if ( $watched ) {
$articleLink = ''.$articleLink.'';
}
+
+ if ($rc->notificationtimestamp) {
+ $articleLink .= wfMsg( 'updatedmarker' );
+ }
+
$s .= ' '.$articleLink;
wfProfileOut("$fname-page");
}
@@ -412,6 +434,11 @@ class ChangesList {
$rc_comment = $this->skin->formatComment($rc_comment,$rc->getTitle());
$s .= $wgContLang->emphasize(' (' . $rc_comment . ')');
}
+
+ if ($rc->numberofWatchingusers > 0) {
+ $s .= ' ' . wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rc->numberofWatchingusers));
+ }
+
$s .= "\n";
wfProfileOut( "$fname-rest" );
@@ -477,6 +504,8 @@ class ChangesList {
$rc->watched = $watched ;
$rc->link = $clink ;
$rc->timestamp = $time;
+ $rc->notificationtimestamp = $baseRC->notificationtimestamp;
+ $rc->numberofWatchingusers = $baseRC->numberofWatchingusers;
# Make "cur" and "diff" links
$titleObj = $rc->getTitle();
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 79e6a6ff8b..2e0b48502c 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -164,6 +164,14 @@ $wgEmergencyContact = 'wikiadmin@' . $wgServerName;
*/
$wgPasswordSender = 'Wikipedia Mail ';
+/**
+ * dummy address which should be accepted during mail send action
+ * It might be necessay to adapt the address or to set it equal
+ * to the $wgEmergencyContact address
+ */
+#$wgNoReplyAddress = $wgEmergencyContact;
+$wgNoReplyAddress = 'reply@not.possible';
+
/**
* Set to true to enable the e-mail basic features:
* Password reminders, etc. If sending e-mail on your
@@ -495,9 +503,63 @@ $wgFileCacheDirectory = "{$wgUploadDirectory}/cache";
# Requires zlib support enabled in PHP.
$wgUseGzip = false;
+/* T. Gries Aug.-Nov.2004
-$wgCookieExpiration = 2592000;
+ THESE ARE MY SUGGESTED FIRST TEST global admin options FOR ENOTIF.
+ Attention: the defaults might differ from standard media wiki distributions.
+
+ However, I suggest to start with these which allow to evaluate almost all new features quickly.
+ user preferences default options SEE AS USUAL /languages/Language.php
+*/
+
+########################### CAUTION ################# ATTENTION ###############################################
+#
+# T. Gries Aug.-Dec. 2004
+#
+# SECTION FOR DEVELOPERS and SERVER ADMINS
+#
+# HERE COME TWO OPTIONS, WHICH ALLOW ACOUSTIC SIGNALS on the server beeper WHEN AN EMAIL IS ACTUALLY SENT OUT.
+# YOU MIGHT WISH TO ENABLE THESE, BUT BE CAREFUL, AS A system() CALL IS PERFORMED using the shown parameters.
+# I FIND IT VERY USEFUL, but this is a very personal comment. T. Gries
+#
+# The system speaker beeps when the wiki actually sends out a notification mail (safe default = disabled).
+#
+# The following string is passed as parameter to a system() call in UserMailer.php
+# The system() calls call - in the shown example - the beep 1.2.2 program (LINUX) with frequency f [Hz] and length l [msec]
+#
+# Beep 1.2.2 can be found on http://freshmeat.net/projects/beep/ and I like it.
+#
+########################### SAFE #################### SAFE #####################################################
+$wgEmailNotificationSystembeep = ''; # empty string disables this feature; this appears to be safe
+######ENTER#AT#YOUR#OWN#RISK###CAUTION###### ATTENTION ###################################################
+#$wgEmailNotificationSystembeep = '/usr/bin/beep -f 4000 -l 20 &'; # a system() call with exactly this string as parameter is executed when such a mail is sent
+########################### CAUTION ################# ATTENTION ###############################################
+
+# For email notification on page changes T.Gries/M.Arndt 01.11.2004
+$wgPasswordSender = $wgEmergencyContact;
+$wgEmailNotificationMailsSentFromPageEditor = false; # false: Enotif mails appear to come from $wgEmergencyContact
+# # true: from PageEditor if s/he opted-in
+
+# If set to true, users get a corresponding option in their preferences and can choose to enable or disable at their discretion
+# If set to false, the corresponding input form on the user preference page is suppressed
+# It call this to be a "user-preferences-option (UPO)"
+$wgEmailAuthentication = true; # UPO (if this is set to false, texts referring to authentication are suppressed)
+$wgEmailNotificationForWatchlistPages = true; # UPO
+$wgEmailNotificationForUserTalkPages = true; # UPO
+$wgEmailNotificationRevealPageEditorAddress = true; # UPO; reply-to address may be filled with page editor's address (if user allowed this in the preferences)
+$wgEmailNotificationForMinorEdits = true; # UPO; false: "minor edits" on pages do not trigger notification mails.
+# # Attention: _every_ change on a user_talk page trigger a notification mail (if the user is not yet notified)
+
+# Show recent changes in UseMod style, i.e. only the recent change of a page is listed
+$wgRCUseModStyle = true; # UPO
+# Show watching users in recent changes, watchlist and page history views
+$wgRCShowWatchingUsers = true; # UPO
+# Show watching users in Page views
+$wgPageShowWatchingUsers = true;
+# Show "Updated (since my last visit)" marker in RC view, watchlist and history view for watched pages with new changes
+$wgShowUpdatedMarker = true; # UPO
+$wgCookieExpiration = 2592000;
# Squid-related settings
#
@@ -743,10 +805,10 @@ $wgDefaultSkin = 'monobook';
$wgDefaultUserOptions = array();
# Whether or not to allow real name fields. Defaults to true.
+# If set to false, the corresponding input forms on the log-in page and on the user preference page is suppressed.
$wgAllowRealName = true;
# Use XML parser?
-
$wgUseXMLparser = false ;
# Extensions
diff --git a/includes/PageHistory.php b/includes/PageHistory.php
index f229792d3c..754a2d1d4e 100644
--- a/includes/PageHistory.php
+++ b/includes/PageHistory.php
@@ -22,7 +22,7 @@ class PageHistory {
# This shares a lot of issues (and code) with Recent Changes
function history() {
- global $wgUser, $wgOut, $wgLang;
+ global $wgUser, $wgOut, $wgLang, $wgShowUpdatedMarker;
# If page hasn't changed, client can cache this
@@ -59,8 +59,17 @@ class PageHistory {
$namespace = $this->mTitle->getNamespace();
$title = $this->mTitle->getText();
-
+ $uid = $wgUser->getID();
$db =& wfGetDB( DB_SLAVE );
+ if ($wgShowUpdatedMarker && $wgUser->getOption( 'showupdated' )) {
+ $dbr =& wfGetDB( DB_MASTER );
+ $row = $dbr->selectRow( 'watchlist',
+ array( 'wl_notificationtimestamp' ),
+ array( 'wl_namespace' => $namespace, 'wl_title' => $this->mTitle->getDBkey(), 'wl_user' => $wgUser->getID() ),
+ $fname );
+ $notificationtimestamp = $row->wl_notificationtimestamp;
+ } else $notificationtimestamp = false ;
+
$use_index = $db->useIndexClause( 'name_title_timestamp' );
$oldtable = $db->tableName( 'old' );
@@ -103,7 +112,8 @@ class PageHistory {
$this->mArticle->getUserText(), $namespace,
$title, 0, $this->mArticle->getComment(),
( $this->mArticle->getMinorEdit() > 0 ),
- $counter++
+ $counter++,
+ $notificationtimestamp
);
}
while ( $line = $db->fetchObject( $res ) ) {
@@ -112,7 +122,8 @@ class PageHistory {
$line->old_user_text, $namespace,
$title, $line->old_id,
$line->old_comment, ( $line->old_minor_edit > 0 ),
- $counter++
+ $counter++,
+ $notificationtimestamp
);
}
$s .= $this->endHistoryList( !$atend );
@@ -143,7 +154,7 @@ class PageHistory {
return $s;
}
- function historyLine( $ts, $u, $ut, $ns, $ttl, $oid, $c, $isminor, $counter = '' ) {
+ function historyLine( $ts, $u, $ut, $ns, $ttl, $oid, $c, $isminor, $counter = '', $notificationtimestamp = false ) {
global $wgLang, $wgContLang;
static $message;
@@ -206,6 +217,9 @@ class PageHistory {
$c = $this->mSkin->formatcomment( $c, $this->mTitle );
$s .= " ($c)";
}
+ if ($notificationtimestamp && ($ts >= $notificationtimestamp)) {
+ $s .= wfMsg( 'updatedmarker' );
+ }
$s .= '';
$this->lastline = $s;
diff --git a/includes/RecentChange.php b/includes/RecentChange.php
index 248cb2fa22..f64191dc76 100644
--- a/includes/RecentChange.php
+++ b/includes/RecentChange.php
@@ -40,6 +40,10 @@ define( 'RC_MOVE_OVER_REDIRECT', 4);
* lastTimestamp timestamp of previous entry, used in WHERE clause during update
* lang the interwiki prefix, automatically set in save()
*
+ * temporary: not stored in the database
+ * notificationtimestamp
+ * numberofWatchingusers
+ *
* @todo document functions and variables
* @package MediaWiki
*/
@@ -61,6 +65,8 @@ class RecentChange
{
$rc = new RecentChange;
$rc->loadFromCurRow( $row );
+ $rc->notificationtimestamp = false;
+ $rc->numberofWatchingusers = false;
return $rc;
}
diff --git a/includes/Setup.php b/includes/Setup.php
index d9d3ca2303..0f55446313 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -80,8 +80,6 @@ require_once( 'HistoryBlob.php' );
$wgRequest = new WebRequest();
-
-
wfProfileOut( $fname.'-includes' );
wfProfileIn( $fname.'-misc1' );
global $wgUser, $wgLang, $wgContLang, $wgOut, $wgTitle;
diff --git a/includes/Skin.php b/includes/Skin.php
index 4978cdbe38..ebb3018a1b 100644
--- a/includes/Skin.php
+++ b/includes/Skin.php
@@ -797,8 +797,8 @@ class Skin {
}
function pageStats() {
- global $wgOut, $wgLang, $wgArticle, $wgRequest;
- global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
+ global $wgOut, $wgLang, $wgArticle, $wgRequest, $wgUser;
+ global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax, $wgTitle, $wgPageShowWatchingUsers;
extract( $wgRequest->getValues( 'oldid', 'diff' ) );
if ( ! $wgOut->isArticle() ) { return ''; }
@@ -820,6 +820,17 @@ class Skin {
$s .= $this->lastModified();
}
+ if ($wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ extract( $dbr->tableNames( 'watchlist' ) );
+ $sql = "SELECT COUNT(*) AS n FROM $watchlist
+ WHERE wl_title='" . $dbr->strencode($wgTitle->getDBKey()) .
+ "' AND wl_namespace=" . $wgTitle->getNamespace() ;
+ $res = $dbr->query( $sql, 'Skin::pageStats');
+ $x = $dbr->fetchObject( $res );
+ $s .= ' ' . wfMsg('number_of_watching_users_pageview', $x->n );
+ }
+
return $s . ' ' . $this->getCopyright();
}
@@ -1101,7 +1112,10 @@ class Skin {
return $wgEnableEmail &&
$wgEnableUserEmail &&
0 != $wgUser->getID() && # show only to signed in users
- 0 != $id; # can only email non-anons
+ 0 != $id; # we can only email to non-anons ..
+# '' != $id->getEmail() && # who must have an email address stored ..
+# 0 != $id->getEmailauthenticationtimestamp() && # .. which is authenticated
+# 1 != $wgUser->getOption('disablemail'); # and not disabled
}
function emailUserLink() {
@@ -1928,7 +1942,6 @@ class Skin {
return ''.$text.'';
}
-
/**
* This function is called by all recent changes variants, by the page history,
* and by the user contributions list. It is responsible for formatting edit
diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php
index 6298debc66..4577584c06 100644
--- a/includes/SkinTemplate.php
+++ b/includes/SkinTemplate.php
@@ -148,6 +148,7 @@ class SkinTemplate extends Skin {
global $wgMimeType, $wgOutputEncoding, $wgUseDatabaseMessages, $wgRequest;
global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgSiteNotice;
global $wgMaxCredits, $wgShowCreditsIfMax;
+ global $wgPageShowWatchingUsers;
$fname = 'SkinTemplate::outputPage';
wfProfileIn( $fname );
@@ -282,6 +283,25 @@ class SkinTemplate extends Skin {
$tpl->set('viewcount', false);
}
}
+
+ if ($wgPageShowWatchingUsers) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ extract( $dbr->tableNames( 'watchlist' ) );
+ $sql = "SELECT COUNT(*) AS n FROM $watchlist
+ WHERE wl_title='" . $dbr->strencode($wgTitle->getDBKey()) .
+ "' AND wl_namespace=" . $wgTitle->getNamespace() ;
+ $res = $dbr->query( $sql, 'SkinPHPTal::outputPage');
+ $x = $dbr->fetchObject( $res );
+ $numberofwatchingusers = $x->n;
+ if ($numberofwatchingusers > 0) {
+ $tpl->set('numberofwatchingusers', wfMsg('number_of_watching_users_pageview', $numberofwatchingusers));
+ } else {
+ $tpl->set('numberofwatchingusers', false);
+ };
+ } else {
+ $tpl->set('numberofwatchingusers', false);
+ }
+
$tpl->set('lastmod', $this->lastModified());
$tpl->set('copyright',$this->getCopyright());
@@ -316,6 +336,7 @@ class SkinTemplate extends Skin {
$tpl->setRef( 'debug', $out->mDebugtext );
$tpl->set( 'reporttime', $out->reportTime() );
$tpl->set( 'sitenotice', $wgSiteNotice );
+ $tpl->set( 'tagline', wfMsg('tagline') );
$printfooter = "\n";
$out->mBodytext .= $printfooter ;
diff --git a/includes/SpecialEmailuser.php b/includes/SpecialEmailuser.php
index 6006b25810..860d25b7f4 100644
--- a/includes/SpecialEmailuser.php
+++ b/includes/SpecialEmailuser.php
@@ -19,7 +19,7 @@ function wfSpecialEmailuser( $par ) {
}
if ( 0 == $wgUser->getID() ||
- ( false === strpos( $wgUser->getEmail(), "@" ) ) ) {
+ ( !$wgUser->isValidEmailAddr( $wgUser->getEmail() ) ) ) {
$wgOut->errorpage( "mailnologin", "mailnologintext" );
return;
}
@@ -48,8 +48,9 @@ function wfSpecialEmailuser( $par ) {
$address = $nu->getEmail();
- if ( ( false === strpos( $address, "@" ) ) ||
- ( 1 == $nu->getOption( "disablemail" ) ) ) {
+ if ( ( !$nu->isValidEmailAddr( $address ) ) ||
+ ( 1 == $nu->getOption( "disablemail" ) ) ||
+ ( 0 == $nu->getEmailauthenticationtimestamp() ) ) {
$wgOut->errorpage( "noemailtitle", "noemailtext" );
return;
}
diff --git a/includes/SpecialPreferences.php b/includes/SpecialPreferences.php
index 74cc649cc0..bffacf4a88 100644
--- a/includes/SpecialPreferences.php
+++ b/includes/SpecialPreferences.php
@@ -166,6 +166,8 @@ class PreferencesForm {
*/
function savePreferences() {
global $wgUser, $wgLang, $wgOut;
+ global $wgEnableUserEmail, $wgEnableEmail;
+ global $wgEmailAuthentication;
if ( '' != $this->mNewpass ) {
if ( $this->mNewpass != $this->mRetypePass ) {
@@ -179,10 +181,6 @@ class PreferencesForm {
}
$wgUser->setPassword( $this->mNewpass );
}
- global $wgEnableEmail;
- if( $wgEnableEmail ) {
- $wgUser->setEmail( $this->mUserEmail );
- }
$wgUser->setRealName( $this->mRealName );
$wgUser->setOption( 'language', $this->mUserLanguage );
$wgUser->setOption( 'variant', $this->mUserVariant );
@@ -206,7 +204,6 @@ class PreferencesForm {
$wgUser->setOption( "searchNs{$i}", $value );
}
- global $wgEnableUserEmail;
if( $wgEnableEmail && $wgEnableUserEmail ) {
$wgUser->setOption( 'disablemail', $this->mEmailFlag );
}
@@ -216,8 +213,38 @@ class PreferencesForm {
$wgUser->setOption( $tname, $tvalue );
}
$wgUser->setCookies();
+ $wgUser->saveSettings();
+ if( $wgEnableEmail ) {
+ $newadr = strtolower( $this->mUserEmail );
+ $oldadr = strtolower($wgUser->getEmail());
+ if (($newadr <> '') && ($newadr <> $oldadr)) { # the user has supplied a new email address on the login page
+ # prepare for authentication and mail a temporary password to newadr
+ require_once( 'SpecialUserlogin.php' );
+ if ( !$wgUser->isValidEmailAddr( $newadr ) ) {
+ $this->mainPrefsForm( wfMsg( 'invalidemailaddress' ) );
+ return;
+ }
+ $wgUser->mEmail = $newadr; # new behaviour: set this new emailaddr from login-page into user database record
+ $wgUser->mEmailAuthenticationtimestamp = 0; # but flag as "dirty" = unauthenticated
$wgUser->saveSettings();
+ if ($wgEmailAuthentication) {
+ # mail a temporary password to the dirty address
+ # on "save options", this user will be logged-out automatically
+ $error = LoginForm::mailPasswordInternal( $wgUser, true, $dummy );
+ if ($error === '') {
+ return LoginForm::mainLoginForm( wfMsg( 'passwordsentforemailauthentication', $wgUser->getName() ) );
+ } else {
+ return LoginForm::mainLoginForm( wfMsg( 'mailerror', $error ) );
+ }
+ # if user returns, that new email address gets authenticated in checkpassword()
+ }
+ } else {
+ $wgUser->setEmail( strtolower($this->mUserEmail) );
+ $wgUser->setCookies();
+ $wgUser->saveSettings();
+ }
+ }
$wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) );
$po = ParserOptions::newFromUser( $wgUser );
@@ -232,6 +259,7 @@ class PreferencesForm {
$this->mOldpass = $this->mNewpass = $this->mRetypePass = '';
$this->mUserEmail = $wgUser->getEmail();
+ $this->mUserEmailAuthenticationtimestamp = $wgUser->getEmailAuthenticationtimestamp();
$this->mRealName = ($wgAllowRealName) ? $wgUser->getRealName() : '';
$this->mUserLanguage = $wgUser->getOption( 'language' );
if( empty( $this->mUserLanguage ) ) {
@@ -306,7 +334,7 @@ class PreferencesForm {
}
- function getToggle( $tname ) {
+ function getToggle( $tname, $trailer = false) {
global $wgUser, $wgLang;
$this->mUsedToggles[$tname] = true;
@@ -317,8 +345,9 @@ class PreferencesForm {
} else {
$checked = '';
}
+ $trailer =($trailer) ? $trailer : '';
return "\n";
+ . "id=\"$tname\" name=\"wpOp$tname\"$checked />$trailer\n";
}
/**
@@ -328,7 +357,11 @@ class PreferencesForm {
global $wgUser, $wgOut, $wgLang, $wgContLang, $wgUseDynamicDates, $wgValidSkinNames;
global $wgAllowRealName, $wgImageLimits;
global $wgLanguageNames, $wgDisableLangConversion;
+ global $wgEmailNotificationForWatchlistPages, $wgEmailNotificationForUserTalkPages,$wgEmailNotificationForMinorEdits;
+ global $wgRCUseModStyle, $wgRCShowWatchingUsers, $wgEmailNotificationRevealPageEditorAddress;
+ global $wgEnableEmail, $wgEnableUserEmail, $wgEmailAuthentication;
global $wgContLanguageCode;
+
$wgOut->setPageTitle( wfMsg( 'preferences' ) );
$wgOut->setArticleRelated( false );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
@@ -396,21 +429,50 @@ class PreferencesForm {
if ( $this->mEmailFlag ) { $emfc = 'checked="checked"'; }
else { $emfc = ''; }
+ if ($wgEmailAuthentication && ($this->mUserEmail != '') ) {
+ if ($wgUser->getEmailAuthenticationtimestamp() != 0) {
+ $emailauthenticated = wfMsg('emailauthenticated',$wgLang->timeanddate($wgUser->getEmailAuthenticationtimestamp(), true ) ).' ';
+ $disabled = '';
+ } else {
+ $emailauthenticated = wfMsg('emailnotauthenticated').' ';
+ $disabled = ' '.wfMsg('disableduntilauthent');
+ }
+ } else {
+ $emailauthenticated = '';
+ }
+
+ if ($this->mUserEmail == '') {
+ $disabled = ' '.wfMsg('disablednoemail');
+ }
+
$ps = $this->namespacesCheckboxes();
+ $enotifwatchlistpages = ($wgEmailNotificationForWatchlistPages) ? $this->getToggle( 'enotifwatchlistpages', $disabled) : '';
+ $enotifusertalkpages = ($wgEmailNotificationForUserTalkPages) ? $this->getToggle( 'enotifusertalkpages', $disabled) : '';
+ $enotifminoredits = ($wgEmailNotificationForMinorEdits) ? $this->getToggle( 'enotifminoredits', $disabled) : '';
+ $enotifrevealaddr = ($wgEmailNotificationRevealPageEditorAddress) ? $this->getToggle( 'enotifrevealaddr', $disabled) : '';
+ $prefs_help_email_enotif = ( $wgEmailNotificationForWatchlistPages || $wgEmailNotificationForUserTalkPages) ? ' ' . wfMsg('prefs-help-email-enotif') : '';
+ $prefs_help_realname = '';
+
$wgOut->addHTML( "
-