/** * 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; }
/** * 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; }
/** * 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; }
/** * 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]); }