/**
  * Webhook parser class method for SendGrid.
  */
 public function webhook_parser()
 {
     if (empty($_SERVER['HTTP_USER_AGENT']) || !empty($_SERVER['HTTP_USER_AGENT']) && 0 !== strpos($_SERVER['HTTP_USER_AGENT'], 'SendGrid')) {
         return;
     }
     if (empty($_POST) || empty($_POST['headers'])) {
         return;
     }
     bp_rbe_log('- SendGrid webhook received -');
     // Format email headers to fit RBE spec.
     $temp = explode("\n", $_POST['headers']);
     $headers = array();
     foreach ($temp as $line) {
         $colun = strpos($line, ':');
         if (false === $colun) {
             continue;
         }
         $key = substr($line, 0, $colun);
         $headers[$key] = stripslashes(trim(substr($line, $colun + 1)));
     }
     $data = array('headers' => $headers, 'to_email' => BP_Reply_By_Email_Parser::get_header($headers, 'To'), 'from_email' => BP_Reply_By_Email_Parser::get_header($headers, 'From'), 'content' => $_POST['text'], 'subject' => $_POST['subject']);
     $parser = BP_Reply_By_Email_Parser::init($data, 1);
     if (is_wp_error($parser)) {
         do_action('bp_rbe_no_match', $parser, $data, 1, false);
     }
     bp_rbe_log('- Webhook parsing completed -');
     die;
 }
 /**
  * Webhook parser class method for Mandrill.
  */
 public function webhook_parser()
 {
     if (empty($_SERVER['CONTENT_TYPE']) || !empty($_SERVER['CONTENT_TYPE']) && 'application/json' !== $_SERVER['CONTENT_TYPE']) {
         return;
     }
     if (!empty($_SERVER['HTTP_USER_AGENT']) && 'Postmark' !== $_SERVER['HTTP_USER_AGENT']) {
         return;
     }
     bp_rbe_log('- Postmark webhook received -');
     $response = file_get_contents('php://input');
     if (empty($response)) {
         bp_rbe_log('- Postmark webhook response failed -');
     }
     $response = json_decode($response);
     // Format email headers to fit RBE spec.
     $headers = array();
     foreach ($response->Headers as $header) {
         $headers[$header->Name] = $header->Value;
     }
     // Postmark separates parsed email headers; add them back for RBE parsing.
     $headers['From'] = $response->From;
     $headers['To'] = $response->To;
     $data = array('headers' => $headers, 'to_email' => $response->To, 'from_email' => $response->From, 'content' => $response->TextBody, 'subject' => $response->Subject);
     $parser = BP_Reply_By_Email_Parser::init($data, 1);
     if (is_wp_error($parser)) {
         do_action('bp_rbe_no_match', $parser, $data, 1, false);
     }
     bp_rbe_log('- Webhook parsing completed -');
     die;
 }
Ejemplo n.º 3
0
/**
 * Remove our scheduled function from WP and stop the IMAP loop.
 */
