- <?php
-
- function pingback_perm() {
- return array('administer pingbacks');
- }
-
-
- function pingback_menu($may_cache) {
- $items = array();
- if ($may_cache) {
- $items[] = array(
- 'path' => 'admin/settings/pingback',
- 'title' => t('Pingback'),
- 'description' => t('Configure pingbacks.'),
- 'callback' => 'drupal_get_form',
- 'callback arguments' => array('pingback_settings_form'),
- 'access' => user_access('administer pingbacks'),
- );
- }
- else {
-
-
- require_once drupal_get_path('module', 'pingback') . '/pingback.admin.inc';
-
-
- if (arg(0) == 'node' && is_numeric(arg(1)) && arg(3) == NULL) {
- drupal_set_header('X-Pingback: ' .$GLOBALS['base_url'] . '/xmlrpc.php');
-
- }
- }
- return $items;
- }
-
- function pingback_form_alter($form_id, &$form) {
- global $user;
- if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
- $type = $form['#node_type']->type;
- $form['workflow']['pingback'] = array(
- '#type' => 'radios',
- '#title' => t('Pingbacks'),
- '#options' => array(1 => t('Enabled'), 0 => t('Disabled')),
- '#default_value' => _pingback_valid_for_node_type($type),
- '#description' => t('Enable pingbacks for this node type.')
- );
- }
- else if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
- $node = $form['#node'];
- if (_pingback_valid_for_node_type($node->type)) {
-
- $past_successes_listing = array();
- $q = db_query("SELECT url FROM {pingback_sent} WHERE nid = %d", $node->nid);
- while ($pb = db_fetch_object($q)) {
- $past_successes_listing[] = $pb->url;
- }
-
- if (count($past_successes_listing)) {
- $form['pingback'] = array(
- '#type' => 'fieldset',
- '#title' => t('Pingbacks'),
- '#collapsible' => TRUE
- );
- $form['pingback'][] = array(
- '#type' => 'markup',
- '#value' => theme('item_list', $past_successes_listing, t('Successfully pingbacked URLs')),
- );
-
- }
- }
- }
-
- else if (
- $form_id == 'comment_form'
- && (!$user->uid)
- && variable_get('pingback_hide_format_for_anon', 0)
-
- ) {
-
- $alternate_formats = array();
- foreach ($form['comment_filter']['format'] as $k => $v) {
-
- if (!element_property($k) && isset($v['#return_value'])) {
- if ($v['#return_value'] == variable_get('pingback_input_format', FILTER_FORMAT_DEFAULT)) {
- unset($form['comment_filter']['format'][$k]);
- }
- else {
-
- $alternate_formats[] = $k;
- }
- }
- }
- if (count($alternate_formats) == 1) {
-
- $new_form[$alternate_formats[0]] = array(
- '#type' => 'value',
- '#value' => $alternate_formats[0],
- '#parents' => $form['comment_filter']['format'][$alternate_formats[0]]['#parents'],
- );
- $new_form['format']['guidelines'] = array(
- '#title' => t('Formatting guidelines'),
- '#value' => $form['comment_filter']['format'][$alternate_formats[0]]['#description'],
- );
- $form['comment_filter']['format'] = $new_form;
- }
- }
- }
-
-
- * Menu callback: lists pingbacks. TODO: ability to delete them!
- */
-
- function pingback_list_page() {
-
- return 'TODO';
- }
-
-
- function pingback_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
-
- if (_pingback_valid_for_node_type($node->type)) {
- switch ($op) {
- case 'insert':
- case 'update':
- if (variable_get('pingback_mode', 'off') == 'submit') {
- global $pingback_nid;
- $pingback_nid = $node->nid;
- }
- else {
-
- $q = variable_get('pingback_nid_queue', array());
- if (!in_array($node->nid, $q)) {
- $q[] = $node->nid;
- variable_set('pingback_nid_queue', $q);
- }
- }
- break;
-
- }
- }
- }
-
-
- function pingback_cron() {
- $q = variable_get('pingback_nid_queue', array());
- $limit = variable_get('pingback_check_per_cron', 30);
- $count = 0;
-
- while (($nid = array_shift($q)) && ($count++ < $limit)) {
- pingback_send_by_nid($nid, FALSE);
-
- }
- variable_set('pingback_nid_queue', $q);
- }
-
- function pingback_exit() {
- global $pingback_nid;
- if (isset($pingback_nid)) {
-
- node_load($pingback_nid, NULL, TRUE);
- pingback_send_by_nid($pingback_nid, variable_get('pingback_notify_successful_pings', 1));
- }
- }
-
-
- function pingback_xmlrpc() {
- return array(
- array(
- 'pingback.ping',
- 'pingback_receive',
- array('string', 'string', 'string'),
- t('Handles pingback pings.'),
- ),
- );
- }
-
-
- * XML-RPC callback: process pingback.ping() call.
- */
- function pingback_receive($pagelinkedfrom, $pagelinkedto) {
-
-
-
-
- if (!variable_get('pingback_receive', 1)) return xmlrpc_server_error(33, t("The specified target URL cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource."));
-
-
- $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom);
- $pagelinkedto = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedto);
- $error_code = -1;
-
-
- $pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', $GLOBALS['base_url']));
- if( !$pos1 ) {
- return new xmlrpc_server_error(0, t('Is there no link to us?'));
- }
-
-
- $nid = _pingback_url_to_nid($pagelinkedto);
-
-
-
-
- $node = $nid ? node_load($nid) : FALSE;
-
-
- if (!$node || !_pingback_valid_for_node($node))
- return xmlrpc_server_error(33, t("The specified target URL cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource."));
-
- if ($nid == _pingback_url_to_nid($pagelinkedfrom))
- return xmlrpc_server_error(0, t('The source URL and the target URL cannot both point to the same resource.'));
-
- if (!$node->status)
- return xmlrpc_server_error(33, t("The specified target URL cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource."));
-
-
- $result = db_query("SELECT cid FROM {comments} WHERE nid = %d AND homepage = '%s' AND format = %d", $nid, $pagelinkedfrom, variable_get('pingback_input_format', FILTER_FORMAT_DEFAULT));
-
- if (db_num_rows($result))
- return xmlrpc_server_error(48, 'The pingback has already been registered.');
-
-
- sleep(1);
-
-
- $r = drupal_http_request($pagelinkedfrom);
- if ($r->error)
- return xmlrpc_server_error(16, 'The source URL does not exist.');
-
- $linea = $r->data;
-
-
- $linea = str_replace('<!DOC', '<DOC', $linea);
- $linea = preg_replace( '/[\s\r\n\t]+/', ' ', $linea );
- $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 = check_plain($matchtitle[1]);
- if ( empty( $title ) )
- return xmlrpc_server_error(32, 'We cannot find a title on that page.');
-
- $linea = strip_tags( $linea, '<a>' );
-
- $p = explode( "\n\n", $linea );
-
- $preg_target = preg_quote($pagelinkedto);
-
- foreach ( $p as $para ) {
- if ( strpos($para, $pagelinkedto) !== false ) {
- preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context);
-
-
- if (empty($context)) continue;
-
-
-
-
- $excerpt = preg_replace('|\</?dpcontext\>|', '', $para);
-
-
- if ( strlen($context[1]) > 100 )
- $context[1] = substr($context[1], 0, 100) . '...';
-
-
- $marker = '<dpcontext>'.$context[1].'</dpcontext>';
- $excerpt = str_replace($context[0], $marker, $excerpt);
- $excerpt = strip_tags($excerpt, '<dpcontext>');
- $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);
-
- break;
- }
- }
-
- if (empty($context))
- return xmlrpc_server_error(17, t('The source URL does not contain a link to the target URL, and so cannot be used as a source.'));
-
-
- $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedfrom);
-
-
-
- $edit = array(
- 'nid' => $nid,
- 'subject' => t('Pingback'),
- 'comment' => '[...] ' . $excerpt . ' [...]',
- 'hostname' => $_SERVER['REMOTE_ADDR'],
- 'format' => variable_get('pingback_input_format', FILTER_FORMAT_DEFAULT),
- 'name' => $title,
- 'homepage' => $pagelinkedfrom,
- );
- comment_save($edit);
-
- //bypass the hiding in pingback_form_alter() because we want to use the input format
- $GLOBALS['pingback_bypass_format_hiding'] = TRUE;
- drupal_execute('comment_form', $edit, array());
- $GLOBALS['pingback_bypass_format_hiding'] = FALSE;
- watchdog('debug', print_r(form_get_errors(), TRUE));
- */
- $message = t('Pingback from @source to @target registered! Keep the web talking! :-)', array('@source' => $pagelinkedfrom, '@target' => $pagelinkedto));
-
-
- return $message;
- }
-
-
-
-
-
-
-
- function theme_pingback($pb, $links = 0) {
- return theme('comment', $pb, $links);
- }
-
-
-
-
-
-
-
- * Discover a pingback server with pingback autodiscovery schemes.
- * @param $target the absolute URL to search for its server. This should have passed check_url() first.
- */
- function pingback_discover($target) {
- $server = '';
-
- $r = drupal_http_request($target, array(), 'HEAD');
-
- if (!$r->error) {
- if (is_array($r->headers) && isset($r->headers['X-Pingback'])) {
- $server = $r->headers['X-Pingback'];
- }
- else {
-
- $get = drupal_http_request($target);
- if (!$get->error) {
-
-
- if (preg_match('#<link rel="pingback" href="([^"]+)" ?/?>#', $get->data, $matches)) {
- $server = $matches[1];
- }
-
- }
- }
- }
- if (!empty($server)) {
- return check_url($server);
- }
- else return '';
- }
-
- * Send pingbacks. Does nothing if the target does not have a pingback server.
- * @param $nid the source node ID.
- * @param $target the target absolute URL.
- * @param $source_is_absolute if this value is set to TRUE, $nid is interpreted as an absolute URL (which may originate not from the host site).
- * @return TRUE on success, FALSE otherwise.
- */
- function pingback_send($nid, $target, $source_is_absolute = FALSE) {
- if (!valid_url($target, TRUE)) return FALSE;
- if (!$source_is_absolute) {
- $source = url("node/$nid", NULL, NULL, TRUE);
- $result = db_query("SELECT nid FROM {pingback_sent} WHERE nid = %d AND url = '%s'", $nid, $target);
- if (db_num_rows($result) > 0) {
-
- return FALSE;
- }
- }
- else {
- $source = $nid;
- if (!valid_url($source)) return FALSE;
- }
-
- $retval = FALSE;
-
-
- $server = pingback_discover($target);
-
-
- if (!empty($server)) {
- if(xmlrpc($server, 'pingback.ping', $source, $target)) {
- if (!$source_is_absolute) {
- db_query("INSERT INTO {pingback_sent} (nid, url, timestamp) VALUES (%d, '%s', %d)", $nid, $target, time());
- }
- watchdog('pingback', t('Pingback to %target from %source succeeded.', array('%source' => $source, '%target' => $target)));
- return TRUE;
- }
- else {
- watchdog('pingback', t('Pingback to %target from %source failed. Error @errno: @description', array('%source' => $source, '%target' => $target, '@errno' => xmlrpc_errno(), '@description' => xmlrpc_error_msg())), WATCHDOG_WARNING);
- return FALSE;
- }
- }
- return FALSE;
- }
-
- * Sends pingbacks in all URLs in specified node.
- */
- function pingback_send_by_nid($nid, $message = TRUE) {
- global $base_root;
-
- $node = node_load($nid);
- $prepared = node_prepare($node);
- $urls = _pingback_extract_urls($prepared->body);
- if (isset($node->pingback_sent)) {
-
- }
- $succesful = array();
- foreach ($urls as $url) {
-
- if (pingback_send($node->nid, $url)) {
-
- if ($message) $successful[] = "<a href=\"$url\">$url</a>";
- }
- }
-
- if ($message && count($successful)) {
- drupal_set_message(t('!urls pingbacked successfully.', array('!urls' => implode(', ', $successful))));
- }
-
- }
-
-
- function pingback_comment_is_pingback($comment) {
- return $comment->format == variable_get('pingback_input_format', FILTER_FORMAT_DEFAULT);
- }
-
-
-
- function _pingback_valid_for_node_type($type) {
- return variable_get("pingback_$type", ($type == 'story' || $type == 'blog') ? 1 : 0);
- }
-
- function _pingback_valid_for_node($node) {
- return $node->comment == COMMENT_NODE_READ_WRITE;
- }
-
- function _pingback_extract_urls($text) {
-
- preg_match_all("/(http|https):\/\/[a-zA-Z0-9@:%_~#?&=.,\/;-]*[a-zA-Z0-9@:%_~#&=\/;-]/", $text, $urls);
- return array_unique($urls[0]);
- }
-
- function _pingback_url_to_nid($url) {
-
- if (preg_match($a = '#^' . preg_quote($GLOBALS['base_url'], '#') . '/(.+)$#', $url, $matches)) {
-
-
- if (!variable_get('clean_url', 0)) {
-
- $matches[1] = str_replace('?q=', '', $matches[1]);
- }
- if (preg_match($b = '#^node/([0-9]+)$#', drupal_get_normal_path($matches[1]), $matches2)) {
- return $matches2[1];
- }
- }
-
-
- return FALSE;
- }
-
-