Example #1
0
/**
 * Resize an image to the specified size, but retain the aspect ratio.
 *
 * @param  URLPATH		The URL to the image to resize
 * @param  PATH			The file path (including filename) to where the resized image will be saved
 * @param  integer		The maximum width we want our new image to be (-1 means "don't factor this in")
 * @param  integer		The maximum height we want our new image to be (-1 means "don't factor this in")
 * @param  integer		This is only considered if both $width and $height are -1. If set, it will fit the image to a box of this dimension (suited for resizing both landscape and portraits fairly)
 * @param  boolean		Whether to exit ocPortal if an error occurs
 * @param  ?string		The file extension to save with (NULL: same as our input file)
 * @param  boolean		Whether $from was in fact a path, not a URL
 * @param  boolean		Whether to apply a 'never make the image bigger' rule for thumbnail creation (would affect very small images)
 * @param  ?array			This optional parameter allows us to specify cropping or padding for the image. See comments in the function. (NULL: no details passed)
 * @return boolean		Success
 */
function convert_image($from, $to, $width, $height, $box_width = -1, $exit_on_error = true, $ext2 = NULL, $using_path = false, $only_make_smaller = false, $thumb_options = NULL)
{
    disable_php_memory_limit();
    // Load
    $ext = get_file_extension($from);
    if ($using_path) {
        if (!check_memory_limit_for($from, $exit_on_error)) {
            return false;
        }
        $from_file = @file_get_contents($from);
    } else {
        $file_path_stub = convert_url_to_path($from);
        if (!is_null($file_path_stub)) {
            if (!check_memory_limit_for($file_path_stub, $exit_on_error)) {
                return false;
            }
            $from_file = @file_get_contents($file_path_stub);
        } else {
            $from_file = http_download_file($from, 1024 * 1024 * 20, false);
            if (is_null($from_file)) {
                $from_file = false;
            }
        }
    }
    if ($from_file === false) {
        if ($exit_on_error) {
            warn_exit(do_lang_tempcode('UPLOAD_PERMISSION_ERROR', escape_html($from)));
        }
        require_code('site');
        if (!file_exists(get_custom_file_base() . '/uploads/missing_ok')) {
            attach_message(do_lang_tempcode('UPLOAD_PERMISSION_ERROR', escape_html($from)), 'warn');
        }
        return false;
    }
    $source = @imagecreatefromstring($from_file);
    if (!is_null($thumb_options) || !$only_make_smaller) {
        unset($from_file);
    }
    if ($source === false) {
        if ($exit_on_error) {
            warn_exit(do_lang_tempcode('CORRUPT_FILE', escape_html($from)));
        }
        require_code('site');
        attach_message(do_lang_tempcode('CORRUPT_FILE', escape_html($from)), 'warn');
        return false;
    }
    // Derive actual width x height, for the given maximum box (maintain aspect ratio)
    // ===============================================================================
    $sx = imagesx($source);
    $sy = imagesy($source);
    $red = NULL;
    if (is_null($thumb_options)) {
        if ($width == 0) {
            $width = 1;
        }
        if ($height == 0) {
            $height = 1;
        }
        // If we're not sure if this is gonna stretch to fit a width or stretch to fit a height
        if ($width == -1 && $height == -1) {
            if ($sx > $sy) {
                $width = $box_width;
            } else {
                $height = $box_width;
            }
        }
        if ($width != -1 && $height != -1) {
            if (floatval($sx) / floatval($width) > floatval($sy) / floatval($height)) {
                $_width = $width;
                $_height = intval($sy * ($width / $sx));
            } else {
                $_height = $height;
                $_width = intval($sx * ($height / $sy));
            }
        } elseif ($height == -1) {
            $_width = $width;
            $_height = intval($width / ($sx / $sy));
        } elseif ($width == -1) {
            $_height = $height;
            $_width = intval($height / ($sy / $sx));
        }
        if ($_width > $sx && $only_make_smaller) {
            $_width = $sx;
            $_height = $sy;
            // We can just escape, nothing to do
            imagedestroy($source);
            if ($using_path && $from == $to) {
                return true;
            }
            if ($using_path) {
                copy($from, $to);
            } else {
                $_to = @fopen($to, 'wb') or intelligent_write_error($to);
                fwrite($_to, $from_file);
                fclose($_to);
            }
            fix_permissions($to);
            sync_file($to);
            return true;
        }
        if ($_width < 1) {
            $_width = 1;
        }
        if ($_height < 1) {
            $_height = 1;
        }
        // Pad out options for imagecopyresized
        // $dst_im,$src_im,$dst_x,$dst_y,$src_x,$src_y,$dst_w,$dst_h,$src_w,$src_h
        $dest_x = 0;
        $dest_y = 0;
        $source_x = 0;
        $source_y = 0;
    } else {
        // Thumbnail-specific (for the moment) behaviour. We require the ability
        // to crop (ie. window-off a section of the image), and pad (ie. provide a
        // background around the image). We keep this separate to the above code
        // because that already works well across various aspects of the site.
        //
        // Format of the array is 'type'=>'crop' or 'type'=>'pad'; 'where'=>'end',
        // 'where'=>'start' or 'where'=>'both'. For padding, there is an optional
        // 'background'=>'RRGGBBAA' or 'background'=>'RRGGBB' for colored padding
        // with or without transparency.
        // Grab the dimensions we would get if we didn't crop or scale
        $wrong_x = intval(round(floatval($sx) / $thumb_options['scale']));
        $wrong_y = intval(round(floatval($sy) / $thumb_options['scale']));
        // Handle cropping here
        if ($thumb_options['type'] == 'crop' || $thumb_options['type'] == 'pad_horiz_crop_horiz' && $wrong_x > $width || $thumb_options['type'] == 'pad_vert_crop_vert' && $wrong_y > $height) {
            // See which direction we're cropping in
            if (intval(round(floatval($sx) / $thumb_options['scale'])) != $width) {
                $crop_direction = 'x';
            } else {
                $crop_direction = 'y';
            }
            // We definitely have to crop, since symbols.php only tells us to crop
            // if it has to. Thus we know we're going to fill the output image, the
            // only question is with what part of the source image?
            // Get the amount we'll lose from the source
            if ($crop_direction == 'x') {
                $crop_off = intval($sx - $width * $thumb_options['scale']);
            } elseif ($crop_direction == 'y') {
                $crop_off = intval($sy - $height * $thumb_options['scale']);
            }
            // Now we see how much to chop off the start (we don't care about the
            // end, as this will be handled by using an appropriate window size)
            $displacement = 0;
            if ($thumb_options['where'] == 'start' || $thumb_options['where'] == 'start_if_vertical' && $crop_direction == 'y' || $thumb_options['where'] == 'start_if_horizontal' && $crop_direction == 'x') {
                $displacement = 0;
            } elseif ($thumb_options['where'] == 'end' || $thumb_options['where'] == 'end_if_vertical' && $crop_direction == 'y' || $thumb_options['where'] == 'end_if_horizontal' && $crop_direction == 'x') {
                $displacement = intval(floatval($crop_off));
            } else {
                $displacement = intval(floatval($crop_off) / 2.0);
            }
            // Now we convert this to the right x and y start locations for the
            // window
            $source_x = $crop_direction == 'x' ? $displacement : 0;
            $source_y = $crop_direction == 'y' ? $displacement : 0;
            // Now we set the width and height of our window, which will be scaled
            // versions of the width and height of the output
            $sx = intval($width * $thumb_options['scale']);
            $sy = intval($height * $thumb_options['scale']);
            // We start at the origin of our output
            $dest_x = 0;
            $dest_y = 0;
            // and it is always the full size it can be (or else we'd be cropping
            // too much)
            $_width = $width;
            $_height = $height;
        } elseif ($thumb_options['type'] == 'pad' || $thumb_options['type'] == 'pad_horiz_crop_horiz' && $wrong_x < $width || $thumb_options['type'] == 'pad_vert_crop_vert' && $wrong_y < $height) {
            // Padding code lives here. We definitely need to pad some excess space
            // because otherwise symbols.php would not call us. Thus we need a
            // background (can be transparent). Let's see if we've been given one.
            if (array_key_exists('background', $thumb_options) && !is_null($thumb_options['background'])) {
                if (substr($thumb_options['background'], 0, 1) == '#') {
                    $thumb_options['background'] = substr($thumb_options['background'], 1);
                }
                // We've been given a background, let's find out what it is
                if (strlen($thumb_options['background']) == 8) {
                    // We've got an alpha channel
                    $using_alpha = true;
                    $red_str = substr($thumb_options['background'], 0, 2);
                    $green_str = substr($thumb_options['background'], 2, 2);
                    $blue_str = substr($thumb_options['background'], 4, 2);
                    $alpha_str = substr($thumb_options['background'], 6, 2);
                } else {
                    // We've not got an alpha channel
                    $using_alpha = false;
                    $red_str = substr($thumb_options['background'], 0, 2);
                    $green_str = substr($thumb_options['background'], 2, 2);
                    $blue_str = substr($thumb_options['background'], 4, 2);
                }
                $red = intval($red_str, 16);
                $green = intval($green_str, 16);
                $blue = intval($blue_str, 16);
                if ($using_alpha) {
                    $alpha = intval($alpha_str, 16);
                }
            } else {
                // We've not got a background, so let's find a representative color
                // for the image by resampling the whole thing to 1 pixel.
                $temp_img = imagecreatetruecolor(1, 1);
                // Make an image to map on to
                imagecopyresampled($temp_img, $source, 0, 0, 0, 0, 1, 1, $sx, $sy);
                // Map the source image on to the 1x1 image
                $rgb_index = imagecolorat($temp_img, 0, 0);
                // Grab the color index of the single pixel
                $rgb_array = imagecolorsforindex($temp_img, $rgb_index);
                // Get the channels for it
                $red = $rgb_array['red'];
                // Grab the red
                $green = $rgb_array['green'];
                // Grab the green
                $blue = $rgb_array['blue'];
                // Grab the blue
                // Sort out if we're using alpha
                $using_alpha = false;
                if (array_key_exists('alpha', $rgb_array)) {
                    $using_alpha = true;
                }
                if ($using_alpha) {
                    $alpha = 255 - ($rgb_array['alpha'] * 2 + 1);
                }
                // Destroy the temporary image
                imagedestroy($temp_img);
            }
            // Now we need to work out how much padding we're giving, and where
            // The axis
            if (intval(round(floatval($sx) / $thumb_options['scale'])) != $width) {
                $pad_axis = 'x';
            } else {
                $pad_axis = 'y';
            }
            // The amount
            if ($pad_axis == 'x') {
                $padding = intval(round(floatval($width) - floatval($sx) / $thumb_options['scale']));
            } else {
                $padding = intval(round(floatval($height) - floatval($sy) / $thumb_options['scale']));
            }
            // The distribution
            if ($thumb_options['where'] == 'start' || $thumb_options['where'] == 'start_if_vertical' && $pad_axis == 'y' || $thumb_options['where'] == 'start_if_horizontal' && $pad_axis == 'x') {
                $pad_amount = 0;
            } else {
                $pad_amount = intval(floatval($padding) / 2.0);
            }
            // Now set all of the parameters needed for blitting our image
            // $sx and $sy are fine, since they cover the whole image
            $source_x = 0;
            $source_y = 0;
            $_width = $pad_axis == 'x' ? intval(round(floatval($sx) / $thumb_options['scale'])) : $width;
            $_height = $pad_axis == 'y' ? intval(round(floatval($sy) / $thumb_options['scale'])) : $height;
            $dest_x = $pad_axis == 'x' ? $pad_amount : 0;
            $dest_y = $pad_axis == 'y' ? $pad_amount : 0;
        }
    }
    // Resample/copy
    $gd_version = get_gd_version();
    if ($gd_version >= 2.0) {
        // Set the background if we have one
        if (!is_null($thumb_options) && !is_null($red)) {
            $dest = imagecreatetruecolor($width, $height);
            imagealphablending($dest, false);
            if (function_exists('imagecolorallocatealpha') && $using_alpha) {
                $back_col = imagecolorallocatealpha($dest, $red, $green, $blue, 127 - intval(floatval($alpha) / 2.0));
            } else {
                $back_col = imagecolorallocate($dest, $red, $green, $blue);
            }
            imagefilledrectangle($dest, 0, 0, $width, $height, $back_col);
            if (function_exists('imagesavealpha')) {
                imagesavealpha($dest, true);
            }
        } else {
            $dest = imagecreatetruecolor($_width, $_height);
            imagealphablending($dest, false);
            if (function_exists('imagesavealpha')) {
                imagesavealpha($dest, true);
            }
        }
        imagecopyresampled($dest, $source, $dest_x, $dest_y, $source_x, $source_y, $_width, $_height, $sx, $sy);
    } else {
        // Set the background if we have one
        if (!is_null($thumb_options) && !is_null($red)) {
            $dest = imagecreate($width, $height);
            $back_col = imagecolorallocate($dest, $red, $green, $blue);
            imagefill($dest, 0, 0, $back_col);
        } else {
            $dest = imagecreate($_width, $_height);
        }
        imagecopyresized($dest, $source, $dest_x, $dest_y, $source_x, $source_y, $_width, $_height, $sx, $sy);
    }
    // Clean up
    imagedestroy($source);
    // Save
    if (is_null($ext2)) {
        $ext2 = get_file_extension($to);
    }
    // If we've got transparency then we have to save as PNG
    if (!is_null($thumb_options) && isset($red) && $using_alpha) {
        $ext2 = 'png';
    }
    if (function_exists('imagepng') && $ext2 == 'png') {
        if (strtolower(substr($to, -4)) != '.png') {
            $to = $to . '.png';
        }
        $test = @imagepng($dest, $to);
        if (!$test) {
            if ($exit_on_error) {
                warn_exit(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)));
            }
            require_code('site');
            attach_message(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)), 'warn');
            return false;
        }
    } elseif (function_exists('imagejpeg') && ($ext2 == 'jpg' || $ext2 == 'jpeg')) {
        $jpeg_quality = get_value('jpeg_quality');
        if ($jpeg_quality !== NULL) {
            $test = @imagejpeg($dest, $to, intval($jpeg_quality));
        } else {
            $test = @imagejpeg($dest, $to);
        }
        if (!$test) {
            if ($exit_on_error) {
                warn_exit(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)));
            }
            require_code('site');
            attach_message(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)), 'warn');
            return false;
        }
    } elseif (function_exists('imagegif') && $ext2 == 'gif') {
        $test = @imagegif($dest, $to);
        if (!$test) {
            if ($exit_on_error) {
                warn_exit(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)));
            }
            require_code('site');
            attach_message(do_lang_tempcode('ERROR_IMAGE_SAVE', @strval($php_errormsg)), 'warn');
            return false;
        }
    } else {
        if ($exit_on_error) {
            warn_exit(do_lang_tempcode('UNKNOWN_FORMAT', escape_html($ext2)));
        }
        require_code('site');
        attach_message(do_lang_tempcode('UNKNOWN_FORMAT', escape_html($ext2)), 'warn');
        return false;
    }
    // Clean up
    imagedestroy($dest);
    fix_permissions($to);
    sync_file($to);
    return true;
}
Example #2
0
/**
 * Attempt to send an e-mail to the specified recipient. The mail will be forwarding to the CC address specified in the options (if there is one, and if not specified not to cc).
 * The mail will be sent in dual HTML/text format, where the text is the unconverted comcode source: if a member does not read HTML mail, they may wish to fallback to reading that.
 *
 * @param  string			The subject of the mail in plain text
 * @param  LONG_TEXT		The message, as Comcode
 * @param  ?array			The destination (recipient) e-mail addresses [array of strings] (NULL: site staff address)
 * @param  ?mixed			The recipient name. Array or string. (NULL: site name)
 * @param  EMAIL			The from address (blank: site staff address)
 * @param  string			The from name (blank: site name)
 * @param  integer		The message priority (1=urgent, 3=normal, 5=low)
 * @range  1 5
 * @param  ?array			An list of attachments (each attachment being a map, path=>filename) (NULL: none)
 * @param  boolean		Whether to NOT CC to the CC address
 * @param  ?MEMBER		Convert comcode->tempcode as this member (a privilege thing: we don't want people being able to use admin rights by default!) (NULL: guest)
 * @param  boolean		Replace above with arbitrary admin
 * @param  boolean		HTML-only
 * @param  boolean		Whether to bypass queueing, because this code is running as a part of the queue management tools
 * @param  ID_TEXT		The template used to show the email
 * @param  boolean		Whether to bypass queueing
 * @return ?tempcode		A full page (not complete XHTML) piece of tempcode to output (NULL: it worked so no tempcode message)
 */
