/** * Performs the decoding. Decodes the body string passed to it * If it finds certain content-types it will call itself in a * recursive fashion * * @param string Header section * @param string Body section * @return object Results of decoding process * @access private */ function _decode($headers, $body, $default_ctype = 'text/plain') { $return = new stdClass(); $headers = $this->_parseHeaders($headers); foreach ($headers as $value) { if (isset($return->headers[strtolower($value['name'])]) and !is_array($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]); $return->headers[strtolower($value['name'])][] = $value['value']; } elseif (isset($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])][] = $value['value']; } else { $return->headers[strtolower($value['name'])] = $value['value']; } } reset($headers); while (list($key, $value) = each($headers)) { $headers[$key]['name'] = strtolower($headers[$key]['name']); switch ($headers[$key]['name']) { case 'content-type': $content_type = $this->_parseHeaderValue($headers[$key]['value']); if (preg_match('/([0-9a-z+.-]+)\\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) { $return->ctype_primary = $regs[1]; $return->ctype_secondary = $regs[2]; } if (isset($content_type['other'])) { while (list($p_name, $p_value) = each($content_type['other'])) { $return->ctype_parameters[$p_name] = $p_value; } } break; case 'content-disposition': $content_disposition = $this->_parseHeaderValue($headers[$key]['value']); $return->disposition = $content_disposition['value']; if (isset($content_disposition['other'])) { while (list($p_name, $p_value) = each($content_disposition['other'])) { $return->d_parameters[$p_name] = $p_value; } } break; case 'content-transfer-encoding': $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']); break; } } if (isset($content_type)) { switch (strtolower($content_type['value'])) { case 'text/plain': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $encoding, $return) : $body : null; break; case 'text/html': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $encoding, $return) : $body : null; break; case 'multipart/parallel': case 'multipart/report': // RFC1892 // RFC1892 case 'multipart/signed': // PGP // PGP case 'multipart/digest': case 'multipart/alternative': case 'multipart/related': case 'multipart/mixed': if (!isset($content_type['other']['boundary'])) { $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; return false; } $default_ctype = strtolower($content_type['value']) === 'multipart/digest' ? 'message/rfc822' : 'text/plain'; $parts = $this->_boundarySplit($body, $content_type['other']['boundary']); for ($i = 0; $i < count($parts); $i++) { list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]); $part = $this->_decode($part_header, $part_body, $default_ctype); if ($part === false) { $part = $this->raiseError($this->_error); } $return->parts[] = $part; } break; case 'message/rfc822': $obj = new mimeDecode($body); $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies)); unset($obj); break; default: if (!isset($content_transfer_encoding['value'])) { $content_transfer_encoding['value'] = '7bit'; } $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body : null; break; } } else { $ctype = explode('/', $default_ctype); $return->ctype_primary = $ctype[0]; $return->ctype_secondary = $ctype[1]; $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body) : $body : null; } return $return; }
function workPopfetcher(&$eventData) { global $serendipity; static $debug = null; if ($debug === null) { $debug = $this->debug = serendipity_db_bool($this->get_config('debug')); } // updertEntry() will not function unless this is set: $serendipity['POST']['properties']['fake'] = 'fake'; $_SESSION['serendipityRightPublish'] = true; $this->out('<h3>' . PLUGIN_MF_NAME . ' v' . POPFETCHER_VERSION . ' @ ' . date("D M j G:i:s T Y") . '</h3>'); $debug_file = null; // DEVELOPERS: If set to a filename, you can bypass fetching POP and use a file instead. $debug_mail = $this->get_config('debug_mail'); if (strlen($debug_mail) != '' && file_exists($debug_mail)) { $debug_file = $debug_mail; } if ($debug_file != null) { $this->debug = true; } $authorid = $this->get_config('author'); if (empty($authorid) || $authorid == 'empty') { $authorid = isset($serendipity['authorid']) ? $serendipity['authorid'] : 1; } $mailserver = trim($this->get_config('mailserver')); $mailport = $this->get_config('mailport'); $mailuser = trim($this->get_config('mailuser')); $mailpass = trim($this->get_config('mailpass')); $timeout = $this->get_config('timeout'); $deleteflag = serendipity_db_bool($this->get_config('deleteflag')); $apopflag = serendipity_db_bool($this->get_config('apopflag')); $blogflag = serendipity_db_bool($this->get_config('blogflag')); $striptagsflag = serendipity_db_bool($this->get_config('striptagsflag')); $publishflag = serendipity_db_bool($this->get_config('publishflag')); $onlyfrom = $this->get_config('onlyfrom', ''); $maildir = trim($this->get_config('maildir')); $category = trim($this->get_config('category')); $adflag = serendipity_db_bool($this->get_config('adflag')); $plaintext_is_body_flag = serendipity_db_bool($this->get_config('plaintext_is_body')); $plaintext_use_extended_flag = serendipity_db_bool($this->get_config('plaintext_use_extended')); $list_virus = array('.pif', '.vbs', '.scr', '.bat', '.com', '.exe'); $list_imagetype = array('jpg', 'jpeg', 'gif', 'png', 'x-png', 'pjpeg'); $list_imageext = array('.gif', '.jpg', '.png', '.jpeg'); $list_ignore = array('.smil'); $output = ''; $dirpath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $maildir; $dupcount = 0; // Upload directory must end with a slash character if (strrchr($dirpath, '/') != '/') { $output = MF_ERROR7; $this->out('<br />' . $output . '<br />'); return true; } // Upload directory must be writable if (!is_writable($dirpath)) { $output = MF_ERROR6; $this->out('<br />' . $output . '<br />'); return true; } if (serendipity_db_bool($this->get_config('subfolder'))) { $dirpath = $dirpath . '/' . date('Y'); if (!is_dir($dirpath)) { mkdir($dirpath); } $dirpath = $dirpath . '/' . date('m') . '/'; if (!is_dir($dirpath)) { mkdir($dirpath); } $maildir .= date('Y') . '/' . date('m') . '/'; } $maildir = str_replace('//', '/', $maildir); // Category (if specified) must exist if (!empty($category)) { $cid = serendipity_fetchCategoryInfo(null, $category); if ($cid == false) { $output = MF_ERROR8; $this->out('<br />' . $output . '<br />'); return true; } } if ($debug_file === null) { // Create new instance of POP3 connection $pop3 = new POP3($mailserver, $timeout); // Attempt to connect to mail server if (!$pop3->connect($mailserver, $mailport)) { $output = MF_ERROR1 . ': ' . $pop3->ERROR; $this->out('<br />' . $output . '<br />'); return true; } // Try APOP login if requested, otherwise, regular login if ($apopflag) { $Count = $pop3->apop($mailuser, $mailpass); } else { $Count = $pop3->login($mailuser, $mailpass); } // Check for error retrieving number of msgs in mailbox if ($Count === false or $Count == -1) { $output = MF_ERROR2 . ': ' . $pop3->ERROR; $this->out('<br />' . $output . '<br />'); return true; } // If no msgs in mailbox, exit if ($Count == 0) { $output = MF_MSG1; $this->out('<br />' . $output . '<br />'); return true; } // Get the list of email msgs $msglist = $pop3->uidl(); // Check for error in getting list of email msgs if (!is_array($msglist)) { $output = MF_ERROR3 . ': ' . $pop3->ERROR; $this->out('<br />' . $output . '<br />'); $pop3->quit(); return true; } } else { // Developer debug switch which reads from a file and not a POP3 connection. $dfiles = explode(':', $debug_file); $Count = count($dfiles); } $Message = array(); // ************************ // Fetch each email msg and attachments and put it into the $Message array // ************************ for ($i = 1; $i <= $Count; $i++) { // Messages are numbered starting with '1', not '0' if ($debug_file === null) { $MessArray = $pop3->get($i); } else { $MessArray = file($dfiles[$i - 1]); } // Should have an array. If not, there was an error if (!$MessArray or gettype($MessArray) != "array") { $output = MF_ERROR4 . ': ' . $pop3->ERROR; $this->out('<br />' . $output . '<br />'); $pop3->quit(); return true; } // Extract the msg from MessArray and store it in Message $Message[$i - 1] = ''; while (list($lineNum, $line) = each($MessArray)) { $Message[$i - 1] .= $line; } // Delete the msg if ($deleteflag && $debug_file === null) { $pop3->delete($i); } } if ($debug_file === null) { // Close the connection to the mail server $pop3->quit(); } // ************************ // Message processing section starts here // ************************ $this->out('<br />' . MF_MSG2 . ': ' . $Count . '<br />'); if ($deleteflag) { $this->out(MF_MSG11 . '<br />'); } else { $this->out(MF_MSG12 . '<br />'); } $params['include_bodies'] = true; $params['decode_bodies'] = true; $params['decode_headers'] = true; // Process each email msg foreach ($Message as $M) { $decode = new mimeDecode($M); #$this->out(print_r($M, true)); $s = $decode->decode($params); #$this->out(print_r($s, true)); if ($debug_file !== null) { // DEBUG Struct // echo '<pre>'; // print_r($s); // echo '</pre>'; } if ($s == null) { $this->out('<br />' . MF_ERROR9); return true; } $date = isset($s->headers['date']) ? $s->headers['date'] : MF_MSG3; $from = isset($s->headers['from']) ? $s->headers['from'] : MF_MSG4; if (!empty($onlyfrom) && trim($from) != trim($onlyfrom)) { $this->out('<br />' . sprintf(MF_ERROR_ONLYFROM, '"' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($from) : htmlspecialchars($from, ENT_COMPAT, LANG_CHARSET)) . '"', '"' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($onlyfrom) : htmlspecialchars($onlyfrom, ENT_COMPAT, LANG_CHARSET)) . '"')); continue; } if (empty($s->ctype_parameters['charset'])) { $s->ctype_parameters['charset'] = 'UTF-8'; } if (strtolower($s->ctype_parameters['charset']) == 'us-ascii') { $s->ctype_parameters['charset'] = 'ISO-8859-1'; } $subject = $this->decode(isset($s->headers['subject']) ? $s->headers['subject'] : MF_MSG17, $s->ctype_parameters['charset'], true); #$subject = $this->decode(isset($s->headers['subject']) ? $s->headers['subject'] : MF_MSG17, $s->ctype_parameters['charset']); #$subject = isset($s->headers['subject']) ? $s->headers['subject'] : MF_MSG17; $this->out('<hr />'); $this->out(MF_MSG5 . $date . '<br />'); $this->out(MF_MSG6 . (function_exists('serendipity_specialchars') ? serendipity_specialchars($from) : htmlspecialchars($from, ENT_COMPAT, LANG_CHARSET)) . '<br />'); $this->out(MF_MSG16 . $subject . '<br />'); // Find the author associated with the from address and // set them as the author of the post. $useAuthor = null; if ($authorid == 'byemail') { // We don't have tons of authors .. like two so this isn't a problem // If I wanted this to be "production" quality, I would have to add // a new s9y function that let you retrieve an author given an email address // I suppose I could go with a convention that the base name of the // email address had to be the author's name too. Lookup by name is // supported by s9y. $auths = serendipity_fetchUsers(); $vals = array(); $clean = strtolower($this->cleanEmail($from)); foreach ($auths as $auth) { if (isset($auth['email']) && strtolower($auth['email']) == $clean) { $useAuthor = $auth['authorid']; break; } } if (is_null($useAuthor)) { $this->out('<br />' . sprintf(MF_ERROR_NOAUTHOR, '"' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($clean) : htmlspecialchars($clean, ENT_COMPAT, LANG_CHARSET)) . '"')); continue; } } else { $useAuthor = $authorid; } $postattach = array(); $postbody = array(); $postex = array(); $verizonflag = false; $tmobileflag = false; $firstattachment = false; $firsttext = false; $o2flag = stristr($from, 'mms.o2online.de') !== FALSE; // A mail message with attachments is a series of "parts" if (isset($s->parts) and is_array($s->parts)) { if ($debug_file !== null || $debug) { $this->out('<pre>' . print_r($s->parts, true) . '</pre>'); } $textpref = $this->get_config('textpref'); if ($textpref != 'both') { $has_html = false; $has_text = false; $parts_html = array(); $parts_text = array(); foreach ($s->parts as $idx => $p) { if ($p->ctype_primary == 'text' && $p->ctype_secondary == 'html') { if ($debug_file !== null || $debug) { $this->out("This part is text/html.<br />\n"); } $has_html = true; $parts_html[] = $idx; } elseif ($p->ctype_primary == 'text' && $p->ctype_secondary == 'plain') { if ($debug_file !== null || $debug) { $this->out("This part is text/plain.<br />\n"); } $has_text = true; $parts_text[] = $idx; } } if ($debug_file !== null || $debug) { $this->out("Preference is: {$textpref}.<br />\n"); } if ($textpref == 'text' && $has_html) { if ($debug_file !== null || $debug) { $this->out("Preference is text/plain.<br />\n"); } foreach ($parts_html as $pidx) { if ($debug_file !== null || $debug) { $this->out("Stripping HTML part {$pidx}, because preference is plaintext.<br />\n"); } unset($s->parts[$pidx]); } } if ($textpref == 'html' && $has_text) { if ($debug_file !== null || $debug) { $this->out("Preference is text/html.<br />\n"); } foreach ($parts_text as $pidx) { if ($debug_file !== null || $debug) { $this->out("Stripping text part {$pidx}, because preference is html.<br />\n"); } unset($s->parts[$pidx]); } } } foreach ($s->parts as $p) { if ($debug_file !== null || $debug) { $this->out("Analyzing mail:<br />\n Disposition: {$p->disposition}<br />\n Body: " . (isset($p->body) ? 'Set' : 'Not Set') . "<br />\n Primary CType: {$p->ctype_primary}<br />\n Secondary CType: {$p->ctype_secondary}<br />\n Filename: {$p->d_parameters[filename]}\n .<br />\n"); } // Handle msgs with attachments and messages with images that are inlined if (isset($p->disposition) and $p->disposition == 'attachment' and isset($p->body) or isset($p->disposition) and $p->disposition == 'inline' and isset($p->body) and $p->ctype_primary == 'image' or !empty($p->body) and $p->ctype_primary == 'image') { $this->handleImage($p, $debug, $debug_file, $tmobileflag, $adflag, $dirpath, $list_virus, $list_ignore, $plaintext_is_body_flag, $firsttext, $plaintext_use_extended_flag, $postex, $postbody, $dupcount, $maildir, $authorid, $list_imagetype, $list_imageext, $subject); } elseif (strtolower($p->ctype_primary) == 'text' and isset($p->body)) { if ($debug_file !== null || $debug) { $this->out("<br />\nRecognized text part.<br />\n"); } if (trim($subject) == SPRINTPCS_IDENT_PICTURE) { $p->body = sprintpcs_pictureshare($maildir, $p->body, $authorid); if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } if (trim($subject) == SPRINTPCS_IDENT_ALBUM) { $p->body = sprintpcs_albumshare($maildir, $p->body, $authorid); if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } if (trim($subject) == SPRINTPCS_IDENT_VIDEO) { $p->body = sprintpcs_videoshare($maildir, $p->body, $authorid); if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } if (stristr($subject, CINGULAR_IDENT_PICTURE)) { $p->body = cingular_photo($maildir, $p->body); if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } if (stristr($p->body, VERIZON_IDENT_PICTURE)) { $p->body = verizon_photo($maildir, $p->body); $verizonflag = true; if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } // Because text and HTML attachments get inlined // sometimes (notably Hotmail), // we want to collect them all and attach them to the // regular msg body $bodytext = trim($this->decode($p->body, $p->ctype_parameters['charset'])); if (empty($bodytext)) { continue; } // Strip evil HTML if (preg_match('@<body[^>]*>(.+)</body>@imsU', $bodytext, $m)) { if ($debug_file !== null || $debug) { $this->out("Reduced HTML text.<br />\n"); } $bodytext = $m[1]; } if ($adflag && preg_match('@T\\-Mobile MMS@', $bodytext) && preg_match('@http://www\\.T\\-Mobile\\.(de|nl|com)/mms@', $bodytext)) { if ($debug_file !== null || $debug) { $this->out("<br />\nSkipping T-Mobile ad.<br />\n"); } continue; } if ($firsttext && $plaintext_use_extended_flag) { $postex[] = $bodytext; } else { $postbody[] = $bodytext; $firsttext = true; } } elseif (is_array($p->parts)) { if ($debug_file !== null || $debug) { $this->out("<br />\nRecognized text/multipart.<br />\n"); } if ($textpref != 'both') { $has_html = false; $has_text = false; $parts_html = array(); $parts_text = array(); foreach ($p->parts as $idx => $subp) { if ($subp->ctype_primary == 'text' && $subp->ctype_secondary == 'html') { $has_html = true; $parts_html[] = $idx; } elseif ($subp->ctype_primary == 'text' && $subp->ctype_secondary == 'plain') { $has_text = true; $parts_text[] = $idx; } } if ($textpref == 'text' && $has_html) { foreach ($parts_html as $pidx) { if ($debug_file !== null || $debug) { $this->out("Stripping HTML part {$pidx}, because preference is plaintext.<br />\n"); } unset($p->parts[$pidx]); } } if ($textpref == 'html' && $has_text) { foreach ($parts_text as $pidx) { if ($debug_file !== null || $debug) { $this->out("Stripping text part {$pidx}, because preference is html.<br />\n"); } unset($p->parts[$pidx]); } } } foreach ($p->parts as $subpart) { if ($subpart->ctype_primary == 'text' && $subpart->ctype_secondary == 'html' && $o2flag) { $bodytext = trim($this->decode(popfetcher_provider_o2::getBody($subpart->body), $subpart->ctype_parameters['charset'])); if (empty($bodytext)) { continue; } if ($firsttext && $plaintext_use_extended_flag) { $postex[] = $bodytext; } else { $postbody[] = $bodytext; $firsttext = true; } } elseif ($subpart->ctype_primary == 'text') { $bodytext = trim($this->decode($subpart->body, $subpart->ctype_parameters['charset'])); if (preg_match('@<body[^>]*>(.+)</body>@imsU', $bodytext, $m)) { if ($debug_file !== null || $debug) { $this->out("Reduced HTML text.<br />\n"); } $bodytext = $m[1]; } if ($firsttext && $plaintext_use_extended_flag) { $postex[] = $bodytext; } else { $postbody[] = $bodytext; $firsttext = true; } } elseif ($subpart->ctype_primary == 'image') { // Handle inline multipart images $this->handleImage($subpart, $debug, $debug_file, $tmobileflag, $adflag, $dirpath, $list_virus, $list_ignore, $plaintext_is_body_flag, $firsttext, $plaintext_use_extended_flag, $postex, $postbody, $dupcount, $maildir, $authorid, $list_imagetype, $list_imageext, $subject); } } } else { if ($debug_file !== null || $debug) { $this->out("<br />\nRecognized unknown part.<br />\n"); } if ($p->disposition == 'inline' && isset($p->d_parameters['filename'])) { // Use makeFilename to get rid of spaces and other oddities $filename = serendipity_makeFilename($p->d_parameters['filename']); // if no file extension exists, add default .txt file extension if (!strrpos($filename, ".")) { $filename = $filename . 'txt'; } if ($debug_file !== null || $debug) { $this->out("<br />\nStoring attachment as {$filename}<br />\n"); } $this->out('<br />' . MF_MSG8 . $filename); $fullname = $dirpath . $filename; // Extract file extension and file name for various processing $ext = substr(strrchr($filename, "."), 0); $name = substr($filename, 0, strrpos($filename, ".")); // Skip message and all attachments if possible virus found $lext = strtolower($ext); if (in_array($lext, $list_virus)) { $output = MF_MSG19 . ': ' . $filename; $this->out('<br />' . $output . '<br />'); continue 2; } if (in_array($lext, $list_ignore)) { $this->out('<br />' . MF_MSG20 . '<br />'); continue; } // Check for duplicate filename. Give dup file name file.time().dup.ext if (is_file($fullname)) { $this->out('<br />' . MF_MSG14 . $filename); $name = $name . time() . $dupcount . 'dup'; $filename = $name . $ext; $fullname = $dirpath . $filename; $dupcount++; } $fp = fopen($fullname, 'w'); if (!$fp) { $this->out('<br />' . MF_ERROR5 . $fullname); return true; } fwrite($fp, $p->body); fclose($fp); serendipity_insertImageInDatabase($filename, $maildir, $authorid, NULL); $attlink = '<a class="popfetcherfile" href="' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $maildir . $filename . '" target="_blank">' . $filename . '</a>'; // Inline pictures to match the structure of the mail if ($plaintext_is_body_flag) { // Only the first image is embedded in body, or if no extended entry is used if (!$firstattachment || !$plaintext_use_extended_flag) { $postbody[] = $attlink; } else { $postex[] = $attlink; $firsttext = true; } } else { // Standard attachment mode $postattach[] = $attlink; } $firstattachment = true; $this->out('<br />' . MF_MSG13 . $filename); } $this->out('<br />' . MF_MSG9); // Tmobile sends a weird nested text and html // sub-attachment (at least the nokia does) if (isset($s->headers['x-operator']) and strtolower($s->headers['x-operator']) == TMOBILE_IDENT_PICTURE) { $p->body = tmobile_photo($maildir, $p->body); $tmobileflag = true; if (strstr($p->body, ERROR_CHECK)) { $this->out('<br />' . $p->body); return true; } } } } if ($blogflag) { if (trim($subject) == SPRINTPCS_IDENT_ALBUM || trim($subject) == SPRINTPCS_IDENT_PICTURE || trim($subject) == SPRINTPCS_IDENT_VIDEO || stristr($subject, CINGULAR_IDENT_PICTURE) || ($verizonflag and $subject == MF_MSG17) || ($tmobileflag and $subject == MF_MSG17)) { $time = strtotime($s->headers['date']); $stamp = $time == -1 ? date("l, F j, Y, g:ia") : date("l, F j, Y, g:ia", $time); $subject = MF_MSG23 . $stamp; } $msgbody = implode("<br />\n", $postbody); $msgbody .= implode("<br />\n", $postattach); //New draft post $entry = $this->workEntry($subject, $msgbody, $useAuthor, $postex, $cid, $s); } } elseif (strtolower($s->ctype_primary) == 'text') { // Email msg with no attachments if ($blogflag) { if (trim($subject) == SPRINTPCS_IDENT_ALBUM || trim($subject) == SPRINTPCS_IDENT_PICTURE || trim($subject) == SPRINTPCS_IDENT_VIDEO || stristr($subject, CINGULAR_IDENT_PICTURE) || (stristr($s->body, VERIZON_IDENT_PICTURE) and $subject == MF_MSG17) || ($tmobileflag and $subject == MF_MSG17)) { $time = strtotime($s->headers['date']); $stamp = $time == -1 ? date("l, F j, Y, g:ia") : date("l, F j, Y, g:ia", $time); $subject = MF_MSG23 . $stamp; } $bodytext = trim($this->decode($s->body, $s->ctype_parameters['charset'])); $entry = $this->workEntry($subject, $bodytext, $useAuthor, $postex, $cid, $s); } else { $this->out('<br />' . MF_MSG20); } } else { $this->out('<br />' . MF_MSG10 . '<br />'); } } echo '<br /><hr />'; }