function bp_rbe_deactivate()
{
    // stop IMAP connection if active
    if (bp_rbe_is_connected()) {
        bp_rbe_stop_imap();
        // give plugin a chance to stop IMAP connection as it could be sleeping
        sleep(10);
        bp_rbe_log('Daisy, Daisy, give me your answer, do...');
    }
    // remove remnants from any previous failed attempts to stop the inbox
    bp_rbe_cleanup();
    bp_rbe_log('Plugin deactivated!');
}
 /**
  * Webhook parser class method for SparkPost.
  */
 public function webhook_parser()
 {
     if (empty($_SERVER['CONTENT_TYPE']) || !empty($_SERVER['CONTENT_TYPE']) && 'application/json' !== $_SERVER['CONTENT_TYPE']) {
         return;
     }
     if (false === isset($_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN'])) {
         return;
     }
     bp_rbe_log('- SparkPost webhook received -');
     // SparkPost auth token verification.
     if (defined('BP_RBE_SPARKPOST_WEBHOOK_TOKEN') && !empty($_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN'])) {
         // Make sure auth token matches; if it doesn't, bail!
         if (constant('BP_RBE_SPARKPOST_WEBHOOK_TOKEN') !== $_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN']) {
             bp_rbe_log('SparkPost token verification failed.');
             die;
         }
     }
     $response = file_get_contents('php://input');
     if (empty($response)) {
         bp_rbe_log('- SporkPost webhook response failed -');
     }
     $response = json_decode($response);
     $i = 1;
     foreach ($response as $item) {
         // Format email headers to fit RBE spec.
         $headers = array();
         foreach ($item->msys->relay_message->content->headers as $header) {
             $headers = array_merge($headers, (array) $header);
         }
         $data = array('headers' => $headers, 'to_email' => $item->msys->relay_message->rcpt_to, 'from_email' => $item->msys->relay_message->friendly_from, 'content' => $item->msys->relay_message->content->text, 'subject' => $item->msys->relay_message->content->subject);
         $parser = BP_Reply_By_Email_Parser::init($data, $i);
         if (is_wp_error($parser)) {
             do_action('bp_rbe_no_match', $parser, $data, $i, false);
         }
         ++$i;
     }
     bp_rbe_log('- Webhook parsing completed -');
     die;
 }
Ejemplo n.º 5
0
 /**
  * Validate and sanitize our options before saving to the DB.
  *
  * Callback from {@link register_setting()}.
  *
  * @param array $input The submitted values from the form
  * @return array $output The validated values to be inserted into the DB
  */
 public function validate($input)
 {
     $messages = false;
     $output = array();
     $output['mode'] = wp_filter_nohtml_kses($input['mode']);
     // switching from IMAP to inbound email mode
     if ('inbound' == $output['mode'] && 'imap' == bp_rbe_get_setting('mode')) {
         // stop RBE if still connected via IMAP
         if (bp_rbe_is_connected()) {
             bp_rbe_stop_imap();
         }
         bp_rbe_log('- Operating mode switched to inbound -');
     }
     // check if key is alphanumeric
     if (ctype_alnum($input['key'])) {
         $output['key'] = $input['key'];
     }
     /** INBOUND-related ***************************************************/
     $inbound_provider = wp_filter_nohtml_kses($input['inbound-provider']);
     if (!empty($inbound_provider)) {
         $output['inbound-provider'] = $inbound_provider;
     }
     $inbound_domain = isset($input['inbound-domain']) ? wp_filter_nohtml_kses($input['inbound-domain']) : '';
     if (!empty($inbound_domain)) {
         $output['inbound-domain'] = $inbound_domain;
     }
     /** IMAP-related ******************************************************/
     $username = wp_filter_nohtml_kses($input['username']);
     $password = wp_filter_nohtml_kses($input['password']);
     if ($email = is_email($input['email'])) {
         $output['email'] = $email;
         if ($input['gmail'] == 1) {
             $output['username'] = $email;
         }
     }
     if (!empty($username)) {
         $output['username'] = $username;
         if (is_email($username)) {
             $output['email'] = $username;
         }
     }
     if (!empty($password)) {
         $output['password'] = $password;
     }
     // check if port is numeric
     if (is_numeric($input['port'])) {
         $output['port'] = $input['port'];
     }
     // check if address tag is one character
     if (strlen($input['tag']) == 1) {
         $output['tag'] = $input['tag'];
     }
     // override certain settings if "gmail" setting is true
     if (!empty($input['gmail']) && $input['gmail'] == 1) {
         $output['servername'] = 'imap.gmail.com';
         $output['port'] = 993;
         $output['tag'] = '+';
         $output['gmail'] = 1;
         $output['email'] = $username;
         // use alternate server settings as defined by the user
     } else {
         $output['servername'] = wp_filter_nohtml_kses($input['servername']);
         $output['port'] = absint($input['port']);
         $output['tag'] = wp_filter_nohtml_kses($input['tag']);
         $output['gmail'] = 0;
     }
     if (is_numeric($input['keepalive']) && $input['keepalive'] < 30) {
         $output['keepalive'] = $input['keepalive'];
     }
     // keepalive for safe mode will never exceed the execution time
     if (ini_get('safe_mode')) {
         $output['keepalive'] = $input['keepalive'] = bp_rbe_get_execution_time('minutes');
     }
     // automatically reconnect after keep-alive limit
     if (!empty($input['keepaliveauto'])) {
         $output['keepaliveauto'] = 1;
     } else {
         $output['keepaliveauto'] = 0;
     }
     // do a quick imap check if we have valid credentials to check
     if ($output['mode'] == 'imap' && !empty($output['servername']) && !empty($output['port']) && !empty($output['username']) && !empty($output['password'])) {
         if (function_exists('imap_open')) {
             $imap = BP_Reply_By_Email_Connect::init(array('host' => $output['servername'], 'port' => $output['port'], 'username' => $output['username'], 'password' => $output['password']));
             // if connection failed, add an error
             if ($imap === false) {
                 $errors = imap_errors();
                 $messages['connect_error'] = sprintf(__('Error: Unable to connect to inbox - %s', 'bp-rbe'), $errors[0]);
                 $output['connect'] = 0;
                 // connection was successful, now close our temporary connection
             } else {
                 // this tells bp_rbe_is_required_completed() that we're good to go!
                 $output['connect'] = 1;
                 imap_close($imap);
             }
         }
     }
     // encode the password
     if (!empty($password)) {
         $output['password'] = bp_rbe_encode(array('string' => $password, 'key' => wp_salt()));
     }
     /**********************************************************************/
     /* error time! */
     if (strlen($input['tag']) > 1 && !$output['tag']) {
         $messages['tag_error'] = __('Error: <strong>Address tag</strong> must only be one character.', 'bp-rbe');
     }
     if (!empty($input['port']) && !is_numeric($input['port']) && !$output['port']) {
         $messages['port_error'] = __('Error: <strong>Port</strong> must be numeric.', 'bp-rbe');
     }
     if (!empty($input['key']) && !$output['key']) {
         $messages['key_error'] = __('Error: <strong>Key</strong> must only contain letters and / or numbers.', 'bp-rbe');
     }
     if (!empty($input['keepalive']) && !is_numeric($input['keepalive']) && !$output['keepalive']) {
         $messages['keepalive_error'] = __('Error: <strong>Keep Alive Connection</strong> value must be less than 30.', 'bp-rbe');
     }
     if (is_array($messages)) {
         $output['messages'] = $messages;
     }
     // For sites using an external object cache, make sure they get the new value.
     // This is all sorts of ugly! :(
     // I think this is a WP core bug with the WP Settings API...
     wp_cache_delete('alloptions', 'options');
     return $output;
 }
/**
 * Post by email routine for legacy forums.
 *
 * Validates the parsed data and posts the various BuddyPress content.
 *
 * @since 1.0-RC3
 *
 * @param bool $retval True by default.
 * @param array $data {
 *     An array of arguments.
 *
 *     @type array $headers Email headers.
 *     @type string $content The email body content.
 *     @type string $subject The email subject line.
 *     @type int $user_id The user ID who sent the email.
 *     @type bool $is_html Whether the email content is HTML or not.
 *     @type int $i The email message number.
 * }
 * @param array $params Parsed paramaters from the email address querystring.
 *   See {@link BP_Reply_By_Email_Parser::get_parameters()}.
 * @return array|object Array of the parsed item on success. WP_Error object
 *  on failure.
 */
function bp_rbe_legacy_forums_post($retval, $data, $params)
{
    // Forum reply
    if (!empty($params['t'])) {
        if (bp_is_active('groups') && bp_is_active('forums')) {
            bp_rbe_log('Message #' . $data['i'] . ': this is a forum reply');
            // get all group member data for the user in one swoop!
            $group_member_data = bp_rbe_get_group_member_info($data['user_id'], $params['g']);
            // user is not a member of the group anymore
            if (empty($group_member_data)) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'user_not_group_member' );
                return new WP_Error('user_not_group_member');
            }
            // user is banned from group
            if ((int) $group_member_data->is_banned == 1) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'user_banned_from_group' );
                return new WP_Error('user_banned_from_group');
            }
            // Don't allow reply flooding
            // Only available in 1.6+
            if (function_exists('bp_forums_reply_exists') && bp_forums_reply_exists(esc_sql($data['content']), $params['t'], $data['user_id'])) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'forum_reply_exists' );
                return new WP_Error('forum_reply_exists');
            }
            /* okay, we should be good to post now! */
            $forum_post_id = bp_rbe_groups_new_group_forum_post(array('post_text' => $data['content'], 'topic_id' => $params['t'], 'user_id' => $data['user_id'], 'group_id' => $params['g']));
            if (!$forum_post_id) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'forum_reply_fail' );
                return new WP_Error('forum_reply_fail');
            }
            bp_rbe_log('Message #' . $data['i'] . ': forum reply successfully posted!');
            // could potentially add attachments
            // @todo
            do_action('bp_rbe_new_forum_post', false, $forum_post_id, $data['user_id'], $params['g'], $data['headers']);
            return array('legacy_forums_post_id' => $forum_post_id);
        }
        // New forum topic
    } elseif (!empty($params['g'])) {
        if (bp_is_active('groups') && bp_is_active('forums')) {
            bp_rbe_log('Message #' . $data['i'] . ': this is a new forum topic');
            bp_rbe_log('Message #' . $data['i'] . ': body contents - ' . $data['content']);
            bp_rbe_log('Subject - ' . $subject);
            if (empty($data['content']) || empty($data['subject'])) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'new_forum_topic_empty' );
                return new WP_Error('new_forum_topic_empty');
            }
            // get all group member data for the user in one swoop!
            $group_member_data = bp_rbe_get_group_member_info($data['user_id'], $params['g']);
            // user is not a member of the group anymore
            if (empty($group_member_data)) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'user_not_group_member' );
                return new WP_Error('user_not_group_member');
            }
            // user is banned from group
            if ((int) $group_member_data->is_banned == 1) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'user_banned_from_group' );
                return new WP_Error('user_banned_from_group');
            }
            /* okay, we should be good to post now! */
            $topic = bp_rbe_groups_new_group_forum_topic(array('topic_title' => $data['subject'], 'topic_text' => $data['content'], 'user_id' => $data['user_id'], 'group_id' => $params['g']));
            if (!$topic) {
                //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'new_topic_fail' );
                return new WP_Error('new_topic_fail');
            }
            bp_rbe_log('Message #' . $data['i'] . ': forum topic successfully posted!');
            // could potentially add attachments
            do_action('bp_rbe_new_forum_topic', false, $topic, $data['user_id'], $params['g'], $data['headers']);
            return array('legacy_forums_topic_id' => $topic);
        }
    }
}
Ejemplo n.º 7
0
/**
 * Failsafe for RBE.
 *
 * RBE occasionally hangs during the inbox loop.  This function tries
 * to snap RBE out of it by checking the last few lines of the RBE
 * debug log.
 *
 * If all lines match our failed cronjob message, then reset RBE so
 * RBE can run fresh on the next scheduled run.
 *
 * @uses bp_rbe_tail() Grabs the last N lines from the RBE debug log
 * @uses bp_rbe_cleanup() Cleans up the DB entries that RBE uses
 * @since 1.0-RC1
 */
