/** * Deprecated methods (to be removed) */ public static function unfold_flowed($text) { return rcube_mime::unfold_flowed($text); }
/** * Workhorse function that does actual conversion. * * @param string Plain text */ protected function _converter($text) { // make links and email-addresses clickable $attribs = array('link_attribs' => array('rel' => 'noreferrer', 'target' => '_blank')); $replacer = new $this->config['replacer']($attribs); if ($this->config['flowed']) { $flowed_char = 0x1; $text = rcube_mime::unfold_flowed($text, chr($flowed_char)); } // search for patterns like links and e-mail addresses and replace with tokens if ($this->config['links']) { $text = $replacer->replace($text); } // split body into single lines $text = preg_split('/\\r?\\n/', $text); $quote_level = 0; $last = null; // wrap quoted lines with <blockquote> for ($n = 0, $cnt = count($text); $n < $cnt; $n++) { $flowed = false; if ($this->config['flowed'] && ord($text[$n][0]) == $flowed_char) { $flowed = true; $text[$n] = substr($text[$n], 1); } if ($text[$n][0] == '>' && preg_match('/^(>+ {0,1})+/', $text[$n], $regs)) { $q = substr_count($regs[0], '>'); $text[$n] = substr($text[$n], strlen($regs[0])); $text[$n] = $this->_convert_line($text[$n], $flowed || $this->config['wrap']); $_length = strlen(str_replace(' ', '', $text[$n])); if ($q > $quote_level) { if ($last !== null) { $text[$last] .= (!$length ? "\n" : '') . $replacer->get_replacement($replacer->add(str_repeat('<blockquote>', $q - $quote_level))) . $text[$n]; unset($text[$n]); } else { $text[$n] = $replacer->get_replacement($replacer->add(str_repeat('<blockquote>', $q - $quote_level))) . $text[$n]; $last = $n; } } else { if ($q < $quote_level) { $text[$last] .= (!$length ? "\n" : '') . $replacer->get_replacement($replacer->add(str_repeat('</blockquote>', $quote_level - $q))) . $text[$n]; unset($text[$n]); } else { $last = $n; } } } else { $text[$n] = $this->_convert_line($text[$n], $flowed || $this->config['wrap']); $q = 0; $_length = strlen(str_replace(' ', '', $text[$n])); if ($quote_level > 0) { $text[$last] .= (!$length ? "\n" : '') . $replacer->get_replacement($replacer->add(str_repeat('</blockquote>', $quote_level))) . $text[$n]; unset($text[$n]); } else { $last = $n; } } $quote_level = $q; $length = $_length; } if ($quote_level > 0) { $text[$last] .= $replacer->get_replacement($replacer->add(str_repeat('</blockquote>', $quote_level))); } $text = join("\n", $text); // colorize signature (up to <sig_max_lines> lines) $len = strlen($text); $sig_sep = "--" . $this->config['space'] . "\n"; $sig_max_lines = rcube::get_instance()->config->get('sig_max_lines', 15); while (($sp = strrpos($text, $sig_sep, $sp ? -$len + $sp - 1 : 0)) !== false) { if ($sp == 0 || $text[$sp - 1] == "\n") { // do not touch blocks with more that X lines if (substr_count($text, "\n", $sp) < $sig_max_lines) { $text = substr($text, 0, max(0, $sp)) . '<span class="sig">' . substr($text, $sp) . '</span>'; } break; } } // insert url/mailto links and citation tags $text = $replacer->resolve($text); // replace line breaks $text = str_replace("\n", $this->config['break'], $text); return $this->config['begin'] . $text . $this->config['end']; }
/** * Test format=flowed unfolding (#1490284) */ function test_unfold_flowed2() { $flowed = "> culpa qui officia deserunt mollit anim id est laborum.\r\n" . "> \r\n" . "Sed ut perspiciatis unde omnis iste natus error \r\nsit voluptatem"; $unfolded = "> culpa qui officia deserunt mollit anim id est laborum.\r\n" . "> \r\n" . "Sed ut perspiciatis unde omnis iste natus error sit voluptatem"; $this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines [2]"); }
/** * Test format=flowed unfolding */ function test_unfold_flowed() { $flowed = file_get_contents(TESTS_DIR . 'src/format-flowed.txt'); $unfolded = file_get_contents(TESTS_DIR . 'src/format-flowed-unfolded.txt'); $this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines"); }
/** * Handler for message signing * * @param Mail_mime Original message * @param int Encryption mode * * @return enigma_error On error returns error object */ function sign_message(&$message, $mode = null) { $mime = new enigma_mime_message($message, enigma_mime_message::PGP_SIGNED); $from = $mime->getFromAddress(); // find private key $key = $this->find_key($from, true); if (empty($key)) { return new enigma_error(enigma_error::KEYNOTFOUND); } // check if we have password for this key $passwords = $this->get_passwords(); $pass = $passwords[$key->id]; if ($pass === null) { // ask for password $error = array('missing' => array($key->id => $key->name)); return new enigma_error(enigma_error::BADPASS, '', $error); } $key->password = $pass; // select mode switch ($mode) { case self::SIGN_MODE_BODY: $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR; break; case self::SIGN_MODE_MIME: $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED; break; /* case self::SIGN_MODE_SEPARATE: $pgp_mode = Crypt_GPG::SIGN_MODE_NORMAL; break; */ /* case self::SIGN_MODE_SEPARATE: $pgp_mode = Crypt_GPG::SIGN_MODE_NORMAL; break; */ default: if ($mime->isMultipart()) { $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED; } else { $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR; } } // get message body if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) { // in this mode we'll replace text part // with the one containing signature $body = $message->getTXTBody(); $text_charset = $message->getParam('text_charset'); $line_length = $this->rc->config->get('line_length', 72); // We can't use format=flowed for signed messages if (strpos($text_charset, 'format=flowed')) { list($charset, $params) = explode(';', $text_charset); $body = rcube_mime::unfold_flowed($body); $body = rcube_mime::wordwrap($body, $line_length, "\r\n", false, $charset); $text_charset = str_replace(";\r\n format=flowed", '', $text_charset); } } else { // here we'll build PGP/MIME message $body = $mime->getOrigBody(); } // sign the body $result = $this->pgp_sign($body, $key, $pgp_mode); if ($result !== true) { if ($result->getCode() == enigma_error::BADPASS) { // ask for password $error = array('bad' => array($key->id => $key->name)); return new enigma_error(enigma_error::BADPASS, '', $error); } return $result; } // replace message body if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) { $message->setTXTBody($body); $message->setParam('text_charset', $text_charset); } else { $mime->addPGPSignature($body); $message = $mime; } }