public function get_header($message) { //== [INITS] //-- $export_from_addr = ''; $export_from_name = ''; $export_to_addr = ''; $export_to_name = ''; $export_cc_addr = ''; $export_cc_name = ''; $export_subject = ''; $export_date = ''; $export_msguid = ''; $export_msgid = ''; $export_inreplyto = ''; $export_priority = ''; $export_attachments = ''; //-- $headers = array(); //-- //== //== [ATTACHMENTS] //-- $export_attachments = 0; // attachments not detected //-- if (preg_match("/^content-disposition:(\\s)attachment(.*);/mi", (string) $message)) { // insensitive $export_attachments = 1; // attachments were detected } //end if //-- //== //== DECODING //-- $params = array(); $params['decode_headers'] = true; // Whether to decode headers $params['include_bodies'] = false; // Whether to include the body in the returned object. $params['decode_bodies'] = false; // Whether to decode the bodies of the parts. (Transfer encoding) //-- $obj = new SmartMailerMimeExtract((string) $message, $this->local_charset); // [OK] unset($message); $structure = $obj->decode($params); //-- $this->reset(); $this->printarray($structure, ''); // this will be free after trying to guess atatchments //-- free memory unset($structure); unset($obj); unset($params); //-- some process of data $headers = (array) $this->arr_heads[0]; // get first header //-- $this->reset(); //-- //== //== [FROM] $from = ''; //-- if (is_array($headers['from'])) { $from = trim($headers['from'][0]); } else { $from = trim($headers['from']); } //end if else //-- if (strlen($from) <= 0) { // if from is not specified we use return path if (is_array($headers['return-path'])) { $from = trim($headers['return-path'][0]); } else { $from = trim($headers['return-path']); } //end if else } //end if //-- $tmp_arr = array(); $tmp_arr = $this->separe_email_from_name($from); //-- $export_from_addr = trim($tmp_arr[0]); $export_from_name = trim($tmp_arr[1]); //-- $tmp_arr = array(); $from = ''; //-- $tmp_arr = array(); $from = ''; //-- //== //== [TO] $to = ''; //-- if (is_array($headers['to'])) { $to = trim($headers['to'][0]); } else { $to = trim($headers['to']); } //end if else //-- $tmp_arr = array(); $tmp_arr = $this->separe_email_from_name($to); //-- $export_to_addr = trim($tmp_arr[0]); $export_to_name = trim($tmp_arr[1]); //-- if (SmartUnicode::str_contains($to, '[::@::]')) { // fix for netoffice :: Multi-Message $export_to_addr = '[@]'; $export_to_name = ''; } elseif (SmartUnicode::str_contains($to, '[::#::]')) { // fix for netoffice :: Fax $export_to_addr = '[#]'; $export_to_name = ''; } elseif (SmartUnicode::str_contains($to, '[::!::]')) { // Not Sent $export_to_addr = '[!]'; $export_to_name = ''; } //end if //-- $tmp_arr = array(); $to = ''; //-- //== //== [CC] $cc = ''; //-- $export_cc_addr = array(); $export_cc_name = array(); //-- if (is_array($headers['cc'])) { $cc = trim($headers['cc'][0]); } else { $cc = trim($headers['cc']); } //end if else //-- $arr_cc = array(); //-- if (SmartUnicode::str_contains($cc, ',')) { $arr_cc = (array) explode(',', (string) $cc); } else { $arr_cc[] = (string) $cc; } //end if else //-- for ($z = 0; $z < Smart::array_size($arr_cc); $z++) { //-- $tmp_arr = array(); $tmp_arr = $this->separe_email_from_name($arr_cc[$z]); //-- $export_cc_addr[] = trim($tmp_arr[0]); $export_cc_name[] = trim($tmp_arr[1]); //-- $tmp_arr = array(); //-- } //end for //-- $export_cc_addr = implode(', ', $export_cc_addr); $export_cc_name = implode(', ', $export_cc_name); //-- $cc = ''; //-- //== //== [BCC] $bcc = ''; //-- if (is_array($headers['bcc'])) { $bcc = trim($headers['bcc'][0]); } else { $bcc = trim($headers['bcc']); } //end if else //-- $tmp_arr = array(); $tmp_arr = $this->separe_email_from_name($bcc); //-- $export_bcc_addr = trim($tmp_arr[0]); $export_bcc_name = trim($tmp_arr[1]); //-- $tmp_arr = array(); //-- $bcc = ''; //-- //== //== [SUBJECT] $subj = ''; //-- if (is_array($headers['subject'])) { $subj = trim($headers['subject'][0]); } else { $subj = trim($headers['subject']); } //end if else //-- $export_subject = trim($subj); //-- if (strlen($export_subject) <= 0) { $export_subject = '[?]'; } //end if //-- $subj = ''; //-- //== //== [DATE] $date = ''; //-- if (is_array($headers['date'])) { $date = trim($headers['date'][0]); } else { $date = trim($headers['date']); } //end if else //-- $export_date = trim($date); //-- if (strlen($export_date) <= 0) { $export_date = '(?)'; } //end if //-- $date = ''; //-- //== //== [MESSAGE-UID] $msguid = ''; //-- if (is_array($headers['message-uid'])) { $msguid = trim($headers['message-uid'][0]); } else { $msguid = trim($headers['message-uid']); } //end if else //-- $msguid = trim(str_replace(array('<', '>'), array('', ''), (string) $msguid)); //-- $export_msguid = trim($msguid); //-- $msguid = ''; //-- //== //== [MESSAGE-ID] $msgid = ''; //-- if (is_array($headers['message-id'])) { $msgid = trim($headers['message-id'][0]); } else { $msgid = trim($headers['message-id']); } //end if else //-- $msgid = trim(str_replace(array('<', '>'), array('', ''), (string) $msgid)); //-- $export_msgid = trim($msgid); //-- $msgid = ''; //-- //== //== [IN-REPLY-TO] $inreplyto = ''; //-- if (is_array($headers['in-reply-to'])) { $inreplyto = trim($headers['in-reply-to'][0]); } else { $inreplyto = trim($headers['in-reply-to']); } //end if else //-- $inreplyto = trim(str_replace(array('<', '>'), array('', ''), (string) $inreplyto)); //-- $export_inreplyto = trim($inreplyto); //-- $inreplyto = ''; //-- //== //== [PRIORITY] :: ( 1=high, 3=normal, 5=low ) $priority = ''; //-- if (is_array($headers['x-priority'])) { $priority = trim($headers['x-priority'][0]); } else { $priority = trim($headers['x-priority']); } //end if else //-- switch (strtolower($priority)) { case 'high': case '0': case '1': case '2': $export_priority = '1'; //high break; case 'low': case '5': case '6': case '7': case '8': case '9': case '10': $export_priority = '5'; //low break; case 'normal': case 'medium': case '3': case '4': default: $export_priority = '3'; //medium (normal) } //end switch //-- $priority = ''; //-- //== //== [CLEANUP] //-- unset($headers); //-- //== //== [EXPORT DATA AS ARRAY] return array('from_addr' => (string) $export_from_addr, 'from_name' => (string) $export_from_name, 'to_addr' => (string) $export_to_addr, 'to_name' => (string) $export_to_name, 'cc_addr' => (string) $export_cc_addr, 'cc_name' => (string) $export_cc_name, 'bcc_addr' => (string) $export_bcc_addr, 'bcc_name' => (string) $export_bcc_name, 'subject' => (string) $export_subject, 'date' => (string) $export_date, 'message-uid' => (string) $export_msguid, 'message-id' => (string) $export_msgid, 'in-reply-to' => (string) $export_inreplyto, 'priority' => (string) $export_priority, 'attachments' => (string) $export_attachments); //== }
public function data_send($msg_data) { //-- if ($this->debug) { $this->log .= '[INF] Data-Send command is sent on Mail Server' . "\n"; } //end if //-- if (strlen($this->error) > 0) { return 0; } //end if //-- $reply = $this->send_cmd('DATA'); if (strlen($this->error) > 0) { return 0; } //end if //-- $test = $this->answer_code($reply); if ((string) $test != '354') { $this->error = '[ERR] Data-Send command Failed on Server :: ' . $test . ' // ' . $reply; return 0; } //end if //-- // The server is ready to accept data. According to rfc 821 we should not send more than 1000 characters including the CRLF on a single line // so we will break the data up into lines by \r and/or \n then if needed we will break each of those into smaller lines to fit within the limit. // In addition we will be looking for lines that start with a period '.' and append and additional period '.' to that line. // NOTE: this does not count towards are limit. //-- normalize the line breaks so we know the explode works $msg_data = str_replace(array("\r\n", "\r"), array("\n", "\n"), $msg_data); // replacing the CRLF to LF $lines = (array) explode("\n", (string) $msg_data); $msg_data = ''; // cleanup //-- // We need to find a good way to determine if headers are in the msg_data or if it is a straight msg body. // Currently assuming rfc 822 definitions of msg headers and if the first field of the first line (':' sperated) does not contain a space // then it _should_ be a header and we can process all lines before a blank "" line as headers. //-- $field = SmartUnicode::sub_str($lines[0], 0, SmartUnicode::str_pos($lines[0], ':')); $in_headers = false; //-- if (strlen($field) > 0 and !SmartUnicode::str_contains($field, ' ')) { $in_headers = true; } //end if //-- $max_line_length = 800; // used below ; set here for ease in change (we use a lower value than 1000 as we use UTF-8 text) //-- //while(list(,$line) = @each($lines)) { while (list($key, $line) = @each($lines)) { // FIX to be compatible with the upcoming PHP 7 //-- $lines_out = null; //-- if ((string) $line == '' and $in_headers) { $in_headers = false; } //end if //-- ok we need to break this line up into several smaller lines while (SmartUnicode::str_len($line) > $max_line_length) { //-- $pos = SmartUnicode::str_rpos(SmartUnicode::sub_str($line, 0, $max_line_length), ' '); // here we need reverse strpos $lines_out[] = SmartUnicode::sub_str($line, 0, $pos); $line = SmartUnicode::sub_str($line, $pos + 1); //-- if we are processing headers we need to add a LWSP-char to the front of the new line rfc 822 on long msg headers if ($in_headers) { $line = "\t" . $line; } //end if //-- } //end while //-- $lines_out[] = $line; //-- now send the lines to the server //while(list(,$line_out) = @each($lines_out)) { while (list($key, $line_out) = @each($lines_out)) { // FIX to be compatible with the upcoming PHP 7 //-- if (strlen($line_out) > 0) { if (SmartUnicode::sub_str($line_out, 0, 1) == '.') { $line_out = '.' . $line_out; } //end if } //end if //-- @fputs($this->socket, $line_out . "\r\n"); //-- } //end while //-- } //end while //-- ok all the message data has been sent so lets get this over with aleady @fputs($this->socket, "\r\n" . '.' . "\r\n"); //-- $reply = $this->retry_data(); $test = $this->answer_code($reply); //-- if ($this->debug) { $this->log .= '[INF] Data-Send Mail Server Reply is :: ' . $test . ' // ' . $reply . "\n"; } //end if //-- if (strlen($this->error) > 0) { return 0; } //end if //-- if ((string) $test != '250') { $this->error = '[ERR] Data-Send Finalize Failed on Server :: ' . $test . ' // ' . $reply; return 0; } //end if //-- return 1; //-- }
public static function test_strings() { //-- $unicode_text = '"Unicode78źź:ăĂîÎâÂșȘțȚşŞţŢグッド'; //-- $idn_domain_unicode = 'jösefsson.tßst123.org'; $idn_domain_iso = 'xn--jsefsson-n4a.xn--tst123-bta.org'; $idn_email_unicode = 'räksmörgås@jösefsson.tßst123.org'; $idn_email_iso = '*****@*****.**'; //-- //-- $err = ''; //-- //-- $tests[] = '##### Unicode STRING / TESTS: #####'; //-- //-- $regex_positive = '/^[\\w"\\:\\?]+$/'; $regex_negative = '/[^\\w"\\:\\?]/'; //-- //-- if (defined('SMART_FRAMEWORK_SECURITY_FILTER_INPUT')) { if ((string) SMART_FRAMEWORK_SECURITY_FILTER_INPUT != '') { if ((string) $err == '') { $the_test = 'Smart.Framework Security Input Filter Regex - test over a full Unicode String'; $tests[] = $the_test; if (preg_match((string) SMART_FRAMEWORK_SECURITY_FILTER_INPUT, 'Platform クラウドアプリケーションプラットフォーム \'áâãäåāăąÁÂÃÄÅĀĂĄćĉčçĆĈČÇďĎèéêëēĕėěęÈÉÊËĒĔĖĚĘĝģĜĢĥħĤĦìíîïĩīĭȉȋįÌÍÎÏĨĪĬȈȊĮijĵIJĴķĶĺļľłĹĻĽŁñńņňÑŃŅŇòóôõöōŏőøœÒÓÔÕÖŌŎŐØŒŕŗřŔŖŘșşšśŝßȘŞŠŚŜțţťȚŢŤùúûüũūŭůűųÙÚÛÜŨŪŬŮŰŲŵŴẏỳŷÿýẎỲŶŸÝźżžŹŻŽ " <p></p> ? & * ^ $ @ ! ` ~ % () [] {} | \\ / + - _ : ; , . #\'0.51085600 1454529112#' . "\r\n\t" . '`~@#$%^&*()-_=+[{]}|;:"<>,.?/\\')) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode Regex Test Positive'; $tests[] = $the_test; if (!preg_match((string) $regex_positive . 'u', (string) $unicode_text)) { $err = 'ERROR: ' . $the_test . ' FAILED (1) ...'; } elseif (preg_match((string) $regex_positive, (string) $unicode_text)) { $err = 'ERROR: ' . $the_test . ' FAILED (2) ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode Regex Test Negative'; $tests[] = $the_test; if (preg_match((string) $regex_negative . 'u', (string) $unicode_text)) { $err = 'ERROR: ' . $the_test . ' FAILED (1) ...'; } elseif (!preg_match((string) $regex_negative, (string) $unicode_text)) { $err = 'ERROR: ' . $the_test . ' FAILED (2) ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Deaccented ISO Regex Test Positive'; $tests[] = $the_test; if (!preg_match((string) $regex_positive, (string) SmartUnicode::deaccent_str($unicode_text))) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Deaccented ISO Regex Test Negative'; $tests[] = $the_test; if (preg_match((string) $regex_negative, (string) SmartUnicode::deaccent_str($unicode_text))) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode Strlen Test'; $tests[] = $the_test; if (SmartUnicode::str_len($unicode_text) !== 30) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { // this tests also SmartUnicode::str_ipos $the_test = 'Unicode Find Substring (Case Insensitive), Positive'; $tests[] = $the_test; if (SmartUnicode::str_icontains($unicode_text, 'șș') !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { // this tests also SmartUnicode::str_ipos $the_test = 'Unicode Find Substring (Case Insensitive), Negative'; $tests[] = $the_test; if (SmartUnicode::str_icontains($unicode_text, 'șş') !== false) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { // this tests also SmartUnicode::str_pos $the_test = 'Unicode Find Substring (Case Sensitive), Positive'; $tests[] = $the_test; if (SmartUnicode::str_contains($unicode_text, 'țȚ') !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { // this tests also SmartUnicode::str_pos $the_test = 'Unicode Find Substring (Case Sensitive), Negative'; $tests[] = $the_test; if (SmartUnicode::str_contains($unicode_text, 'țŢ') !== false) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode Find Substring (Case Insensitive), Reverse'; $tests[] = $the_test; if (SmartUnicode::str_ripos($unicode_text, 'ţţグ') === false) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode Find Substring (Case Sensitive), Reverse'; $tests[] = $the_test; if (SmartUnicode::str_rpos($unicode_text, 'ţŢグ') === false) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode Return Substring (Case Insensitive)'; $tests[] = $the_test; if (SmartUnicode::stri_str($unicode_text, 'âȘșȚ') !== 'ÂșȘțȚşŞţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode Return Substring (Case Sensitive)'; $tests[] = $the_test; if (SmartUnicode::str_str($unicode_text, 'ÂșȘț') !== 'ÂșȘțȚşŞţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode String to LowerCase'; $tests[] = $the_test; if (SmartUnicode::str_tolower($unicode_text) !== '"unicode78źź:ăăîîââșșțțşşţţグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode String to UpperCase'; $tests[] = $the_test; if (SmartUnicode::str_toupper($unicode_text) !== '"UNICODE78ŹŹ:ĂĂÎÎÂÂȘȘȚȚŞŞŢŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode SubString function (without last param)'; $tests[] = $the_test; if (SmartUnicode::sub_str($unicode_text, 25) !== 'ţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'Unicode SubString function (with last param)'; $tests[] = $the_test; if (SmartUnicode::sub_str($unicode_text, 25, 3) !== 'ţŢグ') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode SubString Count function'; $tests[] = $the_test; if (SmartUnicode::substr_count($unicode_text, 'ţ') !== 1) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Unicode String Replace with Limit (Case Sensitive)'; $tests[] = $the_test; if (SmartUnicode::str_limit_replace('ź', '@', $unicode_text, 1) !== '"Unicode78@ź:ăĂîÎâÂșȘțȚşŞţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { $the_test = 'String Replace without Limit (Case Sensitive)'; $tests[] = $the_test; if (str_replace('ź', '@', $unicode_text) !== '"Unicode78@@:ăĂîÎâÂșȘțȚşŞţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if if ((string) $err == '') { /* This test fails if the replacements accented characters are different case than one find in string (upper/lower) ... */ $the_test = 'String Replace without Limit (Case Insensitive) *** Only with unaccented replacements !!'; $tests[] = $the_test; if (str_ireplace('E7', '@', $unicode_text) !== '"Unicod@8źź:ăĂîÎâÂșȘțȚşŞţŢグッド') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Deaccent String'; $tests[] = $the_test; if (SmartUnicode::deaccent_str($unicode_text) !== '"Unicode78zz:aAiIaAsStTsStT???') { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'YAML Unicode Test: Compose from Array / Parse from YAML'; $tests[] = $the_test; $test_arr = array('@test' => 'Testing weird key characters', 'line1' => 'Some ISO-8859-1 String: @ # $ % ^ & * (\') _ - + = { [ ] } ; < ,. > / ? \\ |', 'line2' => 'Unicode (long) String: ' . $unicode_text . ' ' . SmartUnicode::str_toupper($unicode_text) . ' ' . $unicode_text . ' ' . SmartUnicode::str_tolower($unicode_text) . ' ' . $unicode_text . ' ' . SmartUnicode::deaccent_str($unicode_text) . ' ' . $unicode_text, $unicode_text => 'Unicode as Key', 'line3' => ['A' => 'b', 100, 'Thousand'], 'line4' => [1, 0.2, 3.0001], 'line5' => date('Y-m-d H:i:s')); $test_yaml = (string) '# start YAML (to test also comments)' . "\n" . (new SmartYamlConverter())->compose($test_arr) . "\n" . '# end YAML'; $test_parr = (new SmartYamlConverter())->parse($test_yaml); if ($test_arr !== $test_parr) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' #ORIGINAL Array [' . print_r($test_arr, 1) . ']' . "\n\n" . '#YAML Array (from YAML String): ' . print_r($test_parr, 1) . "\n\n" . '#YAML String (from ORIGINAL Array): ' . "\n" . $test_yaml; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'XML Unicode Test: Compose from Array / Parse from XML'; $tests[] = $the_test; $test_arr = array('TEST' => 'Testing weird key characters', 'line1' => 'Some ISO-8859-1 String: @ # $ % ^ & * (\') _ - + = { [ ] } ; < ,. > / ? \\ |', 'line2' => 'Unicode (long) String: ' . $unicode_text . ' ' . SmartUnicode::str_toupper($unicode_text) . ' ' . $unicode_text . ' ' . SmartUnicode::str_tolower($unicode_text) . ' ' . $unicode_text . ' ' . SmartUnicode::deaccent_str($unicode_text) . ' ' . $unicode_text, 'line3' => ['A' => 'b', 'c' => 'D'], 'line4' => '', 'line5' => date('Y-m-d H:i:s')); $test_xml = (string) (new SmartXmlComposer())->transform($test_arr); $test_parr = (new SmartXmlParser())->transform($test_xml); if ($test_arr !== $test_parr) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' #ORIGINAL Array [' . print_r($test_arr, 1) . ']' . "\n\n" . '#XML Array (from XML String): ' . print_r($test_parr, 1) . "\n\n" . '#XML String (from ORIGINAL Array): ' . "\n" . $test_xml; } //end if } //end if //-- $the_random_unicode_text = sha1($unicode_text . Smart::random_number(1000, 9999)) . '-' . $unicode_text . " \r\n\t" . '-' . Smart::uuid_10_num() . '-' . Smart::uuid_10_str() . '-' . Smart::uuid_10_seq(); //-- if ((string) $err == '') { $the_test = 'Data: Archive / Unarchive'; $tests[] = $the_test; if (SmartUtils::data_unarchive(SmartUtils::data_archive($the_random_unicode_text)) !== (string) $the_random_unicode_text) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $the_random_unicode_text . ']'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'Cache: Archive / Unarchive'; $tests[] = $the_test; if (SmartUtils::cache_variable_unarchive(SmartUtils::cache_variable_archive($the_random_unicode_text)) !== (string) $the_random_unicode_text) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $the_random_unicode_text . ']'; } //end if } //end if //-- //-- if ((string) $err == '') { $the_test = 'IDN: Domain Punycode Encode UTF-8 to ISO'; $tests[] = $the_test; if ((string) (new SmartPunycode())->encode($idn_domain_unicode) != (string) $idn_domain_iso) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $idn_domain_unicode . ' -> ' . $idn_domain_iso . ']'; } //end if } //end if if ((string) $err == '') { $the_test = 'IDN: Domain Punycode Decode ISO to UTF-8'; $tests[] = $the_test; if ((string) (new SmartPunycode())->decode($idn_domain_iso) != (string) $idn_domain_unicode) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $idn_domain_iso . ' -> ' . $idn_domain_unicode . ']'; } //end if } //end if //-- if ((string) $err == '') { $the_test = 'IDN: Email Punycode Encode UTF-8 to ISO'; $tests[] = $the_test; if ((string) (new SmartPunycode())->encode($idn_email_unicode) != (string) $idn_email_iso) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $idn_email_unicode . ' -> ' . $idn_email_iso . ']'; } //end if } //end if if ((string) $err == '') { $the_test = 'IDN: Email Punycode Decode ISO to UTF-8'; $tests[] = $the_test; if ((string) (new SmartPunycode())->decode($idn_email_iso) != (string) $idn_email_unicode) { $err = 'ERROR: ' . $the_test . ' FAILED ...' . ' [' . $idn_email_iso . ' -> ' . $idn_email_unicode . ']'; } //end if } //end if //-- //-- regex positive tests $arr_regex = ['number-integer' => [0, '75', '-101'], 'number-decimal' => [0, '0.0', '0.1', '75', '75.0', '75.1', '-555', '-555.0', '-555.1'], 'number-list-integer' => '1;2;30', 'number-list-decimal' => '1.0;2;30.44', 'url' => ['https://192.168.1.0', 'http://localhost', 'https://www.dom.ext', 'http://dom.ext/path?a=b&c=d%20#s'], 'domain' => ['domain.com', 'sdom.domain.org'], 'email' => ['root@localhost', '*****@*****.**', '*****@*****.**'], 'fax' => ['~+99-(0)999-123.456.78~'], 'macaddr' => ['00:0A:95:9d:68:16', '00-0a-95-9D-68-16'], 'ipv4' => ['192.168.0.1', '169.254.1.0', '1.0.0.1'], 'ipv6' => ['::1', '0000:0000:0000:0000:0000:0000:0000:0001', '2001:0db8:0000:0000:0000:ff00:0042:8329', '2001:dB8::2:1', '2001:db8::1', '3731:54:65fe:2::a7']]; //-- foreach ((array) $arr_regex as $key => $val) { //-- if (is_array($val)) { for ($i = 0; $i < Smart::array_size($val); $i++) { $the_test = 'Regex Validate Positive (#' . $i . '): ' . $key . ' [' . $val[$i] . ']'; $tests[] = $the_test; if (SmartValidator::validate_string($val[$i], $key) !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; break; } //end if if (stripos((string) $key, 'number-') === 0 and stripos((string) $key, 'number-list-') === false) { $the_test = 'Regex Validate Numeric Positive (#' . $i . '): ' . $key . ' [' . $val[$i] . ']'; $tests[] = $the_test; if (SmartValidator::validate_numeric_integer_or_decimal_values($val[$i], $key) !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; break; } //end if } //end if } //end for } else { $the_test = 'Regex Validate Positive: ' . $key . ' [' . $val . ']'; $tests[] = $the_test; if (SmartValidator::validate_string($val, $key) !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if if (stripos((string) $key, 'number-') === 0 and stripos((string) $key, 'number-list-') === false) { $the_test = 'Regex Validate Numeric Positive: ' . $key . ' [' . $val . ']'; $tests[] = $the_test; if (SmartValidator::validate_numeric_integer_or_decimal_values($val, $key) !== true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if } //end if else //-- if ((string) $err != '') { break; } //end if //-- } //end foreach //-- //-- regex negative tests $arr_regex = ['number-integer' => ['', '.', 'a9', '7B', '-9 ', ' -7'], 'number-decimal' => ['', '.0', '.1', '-.10', ' -7', '-9.0 '], 'number-list-integer' => '1;2.3;30', 'number-list-decimal' => '1.0;2;30.44a', 'url' => ['http:://192.168.1.0', 'https://local host', 'http:/www.dom.ext', 'https:dom.ext/path?a=b&c=d%20#s'], 'domain' => ['doMain.com', 's dom.domain.org', '.dom.ext', 'dom..ext', 'localhost', 'loc', 'dom.ext.'], 'email' => ['rooT@localhost', 'root@local host.loc', 'sometest-name.extra@do_m.ext'], 'fax' => ['~ +99-(0)999-123.456.78 ~'], 'macaddr' => ['00:0A:95:9z:68:16', '00-0Z-95-9D-68-16'], 'ipv4' => ['192.168.0.', '169..1.0', '1.0.1'], 'ipv6' => ['::x', '00z0:0000:0000:0000:0000:0000:0000:0001', '2001:0dx8:0000:0000:0000:ff00:0042:8329', '2001:WB8::2:1', '2001:@db8::1', '3731:54:65Qe:2::a7']]; //-- foreach ((array) $arr_regex as $key => $val) { //-- if (is_array($val)) { for ($i = 0; $i < Smart::array_size($val); $i++) { $the_test = 'Regex Validate Negative (#' . $i . '): ' . $key . ' [' . $val[$i] . ']'; $tests[] = $the_test; if (SmartValidator::validate_string($val[$i], $key) === true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; break; } //end if } //end for } else { $the_test = 'Regex Validate Negative: ' . $key . ' [' . $val . ']'; $tests[] = $the_test; if (SmartValidator::validate_string($val, $key) === true) { $err = 'ERROR: ' . $the_test . ' FAILED ...'; } //end if } //end if else //-- if ((string) $err != '') { break; } //end if //-- } //end foreach //-- //-- $endtest = '##### END TESTS ... #####'; //-- //-- if ((string) $err == '') { $img_sign = 'lib/core/img/sign_info.png'; $img_check = 'lib/core/img/q_completed.png'; $text_main = Smart::escape_js('<span style="color:#83B953;">Good ... Perfect :: グッド ... パーフェクト</span>'); $text_info = Smart::escape_js('<h2><span style="color:#83B953;">All</span> the SmartFramework Unicode String <span style="color:#83B953;">Tests PASSED on PHP</span><hr></h2><span style="font-size:14px;">' . Smart::nl_2_br(Smart::escape_html(implode("\n" . '* ', $tests) . "\n" . $endtest)) . '</span>'); } else { $img_sign = 'lib/core/img/sign_error.png'; $img_check = 'lib/core/img/q_warning.png'; $text_main = Smart::escape_js('<span style="color:#FF5500;">An ERROR occured ... :: エラーが発生しました ...</span>'); $text_info = Smart::escape_js('<h2><span style="color:#FF5500;">A test FAILED</span> when testing Unicode String Tests.<span style="color:#FF5500;"><hr>FAILED Test Details</span>:</h2><br><h3>' . Smart::escape_html($tests[Smart::array_size($tests) - 1]) . '</h3><br><span style="font-size:14px;"><pre>' . Smart::escape_html($err) . '</pre></span>'); } //end if else //-- //-- $html = <<<HTML <h1>SmartFramework Unicode Strings Tests: DONE ...</h1> <script type="text/javascript"> \tSmartJS_BrowserUtils.alert_Dialog( \t\t'<img src="{$img_sign}" align="right"><h1>{$text_main}</h1><hr><span style="color:#333333;"><img src="{$img_check}" align="right">{$text_info}<br>', \t\t'', \t\t'Unicode String Test Suite for SmartFramework: PHP', \t\t'725', \t\t'425' \t); </script> HTML; //-- //-- return $html; //-- }
private static function read_mime_message($y_enc_msg_file, $y_ctrl_key, $y_process_mode, $y_show_headers, $y_title, $y_link, $y_target) { // $y_process_mode : 'default' | 'print' | 'data-full' | 'data-reply' // $y_show_headers : 'default' | 'subject' (just for mode: 'default' | 'print') //-- $msg_decode_arr = (array) self::decode_mime_fileurl((string) $y_enc_msg_file, (string) $y_ctrl_key); //-- if ((string) $msg_decode_arr['error'] != '') { Smart::raise_error('ERROR: MIME Parser // Mesage File Decode: ' . $msg_decode_arr['error'], 'ERROR: MIME Parser // Mesage File Decode // See error log for details ...'); return ''; } //end if //-- //-- $the_message_eml = (string) trim((string) $msg_decode_arr['message-file']); $the_part_id = (string) trim((string) $msg_decode_arr['message-part']); //-- //-- if ((string) $the_message_eml == '' or !is_file((string) $the_message_eml)) { Smart::raise_error('ERROR: MIME Parser // Message File EMPTY or NOT FOUND !: ' . $the_message_eml, 'ERROR: MIME Parser // Mesage File Decode // See error log for details ...'); return ''; } //end if //-- if (substr((string) $the_message_eml, -4, 4) != '.eml') { Smart::raise_error('ERROR: MIME Parser // Message File Extension is not .eml !: ' . $the_message_eml, 'ERROR: MIME Parser // Mesage File Decode // See error log for details ...'); return ''; } //end if //-- //-- $out = ''; // init $reply_text = array(); // init //-- //== //-- $content = SmartFileSystem::read((string) $the_message_eml); $eml = new SmartMailerMimeDecode(); $head = $eml->get_header(SmartUnicode::sub_str((string) $content, 0, 65535)); // some messages fail with 8192 to decode ; a faster compromise would be 16384, but here we can use a higher value since is done once (text 65535) $msg = $eml->get_bodies((string) $content, (string) $the_part_id); unset($eml); unset($content); //-- //== //-- $reg_atts_num = 0; $reg_atts_list = ''; // list separed by \n //-- if (strlen($the_part_id) <= 0) { //-- display whole message $reg_is_part = 'no'; $skip_part_processing = 'no'; $skip_part_linking = 'no'; //-- } else { //-- display only a part of the message $reg_is_part = 'yes'; $skip_part_processing = 'no'; $skip_part_linking = 'yes'; //-- if (substr($the_part_id, 0, 4) == 'txt_') { //-- text part $tmp_part = $msg['texts'][$the_part_id]; $msg = array(); $msg['texts'][$the_part_id] = (array) $tmp_part; unset($tmp_part); //-- } else { //-- att / cid part $skip_part_processing = 'yes'; //-- if (!is_array($msg['attachments'][$the_part_id])) { // try to normalize name $the_part_id = trim(str_replace(' ', '', $the_part_id)); } //end if //-- $out = (string) $msg['attachments'][$the_part_id]['content']; // DO NO MORE ADD ANYTHING TO $out ... downloading, there are no risk of code injection //-- } //end if else //-- } //end if else //-- //-- if ((string) $y_process_mode == 'print') { $skip_part_linking = 'yes'; // skip links to other sub-parts like texts / attachments but not cids ! } elseif ((string) $y_process_mode == 'data-reply') { $skip_part_linking = 'yes'; } //end if //-- //-- if ((string) $skip_part_processing != 'yes') { //-- if ((string) $y_title != '') { $out .= (string) $y_title; // expects '' or valid HTML } //end if //-- $out .= '<!-- Smart.Framework // MIME MESSAGE HTML --><div align="left"><div id="mime_msg_box">'; //-- if (strlen($the_part_id) <= 0) { //-- $priority_img = ''; switch ((string) $head['priority']) { case '1': // high $priority_img = '<img src="lib/core/plugins/img/email/priority_high.png" align="left" alt="High Priority" title="High Priority">'; break; case '5': // low $priority_img = '<img src="lib/core/plugins/img/email/priority_low.png" align="left" alt="Low Priority" title="Low Priority">'; break; case '3': // medium // medium default: $priority_img = ''; //$priority_img = '<img src="lib/core/plugins/img/email/priority_normal.png" align="left" alt="Normal Priority" title="Normal Priority">'; } //end switch //-- if ((string) $skip_part_linking != 'yes') { // avoid display the print link when only a part is displayed $out .= '<a href="' . self::mime_link($y_ctrl_key, $the_message_eml, $the_part_id, $y_link, $eval_arr[0], $eval_arr[1], 'print') . '" target="' . $y_target . '__mimepart" data-smart="open.modal">' . '<img align="right" src="lib/core/img/buttons/bttn_print.png">' . '</a>'; } //end if //-- switch ((string) $y_show_headers) { case 'subject': //-- if ((string) $head['subject'] != '[?]') { $out .= '<h1><font size="4">' . Smart::escape_html($head['subject']) . '</font></h1><br>'; } //end if //-- break; case 'default': default: //-- if ((string) $head['subject'] != '[?]') { $out .= '<h1><font size="4"> ' . Smart::escape_html($head['subject']) . '</font>' . $priority_img . '</h1><hr>'; } //end if //-- if ((string) $head['date'] != '(?)') { $out .= '<font size="3"><b>Date:</b> ' . Smart::escape_html(date('Y-m-d H:i:s O', @strtotime($head['date']))) . '</font><br>'; } //end if //-- $out .= '<font size="2"><b>From:</b> ' . Smart::escape_html($head['from_addr']) . ' <i>' . Smart::escape_html($head['from_name']) . '</i>' . '</font><br>'; $out .= '<font size="2"><b>To:</b> ' . Smart::escape_html($head['to_addr']) . ' <i>' . Smart::escape_html($head['to_name']) . '</i>' . '</font><br>'; //-- if (strlen($head['cc_addr']) > 0) { $out .= '<font size="2"><b>Cc:</b> '; if (SmartUnicode::str_contains($head['cc_addr'], ',')) { $arr_cc_addr = (array) explode(',', (string) $head['cc_addr']); $arr_cc_name = (array) explode(',', (string) $head['cc_name']); $out .= '[@]'; for ($z = 0; $z < Smart::array_size($arr_cc_addr); $z++) { $out .= '<br> ' . Smart::escape_html(trim($arr_cc_addr[$z])) . ' <i>' . Smart::escape_html(trim($arr_cc_name[$z])) . '</i>'; } //end for } else { $out .= Smart::escape_html($head['cc_addr']) . ' <i>' . Smart::escape_html($head['cc_name']) . '</i>'; } //end if else $out .= '</font><br>'; } //end if //-- if (strlen($head['bcc_addr']) > 0) { $out .= '<font size="2"><b>Bcc:</b> '; $out .= Smart::escape_html($head['bcc_addr']) . ' <i>' . Smart::escape_html($head['bcc_name']) . '</i>'; $out .= '</font><br>'; } //end if //-- } //end switch //-- print attachments if (is_array($msg['attachments'])) { //-- $cnt = 0; //-- $atts = ''; // atts with link $xatts = ''; // atts without link //-- $tmp_att_img = '<img src="lib/core/plugins/img/email/attachment.png">'; //-- foreach ($msg['attachments'] as $key => $val) { //-- $tmp_arr = array(); $tmp_arr = (array) $val; //-- if ((string) $tmp_arr['mode'] == 'normal') { //-- $cnt += 1; //-- $eval_arr = SmartFileSysUtils::mime_eval((string) $tmp_arr['filename']); $tmp_att_name = Smart::escape_html((string) $tmp_arr['filename']); $tmp_att_size = Smart::escape_html((string) SmartUtils::pretty_print_bytes((int) $tmp_arr['filesize'], 1)); //-- $reg_atts_num += 1; $reg_atts_list .= str_replace(array("\r", "\n", "\t"), array('', '', ''), (string) $tmp_arr['filename']) . "\n"; //-- $atts .= '<div align="left"><table border="0" cellpadding="2" cellspacing="0" title="Attachment #' . $cnt . '"><tr><td>' . $tmp_att_img . '</td><td> </td><td><a href="' . self::mime_link($y_ctrl_key, $the_message_eml, $key, $y_link, $eval_arr[0], $eval_arr[1]) . '" target="' . $y_target . '__mimepart" data-smart="open.modal"><font size="1"><b>' . $tmp_att_name . '</b></font></a></td><td><font size="1"> <b><i>' . $tmp_att_size . '</i></b></font></td></tr></table></div>'; $xatts .= '<div align="left">' . $tmp_att_img . ' <font size="1">' . $tmp_att_name . ' <i>' . $tmp_att_size . '</i></font></div>'; //-- } //end if //-- } //end foreach //-- if ($cnt > 0) { if ((string) $skip_part_linking == 'yes') { // avoid displaying attachments links when only a part is displayed $out .= '<hr><div align="left">' . $xatts . '</div>'; } else { $out .= '<hr><div align="left">' . $atts . '</div>'; } //end if } //end if //-- $tmp_att_name = ''; $tmp_att_size = ''; //-- $atts = ''; $xatts = ''; //-- } //end if //-- } else { //-- $out .= '<div align="right"><font size="1">' . Smart::escape_html($head['subject']) . ' // ' . 'MIME Part ID : <i>' . Smart::escape_html($the_part_id) . '</i></font></div>'; //-- } //end if //-- print text bodies $markup_multipart = 'This is a multi-part message in MIME format.'; if (is_array($msg['texts'])) { //-- check similarity and prepare the HTML parts $buff = ''; $buff_id = ''; $xbuff = ''; $xbuff_id = ''; $skips = array(); $numparts = 0; foreach ($msg['texts'] as $key => $val) { //-- $numparts += 1; //-- if ((string) $val['type'] == 'text') { // assure we don't print other things //-- if ((string) $val['mode'] == 'text/plain') { // Plain TEXT //-- sanitize text $val['content'] = '<!-- MIMEREAD:PART:TEXT -->' . Smart::escape_html($val['content']); $val['content'] = str_replace(array("\r\n", "\r", "\n"), array("\n", "\n", '<br>'), $val['content']); $val['content'] = SmartParser::text_urls($val['content']); //-- $msg['texts'][$key]['content'] = $val['content']; // rewrite back //-- assign buffer $buff = SmartUnicode::sub_str($val['content'], 0, 16384); $buff_id = $key; //-- $percent_similar = 0; if (strlen($the_part_id) <= 0) { @similar_text($buff, $markup_multipart, $percent_similar); if ($percent_similar >= 25) { // 25% at least similarity $skips[$buff_id] = $percent_similar; // skip this alternate html part ... } //end if } //end if //-- // clean buffer $xbuff = ''; $xbuff_id = ''; //-- } else { // HTML Parts :: check similarity //-- $val['content'] = '<!-- MIMEREAD:PART:HTML -->' . preg_replace("'" . '<\\?xml' . ".*?" . '>' . "'si", " ", (string) $val['content']); // remove always fake "< ?" as "< ?xml" (fixed with /u modifier for unicode strings) //-- if (SmartUnicode::str_contains($val['content'], '<' . '?') or SmartUnicode::str_contains($val['content'], '?' . '>') or SmartUnicode::str_contains($val['content'], '<' . '%') or SmartUnicode::str_contains($val['content'], '%' . '>')) { //-- $val['content'] = @highlight_string($val['content'], 1); // highlight the PHP* code & sanitize the parts //-- } else { //-- sanitize this html part $val['content'] = (new SmartHtmlParser($val['content']))->get_clean_html(); //-- replace cid images $tmp_matches = array(); preg_match_all('/<img[^>]+src=[\'"]?(cid:)([^\'"]*)[\'"]?[^>]*>/si', (string) $val['content'], $tmp_matches); // fix: previous was just i (not si) ; modified on 160205 // $tmp_matches[0][i] : the full link // $tmp_matches[1][i] : 'cid:' // $tmp_matches[2][i] : cid part id for ($cids = 0; $cids < Smart::array_size($tmp_matches[0]); $cids++) { $tmp_replace_cid_link = ''; $tmp_replace_cid_link = (string) $tmp_matches[0][$cids]; $tmp_replace_cid_link = str_replace("\n", ' ', $tmp_replace_cid_link); $tmp_replace_cid_link = str_replace($tmp_matches[1][$cids] . $tmp_matches[2][$cids], self::mime_link($y_ctrl_key, $the_message_eml, 'cid_' . $tmp_matches[2][$cids], $y_link, 'image', 'inline'), $tmp_replace_cid_link); //echo '<pre>'.Smart::escape_html($tmp_replace_cid_link).'</pre>'; $val['content'] = str_replace($tmp_matches[0][$cids], $tmp_replace_cid_link, $val['content']); } //end for $tmp_matches = array(); //-- } //end if else //-- $msg['texts'][$key]['content'] = $val['content']; // rewrite back //-- $xbuff = SmartUnicode::sub_str(Smart::striptags($val['content']), 0, 16384); $xbuff_id = $key; //-- $percent_similar = 0; if (strlen($the_part_id) <= 0) { @similar_text($buff, $xbuff, $percent_similar); if ($percent_similar >= 15) { // 15% at least similarity $skips[$buff_id] = $percent_similar; // skip this alternate text part ... } //end if } //end if //-- // clean buffer $buff = ''; $buff_id = ''; //-- } //end if //-- } //end if //-- } //end foreach //-- if ($numparts <= 1) { $skips = array(); // disallow skips if only one part } //end if //-- print bodies except the skipped by similarity $out .= '<hr>'; //-- $cnt = 0; foreach ($msg['texts'] as $key => $val) { //-- if ((string) $val['type'] == 'text') { // assure we don't print other things //-- $cnt += 1; //-- $eval_arr = array(); $eval_arr = SmartFileSysUtils::mime_eval('part_' . $cnt . '.html', 'inline'); //-- $tmp_link_pre = '<span title="Mime Part #' . $cnt . ' ( ' . Smart::escape_html(strtolower($val['mode']) . ' : ' . strtoupper($val['charset'])) . ' )"><a href="' . self::mime_link($y_ctrl_key, $the_message_eml, $key, $y_link, $eval_arr[0], $eval_arr[1], 'minimal') . '" target="' . $y_target . '__mimepart" data-smart="open.modal">'; $tmp_link_pst = '</a></span>'; //-- if (strlen($skips[$key]) <= 0) { // print part if not skipped by similarity ... //-- if ((string) $skip_part_linking == 'yes') { // avoid display sub-text part links when only a part is displayed $tmp_pict_img = ''; } else { $tmp_pict_img = '<div align="right">' . $tmp_link_pre . '<img src="lib/framework/img/mark_right.gif">' . $tmp_link_pst . '</div>'; } //end if //-- if ((string) $y_process_mode == 'data-reply') { if (strlen($reply_text['message']) <= 0) { $reply_text['message'] = (string) $val['content']; } //end if } else { $out .= $tmp_pict_img; $out .= $val['content']; $out .= '<br><hr><br>'; } //end if //-- } else { //-- if ((string) $skip_part_linking != 'yes') { // for replies, avoid display sub-text part links when only a part is displayed if ((string) $y_process_mode == 'data-reply') { // nothing } else { $out .= '<div align="right">' . '<span title="' . '~' . Smart::escape_html(Smart::format_number_dec($skips[$key], 0, '.', ',') . '%') . '"> </span>' . $tmp_link_pre . '<img src="lib/framework/img/mark_check.gif">' . $tmp_link_pst . '</div>'; } //end if else } //end if //-- } //end if else //-- } //end if //-- } //end foreach //-- } //end if //-- $out .= '</div></div><!-- END MIME MESSAGE HTML -->'; //-- } //end if else //-- //-- if ((string) $y_process_mode == 'data-full') { // output an array with message and all header info as data structure //-- return array('message' => (string) $out, 'message-id' => (string) $head['message-id'], 'in-reply-to' => (string) $head['in-reply-to'], 'from' => (string) $head['from_addr'], 'to' => (string) $head['to_addr'], 'cc' => (string) $head['cc_addr'], 'date' => (string) $head['date'], 'atts_num' => (int) $reg_atts_num, 'atts_lst' => (string) $reg_atts_list, 'filepath' => (string) $the_message_eml, 'is_part' => (string) $reg_is_part); //-- } elseif ((string) $y_process_mode == 'data-reply') { // output a special array for replies only //-- $reply_text['message'] = (string) $reply_text['message']; // this comes from above $reply_text['from'] = (string) $head['from_addr']; $reply_text['to'] = (string) $head['to_addr']; $reply_text['cc'] = (string) $head['cc_addr']; $reply_text['date'] = (string) $head['date']; $reply_text['subject'] = (string) $head['subject']; $reply_text['message-id'] = (string) $head['message-id']; $reply_text['in-reply-to'] = (string) $head['in-reply-to']; //-- return (array) $reply_text; //-- } else { // 'default' or 'print' :: message as html view //-- return (string) $out; //-- } //end if //-- }