Ejemplo n.º 1
0
 function format_address($address)
 {
     foreach ($address as $array) {
         $array['name'] = trim($array['name']);
         $formatted[] = $array['name'] && $this->named_addresses ? '"' . mail_encode($array['name'], $this->encoding) . '" <' . $array['address'] . '>' : $array['address'];
     }
     return implode(', ', $formatted);
 }
Ejemplo n.º 2
0
 /**
  * Process queue
  * Using lock file
  */
 function process()
 {
     global $db, $config, $phpEx, $phpbb_root_path, $user;
     set_config('last_queue_run', time(), true);
     // Delete stale lock file
     if (file_exists($this->cache_file . '.lock') && !file_exists($this->cache_file)) {
         @unlink($this->cache_file . '.lock');
         return;
     }
     if (!file_exists($this->cache_file) || file_exists($this->cache_file . '.lock') && filemtime($this->cache_file) > time() - $config['queue_interval']) {
         return;
     }
     $fp = @fopen($this->cache_file . '.lock', 'wb');
     fclose($fp);
     @chmod($this->cache_file . '.lock', 0777);
     include $this->cache_file;
     foreach ($this->queue_data as $object => $data_ary) {
         @set_time_limit(0);
         if (!isset($data_ary['package_size'])) {
             $data_ary['package_size'] = 0;
         }
         $package_size = $data_ary['package_size'];
         $num_items = !$package_size || sizeof($data_ary['data']) < $package_size ? sizeof($data_ary['data']) : $package_size;
         // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs...
         if (sizeof($data_ary['data']) > $package_size * 2.5) {
             $num_items = sizeof($data_ary['data']);
         }
         switch ($object) {
             case 'email':
                 // Delete the email queued objects if mailing is disabled
                 if (!$config['email_enable']) {
                     unset($this->queue_data['email']);
                     continue 2;
                 }
                 break;
             case 'jabber':
                 if (!$config['jab_enable']) {
                     unset($this->queue_data['jabber']);
                     continue 2;
                 }
                 include_once $phpbb_root_path . 'includes/functions_jabber.' . $phpEx;
                 $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_use_ssl']);
                 if (!$this->jabber->connect()) {
                     messenger::error('JABBER', $user->lang['ERR_JAB_CONNECT']);
                     continue 2;
                 }
                 if (!$this->jabber->login()) {
                     messenger::error('JABBER', $user->lang['ERR_JAB_AUTH']);
                     continue 2;
                 }
                 break;
             default:
                 return;
         }
         for ($i = 0; $i < $num_items; $i++) {
             // Make variables available...
             extract(array_shift($this->queue_data[$object]['data']));
             switch ($object) {
                 case 'email':
                     $err_msg = '';
                     $to = !$to ? 'undisclosed-recipients:;' : $to;
                     if ($config['smtp_delivery']) {
                         $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers);
                     } else {
                         ob_start();
                         $result = $config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers);
                         $err_msg = ob_get_clean();
                     }
                     if (!$result) {
                         @unlink($this->cache_file . '.lock');
                         messenger::error('EMAIL', $err_msg);
                         continue 2;
                     }
                     break;
                 case 'jabber':
                     foreach ($addresses as $address) {
                         if ($this->jabber->send_message($address, $msg, $subject) === false) {
                             messenger::error('JABBER', $this->jabber->get_log());
                             continue 3;
                         }
                     }
                     break;
             }
         }
         // No more data for this object? Unset it
         if (!sizeof($this->queue_data[$object]['data'])) {
             unset($this->queue_data[$object]);
         }
         // Post-object processing
         switch ($object) {
             case 'jabber':
                 // Hang about a couple of secs to ensure the messages are
                 // handled, then disconnect
                 $this->jabber->disconnect();
                 break;
         }
     }
     if (!sizeof($this->queue_data)) {
         @unlink($this->cache_file);
     } else {
         if ($fp = @fopen($this->cache_file, 'wb')) {
             @flock($fp, LOCK_EX);
             fwrite($fp, "<?php\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>");
             @flock($fp, LOCK_UN);
             fclose($fp);
             phpbb_chmod($this->cache_file, CHMOD_WRITE);
         }
     }
     @unlink($this->cache_file . '.lock');
 }
Ejemplo n.º 3
0
/**
 * @brief Create an array representing the important channel information
 * which would be necessary to create a nomadic identity clone. This includes
 * most channel resources and connection information with the exception of content.
 *
 * @param int $channel_id
 *     Channel_id to export
 * @param boolean $items
 *     Include channel posts (wall items), default false
 *
 * @returns array
 *     See function for details
 */