function mail_wrap($subject_tag, $message_raw, $to_email = NULL, $to_name = NULL, $from_email = '', $from_name = '', $priority = 3, $attachments = NULL, $no_cc = false, $as = NULL, $as_admin = false, $in_html = false, $coming_out_of_queue = false, $mail_template = 'MAIL', $bypass_queue = false)
{
    if (get_option('smtp_sockets_use') == '0') {
        return non_overrided__mail_wrap($subject_tag, $message_raw, $to_email, $to_name, $from_email, $from_name, $priority, $attachments, $no_cc, $as, $as_admin, $in_html, $coming_out_of_queue);
    }
    if (running_script('stress_test_loader')) {
        return NULL;
    }
    if (is_null($bypass_queue)) {
        $bypass_queue = $priority < 3 || strpos(serialize($attachments), 'tmpfile') !== false;
    }
    global $EMAIL_ATTACHMENTS;
    $EMAIL_ATTACHMENTS = array();
    require_code('site');
    require_code('mime_types');
    if (is_null($as)) {
        $as = $GLOBALS['FORUM_DRIVER']->get_guest_id();
    }
    if (!$coming_out_of_queue) {
        $GLOBALS['SITE_DB']->query('DELETE FROM ' . get_table_prefix() . 'logged_mail_messages WHERE m_date_and_time<' . strval(time() - 60 * 60 * 24 * 14) . ' AND m_queued=0');
        // Log it all for 2 weeks, then delete
        $through_queue = !$bypass_queue && (get_option('mail_queue_debug') === '1' || get_option('mail_queue') === '1' && cron_installed());
        $GLOBALS['SITE_DB']->query_insert('logged_mail_messages', array('m_subject' => $subject_tag, 'm_message' => $message_raw, 'm_to_email' => serialize($to_email), 'm_to_name' => serialize($to_name), 'm_from_email' => $from_email, 'm_from_name' => $from_name, 'm_priority' => 3, 'm_attachments' => serialize($attachments), 'm_no_cc' => $no_cc ? 1 : 0, 'm_as' => $as, 'm_as_admin' => $as_admin ? 1 : 0, 'm_in_html' => $in_html ? 1 : 0, 'm_date_and_time' => time(), 'm_member_id' => get_member(), 'm_url' => get_self_url(true), 'm_queued' => $through_queue ? 1 : 0, 'm_template' => $mail_template));
        if ($through_queue) {
            return NULL;
        }
    }
    if (count($attachments) == 0) {
        $attachments = NULL;
    }
    global $SENDING_MAIL;
    if ($SENDING_MAIL) {
        return NULL;
    }
    $SENDING_MAIL = true;
    // To and from, and language
    $staff_address = get_option('staff_address');
    if (is_null($to_email)) {
        $to_email = array($staff_address);
    }
    $to_email_new = array();
    foreach ($to_email as $test_address) {
        if ($test_address != '') {
            $to_email_new[] = $test_address;
        }
    }
    $to_email = $to_email_new;
    if ($to_email == array()) {
        $SENDING_MAIL = false;
        return NULL;
    }
    if ($to_email[0] == $staff_address) {
        $lang = get_site_default_lang();
    } else {
        $lang = user_lang();
        if (method_exists($GLOBALS['FORUM_DRIVER'], 'get_member_from_email_address')) {
            $member_id = $GLOBALS['FORUM_DRIVER']->get_member_from_email_address($to_email[0]);
            if (!is_null($member_id)) {
                $lang = get_lang($member_id);
            }
        }
    }
    if (is_null($to_name)) {
        if ($to_email[0] == $staff_address) {
            $to_name = get_site_name();
        } else {
            $to_name = '';
        }
    }
    if ($from_email == '') {
        $from_email = get_option('staff_address');
    }
    if ($from_name == '') {
        $from_name = get_site_name();
    }
    $theme = method_exists($GLOBALS['FORUM_DRIVER'], 'get_theme') ? $GLOBALS['FORUM_DRIVER']->get_theme() : 'default';
    if ($theme == 'default') {
        $theme = $GLOBALS['FORUM_DRIVER']->get_theme('');
        // ... So get theme of welcome zone
    }
    // Our subject
    $_subject = do_template('MAIL_SUBJECT', array('_GUID' => '44a57c666bb00f96723256e26aade9e5', 'SUBJECT_TAG' => $subject_tag), $lang, false, NULL, '.tpl', 'templates', $theme);
    $subject = $_subject->evaluate($lang);
    // Note that this is slightly against spec, because characters aren't forced to be printable us-ascii. But it's better we allow this (which works in practice) than risk incompatibility via charset-base64 encoding.
    // Evaluate message. Needs doing early so we know if we have any headers
    // Misc settings
    $website_email = get_option('website_email');
    if ($website_email == '') {
        $website_email = $from_email;
    }
    $cc_address = $no_cc ? '' : get_option("cc_address");
    global $CID_IMG_ATTACHMENT;
    $CID_IMG_ATTACHMENT = array();
    // Decide message
    $GLOBALS['NO_LINK_TITLES'] = true;
    global $LAX_COMCODE;
    $temp = $LAX_COMCODE;
    $LAX_COMCODE = true;
    $html_content = comcode_to_tempcode($message_raw, $as, $as_admin);
    $LAX_COMCODE = $temp;
    $GLOBALS['NO_LINK_TITLES'] = false;
    if (!$in_html) {
        $_html_content = $html_content->evaluate($lang);
        $_html_content = preg_replace('#(keep|for)_session=[\\d\\w]*#', 'filtered=1', $_html_content);
        $message_html = strpos($_html_content, '<html') !== false ? make_string_tempcode($_html_content) : do_template($mail_template, array('_GUID' => 'b23069c20202aa59b7450ebf8d49cde1', 'CSS' => '{CSS}', 'LOGOURL' => get_logo_url(''), 'LANG' => $lang, 'TITLE' => $subject, 'CONTENT' => $_html_content), $lang, false, NULL, '.tpl', 'templates', $theme);
        $css = css_tempcode(true, true, $message_html->evaluate($lang), $theme);
        $_css = $css->evaluate($lang);
        if (get_option('allow_ext_images') != '1') {
            $_css = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $_css);
        }
        $html_evaluated = $message_html->evaluate($lang);
        $html_evaluated = str_replace('{CSS}', $_css, $html_evaluated);
        // Cleanup the Comcode a bit
        $message_plain = comcode_to_clean_text($message_raw);
    } else {
        $html_evaluated = $message_raw;
    }
    // Character set
    $regexp = '#^[\\x' . dechex(32) . '-\\x' . dechex(126) . ']*$#';
    $charset = preg_match($regexp, $html_evaluated) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii';
    // CID attachments
    if (get_option('allow_ext_images') != '1') {
        $html_evaluated = preg_replace_callback('#<img\\s([^>]*)src="(http://[^"]*)"#U', '_mail_img_rep_callback', $html_evaluated);
        $matches = array();
        foreach (array('#<([^"<>]*\\s)style="([^"]*)"#', '#<style( [^<>]*)?' . '>(.*)</style>#Us') as $over) {
            $num_matches = preg_match_all($over, $html_evaluated, $matches);
            for ($i = 0; $i < $num_matches; $i++) {
                $altered_inner = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $matches[2][$i]);
                if ($matches[2][$i] != $altered_inner) {
                    $altered_outer = str_replace($matches[2][$i], $altered_inner, $matches[0][$i]);
                    $html_evaluated = str_replace($matches[0][$i], $altered_outer, $html_evaluated);
                }
            }
        }
    }
    $cid_attachments = array();
    foreach ($CID_IMG_ATTACHMENT as $id => $img) {
        $file_path_stub = convert_url_to_path($img);
        $mime_type = get_mime_type(get_file_extension($img));
        $filename = basename($img);
        if (!is_null($file_path_stub)) {
            $cid_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $file_path_stub, 'temp' => false, 'cid' => $id);
        } else {
            $myfile = ocp_tempnam('email_attachment');
            http_download_file($img, NULL, false, false, 'ocPortal', NULL, NULL, NULL, NULL, NULL, $myfile);
            if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) {
                $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'];
            }
            if (!is_null($GLOBALS['HTTP_FILENAME'])) {
                $filename = $GLOBALS['HTTP_FILENAME'];
            }
            $cid_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $myfile, 'temp' => true, 'cid' => $id);
        }
        $cid_attachments[] = $cid_attachment;
    }
    // Attachments
    $real_attachments = array();
    $attachments = array_merge(is_null($attachments) ? array() : $attachments, $EMAIL_ATTACHMENTS);
    if (!is_null($attachments)) {
        foreach ($attachments as $path => $filename) {
            $mime_type = get_mime_type(get_file_extension($filename));
            if (strpos($path, '://') === false) {
                $real_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $path, 'temp' => false);
            } else {
                $myfile = ocp_tempnam('email_attachment');
                http_download_file($path, NULL, false, false, 'ocPortal', NULL, NULL, NULL, NULL, NULL, $myfile);
                if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) {
                    $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'];
                }
                if (!is_null($GLOBALS['HTTP_FILENAME'])) {
                    $filename = $GLOBALS['HTTP_FILENAME'];
                }
                $real_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $myfile, 'temp' => true);
            }
            $real_attachments[] = $real_attachment;
        }
    }
    // ==========================
    // Interface with SwiftMailer
    // ==========================
    require_code('Swift-4.1.1/lib/swift_required');
    // Read in SMTP settings
    $host = get_option('smtp_sockets_host');
    $port = intval(get_option('smtp_sockets_port'));
    $username = get_option('smtp_sockets_username');
    $password = get_option('smtp_sockets_password');
    $smtp_from_address = get_option('smtp_from_address');
    if ($smtp_from_address != '') {
        $from_email = $smtp_from_address;
    }
    // Create the Transport
    $transport = Swift_SmtpTransport::newInstance($host, $port)->setUsername($username)->setPassword($password);
    if ($port == 419 || $port == 465 || $port == 587) {
        $transport->setEncryption('tls');
    }
    // Create the Mailer using your created Transport
    $mailer = Swift_Mailer::newInstance($transport);
    // Create a message
    $to_array = array();
    if ($to_name === '') {
        foreach ($to_email as $_to_email) {
            $to_array[] = $_to_email;
        }
    } else {
        foreach ($to_email as $i => $_to_email) {
            $to_array[$_to_email] = is_array($to_name) ? $to_name[$i] : $to_name;
        }
    }
    $message = Swift_Message::newInstance($subject)->setFrom(array($website_email => $from_name))->setReplyTo(array($from_email => $from_name))->setTo($to_array)->setPriority($priority)->setCharset($charset)->setBody($html_evaluated, 'text/html', $charset)->addPart($message_plain, 'text/plain', $charset);
    if ($cc_address != '') {
        $message->setCc($cc_address);
    }
    // Attachments
    foreach ($real_attachments as $r) {
        $attachment = Swift_Attachment::fromPath($r['path'], $r['mime'])->setFilename($r['filename'])->setDisposition('attachment');
        $message->attach($attachment);
    }
    foreach ($cid_attachments as $r) {
        $attachment = Swift_Attachment::fromPath($r['path'], $r['mime'])->setFilename($r['filename'])->setDisposition('attachment')->setId($r['cid']);
        $message->attach($attachment);
    }
    // Send the message, and error collection
    $error = '';
    try {
        $result = $mailer->send($message);
    } catch (Exception $e) {
        $error = $e->getMessage();
    }
    if ($error == '' && !$result) {
        $error = 'Unknown error';
    }
    // Attachment cleanup
    foreach ($real_attachments as $r) {
        if ($r['temp']) {
            @unlink($r['path']);
        }
    }
    foreach ($cid_attachments as $r) {
        if ($r['temp']) {
            @unlink($r['path']);
        }
    }
    // Return / Error handling
    $SENDING_MAIL = false;
    if ($error != '') {
        if (get_param_integer('keep_hide_mail_failure', 0) == 0) {
            require_code('site');
            attach_message(!is_null($error) ? make_string_tempcode($error) : do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))), 'warn');
        } else {
            return warn_screen(get_page_title('ERROR_OCCURRED'), do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))));
        }
    }
    return NULL;
}
Example #3
0
/**
 * Generate a logo from the template.
 *
 * @param  string		The site name.
 * @param  string		The site slogan.
 * @param  boolean	Whether to output the logo to the browser, destroy then image, and exit the script (i.e. never returns)
 * @param  ?string	The theme to use the logo template from (NULL: default root zone theme).
 * @param  string		The logo img file to base upon.
 * @return resource  The image resource.
 */
