web/wp-content/plugins/bbpress/includes/extend/akismet.php
changeset 196 5e8dcbe22c24
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/wp-content/plugins/bbpress/includes/extend/akismet.php	Tue Dec 04 18:43:10 2012 -0800
@@ -0,0 +1,686 @@
+<?php
+
+/**
+ * Main bbPress Akismet Class
+ *
+ * @package bbPress
+ * @subpackage Akismet
+ */
+
+// Exit if accessed directly
+if ( !defined( 'ABSPATH' ) ) exit;
+
+if ( !class_exists( 'BBP_Akismet' ) ) :
+/**
+ * Loads Akismet extension
+ *
+ * @since bbPress (r3277)
+ *
+ * @package bbPress
+ * @subpackage Akismet
+ */
+class BBP_Akismet {
+
+	/**
+	 * The main bbPress Akismet loader
+	 *
+	 * @since bbPress (r3277)
+	 *
+	 * @uses add_filter()
+	 */
+	public function __construct() {
+		$this->setup_actions();
+	}
+
+	/**
+	 * Setup the admin hooks
+	 *
+	 * @since bbPress (r3277)
+	 * @access private
+	 *
+	 * @uses add_filter() To add various filters
+	 * @uses add_action() To add various actions
+	 */
+	private function setup_actions() {
+
+		// Prevent debug notices
+		$checks = array();
+
+		// bbPress functions to check for spam
+		$checks['check']  = array(
+			'bbp_new_topic_pre_insert'  => 1,  // New topic check
+			'bbp_new_reply_pre_insert'  => 1,  // New reply check
+			'bbp_edit_topic_pre_insert' => 1,  // Edit topic check
+			'bbp_edit_reply_pre_insert' => 1   // Edit reply check
+		);
+
+		// bbPress functions for spam and ham submissions
+		$checks['submit'] = array(
+			'bbp_spammed_topic'   => 10, // Spammed topic
+			'bbp_unspammed_topic' => 10, // Unspammed reply
+			'bbp_spammed_reply'   => 10, // Spammed reply
+			'bbp_unspammed_reply' => 10, // Unspammed reply
+		);
+
+		// Add the checks
+		foreach ( $checks as $type => $functions )
+			foreach( $functions as $function => $priority )
+				add_filter( $function, array( $this, $type . '_post'  ), $priority );
+
+		// Update post meta
+		add_action( 'wp_insert_post', array( $this, 'update_post_meta' ), 10, 2 );
+	}
+
+	/**
+	 * Converts topic/reply data into Akismet comment checking format
+	 *
+	 * @since bbPress (r3277)
+	 *
+	 * @param string $post_data
+	 *
+	 * @uses get_userdata() To get the user data
+	 * @uses bbp_filter_anonymous_user_data() To get anonymous user data
+	 * @uses bbp_get_topic_permalink() To get the permalink of the topic
+	 * @uses bbp_get_reply_url() To get the permalink of the reply
+	 * @uses bbp_current_author_ip() To get the IP address of the current user
+	 * @uses BBP_Akismet::maybe_spam() To check if post is spam
+	 * @uses akismet_get_user_roles() To get the role(s) of the current user
+	 * @uses do_action() To call the 'bbp_akismet_spam_caught' hook
+	 * @uses add_filter() To call the 'bbp_new_reply_pre_set_terms' hook
+	 *
+	 * @return array Array of post data
+	 */
+	public function check_post( $post_data ) {
+
+		// Define local variables
+		$user_data = array();
+		$post_permalink = '';
+
+		// Post is not published
+		if ( bbp_get_public_status_id() != $post_data['post_status'] )
+			return $post_data;
+
+		// Cast the post_author to 0 if it's empty
+		if ( empty( $post_data['post_author'] ) )
+			$post_data['post_author'] = 0;
+
+		/** Author ************************************************************/
+
+		// Get user data
+		$userdata       = get_userdata( $post_data['post_author'] );
+		$anonymous_data = bbp_filter_anonymous_post_data();
+
+		// Author is anonymous
+		if ( !empty( $anonymous_data ) ) {
+			$user_data['name']    = $anonymous_data['bbp_anonymous_name'];
+			$user_data['email']   = $anonymous_data['bbp_anonymous_name'];
+			$user_data['website'] = $anonymous_data['bbp_anonymous_name'];
+
+		// Author is logged in
+		} elseif ( !empty( $userdata ) ) {
+			$user_data['name']    = $userdata->display_name;
+			$user_data['email']   = $userdata->user_email;
+			$user_data['website'] = $userdata->user_url;
+
+		// Missing author data, so set some empty strings
+		} else {
+			$user_data['name']    = '';
+			$user_data['email']   = '';
+			$user_data['website'] = '';
+		}
+
+		/** Post **************************************************************/
+
+		// Use post parent for permalink
+		if ( !empty( $post_data['post_parent'] ) )
+			$post_permalink = get_permalink( $post_data['post_parent'] );
+
+		// Put post_data back into usable array
+		$_post = array(
+			'comment_author'       => $user_data['name'],
+			'comment_author_email' => $user_data['email'],
+			'comment_author_url'   => $user_data['website'],
+			'comment_content'      => $post_data['post_content'],
+			'comment_post_ID'      => $post_data['post_parent'],
+			'comment_type'         => $post_data['post_type'],
+			'permalink'            => $post_permalink,
+			'referrer'             => $_SERVER['HTTP_REFERER'],
+			'user_agent'           => $_SERVER['HTTP_USER_AGENT'],
+			'user_ID'              => $post_data['post_author'],
+			'user_ip'              => bbp_current_author_ip(),
+			'user_role'            => akismet_get_user_roles( $post_data['post_author'] ),
+		);
+
+		// Check the post_data
+		$_post = $this->maybe_spam( $_post );
+
+		// Get the result
+		$post_data['bbp_akismet_result'] = $_post['bbp_akismet_result'];
+		unset( $_post['bbp_akismet_result'] );
+
+		// Store the data as submitted
+		$post_data['bbp_post_as_submitted'] = $_post;
+
+		// Allow post_data to be manipulated
+		do_action_ref_array( 'bbp_akismet_check_post', $post_data );
+
+		// Spam
+		if ( 'true' == $post_data['bbp_akismet_result'] ) {
+
+			// Let plugins do their thing
+			do_action( 'bbp_akismet_spam_caught' );
+
+			// This is spam
+			$post_data['post_status'] = bbp_get_spam_status_id();
+
+			// We don't want your spam tags here
+			add_filter( 'bbp_new_reply_pre_set_terms', array( $this, 'filter_post_terms' ), 1, 3 );
+
+			// @todo Spam counter?
+		}
+
+		// @todo Topic/reply moderation? No true/false response - 'pending' or 'draft'
+		// @todo Auto-delete old spam?
+
+		// Log the last post
+		$this->last_post = $post_data;
+
+		// Pass the data back to the filter
+		return $post_data;
+	}
+
+	/**
+	 * Submit a post for spamming or hamming
+	 *
+	 * @since bbPress (r3277)
+	 *
+	 * @param int $post_id
+	 *
+	 * @global WP_Query $wpdb
+	 * @global string $akismet_api_host
+	 * @global string $akismet_api_port
+	 * @global object $current_user
+	 * @global object $current_site
+	 *
+	 * @uses current_filter() To get the reply_id
+	 * @uses get_post() To get the post object
+	 * @uses get_the_author_meta() To get the author meta
+	 * @uses get_post_meta() To get the post meta
+	 * @uses bbp_get_user_profile_url() To get a user's profile url
+	 * @uses get_permalink() To get the permalink of the post_parent
+	 * @uses akismet_get_user_roles() To get the role(s) of the post_author
+	 * @uses bbp_current_author_ip() To get the IP address of the current user
+	 * @uses BBP_Akismet::maybe_spam() To submit the post as ham or spam
+	 * @uses update_post_meta() To update the post meta with some Akismet data
+	 * @uses do_action() To call the 'bbp_akismet_submit_spam_post' and 'bbp_akismet_submit_ham_post' hooks
+	 *
+	 * @return array Array of existing topic terms
+	 */
+	public function submit_post( $post_id = 0 ) {
+		global $current_user, $current_site;
+
+		// Innocent until proven guilty
+		$request_type   = 'ham';
+		$current_filter = current_filter();
+
+		// Check this filter and adjust the $request_type accordingly
+		switch ( $current_filter ) {
+
+			// Mysterious, and straight from the can
+			case 'bbp_spammed_topic' :
+			case 'bbp_spammed_reply' :
+				$request_type = 'spam';
+				break;
+
+			// Honey-glazed, a straight off the bone
+			case 'bbp_unspammed_topic' :
+			case 'bbp_unspammed_reply' :
+				$request_type = 'ham';
+				break;
+
+			// Possibly poison...
+			default :
+				return;
+		}
+
+		// Setup some variables
+		$post_id = (int) $post_id;
+
+		// Make sure we have a post
+		$_post = get_post( $post_id );
+
+		// Bail if get_post() fails
+		if ( empty( $_post ) )
+			return;
+
+		// Bail if we're spamming, but the post_status isn't spam
+		if ( ( 'spam' == $request_type ) && ( bbp_get_spam_status_id() != $_post->post_status ) )
+			return;
+
+		// Set some default post_data
+		$post_data = array(
+			'comment_approved'     => $_post->post_status,
+			'comment_author'       => $_post->post_author ? get_the_author_meta( 'display_name', $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_name',    true ),
+			'comment_author_email' => $_post->post_author ? get_the_author_meta( 'email',        $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_email',   true ),
+			'comment_author_url'   => $_post->post_author ? bbp_get_user_profile_url(            $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_website', true ),
+			'comment_content'      => $_post->post_content,
+			'comment_date'         => $_post->post_date,
+			'comment_ID'           => $post_id,
+			'comment_post_ID'      => $_post->post_parent,
+			'comment_type'         => $_post->post_type,
+			'permalink'            => get_permalink( $post_id ),
+			'user_ID'              => $_post->post_author,
+			'user_ip'              => get_post_meta( $post_id, '_bbp_author_ip', true ),
+			'user_role'            => akismet_get_user_roles( $_post->post_author ),
+		);
+
+		// Use the original version stored in post_meta if available
+		$as_submitted = get_post_meta( $post_id, '_bbp_akismet_as_submitted', true );
+		if ( $as_submitted && is_array( $as_submitted ) && isset( $as_submitted['comment_content'] ) )
+			$post_data = array_merge( $post_data, $as_submitted );
+
+		// Add the reporter IP address
+		$post_data['reporter_ip']  = bbp_current_author_ip();
+
+		// Add some reporter info
+		if ( is_object( $current_user ) )
+		    $post_data['reporter'] = $current_user->user_login;
+
+		// Add the current site domain
+		if ( is_object( $current_site ) )
+			$post_data['site_domain'] = $current_site->domain;
+
+		// Place your slide beneath the microscope
+		$post_data = $this->maybe_spam( $post_data, 'submit', $request_type );
+
+		// Manual user action
+		if ( isset( $post_data['reporter'] ) ) {
+
+			// What kind of action
+			switch ( $request_type ) {
+
+				// Spammy
+				case 'spam' :
+					$this->update_post_history( $post_id, sprintf( __( '%1$s reported this %2$s as spam', 'bbpress' ),     $post_data['reporter'], $post_data['comment_type'] ), 'report-spam' );
+					update_post_meta( $post_id, '_bbp_akismet_user_result', 'true'                 );
+					update_post_meta( $post_id, '_bbp_akismet_user',        $post_data['reporter'] );
+					break;
+
+				// Hammy
+				case 'ham'  :
+					$this->update_post_history( $post_id, sprintf( __( '%1$s reported this %2$s as not spam', 'bbpress' ), $post_data['reporter'], $post_data['comment_type'] ), 'report-ham'  );
+					update_post_meta( $post_id, '_bbp_akismet_user_result', 'false'                 );
+					update_post_meta( $post_id, '_bbp_akismet_user',         $post_data['reporter'] );
+
+					// @todo Topic term revision history
+					break;
+
+				// Possible other actions
+				default :
+					break;
+			}
+		}
+
+		do_action( 'bbp_akismet_submit_' . $request_type . '_post', $post_id, $post_data['bbp_akismet_result'] );
+	}
+
+	/**
+	 * Ping Akismet service and check for spam/ham response
+	 *
+	 * @since bbPress (r3277)
+	 *
+	 * @param array $post_data
+	 * @param string $check Accepts check|submit
+	 * @param string $spam Accepts spam|ham
+	 *
+	 * @global string $akismet_api_host
+	 * @global string $akismet_api_port
+	 *
+	 * @uses akismet_test_mode() To determine if Akismet is in test mode
+	 * @uses akismet_http_post() To send data to the mothership for processing
+	 *
+	 * @return array Array of post data
+	 */
+	private function maybe_spam( $post_data, $check = 'check', $spam = 'spam' ) {
+		global $akismet_api_host, $akismet_api_port;
+
+		// Define variables
+		$query_string = $path = $response = '';
+
+		// Populate post data
+		$post_data['blog']         = get_option( 'home' );
+		$post_data['blog_charset'] = get_option( 'blog_charset' );
+		$post_data['blog_lang']    = get_locale();
+		$post_data['referrer']     = $_SERVER['HTTP_REFERER'];
+		$post_data['user_agent']   = $_SERVER['HTTP_USER_AGENT'];
+
+		// Akismet Test Mode
+		if ( akismet_test_mode() )
+			$post_data['is_test'] = 'true';
+
+		// Loop through _POST args and rekey strings
+		foreach ( $_POST as $key => $value )
+			if ( is_string( $value ) )
+				$post_data['POST_' . $key] = $value;
+
+		// Keys to ignore
+		$ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' );
+
+		// Loop through _SERVER args and remove whitelisted keys
+		foreach ( $_SERVER as $key => $value ) {
+
+			// Key should not be ignored
+			if ( !in_array( $key, $ignore ) && is_string( $value ) ) {
+				$post_data[$key] = $value;
+
+			// Key should be ignored
+			} else {
+				$post_data[$key] = '';
+			}
+		}
+
+		// Ready...
+		foreach ( $post_data as $key => $data )
+			$query_string .= $key . '=' . urlencode( stripslashes( $data ) ) . '&';
+
+		// Aim...
+		if ( 'check' == $check ) {
+			$path = '/1.1/comment-check';
+		} elseif ( 'submit' == $check ) {
+			$path = '/1.1/submit-' . $spam;
+		}
+
+		// Fire!
+		$response = $this->http_post( $query_string, $akismet_api_host, $path, $akismet_api_port );
+
+		// Check the high-speed cam
+		if ( !empty( $response[1] ) ) {
+			$post_data['bbp_akismet_result'] = $response[1];
+		} else {
+			$post_data['bbp_akismet_result'] = __( 'No response', 'bbpress' );
+		}
+
+		// This is ham
+		return $post_data;
+	}
+
+	/**
+	 * Update post meta after a spam check
+	 *
+	 * @since bbPress (r3308)
+	 *
+	 * @param int $post_id
+	 * @param object $_post
+	 *
+	 * @global object $this->last_post
+	 *
+	 * @uses get_post() To get the post object
+	 * @uses get_userdata() To get the user data
+	 * @uses bbp_filter_anonymous_user_data() To get anonymous user data
+	 * @uses update_post_meta() To update post meta with Akismet data
+	 * @uses BBP_Akismet::update_post_history() To update post Akismet history
+	 */
+	public function update_post_meta( $post_id = 0, $_post = false ) {
+
+		// Define local variable(s)
+		$as_submitted = false;
+
+		// Setup some variables
+		$post_id = (int) $post_id;
+
+		// Ensure we have a post object
+		if ( empty( $_post ) )
+			$_post = get_post( $post_id );
+
+		// Set up Akismet last post data
+		if ( !empty( $this->last_post ) )
+			$as_submitted = $this->last_post['bbp_post_as_submitted'];
+
+		// wp_insert_post() might be called in other contexts. Ensure this is
+		// the same topic/reply as was checked by BBP_Akismet::check_post()
+		if ( is_object( $_post ) && !empty( $this->last_post ) && is_array( $as_submitted ) ) {
+
+			// Get user data
+			$userdata       = get_userdata( $_post->post_author );
+			$anonymous_data = bbp_filter_anonymous_post_data();
+
+			// More checks
+			if (	intval( $as_submitted['comment_post_ID'] )    == intval( $_post->post_parent )
+					&&      $as_submitted['comment_author']       == ( $anonymous_data ? $anonymous_data['bbp_anonymous_name']  : $userdata->display_name )
+					&&      $as_submitted['comment_author_email'] == ( $anonymous_data ? $anonymous_data['bbp_anonymous_email'] : $userdata->user_email   )
+				) {
+
+				// Normal result: true
+				if ( $this->last_post['bbp_akismet_result'] == 'true' ) {
+
+					// Leave a trail so other's know what we did
+					update_post_meta( $post_id, '_bbp_akismet_result', 'true' );
+					$this->update_post_history( $post_id, __( 'Akismet caught this post as spam', 'bbpress' ), 'check-spam' );
+
+					// If post_status isn't the spam status, as expected, leave a note
+					if ( $_post->post_status != bbp_get_spam_status_id() ) {
+						$this->update_post_history( $post_id, sprintf( __( 'Post status was changed to %s', 'bbpress' ), $_post->post_status ), 'status-changed-' . $_post->post_status );
+					}
+
+				// Normal result: false
+				} elseif ( $this->last_post['bbp_akismet_result'] == 'false' ) {
+
+					// Leave a trail so other's know what we did
+					update_post_meta( $post_id, '_bbp_akismet_result', 'false' );
+					$this->update_post_history( $post_id, __( 'Akismet cleared this post', 'bbpress' ), 'check-ham' );
+
+					// If post_status is the spam status, which isn't expected, leave a note
+					if ( $_post->post_status == bbp_get_spam_status_id() ) {
+
+						// @todo Use wp_blacklist_check()
+
+						$this->update_post_history( $post_id, sprintf( __( 'Post status was changed to %s', 'bbpress' ), $_post->post_status ), 'status-changed-' . $_post->post_status );
+					}
+
+				// Abnormal result: error
+				} else {
+					// Leave a trail so other's know what we did
+					update_post_meta( $post_id, '_bbp_akismet_error', time() );
+					$this->update_post_history( $post_id, sprintf( __( 'Akismet was unable to check this post (response: %s), will automatically retry again later.', 'bbpress' ), $this->last_post['bbp_akismet_result'] ), 'check-error' );
+				}
+
+				// Record the complete original data as submitted for checking
+				if ( isset( $this->last_post['bbp_post_as_submitted'] ) ) {
+					update_post_meta( $post_id, '_bbp_akismet_as_submitted', $this->last_post['bbp_post_as_submitted'] );
+				}
+			}
+		}
+	}
+
+	/**
+	 * Update a post's Akismet history
+	 *
+	 * @since bbPress (r3308)
+	 *
+	 * @param int $post_id
+	 * @param string $message
+	 * @param string $event
+	 *
+	 * @uses wp_get_current_user() To get the current_user object
+	 * @uses add_post_meta() Add Akismet post history
+	 */
+	private function update_post_history( $post_id = 0, $message = null, $event = null ) {
+
+		// Define local variable(s)
+		$user = '';
+
+		// Get the current user
+		$current_user = wp_get_current_user();
+
+		// Get the user's login name if possible
+		if ( is_object( $current_user ) && isset( $current_user->user_login ) )
+			$user = $current_user->user_login;
+
+		// Setup the event to be saved
+		$event = array(
+			'time'    => akismet_microtime(),
+			'message' => $message,
+			'event'   => $event,
+			'user'    => $user,
+		);
+
+		// Save the event data
+		add_post_meta( $post_id, '_bbp_akismet_history', $event );
+	}
+
+	/**
+	 * Get a post's Akismet history
+	 *
+	 * @since bbPress (r3308)
+	 *
+	 * @param int $post_id
+	 *
+	 * @uses wp_get_current_user() To get the current_user object
+	 * @uses get_post_meta() Get a post's Akismet history
+	 *
+	 * @return array Array of a post's Akismet history
+	 */
+	public function get_post_history( $post_id = 0 ) {
+
+		// Retrieve any previous history
+		$history = get_post_meta( $post_id, '_bbp_akismet_history' );
+
+		// Sort it by the time recorded
+		usort( $history, 'akismet_cmp_time' );
+
+		return $history;
+	}
+
+	/**
+	 * Handle any terms submitted with a post flagged as spam
+	 *
+	 * @since bbPress (r3308)
+	 *
+	 * @param string $terms Comma-separated list of terms
+	 * @param int $topic_id
+	 * @param int $reply_id
+	 *
+	 * @uses bbp_get_reply_id() To get the reply_id
+	 * @uses bbp_get_topic_id() To get the topic_id
+	 * @uses wp_get_object_terms() To a post's current terms
+	 * @uses update_post_meta() To add spam terms to post meta
+	 *
+	 * @return array Array of existing topic terms
+	 */
+	public function filter_post_terms( $terms = '', $topic_id = 0, $reply_id = 0 ) {
+
+		// Validate the reply_id and topic_id
+		$reply_id = bbp_get_reply_id( $reply_id );
+		$topic_id = bbp_get_topic_id( $topic_id );
+
+		// Get any pre-existing terms
+		$existing_terms = wp_get_object_terms( $topic_id, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
+
+		// Save the terms for later in case the reply gets hammed
+		if ( !empty( $terms ) )
+			update_post_meta( $reply_id, '_bbp_akismet_spam_terms', $terms );
+
+		// Keep the topic tags the same for now
+		return $existing_terms;
+	}
+
+	/**
+	 * Submit data to Akismet service with unique bbPress User Agent
+	 *
+	 * This code is directly taken from the akismet_http_post() function and
+	 * documented to bbPress 2.0 standard.
+	 *
+	 * @since bbPress (r3466)
+	 *
+	 * @param string $request The request we are sending
+	 * @param string $host The host to send our request to
+	 * @param string $path The path from the host
+	 * @param string $port The port to use
+	 * @param string $ip Optional Override $host with an IP address
+	 * @uses bbp_get_version() To get the current bbPress version
+	 * @return mixed WP_Error on error, array on success, empty on failure
+	 */
+	private function http_post( $request, $host, $path, $port = 80, $ip = '' ) {
+
+		// Preload required variables
+		$bbp_version    = bbp_get_version();
+		$content_length = strlen( $request );
+		$http_host      = $host;
+		$blog_charset   = get_option( 'blog_charset' );
+		$response       = '';
+		$errno          = null;
+		$errstr         = null;
+
+		// Untque User Agent
+		$akismet_ua     = "bbPress/{$bbp_version} | ";
+		$akismet_ua    .= 'Akismet/' . constant( 'AKISMET_VERSION' );
+
+		// Use specific IP (if provided)
+		if ( !empty( $ip ) && long2ip( ip2long( $ip ) ) )
+			$http_host = $ip;
+
+		// WP HTTP class is available
+		if ( function_exists( 'wp_remote_post' ) ) {
+
+			// Setup the arguments
+			$http_args = array(
+				'body'             => $request,
+				'headers'          => array(
+					'Content-Type' => 'application/x-www-form-urlencoded; charset=' . $blog_charset,
+					'Host'         => $host,
+					'User-Agent'   => $akismet_ua
+				),
+				'httpversion'      => '1.0',
+				'timeout'          => 15
+			);
+
+			// Where we are sending our request
+			$akismet_url = 'http://' . $http_host . $path;
+
+			// Send the request
+			$response    = wp_remote_post( $akismet_url, $http_args );
+
+			// Bail if the response is an error
+			if ( is_wp_error( $response ) )
+				return '';
+
+			// No errors so return response
+			return array( $response['headers'], $response['body'] );
+
+		// WP HTTP class is not available (Why not?)
+		} else {
+
+			// Header info to use with our socket
+			$http_request  = "POST {$path} HTTP/1.0\r\n";
+			$http_request .= "Host: {$host}\r\n";
+			$http_request .= "Content-Type: application/x-www-form-urlencoded; charset={$blog_charset}\r\n";
+			$http_request .= "Content-Length: {$content_length}\r\n";
+			$http_request .= "User-Agent: {$akismet_ua}\r\n";
+			$http_request .= "\r\n";
+			$http_request .= $request;
+
+			// Open a socket connection
+			if ( false != ( $fs = @fsockopen( $http_host, $port, $errno, $errstr, 10 ) ) ) {
+
+				// Write our request to the pointer
+				fwrite( $fs, $http_request );
+
+				// Loop through pointer and compile a response
+				while ( !feof( $fs ) ) {
+					// One TCP-IP packet at a time
+					$response .= fgets( $fs, 1160 );
+				}
+
+				// Close our socket
+				fclose( $fs );
+
+				// Explode the response into usable data
+				$response = explode( "\r\n\r\n", $response, 2 );
+			}
+
+			// Return the response ('' if error/empty)
+			return $response;
+		}
+	}
+}
+endif;