2 rcs_id('$Id: MailNotify.php,v 1.4 2007-01-04 16:47:49 rurban Exp $');
5 * Handle the pagelist pref[notifyPages] logic for users
6 * and notify => hash ( page => (userid => userhash) ) for pages.
7 * Generate notification emails.
9 * We add WikiDB handlers and register ourself there:
10 * onChangePage, onDeletePage, onRenamePage
11 * Administrative actions:
12 * [Watch] WatchPage - add a page, or delete watch handlers into the users
13 * pref[notifyPages] slot.
14 * My WatchList - view or edit list/regex of pref[notifyPages].
15 * EMailConfirm methods: send and verify
20 * ? handle emailed confirmation links (EmailSignup, ModeratedPage)
28 function MailNotify($pagename) {
29 $this->pagename = $pagename; /* which page */
30 $this->emails = array(); /* to whch addresses */
31 $this->userids = array(); /* corresponding array of displayed names,
32 dont display the email addersses */
33 /* from: from which the mail appears to be */
34 $this->from = $this->fromId();
39 return $request->_user->getId() . '@' . $request->get('REMOTE_HOST');
42 function userEmail($userid, $doverify = true) {
44 $u = $request->getUser();
45 if ($u->UserName() == $userid) { // lucky: current user
46 $prefs = $u->getPreferences();
47 $email = $prefs->get('email');
48 // do a dynamic emailVerified check update
49 if ($doverify and !$request->_prefs->get('emailVerified'))
51 } else { // not current user
52 if (ENABLE_USER_NEW) {
53 $u = WikiUser($userid);
57 $u = new WikiUser($request, $userid);
58 $prefs = $u->getPreferences();
60 $email = $prefs->get('email');
61 if ($doverify and !$prefs->get('emailVerified')) {
69 * getPageChangeEmails($notify)
70 * @param $notify: hash ( page => (userid => userhash) )
72 * unique array of ($emails, $userids)
74 function getPageChangeEmails($notify) {
76 $emails = array(); $userids = array();
77 foreach ($notify as $page => $users) {
78 if (glob_match($page, $this->pagename)) {
79 foreach ($users as $userid => $user) {
80 if (!$user) { // handle the case for ModeratePage:
81 // no prefs, just userid's.
82 $emails[] = $this->userEmail($userid, false);
85 if (!empty($user['verified']) and !empty($user['email'])) {
86 $emails[] = $user['email'];
88 } elseif (!empty($user['email'])) {
89 // do a dynamic emailVerified check update
90 $email = $this->userEmail($userid, true);
92 $notify[$page][$userid]['verified'] = 1;
93 $request->_dbi->set('notify', $notify);
98 // ignore verification
101 if (!in_array($user['email'],$emails))
102 $emails[] = $user['email'];
109 $this->emails = array_unique($emails);
110 $this->userids = array_unique($userids);
111 return array($this->emails, $this->userids);
114 function sendMail($subject, $content,
119 $emails = $this->emails;
121 if (!$notice) $notice = _("PageChange Notification of %s");
122 if (mail(array_shift($emails),
123 "[".WIKI_NAME."] ".$subject,
124 $subject."\n".$content,
125 "From: $from\r\nBcc: ".join(',', $emails)
129 trigger_error(sprintf($notice, $this->pagename)
131 . sprintf(_("sent to %s"), join(',',$this->userids)),
135 trigger_error(sprintf($notice, $this->pagename)
137 . sprintf(_("Error: Couldn't send to %s"), join(',',$this->userids)),
144 * Send udiff for a changed page to multiple users.
145 * See rename and remove methods also
147 function sendPageChangeNotification(&$wikitext, $version, &$meta) {
151 if (@is_array($request->_deferredPageChangeNotification)) {
152 // collapse multiple changes (loaddir) into one email
153 $request->_deferredPageChangeNotification[] =
154 array($this->pagename, $this->emails, $this->userids);
157 $backend = &$this->_wikidb->_backend;
158 //$backend = &$request->_dbi->_backend;
159 $subject = _("Page change").' '.urlencode($this->pagename);
160 $previous = $backend->get_previous_version($this->pagename, $version);
161 if (!isset($meta['mtime'])) $meta['mtime'] = time();
163 $difflink = WikiURL($this->pagename, array('action'=>'diff'), true);
164 $dbh = &$request->getDbh();
165 $cache = &$dbh->_wikidb->_cache;
166 //$cache = &$request->_dbi->_cache;
167 $content = explode("\n", $wikitext);
168 $prevdata = $cache->get_versiondata($this->pagename, $previous, true);
169 if (empty($prevdata['%content']))
170 $prevdata = $backend->get_versiondata($this->pagename, $previous, true);
171 $other_content = explode("\n", $prevdata['%content']);
173 include_once("lib/difflib.php");
174 $diff2 = new Diff($other_content, $this_content);
175 //$context_lines = max(4, count($other_content) + 1,
176 // count($this_content) + 1);
177 $fmt = new UnifiedDiffFormatter(/*$context_lines*/);
178 $content = $this->pagename . " " . $previous . " " .
179 Iso8601DateTime($prevdata['mtime']) . "\n";
180 $content .= $this->pagename . " " . $version . " " .
181 Iso8601DateTime($meta['mtime']) . "\n";
182 $content .= $fmt->format($diff2);
185 $difflink = WikiURL($this->pagename,array(),true);
186 $content = $this->pagename . " " . $version . " " .
187 Iso8601DateTime($meta['mtime']) . "\n";
188 $content .= _("New page");
190 $editedby = sprintf(_("Edited by: %s"), $this->from);
191 //$editedby = sprintf(_("Edited by: %s"), $meta['author']);
192 $this->sendMail($subject,
193 $editedby."\n".$difflink."\n\n".$content);
197 * support mass rename / remove (not yet tested)
199 function sendPageRenameNotification ($to, &$meta) {
202 if (@is_array($request->_deferredPageRenameNotification)) {
203 $request->_deferredPageRenameNotification[] =
204 array($this->pagename, $to, $meta, $this->emails, $this->userids);
206 $pagename = $this->pagename;
207 //$editedby = sprintf(_("Edited by: %s"), $meta['author']) . ' ' . $meta['author_id'];
208 $editedby = sprintf(_("Edited by: %s"), $this->from);
209 $subject = sprintf(_("Page rename %s to %s"), urlencode($pagename), urlencode($to));
210 $link = WikiURL($to, true);
211 $this->sendMail($subject,
212 $editedby."\n".$link."\n\n"."Renamed $pagename to $to");
219 function onChangePage (&$wikidb, &$wikitext, $version, &$meta) {
221 if (!isa($GLOBALS['request'],'MockRequest')) {
222 $notify = $wikidb->_wikidb->get('notify');
223 /* Generate notification emails? */
224 if (!empty($notify) and is_array($notify)) {
225 if (empty($this->pagename))
226 $this->pagename = $meta['pagename'];
227 //TODO: defer it (quite a massive load if you MassRevert some pages).
228 //TODO: notification class which catches all changes,
229 // and decides at the end of the request what to mail. (type, page, who, what, users, emails)
230 // could be used for PageModeration and RSS2 Cloud xml-rpc also.
231 $this->getPageChangeEmails($notify);
232 if (!empty($this->emails)) {
233 $result = $this->sendPageChangeNotification($wikitext, $version, $meta);
240 function onDeletePage (&$wikidb, $pagename) {
242 /* Generate notification emails? */
243 if (! $wikidb->isWikiPage($pagename) and !isa($GLOBALS['request'],'MockRequest')) {
244 $notify = $wikidb->get('notify');
245 if (!empty($notify) and is_array($notify)) {
246 //TODO: deferr it (quite a massive load if you remove some pages).
247 //TODO: notification class which catches all changes,
248 // and decides at the end of the request what to mail.
249 // (type, page, who, what, users, emails)
251 // could be used for PageModeration and RSS2 Cloud xml-rpc also.
252 $this->getPageChangeEmails($notify);
253 if (!empty($this->emails)) {
254 $editedby = sprintf(_("Removed by: %s"), $this->from); // Todo: host_id
255 $emails = join(',', $emails);
256 $subject = sprintf(_("Page removed %s"), urlencode($pagename));
257 $result = $this->sendMail($subject,
258 $editedby."\n"."Deleted $pagename"."\n\n".$content);
262 //How to create a RecentChanges entry with explaining summary? Dynamically
264 $page = $this->getPage($pagename);
265 $current = $page->getCurrentRevision();
266 $meta = $current->_data;
267 $version = $current->getVersion();
268 $meta['summary'] = _("removed");
269 $page->save($current->getPackedContent(), $version + 1, $meta);
274 function onRenamePage (&$wikidb, $oldpage, $new_pagename) {
276 if (!isa($GLOBALS['request'], 'MockRequest')) {
277 $notify = $wikidb->get('notify');
278 if (!empty($notify) and is_array($notify)) {
279 $this->getPageChangeEmails($notify);
280 if (!empty($this->emails)) {
281 $newpage = $wikidb->getPage($new_pagename);
282 $current = $newpage->getCurrentRevision();
283 $meta = $current->_data;
284 $this->pagename = $oldpage;
285 $result = $this->sendPageRenameNotification($new_pagename, $meta);
292 * send mail to user and store the cookie in the db
293 * wikiurl?action=ConfirmEmail&id=bla
295 function sendEmailConfirmation ($email, $userid) {
296 $id = rand_ascii_readable(16);
297 $wikidb = $GLOBALS['request']->getDbh();
298 $data = $wikidb->get('ConfirmEmail');
299 while(!empty($data[$id])) { // id collision
300 $id = rand_ascii_readable(16);
302 $subject = WIKI_NAME . " " . _("e-mail address confirmation");
303 $ip = $request->get('REMOTE_HOST');
304 $expire_date = time() + 7*86400;
305 $content = fmt("Someone, probably you from IP address %s, has registered an
306 account \"%s\" with this e-mail address on %s.
308 To confirm that this account really does belong to you and activate
309 e-mail features on %s, open this link in your browser:
313 If this is *not* you, don't follow the link. This confirmation code
315 $ip, $userid, WIKI_NAME, WIKI_NAME,
316 WikiURL(HOME_PAGE, array('action' => 'ConfirmEmail',
319 CTime($expire_date));
320 $this->sendMail($subject, $content, "", true);
321 $data[$id] = array('email' => $email,
323 'expire' => $expire_date);
324 $wikidb->set('ConfirmEmail', $data);
328 function checkEmailConfirmation () {
330 $wikidb = $request->getDbh();
331 $data = $wikidb->get('ConfirmEmail');
332 $id = $request->getArg('id');
333 if (empty($data[$id])) { // id not found
334 return HTML(HTML::h1("Confirm E-mail address"),
335 HTML::h1("Sorry! Wrong URL"));
338 $userid = $data['userid'];
339 $email = $data['email'];
340 $u = $request->getUser();
341 if ($u->UserName() == $userid) { // lucky: current user (session)
342 $prefs = $u->getPreferences();
343 $request->_user->_level = WIKIAUTH_USER;
344 $request->_prefs->set('emailVerified', true);
345 } else { // not current user
346 if (ENABLE_USER_NEW) {
347 $u = WikiUser($userid);
348 $u->getPreferences();
349 $prefs = &$u->_prefs;
351 $u = new WikiUser($request, $userid);
352 $prefs = $u->getPreferences();
354 $u->_level = WIKIAUTH_USER;
355 $request->setUser($u);
356 $request->_prefs->set('emailVerified', true);
359 $wikidb->set('ConfirmEmail', $data);
360 return HTML(HTML::h1("Confirm E-mail address"),
361 HTML::p("Your e-mail address has now been confirmed."));
366 // $Log: not supported by cvs2svn $
367 // Revision 1.3 2006/12/24 13:35:43 rurban
368 // added experimental EMailConfirm auth. (not yet tested)
369 // requires actionpage ConfirmEmail
370 // TBD: purge expired cookies
372 // Revision 1.2 2006/12/23 11:50:45 rurban
373 // added missing result init
375 // Revision 1.1 2006/12/22 17:59:55 rurban
376 // Move mailer functions into seperate MailNotify.php
383 // c-hanging-comment-ender-p: nil
384 // indent-tabs-mode: nil