public function bindAttachments() { $mainframe = JFactory::getApplication(); $config = DiscussHelper::getConfig(); // @task: Do not allow file attachments if its disabled. if (!$config->get('attachment_questions')) { return false; } $allowed = explode(',', $config->get('main_attachment_extension')); $files = JRequest::getVar('filedata', array(), 'FILES'); if (empty($files)) { return false; } $total = count($files['name']); // @rule: Handle empty files. if (empty($files['name'][0])) { $total = 0; } if ($total < 1) { return false; } jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); jimport('joomla.utilities.utility'); // @rule: Create default media path $path = DISCUSS_MEDIA . '/' . trim($config->get('attachment_path'), DIRECTORY_SEPARATOR); if (!JFolder::exists($path)) { JFolder::create($path); JFile::copy(DISCUSS_ROOT . '/index.html', $path . '/index.html'); } $maxSize = (double) $config->get('attachment_maxsize') * 1024 * 1024; for ($i = 0; $i < $total; $i++) { $extension = JFile::getExt($files['name'][$i]); // Skip empty data's. if (!$extension) { continue; } // @rule: Check for allowed extensions if (!isset($extension) || !in_array(strtolower($extension), $allowed)) { $mainframe->enqueueMessage(JText::sprintf('COM_EASYDISCUSS_FILE_ATTACHMENTS_INVALID_EXTENSION', $files['name'][$i]), 'error'); $this->setError(JText::sprintf('COM_EASYDISCUSS_FILE_ATTACHMENTS_INVALID_EXTENSION', $files['name'][$i])); return false; } else { $size = $files['size'][$i]; // @rule: File size should not exceed maximum allowed size if (!empty($size) && ($size < $maxSize || $maxSize == 0)) { $name = DiscussHelper::getHash($files['name'][$i] . DiscussHelper::getDate()->toMySQL()); $attachment = DiscussHelper::getTable('Attachments'); $attachment->set('path', $name); $attachment->set('title', $files['name'][$i]); $attachment->set('uid', $this->id); $attachment->set('type', $this->getType()); $attachment->set('created', DiscussHelper::getDate()->toMySQL()); $attachment->set('published', true); $attachment->set('mime', $files['type'][$i]); $attachment->set('size', $size); JFile::copy($files['tmp_name'][$i], $path . '/' . $name); $attachment->store(); // Create a thumbnail if attachment is an image if (DiscussHelper::getHelper('Image')->isImage($files['name'][$i])) { require_once DISCUSS_CLASSES . '/simpleimage.php'; $image = new SimpleImage(); $image->load($files['tmp_name'][$i]); $image->resizeToFill(160, 120); $image->save($path . '/' . $name . '_thumb', $image->image_type); } } else { $mainframe->enqueueMessage(JText::sprintf('COM_EASYDISCUSS_FILE_ATTACHMENTS_MAX_SIZE_EXCLUDED', $files['name'][$i], $config->get('attachment_maxsize')), 'error'); $this->setError(JText::sprintf('COM_EASYDISCUSS_FILE_ATTACHMENTS_MAX_SIZE_EXCLUDED', $files['name'][$i], $config->get('attachment_maxsize'))); return false; } } } return true; }
private function processEmails($mailer = '', $category = '') { // @task: Only search for messages that are new. $unread = $mailer->searchMessages('UNSEEN'); // If there is no unread emails, just skip this altogether if (!$unread) { echo JText::_('COM_EASYDISCUSS_NO_EMAILS_TO_PARSE'); return false; } $config = DiscussHelper::getConfig(); $acl = DiscussHelper::getHelper('ACL'); $filter = JFilterInput::getInstance(); $total = 0; $replyBreaker = $config->get('mail_reply_breaker'); foreach ($unread as $sequence) { // Get the message info $info = $mailer->getMessageInfo($sequence); $from = $info->from; $senderName = $from[0]->personal; // Get the subject of the email and clean it to avoid any unclose html tags $subject = $filter->clean($info->subject); // @rule: Detect if this is actually a reply. preg_match('/\\[\\#(.*)\\]/is', $subject, $matches); $isReply = !empty($matches); $message = new DiscussMailerMessage($mailer->stream, $sequence); // Load up the post object $post = DiscussHelper::getTable('Post'); // Get the html output $html = $message->getHTML(); // Default allowed html codes $allowed = '<img>,<a>,<br>,<table>,<tbody>,<th>,<tr>,<td>,<div>,<span>,<p>,<h1>,<h2>,<h3>,<h4>,<h5>,<h6>'; // Remove disallowed tags $html = strip_tags($html, $allowed); // Remove img tags because we do not support email embeded images $pattern = array(); $pattern[] = '/<img.*?src=["|\'](.*?)["|\'].*?\\>/ims'; $html = preg_replace($pattern, array(''), $html); // Insert default subject if emails do not contain title if (empty($subject)) { $subject = JText::_('COM_EASYDISCUSS_EMAIL_NO_SUBJECT'); } $post->set('content', $html); $post->set('title', $subject); $post->set('published', DISCUSS_ID_PUBLISHED); $post->set('created', DiscussHelper::getDate()->toMySQL()); $post->set('replied', DiscussHelper::getDate()->toMySQL()); $post->set('modified', DiscussHelper::getDate()->toMySQL()); // If this is a reply, and the site isn't configured to parse replies, skip this if ($isReply && !$config->get('main_email_parser_replies')) { continue; } // By default, set the category to the one pre-configured at the back end. $post->category_id = $config->get('main_email_parser_category'); if ($isReply) { $parentId = (int) $matches[1]; $post->set('parent_id', $parentId); // Trim content, get text before the defined line if ($replyBreaker) { if ($pos = JString::strpos($post->content, $replyBreaker)) { $post->content = JString::substr($post->content, 0, $pos); } } // Since this is a reply, we need to determine the correct category for it based on the parent discussion. $parent = DiscussHelper::getTable('Post'); $parent->load($parentId); $post->category_id = $parent->category_id; } // @rule: Map the sender's email with the user in Joomla? $replyToEmail = $info->fromemail; // Lookup for the user based on their email address. $user = DiscussHelper::getUserByEmail($replyToEmail); if ($user instanceof JUser) { $post->user_id = $user->id; $post->user_type = DISCUSS_POSTER_MEMBER; } else { // Guest posts $post->user_type = DISCUSS_POSTER_GUEST; $post->poster_name = $senderName; $post->poster_email = $replyToEmail; } // check if guest can post question or not. if not skip the processing. if ($post->get('user_type') == DISCUSS_POSTER_GUEST) { $acl = DiscussHelper::getHelper('ACL', '0'); if (!$acl->allowed('add_question')) { continue; } } // If the system is configured to moderate all emails, then we should update the state accordingly if ($config->get('main_email_parser_moderation')) { $post->set('published', DISCUSS_ID_PENDING); } // @rule: Process the post $post->store(); // prepare email content and information. $profile = DiscussHelper::getTable('Profile'); if (isset($user->id)) { $profile->load($user->id); } // For use within the emails. $emailData = array(); $emailData['postTitle'] = $post->title; $emailData['postAuthor'] = $profile->id ? $profile->getName() : $post->poster_name; $emailData['postAuthorAvatar'] = $profile->getAvatar(); $emailData['postLink'] = DiscussRouter::getRoutedURL('index.php?option=com_easydiscuss&view=post&id=' . $post->id, false, true); $emailContent = $post->content; if ($post->content_type != 'html') { // the content is bbcode. we need to parse it. $emailContent = EasyDiscussParser::bbcode($emailContent); $emailContent = EasyDiscussParser::removeBrTag($emailContent); } // If post is html type we need to strip off html codes. if ($post->content_type == 'html') { $emailContent = strip_tags($post->content); } // Notify moderators when there's a new pending post if ($post->published == DISCUSS_ID_PENDING) { // Generate hashkeys to map this current request $hashkey = DiscussHelper::getTable('HashKeys'); $hashkey->uid = $post->id; $hashkey->type = DISCUSS_QUESTION_TYPE; $hashkey->store(); // Prepare the email template. $approveURL = DiscussHelper::getExternalLink('index.php?option=com_easydiscuss&controller=posts&task=approvePost&key=' . $hashkey->key); $rejectURL = DiscussHelper::getExternalLink('index.php?option=com_easydiscuss&controller=posts&task=rejectPost&key=' . $hashkey->key); $emailData['moderation'] = '<div style="display:inline-block;width:100%;padding:20px;border-top:1px solid #ccc;padding:20px 0 10px;margin-top:20px;line-height:19px;color:#555;font-family:\'Lucida Grande\',Tahoma,Arial;font-size:12px;text-align:left">'; $emailData['moderation'] .= '<a href="' . $approveURL . '" style="display:inline-block;padding:5px 15px;background:#fc0;border:1px solid #caa200;border-bottom-color:#977900;color:#534200;text-shadow:0 1px 0 #ffe684;font-weight:bold;box-shadow:inset 0 1px 0 #ffe064;-moz-box-shadow:inset 0 1px 0 #ffe064;-webkit-box-shadow:inset 0 1px 0 #ffe064;border-radius:2px;moz-border-radius:2px;-webkit-border-radius:2px;text-decoration:none!important">' . JText::_('COM_EASYDISCUSS_EMAIL_APPROVE_POST') . '</a>'; $emailData['moderation'] .= ' ' . JText::_('COM_EASYDISCUSS_OR') . ' <a href="' . $rejectURL . '" style="color:#477fda">' . JText::_('COM_EASYDISCUSS_REJECT') . '</a>'; $emailData['moderation'] .= '</div>'; $emailData['postContent'] = $post->content; $emailData['emailTemplate'] = 'email.subscription.site.moderate.php'; $emailData['emailSubject'] = JText::sprintf('COM_EASYDISCUSS_NEW_QUESTION_MODERATE', $post->id, $post->title); // Notify the moderators now DiscussHelper::getHelper('Mailer')->notifyAdministrators($emailData, array($replyToEmail), $config->get('notify_admin'), $config->get('notify_moderator')); } $attachments = array(); $attachments = $message->getAttachment(); // process attached images if (!empty($attachments)) { $config = DiscussHelper::getConfig(); $main_image_path = rtrim('images/easydiscuss_images/', '/'); $file = JPATH_ROOT . DIRECTORY_SEPARATOR . $main_image_path; if (!JFolder::exists($file)) { JFolder::create($file); } $senderMail = $info->fromemail; $user = DiscussHelper::getUserByEmail($senderMail); $userid = $user->get('id'); $rel_upload_path = $main_image_path . '/' . $userid; $userUploadPath = JPATH_ROOT . DIRECTORY_SEPARATOR . $main_image_path . DIRECTORY_SEPARATOR . $userid; $userUploadPath = JPath::clean($userUploadPath); $dir = $userUploadPath . DIRECTORY_SEPARATOR; $tmp_dir = JPATH_ROOT . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; $uri = JURI::base() . $main_image_path . '/' . $userid . '/'; if (!JFolder::exists($dir)) { JFolder::create($dir); } foreach ($attachments as $attachment) { // clean up file name if (strpos($attachment['name'], '/') !== FALSE) { $attachment['name'] = substr($attachment['name'], strrpos($attachment['name'], '/') + 1); } elseif (strpos($attachment['name'], '\\' !== FALSE)) { $attachment['name'] = substr($attachment['name'], strrpos($attachment['name'], '\\') + 1); } // @task: check if the attachment has file extension. ( assuming is images ) $imgExts = array('jpg', 'png', 'gif', 'JPG', 'PNG', 'GIF', 'jpeg', 'JPEG'); $imageSegment = explode('.', $attachment['name']); if (!in_array($imageSegment[count($imageSegment) - 1], $imgExts)) { $attachment['name'] = $attachment['name'] . '.jpg'; } // @task: Store the file into a temporary location first. $attachment['tmp_name'] = $tmp_dir . $attachment['name']; JFile::write($attachment['tmp_name'], $attachment['data']); $atmTitle = $attachment['name']; $atmURL = $uri . $attachment['name']; // Bind file attachments jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); jimport('joomla.utilities.utility'); // @rule: Create default media path $path = DISCUSS_MEDIA . '/' . trim($config->get('attachment_path'), DIRECTORY_SEPARATOR); if (!JFolder::exists($path)) { JFolder::create($path); JFile::copy(DISCUSS_ROOT . '/index.html', $path . '/index.html'); } $maxSize = (double) $config->get('attachment_maxsize') * 1024 * 1024; $extension = JFile::getExt($attachment['name']); // Skip empty data's. if (!$extension) { continue; } $allowed = explode(',', $config->get('main_attachment_extension')); // @rule: Check for allowed extensions if (!isset($extension) || !in_array(strtolower($extension), $allowed)) { echo 'Invalid extension.'; } else { $size = $attachment['size']; $name = $attachment['name']; $mime = $attachment['mime']; $tmpName = $attachment['tmp_name']; // Check the mime contains the attachment type, if not we insert our own $imgExts = array('jpg', 'png', 'gif', 'JPG', 'PNG', 'GIF', 'jpeg', 'JPEG'); if (in_array($mime, $imgExts)) { $mime = 'image/' . $mime; } else { $mime = 'application/' . $mime; } // @rule: File size should not exceed maximum allowed size if (!empty($size) && $size < $maxSize) { $hash = DiscussHelper::getHash($name . DiscussHelper::getDate()->toMySQL()); $attachment = DiscussHelper::getTable('Attachments'); $attachment->set('path', $hash); $attachment->set('title', $name); $attachment->set('uid', $post->id); $attachment->set('type', $isReply ? 'replies' : 'questions'); $attachment->set('created', DiscussHelper::getDate()->toMySQL()); $attachment->set('published', true); $attachment->set('mime', $mime); $attachment->set('size', $size); if (!JFile::copy($tmpName, $path . '/' . $hash)) { echo 'Copy failed from tmp to attachment folder'; } $attachment->store(); // Create a thumbnail if attachment is an image if (DiscussHelper::getHelper('Image')->isImage($name)) { require_once DISCUSS_CLASSES . '/simpleimage.php'; $image = new SimpleImage(); $image->load($tmpName); $image->resizeToFill(160, 120); $image->save($path . '/' . $hash . '_thumb', $image->image_type); } // @task: Once the attachment is processed, delete the temporary file. JFile::delete($tmpName); } else { echo 'Invalid extension ' . $name; } } } } // Send notification email to the subscribers in the thread. if ($isReply && $post->get('published') == DISCUSS_ID_PUBLISHED) { self::replyNotifyUsers($post, $user, $senderName); } // @task: Increment the count. $total += 1; // @rule: Only send autoresponders when it's a new post. if (!$isReply && $config->get('main_email_parser_receipt') && $post->get('published') == DISCUSS_ID_PUBLISHED) { $sendAsHTML = (bool) $config->get('notify_html_format'); $theme = new DiscussThemes(); $postId = $post->get('id'); if ($isReply) { $postId = $parentId; } $url = DiscussRouter::getRoutedURL('index.php?option=com_easydiscuss&view=post&id=' . $postId, false, true); $emailData = array(); $emailData['postLink'] = $url; if ($post->get('user_type') == DISCUSS_POSTER_GUEST) { $emailData['postAuthor'] = $senderName; } else { $profile = DiscussHelper::getTable('Profile'); $profile->load($user->id); $emailData['postAuthor'] = $profile->getName(); } require_once DISCUSS_CLASSES . '/notification.php'; $notification = new DNotification(); $output = $notification->getEmailTemplateContent('email.accepted.responder.php', $emailData); $app = JFactory::getApplication(); if (!$sendAsHTML) { $output = strip_tags($output); } // @rule: Send confirmation message. JUtility::sendMail($app->getCfg('mailfrom'), $app->getCfg('fromname'), $replyToEmail, '[#' . $post->id . ']: ' . $subject, $output, $sendAsHTML); } if (!$isReply && $post->get('published') == DISCUSS_ID_PUBLISHED) { // Send email to subscribers about new post has created Discusshelper::sendNotification($post, $post->parent_id, true, $post->user_id, DISCUSS_ID_PENDING); } echo JText::sprintf('COM_EASYDISCUSS_EMAIL_PARSED', $total); } }