function bp_rbe_failsafe()
{
    // get the last N lines from the RBE debug log
    $last_entries = bp_rbe_tail(constant('BP_RBE_DEBUG_LOG_PATH'), constant('BP_RBE_TAIL_LINES'));
    if (empty($last_entries)) {
        return;
    }
    // count the number of tines our 'cronjob wants to connect' message occurs
    $counter = 0;
    // see if each line contains our cronjob fail string
    foreach ($last_entries as $entry) {
        if (strpos($entry, '--- Cronjob wants to connect - however according to our DB indicator, we already have an active IMAP connection! ---') !== false) {
            ++$counter;
        }
    }
    // if all lines match the cronjob fail string, reset RBE!
    if ($counter == constant('BP_RBE_TAIL_LINES')) {
        bp_rbe_log('--- Uh-oh! Looks like RBE is stuck! - FORCE RBE cleanup ---');
        // cleanup RBE!
        bp_rbe_cleanup();
        // use this hook to perhaps send an email to the admin?
        do_action('bp_rbe_failsafe_complete');
    }
}
 /**
  * Post by email handler.
  *
  * Validate data and post on success.
  *
  * @param bool $retval True by default.
  * @param array $data {
  *     An array of arguments.
  *
  *     @type array $headers Email headers.
  *     @type string $content The email body content.
  *     @type string $subject The email subject line.
  *     @type int $user_id The user ID who sent the email.
  *     @type bool $is_html Whether the email content is HTML or not.
  *     @type int $i The email message number.
  * }
  * @param array $params Parsed paramaters from the email address querystring.
  *   See {@link BP_Reply_By_Email_Parser::get_parameters()}.
  * @return array|object Array of the parsed item on success. WP_Error object
  *  on failure.
  */
 public function post($retval, $data, $params)
 {
     global $bp;
     $comment_id = !empty($params[$this->secondary_item_id_param]) ? $params[$this->secondary_item_id_param] : false;
     $i = $data['i'];
     // this means that the current email is a BP Doc reply
     // let's proceed!
     if (!empty($comment_id)) {
         // it's important to let RBE know what's happening during the process
         // for debugging purposes
         //
         // use bp_rbe_log() to log anything you want
         // in this case, we're letting RBE know that we're in the process of
         // rendering a comment reply
         bp_rbe_log('Message #' . $i . ': this is a BP Doc comment reply');
         // get parent comment data
         $comment = get_comment($comment_id);
         // parent comment doesn't exist or was deleted
         if (empty($comment)) {
             // when a condition for posting isn't met, return a WP_Error object.
             // next, log it under the internal_rbe_log()_method
             // and optionally, prep a failure message under the failure_message_to_sender() method
             //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_parent_comment_deleted' );
             return new WP_Error('bp_doc_parent_comment_deleted', '', $data);
         }
         // parent comment status checks
         switch ($comment->comment_approved) {
             case 'spam':
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_parent_comment_spam' );
                 return new WP_Error('bp_doc_parent_comment_spam', '', $data);
                 break;
             case 'trash':
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_parent_comment_deleted' );
                 return new WP_Error('bp_doc_parent_comment_deleted', '', $data);
                 break;
             case '0':
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_parent_comment_unapproved' );
                 return new WP_Error('bp_doc_parent_comment_unapproved', '', $data);
                 break;
         }
         // get doc settings
         $doc_settings = get_post_meta($comment->comment_post_ID, 'bp_docs_settings', true);
         // set temporary variable
         $bp->rbe = $bp->rbe->temp = new stdClass();
         // get group ID
         // $bp->rbe->temp->group_id gets passed to BP_Reply_By_Email::set_group_id()
         $group_id = $bp->rbe->temp->group_id = $params[$this->item_id_param];
         // get user ID
         $user_id = $data['user_id'];
         // check to see if the user can post comments for the group doc in question
         //
         // bp_docs_user_can( 'post_comments', $user_id, $group_id ) doesn't work the way I want it to
         // using the doc's comment settings as a guideline
         // check the comment settings for the doc
         switch ($doc_settings['post_comments']) {
             // this means that the comment settings for the doc recently switched to 'no-one'
             case 'no-one':
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_comment_change_to_noone' );
                 return new WP_Error('bp_doc_comment_change_to_noone', '', $data);
                 break;
                 // if the doc only allows group admins and mods to comment, return false for regular group members
             // if the doc only allows group admins and mods to comment, return false for regular group members
             case 'admins-mods':
                 // get the email address of the replier
                 $user_email = BP_Reply_By_Email_Parser::get_header($data['headers'], 'From');
                 // get an array of group admin / mod email addresses
                 // note: email addresses are set as key, not value
                 $admin_mod_emails = $this->get_admin_mod_user_emails($group_id);
                 // if the replier's email address does not match a group admin or mod, stop now!
                 if (!isset($admin_mod_emails[$user_email])) {
                     //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_user_not_admin_mod' );
                     return new WP_Error('bp_doc_user_not_admin_mod', '', $data);
                 }
                 break;
                 // if the doc allows any group member to comment, check if member is still part of
                 // the group and not banned
             // if the doc allows any group member to comment, check if member is still part of
             // the group and not banned
             case 'group-members':
                 if (!groups_is_user_member($user_id, $group_id)) {
                     //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_user_not_member' );
                     return new WP_Error('bp_doc_user_not_member', '', $data);
                 }
                 if (groups_is_user_banned($user_id, $group_id)) {
                     //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_user_banned' );
                     return new WP_Error('bp_doc_user_banned', '', $data);
                 }
                 break;
         }
         /* okay! we should be good to post now! */
         // get the userdata
         $userdata = get_userdata($user_id);
         // we're using wp_insert_comment() instead of wp_new_comment()
         // why? because wp_insert_comment() bypasses all the WP comment hooks, which is good for us!
         $new_comment_id = wp_insert_comment(array('user_id' => $user_id, 'comment_post_ID' => $comment->comment_post_ID, 'comment_content' => $data['content'], 'comment_parent' => $comment_id, 'comment_author' => $userdata->user_nicename, 'comment_author_url' => '', 'comment_author_email' => $userdata->user_email, 'comment_author_IP' => '', 'comment_agent' => '', 'comment_type' => ''));
         // comment successfully posted!
         if (!empty($new_comment_id)) {
             // more internal logging
             bp_rbe_log('Message #' . $i . ': BP Doc comment reply successfully posted!');
             /* now let's record the activity item for this comment */
             // override BP Docs' default comment activity action
             add_filter('bp_docs_comment_activity_action', array($this, 'comment_activity_action'));
             // now post the activity item with BP Docs' special class method
             if (class_exists('BP_Docs_BP_Integration')) {
                 // BP Docs v1.1.x support
                 $activity_id = BP_Docs_BP_Integration::post_comment_activity($new_comment_id);
             } else {
                 // BP Docs v1.2.x support
                 $activity_id = BP_Docs_Component::post_comment_activity($new_comment_id);
             }
             // special hook for RBE activity items
             // if you're adding an activity entry in this method, remember to add this hook after posting
             // your activity item in this method!
             do_action('bp_rbe_new_activity', array('activity_id' => $activity_id, 'type' => $this->activity_type, 'user_id' => $user_id, 'item_id' => $group_id, 'secondary_item_id' => $comment_id, 'content' => $data['content']));
             // remove the filter after posting
             remove_filter('bp_docs_comment_activity_action', array($this, 'comment_activity_action'));
             return array('bp_doc_comment_id' => $new_comment_id);
         } else {
             //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bp_doc_new_comment_fail' );
             return new WP_Error('bp_doc_new_comment_fail', '', $data);
         }
     }
 }
 /**
  * Post new topic by email handler.
  *
  * For bbPress, the logic in this method is the same as {@link bbp_new_topic_handler()}.
  * It's duplicated because bbPress doesn't utilize hooks for verifying topics.
  *
  * @todo No fancy support for topic tags, subscriptions yet. Will probably need shortcodes.
  *
  * @param array $data {
  *     An array of arguments.
  *
  *     @type array $headers Email headers.
  *     @type string $content The email body content.
  *     @type string $subject The email subject line.
  *     @type int $user_id The user ID who sent the email.
  *     @type bool $is_html Whether the email content is HTML or not.
  *     @type int $i The email message number.
  * }
  * @param array $params Parsed paramaters from the email address querystring.
  *   See {@link BP_Reply_By_Email_Parser::get_parameters()}.
  * @return array|object Array of the parsed item on success. WP_Error object
  *  on failure.
  */
 private function post_new_topic($data, $params)
 {
     //private function post_new_topic( $connection, $i, $headers, $params, $body, $topic_author ) {
     /** SETUP DATA ***************************************************/
     $i = $data['i'];
     $topic_author = $data['user_id'];
     $forum_id = $params[$this->forum_id_param];
     /* current email is a bbPress new topic, let's proceed! */
     // let RBE know that we're in the process of rendering a bbP new topic
     // BuddyPress group new topic
     if (!empty($params[$this->item_id_param])) {
         bp_rbe_log('Message #' . $i . ': this is a bbPress group forum new topic');
         // bbPress
     } else {
         bp_rbe_log('Message #' . $i . ': this is a bbPress new topic');
     }
     // other variables
     $anonymous_data = 0;
     /** GROUP PERMISSIONS ********************************************/
     // posting from a BP group
     if (!empty($params[$this->item_id_param])) {
         global $bp;
         // set group ID and cache it in global for later use
         // $bp->rbe->temp->group_id gets passed to the set_group_id() method later on
         $group_id = $bp->rbe->temp->group_id = $params[$this->item_id_param];
         // get all group member data for the user in one swoop!
         $group_member_data = bp_rbe_get_group_member_info($topic_author, $group_id);
         // user is not a member of the group anymore
         if (empty($group_member_data)) {
             //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'user_not_group_member' );
             return new WP_Error('user_not_group_member', '', $data);
         }
         // user is banned from group
         if ((int) $group_member_data->is_banned == 1) {
             //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'user_banned_from_group' );
             return new WP_Error('user_banned_from_group', '', $data);
         }
         // override groups_get_current_group() with our cached group ID
         add_filter('groups_get_current_group', array($this, 'set_group_id'));
         // temporarily add some GES filters here
         add_filter('bp_ass_activity_notification_subject', 'wp_specialchars_decode');
         add_filter('bp_ass_activity_notification_content', 'wp_specialchars_decode');
     }
     /** TOPIC / FORUM PERMISSIONS ************************************/
     // Allow member to pass default cap checks.
     // The reason why we keep the user_can() checks below is b/c bbPress
     // plugins may disable cap access for a specific user if they have hooked into
     // the 'bbp_map_meta_caps' filter.
     add_filter('bbp_map_meta_caps', array($this, 'map_forum_meta_caps'), 5, 4);
     // User cannot create topics
     if (!user_can($topic_author, 'publish_topics')) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_permissions' );
         return new WP_Error('bbp_topic_permissions', '', $data);
     }
     // Forum is a category
     if (bbp_is_forum_category($forum_id)) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_category' );
         //bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) );
         return new WP_Error('bbp_edit_topic_forum_category', '', $data);
         // Forum is not a category
     } else {
         // Forum is closed and user cannot access
         if (bbp_is_forum_closed($forum_id) && !user_can($topic_author, 'edit_forum')) {
             //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_closed' );
             //bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) );
             return new WP_Error('bbp_edit_topic_forum_closed', '', $data);
         }
         // Forum is private and user cannot access
         if (bbp_is_forum_private($forum_id)) {
             if (!user_can($topic_author, 'read_private_forums')) {
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_private' );
                 //bbp_add_error( 'bbp_edit_topic_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
                 return new WP_Error('bbp_edit_topic_forum_private', '', $data);
             }
         }
         // Forum is hidden and user cannot access
         if (bbp_is_forum_hidden($forum_id)) {
             if (!user_can($topic_author, 'read_hidden_forums')) {
                 //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_hidden' );
                 //bbp_add_error( 'bbp_edit_topic_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
                 return new WP_Error('bbp_edit_topic_forum_hidden', '', $data);
             }
         }
     }
     /** UNFILTERED HTML **********************************************/
     // Remove wp_filter_kses filters from title and content for capable users
     if (user_can($topic_author, 'unfiltered_html')) {
         remove_filter('bbp_new_topic_pre_title', 'wp_filter_kses');
         remove_filter('bbp_new_topic_pre_content', 'wp_filter_kses');
     }
     /** TOPIC DATA ***************************************************/
     $topic_content = $data['content'];
     $topic_title = $data['subject'];
     bp_rbe_log('Message #' . $i . ': body contents - ' . $topic_content);
     bp_rbe_log('Subject - ' . $topic_title);
     if (empty($topic_content) || empty($topic_title)) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_new_forum_topic_empty' );
         return new WP_Error('bbp_new_forum_topic_empty', '', $data);
     }
     // Filter and sanitize
     $topic_title = apply_filters('bbp_new_topic_pre_title', $topic_title);
     $topic_content = apply_filters('bbp_new_topic_pre_content', $topic_content);
     /** Topic Tags ****************************************************/
     /* TODO
     		if ( bbp_allow_topic_tags() ) {
     
     			// Escape tag input
     			$terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) );
     
     			// Explode by comma
     			if ( strstr( $terms, ',' ) ) {
     				$terms = explode( ',', $terms );
     			}
     
     			// Add topic tag ID as main key
     			$terms = array( bbp_get_topic_tag_tax_id() => $terms );
     		}
     		*/
     /** TOPIC MODERATION *********************************************/
     // Post Flooding
     if (!bbp_check_for_flood($anonymous_data, $topic_author)) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_flood' );
         //bbp_add_error( 'bbp_reply_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
         return new WP_Error('bbp_topic_flood', '', $data);
     }
     // Topic Duplicate
     if (!bbp_check_for_duplicate(array('post_type' => bbp_get_topic_post_type(), 'post_author' => $topic_author, 'post_content' => $topic_content, 'anonymous_data' => $anonymous_data))) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_duplicate' );
         return new WP_Error('bbp_topic_duplicate', '', $data);
     }
     // Topic Blacklist
     if (!bbp_check_for_blacklist($anonymous_data, $topic_author, $topic_title, $topic_content)) {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_blacklist' );
         return new WP_Error('bbp_topic_blacklist', '', $data);
     }
     // Topic Status
     // Maybe put into moderation
     if (!bbp_check_for_moderation($anonymous_data, $topic_author, $topic_title, $topic_content)) {
         $topic_status = bbp_get_pending_status_id();
         // Default
     } else {
         $topic_status = bbp_get_public_status_id();
     }
     /** POSTING TIME! ************************************************/
     // bbP hook before save
     do_action('bbp_new_topic_pre_extras', $forum_id);
     // Setup reply data
     $topic_data = apply_filters('bbp_new_topic_pre_insert', array('post_author' => $topic_author, 'post_title' => $topic_title, 'post_content' => $topic_content, 'post_status' => $topic_status, 'post_parent' => $forum_id, 'post_type' => bbp_get_topic_post_type(), 'comment_status' => 'closed'));
     // Insert topic
     $topic_id = wp_insert_post($topic_data);
     // Topic posted!
     if (!is_wp_error($topic_id)) {
         // more internal logging
         bp_rbe_log('Message #' . $i . ': bbPress topic successfully posted!');
         // Problem posting
     } else {
         //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_error' );
         return new WP_Error('bbp_topic_error', '', $data);
     }
     /** AFTER POSTING ************************************************/
     // stuff that needs to happen after a bbP topic is posted occurs here... bbP
     // should preferably do the following at the 'bbp_new_reply' hook, until then
     // do what bbP does inline.
     // Trash Check ////////////////////////////////////////////////////
     // If the forum is trash, or the topic_status is switched to
     // trash, trash it properly
     if (get_post_field('post_status', $forum_id) == bbp_get_trash_status_id() || $topic_data['post_status'] == bbp_get_trash_status_id()) {
         // Trash the reply
         wp_trash_post($topic_id);
     }
     // Spam Check /////////////////////////////////////////////////////
     // If reply or topic are spam, officially spam this reply
     if ($topic_data['post_status'] == bbp_get_spam_status_id()) {
         add_post_meta($topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id());
     }
     // Reply By Email /////////////////////////////////////////////////
     // Add a RBE marker to the post's meta
     // Could potentially show that post was made via email on the frontend
     add_post_meta($topic_id, 'bp_rbe', 1);
     /** POST HOOKS ***************************************************/
     // RBE Custom Hooks ///////////////////////////////////////////////
     // change activity action
     add_filter('bbp_before_record_activity_parse_args', array($this, 'change_activity_action'));
     // add RBE's special activity hook
     add_action('bp_activity_after_save', array($this, 'activity_rbe_hook'));
     // bbPress Topic Hooks ////////////////////////////////////////////
     do_action('bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author);
     do_action('bbp_new_topic_post_extras', $topic_id);
     return array('bbp_topic_id' => $topic_id);
 }
 /**
  * Parses and returns the email body content.
  *
  * @param string $body The email body content.
  * @param bool $html Whether the email body is HTML or not. Defaults to false.
  * @param bool $reply Whether the current item is a reply.  Defaults to true.
  * @param int $i The current email message number.
  * @return string|bool
  */
 public static function get_body($body = '', $html = false, $reply = true, $i = 1)
 {
     if ($html) {
         $body = apply_filters('bp_rbe_parse_html_email', $body);
     }
     // Check to see if we're parsing a reply
     if ($reply) {
         // Find our pointer
         $pointer = strpos($body, bp_rbe_get_marker());
         // If our pointer isn't found, return false
         if ($pointer === false) {
             return false;
         }
         // Return email body up to our pointer only
         $body = apply_filters('bp_rbe_parse_email_body_reply', trim(substr($body, 0, $pointer)), $body);
         // this means we're posting something new (eg. new forum topic)
         // do something special for this case
     } else {
         $body = apply_filters('bp_rbe_parse_email_body_new', $body);
     }
     if (empty($body)) {
         bp_rbe_log('Message #' . $i . ': empty body');
         return false;
     }
     return apply_filters('bp_rbe_parse_email_body', trim($body));
 }
 /**
  * Webhook parser class method for Mandrill.
  */
 public function webhook_parser()
 {
     if (empty($_SERVER['HTTP_X_MANDRILL_SIGNATURE'])) {
         return;
     }
     if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mandrill-Webhook/') === false) {
         return;
     }
     if (empty($_POST) || empty($_POST['mandrill_events'])) {
         return;
     }
     bp_rbe_log('- Mandrill webhook received -');
     // mandrill signature verification
     if (defined('BP_RBE_MANDRILL_WEBHOOK_URL') && defined('BP_RBE_MANDRILL_WEBHOOK_KEY')) {
         $signed_data = constant('BP_RBE_MANDRILL_WEBHOOK_URL');
         $signed_data .= 'mandrill_events';
         $signed_data .= stripslashes($_POST['mandrill_events']);
         $webhook_key = constant('BP_RBE_MANDRILL_WEBHOOK_KEY');
         $signature = base64_encode(hash_hmac('sha1', $signed_data, $webhook_key, true));
         // check if generated signature matches Mandrill's
         if ($signature !== $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) {
             bp_rbe_log('Mandrill signature verification failed.');
             die;
         }
     }
     // get parsed content
     $response = json_decode(stripslashes($_POST['mandrill_events']));
     // log JSON errors if present
     if (json_last_error() != JSON_ERROR_NONE) {
         switch (json_last_error()) {
             case JSON_ERROR_DEPTH:
                 bp_rbe_log('json error: - Maximum stack depth exceeded');
                 break;
             case JSON_ERROR_STATE_MISMATCH:
                 bp_rbe_log('json error: - Underflow or the modes mismatch');
                 break;
             case JSON_ERROR_CTRL_CHAR:
                 bp_rbe_log('json error: - Unexpected control character found');
                 break;
             case JSON_ERROR_SYNTAX:
                 bp_rbe_log('json error: - Syntax error, malformed JSON');
                 break;
             case JSON_ERROR_UTF8:
                 bp_rbe_log('json error: - Malformed UTF-8 characters, possibly incorrectly encoded');
                 break;
             default:
                 bp_rbe_log('json error: - Unknown error');
                 break;
         }
         die;
         // ready to start the parsing!
     } else {
         $i = 1;
         foreach ($response as $item) {
             $data = array('headers' => $item->msg->headers, 'to_email' => $item->msg->email, 'from_email' => $item->msg->from_email, 'content' => $item->msg->text, 'subject' => $item->msg->subject);
             $parser = BP_Reply_By_Email_Parser::init($data, $i);
             if (is_wp_error($parser)) {
                 do_action('bp_rbe_no_match', $parser, $data, $i, false);
             }
             ++$i;
         }
         bp_rbe_log('- Webhook parsing completed -');
         die;
     }
 }
 /**
  * Fetch all headers for an email and parses them into an array.
  *
  * @uses imap_fetchheader() Grabs full, raw unmodified email header
  * @param resource $imap The current IMAP connection
  * @param int $i The current email message number
  * @return mixed Array of email headers. False if no headers.
  */
 protected function get_mail_headers($imap, $i)
 {
     // Grab full, raw email header
     $header = imap_fetchheader($imap, $i);
     // No header? Return false
     if (empty($header)) {
         bp_rbe_log('Message #' . $i . ': error - no IMAP header');
         return false;
     }
     // Do a regex match
     $pattern = apply_filters('bp_rbe_header_regex', '/([^: ]+): (.+?(?:\\r\\n\\s(?:.+?))*)\\r\\n/m');
     preg_match_all($pattern, $header, $matches);
     // Parse headers into an array with descriptive key
     $headers = array_combine($matches[1], $matches[2]);
     // No headers? Return false
     if (empty($headers)) {
         bp_rbe_log('Message #' . $i . ': error - no headers found');
         return false;
     }
     return $headers;
 }
