/**
  * Retrieves a pingback and registers it.
  *
  * @since 1.5.0
  *
  * @param array $args Method parameters.
  * @return array
  */
 function pingback_ping($args)
 {
     global $nxtdb;
     do_action('xmlrpc_call', 'pingback.ping');
     $this->escape($args);
     $pagelinkedfrom = $args[0];
     $pagelinkedto = $args[1];
     $title = '';
     $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom);
     $pagelinkedto = str_replace('&', '&', $pagelinkedto);
     $pagelinkedto = str_replace('&', '&', $pagelinkedto);
     // Check if the page linked to is in our site
     $pos1 = strpos($pagelinkedto, str_replace(array('http://www.', 'http://', 'https://www.', 'https://'), '', get_option('home')));
     if (!$pos1) {
         return new IXR_Error(0, __('Is there no link to us?'));
     }
     // let's find which post is linked to
     // FIXME: does url_to_postid() cover all these cases already?
     //        if so, then let's use it and drop the old code.
     $urltest = parse_url($pagelinkedto);
     if ($post_ID = url_to_postid($pagelinkedto)) {
         $way = 'url_to_postid()';
     } elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
         // the path defines the post_ID (archives/p/XXXX)
         $blah = explode('/', $match[0]);
         $post_ID = (int) $blah[1];
         $way = 'from the path';
     } elseif (preg_match('#p=[0-9]{1,}#', $urltest['query'], $match)) {
         // the querystring defines the post_ID (?p=XXXX)
         $blah = explode('=', $match[0]);
         $post_ID = (int) $blah[1];
         $way = 'from the querystring';
     } elseif (isset($urltest['fragment'])) {
         // an #anchor is there, it's either...
         if (intval($urltest['fragment'])) {
             // ...an integer #XXXX (simplest case)
             $post_ID = (int) $urltest['fragment'];
             $way = 'from the fragment (numeric)';
         } elseif (preg_match('/post-[0-9]+/', $urltest['fragment'])) {
             // ...a post id in the form 'post-###'
             $post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']);
             $way = 'from the fragment (post-###)';
         } elseif (is_string($urltest['fragment'])) {
             // ...or a string #title, a little more complicated
             $title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']);
             $sql = $nxtdb->prepare("SELECT ID FROM {$nxtdb->posts} WHERE post_title RLIKE %s", like_escape($title));
             if (!($post_ID = $nxtdb->get_var($sql))) {
                 // returning unknown error '0' is better than die()ing
                 return new IXR_Error(0, '');
             }
             $way = 'from the fragment (title)';
         }
     } else {
         // TODO: Attempt to extract a post ID from the given URL
         return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.'));
     }
     $post_ID = (int) $post_ID;
     logIO("O", "(PB) URL='{$pagelinkedto}' ID='{$post_ID}' Found='{$way}'");
     $post = get_post($post_ID);
     if (!$post) {
         // Post_ID not found
         return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.'));
     }
     if ($post_ID == url_to_postid($pagelinkedfrom)) {
         return new IXR_Error(0, __('The source URL and the target URL cannot both point to the same resource.'));
     }
     // Check if pings are on
     if (!pings_open($post)) {
         return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.'));
     }
     // Let's check that the remote site didn't already pingback this entry
     if ($nxtdb->get_results($nxtdb->prepare("SELECT * FROM {$nxtdb->comments} WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom))) {
         return new IXR_Error(48, __('The pingback has already been registered.'));
     }
     // very stupid, but gives time to the 'from' server to publish !
     sleep(1);
     // Let's check the remote site
     $linea = nxt_remote_fopen($pagelinkedfrom);
     if (!$linea) {
         return new IXR_Error(16, __('The source URL does not exist.'));
     }
     $linea = apply_filters('pre_remote_source', $linea, $pagelinkedto);
     // Work around bug in strip_tags():
     $linea = str_replace('<!DOC', '<DOC', $linea);
     $linea = preg_replace('/[\\s\\r\\n\\t]+/', ' ', $linea);
     // normalize spaces
     $linea = preg_replace("/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea);
     preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
     $title = $matchtitle[1];
     if (empty($title)) {
         return new IXR_Error(32, __('We cannot find a title on that page.'));
     }
     $linea = strip_tags($linea, '<a>');
     // just keep the tag we need
     $p = explode("\n\n", $linea);
     $preg_target = preg_quote($pagelinkedto, '|');
     foreach ($p as $para) {
         if (strpos($para, $pagelinkedto) !== false) {
             // it exists, but is it a link?
             preg_match("|<a[^>]+?" . $preg_target . "[^>]*>([^>]+?)</a>|", $para, $context);
             // If the URL isn't in a link context, keep looking
             if (empty($context)) {
                 continue;
             }
             // We're going to use this fake tag to mark the context in a bit
             // the marker is needed in case the link text appears more than once in the paragraph
             $excerpt = preg_replace('|\\</?nxtcontext\\>|', '', $para);
             // prevent really long link text
             if (strlen($context[1]) > 100) {
                 $context[1] = substr($context[1], 0, 100) . '...';
             }
             $marker = '<nxtcontext>' . $context[1] . '</nxtcontext>';
             // set up our marker
             $excerpt = str_replace($context[0], $marker, $excerpt);
             // swap out the link for our marker
             $excerpt = strip_tags($excerpt, '<nxtcontext>');
             // strip all tags but our context marker
             $excerpt = trim($excerpt);
             $preg_marker = preg_quote($marker, '|');
             $excerpt = preg_replace("|.*?\\s(.{0,100}{$preg_marker}.{0,100})\\s.*|s", '$1', $excerpt);
             $excerpt = strip_tags($excerpt);
             // YES, again, to remove the marker wrapper
             break;
         }
     }
     if (empty($context)) {
         // Link to target not found
         return new IXR_Error(17, __('The source URL does not contain a link to the target URL, and so cannot be used as a source.'));
     }
     $pagelinkedfrom = str_replace('&', '&amp;', $pagelinkedfrom);
     $context = '[...] ' . esc_html($excerpt) . ' [...]';
     $pagelinkedfrom = $nxtdb->escape($pagelinkedfrom);
     $comment_post_ID = (int) $post_ID;
     $comment_author = $title;
     $comment_author_email = '';
     $this->escape($comment_author);
     $comment_author_url = $pagelinkedfrom;
     $comment_content = $context;
     $this->escape($comment_content);
     $comment_type = 'pingback';
     $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email', 'comment_content', 'comment_type');
     $comment_ID = nxt_new_comment($commentdata);
     do_action('pingback_post', $comment_ID);
     return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto);
 }
Example #2
0
 /**
  * Processes pingback requests
  *
  * @since 1.0
  * @link http://www.hixie.ch/specs/pingback/pingback
  * @return string|object A message of success or an IXR_Error object on failure
  * @param array $args Arguments passed by the XML-RPC call
  * @param string $args[0] The full URI of the post where the pingback is being sent from
  * @param string $args[1] The full URI of the post where the pingback is being sent to
  *
  * XML-RPC request to register a pingback
  * <methodCall>
  *     <methodName>pingback.ping</methodName>
  *     <params>
  *         <param><value><string>http://example.org/2008/09/post-containing-a-link/</string></value></param>
  *         <param><value><string>http://example.com/2008/08/post-being-linked-to/</string></value></param>
  *     </params>
  * </methodCall>
  */
 function pingback_ping($args)
 {
     do_action('bb_xmlrpc_call', 'pingback.ping');
     $this->escape($args);
     // No particular need to sanitise
     $link_from = (string) $args[0];
     $link_to = (string) $args[1];
     // Tidy up ampersands in the URLs
     $link_from = str_replace('&amp;', '&', $link_from);
     $link_to = str_replace('&amp;', '&', $link_to);
     $link_to = str_replace('&', '&amp;', $link_to);
     // Check if the topic linked to is in our site - a little more strict than NXTClass, doesn't pull out the www if added
     if (!bb_match_domains($link_to, bb_get_uri())) {
         // These are not the droids you are looking for
         $this->error = new IXR_Error(0, __('This is not the site you are trying to pingback.'));
         return $this->error;
     }
     // Get the topic
     if ($topic_to = bb_get_topic_from_uri($link_to)) {
         // Topics shouldn't ping themselves
         if ($topic_from = bb_get_topic_from_uri($link_from)) {
             if ($topic_from->topic_id === $topic_to->topic_id) {
                 $this->error = new IXR_Error(0, __('The source URL and the target URL cannot both point to the same resource.'));
                 return $this->error;
             }
         }
     } else {
         $this->error = new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.'));
         return $this->error;
     }
     // Let's check that the remote site didn't already pingback this entry
     $query = new BB_Query('post', array('topic_id' => $topic_to->topic_id, 'append_meta' => true), 'get_thread');
     $posts_to = $query->results;
     unset($query);
     // Make sure we have some posts in the topic, this error should never happen really
     if (!$posts_to || !is_array($posts_to) || !count($posts_to)) {
         $this->error = new IXR_Error(0, __('The specified target topic does not contain any posts.'));
         return $this->error;
     }
     // Check if we already have a pingback from this URL
     foreach ($posts_to as $post) {
         if (isset($post->pingback_uri) && trim($post->pingback_uri) === trim($link_from)) {
             $this->error = new IXR_Error(48, __('The pingback has already been registered.'));
             return $this->error;
         }
     }
     unset($posts_to, $post);
     // Give time for the server sending the pingback to finish publishing it's post
     sleep(1);
     // Let's check the remote site for valid URL and content
     $link_from_source = nxt_remote_fopen($link_from);
     if (!$link_from_source) {
         $this->error = new IXR_Error(16, __('The source URL does not exist.'));
         return $this->error;
     }
     // Allow plugins to filter here
     $link_from_source = apply_filters('bb_pre_remote_source', $link_from_source, $link_to);
     // Work around bug in strip_tags()
     $link_from_source = str_replace('<!DOC', '<DOC', $link_from_source);
     // Normalize spaces
     $link_from_source = preg_replace('/[\\s\\r\\n\\t]+/', ' ', $link_from_source);
     // Turn certain elements to double line returns
     $link_from_source = preg_replace("/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $link_from_source);
     // Find the title of the page
     preg_match('|<title>([^<]*?)</title>|is', $link_from_source, $link_from_title);
     $link_from_title = $link_from_title[1];
     if (empty($link_from_title)) {
         $this->error = new IXR_Error(32, __('We cannot find a title on that page.'));
         return $this->error;
     }
     // Strip out all tags except anchors
     $link_from_source = strip_tags($link_from_source, '<a>');
     // just keep the tag we need
     // Split the source into paragraphs
     $link_from_paragraphs = explode("\n\n", $link_from_source);
     // Prepare the link to search for in preg_match() once here
     $preg_target = preg_quote($link_to);
     // Loop through the paragraphs looking for the context for the url
     foreach ($link_from_paragraphs as $link_from_paragraph) {
         // The url exists
         if (strpos($link_from_paragraph, $link_to) !== false) {
             // But is it in an anchor tag
             preg_match("|<a[^>]+?" . $preg_target . "[^>]*>([^>]+?)</a>|", $link_from_paragraph, $context);
             // If the URL isn't in an anchor tag, keep looking
             if (empty($context)) {
                 continue;
             }
             // We're going to use this fake tag to mark the context in a bit
             // the marker is needed in case the link text appears more than once in the paragraph
             $excerpt = preg_replace('|\\</?nxtcontext\\>|', '', $link_from_paragraph);
             // Prevent really long link text
             if (strlen($context[1]) > 100) {
                 $context[1] = substr($context[1], 0, 100) . '...';
             }
             // Set up the marker around the context
             $marker = '<nxtcontext>' . $context[1] . '</nxtcontext>';
             // Swap out the link for our marker
             $excerpt = str_replace($context[0], $marker, $excerpt);
             // Strip all tags except for our context marker
             $excerpt = trim(strip_tags($excerpt, '<nxtcontext>'));
             // Make the marker safe for use in regexp
             $preg_marker = preg_quote($marker);
             // Reduce the excerpt to only include 100 characters on either side of the link
             $excerpt = preg_replace("|.*?\\s(.{0,100}" . $preg_marker . "{0,100})\\s.*|s", '$1', $excerpt);
             // Strip tags again, to remove the marker wrapper
             $excerpt = strip_tags($excerpt);
             break;
         }
     }
     // Make sure the link to the target was found in the excerpt
     if (empty($context)) {
         $this->error = new IXR_Error(17, __('The source URL does not contain a link to the target URL, and so cannot be used as a source.'));
         return $this->error;
     }
     // Add whacky prefix and suffix to the excerpt and sanitize
     $excerpt = '[...] ' . esc_html($excerpt) . ' [...]';
     $this->escape($excerpt);
     // Build an array of post data to insert then insert a new post
     $postdata = array('topic_id' => $topic_to->topic_id, 'post_text' => $excerpt, 'poster_id' => 0);
     if (!($post_ID = bb_insert_post($postdata))) {
         $this->error = new IXR_Error(0, __('The pingback could not be added.'));
         return $this->error;
     }
     // Add meta to let us know where the pingback came from
     $link_from = str_replace('&', '&amp;', $link_from);
     $this->escape($link_from);
     bb_update_postmeta($post_ID, 'pingback_uri', $link_from);
     // Add the title to meta
     $this->escape($link_from_title);
     bb_update_postmeta($post_ID, 'pingback_title', $link_from_title);
     // Action for plugins and what not
     do_action('bb_pingback_post', $post_ID);
     // Return success message, complete with emoticon
     return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $link_from, $link_to);
 }
Example #3
0
 /**
  */
 public function fetch()
 {
     // try to open url
     $result = nxt_remote_fopen(self::API_URL);
     // success?
     if ($result !== false) {
         return $result;
     } else {
         return null;
     }
 }