function identity_basic_export($channel_id, $items = false)
{
    /*
     * Red basic channel export
     */
    $ret = array();
    $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => RED_VERSION, 'database' => DB_UPDATE_VERSION);
    $r = q("select * from channel where channel_id = %d limit 1", intval($channel_id));
    if ($r) {
        $ret['channel'] = $r[0];
    }
    $r = q("select * from profile where uid = %d", intval($channel_id));
    if ($r) {
        $ret['profile'] = $r;
    }
    $xchans = array();
    $r = q("select * from abook where abook_channel = %d ", intval($channel_id));
    if ($r) {
        $ret['abook'] = $r;
        foreach ($r as $rr) {
            $xchans[] = $rr['abook_xchan'];
        }
        stringify_array_elms($xchans);
    }
    if ($xchans) {
        $r = q("select * from xchan where xchan_hash in ( " . implode(',', $xchans) . " ) ");
        if ($r) {
            $ret['xchan'] = $r;
        }
        $r = q("select * from hubloc where hubloc_hash in ( " . implode(',', $xchans) . " ) ");
        if ($r) {
            $ret['hubloc'] = $r;
        }
    }
    $r = q("select * from `groups` where uid = %d ", intval($channel_id));
    if ($r) {
        $ret['group'] = $r;
    }
    $r = q("select * from group_member where uid = %d ", intval($channel_id));
    if ($r) {
        $ret['group_member'] = $r;
    }
    $r = q("select * from pconfig where uid = %d", intval($channel_id));
    if ($r) {
        $ret['config'] = $r;
    }
    $r = q("select type, data, os_storage from photo where scale = 4 and profile = 1 and uid = %d limit 1", intval($channel_id));
    if ($r) {
        $ret['photo'] = array('type' => $r[0]['type'], 'data' => $r[0]['os_storage'] ? base64url_encode(file_get_contents($r[0]['data'])) : base64url_encode($r[0]['data']));
    }
    // All other term types will be included in items, if requested.
    $r = q("select * from term where type in (%d,%d) and uid = %d", intval(TERM_SAVEDSEARCH), intval(TERM_THING), intval($channel_id));
    if ($r) {
        $ret['term'] = $r;
    }
    // add psuedo-column obj_baseurl to aid in relocations
    $r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d", dbesc(z_root()), intval($channel_id));
    if ($r) {
        $ret['obj'] = $r;
    }
    $r = q("select * from app where app_channel = %d", intval($channel_id));
    if ($r) {
        $ret['app'] = $r;
    }
    $r = q("select * from chatroom where cr_uid = %d", intval($channel_id));
    if ($r) {
        $ret['chatroom'] = $r;
    }
    $r = q("select * from event where uid = %d", intval($channel_id));
    if ($r) {
        $ret['event'] = $r;
    }
    $r = q("select * from item where resource_type = 'event' and uid = %d", intval($channel_id));
    if ($r) {
        $ret['event_item'] = array();
        xchan_query($r);
        $r = fetch_post_tags($r, true);
        foreach ($r as $rr) {
            $ret['event_item'][] = encode_item($rr, true);
        }
    }
    $x = menu_list($channel_id);
    if ($x) {
        $ret['menu'] = array();
        for ($y = 0; $y < count($x); $y++) {
            $m = menu_fetch($x[$y]['menu_name'], $channel_id, $ret['channel']['channel_hash']);
            if ($m) {
                $ret['menu'][] = menu_element($m);
            }
        }
    }
    $x = menu_list($channel_id);
    if ($x) {
        $ret['menu'] = array();
        for ($y = 0; $y < count($x); $y++) {
            $m = menu_fetch($x[$y]['menu_name'], $channel_id, $ret['channel']['channel_hash']);
            if ($m) {
                $ret['menu'][] = menu_element($m);
            }
        }
    }
    $addon = array('channel_id' => $channel_id, 'data' => $ret);
    call_hooks('identity_basic_export', $addon);
    $ret = $addon['data'];
    if (!$items) {
        return $ret;
    }
    $r = q("select * from likes where channel_id = %d", intval($channel_id));
    if ($r) {
        $ret['likes'] = $r;
    }
    $r = q("select * from conv where uid = %d", intval($channel_id));
    if ($r) {
        for ($x = 0; $x < count($r); $x++) {
            $r[$x]['subject'] = base64url_decode(str_rot47($r[$x]['subject']));
        }
        $ret['conv'] = $r;
    }
    $r = q("select * from mail where mail.uid = %d", intval($channel_id));
    if ($r) {
        $m = array();
        foreach ($r as $rr) {
            xchan_mail_query($rr);
            $m[] = mail_encode($rr, true);
        }
        $ret['mail'] = $m;
    }
    $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d", intval($channel_id));
    if ($r) {
        $ret['item_id'] = $r;
    }
    //$key = get_config('system','prvkey');
    /** @warning this may run into memory limits on smaller systems */
    /** export three months of posts. If you want to export and import all posts you have to start with 
     * the first year and export/import them in ascending order. 
     *
     * Don't export linked resource items. we'll have to pull those out separately.
     */
    $r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created > %s - INTERVAL %s and resource_type = '' order by created", intval($channel_id), db_utcnow(), db_quoteinterval('3 MONTH'));
    if ($r) {
        $ret['item'] = array();
        xchan_query($r);
        $r = fetch_post_tags($r, true);
        foreach ($r as $rr) {
            $ret['item'][] = encode_item($rr, true);
        }
    }
    return $ret;
}
 /**
  * Process queue
  * Using lock file
  */
 function process()
 {
     global $db, $config, $phpEx, $phpbb_root_path, $user;
     $lock = new \phpbb\lock\flock($this->cache_file);
     $lock->acquire();
     // avoid races, check file existence once
     $have_cache_file = file_exists($this->cache_file);
     if (!$have_cache_file || $config['last_queue_run'] > time() - $config['queue_interval']) {
         if (!$have_cache_file) {
             set_config('last_queue_run', time(), true);
         }
         $lock->release();
         return;
     }
     set_config('last_queue_run', time(), true);
     include $this->cache_file;
     foreach ($this->queue_data as $object => $data_ary) {
         @set_time_limit(0);
         if (!isset($data_ary['package_size'])) {
             $data_ary['package_size'] = 0;
         }
         $package_size = $data_ary['package_size'];
         $num_items = !$package_size || sizeof($data_ary['data']) < $package_size ? sizeof($data_ary['data']) : $package_size;
         /*
         * This code is commented out because it causes problems on some web hosts.
         * The core problem is rather restrictive email sending limits.
         * This code is nly useful if you have no such restrictions from the
         * web host and the package size setting is wrong.
         
         // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs...
         if (sizeof($data_ary['data']) > $package_size * 2.5)
         {
         	$num_items = sizeof($data_ary['data']);
         }
         */
         switch ($object) {
             case 'email':
                 // Delete the email queued objects if mailing is disabled
                 if (!$config['email_enable']) {
                     unset($this->queue_data['email']);
                     continue 2;
                 }
                 break;
             case 'jabber':
                 if (!$config['jab_enable']) {
                     unset($this->queue_data['jabber']);
                     continue 2;
                 }
                 include_once $phpbb_root_path . 'includes/functions_jabber.' . $phpEx;
                 $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], htmlspecialchars_decode($config['jab_password']), $config['jab_use_ssl']);
                 if (!$this->jabber->connect()) {
                     $messenger = new messenger();
                     $messenger->error('JABBER', $user->lang['ERR_JAB_CONNECT']);
                     continue 2;
                 }
                 if (!$this->jabber->login()) {
                     $messenger = new messenger();
                     $messenger->error('JABBER', $user->lang['ERR_JAB_AUTH']);
                     continue 2;
                 }
                 break;
             default:
                 $lock->release();
                 return;
         }
         for ($i = 0; $i < $num_items; $i++) {
             // Make variables available...
             extract(array_shift($this->queue_data[$object]['data']));
             switch ($object) {
                 case 'email':
                     $err_msg = '';
                     $to = !$to ? 'undisclosed-recipients:;' : $to;
                     if ($config['smtp_delivery']) {
                         $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers);
                     } else {
                         $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg);
                     }
                     if (!$result) {
                         $messenger = new messenger();
                         $messenger->error('EMAIL', $err_msg);
                         continue 2;
                     }
                     break;
                 case 'jabber':
                     foreach ($addresses as $address) {
                         if ($this->jabber->send_message($address, $msg, $subject) === false) {
                             $messenger = new messenger();
                             $messenger->error('JABBER', $this->jabber->get_log());
                             continue 3;
                         }
                     }
                     break;
             }
         }
         // No more data for this object? Unset it
         if (!sizeof($this->queue_data[$object]['data'])) {
             unset($this->queue_data[$object]);
         }
         // Post-object processing
         switch ($object) {
             case 'jabber':
                 // Hang about a couple of secs to ensure the messages are
                 // handled, then disconnect
                 $this->jabber->disconnect();
                 break;
         }
     }
     if (!sizeof($this->queue_data)) {
         @unlink($this->cache_file);
     } else {
         if ($fp = @fopen($this->cache_file, 'wb')) {
             fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>");
             fclose($fp);
             phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
         }
     }
     $lock->release();
 }
Ejemplo n.º 5
0
/**
 * Отправить HTML письмо
 *
 * @param string $to      Кому
 * @param string $from    От кого
 * @param string $message Письмо
 * @param string $subject Тема письма
 */
function mail_send($to, $from = '*****@*****.**', $message = '', $subject = '', $from_user = '')
{
    // Обработаем кирилицу в поле: От кого
    $from_user = mail_encode($from_user, 'UTF-8');
    // Обработаем кирилицу в поле: Тема письма
    $subject = mail_encode($subject, 'UTF-8');
    // Uniqid Session
    $session = md5(uniqid(time()));
    // Установим необходимые заголовки
    $headers = 'MIME-Version: 1.0' . "\r\n";
    $headers .= 'Content-type: text/html; charset="UTF-8"' . "\r\n";
    //"Content-Type: multipart/mixed; boundary=\"".$strSid."\"\n\n";
    //$strHeader .= "This is a multi-part message in MIME format.\n";
    $headers .= 'From: ' . $from_user . '<' . $from . '>' . "\r\n";
    // Добавим в сообщение HTML тэги
    $message = '<html><head><meta charset="utf-8"></head><body>' . $message . '</body></html>';
    // Если письмо отправленно вернем 1
    return mail($to, $subject, $message, $headers);
}
Ejemplo n.º 6
0
 function format_address($address, $header = false)
 {
     if ($header) {
         return $address['name'] && $this->named_addresses ? '"' . mail_encode($address['name'], $this->encoding) . '" <' . $address['address'] . '>' : $address['address'];
     }
     //return ($address['name'] && $this->named_addresses) ?  '<' . $address['address'] . '> '.$address['name'] : '<' . $address['address'] . '>';
     return '<' . $address['address'] . '>';
 }
