/** * Convert from charset used by LDAP server to charset used by translation * * Output must be sanitized. * @param string string that has to be converted * @return string converted string */ function charset_decode($str) { global $default_charset; if ($this->charset != $default_charset) { return charset_convert($this->charset, $str, $default_charset, false); } else { return $str; } }
/** * Decodes headers * * This functions decode strings that is encoded according to * RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text). * Patched by Christian Schmidt <*****@*****.**> 23/03/2002 */ function decodeHeader($string, $utfencode = true, $htmlsave = true, $decide = false) { global $languages, $squirrelmail_language, $default_charset; if (is_array($string)) { $string = implode("\n", $string); } if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) { $string = $languages[$squirrelmail_language]['XTRA_CODE']('decodeheader', $string); // Do we need to return at this point? // return $string; } $i = 0; $iLastMatch = -2; $encoded = false; $aString = explode(' ', $string); $ret = ''; foreach ($aString as $chunk) { if ($encoded && $chunk === '') { continue; } elseif ($chunk === '') { $ret .= ' '; continue; } $encoded = false; /* if encoded words are not separated by a linear-space-white we still catch them */ $j = $i - 1; while ($match = preg_match('/^(.*)=\\?([^?]*)\\?(Q|B)\\?([^?]*)\\?=(.*)$/Ui', $chunk, $res)) { /* if the last chunk isn't an encoded string then put back the space, otherwise don't */ if ($iLastMatch !== $j) { if ($htmlsave) { $ret .= ' '; } else { $ret .= ' '; } } $iLastMatch = $i; $j = $i; if ($htmlsave) { $ret .= htmlspecialchars($res[1]); } else { $ret .= $res[1]; } $encoding = ucfirst($res[3]); /* decide about valid decoding */ if ($decide && is_conversion_safe($res[2])) { $can_be_encoded = true; } else { $can_be_encoded = false; } switch ($encoding) { case 'B': $replace = base64_decode($res[4]); if ($can_be_encoded) { // string is converted from one charset to another. sanitizing depends on $htmlsave $replace = charset_convert($res[2], $replace, $default_charset, $htmlsave); } elseif ($utfencode) { // string is converted to htmlentities and sanitized $replace = charset_decode($res[2], $replace); } elseif ($htmlsave) { // string is not converted, but still sanitized $replace = htmlspecialchars($replace); } $ret .= $replace; break; case 'Q': $replace = str_replace('_', ' ', $res[4]); $replace = preg_replace('/=([0-9a-f]{2})/ie', 'chr(hexdec("\\1"))', $replace); if ($can_be_encoded) { // string is converted from one charset to another. sanitizing depends on $htmlsave $replace = charset_convert($res[2], $replace, $default_charset, $htmlsave); } elseif ($utfencode) { // string is converted to html entities and sanitized $replace = charset_decode($res[2], $replace); } elseif ($htmlsave) { // string is not converted, but still sanizited $replace = htmlspecialchars($replace); } $ret .= $replace; break; default: break; } $chunk = $res[5]; $encoded = true; } if (!$encoded) { if ($htmlsave) { $ret .= ' '; } else { $ret .= ' '; } } if (!$encoded && $htmlsave) { $ret .= htmlspecialchars($chunk); } else { $ret .= $chunk; } ++$i; } /* remove the first added space */ if ($ret) { if ($htmlsave) { $ret = substr($ret, 5); } else { $ret = substr($ret, 1); } } return $ret; }
/** * Check for UTF-8 URLs; Internet Explorer produces these if you * type non-ASCII chars in the URL bar or follow unescaped links. * Requires urldecoded pagename. * Fixes sf.net bug #953949 * * src: languages/Language.php:checkTitleEncoding() from mediawiki */ function fixTitleEncoding($s) { global $charset; $s = trim($s); // print a warning? if (empty($s)) { return $s; } $ishigh = preg_match('/[\\x80-\\xff]/', $s); /* $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' . '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true ); */ $isutf = $ishigh ? isUtf8String($s) : true; $locharset = strtolower($charset); if ($locharset != "utf-8" and $ishigh and $isutf) { $s = charset_convert('UTF-8', $locharset, $s); } if ($locharset == "utf-8" and $ishigh and !$isutf) { return utf8_encode($s); } // Other languages can safely leave this function, or replace // it with one to detect and convert another legacy encoding. return $s; }
function newMail($mailbox = '', $passed_id = '', $passed_ent_id = '', $action = '', $session = '') { global $editor_size, $default_use_priority, $body, $idents, $use_signature, $composesession, $data_dir, $username, $username, $key, $imapServerAddress, $imapPort, $compose_messages, $composeMessage, $body_quote; global $languages, $squirrelmail_language, $default_charset; /* * Set $default_charset to correspond with the user's selection * of language interface. $default_charset global is not correct, * if message is composed in new window. */ set_my_charset(); $send_to = $send_to_cc = $send_to_bcc = $subject = $identity = ''; $mailprio = 3; if ($passed_id) { $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0); sqimap_mailbox_select($imapConnection, $mailbox); $message = sqimap_get_message($imapConnection, $passed_id, $mailbox); $body = ''; if ($passed_ent_id) { /* redefine the messsage in case of message/rfc822 */ $message = $message->getEntity($passed_ent_id); /* message is an entity which contains the envelope and type0=message * and type1=rfc822. The actual entities are childs from * $message->entities[0]. That's where the encoding and is located */ $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain', 'html/plain')); } $orig_header = $message->rfc822_header; /* here is the envelope located */ /* redefine the message for picking up the attachments */ $message = $message->entities[0]; } else { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain', 'html/plain')); } $orig_header = $message->rfc822_header; } $encoding = $message->header->encoding; $type0 = $message->type0; $type1 = $message->type1; foreach ($entities as $ent) { $msg = $message->getEntity($ent); $type0 = $msg->type0; $type1 = $msg->type1; $unencoded_bodypart = mime_fetch_body($imapConnection, $passed_id, $ent); $body_part_entity = $message->getEntity($ent); $bodypart = decodeBody($unencoded_bodypart, $body_part_entity->header->encoding); if ($type1 == 'html') { $bodypart = str_replace("\n", ' ', $bodypart); $bodypart = preg_replace(array('/<\\/?p>/i', '/<div><\\/div>/i', '/<br\\s*(\\/)*>/i', '/<\\/?div>/i'), "\n", $bodypart); $bodypart = str_replace(array(' ', '>', '<'), array(' ', '>', '<'), $bodypart); $bodypart = strip_tags($bodypart); } if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode')) { if (mb_detect_encoding($bodypart) != 'ASCII') { $bodypart = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode', $bodypart); } } if (isset($body_part_entity->header->parameters['charset'])) { $actual = $body_part_entity->header->parameters['charset']; } else { $actual = 'us-ascii'; } if ($actual && is_conversion_safe($actual) && $actual != $default_charset) { $bodypart = charset_convert($actual, $bodypart, $default_charset, false); } $body .= $bodypart; } if ($default_use_priority) { $mailprio = substr($orig_header->priority, 0, 1); if (!$mailprio) { $mailprio = 3; } } else { $mailprio = ''; } //ClearAttachments($session); $identity = ''; $from_o = $orig_header->from; if (is_array($from_o)) { if (isset($from_o[0])) { $from_o = $from_o[0]; } } if (is_object($from_o)) { $orig_from = $from_o->getAddress(); } else { $orig_from = ''; } $identities = array(); if (count($idents) > 1) { foreach ($idents as $nr => $data) { $enc_from_name = '"' . $data['full_name'] . '" <' . $data['email_address'] . '>'; if ($enc_from_name == $orig_from) { $identity = $nr; break; } $identities[] = $enc_from_name; } $identity_match = $orig_header->findAddress($identities); if ($identity_match) { $identity = $identity_match; } } switch ($action) { case 'draft': $use_signature = FALSE; $composeMessage->rfc822_header = $orig_header; $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); $send_from = $orig_header->getAddr_s('from'); $send_from_parts = new AddressStructure(); $send_from_parts = $orig_header->parseAddress($send_from); $send_from_add = $send_from_parts->mailbox . '@' . $send_from_parts->host; $identities = get_identities(); if (count($identities) > 0) { foreach ($identities as $iddata) { if ($send_from_add == $iddata['email_address']) { $identity = $iddata['index']; break; } } } $subject = decodeHeader($orig_header->subject, false, false, true); /* remember the references and in-reply-to headers in case of an reply */ $composeMessage->rfc822_header->more_headers['References'] = $orig_header->references; $composeMessage->rfc822_header->more_headers['In-Reply-To'] = $orig_header->in_reply_to; // rewrap the body to clean up quotations and line lengths sqBodyWrap($body, $editor_size); $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); break; case 'edit_as_new': $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); $subject = decodeHeader($orig_header->subject, false, false, true); $mailprio = $orig_header->priority; $orig_from = ''; $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); // rewrap the body to clean up quotations and line lengths sqBodyWrap($body, $editor_size); break; case 'forward': $send_to = ''; $subject = getforwardSubject(decodeHeader($orig_header->subject, false, false, true)); $body = getforwardHeader($orig_header) . $body; // the logic for calling sqUnWordWrap here would be to allow the browser to wrap the lines // forwarded message text should be as undisturbed as possible, so commenting out this call // sqUnWordWrap($body); $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); //add a blank line after the forward headers $body = "\n" . $body; break; case 'forward_as_attachment': $subject = getforwardSubject(decodeHeader($orig_header->subject, false, false, true)); $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection); $body = ''; break; case 'reply_all': if (isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) { $send_to = $orig_header->getAddr_s('mail_followup_to'); } else { $send_to_cc = replyAllString($orig_header); $send_to_cc = decodeHeader($send_to_cc, false, false, true); } case 'reply': // skip this if send_to was already set right above here if (!$send_to) { $send_to = $orig_header->reply_to; if (is_array($send_to) && count($send_to)) { $send_to = $orig_header->getAddr_s('reply_to'); } else { if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */ $send_to = $orig_header->getAddr_s('reply_to'); } else { $send_to = $orig_header->getAddr_s('from'); } } } $send_to = decodeHeader($send_to, false, false, true); $subject = decodeHeader($orig_header->subject, false, false, true); $subject = str_replace('"', "'", $subject); $subject = trim($subject); if (substr(strtolower($subject), 0, 3) != 're:') { $subject = 'Re: ' . $subject; } /* this corrects some wrapping/quoting problems on replies */ $rewrap_body = explode("\n", $body); $from = is_array($orig_header->from) ? $orig_header->from[0] : $orig_header->from; $body = ''; $strip_sigs = getPref($data_dir, $username, 'strip_sigs'); foreach ($rewrap_body as $line) { if ($strip_sigs && substr($line, 0, 3) == '-- ') { break; } if (preg_match("/^(>+)/", $line, $matches)) { $gt = $matches[1]; $body .= $body_quote . str_replace("\n", "\n{$body_quote}{$gt} ", rtrim($line)) . "\n"; } else { $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n{$body_quote}" . (!empty($body_quote) ? ' ' : ''), rtrim($line)) . "\n"; } } //rewrap the body to clean up quotations and line lengths $body = sqBodyWrap($body, $editor_size); $body = getReplyCitation($from, $orig_header->date) . $body; $composeMessage->reply_rfc822_header = $orig_header; break; default: break; } $compose_messages[$session] = $composeMessage; sqsession_register($compose_messages, 'compose_messages'); session_write_close(); sqimap_logout($imapConnection); } $ret = array('send_to' => $send_to, 'send_to_cc' => $send_to_cc, 'send_to_bcc' => $send_to_bcc, 'subject' => $subject, 'mailprio' => $mailprio, 'body' => $body, 'identity' => $identity); return $ret; }
/** * Security alert! We should not allow to import config.ini into our wiki (or from a sister wiki?) * because the sql passwords are in plaintext there. And the webserver must be able to read it. * Detected by Santtu Jarvi. */ function LoadFile(&$request, $filename, $text = false, $mtime = false) { if (preg_match("/config\$/", dirname($filename)) and preg_match("/config.*\\.ini/", basename($filename))) { trigger_error(sprintf("Refused to load %s", $filename), E_USER_WARNING); return; } if (!is_string($text)) { // Read the file. $stat = stat($filename); $mtime = $stat[9]; $text = implode("", file($filename)); } if (!$request->getArg('start_debug')) { @set_time_limit(30); } else { @set_time_limit(240); } // FIXME: basename("filewithnoslashes") seems to return garbage sometimes. $basename = basename("/dummy/" . $filename); if (!$mtime) { $mtime = time(); } // Last resort. // DONE: check source - target charset for content and pagename // but only for pgsrc'ed content, not from the browser. $default_pagename = rawurldecode($basename); if ($parts = ParseMimeifiedPages($text)) { if (count($parts) > 1) { $overwrite = $request->getArg('overwrite'); } usort($parts, 'SortByPageVersion'); foreach ($parts as $pageinfo) { // force overwrite if (count($parts) > 1) { $request->setArg('overwrite', 1); } SavePage($request, $pageinfo, sprintf(_("MIME file %s"), $filename), $basename); } if (count($parts) > 1) { if ($overwrite) { $request->setArg('overwrite', $overwrite); } else { unset($request->_args['overwrite']); } } } else { if ($pageinfo = ParseSerializedPage($text, $default_pagename, $request->getUser())) { SavePage($request, $pageinfo, sprintf(_("Serialized file %s"), $filename), $basename); } else { // plain old file $user = $request->getUser(); $file_charset = 'utf-8'; // compare to target charset if ($file_charset != strtolower($GLOBALS['charset'])) { $text = charset_convert($file_charset, $GLOBALS['charset'], $text); $default_pagename = charset_convert($file_charset, $GLOBALS['charset'], $default_pagename); } // Assume plain text file. $pageinfo = array('pagename' => $default_pagename, 'pagedata' => array(), 'versiondata' => array('author' => $user->getId()), 'content' => preg_replace('/[ \\t\\r]*\\n/', "\n", chop($text))); SavePage($request, $pageinfo, sprintf(_("plain file %s"), $filename), $basename); } } }
function ParseMimeifiedPages($data) { if (!($headers = ParseRFC822Headers($data)) || empty($headers['content-type'])) { //trigger_error( sprintf(_("Can't find %s"),'content-type header'), // E_USER_WARNING ); return false; } $typeheader = $headers['content-type']; if (!(list($type, $subtype, $params) = ParseMimeContentType($typeheader))) { trigger_error(sprintf("Can't parse %s: (%s)", 'content-type', $typeheader), E_USER_WARNING); return false; } if ("{$type}/{$subtype}" == 'multipart/mixed') { return ParseMimeMultipart($data, $params['boundary']); } else { if ("{$type}/{$subtype}" != 'application/x-phpwiki') { trigger_error(sprintf("Bad %s", "content-type: {$type}/{$subtype}"), E_USER_WARNING); return false; } } // FIXME: more sanity checking? $page = array(); $pagedata = array(); $versiondata = array(); if (isset($headers['date'])) { $pagedata['date'] = strtotime($headers['date']); } //DONE: support owner and acl foreach ($params as $key => $value) { if (empty($value)) { continue; } $value = rawurldecode($value); switch ($key) { case 'pagename': case 'version': $page[$key] = $value; break; case 'flags': if (preg_match('/PAGE_LOCKED/', $value)) { $pagedata['locked'] = 'yes'; } if (ENABLE_EXTERNAL_PAGES && preg_match('/EXTERNAL_PAGE/', $value)) { $pagedata['external'] = 'yes'; } break; case 'owner': case 'created': case 'hits': $pagedata[$key] = $value; break; case 'acl': case 'perm': if (class_exists('PagePermission')) { $pagedata['perm'] = ParseMimeifiedPerm($value); } break; case 'lastmodified': $versiondata['mtime'] = $value; break; case 'author': case 'author_id': case 'summary': case 'markup': case 'pagetype': $versiondata[$key] = $value; break; } } // FIXME: do we need to try harder to find a pagename if we // haven't got one yet? if (!isset($versiondata['author'])) { global $request; if (is_object($request)) { $user = $request->getUser(); $versiondata['author'] = $user->getId(); //FIXME:? } } $encoding = strtolower($headers['content-transfer-encoding']); if ($encoding == 'quoted-printable') { $data = QuotedPrintableDecode($data); } else { if ($encoding && $encoding != 'binary') { ExitWiki(sprintf("Unknown %s", 'encoding type: $encoding')); } } if (empty($params['charset'])) { $params['charset'] = 'utf-8'; } // compare to target charset if (strtolower($params['charset']) != strtolower($GLOBALS['charset'])) { $data = charset_convert($params['charset'], $GLOBALS['charset'], $data); //$page['pagename'] = charset_convert($params['charset'], $GLOBALS['charset'], $page['pagename']); if (isset($versiondata['summary'])) { $versiondata['summary'] = charset_convert($params['charset'], $GLOBALS['charset'], $versiondata['summary']); } } $data .= GenerateFootnotesFromRefs($params); $page['content'] = preg_replace('/[ \\t\\r]*\\n/', "\n", chop($data)); $page['pagedata'] = $pagedata; $page['versiondata'] = $versiondata; return array($page); }
function register_changes() { global $CONFIG; if (count($_POST) > 0) { if (isset($_POST['check'])) { $doconvert = 0; } else { if (isset($_POST['convert'])) { $doconvert = 1; } } if (isset($doconvert)) { $charsetin = $_POST['charset_in']; $charsetout = $_POST['charset_out']; // elements of the database that need converting // the first element in the array is the id name of the table $affected_elements = array($CONFIG['TABLE_ALBUMS'] => array('aid', 'title', 'description', 'keyword'), $CONFIG['TABLE_PICTURES'] => array('pid', 'title', 'caption', 'keywords'), $CONFIG['TABLE_COMMENTS'] => array('msg_id', 'msg_author', 'msg_body'), $CONFIG['TABLE_CATEGORIES'] => array('cid', 'name', 'description'), $CONFIG['TABLE_USERGROUPS'] => array('group_id', 'group_name'), $CONFIG['TABLE_USERS'] => array('user_id', 'user_name', 'user_password', 'user_profile1', 'user_profile2', 'user_profile3', 'user_profile4', 'user_profile5', 'user_profile6')); header("Content-Type: text/html; charset={$charsetout}"); //echo $charsetin . " " .$charsetout; if (!$doconvert) { $windowtitle = "Charset Manager - 2/3 - Check"; $title = "2/3 - Checking conversion from <b>{$charsetin}</b> to <b>{$charsetout}</b>"; } else { if ($doconvert) { $windowtitle = "Charset Manager - 3/3 - Conversion"; $title = "3/3 - Converting from <b>{$charsetin}</b> to <b>{$charsetout}</b>"; } } html_header($windowtitle, $charsetout); html_logo(); echo "<h1>{$title}</h1>"; echo '<table border="1" class="charsetchecktable" cellpadding="3" cellspacing="0" style="margin:auto;">'; if (!$doconvert) { echo '<p class="warning">You <b>must check</b> that all the cells in <span class="check">blue</span> are displayed properly.</p>'; } echo "<tr><th>String</th><th>Table</th><th>Column</th><th>Id</th><th>" . ($doconvert ? "Result" : "Query") . "</th></tr>"; foreach ($affected_elements as $table => $columns) { for ($i = 1; $i < count($columns); ++$i) { charset_convert($table, $columns[$i], $columns[0], $charsetin, $charsetout, $doconvert); } } echo '</table>'; if (!$doconvert) { echo '<form action="' . $_SERVER['PHP_SELF'] . '" method="post" name="cpgform" id="cpgform">'; echo '<input type="hidden" name="charset_in" value="' . $charsetin . "\" />\n"; echo '<input type="hidden" name="charset_out" value="' . $charsetout . "\" />\n"; echo <<<EOT <div class="warning"> <p>Before converting you <b>must</b>:</p> <ol> <li>Make a backup of your database. <span class="bigwarning">A malfunction of this script will result in the partial or complete loss or corruption of your comments and other string data containing non-ascii characters.</span></li> <li>Check that all the strings above in <span class="check">blue</span> are displayed correctly. </ol> </div> EOT; echo '<div class="input"><input type="submit" class="button" name="convert" value="Convert" /></div>'; echo '</form>'; } if ($doconvert) { // the script has succeeded (hopefully): we change the charset accordingly in the database set_config('charset', $charsetout); echo <<<EOT <div class="warning"> <p>The conversion has been carried out.<br/> If you did not get any errors, for security reasons, you may now <b>remove the file charsetmgr.php</b>, or make it unaccessible, since you will not need this file anymore.<br/> You may now <a href="index.php">proceed to the main page.</a> </p> </div> EOT; } html_footer(); exit; } } }
function newMail($mailbox = '', $passed_id = '', $passed_ent_id = '', $action = '', $session = '') { global $editor_size, $default_use_priority, $body, $idents, $use_signature, $data_dir, $username, $key, $imapServerAddress, $imapPort, $imap_stream_options, $composeMessage, $body_quote, $request_mdn, $request_dr, $mdn_user_support, $languages, $squirrelmail_language, $default_charset, $do_not_reply_to_self; /* * Set $default_charset to correspond with the user's selection * of language interface. $default_charset global is not correct, * if message is composed in new window. */ set_my_charset(); $send_to = $send_to_cc = $send_to_bcc = $subject = $identity = ''; $mailprio = 3; if ($passed_id) { $imapConnection = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options); sqimap_mailbox_select($imapConnection, $mailbox); $message = sqimap_get_message($imapConnection, $passed_id, $mailbox); $body = ''; if ($passed_ent_id) { /* redefine the messsage in case of message/rfc822 */ $message = $message->getEntity($passed_ent_id); /* message is an entity which contains the envelope and type0=message * and type1=rfc822. The actual entities are childs from * $message->entities[0]. That's where the encoding and is located */ $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain', 'text/html')); } $orig_header = $message->rfc822_header; /* here is the envelope located */ /* redefine the message for picking up the attachments */ $message = $message->entities[0]; } else { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain', 'text/html')); } $orig_header = $message->rfc822_header; } $type0 = $message->type0; $type1 = $message->type1; foreach ($entities as $ent) { $msg = $message->getEntity($ent); $type0 = $msg->type0; $type1 = $msg->type1; $unencoded_bodypart = mime_fetch_body($imapConnection, $passed_id, $ent); $body_part_entity = $message->getEntity($ent); $bodypart = decodeBody($unencoded_bodypart, $body_part_entity->header->encoding); if ($type1 == 'html') { $bodypart = str_replace("\n", ' ', $bodypart); $bodypart = preg_replace(array('/<\\/?p>/i', '/<div><\\/div>/i', '/<br\\s*(\\/)*>/i', '/<\\/?div>/i'), "\n", $bodypart); $bodypart = str_replace(array(' ', '>', '<'), array(' ', '>', '<'), $bodypart); $bodypart = strip_tags($bodypart); } if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode')) { if (mb_detect_encoding($bodypart) != 'ASCII') { $bodypart = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode', $bodypart); } } // charset encoding in compose form stuff if (isset($body_part_entity->header->parameters['charset'])) { $actual = $body_part_entity->header->parameters['charset']; } else { $actual = 'us-ascii'; } if ($actual && is_conversion_safe($actual) && $actual != $default_charset) { $bodypart = charset_convert($actual, $bodypart, $default_charset, false); } // end of charset encoding in compose $body .= $bodypart; } if ($default_use_priority) { $mailprio = substr($orig_header->priority, 0, 1); if (!$mailprio) { $mailprio = 3; } } else { $mailprio = ''; } $from_o = $orig_header->from; if (is_array($from_o)) { if (isset($from_o[0])) { $from_o = $from_o[0]; } } if (is_object($from_o)) { $orig_from = $from_o->getAddress(); } else { $orig_from = ''; } $identities = array(); if (count($idents) > 1) { foreach ($idents as $nr => $data) { $enc_from_name = '"' . $data['full_name'] . '" <' . $data['email_address'] . '>'; $identities[] = $enc_from_name; } $identity_match = $orig_header->findAddress($identities); if ($identity_match !== FALSE) { $identity = $identity_match; } } switch ($action) { case 'draft': $use_signature = FALSE; $composeMessage->rfc822_header = $orig_header; $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); $send_from = $orig_header->getAddr_s('from'); $send_from_parts = new AddressStructure(); $send_from_parts = $orig_header->parseAddress($send_from); $send_from_add = $send_from_parts->mailbox . '@' . $send_from_parts->host; $identity = find_identity(array($send_from_add)); $subject = decodeHeader($orig_header->subject, false, false, true); // Remember the receipt settings $request_mdn = $mdn_user_support && !empty($orig_header->dnt) ? '1' : '0'; $request_dr = $mdn_user_support && !empty($orig_header->drnt) ? '1' : '0'; /* remember the references and in-reply-to headers in case of an reply */ //FIXME: it would be better to fiddle with headers inside of the message object or possibly when delivering the message to its destination (drafts folder?); is this possible? $composeMessage->rfc822_header->more_headers['References'] = $orig_header->references; $composeMessage->rfc822_header->more_headers['In-Reply-To'] = $orig_header->in_reply_to; // rewrap the body to clean up quotations and line lengths sqBodyWrap($body, $editor_size); $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); break; case 'edit_as_new': $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); $subject = decodeHeader($orig_header->subject, false, false, true); $mailprio = $orig_header->priority; $orig_from = ''; $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); // rewrap the body to clean up quotations and line lengths sqBodyWrap($body, $editor_size); break; case 'forward': $send_to = ''; $subject = getforwardSubject(decodeHeader($orig_header->subject, false, false, true)); $body = getforwardHeader($orig_header) . $body; // the logic for calling sqUnWordWrap here would be to allow the browser to wrap the lines // forwarded message text should be as undisturbed as possible, so commenting out this call // sqUnWordWrap($body); $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); //add a blank line after the forward headers $body = "\n" . $body; break; case 'forward_as_attachment': $subject = getforwardSubject(decodeHeader($orig_header->subject, false, false, true)); $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection); $subject = decodeHeader($orig_header->subject, false, false, true); $subject = str_replace('"', "'", $subject); $subject = trim($subject); if (substr(strtolower($subject), 0, 4) != 'fwd:') { $subject = 'Fwd: ' . $subject; } $body = ''; break; case 'reply_all': if (isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) { $send_to = $orig_header->getAddr_s('mail_followup_to'); } else { $send_to_cc = replyAllString($orig_header); $send_to_cc = decodeHeader($send_to_cc, false, false, true); $send_to_cc = str_replace('""', '"', $send_to_cc); } case 'reply': // skip this if send_to was already set right above here if (!$send_to) { $send_to = $orig_header->reply_to; if (is_array($send_to) && count($send_to)) { $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE); } else { if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */ $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE); } else { $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE); } } } $send_to = decodeHeader($send_to, false, false, true); $send_to = str_replace('""', '"', $send_to); // If user doesn't want replies to her own messages // going back to herself (instead send again to the // original recipient of the message being replied to), // then iterate through identities, checking if the TO // field is one of them (if the reply is to ourselves) // // Note we don't bother if the original message doesn't // have anything in the TO field itself (because that's // what we use if we change the recipient to be that of // the previous message) // if ($do_not_reply_to_self && !empty($orig_header->to)) { $orig_to = ''; foreach ($idents as $id) { if (!empty($id['email_address']) && strpos($send_to, $id['email_address']) !== FALSE) { // if this is a reply-all, the original recipient // is already in the CC field, so we can just blank // the recipient (TO field) (as long as the CC field // isn't empty that is)... but then move the CC into // the TO, so TO isn't empty // if ($action == 'reply_all' && !empty($send_to_cc)) { $orig_to = $send_to_cc; $send_to_cc = ''; break; } $orig_to = $orig_header->to; if (is_array($orig_to) && count($orig_to)) { $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE); } else { if (is_object($orig_to)) { /* unneccesarry, just for failsafe purpose */ $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE); } else { $orig_to = ''; } } $orig_to = decodeHeader($orig_to, false, false, true); $orig_to = str_replace('""', '"', $orig_to); break; } } // if the reply was addressed back to ourselves, // we will send it to the TO of the previous message // if (!empty($orig_to)) { $send_to = $orig_to; // in this case, we also want to reset the FROM // identity as well (it should match the original // *FROM* header instead of TO or CC) // if (count($idents) > 1) { $identity = ''; foreach ($idents as $i => $id) { if (!empty($id['email_address']) && strpos($orig_from, $id['email_address']) !== FALSE) { $identity = $i; break; } } } } } $subject = decodeHeader($orig_header->subject, false, false, true); $subject = str_replace('"', "'", $subject); $subject = trim($subject); if (substr(strtolower($subject), 0, 3) != 're:') { $subject = 'Re: ' . $subject; } /* this corrects some wrapping/quoting problems on replies */ $rewrap_body = explode("\n", $body); $from = is_array($orig_header->from) && !empty($orig_header->from) ? $orig_header->from[0] : $orig_header->from; $body = ''; $strip_sigs = getPref($data_dir, $username, 'strip_sigs'); foreach ($rewrap_body as $line) { if ($strip_sigs && rtrim($line, "\r\n") == '-- ') { break; } if (preg_match("/^(>+)/", $line, $matches)) { $gt = $matches[1]; $body .= $body_quote . str_replace("\n", "\n{$body_quote}{$gt} ", rtrim($line)) . "\n"; } else { $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n{$body_quote}" . (!empty($body_quote) ? ' ' : ''), rtrim($line)) . "\n"; } } //rewrap the body to clean up quotations and line lengths $body = sqBodyWrap($body, $editor_size); $body = getReplyCitation($from, $orig_header->date) . $body; $composeMessage->reply_rfc822_header = $orig_header; break; default: break; } //FIXME: we used to register $compose_messages in the session here, but not any more - so do we still need the session_write_close() and sqimap_logout() here? We probably need the IMAP logout, but what about the session closure? session_write_close(); sqimap_logout($imapConnection); } $ret = array('send_to' => $send_to, 'send_to_cc' => $send_to_cc, 'send_to_bcc' => $send_to_bcc, 'subject' => $subject, 'mailprio' => $mailprio, 'body' => $body, 'identity' => $identity); return $ret; }
function newMail($mailbox = '', $passed_id = '', $passed_ent_id = '', $action = '', $session = '') { global $editor_size, $default_use_priority, $body, $idents, $use_signature, $composesession, $data_dir, $username, $username, $key, $imapServerAddress, $imapPort, $compose_messages, $composeMessage, $body_quote; global $languages, $squirrelmail_language, $default_charset; /* * Set $default_charset to correspond with the user's selection * of language interface. $default_charset global is not correct, * if message is composed in new window. */ set_my_charset(); $send_to = $send_to_cc = $send_to_bcc = $subject = $identity = ''; $mailprio = 3; if ($passed_id) { $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0); sqimap_mailbox_select($imapConnection, $mailbox); $message = sqimap_get_message($imapConnection, $passed_id, $mailbox); $body = ''; if ($passed_ent_id) { /* redefine the messsage in case of message/rfc822 */ $message = $message->getEntity($passed_ent_id); /* message is an entity which contains the envelope and type0=message * and type1=rfc822. The actual entities are childs from * $message->entities[0]. That's where the encoding and is located */ $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->entities[0]->findDisplayEntity(array(), $alt_order = array('text/plain', 'html/plain')); } $orig_header = $message->rfc822_header; /* here is the envelope located */ /* redefine the message for picking up the attachments */ $message = $message->entities[0]; } else { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain')); if (!count($entities)) { $entities = $message->findDisplayEntity(array(), $alt_order = array('text/plain', 'html/plain')); } $orig_header = $message->rfc822_header; } $encoding = $message->header->encoding; $type0 = $message->type0; $type1 = $message->type1; foreach ($entities as $ent) { $unencoded_bodypart = mime_fetch_body($imapConnection, $passed_id, $ent); $body_part_entity = $message->getEntity($ent); $bodypart = decodeBody($unencoded_bodypart, $body_part_entity->header->encoding); if ($type1 == 'html') { $bodypart = str_replace("\n", ' ', $bodypart); $bodypart = preg_replace(array('/<p>/i', '/<br\\s*(\\/)*>/i'), "\n", $bodypart); $bodypart = str_replace(array(' ', '>', '<'), array(' ', '>', '<'), $bodypart); $bodypart = strip_tags($bodypart); } if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) { if (mb_detect_encoding($bodypart) != 'ASCII') { $bodypart = $languages[$squirrelmail_language]['XTRA_CODE']('decode', $bodypart); } } // charset encoding in compose form stuff if (isset($body_part_entity->header->parameters['charset'])) { $actual = $body_part_entity->header->parameters['charset']; } else { $actual = 'us-ascii'; } if ($actual && is_conversion_safe($actual) && $actual != $default_charset) { $bodypart = charset_convert($actual, $bodypart, $default_charset, false); } // end of charset encoding in compose $body .= $bodypart; } if ($default_use_priority) { $mailprio = substr($orig_header->priority, 0, 1); if (!$mailprio) { $mailprio = 3; } } else { $mailprio = ''; } $identity = ''; $from_o = $orig_header->from; if (is_array($from_o)) { if (isset($from_o[0])) { $from_o = $from_o[0]; } } if (is_object($from_o)) { $orig_from = $from_o->getAddress(); } else { $orig_from = ''; } $identities = array(); if (count($idents) > 1) { foreach ($idents as $nr => $data) { $enc_from_name = '"' . $data['full_name'] . '" <' . $data['email_address'] . '>'; if ($enc_from_name == $orig_from) { $identity = $nr; break; } $identities[] = $enc_from_name; } $identity_match = $orig_header->findAddress($identities); if ($identity_match) { $identity = $identity_match; } } switch ($action) { case 'draft': $use_signature = FALSE; $composeMessage->rfc822_header = $orig_header; $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); // FIXME: ident support? $subject = decodeHeader($orig_header->subject, false, false, true); /* remember the references and in-reply-to headers in case of an reply */ $composeMessage->rfc822_header->more_headers['References'] = $orig_header->references; $composeMessage->rfc822_header->more_headers['In-Reply-To'] = $orig_header->in_reply_to; $body_ary = explode("\n", $body); $cnt = count($body_ary); $body = ''; for ($i = 0; $i < $cnt; $i++) { if (!ereg("^[>\\s]*\$", $body_ary[$i]) || !$body_ary[$i]) { sqWordWrap($body_ary[$i], $editor_size, $default_charset); $body .= $body_ary[$i] . "\n"; } unset($body_ary[$i]); } sqUnWordWrap($body); $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); break; case 'edit_as_new': $send_to = decodeHeader($orig_header->getAddr_s('to'), false, false, true); $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'), false, false, true); $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'), false, false, true); $subject = decodeHeader($orig_header->subject, false, false, true); $mailprio = $orig_header->priority; $orig_from = ''; $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); sqUnWordWrap($body); break; case 'forward': $send_to = ''; $subject = decodeHeader($orig_header->subject, false, false, true); if (substr(strtolower($subject), 0, 4) != 'fwd:' && substr(strtolower($subject), 0, 5) != '[fwd:' && substr(strtolower($subject), 0, 6) != '[ fwd:') { $subject = '[Fwd: ' . $subject . ']'; } $body = getforwardHeader($orig_header) . $body; $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection); $body = "\n" . $body; break; case 'forward_as_attachment': $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection); $body = ''; break; case 'reply_all': if (isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) { $send_to = $orig_header->getAddr_s('mail_followup_to'); } else { $send_to_cc = replyAllString($orig_header); $send_to_cc = decodeHeader($send_to_cc, false, false, true); } case 'reply': if (!$send_to) { $send_to = $orig_header->reply_to; if (is_array($send_to) && count($send_to)) { $send_to = $orig_header->getAddr_s('reply_to'); } else { if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */ $send_to = $orig_header->getAddr_s('reply_to'); } else { $send_to = $orig_header->getAddr_s('from'); } } } $send_to = decodeHeader($send_to, false, false, true); $subject = decodeHeader($orig_header->subject, false, false, true); $subject = trim($subject); if (substr(strtolower($subject), 0, 3) != 're:') { $subject = 'Re: ' . $subject; } /* this corrects some wrapping/quoting problems on replies */ $rewrap_body = explode("\n", $body); $from = is_array($orig_header->from) && !empty($orig_header->from) ? $orig_header->from[0] : $orig_header->from; sqUnWordWrap($body); $body = ''; $cnt = count($rewrap_body); for ($i = 0; $i < $cnt; $i++) { sqWordWrap($rewrap_body[$i], $editor_size, $default_charset); if (preg_match("/^(>+)/", $rewrap_body[$i], $matches)) { $gt = $matches[1]; $body .= $body_quote . str_replace("\n", "\n" . $body_quote . "{$gt} ", rtrim($rewrap_body[$i])) . "\n"; } else { $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n" . $body_quote . (!empty($body_quote) ? ' ' : ''), rtrim($rewrap_body[$i])) . "\n"; } unset($rewrap_body[$i]); } $body = getReplyCitation($from, $orig_header->date) . $body; $composeMessage->reply_rfc822_header = $orig_header; break; default: break; } $compose_messages[$session] = $composeMessage; sqsession_register($compose_messages, 'compose_messages'); session_write_close(); sqimap_logout($imapConnection); } $ret = array('send_to' => $send_to, 'send_to_cc' => $send_to_cc, 'send_to_bcc' => $send_to_bcc, 'subject' => $subject, 'mailprio' => $mailprio, 'body' => $body, 'identity' => $identity); return $ret; }
/** * Decodes headers * * This function decodes strings that are encoded according to * RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text). * Patched by Christian Schmidt <*****@*****.**> 23/03/2002 * * @param string $string header string that has to be made readable * @param boolean $utfencode change message in order to be readable on user's charset. defaults to true * @param boolean $htmlsafe preserve spaces and sanitize html special characters. defaults to true * @param boolean $decide decide if string can be utfencoded. defaults to false * @return string decoded header string */ function decodeHeader($string, $utfencode = true, $htmlsafe = true, $decide = false) { global $languages, $squirrelmail_language, $default_charset; if (is_array($string)) { $string = implode("\n", $string); } if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decodeheader')) { $string = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decodeheader', $string); // Do we need to return at this point? // return $string; } $i = 0; $iLastMatch = -2; $encoded = true; // FIXME: spaces are allowed inside quoted-printable encoding, but the following line will bust up any such encoded strings $aString = explode(' ', $string); $ret = ''; foreach ($aString as $chunk) { if ($encoded && $chunk === '') { continue; } elseif ($chunk === '') { $ret .= ' '; continue; } $encoded = false; /* if encoded words are not separated by a linear-space-white we still catch them */ $j = $i - 1; while ($match = preg_match('/^(.*)=\\?([^?]*)\\?(Q|B)\\?([^?]*)\\?=(.*)$/Ui', $chunk, $res)) { /* if the last chunk isn't an encoded string then put back the space, otherwise don't */ if ($iLastMatch !== $j) { if ($htmlsafe) { $ret .= ' '; } else { $ret .= ' '; } } $iLastMatch = $i; $j = $i; if ($htmlsafe) { $ret .= sm_encode_html_special_chars($res[1]); } else { $ret .= $res[1]; } $encoding = ucfirst($res[3]); /* decide about valid decoding */ if ($decide && is_conversion_safe($res[2])) { $utfencode = true; $can_be_encoded = true; } else { $can_be_encoded = false; } switch ($encoding) { case 'B': $replace = base64_decode($res[4]); if ($utfencode) { if ($can_be_encoded) { /* convert string to different charset, * if functions asks for it (usually in compose) */ $ret .= charset_convert($res[2], $replace, $default_charset, $htmlsafe); } else { // convert string to html codes in order to display it $ret .= charset_decode($res[2], $replace); } } else { if ($htmlsafe) { $replace = sm_encode_html_special_chars($replace); } $ret .= $replace; } break; case 'Q': $replace = str_replace('_', ' ', $res[4]); $replace = preg_replace_callback('/=([0-9a-f]{2})/i', create_function('$matches', 'return chr(hexdec($matches[1]));'), $replace); if ($utfencode) { if ($can_be_encoded) { /* convert string to different charset, * if functions asks for it (usually in compose) */ $replace = charset_convert($res[2], $replace, $default_charset, $htmlsafe); } else { // convert string to html codes in order to display it $replace = charset_decode($res[2], $replace); } } else { if ($htmlsafe) { $replace = sm_encode_html_special_chars($replace); } } $ret .= $replace; break; default: break; } $chunk = $res[5]; $encoded = true; } if (!$encoded) { if ($htmlsafe) { $ret .= ' '; } else { $ret .= ' '; } } if (!$encoded && $htmlsafe) { $ret .= sm_encode_html_special_chars($chunk); } else { $ret .= $chunk; } ++$i; } /* remove the first added space */ if ($ret) { if ($htmlsafe) { $ret = substr($ret, 5); } else { $ret = substr($ret, 1); } } return $ret; }