function generate_logo($name, $slogan, $raw = false, $theme = NULL, $use = 'logo-template')
{
    require_code('character_sets');
    if (is_null($theme)) {
        $theme = $GLOBALS['SITE_DB']->query_value('zones', 'zone_theme', array('zone_name' => ''));
        if ($theme == '' || $theme == '-1') {
            $theme = 'default';
        }
    }
    $logo_wizard_details = array();
    if ($theme != 'default') {
        $ini_path = get_custom_file_base() . '/themes/' . filter_naughty($theme) . '/theme.ini';
        if (file_exists($ini_path)) {
            $logo_wizard_details += better_parse_ini_file($ini_path);
        }
    }
    $ini_path = get_file_base() . '/themes/default/theme.ini';
    $logo_wizard_details += better_parse_ini_file($ini_path);
    $logo_url = $GLOBALS['SITE_DB']->query_value_null_ok('theme_images', 'path', array('theme' => $theme, 'id' => $use));
    if (!is_null($logo_url)) {
        $file_path_stub = convert_url_to_path($logo_url);
    }
    if (is_null($logo_url) || !file_exists($file_path_stub)) {
        $logo_url = find_theme_image($use, false, false, $theme);
    } else {
        if (url_is_local($logo_url)) {
            $logo_url = (strpos($logo_url, 'themes/default/') !== false ? get_base_url() : get_custom_base_url()) . '/' . $logo_url;
        }
    }
    $file_path_stub = convert_url_to_path($logo_url);
    if (!is_null($file_path_stub)) {
        if (!file_exists($file_path_stub)) {
            $file_path_stub = get_file_base() . '/themes/default/images/trimmed-logo-template.png';
        }
        // Exceptional situation. Maybe theme got corrupted?
        $data = file_get_contents($file_path_stub);
    } else {
        $data = http_download_file($logo_url);
    }
    $img = imagecreatefromstring($data);
    if ($img === false) {
        warn_exit(do_lang_tempcode('CORRUPT_FILE', escape_html($logo_url)));
    }
    $ttf_font = get_file_base() . '/data/fonts/Vera.ttf';
    if (!function_exists('imagettftext') || !array_key_exists('FreeType Support', gd_info()) || !file_exists($ttf_font) || @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') === false) {
        $font = intval($logo_wizard_details['site_name_font_size_small_non_ttf']);
        $font_width = imagefontwidth($font) * strlen($name);
        $font_height = imagefontheight($font);
    } else {
        list(, , $font_width, , , , , $font_height) = imagettfbbox(26.0, 0.0, $ttf_font, foxy_utf8_to_nce($name));
        $font_height = max($font_height, -$font_height);
    }
    $white = imagecolorallocate($img, hexdec(substr($logo_wizard_details['site_name_colour'], 0, 2)), hexdec(substr($logo_wizard_details['site_name_colour'], 2, 2)), hexdec(substr($logo_wizard_details['site_name_colour'], 4, 2)));
    $black = imagecolorallocate($img, 0, 0, 0);
    $matches = array();
    if (file_exists(get_custom_file_base() . '/themes/' . $theme . '/css_custom/global.css')) {
        $css_file = file_get_contents(get_custom_file_base() . '/themes/' . $theme . '/css_custom/global.css');
    } else {
        $css_file = file_get_contents(get_file_base() . '/themes/default/css/global.css');
    }
    if (preg_match('/#(\\w\\w)(\\w\\w)(\\w\\w); \\/\\* \\{\\$,wizard, 100% medborder.border}/', $css_file, $matches) != 0) {
        $blue = imagecolorallocate($img, hexdec($matches[1]), hexdec($matches[2]), hexdec($matches[3]));
    } else {
        $blue = imagecolorallocate($img, hexdec(substr($logo_wizard_details['slogan_colour'], 0, 2)), hexdec(substr($logo_wizard_details['slogan_colour'], 2, 2)), hexdec(substr($logo_wizard_details['slogan_colour'], 4, 2)));
    }
    $do = array(array($slogan, intval($logo_wizard_details['slogan_x_offset']), intval($logo_wizard_details['slogan_y_offset']), intval($logo_wizard_details['slogan_font_size']), $ttf_font, $white));
    if ($font_width > intval($logo_wizard_details['site_name_split']) && strpos($name, ' ') !== false) {
        if (function_exists('imagettftext') && array_key_exists('FreeType Support', gd_info()) && file_exists($ttf_font) && @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') !== false) {
            list(, , $font_width, , , , , $font_height) = imagettfbbox(floatval($logo_wizard_details['site_name_font_size_small']), 0.0, $ttf_font, foxy_utf8_to_nce($name));
            $font_height = max($font_height, -$font_height);
        }
        $bits = explode(' ', $name);
        $a = '';
        $b = '';
        foreach ($bits as $bit) {
            if (strlen($a) < intval(round(floatval(strlen($name)) / 2.0))) {
                $a .= $bit . ' ';
            } else {
                $b .= $bit . ' ';
            }
        }
        $do[] = array($a, intval($logo_wizard_details['site_name_x_offset']), intval($logo_wizard_details['site_name_y_offset_small']) + $font_height, intval($logo_wizard_details['site_name_font_size_small']), $ttf_font, $blue);
        $do[] = array($b, intval($logo_wizard_details['site_name_x_offset']), intval($logo_wizard_details['site_name_y_offset_small']) + $font_height * 2 + intval($logo_wizard_details['site_name_split_gap']), intval($logo_wizard_details['site_name_font_size_small']), $ttf_font, $blue);
    } elseif ($font_width > intval($logo_wizard_details['site_name_split'])) {
        if (function_exists('imagettftext') && array_key_exists('FreeType Support', gd_info()) && file_exists($ttf_font) && @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') !== false) {
            list(, , $font_width, , , , , $font_height) = imagettfbbox(floatval($logo_wizard_details['site_name_font_size_small']), 0.0, $ttf_font, foxy_utf8_to_nce($name));
            $font_height = max($font_height, -$font_height);
        }
        $do[] = array($name, intval($logo_wizard_details['site_name_x_offset']), intval($logo_wizard_details['site_name_y_offset']) + $font_height, intval($logo_wizard_details['site_name_font_size_small']), $ttf_font, $blue);
    } else {
        $do[] = array($name, intval($logo_wizard_details['site_name_x_offset']), intval($logo_wizard_details['site_name_y_offset']) + $font_height, floatval($logo_wizard_details['site_name_font_size']), $ttf_font, $blue);
    }
    foreach ($do as $i => $doing) {
        //if ($i==1) continue;
        if (function_exists('imagettftext') && array_key_exists('FreeType Support', gd_info()) && file_exists($doing[4]) && @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') !== false) {
            imagettftext($img, (double) $doing[3], 0.0, $doing[1], $doing[2], $doing[5], $doing[4], foxy_utf8_to_nce($doing[0]));
        } else {
            imagestring($img, $doing[3] == intval($logo_wizard_details['site_name_font_size_small']) ? intval($logo_wizard_details['site_name_font_size_nonttf']) : $font, $doing[1], $doing[2] - 11, $doing[0], $doing[5]);
        }
    }
    if ($raw) {
        header('Content-type: image/png');
        /*if (strstr(ocp_srv('HTTP_USER_AGENT'),'MSIE')!==false)
        			header('Content-Disposition: filename="-logo.png"');
        		else
        			header('Content-Disposition: attachment; filename="-logo.png"');*/
        imagepng($img);
        imagedestroy($img);
        exit;
    }
    return $img;
}
Example #4
0
/**
 * Attempt to send an e-mail to the specified recipient. The mail will be forwarding to the CC address specified in the options (if there is one, and if not specified not to cc).
 * The mail will be sent in dual HTML/text format, where the text is the unconverted comcode source: if a member does not read HTML mail, they may wish to fallback to reading that.
 *
 * @param  string			The subject of the mail in plain text
 * @param  LONG_TEXT		The message, as Comcode
 * @param  ?array			The destination (recipient) e-mail addresses [array of strings] (NULL: site staff address)
 * @param  ?mixed			The recipient name. Array or string. (NULL: site name)
 * @param  EMAIL			The from address (blank: site staff address)
 * @param  string			The from name (blank: site name)
 * @param  integer		The message priority (1=urgent, 3=normal, 5=low)
 * @range  1 5
 * @param  ?array			An list of attachments (each attachment being a map, path=>filename) (NULL: none)
 * @param  boolean		Whether to NOT CC to the CC address
 * @param  ?MEMBER		Convert comcode->tempcode as this member (a privilege thing: we don't want people being able to use admin rights by default!) (NULL: guest)
 * @param  boolean		Replace above with arbitrary admin
 * @param  boolean		HTML-only
 * @param  boolean		Whether to bypass queueing, because this code is running as a part of the queue management tools
 * @param  ID_TEXT		The template used to show the email
 * @param  boolean		Whether to bypass queueing
 * @return ?tempcode		A full page (not complete XHTML) piece of tempcode to output (NULL: it worked so no tempcode message)
 */