Ejemplo n.º 7
0
 /**
  * Send out emails
  */
 function msg_email($is_html = false)
 {
     global $config;
     if (empty($config['email_enable'])) {
         return false;
     }
     // Addresses to send to?
     if (empty($this->addresses) || empty($this->addresses['to']) && empty($this->addresses['cc']) && empty($this->addresses['bcc'])) {
         // Send was successful. ;)
         return true;
     }
     $contact_name = htmlspecialchars_decode($config['board_contact_name']);
     $board_contact = ($contact_name !== '' ? '"' . mail_encode($contact_name) . '" ' : '') . '<' . $config['board_contact'] . '>';
     if (empty($this->replyto)) {
         $this->replyto = $board_contact;
     }
     if (empty($this->from)) {
         $this->from = $board_contact;
     }
     $encode_eol = $config['smtp_delivery'] ? "\r\n" : $this->eol;
     // Build to, cc and bcc strings
     $to = $cc = $bcc = '';
     foreach ($this->addresses as $type => $address_ary) {
         if ($type == 'im') {
             continue;
         }
         foreach ($address_ary as $which_ary) {
             ${$type} .= (${$type} != '' ? ', ' : '') . ($which_ary['name'] != '' ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']);
         }
     }
     // Build header
     $headers = $this->build_header($to, $cc, $bcc, $is_html);
     // Send message ...
     $mail_to = $to == '' ? 'undisclosed-recipients:;' : $to;
     $err_msg = '';
     if ($config['smtp_delivery']) {
         $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $err_msg, $headers);
     } else {
         $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg);
     }
     if (!$result) {
         $this->error('EMAIL', $err_msg);
         return false;
     }
     return true;
 }
