$link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), FALSE); } // finalize links $message .= Skin::build_mail_menu($menu); // provide a link that also authenticates surfers on click-through --see users/login.php $message = str_replace(array(Sections::get_permalink($item), str_replace('&', '&', Sections::get_permalink($item))), $context['url_to_root'] . Users::get_login_url('visit', 'section:' . $item['id'], $user['id'], $item['handle']), $message); // threads messages $headers = Mailer::set_thread('section:' . $item['id']); // get attachments from the overlay, if any $attachments = NULL; if (is_callable(array($overlay, 'get_invite_attachments'))) { $attachments = $overlay->get_invite_attachments('PUBLISH'); } // post it if (Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments)) { $actual_names[] = htmlspecialchars($recipient); } } Mailer::close(); // display the list of actual recipients if ($actual_names) { $context['text'] .= '<div>' . sprintf(i18n::s('Your message is being transmitted to %s'), Skin::finalize_list($actual_names, 'compact')) . '</div>'; } else { $context['text'] .= '<p>' . i18n::s('No message has been sent') . '</p>'; } // back to the section page $menu = array(); $menu[] = Skin::build_link(Sections::get_permalink($item), i18n::s('Done'), 'button'); $context['text'] .= Skin::finalize_list($menu, 'assistant_bar'); // a form to send an invitation to several people
} if (!isset($context['letter_suffix'])) { $context['letter_suffix'] = ''; } if (!isset($context['letter_title'])) { $context['letter_title'] = ''; } if (!isset($context['title_prefix'])) { $context['title_prefix'] = '*** '; } if (!isset($context['title_suffix'])) { $context['title_suffix'] = ''; } // if no reply-to, use the one of the logged user if (!isset($context['letter_reply_to']) || !$context['letter_reply_to']) { $context['letter_reply_to'] = Surfer::from(); } // restrictions: for associates only if (!Surfer::is_associate()) { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation.')); // e-mail has not been enabled } elseif (!isset($context['with_email']) || $context['with_email'] != 'Y') { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('E-mail has not been activated on this system.')); // no post account } elseif ((!isset($context['mail_from']) || !$context['mail_from']) && (!isset($context['letter_reply_to']) || !$context['letter_reply_to'])) { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(sprintf(i18n::s('No account to post the letter. Please %s.'), Skin::build_link('letters/configure.php', i18n::s('configure one')))); // prepare some announcement } elseif (isset($action) && $action == 'announcement') {
if (Surfer::is_crawler()) { Safe::header('Status: 401 Unauthorized', TRUE, 401); } elseif (!Surfer::is_logged()) { Safe::redirect($context['url_to_home'] . $context['url_to_root'] . 'users/login.php?url=' . urlencode(Articles::get_permalink($item))); } elseif (isset($_REQUEST['requested']) && ($requested = Users::get($_REQUEST['requested'])) && $requested['email']) { // prepare the mail message $to = Mailer::encode_recipient($requested['email'], $requested['full_name']); $subject = sprintf(i18n::c('%s: %s'), i18n::c('Request'), strip_tags($item['title'])); $message = Articles::build_notification('apply', $item, $overlay); $headers = Mailer::set_thread('article:' . $item['id']); // allow for skinnable template $message = Skin::build_mail_message($message); // build multiple parts, for HTML rendering $message = Mailer::build_multipart($message); // send the message to requested user if (Mailer::post(Surfer::from(), $to, $subject, $message, NULL, $headers)) { $text = sprintf(i18n::s('Your request has been transmitted to %s. Check your mailbox for feed-back.'), Skin::build_link(Users::get_permalink($requested), Codes::beautify_title($requested['full_name']), 'user')); $context['text'] .= Skin::build_block($text, 'note'); } // follow-up navigation $context['text'] .= '<div>' . i18n::s('Where do you want to go now?') . '</div>'; $menu = array(); $menu[] = Skin::build_link($context['url_to_root'], i18n::s('Front page'), 'button'); $menu[] = Skin::build_link(Surfer::get_permalink(), i18n::s('My profile'), 'span'); $context['text'] .= Skin::finalize_list($menu, 'menu_bar'); // offer to request some owner } else { // provide feed-back to surfer $context['text'] .= Skin::build_block(i18n::s('You are not allowed to access this page.'), 'caution'); // list owners $owners = array();
$headline = sprintf(i18n::c('%s is following you'), '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $follower->get_url() . '">' . $follower->get_title() . '</a>'); // information $message = '<p>' . sprintf(i18n::c('%s will receive notifications when you will update your followers at %s'), $follower->get_title(), $context['site_name']) . '</p>'; // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . $follower->get_url(); $menu[] = Skin::build_mail_button($link, $follower->get_title(), TRUE); // finalize links $message .= Skin::build_mail_menu($menu); // enable threading $headers = Mailer::set_thread($follower->get_reference()); // allow for cross-referencing Mailer::notify(Surfer::from(), $user['email'], $subject, $message, $headers); } // regular container } else { // always update the watch list Members::assign($_REQUEST['member'], $_REQUEST['anchor']); // editor link has to be added explicitly on non-private items if (!$anchor->is_hidden() && (!isset($_REQUEST['assignment']) || $_REQUEST['assignment'] != 'editor')) { } else { Members::assign($_REQUEST['anchor'], $_REQUEST['member']); } } // set editor } elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'set' && isset($_REQUEST['editor']) && isset($_REQUEST['member'])) { Members::assign($_REQUEST['editor'], $_REQUEST['member']); // reset editor
$link = Categories::get_permalink($item); if (!is_object($overlay) || !($label = $overlay->get_label('permalink_command', 'categories', FALSE))) { $label = i18n::c('View the category'); } $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to the container if (is_object($anchor)) { $link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), FALSE); } // finalize links $message .= Skin::build_mail_menu($menu); // threads messages $headers = Mailer::set_thread('category:' . $item['id']); // send the message if (Mailer::notify(Surfer::from(), $to, $subject, $message, $headers)) { // feed-back to the sender $context['text'] .= '<p>' . i18n::s('A message has been sent to:') . "</p>\n" . '<ul>' . "\n"; foreach ($to as $address) { $context['text'] .= '<li>' . encode_field($address) . '</li>' . "\n"; } $context['text'] .= '</ul>' . "\n"; // back to the category page $menu = array(); $menu[] = Skin::build_link(Categories::get_permalink($item), i18n::s('Done'), 'button'); $context['text'] .= Skin::finalize_list($menu, 'assistant_bar'); } Mailer::close(); // no recipient has been found } elseif (!($recipients =& Members::list_users_by_posts_for_anchor('category:' . $item['id'], 0, 200, 'mail')) || !count($recipients)) { Logger::error(i18n::s('No recipient has been found.'));
/** * remember an action once it's done * * To be overloaded into derived class * * @param string the action 'insert', 'update' or 'delete' * @param array the hosting record * @param string reference of the hosting record (e.g., 'article:123') * @return FALSE on error, TRUE otherwise */ function remember($action, $host, $reference) { global $context; // remember the id of the master record $id = $host['id']; // set default values for this editor Surfer::check_default_editor($this->attributes); // we use the existing back-end for dates include_once $context['path_to_root'] . 'dates/dates.php'; // build the update query switch ($action) { case 'delete': // no need to notify participants after the date planned for the event, nor if the event has been initiated if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp'] > gmstrftime('%Y-%m-%d %H:%M') && isset($this->attributes['status']) && $this->attributes['status'] != 'started' && $this->attributes['status'] != 'stopped') { // send a cancellation message to participants $query = "SELECT user_email FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "') AND (approved LIKE 'Y')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // message title $subject = sprintf('%s: %s', i18n::c('Cancellation'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('%s has cancelled %s'), Surfer::get_link(), $this->anchor->get_title()); // message to reader $message = $this->get_invite_default_message('CANCEL'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('CANCEL'); // post it Mailer::notify(Surfer::from(), $item['user_email'], $subject, $message, $headers, $attachments); } } // delete dates for this anchor Dates::delete_for_anchor($reference); // also delete related enrolment records $query = "DELETE FROM " . SQL::table_name('enrolments') . " WHERE anchor LIKE '" . $reference . "'"; SQL::query($query); break; case 'insert': // bind one date to this record if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp']) { $fields = array(); $fields['anchor'] = $reference; $fields['date_stamp'] = $this->attributes['date_stamp']; // update the database if (!($fields['id'] = Dates::post($fields))) { Logger::error(i18n::s('Impossible to add an item.')); return FALSE; } } // enroll page creator include_once $context['path_to_root'] . 'shared/enrolments.php'; enrolments::confirm($reference); // reload the anchor through the cache to reflect the update if ($reference) { $this->anchor = Anchors::get($reference, TRUE); } // send a confirmation message to event creator $query = "SELECT * FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // a user registered on this server if ($item['user_id'] && ($watcher = Users::get($item['user_id']))) { // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // use this email address if ($watcher['full_name']) { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['full_name']); } else { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['nick_name']); } // message title $subject = sprintf(i18n::c('Meeting: %s'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('you have arranged %s'), '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url() . '">' . $this->anchor->get_title() . '</a>'); // message to reader $message = $this->get_invite_default_message('PUBLISH'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url(); $menu[] = Skin::build_mail_button($link, i18n::c('View event details'), TRUE); // finalize links $message .= Skin::build_mail_menu($menu); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('PUBLISH'); // post it Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments); } } break; case 'update': // reload the anchor through the cache to reflect the update if ($reference) { $this->anchor = Anchors::get($reference, TRUE); } // no need to notify watchers after the date planned for the event, nor if the event has been initiated if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp'] > gmstrftime('%Y-%m-%d %H:%M') && isset($this->attributes['status']) && $this->attributes['status'] != 'started' && $this->attributes['status'] != 'stopped' && isset($_REQUEST['notify_watchers']) && $_REQUEST['notify_watchers'] == 'Y') { // send a confirmation message to participants $query = "SELECT * FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // skip current surfer if (Surfer::get_id() && Surfer::get_id() == $item['user_id']) { continue; } // a user registered on this server if ($item['user_id'] && ($watcher = Users::get($item['user_id']))) { // skip banned users if ($watcher['capability'] == '?') { continue; } // ensure this surfer wants to be alerted if ($watcher['without_alerts'] == 'Y') { continue; } // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // use this email address if ($watcher['full_name']) { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['full_name']); } else { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['nick_name']); } // message title $subject = sprintf(i18n::c('Updated: %s'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('%s has updated %s'), Surfer::get_link(), '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url() . '">' . $this->anchor->get_title() . '</a>'); // message to reader $message = $this->get_invite_default_message('PUBLISH'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url(); $menu[] = Skin::build_mail_button($link, i18n::c('View event details'), TRUE); // finalize links $message .= Skin::build_mail_menu($menu); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('PUBLISH'); // post it Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments); } } } // bind one date to this record if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp']) { $fields = array(); $fields['anchor'] = $reference; $fields['date_stamp'] = $this->attributes['date_stamp']; // there is an existing record if ($date =& Dates::get_for_anchor($reference)) { // update the record $fields['id'] = $date['id']; if (!($id = Dates::post($fields))) { Logger::error(sprintf(i18n::s('Impossible to update date %s'), $this->attributes['date_stamp'])); return FALSE; } // create a record instead of raising an error, we are smart y'a'know } else { if (!($fields['id'] = Dates::post($fields))) { Logger::error(i18n::s('Impossible to add an item.')); return FALSE; } } } break; } // job done return TRUE; }
continue; } // target recipient does not accept messages if (isset($item['without_messages']) && $item['without_messages'] == 'Y') { continue; } // target is known here if (isset($item['id'])) { // suggest to change user preferences if applicable $mail['message'] .= '<p> </p>' . '<p>' . i18n::c('To prevent other members from contacting you, please visit your profile at the following address, and change preferences.') . '</p>' . '<p>' . $context['url_to_master'] . $context['url_to_root'] . Users::get_permalink($item) . '</p>'; // alert the target user if (!Users::alert($item, $mail)) { Logger::error(sprintf(i18n::s('Impossible to send a message to %s.'), $item['nick_name'])); } // we only have a recipient address } elseif ($item['email'] && !Mailer::notify(Surfer::from(), $item['email'], $mail['subject'], $mail['message'], $mail['headers'])) { Logger::error(sprintf(i18n::s('Impossible to send a message to %s.'), $item['email'])); } } } } // follow-up commands if (!$render_overlaid) { $menu = array(); if (isset($article['id'])) { $menu = array(Articles::get_permalink($article) => i18n::s('View the new thread')); } if (count($items) == 1 && ($item = $items[0]) && isset($item['id'])) { $menu = array_merge($menu, array(Users::get_permalink($item) => sprintf(i18n::s('Back to %s'), $item['nick_name']))); } elseif (Surfer::get_id()) { $menu = array_merge($menu, array(Surfer::get_permalink() => i18n::s('Back to my profile')));
/** * alert one user * * This function sends messages only to users ready to receive alerts and notifications. * * It ensures that only one alert is send to a user, * by maintaining an internal list of ids that have been processed. * * @param mixed an array of attributes, or only an id of the user profile * @param array components of a mail message to be submitted to Mailer::notify() * @return TRUE on success, FALSE otherwise */ public static function alert($user, $mail) { global $context; // sanity check if (!isset($mail['subject']) || !$mail['subject'] || !isset($mail['message']) || !$mail['message']) { return FALSE; } // retrieve user attributes if (!isset($user['id']) && !($user = Users::get($user))) { return FALSE; } // skip banned users if (isset($user['capability']) && $user['capability'] == '?') { return FALSE; } // a valid address is required for e-mail... if (!isset($user['email']) || !$user['email'] || !preg_match(VALID_RECIPIENT, $user['email'])) { return FALSE; } // ensure poster wants alerts if (isset($user['without_alerts']) && $user['without_alerts'] == 'Y') { return FALSE; } // the list of users notified during overall script execution static $already_processed; if (!isset($already_processed)) { $already_processed = array(); } // this user has already been notified if (in_array($user['id'], $already_processed)) { return FALSE; } // remember this recipient $already_processed[] = $user['id']; // use this email address if ($user['full_name']) { $recipient = Mailer::encode_recipient($user['email'], $user['full_name']); } else { $recipient = Mailer::encode_recipient($user['email'], $user['nick_name']); } // post a message to this particular user return Mailer::notify(Surfer::from(), $recipient, $mail['subject'], $mail['message'], isset($mail['headers']) ? $mail['headers'] : '', isset($mail['attachement']) ? $mail['attachement'] : null); }
if (!Surfer::is_logged()) { Safe::redirect($context['url_to_home'] . $context['url_to_root'] . 'users/login.php?url=' . urlencode(Users::get_url($item['id'], 'mail'))); } // permission denied to authenticated user Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation.')); // no mail in demo mode } elseif (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && file_exists($context['path_to_root'] . 'parameters/demo.flag')) { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation in demonstration mode.')); // no recipient has been found } elseif (!isset($item['email']) || !$item['email']) { Logger::error(i18n::s('No email address has been provided for this person.')); } elseif (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { // sender address $from = Surfer::from(); // recipient(s) address(es) $to = strip_tags($item['email']); // get a copy if (isset($_REQUEST['self_copy']) && $_REQUEST['self_copy'] == 'Y') { $to .= ', ' . $from; } // message subject $subject = ''; if (isset($_REQUEST['subject'])) { $subject = strip_tags($_REQUEST['subject']); } // enable yacs codes in messages $message = Codes::beautify($_REQUEST['message']); // nothing to do if (!$subject || !$message) {