break; case 'directoryDelete': if (!serendipity_checkPermission('adminImagesDirectories')) { return; } $data['case_directoryDelete'] = true; $data['dir'] = serendipity_specialchars($serendipity['GET']['dir']); $data['formtoken'] = serendipity_setFormToken(); $data['basename_dir'] = basename(serendipity_specialchars($serendipity['GET']['dir'])); break; case 'directoryDoCreate': if (!serendipity_checkFormToken() || !serendipity_checkPermission('adminImagesDirectories')) { return; } $data['case_directoryDoCreate'] = true; $new_dir = serendipity_uploadSecure($serendipity['POST']['parent'] . '/' . serendipity_makeFilename($serendipity['POST']['name']), true); $new_dir = str_replace(array('..', '//'), array('', '/'), $new_dir); $nd = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir; serendipity_plugin_api::hook_event('backend_directory_create', $nd); /* TODO: check if directory already exist */ if (is_dir($nd) || @mkdir($nd)) { $data['print_DIRECTORY_CREATED'] = sprintf(DIRECTORY_CREATED, $serendipity['POST']['name']); @umask(00); @chmod($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir, 0777); // Apply parent ACL to new child. $array_parent_read = serendipity_ACLGet(0, 'directory', 'read', $serendipity['POST']['parent']); $array_parent_write = serendipity_ACLGet(0, 'directory', 'write', $serendipity['POST']['parent']); if (!is_array($array_parent_read) || count($array_parent_read) < 1) { $parent_read = array(0); } else { $parent_read = array_keys($array_parent_read);
/** * Send a comment notice to the admin/author of an entry * * @access public * @param int ID of the comment that has been made * @param string Author's email address to send the mail to * @param string The name of the sender * @param string The URL of the sender * @param int The ID of the entry that has been commented * @param string The title of the entry that has been commented * @param string The text of the comment * @param string The type of the comment (normal|trackback) * @param boolean Toggle Whether comments to this entry need approval * @return boolean Return success of sending the mails */ function serendipity_sendComment($comment_id, $to, $fromName, $fromEmail, $fromUrl, $id, $title, $comment, $type = 'NORMAL', $moderate_comment = false) { global $serendipity; if (empty($fromName)) { $fromName = ANONYMOUS; } $entryURI = serendipity_archiveURL($id, $title, 'baseURL'); $path = $type == 'TRACKBACK' ? 'trackback' : 'comment'; // Check for using Tokens if ($serendipity['useCommentTokens']) { $token = md5(uniqid(rand(), 1)); $path = $path . "_token_" . $token; //Delete any comment tokens older than 1 week. serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options\n WHERE okey LIKE 'comment_%' AND name < " . (time() - 604800)); // Issue new comment moderation hash serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}options (name, value, okey)\n VALUES ('" . time() . "', '" . $token . "', 'comment_" . $comment_id . "')"); } $deleteURI = serendipity_rewriteURL(PATH_DELETE . '/' . $path . '/' . $comment_id . '/' . $id . '-' . serendipity_makeFilename($title) . '.html', 'baseURL'); $approveURI = serendipity_rewriteURL(PATH_APPROVE . '/' . $path . '/' . $comment_id . '/' . $id . '-' . serendipity_makeFilename($title) . '.html', 'baseURL'); if ($type == 'TRACKBACK') { /******************* TRACKBACKS *******************/ $subject = ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_TRACKBACK_TO . ' ' . $title; $text = sprintf(A_NEW_TRACKBACK_BLAHBLAH, $title) . "\n" . "\n" . REQUIRES_REVIEW . ': ' . ($moderate_comment ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '') . "\n" . LINK_TO_ENTRY . ': ' . $entryURI . "\n" . 'Weblog ' . NAME . ': ' . stripslashes($fromName) . "\n" . LINK_TO_REMOTE_ENTRY . ': ' . $fromUrl . "\n" . "\n" . EXCERPT . ':' . "\n" . strip_tags($comment) . "\n" . "\n" . '----' . "\n" . YOU_HAVE_THESE_OPTIONS . ($moderate_comment ? "\n" . str_repeat(' ', 2) . THIS_TRACKBACK_NEEDS_REVIEW : '') . "\n" . str_repeat(' ', 3) . str_pad(VIEW_ENTRY, 15) . ' -- ' . $entryURI . "\n" . str_repeat(' ', 3) . str_pad(DELETE_TRACKBACK, 15) . ' -- ' . $deleteURI . ($moderate_comment ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_TRACKBACK, 15) . ' -- ' . $approveURI : ''); } else { /******************* COMMENTS *********************/ $subject = ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_COMMENT_TO . ' ' . $title; $text = sprintf(A_NEW_COMMENT_BLAHBLAH, $serendipity['blogTitle'], $title) . "\n" . LINK_TO_ENTRY . ': ' . $entryURI . "\n" . "\n" . REQUIRES_REVIEW . ': ' . ($moderate_comment ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '') . "\n" . USER . ' ' . IP_ADDRESS . ': ' . $_SERVER['REMOTE_ADDR'] . "\n" . USER . ' ' . NAME . ': ' . $fromName . "\n" . USER . ' ' . EMAIL . ': ' . $fromEmail . "\n" . USER . ' ' . HOMEPAGE . ': ' . $fromUrl . "\n" . "\n" . COMMENTS . ': ' . "\n" . strip_tags($comment) . "\n" . "\n" . '----' . "\n" . YOU_HAVE_THESE_OPTIONS . ($moderate_comment ? "\n" . str_repeat(' ', 2) . THIS_COMMENT_NEEDS_REVIEW : '') . "\n" . str_repeat(' ', 3) . str_pad(VIEW_COMMENT, 15) . ' -- ' . $entryURI . '#c' . $comment_id . "\n" . str_repeat(' ', 3) . str_pad(DELETE_COMMENT, 15) . ' -- ' . $deleteURI . ($moderate_comment ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_COMMENT, 15) . ' -- ' . $approveURI : ''); } return serendipity_sendMail($to, $subject, $text, $fromEmail, null, $fromName); }
/** * Return HTML containing a list of categories * * Prints a list of categories for use in forms, the sidebar, or whereever... * * @access public * @param array An array of categories, typically gathered by serendipity_fetchCategories() * @param array An array which holds IDs which are meant to be selected within a HTML SELECT form field [used for recursion] * @param int The type of category list (0: HTML span list, 1/2: <option>s, 3: HTML Div list, 4: CSV data) to return * @param int The parent ID of a category [for recursion] * @param int The current nesting level [for recursion] * @param string Tells the function, whether or not to display the XML button for each category. * If empty, no links to the xml feeds will be displayed; If you want to, you can * pass an image here (this setting is only used, when type==3). * @param string The character to use for blank indenting * @see serendipity_fetchCategories() */ function serendipity_generateCategoryList($cats, $select = array(0), $type = 0, $id = 0, $level = 0, $xmlImg = '', $blank_char = '�') { global $serendipity; if (!is_array($cats) || !count($cats)) { return; } $ret = ''; foreach ($cats as $cat) { if ($cat['parentid'] == $id) { switch ($type) { case 0: $ret .= str_repeat(' ', $level * 2) . '• <span id="catItem_' . $cat['categoryid'] . '"' . ($cat['categoryid'] && in_array($cat['categoryid'], $select) ? ' selected="selected"' : '') . '><a href="?serendipity[adminModule]=category&serendipity[cat][catid]=' . $cat['categoryid'] . '">' . (!empty($cat['category_icon']) ? '<img style="vertical-align: middle;" src="' . $cat['category_icon'] . '" border="0" alt="' . $cat['category_name'] . '"/> ' : '') . htmlspecialchars($cat['category_name']) . (!empty($cat['category_description']) ? ' - ' . htmlspecialchars($cat['category_description']) : '') . '</a></span><br/>' . "\n"; break; case 1: case 2: $ret .= '<option value="' . $cat['categoryid'] . '"' . ($cat['categoryid'] && in_array($cat['categoryid'], $select) ? ' selected="selected"' : '') . '>'; $ret .= str_repeat(' ', $level * 2) . htmlspecialchars($cat['category_name']) . ($type == 1 && !empty($cat['category_description']) ? ' - ' . htmlspecialchars($cat['category_description']) : ''); $ret .= '</option>'; break; case 3: $category_id = serendipity_makeFilename($cat['category_name']); if (!empty($xmlImg)) { $ret .= sprintf('<div style="padding-bottom: 2px;">' . '<a href="%s" title="%s"><img alt="xml" src="%s" style="vertical-align: bottom; display: inline; border: 0px" /></a> %s' . '<a href="%s" title="%s">%s</a>' . '</div>', $serendipity['serendipityHTTPPath'] . 'rss.php?category=' . $cat['categoryid'] . '_' . $category_id, htmlspecialchars($cat['category_description']), $xmlImg, str_repeat(' ', $level * 3), serendipity_categoryURL($cat, 'serendipityHTTPPath'), htmlspecialchars($cat['category_description']), htmlspecialchars($cat['category_name'])); } else { $ret .= sprintf('%s<a href="%s" title="%s">%s</a><br />', str_repeat(' ', $level * 3), serendipity_categoryURL($cat, 'serendipityHTTPPath'), htmlspecialchars($cat['category_description']), htmlspecialchars($cat['category_name'])); } break; case 4: $ret .= $cat['categoryid'] . '|||' . str_repeat($blank_char, $level * 2) . $cat['category_name'] . '@@@'; break; } $ret .= serendipity_generateCategoryList($cats, $select, $type, $cat['categoryid'], $level + 1, $xmlImg, $blank_char); } } return $ret; }
function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { switch ($event) { case 'genpage': $args = implode('/', serendipity_getUriArguments($eventData, true)); if ($serendipity['rewrite'] != 'none') { $nice_url = $serendipity['serendipityHTTPPath'] . $args; } else { $nice_url = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?/' . $args; } $myi = strpos($nice_url, '?'); if ($myi != 0 && $serendipity['rewrite'] != 'none') { $nice_url2 = substr($nice_url, $myi + 1); } $myi = strpos($nice_url, '?'); if ($myi != 0 && $serendipity['rewrite'] != 'none') { $nice_url = substr($nice_url, 0, $myi); } $myi = strpos($nice_url, '&'); if ($myi != 0 && $serendipity['rewrite'] != 'none') { $nice_url = substr($nice_url, 0, $myi); } $myi = strpos($nice_url2, '&'); if ($myi != 0 && $serendipity['rewrite'] != 'none') { $nice_url2 = substr($nice_url2, 0, $myi); } $query = "SELECT entryid FROM {$serendipity['dbPrefix']}entryproperties WHERE property = 'permalink'\n AND value IN ('" . serendipity_db_escape_string($nice_url) . "', '/" . serendipity_db_escape_string($nice_url) . "',\n '" . serendipity_db_escape_string($nice_url2) . "', '/" . serendipity_db_escape_string($nice_url2) . "')"; $retid = serendipity_db_query($query); if (is_array($retid) && !empty($retid[0]['entryid'])) { $this->show($retid[0]['entryid']); } break; case 'entry_display': $ids = array(); if (!is_array($eventData)) { return true; } foreach ($eventData as $entry) { $ids[] = $entry['id']; } $query = "SELECT entryid,value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid IN (" . implode(', ', $ids) . ") AND property = 'permalink'"; $retval = serendipity_db_query($query); if (is_array($retval)) { foreach ((array) $retval as $pl) { $this->ids[$pl['entryid']] = $pl['value']; } } break; case 'frontend_display:html:per_entry': if (isset($this->ids[$eventData['id']]) && stristr($this->ids[$eventData['id']], '/' . UNKNOWN) === FALSE) { $eventData['link'] = $this->ids[$eventData['id']]; $urldata = parse_url($serendipity['baseURL']); $eventData['rdf_ident'] = $urldata['scheme'] . '://' . $urldata['host'] . $this->ids[$eventData['id']]; } break; case 'backend_display': $permalink = !empty($serendipity['POST']['permalink']) ? $serendipity['POST']['permalink'] : ''; if (!empty($eventData['id']) && empty($permalink)) { $query = "SELECT value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = '" . $eventData['id'] . "' AND property = 'permalink'"; $retval = serendipity_db_query($query); if (is_array($retval) && !empty($retval[0]['value'])) { $permalink = $retval[0]['value']; } } $title = $eventData['title']; if (empty($title)) { $title = UNKNOWN; } if (empty($permalink)) { $permalink = $serendipity['rewrite'] != 'none' ? $serendipity['serendipityHTTPPath'] . 'permalink/' . serendipity_makeFilename($title) . '.html' : $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?/permalink/' . serendipity_makeFilename($title) . '.html'; } ?> <fieldset style="margin: 5px"> <legend><?php echo PLUGIN_EVENT_CUSTOM_PERMALINKS_PL; ?> </legend> <div><?php echo PLUGIN_EVENT_CUSTOM_PERMALINKS_PL_DESC; ?> <br /><br /></div> <label for="permalink" title="<?php echo htmlentities(PLUGIN_EVENT_CUSTOM_PERMALINKS_PL, ENT_COMPAT, LANG_CHARSET); ?> "><?php echo PLUGIN_EVENT_CUSTOM_PERMALINKS_PL; ?> :</label> <input class="input_textbox" type="text" style="width: 60%" name="serendipity[permalink]" id="permalink" value="<?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($permalink) : htmlspecialchars($permalink, ENT_COMPAT, LANG_CHARSET); ?> " /> </fieldset> <?php return true; break; case 'backend_publish': case 'backend_save': if (!isset($serendipity['POST']['permalink']) || !isset($eventData['id'])) { return true; } serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = '" . $eventData['id'] . "' AND property = 'permalink'"); serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, value, property) VALUES ('" . $eventData['id'] . "', '" . serendipity_db_escape_string($serendipity['POST']['permalink']) . "', 'permalink')"); return true; break; default: return false; break; } } else { return false; } }
function import() { global $serendipity; global $elements; // Dependency on static pages if (!class_exists('serendipity_event_staticpage')) { die(IMPORTER_VOODOO_REQUIREMENTFAIL . '<br/>'); } // The selected file $file = $_FILES['serendipity']['tmp_name']['import']['voodooPadXML']; // Create a parser and set it up with the callbacks $xml_parser = xml_parser_create(''); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler($xml_parser, "start_element_handler", "end_element_handler"); xml_set_character_data_handler($xml_parser, "character_data_handler"); // Feed the contents of the file into the parser if (!file_exists($file)) { die(sprintf(DOCUMENT_NOT_FOUND, htmlspecialchars($file))); } if (!($handle = fopen($file, "r"))) { die(sprintf(SKIPPING_FILE_UNREADABLE, htmlspecialchars($file))); } while ($contents = fread($handle, 4096)) { xml_parse($xml_parser, $contents, feof($handle)); } fclose($handle); xml_parser_free($xml_parser); // Maintain a list of the aliases and their links $aliases = array(); // Now have a list of elements referenceable by id // so loop through building and/or updating page objects while (list($key_a) = each($elements)) { $name = $elements[$key_a]->name; switch ($name) { case 'data': // <data> indicates the start of the VoodooPad entry, so create page object $thispage = array(); break; case 'key': // This is the unique identifier of the page $mykey = serendipity_makeFilename($elements[$key_a]->data); $mykey = basename($this->data['keyPrefix']) . $mykey; // Pluck out the existing one if its there $page = serendipity_db_query("SELECT * \n FROM {$serendipity['dbPrefix']}staticpages \n WHERE filename = '" . serendipity_db_escape_string($mykey . '.htm') . "'\n LIMIT 1", true, 'assoc'); if (is_array($page)) { $thispage =& $page; if (empty($thispage['timestamp'])) { $thispage['timestamp'] = time(); } } $thispage['filename'] = $mykey . '.htm'; // Thanks for pointing this out to me and not just fixing it, I'm learning. $thispage['permalink'] = $serendipity['serendipityHTTPPath'] . 'index.php?serendipity[subpage]=' . $mykey; break; case 'alias': // The title and the string used to match links $thispage['articleformattitle'] = $this->data['wikiName']; $thispage['pagetitle'] = $mykey; $thispage['headline'] = $elements[$key_a]->data; break; case 'content': // The content of a voodoopad entry // The content of a voodoopad entry case 'path': // The path of a url string $thispage['content'] = $elements[$key_a]->data; // If its a content link list it for referencing with the page permalink if ($name == 'content') { $aliases[$thispage['headline']] = $thispage['permalink']; // Either replace or insert depending on previous existence if (!isset($thispage['id'])) { echo '<br/>' . IMPORTER_VOODOO_CREATINGPAGE . ': ' . $mykey; serendipity_db_insert('staticpages', $thispage); $serendipity["POST"]["staticpage"] = serendipity_db_insert_id("staticpages", 'id'); } elseif ($this->data['updateExisting'] == 'true') { echo '<br/>' . IMPORTER_VOODOO_UPDATINGPAGE . ': ' . $mykey; serendipity_db_update("staticpages", array("id" => $thispage["id"]), $thispage); } else { echo '<br/>' . IMPORTER_VOODOO_NOTUPDATING . ': ' . $mykey; } } else { // If its a url, the content is the link instead echo '<br/>' . IMPORTER_VOODOO_RECORDURL . ': ' . $thispage['headline']; $aliases[$thispage['headline']] = $thispage['content']; } break; } } // Now rewrite the permalinks echo '<br/>'; if ($this->data['shouldWriteLinks'] == 'true') { Serendipity_Import_VoodooPad::write_links($aliases); } return true; }
/** * Format a permalink according to the configured format * * @access public * @param string The URL format to use * @param array The input data to format a permalink * @param string The type of the permalink (entry|category|author) * @return string The formatted permalink */ function serendipity_makePermalink($format, $data, $type = 'entry') { global $serendipity; static $entryKeys = array('%id%', '%lowertitle%', '%title%', '%day%', '%month%', '%year%'); static $authorKeys = array('%id%', '%username%', '%realname%', '%email%'); static $categoryKeys = array('%id%', '%name%', '%parentname%', '%description%'); switch ($type) { case 'entry': if (!isset($data['entry']['timestamp']) && preg_match('@(%day%|%month%|%year%)@', $format)) { // We need the timestamp to build the URI, but no timestamp has been submitted. Thus we need to fetch the data. $ts = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries WHERE id = " . (int) $data['id'], true); if (is_array($ts)) { $data['entry']['timestamp'] = $ts['timestamp']; } else { $data['entry']['timestamp'] = time(); } } $ts = serendipity_serverOffsetHour($data['entry']['timestamp']); $ftitle = serendipity_makeFilename($data['title']); $fltitle = strtolower($ftitle); $replacements = array((int) $data['id'], $fltitle, $ftitle, date('d', $ts), date('m', $ts), date('Y', $ts)); return str_replace($entryKeys, $replacements, $format); break; case 'author': $replacements = array((int) $data['authorid'], serendipity_makeFilename($data['username'], true), serendipity_makeFilename($data['realname'], true), serendipity_makeFilename($data['email'], true)); return str_replace($authorKeys, $replacements, $format); break; case 'category': $parent_path = array(); // This is expensive. Only lookup if required. if (strstr($format, '%parentname%')) { $parents = serendipity_getCategoryRoot($data['categoryid']); if (is_array($parents)) { foreach ($parents as $parent) { $parent_path[] = serendipity_makeFilename($parent['category_name'], true); } } } $replacements = array((int) $data['categoryid'], serendipity_makeFilename($data['category_name'], true), implode('/', $parent_path), serendipity_makeFilename($data['category_description'], true)); return str_replace($categoryKeys, $replacements, $format); break; } return false; }
if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); } if (count($_from)) { foreach ($_from as $this->_tpl_vars['entry']) { ?> <h4 class="entry-title serendipity_title"><a href="<?php echo $this->_tpl_vars['entry']['link']; ?> " rel="bookmark"><?php echo $this->_tpl_vars['entry']['title']; ?> </a></h4> <div class="serendipity_entry serendipity_entry_author_<?php echo serendipity_makeFilename($this->_tpl_vars['entry']['author']); ?> <?php if ($this->_tpl_vars['entry']['is_entry_owner']) { ?> serendipity_entry_author_self<?php } ?> "> <?php if (!$this->_tpl_vars['dategroup']['is_sticky'] || $this->_tpl_vars['dategroup']['is_sticky'] && $this->_tpl_vars['template_option']['show_sticky_entry_footer'] == 'true') { ?> <?php if ($this->_tpl_vars['template_option']['entryfooterpos'] == 'belowtitle') { ?>
/** * * Create a vcard from user * * @access private * * @param int $authorid The UserID to build the vcard * * @return bool * */ function createVCard($authorid) { global $serendipity; include 'Contact_Vcard_Build.php'; if (!class_exists('Contact_Vcard_Build')) { return false; } $authorres = $this->getConfigVars($authorid); $name = explode(" ", $serendipity['POST']['profilerealname']); $city = explode(" ", $serendipity['POST']['profilecity']); $vcard = new Contact_Vcard_Build(); $vcard->setFormattedName($serendipity['POST']['profilerealname']); $vcard->setName($name[1], $name[0], "", "", ""); $vcard->addEmail($serendipity['POST']['profileemail']); $vcard->addParam('TYPE', 'WORK'); $vcard->addParam('TYPE', 'PREF'); $vcard->addAddress("", "", $serendipity['POST']['profilestreet'], $city[1], "", $city[0], $serendipity['POST']['profilecountry']); $vcard->addParam('TYPE', 'WORK'); $vcard->setURL($serendipity['POST']['profileurl']); $card = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . serendipity_makeFilename($serendipity['POST']['profilerealname']) . ".vcf"; if (!($fp = @fopen($card, "w"))) { return false; } fwrite($fp, $vcard->fetch()); fclose($fp); $q = 'SELECT id FROM ' . $serendipity['dbPrefix'] . 'images WHERE name = \'' . serendipity_makeFilename($serendipity['POST']['profilerealname']) . '\' AND extension = \'vcf\''; $res = serendipity_db_query($q, true, 'assoc'); if (!is_array($res)) { serendipity_insertImageInDatabase(basename($card), ''); } return true; }
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 />'; }