Ejemplo n.º 8
0
    private function mail_digests($now, $hour)
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //                                                                                                                  //
        // This method is what used to be mail_digests.php. It will mail all the digests for the given year, date and hour  //
        // offset by the $hour parameter.                                                                                   //
        //                                                                                                                  //
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        static $daily_digest_sql, $weekly_digest_sql;
        $run_successful = true;
        // Assume a successful run
        // If it was requested, get the year, month, date and hour of the digests to recreate. If it was not requested, simply use the current time. Note:
        // these cannot be acquired as URL key/value pairs anymore like in the mod. If used it must be as a result of a manual run of the mailer.
        if ($this->manual_mode && $this->config['phpbbservices_digests_test_time_use']) {
            $this->time = mktime($this->config['phpbbservices_digests_test_hour'], 0, 0, $this->config['phpbbservices_digests_test_month'], $this->config['phpbbservices_digests_test_day'], $this->config['phpbbservices_digests_test_year']);
            $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_SIMULATION_DATE_TIME', false, array(str_pad($this->config['phpbbservices_digests_test_year'], 2, '0', STR_PAD_LEFT) . '-' . str_pad($this->config['phpbbservices_digests_test_month'], 2, '0', STR_PAD_LEFT) . '-' . str_pad($this->config['phpbbservices_digests_test_day'], 2, '0', STR_PAD_LEFT), $this->config['phpbbservices_digests_test_hour']));
        } else {
            $this->time = $now + $hour * (60 * 60);
        }
        $this->gmt_time = $this->time - (int) ($this->server_timezone * 60 * 60);
        // Convert server time (or requested run date) into GMT time
        // Get the current hour in GMT, so applicable digests can be sent out for this hour
        $current_hour_gmt = date('G', $this->gmt_time);
        // 0 thru 23
        $current_hour_gmt_plus_30 = date('G', $this->gmt_time) + 0.5;
        if ($current_hour_gmt_plus_30 >= 24) {
            $current_hour_gmt_plus_30 = $current_hour_gmt_plus_30 - 24;
            // A very unlikely situation
        }
        // Create SQL fragment to fetch users wanting a daily digest
        if (!isset($daily_digest_sql)) {
            $daily_digest_sql = '(' . $this->db->sql_in_set('user_digest_type', array(constants::DIGESTS_DAILY_VALUE)) . ')';
        }
        // Create SQL fragment to also fetch users wanting a weekly digest, if today is the day weekly digests should go out
        if (!isset($weekly_digest_sql)) {
            $weekly_digest_sql = date('w', $this->gmt_time) == $this->config['phpbbservices_digests_weekly_digest_day'] ? ' OR (' . $this->db->sql_in_set('user_digest_type', array(constants::DIGESTS_WEEKLY_VALUE)) . ')' : '';
        }
        // Create SQL fragment to also fetch users wanting a monthly digest. This only happens if the current GMT day is the first of the month.
        $gmt_year = (int) date('Y', $this->gmt_time);
        $gmt_month = (int) date('n', $this->gmt_time);
        $gmt_day = (int) date('j', $this->gmt_time);
        $gmt_hour = (int) date('G', $this->gmt_time);
        if ($gmt_day == 1) {
            if ($gmt_month == 1) {
                $gmt_month = 12;
                $gmt_year--;
            } else {
                $gmt_month--;
                // Otherwise monthly digests are run for the previous month for the year
            }
            // Create a Unix timestamp that represents a time range for monthly digests, based on the current hour
            $gmt_month_last_day = date('t', mktime(0, 0, 0, $gmt_month, $gmt_day, $gmt_year));
            $gmt_month_1st_begin = mktime(0, 0, 0, $gmt_month, $gmt_day, $gmt_year);
            $this->gmt_month_lastday_end = mktime(23, 59, 59, $gmt_month, $gmt_month_last_day, $gmt_year);
            $monthly_digest_sql = ' OR (' . $this->db->sql_in_set('user_digest_type', array(constants::DIGESTS_MONTHLY_VALUE)) . ')';
        } else {
            $monthly_digest_sql = '';
            $gmt_month_1st_begin = 0;
            // Make PhpStorm happy
        }
        $formatted_date = date('Y-m-d H', $this->gmt_time);
        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_HOUR_RUN', false, array($formatted_date));
        // We need to know which auth_option_id corresponds to the forum read privilege (f_read) and forum list (f_list) privilege. Why not use $this->auth->acl_get?
        // Because this program must get permissions for different users, so forum authentication will need to be done outside of the regular authentication
        // mechanism.
        $auth_options = array('f_read', 'f_list');
        $sql = 'SELECT auth_option, auth_option_id
				FROM ' . ACL_OPTIONS_TABLE . '
				WHERE ' . $this->db->sql_in_set('auth_option', $auth_options);
        $result = $this->db->sql_query($sql);
        while ($row = $this->db->sql_fetchrow($result)) {
            if ($row['auth_option'] == 'f_read') {
                $this->read_id = $row['auth_option_id'];
            }
            if ($row['auth_option'] == 'f_list') {
                $this->list_id = $row['auth_option_id'];
            }
        }
        $this->db->sql_freeresult($result);
        // Query be gone!
        // Get users requesting digests for the current hour. Also, grab the user's style, so the digest will have a familiar look.
        if ($this->config['override_user_style']) {
            $sql_array = array('SELECT' => 'u.*, s.*', 'FROM' => array(USERS_TABLE => 'u', STYLES_TABLE => 's'), 'WHERE' => 's.style_id = ' . $this->config['default_style'] . ' 
								AND (' . $daily_digest_sql . $weekly_digest_sql . $monthly_digest_sql . ") \n\t\t\t\t\t\t\t\tAND (user_digest_send_hour_gmt = {$current_hour_gmt} OR user_digest_send_hour_gmt = {$current_hour_gmt_plus_30}) \n\t\t\t\t\t\t\t\tAND user_inactive_reason = 0\n\t\t\t\t\t\t\t\tAND user_digest_type <> '" . constants::DIGESTS_NONE_VALUE . "'", 'ORDER_BY' => ' user_lang');
        } else {
            $sql_array = array('SELECT' => 'u.*, s.*', 'FROM' => array(USERS_TABLE => 'u', STYLES_TABLE => 's'), 'WHERE' => 'u.user_style = s.style_id
								AND (' . $daily_digest_sql . $weekly_digest_sql . $monthly_digest_sql . ") \n\t\t\t\t\t\t\t\tAND (user_digest_send_hour_gmt = {$current_hour_gmt} OR user_digest_send_hour_gmt = {$current_hour_gmt_plus_30}) \n\t\t\t\t\t\t\t\tAND user_inactive_reason = 0\n\t\t\t\t\t\t\t\tAND user_digest_type <> '" . constants::DIGESTS_NONE_VALUE . "'", 'ORDER_BY' => 'user_lang');
        }
        $sql = $this->db->sql_build_query('SELECT', $sql_array);
        $result = $this->db->sql_query($sql);
        $rowset = $this->db->sql_fetchrowset($result);
        // Gets users and their metadata that are receiving digests for this hour
        // Fetch all the posts (no private messages) but do it just once for efficiency. These will be filtered later
        // to remove those posts a particular user should not see.
        // First, determine a maximum date range fetched: daily, weekly or monthly
        if ($monthly_digest_sql != '') {
            // In the case of monthly digests, it's important to include posts that support daily and weekly digests as well, hence dates of posts
            // retrieved may exceed post dates for the previous month. Logic to exclude posts past the end of the previous month in the case of
            // monthly digests must be handled in the create_content function to skip these.
            $date_limit_sql = ' AND p.post_time >= ' . $gmt_month_1st_begin . ' AND p.post_time <= ' . max($this->gmt_month_lastday_end, $this->gmt_time);
        } else {
            if ($weekly_digest_sql != '') {
                $this->date_limit = $this->time - 7 * 24 * 60 * 60;
                $date_limit_sql = ' AND p.post_time >= ' . $this->date_limit . ' AND p.post_time < ' . $this->time;
            } else {
                $this->date_limit = $this->time - 24 * 60 * 60;
                $date_limit_sql = ' AND p.post_time >= ' . $this->date_limit . ' AND p.post_time < ' . $this->time;
            }
        }
        // Now get all potential posts for all users and place them in an array for parsing. Later the mailer will filter out the stuff that should not go
        // in a particular digest, based on permissions and options the user selected.
        // Prepare SQL
        $sql_array = array('SELECT' => 'f.*, t.*, p.*, u.*', 'FROM' => array(POSTS_TABLE => 'p', USERS_TABLE => 'u', TOPICS_TABLE => 't', FORUMS_TABLE => 'f'), 'WHERE' => "f.forum_id = t.forum_id\n\t\t\t\t\t\t\t\tAND p.topic_id = t.topic_id \n\t\t\t\t\t\t\t\tAND p.poster_id = u.user_id\n\t\t\t\t\t\t\t\t{$date_limit_sql}\n\t\t\t\t\t\t\t\tAND p.post_visibility = 1\n\t\t\t\t\t\t\t\tAND forum_password = ''", 'ORDER_BY' => 'f.left_id, f.right_id');
        // Build query
        $sql_posts = $this->db->sql_build_query('SELECT', $sql_array);
        // Execute the SQL to retrieve the relevant posts. Note, if $this->config['phpbbservices_digests_max_items'] == 0 then there is no limit on the rows returned
        $result_posts = $this->db->sql_query_limit($sql_posts, $this->config['phpbbservices_digests_max_items']);
        $rowset_posts = $this->db->sql_fetchrowset($result_posts);
        // Get all the posts as a set
        // Now that we have all the posts, time to send one digest at a time
        foreach ($rowset as $row) {
            // Each traverse through this loop sends out exactly one digest
            // Skip sending this digest if a full "cycle" has not elapsed since when the digest was last sent out. For example, if the user has
            // subscribed to a daily digest, 24 hours needs to have elapsed since the last digest went out. The digest last send time is recorded
            // in the database when sent out.
            switch ($row['user_digest_type']) {
                case constants::DIGESTS_DAILY_VALUE:
                    if ($row['user_digest_last_sent'] + 60 * 60 * 24 > $now) {
                        continue;
                    }
                    break;
                case constants::DIGESTS_WEEKLY_VALUE:
                    if ($row['user_digest_last_sent'] + 7 * 60 * 60 * 24 > $now) {
                        continue;
                    }
                    break;
                case constants::DIGESTS_MONTHLY_VALUE:
                    // Calculate seconds in previous month, which depends on number of days in that month
                    $use_year = date($now, 'Y');
                    $use_month = date($now, 'n') - 1;
                    if ($use_month == 0) {
                        $use_month = 12;
                        $use_year--;
                    }
                    $use_days_in_month = cal_days_in_month(CAL_GREGORIAN, $use_month, $use_year);
                    if ($row['user_digest_last_sent'] + $use_days_in_month * 60 * 60 * 24 > $now) {
                        continue;
                    }
                    break;
                default:
                    // Shouldn't happen but assume a daily digest if it did happen
                    if ($row['user_digest_last_sent'] + 60 * 60 * 24 > $now) {
                        continue;
                    }
                    break;
            }
            $this->toc = array();
            // Create or empty the array containing table of contents information
            $this->toc_post_count = 0;
            // # of posts in the table of contents
            $this->toc_pm_count = 0;
            // # of private messages in the table of contents
            $html_messenger = new \phpbbservices\digests\includes\html_messenger();
            // Set the text showing the digest type
            switch ($row['user_digest_type']) {
                case constants::DIGESTS_DAILY_VALUE:
                    $digest_type = $this->user->lang['DIGESTS_DAILY'];
                    break;
                case constants::DIGESTS_WEEKLY_VALUE:
                    $digest_type = $this->user->lang['DIGESTS_WEEKLY'];
                    break;
                case constants::DIGESTS_MONTHLY_VALUE:
                    $digest_type = $this->user->lang['DIGESTS_MONTHLY'];
                    break;
                default:
                    // The database may be corrupted if the digest type for a subscriber is invalid.
                    // Write an error to the log and continue to the next subscriber.
                    $digest_type = '';
                    // Make PhpStorm happy
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_BAD_DIGEST_TYPE', false, array($row['user_digest_type'], $row['username']));
                    continue;
                    break;
            }
            $email_subject = $this->user->lang('DIGESTS_SUBJECT_TITLE', $this->config['sitename'], $digest_type);
            // Set various variables and flags based on the requested digest format. Note: will always use the British English email template because it's the
            // only one provided with the extension and it is effectively language neutral since it renders HTML and CSS only. There are no English words
            // in the templates.
            switch ($row['user_digest_format']) {
                case constants::DIGESTS_TEXT_VALUE:
                    $format = $this->user->lang['DIGESTS_FORMAT_TEXT'];
                    $html_messenger->template('digests_text', '', $this->email_templates_path);
                    $is_html = false;
                    $disclaimer = str_replace('&apos;', "'", html_entity_decode(strip_tags($this->user->lang('DIGESTS_DISCLAIMER', $this->board_url, $this->config['sitename'], $this->board_url, $this->phpEx, $this->config['board_contact'], $this->config['sitename']))));
                    $powered_by = $this->config['phpbbservices_digests_host'];
                    $this->layout_with_html_tables = false;
                    break;
                case constants::DIGESTS_PLAIN_VALUE:
                    $format = $this->user->lang['DIGESTS_FORMAT_PLAIN'];
                    $html_messenger->template('digests_plain_html', '', $this->email_templates_path);
                    $is_html = true;
                    $disclaimer = $this->user->lang('DIGESTS_DISCLAIMER', $this->board_url, $this->config['sitename'], $this->board_url, $this->phpEx, $this->config['board_contact'], $this->config['sitename']);
                    $powered_by = sprintf("<a href=\"%s\">%s</a>", $this->config['phpbbservices_digests_page_url'], $this->config['phpbbservices_digests_host']);
                    $this->layout_with_html_tables = false;
                    break;
                case constants::DIGESTS_PLAIN_CLASSIC_VALUE:
                    $format = $this->user->lang['DIGESTS_FORMAT_PLAIN_CLASSIC'];
                    $html_messenger->template('digests_plain_html', '', $this->email_templates_path);
                    $is_html = true;
                    $disclaimer = $this->user->lang('DIGESTS_DISCLAIMER', $this->board_url, $this->config['sitename'], $this->board_url, $this->phpEx, $this->config['board_contact'], $this->config['sitename']);
                    $powered_by = sprintf("<a href=\"%s\">%s</a>", $this->config['phpbbservices_digests_page_url'], $this->config['phpbbservices_digests_host']);
                    $this->layout_with_html_tables = true;
                    break;
                case constants::DIGESTS_HTML_VALUE:
                    $format = $this->user->lang['DIGESTS_FORMAT_HTML'];
                    $html_messenger->template('digests_html', '', $this->email_templates_path);
                    $is_html = true;
                    $disclaimer = $this->user->lang('DIGESTS_DISCLAIMER', $this->board_url, $this->config['sitename'], $this->board_url, $this->phpEx, $this->config['board_contact'], $this->config['sitename']);
                    $powered_by = sprintf("<a href=\"%s\">%s</a>", $this->config['phpbbservices_digests_page_url'], $this->config['phpbbservices_digests_host']);
                    $this->layout_with_html_tables = false;
                    break;
                case constants::DIGESTS_HTML_CLASSIC_VALUE:
                    $format = $this->user->lang['DIGESTS_FORMAT_HTML_CLASSIC'];
                    $html_messenger->template('digests_html', '', $this->email_templates_path);
                    $is_html = true;
                    $disclaimer = $this->user->lang('DIGESTS_DISCLAIMER', $this->board_url, $this->config['sitename'], $this->board_url, $this->phpEx, $this->config['board_contact'], $this->config['sitename']);
                    $powered_by = sprintf("<a href=\"%s\">%s</a>", $this->config['phpbbservices_digests_page_url'], $this->config['phpbbservices_digests_host']);
                    $this->layout_with_html_tables = true;
                    break;
                default:
                    // The database may be corrupted if the digest format for a subscriber is invalid.
                    // Write an error to the log and continue to the next subscriber.
                    $format = '';
                    // Keep PhpStorm happy
                    $is_html = false;
                    // Keep PhpStorm happy
                    $disclaimer = '';
                    // Keep PhpStorm happy
                    $powered_by = '';
                    // Keep PhpStorm happy
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_FORMAT_ERROR', false, array($row['user_digest_type'], $row['username']));
                    continue;
                    break;
            }
            // Set email header information
            $from_field_email = isset($this->config['phpbbservices_digests_from_email_address']) && strlen($this->config['phpbbservices_digests_from_email_address']) > 0 ? $this->config['phpbbservices_digests_from_email_address'] : $this->config['board_email'];
            $from_field_name = isset($this->config['phpbbservices_digests_from_email_name']) && strlen($this->config['phpbbservices_digests_from_email_name']) > 0 ? $this->config['phpbbservices_digests_from_email_name'] : $this->config['sitename'] . ' ' . $this->user->lang['DIGESTS_ROBOT'];
            $reply_to_field_email = isset($this->config['phpbbservices_digests_reply_to_email_address']) && strlen($this->config['phpbbservices_digests_reply_to_email_address']) > 0 ? $this->config['phpbbservices_digests_reply_to_email_address'] : $this->config['board_email'];
            // Admin may override where email is sent in manual mode. This won't apply if digests are stored to the store/phpbbservices/digests folder instead.
            if ($this->manual_mode && $this->config['phpbbservices_digests_test_send_to_admin']) {
                $html_messenger->to($this->email_address_override);
            } else {
                $html_messenger->to($row['user_email']);
            }
            // SMTP delivery must strip text names due to likely bug in messenger class
            if ($this->config['smtp_delivery']) {
                $html_messenger->from($from_field_email);
            } else {
                if (trim($from_field_name) !== '') {
                    $html_messenger->from(mail_encode(htmlspecialchars_decode($from_field_name)) . ' <' . $from_field_email . '>');
                } else {
                    $html_messenger->from($from_field_email);
                }
            }
            $html_messenger->replyto($reply_to_field_email);
            $html_messenger->subject($email_subject);
            // Transform user_digest_send_hour_gmt to the subscriber's local time
            $local_send_hour = $row['user_digest_send_hour_gmt'] + (int) $this->helper->make_tz_offset($row['user_timezone'], $row['username']);
            if ($local_send_hour >= 24) {
                $local_send_hour = $local_send_hour - 24;
            } else {
                if ($local_send_hour < 0) {
                    $local_send_hour = $local_send_hour + 24;
                }
            }
            if ($local_send_hour >= 24 || $local_send_hour < 0) {
                // The database may be corrupted if the local send hour for a subscriber is still not between 0 and 23.
                // Write an error to the log and continue to the next subscriber.
                $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_BAD_SEND_HOUR', false, array($row['user_digest_type'], $row['user_digest_send_hour_gmt']));
                continue;
            }
            // Change the filter type into something human readable
            switch ($row['user_digest_filter_type']) {
                case constants::DIGESTS_ALL:
                    $post_types = $this->user->lang['DIGESTS_POSTS_TYPE_ANY'];
                    break;
                case constants::DIGESTS_FIRST:
                    $post_types = $this->user->lang['DIGESTS_POSTS_TYPE_FIRST'];
                    break;
                case constants::DIGESTS_BOOKMARKS:
                    $post_types = $this->user->lang['DIGESTS_USE_BOOKMARKS'];
                    break;
                default:
                    // The database may be corrupted if the filter type for a subscriber is incorrect.
                    // Write an error to the log and continue to the next subscriber.
                    $post_types = '';
                    // Keep PhpStorm happy
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_FILTER_ERROR', false, array($row['user_digest_filter_type'], $row['username']));
                    continue;
                    break;
            }
            // Change the sort by into something human readable
            switch ($row['user_digest_sortby']) {
                case constants::DIGESTS_SORTBY_BOARD:
                    $sort_by = $this->user->lang['DIGESTS_SORT_USER_ORDER'];
                    break;
                case constants::DIGESTS_SORTBY_STANDARD:
                    $sort_by = $this->user->lang['DIGESTS_SORT_FORUM_TOPIC'];
                    break;
                case constants::DIGESTS_SORTBY_STANDARD_DESC:
                    $sort_by = $this->user->lang['DIGESTS_SORT_FORUM_TOPIC_DESC'];
                    break;
                case constants::DIGESTS_SORTBY_POSTDATE:
                    $sort_by = $this->user->lang['DIGESTS_SORT_POST_DATE'];
                    break;
                case constants::DIGESTS_SORTBY_POSTDATE_DESC:
                    $sort_by = $this->user->lang['DIGESTS_SORT_POST_DATE_DESC'];
                    break;
                default:
                    // The database may be corrupted if the digest sort by for a subscriber is incorrect.
                    // Write an error to the log and continue to the next subscriber.
                    $sort_by = '';
                    // Make PhpStorm happy
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_SORT_BY_ERROR', false, array($row['user_digest_sortby'], $row['username']));
                    continue;
                    break;
            }
            // Send a proper content-language to the output
            $user_lang = $row['user_lang'];
            if (strpos($user_lang, '-x-') !== false) {
                $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-'));
            }
            // Create proper message indicating number of posts allowed in digest and set a value for the maximum posts allowed in this digest
            if ($row['user_digest_max_posts'] == 0 && $this->config['phpbbservices_digests_max_items'] == 0) {
                $this->max_posts = 0;
                // 0 means no limit
                $max_posts_msg = $this->user->lang['DIGESTS_NO_LIMIT'];
            } else {
                if ($this->config['phpbbservices_digests_max_items'] != 0 && $this->config['phpbbservices_digests_max_items'] < $row['user_digest_max_posts']) {
                    $this->max_posts = (int) $row['phpbbservices_digests_max_items'];
                    $max_posts_msg = $this->user->lang('DIGESTS_BOARD_LIMIT', $this->config['phpbbservices_digests_max_items']);
                } else {
                    $this->max_posts = (int) $row['user_digest_max_posts'];
                    $max_posts_msg = $row['user_digest_max_posts'];
                }
            }
            $recipient_time = $this->gmt_time + (int) ($this->helper->make_tz_offset($row['user_timezone']) * 60 * 60);
            // Print the non-post and non-private message information in the digest. The actual posts and private messages require the full templating system,
            // because the messenger class is too dumb to do more than basic templating. Note: most language variables are handled automatically by the templating
            // system.
            $html_messenger->assign_vars(array('DIGESTS_BLOCK_IMAGES' => $row['user_digest_block_images'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_COUNT_LIMIT' => $max_posts_msg, 'DIGESTS_DISCLAIMER' => $disclaimer, 'DIGESTS_FILTER_FOES' => $row['user_digest_remove_foes'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_FILTER_TYPE' => $post_types, 'DIGESTS_FORMAT_FOOTER' => $format, 'DIGESTS_LASTVISIT_RESET' => $row['user_digest_reset_lastvisit'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_MAIL_FREQUENCY' => $digest_type, 'DIGESTS_MAX_SIZE' => $row['user_digest_max_display_words'] == 0 ? $this->user->lang['DIGESTS_NO_POST_TEXT'] : ($row['user_digest_max_display_words'] == -1 ? $this->user->lang['DIGESTS_NO_LIMIT'] : $row['user_digest_max_display_words']), 'DIGESTS_MIN_SIZE' => $row['user_digest_min_words'] == 0 ? $this->user->lang['DIGESTS_NO_CONSTRAINT'] : $row['user_digest_min_words'], 'DIGESTS_NO_POST_TEXT' => $row['user_digest_no_post_text'] == 1 ? $this->user->lang['YES'] : $this->user->lang['NO'], 'DIGESTS_POWERED_BY' => $powered_by, 'DIGESTS_REMOVE_YOURS' => $row['user_digest_show_mine'] == 0 ? $this->user->lang['YES'] : $this->user->lang['NO'], 'DIGESTS_SALUTATION' => $row['username'], 'DIGESTS_SEND_HOUR' => $this->helper->make_hour_string($local_send_hour, $row['user_dateformat']), 'DIGESTS_SEND_IF_NO_NEW_MESSAGES' => $row['user_digest_send_on_no_posts'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_SHOW_ATTACHMENTS' => $row['user_digest_attachments'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_SHOW_NEW_POSTS_ONLY' => $row['user_digest_new_posts_only'] == 1 ? $this->user->lang['YES'] : $this->user->lang['NO'], 'DIGESTS_SHOW_PMS' => $row['user_digest_show_pms'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_SORT_BY' => $sort_by, 'DIGESTS_TOC_YES_NO' => $row['user_digest_toc'] == 0 ? $this->user->lang['NO'] : $this->user->lang['YES'], 'DIGESTS_VERSION' => $this->config['phpbbservices_digests_version'], 'L_DIGESTS_INTRODUCTION' => $this->user->lang('DIGESTS_INTRODUCTION', $this->config['sitename']), 'L_DIGESTS_PUBLISH_DATE' => $this->user->lang('DIGESTS_PUBLISH_DATE', $row['username'], date(str_replace('|', '', $row['user_dateformat']), $recipient_time)), 'L_DIGESTS_TITLE' => $email_subject, 'L_DIGESTS_YOUR_DIGEST_OPTIONS' => $is_html ? $this->user->lang('DIGESTS_YOUR_DIGEST_OPTIONS', $row['username']) : str_replace('&apos;', "'", $this->user->lang('DIGESTS_YOUR_DIGEST_OPTIONS', $row['username'])), 'S_CONTENT_DIRECTION' => $this->user->lang['DIRECTION'], 'S_USER_LANG' => $user_lang, 'T_STYLESHEET_LINK' => $this->config['phpbbservices_digests_enable_custom_stylesheets'] ? "{$this->board_url}styles/" . $this->config['phpbbservices_digests_custom_stylesheet_path'] : "{$this->board_url}styles/" . $row['style_path'] . '/theme/stylesheet.css', 'T_THEME_PATH' => "{$this->board_url}styles/" . $row['style_path'] . '/theme'));
            // Get any private messages for this user
            $this->digest_exception = false;
            // Count # of unread and new for this user. Counts may need to be reduced later.
            $total_pm_unread = 0;
            $total_pm_new = 0;
            if ($row['user_digest_show_pms']) {
                $sql_array = array('SELECT' => '*', 'FROM' => array(PRIVMSGS_TO_TABLE => 'pt', PRIVMSGS_TABLE => 'pm', USERS_TABLE => 'u'), 'WHERE' => 'pt.msg_id = pm.msg_id
										AND pt.author_id = u.user_id
										AND pt.user_id = ' . $row['user_id'] . '
										AND (pm_unread = 1 OR pm_new = 1)', 'ORDER_BY' => 'message_time');
                $pm_sql = $this->db->sql_build_query('SELECT', $sql_array);
                $pm_result = $this->db->sql_query($pm_sql);
                $pm_rowset = $this->db->sql_fetchrowset($pm_result);
                $this->db->sql_freeresult();
                foreach ($pm_rowset as $pm_row) {
                    if ($pm_row['pm_unread'] == 1) {
                        $total_pm_unread++;
                    }
                    if ($pm_row['pm_new'] == 1) {
                        $total_pm_new++;
                    }
                }
            } else {
                // Avoid some PHP Notices...
                $pm_result = NULL;
                $pm_rowset = NULL;
            }
            // Construct the body of the digest. We use the templating system because of the advanced features missing in the
            // email templating system, e.g. loops and switches. Note: create_content may set the flag $this->digest_exception.
            $digest_content = $this->create_content($rowset_posts, $pm_rowset, $row, $is_html);
            // List the subscribed forums, if any
            if ($row['user_digest_filter_type'] == constants::DIGESTS_BOOKMARKS) {
                $subscribed_forums = $this->user->lang['DIGESTS_USE_BOOKMARKS'];
            } else {
                if (sizeof($this->requested_forums_names) > 0) {
                    $subscribed_forums = implode(', ', $this->requested_forums_names);
                } else {
                    // Show that all forums were selected
                    $subscribed_forums = $this->user->lang['DIGESTS_ALL_FORUMS'];
                }
            }
            // Assemble a digest table of contents
            if ($row['user_digest_toc'] == 1) {
                // Create Table of Contents header for private messages
                if ($is_html) {
                    // For HTML digests, the table of contents always appears in a HTML table
                    $digest_toc = "<h2 style=\"color:#000000\">" . $this->user->lang['DIGESTS_TOC'] . "</h2>\n";
                    $digest_toc .= "<p><a href=\"#skip\">" . $this->user->lang['DIGESTS_SKIP'] . "</a></p>\n";
                } else {
                    $digest_toc = "____________________________________________________________\n\n" . $this->user->lang['DIGESTS_TOC'] . "\n\n";
                }
                if ($row['user_digest_show_pms'] == 1) {
                    // Heading for table of contents
                    if ($is_html) {
                        $digest_toc .= sprintf("<div class=\"content\"><table>\n<tbody>\n<tr>\n<th id=\"j1\">%s</th><th id=\"j2\">%s</th><th id=\"j3\">%s</th><th id=\"j4\">%s</th>\n</tr>\n", $this->user->lang['DIGESTS_JUMP_TO_MSG'], ucwords($this->user->lang['PRIVATE_MESSAGE'] . ' ' . $this->user->lang['SUBJECT']), $this->user->lang['DIGESTS_SENDER'], $this->user->lang['DIGESTS_DATE']);
                    }
                    // Add a table row for each private message
                    if ($this->toc_pm_count > 0) {
                        for ($i = 0; $i <= $this->toc_pm_count; $i++) {
                            if ($is_html) {
                                $digest_toc .= isset($this->toc['pms'][$i]) ? "<tr>\n<td headers=\"j1\" style=\"text-align: center;\"><a href=\"#m" . $this->toc['pms'][$i]['message_id'] . '">' . $this->toc['pms'][$i]['message_id'] . '</a></td><td headers="j2">' . $this->toc['pms'][$i]['message_subject'] . '</td><td headers="j3">' . $this->toc['pms'][$i]['author'] . '</td><td headers="j4">' . $this->toc['pms'][$i]['datetime'] . "</td>\n</tr>\n" : '';
                            } else {
                                $digest_toc .= isset($this->toc['pms'][$i]) ? $this->toc['pms'][$i]['author'] . ' ' . $this->user->lang['DIGESTS_SENT_YOU_A_MESSAGE'] . ' ' . $this->user->lang['DIGESTS_OPEN_QUOTE'] . $this->toc['pms'][$i]['message_subject'] . $this->user->lang['DIGESTS_CLOSED_QUOTE'] . ' ' . $this->user->lang['DIGESTS_ON'] . ' ' . $this->toc['pms'][$i]['datetime'] . "\n" : '';
                            }
                        }
                    } else {
                        $digest_toc .= $is_html ? '<tr><td colspan="4">' . $this->user->lang['DIGESTS_NO_PRIVATE_MESSAGES'] . "</td></tr>" : ($digest_toc = $this->user->lang['DIGESTS_NO_PRIVATE_MESSAGES']);
                    }
                    // Create Table of Contents footer for private messages
                    $digest_toc .= $is_html ? "</tbody></table>\n<br />" : "\n";
                } else {
                    $digest_toc = null;
                    // Avoid a PHP Notice
                }
                // Create Table of Contents header for posts
                if ($is_html) {
                    // For HTML digests, the table of contents always appears in a HTML table
                    $digest_toc .= sprintf("<table>\n<tbody>\n<tr>\n<th id=\"h1\">%s</th><th id=\"h2\">%s</th><th id=\"h3\">%s</th><th id=\"h4\">%s</th><th id=\"h5\">%s</th>\n</tr>\n", $this->user->lang['DIGESTS_JUMP_TO_POST'], $this->user->lang['FORUM'], $this->user->lang['TOPIC'], $this->user->lang['AUTHOR'], $this->user->lang['DIGESTS_DATE']);
                }
                // Add a table row for each post
                if ($this->toc_post_count > 0) {
                    for ($i = 0; $i <= $this->toc_post_count; $i++) {
                        if ($is_html) {
                            $digest_toc .= isset($this->toc['posts'][$i]) ? "<tr>\n<td headers=\"h1\" style=\"text-align: center;\"><a href=\"#p" . $this->toc['posts'][$i]['post_id'] . '">' . $this->toc['posts'][$i]['post_id'] . '</a></td><td headers="h2">' . $this->toc['posts'][$i]['forum'] . '</td><td headers="h3">' . $this->toc['posts'][$i]['topic'] . '</td><td headers="h4">' . $this->toc['posts'][$i]['author'] . '</td><td headers="h5">' . $this->toc['posts'][$i]['datetime'] . "</td>\n</tr>\n" : '';
                        } else {
                            $digest_toc .= isset($this->toc['posts'][$i]) ? $this->toc['posts'][$i]['author'] . ' ' . $this->user->lang['DIGESTS_POSTED_TO_THE_TOPIC'] . ' ' . $this->user->lang['DIGESTS_OPEN_QUOTE'] . $this->toc['posts'][$i]['topic'] . $this->user->lang['DIGESTS_CLOSED_QUOTE'] . ' ' . $this->user->lang['IN'] . ' ' . $this->user->lang['DIGESTS_OPEN_QUOTE'] . $this->toc['posts'][$i]['forum'] . $this->user->lang['DIGESTS_CLOSED_QUOTE'] . ' ' . $this->user->lang['DIGESTS_ON'] . ' ' . $this->toc['posts'][$i]['datetime'] . "\n" : '';
                        }
                    }
                } else {
                    $no_posts_msg = $row['user_digest_filter_type'] == constants::DIGESTS_BOOKMARKS ? $this->user->lang['DIGESTS_NO_BOOKMARKED_POSTS'] : $this->user->lang['DIGESTS_NO_POSTS'];
                    $digest_toc .= $is_html ? '<tr><td colspan="5">' . $no_posts_msg . "</td></tr>" : $no_posts_msg;
                }
                // Create Table of Contents footer for posts
                $digest_toc .= $is_html ? "</tbody>\n</table></div>\n<br />" : '';
                // Publish the table of contents
                $html_messenger->assign_vars(array('DIGESTS_TOC' => $digest_toc));
            } else {
                $digest_toc = null;
                // Avoid a PHP Notice
            }
            if (!$is_html) {
                // This reduces extra lines in the text digests. Apparently the phpBB template engine leaves
                // blank lines where a template contains templates commands.
                $digest_content = str_replace("\n\n", "\n", $digest_content);
            }
            // Publish the digest content, marshaled elsewhere and a list of the forums subscribed to.
            $html_messenger->assign_vars(array('DIGESTS_CONTENT' => $digest_content, 'DIGESTS_FORUMS_WANTED' => $subscribed_forums));
            // Mark private messages in the digest as read, if so instructed
            if (sizeof($pm_rowset) != 0 && $row['user_digest_show_pms'] == 1 && $row['user_digest_pm_mark_read'] == 1) {
                $sql_ary = array('pm_new' => 0, 'pm_unread' => 0, 'folder_id' => 0);
                $pm_read_sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
					WHERE user_id = ' . $row['user_id'] . '
						AND (pm_unread = 1 OR pm_new = 1)';
                $this->db->sql_query($pm_read_sql);
                // Decrement the user_unread_privmsg and user_new_privmsg count
                $sql_ary = array('user_unread_privmsg' => 'user_unread_privmsg - ' . $total_pm_unread, 'user_new_privmsg' => 'user_new_privmsg - ' . $total_pm_new);
                $pm_read_sql = 'UPDATE ' . USERS_TABLE . '
					SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
					WHERE user_id = ' . $row['user_id'];
                $this->db->sql_query($pm_read_sql);
            }
            $this->db->sql_freeresult($result_posts);
            $this->db->sql_freeresult($pm_result);
            if ($this->manual_mode && $this->config['phpbbservices_digests_test_spool']) {
                // To grab the content of the email (less mail headers) first run the mailer with the $break parameter set to true. This will keep
                // the mail from being sent out. The function won't fail since nothing is being sent out.
                $html_messenger->send(NOTIFY_EMAIL, true, $is_html, true);
                $email_content = $html_messenger->msg;
                // Save digests as file in the store/phpbbservices/digests folder instead of emailing.
                $suffix = $is_html ? '.html' : '.txt';
                $file_name = $row['username'] . '-' . $gmt_year . '-' . str_pad($gmt_month, 2, '0', STR_PAD_LEFT) . '-' . str_pad($gmt_day, 2, '0', STR_PAD_LEFT) . '-' . str_pad($gmt_hour, 2, '0', STR_PAD_LEFT) . $suffix;
                $handle = @fopen($this->cache_path . $file_name, "w");
                if ($handle === false) {
                    // Since this indicates a major problem, let's abort now. It's likely a global write error.
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_FILE_OPEN_ERROR', false, array($this->cache_path));
                    if ($this->config['phpbbservices_digests_enable_log']) {
                        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_END');
                    }
                    return false;
                }
                $success = @fwrite($handle, htmlspecialchars_decode($email_content));
                if ($success === false) {
                    // Since this indicates a major problem, let's abort now.  It's likely a global write error.
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_FILE_WRITE_ERROR', false, array($this->cache_path . $file_name));
                    if ($this->config['phpbbservices_digests_enable_log']) {
                        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_END');
                    }
                    return false;
                }
                $success = @fclose($handle);
                if ($success === false) {
                    // Since this indicates a major problem, let's abort now
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_FILE_CLOSE_ERROR', false, array($this->cache_path . $file_name));
                    if ($this->config['phpbbservices_digests_enable_log']) {
                        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_END');
                    }
                    return false;
                }
                // Note in the log that digest was written to disk
                if ($this->config['phpbbservices_digests_enable_log']) {
                    $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_GOOD_DISK', false, array($file_name));
                }
            } else {
                // Send the digest out only if there are new qualifying posts OR the user requests a digest to be sent if there are no posts OR
                // if there are unread private messages AND the user wants to see private messages in the digest.
                // Try to send this digest
                if ($row['user_digest_send_on_no_posts'] || $this->toc_post_count > 0 || sizeof($pm_rowset) > 0 && $row['user_digest_show_pms']) {
                    $mail_sent = $html_messenger->send(NOTIFY_EMAIL, false, $is_html, true);
                    if (!$mail_sent) {
                        if ($this->config['phpbbservices_digests_show_email']) {
                            $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_BAD', false, array($row['username'], $row['user_email']));
                        } else {
                            $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_BAD_NO_EMAIL', false, array($row['username']));
                        }
                        $run_successful = false;
                    } else {
                        if ($this->config['phpbbservices_digests_enable_log']) {
                            if ($this->config['phpbbservices_digests_show_email']) {
                                $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_GOOD', false, array($this->user->lang['DIGESTS_SENT_TO'], $row['username'], $row['user_email'], $gmt_year . '-' . $gmt_month . '-' . $gmt_day, $current_hour_gmt, $this->posts_in_digest, sizeof($pm_rowset)));
                            } else {
                                $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_GOOD_NO_EMAIL', false, array($this->user->lang['DIGESTS_SENT_TO'], $row['username'], $gmt_year . '-' . $gmt_month . '-' . $gmt_day, $current_hour_gmt, $this->posts_in_digest, sizeof($pm_rowset)));
                            }
                        }
                        $sql_ary = array('user_digest_last_sent' => time());
                        $sql2 = 'UPDATE ' . USERS_TABLE . '
							SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
							WHERE user_id = ' . $row['user_id'];
                        $this->db->sql_query($sql2);
                        // If requested, update user_lastvisit
                        if ($row['user_digest_reset_lastvisit'] == 1) {
                            $sql_ary = array('user_lastvisit' => time());
                            $sql2 = 'UPDATE ' . USERS_TABLE . '
								SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
								WHERE user_id = ' . $row['user_id'];
                            $this->db->sql_query($sql2);
                        }
                    }
                } else {
                    // Don't send a digest, the user doesn't want one because there are no qualifying posts
                    if ($this->config['phpbbservices_digests_show_email']) {
                        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_NONE', false, array($row['username'], $row['user_email']));
                    } else {
                        $this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_DIGESTS_LOG_ENTRY_NONE_NO_EMAIL', false, array($row['username']));
                    }
                }
            }
            // Reset messenger object, bug fix provided by robdocmagic
            $html_messenger->reset();
        }
        // foreach
        if ($this->digest_exception) {
            // Digest exception errors are handled by create_content but we do want to note that something odd occurred to let the calling program know
            // after all digests for the hour are sent.
            $run_successful = false;
        }
        return $run_successful;
    }
 function msg_email()
 {
     global $config, $_CLASS;
     if (empty($config['email_enable'])) {
         return false;
     }
     $use_queue = false;
     if ($config['email_package_size'] && $this->use_queue) {
         if (empty($this->queue)) {
             $this->queue = new queue();
             $this->queue->init('email', $config['email_package_size']);
         }
         $use_queue = true;
     }
     $to = $cc = $bcc = '';
     // Build to, cc and bcc strings
     foreach ($this->addresses as $type => $address_ary) {
         if ($type == 'im') {
             continue;
         }
         foreach ($address_ary as $which_ary) {
             ${$type} .= (${$type} != '' ? ', ' : '') . ($which_ary['name'] != '' ? '"' . mail_encode($which_ary['name'], $this->encoding) . '" <' . $which_ary['email'] . '>' : $which_ary['email']);
         }
     }
     if (empty($this->replyto)) {
         $this->replyto = '<' . $config['board_email'] . '>';
     }
     if (empty($this->from)) {
         $this->from = '<' . $config['board_email'] . '>';
     }
     // Build header
     $headers = 'From: ' . $this->from . "\n";
     $headers .= $cc != '' ? "Cc: {$cc}\n" : '';
     $headers .= $bcc != '' ? "Bcc: {$bcc}\n" : '';
     $headers .= 'Reply-to: ' . $this->replyto . "\n";
     $headers .= 'Return-Path: <' . $config['board_email'] . ">\n";
     $headers .= 'Sender: <' . $config['board_email'] . ">\n";
     $headers .= "MIME-Version: 1.0\n";
     $headers .= 'Message-ID: <' . md5(uniqid(time())) . "@" . $config['server_name'] . ">\n";
     $headers .= 'Date: ' . gmdate('D, d M Y H:i:s T', time()) . "\n";
     $headers .= "Content-type: text/plain; charset={$this->encoding}\n";
     $headers .= "Content-transfer-encoding: 8bit\n";
     $headers .= "X-Priority: {$this->mail_priority}\n";
     $headers .= 'X-MSMail-Priority: ' . ($this->mail_priority == MAIL_LOW_PRIORITY ? 'Low' : ($this->mail_priority == MAIL_NORMAL_PRIORITY ? 'Normal' : 'High')) . "\n";
     $headers .= "X-Mailer: PhpBB\n";
     $headers .= "X-MimeOLE: phpBB\n";
     $headers .= "X-phpBB-Origin: phpbb://" . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()) . "\n";
     $headers .= $this->extra_headers != '' ? $this->extra_headers : '';
     // Send message ... removed $this->encode() from subject for time being
     if (!$use_queue) {
         $mail_to = $to == '' ? 'Undisclosed-Recipient:;' : $to;
         $err_msg = '';
         $result = $config['smtp_delivery'] ? smtpmail($this->addresses, $this->subject, wordwrap($this->msg), $err_msg, $this->encoding, $headers) : @$config['email_function_name']($mail_to, $this->subject, implode("\n", preg_split("/\r?\n/", wordwrap($this->msg))), $headers);
         if (!$result) {
             $message = '<u>EMAIL ERROR</u> [ ' . ($config['smtp_delivery'] ? 'SMTP' : 'PHP') . ' ]<br /><br />' . $err_msg . '<br /><br /><u>CALLING PAGE</u><br /><br />' . (!empty($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']) . '<br />';
             $this->error('EMAIL', $message);
             return false;
         }
     } else {
         $this->queue->put('email', array('to' => $to, 'addresses' => $this->addresses, 'subject' => $this->subject, 'msg' => $this->msg, 'encoding' => $this->encoding, 'headers' => $headers));
     }
     return true;
 }
Ejemplo n.º 10
0
     foreach ($data[attachment_data] as $filename) {
         $message .= "  " . print_r($filename, 1) . "\n";
     }
     $message .= "\n";
 }
 // add signature
 if ($n2m_SHOW_SIG) {
     if ($mode != "edit") {
         if ($user->data[user_sig] and $data[enable_sig]) {
             $message .= "\nSignature:\n  ";
             $message .= generate_text_for_edit($user->data[user_sig], $user->data[user_sig_bbcode_uid], $post_data[forum_desc_options])["text"] . "\n\n";
         }
     }
 }
 // encode subject
 $subject = mail_encode(html_entity_decode($n2m_SUBJECT));
 // convert all addresses to lowercase and delete any empty addresses
 foreach ($n2m_MAILTO as $key => $value) {
     if (is_null($value) or $value == "") {
         unset($n2m_MAILTO[$key]);
     } else {
         $n2m_MAILTO[$key] = strtolower($n2m_MAILTO[$key]);
     }
 }
 // insure that every address is only used once
 $n2m_MAILTO = array_unique($n2m_MAILTO);
 // Testversion, Mails an Author des Artikels verhindern
 // unset($n2m_MAILTO[array_search($user->data['user_email'], $n2m_MAILTO)]);
 // die($message); // for debugging purposes, mail will be shown in browser and not sent out if we uncomment this line
 // make text "flow" in plain/text
 $temp = $message;