function mail_wrap($subject_tag, $message_raw, $to_email = NULL, $to_name = NULL, $from_email = '', $from_name = '', $priority = 3, $attachments = NULL, $no_cc = false, $as = NULL, $as_admin = false, $in_html = false, $coming_out_of_queue = false, $mail_template = 'MAIL', $bypass_queue = false)
{
    if (running_script('stress_test_loader')) {
        return NULL;
    }
    global $EMAIL_ATTACHMENTS;
    $EMAIL_ATTACHMENTS = array();
    require_code('site');
    require_code('mime_types');
    $bypass_queue = $bypass_queue || $priority < 3 || strpos(serialize($attachments), 'tmpfile') !== false;
    if (is_null($as)) {
        $as = $GLOBALS['FORUM_DRIVER']->get_guest_id();
    }
    if (!$coming_out_of_queue) {
        $GLOBALS['SITE_DB']->query('DELETE FROM ' . get_table_prefix() . 'logged_mail_messages WHERE m_date_and_time<' . strval(time() - 60 * 60 * 24 * 14) . ' AND m_queued=0');
        // Log it all for 2 weeks, then delete
        $through_queue = !$bypass_queue && (get_option('mail_queue_debug') === '1' || get_option('mail_queue') === '1' && cron_installed());
        $GLOBALS['SITE_DB']->query_insert('logged_mail_messages', array('m_subject' => substr($subject_tag, 0, 255), 'm_message' => $message_raw, 'm_to_email' => serialize($to_email), 'm_to_name' => serialize($to_name), 'm_from_email' => $from_email, 'm_from_name' => $from_name, 'm_priority' => $priority, 'm_attachments' => serialize($attachments), 'm_no_cc' => $no_cc ? 1 : 0, 'm_as' => $as, 'm_as_admin' => $as_admin ? 1 : 0, 'm_in_html' => $in_html ? 1 : 0, 'm_date_and_time' => time(), 'm_member_id' => get_member(), 'm_url' => get_self_url(true), 'm_queued' => $through_queue ? 1 : 0, 'm_template' => $mail_template), false, !$through_queue);
        // No errors if we don't NEED this to work
        if ($through_queue) {
            return NULL;
        }
    }
    if (count($attachments) == 0) {
        $attachments = NULL;
    }
    global $SENDING_MAIL;
    if ($SENDING_MAIL) {
        return NULL;
    }
    $SENDING_MAIL = true;
    // To and from, and language
    $staff_address = get_option('staff_address');
    if (is_null($to_email)) {
        $to_email = array($staff_address);
    }
    $to_email_new = array();
    foreach ($to_email as $test_address) {
        if ($test_address != '') {
            $to_email_new[] = $test_address;
        }
    }
    $to_email = $to_email_new;
    if ($to_email == array()) {
        $SENDING_MAIL = false;
        return NULL;
    }
    if ($to_email[0] == $staff_address) {
        $lang = get_site_default_lang();
    } else {
        $lang = user_lang();
        if (method_exists($GLOBALS['FORUM_DRIVER'], 'get_member_from_email_address')) {
            $member_id = $GLOBALS['FORUM_DRIVER']->get_member_from_email_address($to_email[0]);
            if (!is_null($member_id)) {
                $lang = get_lang($member_id);
            }
        }
    }
    if (is_null($to_name)) {
        if ($to_email[0] == $staff_address) {
            $to_name = get_site_name();
        } else {
            $to_name = '';
        }
    }
    if ($from_email == '') {
        $from_email = get_option('staff_address');
    }
    if ($from_name == '') {
        $from_name = get_site_name();
    }
    $from_email = str_replace("\r", '', $from_email);
    $from_email = str_replace("\n", '', $from_email);
    $from_name = str_replace("\r", '', $from_name);
    $from_name = str_replace("\n", '', $from_name);
    $theme = method_exists($GLOBALS['FORUM_DRIVER'], 'get_theme') ? $GLOBALS['FORUM_DRIVER']->get_theme() : 'default';
    if ($theme == 'default') {
        $theme = $GLOBALS['FORUM_DRIVER']->get_theme('');
        // ... So get theme of welcome zone
    }
    // Line termination is fiddly. It is safer to rely on sendmail supporting \n than undetectable-qmail/postfix-masquerading-as-sendmail not supporting the correct \r\n
    /*$sendmail_path=ini_get('sendmail_path');
    	if ((strpos($sendmail_path,'qmail')!==false) || (strpos($sendmail_path,'sendmail')!==false))
    		$line_term="\n";
    	else
    		$line_term="\r\n";
    	*/
    if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' || get_option('smtp_sockets_use') == '1') {
        $line_term = "\r\n";
        /*} elseif (strtoupper(substr(PHP_OS,0,3))=='MAC')
        	{
        		$line_term="\r";*/
    } else {
        $line_term = "\n";
    }
    // We use the boundary to seperate message parts
    $_boundary = uniqid('ocPortal', true);
    $boundary = $_boundary . '_1';
    $boundary2 = $_boundary . '_2';
    $boundary3 = $_boundary . '_3';
    // Our subject
    $subject = do_template('MAIL_SUBJECT', array('_GUID' => '44a57c666bb00f96723256e26aade9e5', 'SUBJECT_TAG' => $subject_tag), $lang, false, NULL, '.tpl', 'templates', $theme);
    $tightened_subject = $subject->evaluate($lang);
    // Note that this is slightly against spec, because characters aren't forced to be printable us-ascii. But it's better we allow this (which works in practice) than risk incompatibility via charset-base64 encoding.
    $tightened_subject = str_replace(chr(10), '', $tightened_subject);
    $tightened_subject = str_replace(chr(13), '', $tightened_subject);
    $regexp = '#^[\\x' . dechex(32) . '-\\x' . dechex(126) . ']*$#';
    if (preg_match($regexp, $tightened_subject) == 0) {
        $tightened_subject = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($tightened_subject) . "?=";
    }
    if (preg_match($regexp, $from_name) == 0) {
        $from_name = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($from_name) . "?=";
    }
    if (is_array($to_name)) {
        foreach ($to_name as $i => $_to_name) {
            if (preg_match($regexp, $_to_name) == 0) {
                $to_name[$i] = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($_to_name) . "?=";
            }
        }
    } else {
        if (preg_match($regexp, $to_name) == 0) {
            $to_name = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($to_name) . "?=";
        }
    }
    $simplify_when_can = true;
    // Used for testing. Not actually needed
    // Evaluate message. Needs doing early so we know if we have any headers
    $GLOBALS['NO_LINK_TITLES'] = true;
    global $LAX_COMCODE;
    $temp = $LAX_COMCODE;
    $LAX_COMCODE = true;
    $html_content = comcode_to_tempcode($message_raw, $as, $as_admin);
    $LAX_COMCODE = $temp;
    $GLOBALS['NO_LINK_TITLES'] = false;
    $attachments = array_merge(is_null($attachments) ? array() : $attachments, $EMAIL_ATTACHMENTS);
    // Headers
    $website_email = get_option('website_email');
    if ($website_email == '') {
        $website_email = $from_email;
    }
    if (get_value('use_true_from') !== '1') {
        $headers = 'From: "' . $from_name . '" <' . $website_email . '>' . $line_term;
    } else {
        $headers = 'From: <' . $from_email . '>' . $line_term;
    }
    $headers .= 'Reply-To: <' . $from_email . '>' . $line_term;
    $headers .= 'Return-Path: <' . $website_email . '>' . $line_term;
    $headers .= 'X-Sender: <' . $website_email . '>' . $line_term;
    $cc_address = $no_cc ? '' : get_option('cc_address');
    if ($cc_address != '' && !in_array($cc_address, $to_email)) {
        $headers .= (get_option('bcc') == '1' ? 'Bcc: <' : 'Cc: <') . $cc_address . '>' . $line_term;
    }
    $headers .= 'Message-ID: <' . $_boundary . '@' . get_domain() . '>' . $line_term;
    $headers .= 'X-Priority: ' . strval($priority) . $line_term;
    $brand_name = get_value('rebrand_name');
    if (is_null($brand_name)) {
        $brand_name = 'ocPortal';
    }
    $headers .= 'X-Mailer: ' . $brand_name . $line_term;
    $headers .= 'MIME-Version: 1.0' . $line_term;
    if (!is_null($attachments) || !$simplify_when_can) {
        $headers .= 'Content-Type: multipart/mixed;' . "\n\t" . 'boundary="' . $boundary . '"';
    } else {
        $headers .= 'Content-Type: multipart/alternative;' . "\n\t" . 'boundary="' . $boundary2 . '"';
    }
    $sending_message = '';
    $sending_message .= 'This is a multi-part message in MIME format.' . $line_term . $line_term;
    if (!is_null($attachments) || !$simplify_when_can) {
        $sending_message .= '--' . $boundary . $line_term;
        $sending_message .= 'Content-Type: multipart/alternative;' . "\n\t" . 'boundary="' . $boundary2 . '"' . $line_term . $line_term . $line_term;
    }
    global $CID_IMG_ATTACHMENT;
    $CID_IMG_ATTACHMENT = array();
    // Message starts (actually: it is kind of in header form also as it uses mime multi-part)
    if (!$in_html) {
        $_html_content = $html_content->evaluate($lang);
        $_html_content = preg_replace('#(keep|for)_session=[\\d\\w]*#', 'filtered=1', $_html_content);
        $message_html = strpos($_html_content, '<html') !== false ? make_string_tempcode($_html_content) : do_template($mail_template, array('_GUID' => 'b23069c20202aa59b7450ebf8d49cde1', 'CSS' => '{CSS}', 'LOGOURL' => get_logo_url(''), 'LANG' => $lang, 'TITLE' => $subject, 'CONTENT' => $_html_content), $lang, false, NULL, '.tpl', 'templates', $theme);
        $css = css_tempcode(true, true, $message_html->evaluate($lang), $theme);
        $_css = $css->evaluate($lang);
        if (get_option('allow_ext_images') != '1') {
            $_css = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $_css);
        }
        $html_evaluated = $message_html->evaluate($lang);
        $html_evaluated = str_replace('{CSS}', $_css, $html_evaluated);
        // Cleanup the Comcode a bit
        $message_plain = comcode_to_clean_text($message_raw);
    } else {
        $html_evaluated = $message_raw;
    }
    $base64_encode = get_value('base64_emails') === '1';
    // More robust, but more likely to be spam-blocked, and some servers can scramble it.
    // Plain version
    if (!$in_html) {
        $sending_message .= '--' . $boundary2 . $line_term;
        $sending_message .= 'Content-Type: text/plain; charset=' . (preg_match($regexp, $message_plain) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii') . $line_term;
        // '; name="message.txt"'.	Outlook doesn't like: makes it think it's an attachment
        if ($base64_encode) {
            $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term;
            $sending_message .= chunk_split(base64_encode(unixify_line_format($message_plain)) . $line_term, 76, $line_term);
        } else {
            $sending_message .= 'Content-Transfer-Encoding: 8bit' . $line_term . $line_term;
            $sending_message .= wordwrap(str_replace(chr(10), $line_term, unixify_line_format($message_plain)) . $line_term, 998, $line_term);
        }
    }
    // HTML version
    $sending_message .= '--' . $boundary2 . $line_term;
    $sending_message .= 'Content-Type: multipart/related;' . "\n\t" . 'type="text/html";' . "\n\t" . 'boundary="' . $boundary3 . '"' . $line_term . $line_term . $line_term;
    $sending_message .= '--' . $boundary3 . $line_term;
    $sending_message .= 'Content-Type: text/html; charset=' . (preg_match($regexp, $html_evaluated) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii') . $line_term;
    // .'; name="message.html"'.	Outlook doesn't like: makes it think it's an attachment
    if (get_option('allow_ext_images') != '1') {
        $html_evaluated = preg_replace_callback('#<img\\s([^>]*)src="(http://[^"]*)"#U', '_mail_img_rep_callback', $html_evaluated);
        $matches = array();
        foreach (array('#<([^"<>]*\\s)style="([^"]*)"#', '#<style( [^<>]*)?' . '>(.*)</style>#Us') as $over) {
            $num_matches = preg_match_all($over, $html_evaluated, $matches);
            for ($i = 0; $i < $num_matches; $i++) {
                $altered_inner = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $matches[2][$i]);
                if ($matches[2][$i] != $altered_inner) {
                    $altered_outer = str_replace($matches[2][$i], $altered_inner, $matches[0][$i]);
                    $html_evaluated = str_replace($matches[0][$i], $altered_outer, $html_evaluated);
                }
            }
        }
    }
    if ($base64_encode) {
        $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term;
        $sending_message .= chunk_split(base64_encode(unixify_line_format($html_evaluated)) . $line_term, 76, $line_term);
    } else {
        $sending_message .= 'Content-Transfer-Encoding: 8bit' . $line_term . $line_term;
        // Requires RFC 1652
        $sending_message .= wordwrap(str_replace(chr(10), $line_term, unixify_line_format($html_evaluated)) . $line_term, 998, $line_term);
    }
    $total_filesize = 0;
    foreach ($CID_IMG_ATTACHMENT as $id => $img) {
        $sending_message .= '--' . $boundary3 . $line_term;
        $file_path_stub = convert_url_to_path($img);
        $mime_type = get_mime_type(get_file_extension($img));
        $filename = basename($img);
        if (!is_null($file_path_stub)) {
            $total_filesize += @filesize($file_path_stub);
            if ($total_filesize > 1024 * 1024 * 5) {
                continue;
            }
            // Too large to process into an email
            $file_contents = @file_get_contents($file_path_stub);
        } else {
            $file_contents = http_download_file($img, NULL, false);
            $total_filesize += strlen($file_contents);
            if ($total_filesize >= 1024 * 1024 * 5) {
                continue;
            }
            // Too large to process into an email
            if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) {
                $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'];
            }
            if (!is_null($GLOBALS['HTTP_FILENAME'])) {
                $filename = $GLOBALS['HTTP_FILENAME'];
            }
        }
        $sending_message .= 'Content-Type: ' . str_replace("\r", '', str_replace("\n", '', $mime_type)) . $line_term;
        $sending_message .= 'Content-ID: <' . $id . '>' . $line_term;
        $sending_message .= 'Content-Disposition: inline; filename="' . str_replace("\r", '', str_replace("\n", '', $filename)) . '"' . $line_term;
        $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term;
        if (is_string($file_contents)) {
            $sending_message .= chunk_split(base64_encode($file_contents), 76, $line_term);
        }
    }
    $sending_message .= $line_term . '--' . $boundary3 . '--' . $line_term . $line_term;
    $sending_message .= $line_term . '--' . $boundary2 . '--' . $line_term . $line_term;
    // Attachments
    if (!is_null($attachments)) {
        foreach ($attachments as $path => $filename) {
            $sending_message .= '--' . $boundary . $line_term;
            $sending_message .= 'Content-Type: ' . get_mime_type(get_file_extension($filename)) . $line_term;
            // .'; name="'.str_replace("\r",'',str_replace("\n",'',$filename)).'"'   http://www.imc.org/ietf-822/old-archive2/msg02121.html
            $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term;
            $sending_message .= 'Content-Disposition: attachment; filename="' . str_replace("\r", '', str_replace("\n", '', $filename)) . '"' . $line_term . $line_term;
            if (strpos($path, '://') === false) {
                $sending_message .= chunk_split(base64_encode(file_get_contents($path)), 76, $line_term);
            } else {
                require_code('files');
                $sending_message .= chunk_split(base64_encode(http_download_file($path)), 76, $line_term);
            }
        }
        $sending_message .= $line_term . '--' . $boundary . '--' . $line_term;
    }
    // Support for SMTP sockets rather than PHP mail()
    $error = NULL;
    if (get_option('smtp_sockets_use') == '1') {
        $worked = false;
        $host = get_option('smtp_sockets_host');
        $port = intval(get_option('smtp_sockets_port'));
        $errno = 0;
        $errstr = '';
        foreach ($to_email as $i => $to) {
            $socket = @fsockopen($host, $port, $errno, $errstr, 30.0);
            if ($socket !== false) {
                $rcv = fread($socket, 1024);
                $base_url = parse_url(get_base_url());
                $domain = $base_url['host'];
                // Login if necessary
                $username = get_option('smtp_sockets_username');
                $password = get_option('smtp_sockets_password');
                if ($username != '') {
                    fwrite($socket, 'EHLO ' . $domain . "\r\n");
                    $rcv = fread($socket, 1024);
                    fwrite($socket, "AUTH LOGIN\r\n");
                    $rcv = fread($socket, 1024);
                    if (strtolower(substr($rcv, 0, 3)) == '334') {
                        fwrite($socket, base64_encode($username) . "\r\n");
                        $rcv = fread($socket, 1024);
                        if (strtolower(substr($rcv, 0, 3)) == '235' || strtolower(substr($rcv, 0, 3)) == '334') {
                            fwrite($socket, base64_encode($password) . "\r\n");
                            $rcv = fread($socket, 1024);
                            if (strtolower(substr($rcv, 0, 3)) == '235') {
                            } else {
                                $error = do_lang('MAIL_ERROR_CONNECT_PASSWORD') . ' (' . str_replace($password, '*', $rcv) . ')';
                            }
                        } else {
                            $error = do_lang('MAIL_ERROR_CONNECT_USERNAME') . ' (' . $rcv . ')';
                        }
                    } else {
                        $error = do_lang('MAIL_ERROR_CONNECT_AUTH') . ' (' . $rcv . ')';
                    }
                } else {
                    fwrite($socket, 'HELO ' . $domain . "\r\n");
                    $rcv = fread($socket, 1024);
                }
                if (is_null($error)) {
                    $smtp_from_address = get_option('smtp_from_address');
                    if ($smtp_from_address == '') {
                        $smtp_from_address = $from_email;
                    }
                    fwrite($socket, 'MAIL FROM:<' . $website_email . ">\r\n");
                    $rcv = fread($socket, 1024);
                    if (strtolower(substr($rcv, 0, 3)) == '250' || strtolower(substr($rcv, 0, 3)) == '251') {
                        $sent_one = false;
                        fwrite($socket, "RCPT TO:<" . $to_email[$i] . ">\r\n");
                        $rcv = fread($socket, 1024);
                        if (strtolower(substr($rcv, 0, 3)) != '250' && strtolower(substr($rcv, 0, 3)) != '251') {
                            $error = do_lang('MAIL_ERROR_TO') . ' (' . $rcv . ')' . ' ' . $to_email[$i];
                        } else {
                            $sent_one = true;
                        }
                        if ($sent_one) {
                            fwrite($socket, "DATA\r\n");
                            $rcv = fread($socket, 1024);
                            if (strtolower(substr($rcv, 0, 3)) == '354') {
                                $attractive_date = strftime('%d %B %Y  %H:%M:%S', time());
                                $_to_name = preg_replace('#@.*$#', '', is_array($to_name) ? $to_name[$i] : $to_name);
                                // preg_replace is because some servers may reject sending names that look like e-mail addresses. ocP tries this from recommend module.
                                if (count($to_email) == 1) {
                                    if ($_to_name == '') {
                                        fwrite($socket, 'To: ' . $to_email[$i] . "\r\n");
                                    } else {
                                        fwrite($socket, 'To: ' . $_to_name . ' <' . $to_email[$i] . '>' . "\r\n");
                                    }
                                } else {
                                    fwrite($socket, 'To: ' . $_to_name . "\r\n");
                                }
                                fwrite($socket, 'Subject: ' . $tightened_subject . "\r\n");
                                fwrite($socket, 'Date: ' . $attractive_date . "\r\n");
                                $headers = preg_replace('#^\\.#m', '..', $headers);
                                $sending_message = preg_replace('#^\\.#m', '..', $sending_message);
                                fwrite($socket, $headers . "\r\n");
                                fwrite($socket, $sending_message);
                                fwrite($socket, "\r\n.\r\n");
                                $rcv = fread($socket, 1024);
                                fwrite($socket, "QUIT\r\n");
                                $rcv = fread($socket, 1024);
                            } else {
                                $error = do_lang('MAIL_ERROR_DATA') . ' (' . $rcv . ')';
                            }
                        }
                    } else {
                        $error = do_lang('MAIL_ERROR_FROM') . ' (' . $rcv . ')';
                    }
                    if (@fwrite($socket, "RSET\r\n") === false) {
                        @fclose($socket);
                        $socket = NULL;
                    } else {
                        $rcv = fread($socket, 1024);
                    }
                }
                if (!is_null($socket)) {
                    fclose($socket);
                }
                if (is_null($error)) {
                    $worked = true;
                }
            } else {
                $error = do_lang('MAIL_ERROR_CONNECT', $host, strval($port));
            }
        }
    } else {
        $worked = false;
        foreach ($to_email as $i => $to) {
            //exit($headers.chr(10).$sending_message);
            $GLOBALS['SUPPRESS_ERROR_DEATH'] = true;
            $additional = '';
            if (get_option('enveloper_override') == '1') {
                $additional = '-f ' . $website_email;
            }
            $_to_name = preg_replace('#@.*$#', '', is_array($to_name) ? $to_name[$i] : $to_name);
            // preg_replace is because some servers may reject sending names that look like e-mail addresses. ocP tries this from recommend module.
            if ($_to_name == '' || strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                $to_line = $to;
            } else {
                $to_line = '"' . $_to_name . '" <' . $to . '>';
            }
            //if (function_exists('mb_language')) mb_language('en');	Stop overridden mbstring mail function from messing and base64'ing stuff. Actually we don't need this as we make sure to pass through as headers with blank message, bypassing any filtering.
            if (str_replace(array('on', 'true', 'yes'), array('1', '1', '1'), strtolower(ini_get('safe_mode'))) == '1') {
                $worked = mail($to_line, $tightened_subject, $sending_message, $headers);
            } else {
                $worked = mail($to_line, $tightened_subject, $sending_message, $headers, $additional);
            }
            if (!$worked && isset($php_errormsg)) {
                $error = $php_errormsg;
            }
            $GLOBALS['SUPPRESS_ERROR_DEATH'] = false;
        }
    }
    if (!$worked) {
        $SENDING_MAIL = false;
        if (get_param_integer('keep_hide_mail_failure', 0) == 0) {
            require_code('site');
            attach_message(!is_null($error) ? make_string_tempcode($error) : do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))), 'warn');
        } else {
            return warn_screen(get_page_title('ERROR_OCCURRED'), do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))));
        }
    }
    $SENDING_MAIL = false;
    return NULL;
}
/**
 * Edit a member's photo, and check validity.
 *
 * @param  ID_TEXT	The identifier for the name of the posted URL field.
 * @param  ID_TEXT	The identifier for the name of the posted upload.
 * @param  ?MEMBER	The member (NULL: the current member).
 */