Ejemplo n.º 13
0
 /**
  * Post by email routine.
  *
  * Validates the parsed data and posts the various BuddyPress content.
  *
  * @since 1.0-RC3
  *
  * @param bool $retval True by default.
  * @param array $data {
  *     An array of arguments.
  *
  *     @type array $headers Email headers.
  *     @type string $content The email body content.
  *     @type string $subject The email subject line.
  *     @type int $user_id The user ID who sent the email.
  *     @type bool $is_html Whether the email content is HTML or not.
  *     @type int $i The email message number.
  * }
  * @param array $params Parsed paramaters from the email address querystring.
  *   See {@link BP_Reply_By_Email_Parser::get_parameters()}.
  * @return array|object Array of the parsed item on success. WP_Error object
  *  on failure.
  */
 public function post($retval, $data, $params)
 {
     global $bp, $wpdb;
     // Activity reply
     if (!empty($params['a'])) {
         bp_rbe_log('Message #' . $data['i'] . ': this is an activity reply, checking if parent activities still exist');
         // Check to see if the root activity ID and the parent activity ID exist before posting
         $activity_count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$bp->activity->table_name} WHERE id IN ( %d, %d )", $params['a'], $params['p']));
         // If $a = $p, this means that we're replying to a top-level activity update
         // So check if activity count is 1
         if ($params['a'] == $params['p'] && $activity_count != 1) {
             //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'root_activity_deleted' );
             return new WP_Error('root_activity_deleted');
             // If we're here, this means we're replying to an activity comment
             // If count != 2, this means either the super admin or activity author has deleted one of the update(s)
         } elseif ($params['a'] != $params['p'] && $activity_count != 2) {
             //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'root_or_parent_activity_deleted' );
             return new WP_Error('root_or_parent_activity_deleted');
         }
         /* Let's start posting! */
         // Add our filter to override the activity action in bp_activity_new_comment()
         bp_rbe_activity_comment_action_filter($data['user_id']);
         $comment_id = bp_activity_new_comment(array('content' => $data['content'], 'user_id' => $data['user_id'], 'activity_id' => $params['a'], 'parent_id' => $params['p']));
         if (!$comment_id) {
             //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'activity_comment_fail' );
             return new WP_Error('activity_comment_fail');
         }
         // special hook for RBE activity items
         // might want to do something like add some activity meta
         do_action('bp_rbe_new_activity', array('activity_id' => $comment_id, 'type' => 'activity_comment', 'user_id' => $data['user_id'], 'item_id' => $params['a'], 'secondary_item_id' => $params['p'], 'content' => $data['content']));
         bp_rbe_log('Message #' . $data['i'] . ': activity comment successfully posted!');
         // remove the filter after posting
         remove_filter('bp_activity_comment_action', 'bp_rbe_activity_comment_action');
         // return array of item on success
         return array('activity_comment_id' => $comment_id);
         // Private message reply
     } elseif (!empty($params['m'])) {
         if (bp_is_active($bp->messages->id)) {
             bp_rbe_log('Message #' . $data['i'] . ': this is a private message reply');
             // see if the PM thread still exists
             if (messages_is_valid_thread($params['m'])) {
                 // see if the user is in the PM conversation
                 $has_access = messages_check_thread_access($params['m'], $data['user_id']) || is_super_admin($data['user_id']);
                 if (!$has_access) {
                     //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'private_message_not_in_thread' );
                     return new WP_Error('private_message_not_in_thread');
                 }
                 // post the PM!
                 $message_id = messages_new_message(array('thread_id' => $params['m'], 'sender_id' => $data['user_id'], 'content' => $data['content']));
                 if (!$message_id) {
                     //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'private_message_fail' );
                     return new WP_Error('private_message_fail');
                 }
                 // special hook for RBE parsed PMs
                 do_action('bp_rbe_new_pm_reply', array('thread_id' => $params['m'], 'sender_id' => $data['user_id'], 'content' => $data['content']));
                 bp_rbe_log('Message #' . $data['i'] . ': PM reply successfully posted!');
                 // return array of item on success
                 return array('message_id' => $message_id);
                 // the PM thread doesn't exist anymore
             } else {
                 //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, 'private_message_thread_deleted' );
                 return new WP_Error('private_message_thread_deleted');
             }
         }
     }
 }