'. t('The trackback module allows users to give a blog post a contextual link to another. A context is made because the trackbacking poster is, in theory, writing about something mentioned on another blogger\'s trackbacked post. Using the trackback URL accompanying each post, another website can send a ping to your website. Once received, the trackback will show up on the trackback page accompanying the post. It also includes auto-discovery, spam moderation queues, and the ability to manually ping another site.') .'
';
$output .= ''. t('If trackback autodisovery is enabled on your website, someone need only visit your post via a link from another website post to have trackback discover the linking site and create the trackback. Trackback auto-discovery also works internally within a website, automatically creating connections between pages which link to each other. To manually send a ping to another site, edit your post and use the trackback URL field at the bottom of the edit page to submit the trackback URL for the post on the other site. Once you enter submit, your website will ping the other site for you. With trackback autodiscovery enabled, your site will attempt to do this automatically without your intervention.') .'
';
$output .= ''. t('To enable the moderation queue, go to the administer trackbacks page and select the configure tab. To view, approve, or delete trackbacks awaiting moderation, go to the administer trackbacks page and select the approval queue. To administer the trackback settings for a particular content type go to that content types administration page.') .'
';
$output .= t('You can
';
$output .= ''. t('For more information please read the configuration and customization handbook Trackback page.', array('%trackback' => 'http://www.drupal.org/handbook/modules/trackback/')) .'
';
return $output;
case 'admin/modules#description':
return t("Allow for sending and receiving TrackBacks, which is a way for sites to notify another that they have commented on a post.");
}
}
function trackback_receive(&$node) {
$trackback = new stdClass();
// Process TrackBack post data.
$trackback->url = check_url($_REQUEST['url']);
if ($trackback->url && valid_url($_REQUEST['url'], TRUE)) {
$trackback->trid = db_next_id('{trackback_received}_trid');
$trackback->nid = $node->nid;
$trackback->created = time();
$trackback->site = $_SERVER['REMOTE_ADDR'];
$trackback->name = strip_tags(($_REQUEST['blog_name']) ? $_REQUEST['blog_name'] : $trackback->url);
$trackback->subject = strip_tags(($_REQUEST['title']) ? $_REQUEST['title'] : $trackback->url);
// $trackback->url already set above. Though I might say something here since I'm setting the fields
// in the exact same order that they are created in the table's create statement (with this exception).
$trackback->excerpt = (strlen($_REQUEST['excerpt'] > 255) ? truncate_utf8($_REQUEST['excerpt'], 252) .'...' : $_REQUEST['excerpt']);
$trackback->status = (variable_get('trackback_moderation', 0) == 0) ? 1 : 0;
// drop silently if this is from a known spammer IP address
if (function_exists('spam_ip_filter') && variable_get('trackback_spam_filter', 1)) {
module_invoke('spam', 'ip_filter', 'trackback', $trackback->trid);
}
if (module_exist('akismet')) {
$trackback->status = trackback_get_akismet_publish_status ( $trackback );
}
if (-1 == $trackback->status ) {
//don't store, wait
sleep(20);
_trackback_nice_watchdog ('ignore spam trackback', $trackback );
// If requested to, generate a delay so the spammer has to wait for a while.
if (($seconds = variable_get('akismet_antispambot_delay', 60)) > 0) {
sleep($seconds);
}
} else
{
// watchdog('trackback', t('trackback: added \'%subject\'', array('%subject' => $trackback->subject)), WATCHDOG_NOTICE, l(t('view trackback'), 'node/'. $node->nid .'#trackback-'. $trackback->trid));
_trackback_nice_watchdog ('added trackback', $trackback );
db_query("INSERT INTO {trackback_received} (trid, nid, created, site, name, subject, url, excerpt, status) VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', '%s', %d)", $trackback->trid, $trackback->nid, $trackback->created, $trackback->site, $trackback->name, $trackback->subject, $trackback->url, $trackback->excerpt, $trackback->status);
$error = 0;
if (function_exists('spam_content_filter') && variable_get('trackback_spam_filter', 1)) {
// invoke spam.module's spam filter
$subject = "$trackback->subject $trackback->url";
module_invoke('spam', 'content_filter', 'trackback', $trackback->trid, $subject, $trackback->excerpt);
}
}
}
else {
$error = 1;
$message = t('Missing TrackBack url.');
}
// Generate response
$output = "\n";
$output .= "\n";
$output .= ''. $error ."\n";
$message and $output .= ''. $message ."\n";
$output .= "\n";
return $output;
}
function theme_trackbacks($trackbacks) {
$output = ''."\n";
$output .= $trackbacks ."\n";
$output .= '
'."\n";
return $output;
}
function trackback_page($nid = null) {
if (is_numeric($nid) && ($node = node_load($nid)) && ($node->can_receive)) {
header("Content-Type: text/xml");
print trackback_receive($node);
}
else {
drupal_goto();
}
}
/**
* Modeled after theme_comment();
* Code was taken directly from there and then mutilated.
*
*/
function theme_trackback($trackback, $display_links = TRUE) {
$output = '\n";
$output .= '
\n";
$output .= '
'. t('from %sitename on %date', array('%sitename' => $trackback->name, '%date' => format_date($trackback->created))) ."
\n";
$output .= '
'. check_markup($trackback->excerpt) ."
\n";
if ($display_links && (user_access('administer trackbacks') || node_access('update', node_load($trackback->nid)))) {
$output .= '
';
$links = array();
$links[] = l(t('edit'), 'admin/trackback/edit/'. $trackback->trid);
$links[] = l(t('delete'), 'admin/trackback/delete/'. $trackback->trid);
if (module_exist('spam')) {
$links = array_merge($links, trackback_spam_link($trackback));
}
$output .= theme('links', $links);
$output .= "
\n";
}
$output .= "
\n";
return $output;
}
/**
* Menu callback; delete a trackback.
*/
function trackback_received_delete() {
$trid = arg(3);
$result = db_query('SELECT * FROM {trackback_received} WHERE trid = %d', $trid);
if ($trackback_received = db_fetch_object($result)) {
if (isset($_POST['op'])) {
db_query('DELETE FROM {trackback_received} WHERE trid = %d', $trid);
if (module_exist('spam')) {
db_query("DELETE FROM {spam_tracker} WHERE id = %d AND source = 'trackback'", $trid);
spam_log(SPAM_LOG, t('spam_delete_trackback: deleted trackback.'), 'trackback', $trid);
}
drupal_goto('node/'. $trackback_received->nid .'#trackbacks');
}
else {
return confirm_form('trackback_received_delete_confirm', array(),
t('Are you sure you want to delete the trackback %title?', array('%title' => $trackback_received->subject)),
'node/'. $trackback_received->nid,
t('This action cannot be undone.'),
t('Delete'), t('Cancel'));
}
}
else {
return t('The trackback you are trying to delete does not exist.');
}
}
function trackback_form_alter($form_id, &$form) {
if (isset($form['type']) && $form['type']['#value'] .'_node_settings' == $form_id) {
$type = $form['type']['#value'];
$default = ($type == 'story' || $type == 'blog' || $type == 'forum') ? 1 : 0;
$form['workflow']['trackback_'. $type] = array(
'#type' => 'radios',
'#title' => 'Trackbacks',
'#options' => array(1 => t('Enabled'), 0 => t('Disabled')),
'#return_value' => 1,
'#default_value' => variable_get('trackback_'. $type, $default),
'#description' => t('Enable trackbacks for this node type.')
);
}
else if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
$node = $form['#node'];
if (_trackback_valid_for_node_type($node)) {
$form['trackback'] = array(
'#type' => 'fieldset',
'#title' => t('Trackbacks'),
'#collapsible' => TRUE,
//'#collapsed' => TRUE
);
$form['trackback']['can_receive'] = array(
'#type' => 'checkbox',
'#title' => t('Allow Trackbacks'),
'#return_value' => 1,
'#default_value' => (isset($node->can_receive) ? $node->can_receive : TRUE),
'#description' => t('Allow other posts to send trackbacks to this content.')
);
$form['trackback']['trackback_urls'] = array(
'#type' => 'textarea',
'#title' => t('Send Trackbacks'),
'#default_value' => $node->trackback_urls,
'#cols' => 80,
'#rows' => 4,
'#description' => t('Enter one URL per line for each trackback you wish to send.')
);
// if there are any past successful trackbacks from this posting, add them to the node editing page.
// if there are any past unsuccessful trackbacks from this posting, add checkmarks to enable resending them
$past_successes_listing = array();
$options = array();
$result = db_query('SELECT url, successful FROM {trackback_sent} WHERE nid = %d', $node->nid);
while ($url = db_fetch_object($result)) {
if ($url->successful) {
$past_successes_listing[] = $url->url;
}
else {
$options[$url->url] = $url->url;
}
}
// add listing of successfully trackbacked URLs
if (count($past_successes_listing)) {
$form['trackback'][] = array(
'#type' => 'markup',
'#value' => theme('item_list', $past_successes_listing, t('Successful URLs'))
);
//t('These URLs have been successfuly pinged by this post.')
}
// add listing of unsuccessfully trackbacked URLs
if (count($options)) {
$form['trackback']['trackback_urls_to_retry'] = array(
'#type' => 'checkboxes',
'#title' => t('Unsuccessful URLs'),
'#default_value' => array(),
'#options' => $options,
'#description' => t('Attempts to ping these URLs with this post have failed. Mark a check next to the trackback URLs you wish to retry for this post.')
);
}
}
}
}
function trackback_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
global $trackback_node;
if ($op == 'load' || _trackback_valid_for_node_type($node)) {
switch ($op) {
case 'load':
$result = db_query('SELECT * FROM {trackback_received} WHERE nid = %d AND status = 1 ORDER BY created DESC', $node->nid);
$trackbacks_received = array();
while ($row = db_fetch_object($result)) {
$trackbacks_received[] = $row;
}
$values_array = array('trackbacks_received' => $trackbacks_received);
if ($node_data = db_fetch_object(db_query('SELECT * FROM {trackback_node} WHERE nid=%d', $node->nid))) {
$values_array['can_receive'] = $node_data->can_receive;
$values_array['awaiting_cron'] = $node_data->awaiting_cron;
}
else {
// if there isn't a row in the node table then we need to default to something sane
// such as when you first enable the module
$values_array['can_receive'] = _trackback_valid_for_node_type($node);
}
return $values_array;
case 'view':
if ($node->can_receive) {
$url = url('node/'. $node->nid, NULL, NULL, TRUE);
$tb_url = url('trackback/'. $node->nid, NULL, NULL, TRUE);
$autodetect_comments .= "\n\n";
}
if (!(($_POST['op'] == t('Preview') || ($_POST['op'] == t('Submit') && form_get_errors())))) {
if ($teaser && $node->can_receive) {
$node->teaser = $node->teaser . $autodetect_comments ."\n";
}
else {
if ($node->can_receive) {
$node->body .= $autodetect_comments ."\n";
$node->body .= theme('box', t('Trackback URL for this post:'), url('trackback/'. $node->nid, NULL, NULL, TRUE));
}
if ($node->can_receive && count($node->trackbacks_received)) {
foreach ($node->trackbacks_received as $tr) {
$trackbacks .= theme('trackback', $tr);
}
$node->body .= theme('trackbacks', $trackbacks);
}
}
}
break;
case 'validate':
$node->trackback_urls_array = explode("\n", $node->trackback_urls);
foreach ($node->trackback_urls_array as $id => $url) {
$node->trackback_urls_array[$id] = trim($url);
if ($node->trackback_urls_array[$id] != '' && !valid_url($node->trackback_urls_array[$id], TRUE)) {
form_set_error('trackback_urls', t('The trackback url %url is not a valid url.', array('%url' => $node->trackback_urls_array[$id] .'')));
}
}
break;
case 'insert':
case 'update':
$node->trackback_urls_array = explode("\n", $node->trackback_urls);
foreach ($node->trackback_urls_array as $id => $url) {
$node->trackback_urls_array[$id] = trim($url);
}
$trackback_node = $node;
}
}
}
function trackback_link($type, $node = NULL, $teaser = FALSE) {
$links = array();
if ($type == 'node' && $teaser && _trackback_valid_for_node_type($node) && $node->can_receive) {
$count = db_fetch_object(db_query('SELECT count(*) AS tbcount from {trackback_received} where nid = %d AND status = 1', $node->nid));
if ($count->tbcount) {
$links[] = l(format_plural($count->tbcount, '1 trackback', '%count trackbacks'), 'node/'. $node->nid .'#trackbacks');
}
}
return $links;
}
function trackback_menu($may_cache = FALSE) {
$items = array();
if ($may_cache) {
$access = user_access('administer trackbacks');
$items[] = array('path' => 'trackback', 'title' => t('trackbacks'),
'callback' => 'trackback_page', 'access' => user_access('access content'),
'type' => MENU_DYNAMIC);
$items[] = array('path' => 'admin/trackback', 'title' => t('trackbacks'),
'callback' => 'trackback_admin_overview', 'access' => $access);
$items[] = array('path' => 'admin/trackback/edit', 'title' => t('moderate trackback'),
'callback' => 'trackback_admin_edit', 'access' => $access,
'type' => MENU_CALLBACK
);
// Tabs:
$items[] = array('path' => 'admin/trackback/new', 'title' => t('new trackbacks'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/trackback/approval', 'title' => t('approval queue'),
'callback' => 'trackback_admin_overview', 'access' => $access,
'callback arguments' => 'approval',
'type' => MENU_LOCAL_TASK);
// Other stuff:
$items[] = array('path' => 'admin/settings/trackback', 'title' => t('trackback'),
'callback' => 'trackback_configure', 'access' => $access);
if (module_exist('spam')) {
$items[] = array('path' => 'admin/trackback/list/spam', 'title' => t('spam'),
'callback' => 'trackback_spam_admin_overview', 'access' => $access,
'type' => MENU_LOCAL_TASK, 'weight' => 10
);
}
}
else {
if (arg(0) == 'admin' && arg(1) == 'trackback' && arg(2) == 'delete' && is_numeric(arg(3))) {
$trackback = db_fetch_object(db_query('SELECT * FROM {trackback_received} WHERE trid=%d', arg(3)));
if (isset($trackback->nid)) {
$items[] = array('path' => 'admin/trackback/delete/'. arg(3), 'title' => t('delete trackback'), 'callback' => 'trackback_received_delete', 'access' => (user_access('administer trackbacks') || node_access('update', node_load($trackback->nid))), 'type' => MENU_CALLBACK);
}
}
}
return $items;
}
function trackback_perm() {
return array('administer trackbacks');
}
/**
* Menu callback; present an administrative trackback listing.
*/
function trackback_admin_overview($type = 'new') {
$spam_module_exists = module_exist('spam');
$operations = array();
if (module_exist('spam')) {
$operations['spam_spam_trackback'] = t('Mark the selected trackbacks as spam');
$operations['spam_notspam_trackback'] = t('Mark the selected trackbacks as not spam');
}
if ($type == 'new') {
$operations['spam_unpublish_trackback'] = t('Unpublish the selected trackbacks');
}
else {
$operations['spam_publish_trackback'] = t('Publish the selected trackbacks');
}
if (module_exist('spam')) {
$operations['spam_delete_trackback'] = t('Delete the selected trackbacks (via Spam, no confirmation)');
}
else {
$operations['norm_delete_trackback'] = t('Delete the selected trackbacks (no confirmation)');
}
if (module_exist('akismet')) {
$operations['akismet_check_trackback'] = t('Check/unpublish the selected trackbacks via Akismet, no confirmation)');
}
if (module_exist('akismet')) {
$operations['akismet_checkdel_trackback'] = t('Check/delete the selected trackbacks via Akismet, no confirmation)');
}
if ($op = $_POST['op']) {
$edit = $_POST['edit'];
if ($op == t('Update trackbacks') && isset($edit['operation']) && isset($edit['status']) && isset($operations[$edit['operation']])) {
$function = $edit['operation'];
foreach ($edit['status'] as $trid => $value) {
if ($value) {
$function($trid);
}
}
drupal_set_message(t('The update has been performed.'));
}
}
$status = ($type == 'approval') ? 0 : 1;
if ($spam_module_exists) {
$sql = 'SELECT tr.*, s.probability FROM {trackback_received} tr LEFT JOIN {spam_tracker} s ON tr.trid = s.id WHERE tr.status = '. db_escape_string($status);
}
else {
$sql = 'SELECT tr.* FROM {trackback_received} tr WHERE tr.status = '. db_escape_string($status);
}
$sql .= tablesort_sql(trackback_admin_table_header($spam_module_exists));
$result = pager_query($sql, 50);
$form = array();
$form['trackbacks'] = array('#theme' => 'trackback_admin_table');
$form['trackbacks']['spam_module_exists'] = array('#type' => 'value', '#value' => $spam_module_exists);
$form['trackbacks']['status'] = array('#tree' => TRUE);
while ($trackback = db_fetch_object($result)) {
$form['trackbacks']['status'][$trackback->trid] = array('#type' => 'checkbox');
$form['trackbacks'][$trackback->trid] = array();
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l($trackback->subject, $trackback->status ? 'node/'. $trackback->nid : 'admin/trackback/edit/'. $trackback->trid, array('title' => truncate_utf8($trackback->excerpt, 128)), NULL, $trackback->status ? 'trackback-'. $trackback->trid : NULL) .' '. theme('mark', node_mark($trackback->nid, $trackback->created)));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => theme('username', $trackback));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->site);
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->status != 0 ? t('Published') : t('Not published'));
if ($spam_module_exists) {
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->probability >= variable_get('spam_threshold', 80) ? t('Spam') : t('Not Spam'));
}
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => format_date($trackback->created, 'small'));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l(t('edit'), 'admin/trackback/edit/'. $trackback->trid));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l(t('delete'), 'admin/trackback/delete/'. $trackback->trid));
}
$form['checkall'] = array(
'#type' => 'fieldset',
'#title' => t('Check / uncheck all')
);
$form['checkall']['operation'] = array(
'#prefix' => '',
'#type' => 'checkbox',
'#attributes' => array('onclick' => 'checkUncheckAll(this);'),
'#default_value' => 0,
'#title' => t('Check / uncheck all items in the list')
);
$form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
$form['update'] = array(
'#type' => 'fieldset',
'#title' => t('Update options')
);
$form['update']['operation'] = array(
'#prefix' => '',
'#type' => 'select',
'#default_value' => 0,
'#options' => $operations
);
$form['update']['op'] = array(
'#type' => 'submit',
'#value' => t('Update trackbacks'),
'#suffix' => '
'
);
return drupal_get_form('trackback_admin_overview', $form);
}
function trackback_admin_table_header($spam_module_exists) {
$header = array();
$header[] = array('data' => '');
$header[] = array('data' => t('Subject'), 'field' => 'tr.subject');
$header[] = array('data' => t('Author'), 'field' => 'tr.name');
$header[] = array('data' => t('Host'), 'field' => 'tr.site');
$header[] = array('data' => t('Status'), 'field' => 'tr.status');
if ($spam_module_exists) {
$header[] = array('data' => t('Spam'), 'field' => 's.probability');
}
$header[] = array('data' => t('Time'), 'field' => 'created', 'sort' => 'desc');
$header[] = array('data' => t('Operations') , 'colspan' => '2');
return $header;
}
function theme_trackback_admin_table($form) {
$spam_module_exists = $form['spam_module_exists']['#value'];
$rows = array();
foreach (element_children($form['status']) as $key) {
$row = array(form_render($form['status'][$key]));
foreach (element_children($form[$key]) as $column_key) {
$row[] = $form[$key][$column_key]['#value'];
}
$rows[] = $row;
}
if (count($rows) == 0) {
$rows[] = array(array('data' => t('No trackbacks available.'), 'colspan' => ($spam_module_exists ? 8 : 7)));
}
return theme('table', trackback_admin_table_header($spam_module_exists), $rows);
}
function trackback_exit() {
global $trackback_node;
if ($trackback_node) {
//gather together data from node fields and format as a ping message
$edit = $_POST['edit'];
$params = array('title' => $trackback_node->title, 'excerpt' => truncate_utf8(strip_tags(check_markup($trackback_node->teaser, $trackback_node->format, FALSE)), 255), 'blog_name' => variable_get('site_name', ''), 'url' => url('node/'. $trackback_node->nid, NULL, NULL, 1) );
foreach ($params as $key => $value) {
$str[] = $key .'='. urlencode($value);
}
// Gather URLs to send pings to.
// First, group together the ping-urls entered by the user with the auto-detected ping-urls
if (!$trackback_node->trackback_urls_array) {
$trackback_node->trackback_urls_array = array();
}
if (variable_get('trackback_auto_detection_enabled', 0) == 1) {
$trackback_node->trackback_urls_array = array_unique(array_merge($trackback_node->trackback_urls_array, trackback_urls_via_nodebody($trackback_node)));
db_query('DELETE FROM {trackback_node} WHERE nid = %d', $trackback_node->nid);
db_query('INSERT INTO {trackback_node} (nid, awaiting_cron, can_receive) VALUES (%d, 0, %d)', $trackback_node->nid, $edit['can_receive']);
}
else {
if (variable_get('trackback_auto_detection_enabled', 0) == 2) {
//save auto-detection trackbacks for cron run later
$result = db_query('SELECT * FROM {trackback_node} WHERE nid=%d', $trackback_node->nid);
if ($tb_node_data = db_fetch_object($result)) {
db_query('UPDATE {trackback_node} SET awaiting_cron = 1, can_receive = %d WHERE nid = %d', $edit['can_receive'], $trackback_node->nid);
}
else {
db_query('INSERT INTO {trackback_node} (nid, awaiting_cron, can_receive) VALUES (%d, 0, %d)', $trackback_node->nid, $edit['can_receive']);
}
}
}
// From the group, take out URLs that have already been pinged.
$trackback_node->trackback_urls_array = array_flip($trackback_node->trackback_urls_array);
$result = db_query('SELECT url FROM {trackback_sent} WHERE nid = %d', $trackback_node->nid);
while ($already_tried_url = db_fetch_object($result)) {
unset($trackback_node->trackback_urls_array[$already_tried_url->url]);
}
$trackback_node->trackback_urls_array = array_flip($trackback_node->trackback_urls_array);
// add back into group the urls that were unsuccessfully pinged but selected for a retry by the user
$trackback_node->trackback_urls_array = array_unique(array_merge($trackback_node->trackback_urls_array, is_array($edit['trackback_urls_to_retry']) ? $edit['trackback_urls_to_retry'] : array()));
foreach ($trackback_node->trackback_urls_array as $url) {
if ($url != '') {
$http_reply = drupal_http_request($url, $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8'), 'POST', implode('&', $str));
if (db_result(db_query("SELECT nid, url FROM {trackback_sent} WHERE nid = %d AND url = '%s'", $trackback_node->nid, $url))) {
db_query("UPDATE {trackback_sent} SET nid = %d, url = '%s', successful = %d WHERE nid = %d AND url = '%s'", $trackback_node->nid, $url, $http_reply->error ? 0 : 1);
}
else {
db_query('INSERT INTO {trackback_sent} (nid, url, successful) VALUES (%d, \'%s\', %d)', $trackback_node->nid, $url, $http_reply->error ? 0 : 1);
}
}
}
$trackback_node = NULL;
}
}
function trackback_urls_via_nodebody($node) {
// First, grab anything that looks like a url from the body of the node.
$parsed_urls = array();
preg_match_all("/(http|https):\/\/[a-zA-Z0-9@:%_~#?&=.,\/;-]*[a-zA-Z0-9@:%_~#&=\/;-]/", $node->body, $parsed_urls);
$parsed_urls = array_unique($parsed_urls[0]);
// Now, send http HEAD requests so we can see if the content type is something that *might* contain
// autodetection text. In other words, check if Content-Type of each URL is text based rather than digital,
// and keep only those that are.
$tryable_urls = array();
foreach($parsed_urls as $url) {
if (_trackback_url_parsable_content($url)) {
$tryable_urls[] = $url;
}
}
//Finally, from the array of tryable urls, download each page, scan each, and compile
//a list of all the trackback URLs listed in the first RDF of each scanned page.
$trackback_urls_from_nodebody = array();
foreach ($tryable_urls as $url) {
$http_reply = drupal_http_request($url);
if (!$http_reply->error) {
$trackbackurl = preg_replace('/.*.*/s', '\1', $http_reply->data);
if ($trackbackurl && valid_url($trackbackurl, TRUE)) {
$trackback_urls_from_nodebody[] = $trackbackurl;
}
}
}
return array_unique($trackback_urls_from_nodebody);
}
// Since autodetection might encounter a link to a media file, we first want to make a
// simple 'HEAD' HTTP request instead of an actual GET. This results in having to make
// an extra drupal_http_request() later for an actual GET, but it is worth it considering
// the strong likelihood that auto-detection may encounter a URL that links to a media file.
function _trackback_url_parsable_content($url) {
global $base_url;
if (!strstr($url, $base_url)) {
$http_reply = drupal_http_request($url, array(), 'HEAD');
$content_type = $http_reply->headers['Content-Type'];
return (substr_count($content_type, 'text/html') || substr_count($content_type, 'application/xhtml+xml') || substr_count($content_type, 'application/xml') || substr_count($content_type, 'text/xml'));
}
}
function trackback_cron() {
// query for all nodes where
$result = db_query("SELECT t.nid FROM {trackback_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE t.awaiting_cron = 1 AND n.status = 1");
while($trackback_node_row = db_fetch_object($result)) {
// First things first, let's unset the 'awaiting_cron' bit in the {trackback_node} table.
db_query('UPDATE {trackback_node} SET awaiting_cron = 0 WHERE nid = %d', $trackback_node_row->nid);
$node = node_load($trackback_node_row->nid);
$urls = trackback_urls_via_nodebody($node);
foreach($urls as $url) {
// see if we've sent a trackback here already
$set = db_fetch_object(db_query('SELECT * FROM {trackback_sent} WHERE nid = %d AND url = \'%s\'', $node->nid, $url));
if(!$set) {
$params = array('title' => $node->title, 'excerpt' => truncate_utf8(strip_tags(check_markup($node->teaser, $node->format, FALSE)), 255), 'blog_name' => variable_get('site_name', ''), 'url' => url('node/'. $node->nid, NULL, NULL, 1) );
foreach ($params as $key => $value) {
$str[] = $key .'='. urlencode($value);
}
$http_reply = drupal_http_request($url, $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8'), 'POST', implode('&', $str));
db_query("DELETE FROM {trackback_sent} WHERE nid = %d AND url = '%s'", $node->nid, $url);
db_query('INSERT INTO {trackback_sent} (nid, url, successful) VALUES (%d, \'%s\', %d)', $node->nid, $url, $http_reply->error ? 0 : 1);
}
}
}
}
// Code that adds configurability for trackback features.
function _trackback_valid_for_node_type(&$node) {
return variable_get('trackback_'. $node->type, ($node->type == 'story' || $node->type == 'forum' || $node->type == 'blog') ? 1 : 0);
}
function trackback_configure() {
$form = array();
$form['trackback_auto_detection_enabled'] = array(
'#type' => 'radios',
'#title' => t('Auto-detection'),
'#default_value' => variable_get('trackback_auto_detection_enabled', 0),
'#options' => array(0 => t('Disable auto-detection'), 1 => t('Enable auto-detection'), 2 => t('Run auto-detection on cron')),
'#description' => t('If auto-detection is enabled, each URL in any posted content (whether in textile, link, or plain-text form) will be checked for a trackback URL upon submission. For each URL in the body of the posted content, trackback will check to see if that URL accepts trackbacks from other sites. If a URL accepts trackbacks, trackback will ping the trackback URL found on that page if one has been posted at that URL.
*note: This has the potential to take a very long time depending on the amount of links you have in your posts. Using the \'Run auto-detection on cron\' option delays the most time consuming part of the process to when cron is run on the site. This speeds perfomance when editing and creating content, but delays trackbacks until cron is run.')
);
$form['trackback_moderation'] = array(
'#type' => 'radios',
'#title' => t('Trackback moderation'),
'#default_value' => variable_get('trackback_moderation', 0),
'#options' => array(0 => t('Disable moderation for trackbacks sent to this site'), 1 => t('Enable moderation for trackbacks sent to this site')),
'#description' => t('Enabling moderation forces every received trackback to be approved before it will appear on your site. The moderation queue can then be viewed on the %linked_page.', array('%linked_page' => l(t('trackback administration page'), 'admin/trackback/list/approval')))
);
$form['trackbacks_display_number'] = array(
'#type' => 'select',
'#title' => t('Number of trackbacks to display'),
'#default_value' => variable_get('trackbacks_display_number', 10),
'#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
'#description' => t('How many trackbacks are displayed in the recent trackbacks block')
);
return system_settings_form('trackback_configure', $form);
}
function trackback_spam($op, $a2, $a3, $a4) {
$return = array();
switch ($op) {
case 'filter_settings':
$return['group']['trackback_spam_filter'] = array(
'#type' => 'checkbox',
'#title' => t('Filter trackbacks'),
'#return_value' => 1,
'#default_value' => variable_get('trackback_spam_filter', 1),
'#description' => t('Enable this option to filter new trackbacks as they are posted, determining whether or not they are spam.'));
break;
case 'page':
$trackback = trackback_load($a2);
$return['old'] = spam_load('trackback', $a2);
$return['header'] = "$trackback->subject $trackback->url";
$return['body'] = $trackback->excerpt;
$return['goto'] = "node/$trackback->nid/#trackbacks";
break;
}
return $return;
}
function trackback_delete($trackback) {
db_query('DELETE FROM {trackback_received} WHERE trid = %d', $trackback->trid);
if (module_exist('spam')) {
db_query("DELETE FROM {spam_tracker} WHERE id = %d AND source = 'trackback'", $trackback->trid);
spam_log(SPAM_LOG, t('spam_delete_trackback: deleted trackback "%subject".', array('%subject' => "$trackback->subject")), 'trackback', $trackback->trid);
}
_trackback_nice_watchdog ('deleted trackback', $trackback );
}
function trackback_admin_edit() {
// Trackback edits need to be saved.
if ($_POST['op'] == t('Submit')) {
$edit = $_POST['edit'];
db_query("UPDATE {trackback_received} SET status = %d WHERE trid = %d", $edit['status'], $edit['trid']);
if ($edit['status'] != $edit['status_old']) {
if ($edit['status']) {
drupal_set_message(t('The trackback is now published.'));
}
else {
drupal_set_message(t('The trackback was un-published'));
}
}
drupal_goto('admin/trackback');
}
// If we're not saving our changes above, we're editing it.
$trid = arg(3);
$result = db_query('SELECT tr.* FROM {trackback_received} tr WHERE trid = %d', $trid);
$trackback = db_fetch_object($result);
$form = array();
$form['status'] = array(
'#type' => 'radios',
'#title' => t('Status'),
'#default_value' => $trackback->status,
'#options' => array(1 => t('Published'), 0 => t('Not published'))
);
$form['trid'] = array(
'#type' => 'hidden',
'#value' => $trackback->trid
);
$form['status_old'] = array(
'#type' => 'hidden',
'#value' => $trackback->status
);
$form['op'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
$node = node_load($trackback->nid);
$node = t('This trackback is in response to: ') . theme('node', $node, TRUE, FALSE);
return theme('trackback', $trackback) . drupal_get_form('trackback_edit', $form) . $node;
}
function trackback_spam_admin_overview($type = 'new') {
$spam_module_exists = module_exist('spam');
$operations = array();
if (module_exist('spam')) {
$operations['spam_spam_trackback'] = t('Mark the selected trackbacks as spam');
$operations['spam_notspam_trackback'] = t('Mark the selected trackbacks as not spam');
}
$operations['spam_publish_trackback'] = t('Publish the selected trackbacks');
if (module_exist('spam')) {
$operations['spam_delete_trackback'] = t('Delete the selected trackbacks (no confirmation)');
}
else {
$operations['norm_delete_trackback'] = t('Delete the selected trackbacks (no confirmation)');
}
if ($op = $_POST['op']) {
$edit = $_POST['edit'];
if ($op == t('Update trackbacks') && isset($edit['operation']) && isset($edit['status']) && isset($operations[$edit['operation']])) {
$function = $edit['operation'];
foreach ($edit['status'] as $trid => $value) {
if ($value) {
$function($trid);
}
}
drupal_set_message(t('The update has been performed.'));
}
}
$status = ($type == 'approval') ? 0 : 1;
$sql = 'SELECT tr.*, s.probability FROM {trackback_received} tr LEFT JOIN {spam_tracker} s ON tr.trid = s.id WHERE s.source = \'trackback\' AND s.probability >= 80';
$sql .= tablesort_sql(trackback_admin_table_header($spam_module_exists));
$result = pager_query($sql, 50);
$form = array();
$form['trackbacks'] = array('#theme' => 'trackback_admin_table');
$form['trackbacks']['spam_module_exists'] = array('#type' => 'value', '#value' => $spam_module_exists);
$form['trackbacks']['status'] = array('#tree' => TRUE);
while ($trackback = db_fetch_object($result)) {
# $form['trackbacks']['status'] = array('#tree' => TRUE);
$form['trackbacks']['status'][$trackback->trid] = array('#type' => 'checkbox');
$form['trackbacks'][$trackback->trid] = array();
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l($trackback->subject, $trackback->status ? 'node/'. $trackback->nid : 'admin/trackback/edit/'. $trackback->trid, array('title' => truncate_utf8($trackback->excerpt, 128)), NULL, $trackback->status ? 'trackback-'. $trackback->trid : NULL) .' '. theme('mark', node_mark($trackback->nid, $trackback->created)));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => theme('username', $trackback));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->site);
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->status != 0 ? t('Published') : t('Not published'));
if ($spam_module_exists) {
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => $trackback->probability >= variable_get('spam_threshold', 80) ? t('Spam') : t('Not Spam'));
}
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => format_date($trackback->created, 'small'));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l(t('edit'), 'admin/trackback/edit/'. $trackback->trid));
$form['trackbacks'][$trackback->trid][] = array('#type' => 'value', '#value' => l(t('delete'), 'admin/trackback/delete/'. $trackback->trid));
}
$form['checkall'] = array(
'#type' => 'fieldset',
'#title' => t('Check / uncheck all')
);
$form['checkall']['operation'] = array(
'#prefix' => '',
'#type' => 'checkbox',
'#attributes' => array('onclick' => 'checkUncheckAll(this);'),
'#default_value' => 0,
'#title' => t('Check / uncheck all items in the list')
);
# $form[] = array('#type' => 'markup', '#value' => theme('pager', NULL, 50, 0));
$form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
$form['update'] = array(
'#type' => 'fieldset',
'#title' => t('Update options')
);
$form['update']['operation'] = array(
'#prefix' => '',
'#type' => 'select',
'#default_value' => 0,
'#options' => $operations
);
$form['update']['op'] = array(
'#type' => 'submit',
'#value' => t('Update trackbacks'),
'#suffix' => '
'
);
return drupal_get_form('trackback_admin_overview', $form);
}
function trackback_spam_link($trackback) {
$links = array();
$output = NULL;
if (variable_get('trackback_spam_filter', 1)) {
$p = db_fetch_object(db_query("SELECT probability FROM {spam_tracker} WHERE id = %d AND source = 'trackback'", $trackback->trid));
$spam = l(t('mark as spam'), "spam/trackback/$trackback->trid/spam");
$notspam = l(t('mark as not spam'), "spam/trackback/$trackback->trid/notspam");
}
else {
return $output;
}
$access = user_access('access spam');
$admin = user_access('administer spam');
$display = variable_get('spam_display_probability', 0);
if (variable_get('spam_log_level', SPAM_LOG)) {
$display_text = " (". l($p->probability, "admin/spam/logs/trackback/$trackback->trid") .")";
}
else {
$display_text = " ($p->probability)";
}
if (!$p->probability && $admin) {
$links[] = $spam .' - '. $notspam;
}
else if ($p->probability < variable_get('spam_threshold', 80)) {
if ($access) {
$output = t('not spam') . ($display ? $display_text : '');
}
if ($admin) {
if ($output)
$output .= ' - ';
$output .= $spam;
}
}
else {
if ($access) {
$output = t('spam') . ($display ? $display_text : '');
}
if ($admin) {
if ($output)
$output .= ' - ';
$output .= $notspam;
}
}
$links[] = $output;
return $links;
}
function trackback_block($op = 'list', $delta = 0) {
$num = variable_get('trackbacks_display_number', 10);
if ($op == 'list') {
$blocks[0]['info'] = t('Recent trackbacks received');
}
else {
$result = db_query_range('SELECT * FROM {trackback_received} WHERE status=1 ORDER BY created DESC', 0, $num);
$items = array();
while ($trackbacks = db_fetch_object($result)) {
$items[] = l(truncate_utf8(strip_tags($trackbacks->subject),27), 'node/'. $trackbacks->nid, NULL, NULL, 'trackback-'. $trackbacks->trid) .'
'. t('%time ago', array('%time' => format_interval(time() - $trackbacks->created)));
}
$blocks['subject'] = t('Recent trackbacks');
$blocks['content'] = theme('item_list', $items);
}
return $blocks;
}
/** spam module support functions **/
function trackback_load($trid) {
return (db_fetch_object(db_query('SELECT * FROM {trackback_received} WHERE trid=%d', $trid)));
}
function spam_publish_trackback($trid) {
$trackback = trackback_load($trid);
db_query('UPDATE {trackback_received} SET status = 1 WHERE trid = %d', $trackback->trid);
cache_clear_all();
_trackback_nice_watchdog ('published trackback', $trackback );
if (module_exist('spam')) {
spam_log(SPAM_LOG, t('spam_publish_trackback: published trackback "%subject".', array('%subject' => "$trackback->subject")), 'trackback', $trackback->trid);
}
}
function _trackback_nice_watchdog ( $operation, $trackback ) {
watchdog('trackback',
$operation.t(' %subj1 from %ipa %subject. The trackback spam was posted to %link by %ip.',
array(
'%subject' => l("$trackback->subject", "admin/trackback/edit/$trackback->trid" ),
'%link' => l(url('node/'. $trackback->nid, NULL, NULL, TRUE), 'node/'. $trackback->nid),
'%ip' => l( "$trackback->site", url('http://www.dnsstuff.com/tools/whois.ch?ip='. $trackback->site) ),
'%ipa' => $trackback->site,
'%subj1' => $trackback->subject
)
) , WATCHDOG_NOTICE,
l( " IPWHOIS ", url('http://www.dnsstuff.com/tools/whois.ch?ip='. $trackback->site) )
.
l(t(' view trackback'), "node/$trackback->nid", NULL,NULL, "trackback-$trackback->trid")
.
l(t(' edit trackback'), "admin/trackback/edit/$trackback->trid" )
);
}
function spam_unpublish_trackback($trid) {
$trackback = trackback_load($trid);
db_query('UPDATE {trackback_received} SET status = 0 WHERE trid = %d', $trackback->trid);
cache_clear_all();
_trackback_nice_watchdog ('unpublished trackback', $trackback );
if (module_exist('spam')) {
spam_log(SPAM_LOG, t('spam_unpublish_trackback: unpublished trackback "%subject".', array('%subject' => "$trackback->subject")), 'trackback', $trackback->trid);
}
}
function spam_delete_trackback($trid) {
if ($trackback = trackback_load($trid)) {
trackback_delete($trackback);
}
}
function norm_delete_trackback($trid) {
if ($trackback = trackback_load($trid)) {
trackback_delete($trackback);
}
}
function trackback_akismet_prepare_comment_data($content_type, $content) {
// Prepare data that is common to nodes/comments.
$comment_data = array(
// IP address of the comment submitter.
'user_ip' => (!empty($content->hostname) ? $content->hostname : $_SERVER['REMOTE_ADDR']),
// User agent information of the comment submitter.
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
// The content of the HTTP_REFERER header should be sent here.
'referrer' => $_SERVER['HTTP_REFERER'],
// May be blank, comment, trackback, pingback, or a made up value like "registration".
'comment_type' => '',
// Submitted name with the comment.
'comment_author' => $content->name,
);
// Prepare data that varies depending on type of content.
if ($content_type == 'trackback') {
$comment_data['permalink'] = url('node/'. $content->nid, NULL, 'trackback-'. $content->trid, TRUE);
$comment_data['comment_author_email'] = ''; //no mail in tracktrack?
$comment_data['comment_author_url'] = $content->url;
$comment_data['comment_content'] = $content->excerpt;
$comment_data['comment_type'] = 'trackback';
$comment_data['user_ip'] = $content->site;
}
return $comment_data;
}
function trackback_get_akismet_publish_status ($trackback) {
$akismet_api_result = akismet_api_cmd_comment_check(
trackback_akismet_prepare_comment_data ('trackback',$trackback)
);
//preset with unpublished
$trackback->status = 0;
if ($akismet_api_result == AKISMET_API_RESULT_IS_HAM) {
//future: akismet_notify_moderators('trackback', $trackback, ($trackback->status == 1 ? TRUE : FALSE), FALSE);
$trackback->status = 1;
}
if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) {
$trackback->status = -1;
variable_set('akismet_counter_spam', akismet_get_spam_counter() + 1);
//future: maybe even discard silently
}
if ($akismet_api_result == AKISMET_API_RESULT_ERROR) {
$trackback->status = 0;
}
return $trackback->status;
}
function akismet_check_trackback($trid) {
if ($trackback = trackback_load($trid)) {
$status = trackback_get_akismet_publish_status( $trackback );
if (1 == $status ) {
spam_publish_trackback ($trid);
}
else
spam_unpublish_trackback ($trid);
# drupal_set_message ( "Subject is : ".$trackback->subject );
# drupal_set_message ( "AKISMET result is : ".$status );
}
}
function akismet_checkdel_trackback($trid) {
if ($trackback = trackback_load($trid)) {
$status = trackback_get_akismet_publish_status( $trackback );
if (1 == $status ) {
spam_publish_trackback ($trid);
}
else
trackback_delete ($trackback);
# drupal_set_message ( "Subject is : ".$trackback->subject );
# drupal_set_message ( "AKISMET result is : ".$status );
}
}
function spam_notspam_trackback($trid) {
$trackback = trackback_load($trid);
$tokens = spam_tokenize("$trackback->subject $trackback->url", 'header*');
$tokens = array_merge($tokens, spam_tokenize($trackback->excerpt));
spam_tokens_unsave($tokens, 0);
spam_tokens_save($tokens, 0);
db_query("UPDATE {spam_tracker} SET probability = %d, timestamp = %d WHERE source = 'trackback' AND id = %d", 1, time(), $trackback->trid);
spam_default_actions('trackback', $trackback->trid, $trackback->subject, $trackback->excerpt, 1, NULL, FALSE);
watchdog('spam', t('Spam: marked trackback %subject as not spam.', array('%subject' => l("$trackback->subject", url("admin/trackback/edit/$trackback->trid")))), WATCHDOG_NOTICE, l(t('view trackback'), url($trackback->status ? "node/$trackback->nid/trackback-$trackback->trid" : "admin/trackback/edit/$trackback->trid")));
spam_log(SPAM_LOG, t('trackback manually marked as not spam'), 'trackback', $trackback->trid);
}
function spam_spam_trackback($trid) {
$trackback = trackback_load($trid);
$tokens = spam_tokenize("$trackback->subject $trackback->url", 'header*');
$tokens = array_merge($tokens, spam_tokenize($trackback->excerpt));
spam_tokens_unsave($tokens, 1);
spam_tokens_save($tokens, 1);
db_query("UPDATE {spam_tracker} SET probability = %d, timestamp = %d WHERE source = 'trackback' AND id = %d", 99, time(), $trackback->trid);
spam_default_actions('trackback', $trackback->trid, $trackback->subject, $trackback->excerpt, 99, NULL, FALSE);
watchdog('spam', t('Spam: marked trackback %subject as not spam.', array('%subject' => l("$trackback->subject", url("admin/trackback/edit/$trackback->trid")))), WATCHDOG_NOTICE, l(t('view trackback'), url($trackback->status ? "node/$trackback->nid/trackback-$trackback->trid" : "admin/trackback/edit/$trackback->trid")));
spam_log(SPAM_LOG, t('trackback manually marked as spam'), 'trackback', $trackback->trid);
}
/** end of spam module support functions */
?>