function ocf_member_choose_photo($param_name, $upload_name, $member_id = NULL)
{
    if (is_null($member_id)) {
        $member_id = get_member();
    }
    require_code('uploads');
    if (!array_key_exists($upload_name, $_FILES) || !is_swf_upload() && !is_uploaded_file($_FILES[$upload_name]['tmp_name'])) {
        $old = $GLOBALS['FORUM_DB']->query_value('f_members', 'm_photo_url', array('id' => $member_id));
        $x = post_param($param_name);
        if ($x != '' && url_is_local($x) && !$GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) {
            if ($old != $x) {
                access_denied('ASSOCIATE_EXISTING_FILE');
            }
        }
        if ($old == $x) {
            return;
        }
        // Not changed, bomb out as we don't want to generate a thumbnail, or copy to avatar, or send notification
    }
    // Find photo URL
    $urls = get_url($param_name, $upload_name, file_exists(get_custom_file_base() . '/uploads/photos') ? 'uploads/photos' : 'uploads/ocf_photos', 0, OCP_UPLOAD_IMAGE, true, 'thumb_' . $param_name, $upload_name . '2', false, true);
    if (!(strlen($urls[0]) > 1)) {
        $urls[1] = '';
    }
    if ((get_base_url() != get_forum_base_url() || array_key_exists('on_msn', $GLOBALS['SITE_INFO']) && $GLOBALS['SITE_INFO']['on_msn'] == '1') && $urls[0] != '' && url_is_local($urls[0])) {
        $urls[0] = get_custom_base_url() . '/' . $urls[0];
    }
    if ((get_base_url() != get_forum_base_url() || array_key_exists('on_msn', $GLOBALS['SITE_INFO']) && $GLOBALS['SITE_INFO']['on_msn'] == '1') && $urls[1] != '' && url_is_local($urls[1])) {
        $urls[1] = get_custom_base_url() . '/' . $urls[1];
    }
    if (get_option('is_on_gd') == '0' || !function_exists('imagetypes')) {
        if (!array_key_exists($upload_name . '2', $_FILES) || !is_swf_upload() && !is_uploaded_file($_FILES[$upload_name . '2']['tmp_name'])) {
            $field = post_param('thumb_' . $param_name, '');
            if ($field == '' && $urls[0] != '') {
                warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN_UPLOAD'));
            }
            if ($field != '' && url_is_local($field) && !$GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) {
                $old = $GLOBALS['FORUM_DB']->query_value('f_members', 'm_photo_thumb_url', array('id' => $member_id));
                if ($old != $field) {
                    access_denied('ASSOCIATE_EXISTING_FILE');
                }
            }
        }
    }
    // Cleanup old photo
    $old = $GLOBALS['FORUM_DB']->query_value('f_members', 'm_photo_url', array('id' => $member_id));
    if ($old == $urls[0]) {
        return;
    }
    if (url_is_local($old) && (substr($old, 0, 19) == 'uploads/ocf_photos/' || substr($old, 0, 15) == 'uploads/photos/')) {
        @unlink(get_custom_file_base() . '/' . rawurldecode($old));
    }
    $GLOBALS['FORUM_DB']->query_update('f_members', array('m_photo_url' => $urls[0], 'm_photo_thumb_url' => $urls[1]), array('id' => $member_id), '', 1);
    require_code('notifications');
    dispatch_notification('ocf_choose_photo', NULL, do_lang('CHOOSE_PHOTO_SUBJECT', $GLOBALS['FORUM_DRIVER']->get_username($member_id), NULL, NULL, get_lang($member_id)), do_lang('CHOOSE_PHOTO_BODY', $urls[0], $urls[1], $GLOBALS['FORUM_DRIVER']->get_username($member_id), get_lang($member_id)));
    // If no avatar, or default avatar, or avatars not installed, use photo for it
    $avatar_url = $GLOBALS['FORUM_DRIVER']->get_member_avatar_url($member_id);
    $default_avatar_url = find_theme_image('ocf_default_avatars/default', true, true);
    if (!addon_installed('ocf_avatars')) {
        $avatar_url = $urls[0];
        if (get_option('is_on_gd') == '1' && function_exists('imagetypes')) {
            $stub = url_is_local($avatar_url) ? get_complex_base_url($avatar_url) . '/' : '';
            $file_path = convert_url_to_path($stub . $avatar_url);
            if (!is_null($file_path)) {
                $new_file_path = str_replace('/ocf_photos/', '/ocf_avatars/', $file_path);
                if (!file_exists($new_file_path)) {
                    copy($file_path, $new_file_path);
                    fix_permissions($new_file_path);
                    sync_file($new_file_path);
                }
                $avatar_url = str_replace('/ocf_photos/', '/ocf_avatars/', $avatar_url);
            }
        }
        ocf_member_choose_avatar($avatar_url, $member_id);
    }
    // Decache from run-time cache
    unset($GLOBALS['FORUM_DRIVER']->MEMBER_ROWS_CACHED[$member_id]);
    unset($GLOBALS['MEMBER_CACHE_FIELD_MAPPINGS'][$member_id]);
}