insertCode($tb_id); break; // Insert TrackBack URL case 'tburl': case 'url': echo $this->getTrackBackUrl($tb_id); break; // Insert manual ping URL case 'form': case 'manualpingformlink': echo $this->getManualPingUrl($tb_id); break; // Insert TrackBack count case 'count': $count = $this->getTrackBackCount($tb_id); switch ($count) { case 0: echo TEMPLATE::fill($this->getOption('tplTbNone'), array('number' => $count)); break; case 1: echo TEMPLATE::fill($this->getOption('tplTbOne'), array('number' => $count)); break; default: echo TEMPLATE::fill($this->getOption('tplTbMore'), array('number' => $count)); break; } break; // Shows the TrackBack list case 'list': case '': $this->showList($tb_id); break; default: return; } } /* * When used in templates, the tb_id will be determined by the itemid there */ function doTemplateVar(&$item, $what = '') { $this->doSkinVar('template', $what, $item->itemid); } /* * A trackback ping is to be received on the URL * http://yourdomain.com/item/1234.trackback * Extra variables to be passed along are url, title, excerpt, blog_name */ function event_InitSkinParse(&$data) { global $CONF, $itemid; $format = requestVar('format'); if ($CONF['URLMode'] == 'pathinfo') { if (preg_match('/(\/|\.)(trackback)(\/|$)/', serverVar('PATH_INFO'), $matches)) { $format = $matches[2]; } } if ($format == 'trackback' && $data['type'] == 'item') { $errorMsg = $this->handlePing($itemid); if ($errorMsg != '') $this->xmlResponse($errorMsg); else $this->xmlResponse(); exit; } } /* * A trackback ping is to be received on the URL * http://yourdomain.com/action.php?action=plugin&name=TrackBack&tb_id=1234 * Extra variables to be passed along are url, title, excerpt, blog_name */ function doAction($type) { global $CONF; switch ($type) { // When no action type is given, assume it's a ping case '': $errorMsg = $this->handlePing(); if ($errorMsg != '') $this->xmlResponse($errorMsg); else $this->xmlResponse(); break; // Manual ping case 'ping': $errorMsg = $this->handlePing(); if ($errorMsg != '') $this->showManualPingError(intRequestVar('tb_id'), $errorMsg); else $this->showManualPingSuccess(intRequestVar('tb_id')); break; // Show manual ping form case 'form': $this->showManualPingForm(intRequestVar('tb_id')); break; // Detect trackback case 'detect': list($url, $title) = $this->getURIfromLink(html_entity_decode(requestVar('tb_link'))); $url = addslashes($url); $url = $this->_utf8_to_javascript($url); $title = addslashes($title); $title = $this->_utf8_to_javascript($title); echo "tbDone('" . requestVar('tb_link') . "', '" . $url . "', '" . $title . "');"; break; } exit; } /************************************************************************************** * OUTPUT */ /* * Show a list of all trackbacks for this ID */ function showList($tb_id) { global $manager, $blog, $CONF; $res = mysql_query(' SELECT url, blog_name, excerpt, title, UNIX_TIMESTAMP(timestamp) AS timestamp FROM '.sql_table('plugin_tb').' WHERE tb_id = '.$tb_id .' AND block = 0 ORDER BY timestamp ASC '); $gVars = array( 'action' => $this->getTrackBackUrl($tb_id), 'form' => $this->getManualPingUrl($tb_id) ); echo TEMPLATE::fill($this->getOption('tplHeader'), $gVars); while ($row = mysql_fetch_array($res)) { $row['blog_name'] = htmlspecialchars($row['blog_name']); $row['title'] = htmlspecialchars($row['title']); $row['excerpt'] = htmlspecialchars($row['excerpt']); if (_CHARSET != 'UTF-8') { $row['blog_name'] = $this->_utf8_to_entities($row['blog_name']); $row['title'] = $this->_utf8_to_entities($row['title']); $row['excerpt'] = $this->_utf8_to_entities($row['excerpt']); } $iVars = array( 'action' => $this->getTrackBackUrl($tb_id), 'form' => $this->getManualPingUrl($tb_id), 'name' => $row['blog_name'], 'title' => $row['title'], 'excerpt' => $row['excerpt'], 'url' => htmlspecialchars($row['url'], ENT_QUOTES), 'date' => htmlspecialchars(strftime($this->getOption('dateFormat'), $row['timestamp'] + ($blog->getTimeOffset() * 3600)), ENT_QUOTES) ); echo TEMPLATE::fill($this->getOption('tplItem'), $iVars); } if (mysql_num_rows($res) == 0) { echo TEMPLATE::fill($this->getOption('tplEmpty'), $gVars); } echo TEMPLATE::fill($this->getOption('tplFooter'), $gVars); } /* * Returns the TrackBack count for a TrackBack item */ function getTrackBackCount($tb_id) { return quickQuery('SELECT COUNT(*) as result FROM ' . sql_table('plugin_tb') . ' WHERE tb_id='.$tb_id.' AND block = 0'); } /** * Returns the manual ping URL */ function getManualPingUrl($itemid) { global $CONF; return $CONF['ActionURL'] . '?action=plugin&name=TrackBack&type=form&tb_id='.$itemid; } /** * Show the manual ping form */ function showManualPingError($itemid, $status = '') { global $CONF; $form = true; $error = true; $success = false; sendContentType('text/html', 'admin-trackback', _CHARSET); include ($this->getDirectory() . '/templates/form.html'); } function showManualPingSuccess($itemid, $status = '') { global $CONF; $form = false; $error = false; $success = true; sendContentType('text/html', 'admin-trackback', _CHARSET); include ($this->getDirectory() . '/templates/form.html'); } function showManualPingForm($itemid, $text = '') { global $CONF; $form = true; $error = false; $success = false; // Check if we are allowed to accept pings if ($this->getOption('AcceptPing') == 'no') { $text = 'Sorry, no trackback pings are accepted'; $form = false; $error = true; } sendContentType('text/html', 'admin-trackback', _CHARSET); include ($this->getDirectory() . '/templates/form.html'); } /** * Returns the trackback URL */ function getTrackBackUrl($itemid) { global $CONF; return $CONF['ActionURL'] . '?action=plugin&name=TrackBack&tb_id='.$itemid; } /* * Insert RDF code for item */ function insertCode($itemid) { global $manager, $CONF; $item = & $manager->getItem($itemid, 0, 0); $blog = & $manager->getBlog(getBlogIDFromItemID($item['itemid'])); $CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL()); $uri = createItemLink($item['itemid'],''); $title = strip_tags($item['title']); $desc = strip_tags($item['body']); $desc = $this->_cut_string($desc, 200); $desc = htmlspecialchars($desc, ENT_QUOTES); ?> getItem($tb_id, 0, 0); if($item) { $blog =& $manager->getBlog(getBlogIDFromItemID($item['itemid'])); $blog_name = $blog->getName(); $title = $item['title']; $excerpt = $item['body']; if (_CHARSET != 'UTF-8') { $title = $this->_convert_to_utf8($title, $encoding); $excerpt = $this->_convert_to_utf8($excerpt, $encoding); $blog_name = $this->_convert_to_utf8($blog_name, $encoding); } $title = $this->_decode_entities(strip_tags($title)); $excerpt = $this->_decode_entities(strip_tags($excerpt)); $blog_name = $this->_decode_entities(strip_tags($blog_name)); $excerpt = $this->_cut_string($excerpt, 200); $CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL()); $url = createItemLink($item['itemid'],''); // Use UTF-8 charset for output header('Content-Type: text/xml'); echo "<","?xml version='1.0' encoding='UTF-8'?",">\n"; echo "\n"; echo "\t0\n"; echo "\t\n"; echo "\t\t\n"; echo "\t\t\t".htmlspecialchars($title)."\n"; echo "\t\t\t".htmlspecialchars($url)."\n"; echo "\t\t\t".htmlspecialchars($excerpt)."\n"; $query = 'SELECT url, blog_name, excerpt, title, UNIX_TIMESTAMP(timestamp) as timestamp FROM '.sql_table('plugin_tb').' WHERE tb_id='.$tb_id .' AND block = 0 ORDER BY timestamp DESC'; $res = mysql_query($query); while ($o = mysql_fetch_object($res)) { // No need to do conversion, because it is already UTF-8 $data = array ( 'url' => htmlspecialchars($o->url), 'blogname' => htmlspecialchars($o->blog_name), 'timestamp' => strftime('%Y-%m-%d',$o->timestamp), 'title' => htmlspecialchars($o->title), 'excerpt' => htmlspecialchars($o->excerpt), 'tburl' => $this->getTrackBackUrl($tb_id) ); echo "\n"; echo "\t\t\t\n"; echo "\t\t\t\t".$data['title']."\n"; echo "\t\t\t\t".$data['url']."\n"; echo "\t\t\t\t".$data['excerpt']."\n"; echo "\t\t\t\n"; } echo "\t\t\n"; echo "\t\n"; echo ""; exit; } else { $this->xmlResponse(_ERROR_NOSUCHITEM); } } /************************************************************************************** * SENDING AND RECEIVING TRACKBACK PINGS */ /* * Send a Trackback ping to another website */ function sendPing($itemid, $title, $url, $excerpt, $blog_name, $ping_url) { // 1. Check some basic things if (!$this->canSendPing()) { return 'You\'re not allowed to send pings'; } if ($this->getOption('SendPings') == 'no') { return 'Sending trackback pings is disabled'; } if ($ping_url == '') { return 'No ping URL'; } // 2. Check if protocol is correct http URL $parsed_url = parse_url($ping_url); if ($parsed_url['scheme'] != 'http' || $parsed_url['host'] == '') return 'Bad ping URL'; $port = ($parsed_url['port']) ? $parsed_url['port'] : 80; // 3. Create contents $content = 'title=' . urlencode( $title ); $content .= '&url=' . urlencode( $url ); $content .= '&excerpt=' . urlencode( $excerpt ); $content .= '&blog_name=' . urlencode( $blog_name ); $user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // 4. Prepare HTTP request $request = 'POST ' . $parsed_url['path']; if ($parsed_url['query'] != '') $request .= '?' . $parsed_url['query']; $request .= " HTTP/1.1\r\n"; $request .= "Accept: */*\r\n"; $request .= "User-Agent: " . $user_agent . "\r\n"; $request .= "Host: " . $parsed_url['host'] . ":" . $port . "\r\n"; $request .= "Connection: Keep-Alive\r\n"; $request .= "Cache-Control: no-cache\r\n"; $request .= "Connection: Close\r\n"; $request .= "Content-Length: " . strlen( $content ) . "\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded; charset="._CHARSET."\r\n"; $request .= "\r\n"; $request .= $content; $socket = fsockopen( $parsed_url['host'], $port, $errno, $errstr ); if ( ! $socket ) return 'Could not send ping: '.$errstr.' ('.$errno.')'; // 5. Execute HTTP request fputs($socket, $request); // 6. Receive response $result = ''; while (!feof($socket)) { $result .= fgets($socket, 4096); } fclose($socket); // instead of parsing the XML, just check for the error string // [TODO] extract real error message and return that if ( strstr($result,'1') ) return 'An error occurred: '.htmlspecialchars($result); } /* * Handle a Trackback ping sent to this website */ function handlePing($tb_id = 0) { global $manager; // Check if we are allowed to accept pings if ($this->getOption('AcceptPing') == 'no') { return 'Sorry, no trackback pings are accepted'; } // Defaults $spam = false; $link = false; $block = true; if ($tb_id == 0) $tb_id = intRequestVar('tb_id'); $rss = requestVar('__mode') == 'rss'; if (!$tb_id) { return 'TrackBack ID is missing (tb_id)'; } if ((!$manager->existsItem($tb_id,0,0)) && ($this->getOption('CheckIDs') == 'yes')) { return _NOSUCH_ITEM; } // 0. Check if we need to output the list as rss if ($rss) { $this->rssResponse($tb_id); return; } // 1. Get attributes $url = requestVar('url'); $title = requestVar('title'); $excerpt = requestVar('excerpt'); $blog_name = requestVar('blog_name'); if (!$url) { return 'URL is missing (url)'; } // 2. Conversion of encoding... if (preg_match ("/;\s*charset=([^\n]+)/is", $_SERVER["CONTENT_TYPE"], $regs)) $encoding = strtoupper(trim($regs[1])); else $encoding = $this->_detect_encoding($excerpt); $title = $this->_convert_to_utf8($title, $encoding); $excerpt = $this->_convert_to_utf8($excerpt, $encoding); $blog_name = $this->_convert_to_utf8($blog_name, $encoding); $title = $this->_decode_entities(strip_tags($title)); $excerpt = $this->_decode_entities(strip_tags($excerpt)); $blog_name = $this->_decode_entities(strip_tags($blog_name)); // 4. Save data in the DB $res = @mysql_query(' SELECT block FROM '.sql_table('plugin_tb').' WHERE url = "'.addslashes($url).'" AND tb_id = "'.$tb_id.'" '); if (mysql_num_rows($res) != 0) { // Existing TB, update it $row = mysql_fetch_row($res); $block = $row[0] == 1; $res = @mysql_query(' UPDATE '.sql_table('plugin_tb').' SET title = "'.addslashes($title).'", excerpt = "'.addslashes($excerpt).'", blog_name = "'.addslashes($blog_name).'", timestamp = '.mysqldate(time()).' WHERE url = "'.addslashes($url).'" AND tb_id = "'.$tb_id.'" '); if (!$res) { return 'Could not update trackback data: '.mysql_error(); } } else { // 4. SPAM check $spamcheck = array ( 'type' => 'trackback', 'id' => $tb_id, 'title' => $title, 'excerpt' => $excerpt, 'blogname' => $blog_name, 'url' => $url, 'return' => true, 'live' => true, /* Backwards compatibility with SpamCheck API 1*/ 'data' => $url . ' ' . $title . ' ' . $excerpt . ' ' . $blog_name, ); $manager->notify('SpamCheck', array ('spamcheck' => & $spamcheck)); if (isset($spamcheck['result']) && $spamcheck['result'] == true) { $spam = true; } // 5. Content check (TO DO) $contents = $this->retrieveUrl ($url); if (preg_match("/(".preg_quote($_SERVER["REQUEST_URI"], '/').")|(".preg_quote($_SERVER["SERVER_NAME"], '/').")/i", $contents)) { $link = true; } // 6. Determine if Trackback is safe... $block = $spam == true || $link == false; // New TB, insert it $query = ' INSERT INTO '.sql_table('plugin_tb').' SET tb_id = "'.$tb_id.'", block = "'.($block ? '1' : '0').'", spam = "'.($spam ? '1' : '0').'", link = "'.($link ? '1' : '0').'", url = "'.addslashes($url).'", title = "'.addslashes($title).'", excerpt = "'.addslashes($excerpt).'", blog_name = "'.addslashes($blog_name).'", timestamp = '.mysqldate(time()).' '; $res = @mysql_query($query); if (!$res) { return 'Could not save trackback data, possibly because of a double entry: ' . mysql_error() . $query; } } // 7. Send notification e-mail if needed if (($block == false || $this->getOption('NoNotifyBlocked') == 'no') && $this->getOption('Notify') == 'yes') { $destAddress = $this->getOption('NotifyEmail'); $vars = array ( 'tb_id' => $tb_id, 'url' => $url, 'title' => $title, 'excerpt' => $excerpt, 'blogname' => $blog_name ); $mailto_title = TEMPLATE::fill($this->notificationMailTitle, $vars); $mailto_msg = TEMPLATE::fill($this->notificationMail, $vars); global $CONF, $DIR_LIBS; // make sure notification class is loaded if (!class_exists('notification')) include($DIR_LIBS . 'NOTIFICATION.php'); $notify = new NOTIFICATION($destAddress); $notify->notify($mailto_title, $mailto_msg , $CONF['AdminEmail']); } return ''; } function xmlResponse($errorMessage = '') { header('Content-Type: text/xml'); echo "<","?xml version='1.0' encoding='UTF-8'?",">\n"; echo "\n"; if ($errorMessage) echo "\t1\n\t",htmlspecialchars($errorMessage),"\n"; else echo "\t0\n"; echo ""; exit; } /* * Check if member may send ping (check if logged in) */ function canSendPing() { global $member; return $member->isLoggedIn() || $this->xmlrpc; } /************************************************************************************** * EVENTS */ function event_SendTrackback($data) { global $manager; // Enable sending trackbacks for the XML-RPC API, otherwise we would // get an error because the current user is not exactly logged in. $this->xmlrpc = true; $itemid = $data['tb_id']; $item = &$manager->getItem($itemid, 0, 0); if (!$item) return; // don't ping for draft & future if ($item['draft']) return; // don't ping on draft items // gather some more information, needed to send the ping (blog name, etc) $blog =& $manager->getBlog(getBlogIDFromItemID($itemid)); $blog_name = $blog->getName(); $title = $data['title'] != '' ? $data['title'] : $item['title']; $title = strip_tags($title); $excerpt = $data['body'] != '' ? $data['body'] : $item['body']; $excerpt = strip_tags($excerpt); $excerpt = $this->_cut_string($excerpt, 200); $CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL()); $url = createItemLink($itemid); while (list(,$url) = each($data['urls'])) { $res = $this->sendPing($itemid, $title, $url, $excerpt, $blog_name, $url); if ($res) ACTIONLOG::add(WARNING, 'TrackBack Error:' . $res . ' (' . $url . ')'); } } function event_RetrieveTrackback($data) { $res = mysql_query(' SELECT url, title, UNIX_TIMESTAMP(timestamp) AS timestamp FROM '.sql_table('plugin_tb').' WHERE tb_id = '.$data['tb_id'].' AND block = 0 ORDER BY timestamp ASC '); while ($row = mysql_fetch_array($res)) { $trackback = array( 'title' => $row['title'], 'url' => $row['url'], 'ip' => '' ); $data['trackbacks'][] = $trackback; } } function event_BookmarkletExtraHead($data) { global $NP_TB_URL; list ($NP_TB_URL,) = $this->getURIfromLink(requestVar('loglink')); } function event_PrepareItemForEdit($data) { if (!$this->getOption('AutoXMLHttp')) { // The space between body and more is to make sure we didn't join 2 words accidently.... $this->larray = $this->autoDiscovery($data['item']['body'].' '.$data['item']['more']); } } /* * After an item has been added to the database, send out a ping if requested * (trackback_ping_url variable in request) */ function event_PostAddItem($data) { $this->pingTrackback($data); } function event_PreUpdateItem($data) { $this->pingTrackback($data); } /** * Add trackback options to add item form/bookmarklet */ function event_AddItemFormExtras($data) { global $NP_TB_URL; ?>

TrackBack


getOption('AutoXMLHttp')) { ?>

Auto Discovered Ping URL's:
jsautodiscovery(); } ?>

TrackBack


getOption('AutoXMLHttp')) { ?>

Auto Discovered Ping URL's:
jsautodiscovery(); } else { if (count($this->larray) > 0) { ?> Auto Discovered Ping URL's:
larray).'" />'; $i = 0; while (list($url, $title) = each ($this->larray)) { echo '
'; $i++; } } } ?>

getItem($itemid, 0, 0); if (!$item) return; // don't ping for draft & future if ($item['draft']) return; // don't ping on draft items // gather some more information, needed to send the ping (blog name, etc) $blog =& $manager->getBlog(getBlogIDFromItemID($itemid)); $blog_name = $blog->getName(); $title = $data['title'] != '' ? $data['title'] : $item['title']; $title = strip_tags($title); $excerpt = $data['body'] != '' ? $data['body'] : $item['body']; $excerpt = strip_tags($excerpt); $excerpt = $this->_cut_string($excerpt, 200); $CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL()); $url = createItemLink($itemid); // send the ping(s) (add errors to actionlog) for ($i=0; $isendPing($itemid, $title, $url, $excerpt, $blog_name, $ping_urls[$i]); if ($res) ACTIONLOG::add(WARNING, 'TrackBack Error:' . $res . ' (' . $ping_urls[$i] . ')'); } } /************************************************************************************** * AUTO-DISCOVERY */ /* * Auto-Discovery of TrackBack Ping URLs based on HTML story */ function autoDiscovery($text) { $links = $this->getPermaLinksFromText($text); $result = array(); for ($i = 0; $i < count($links); $i++) { list ($url, $title) = $this->getURIfromLink($links[$i]); if ($url != '') $result[$url] = $title; } return $result; } /* * Auto-Discovery of TrackBack Ping URLs based on single link */ function getURIfromLink($link) { // Check to see if the cache contains this link $res = mysql_query('SELECT url, title FROM '.sql_table('plugin_tb_lookup').' WHERE link="'.$link.'"'); if ($row = mysql_fetch_array($res)) { if ($row['title'] != '') { return array ( $row['url'], $row['title'] ); } else { return array ( $row['url'], $row['url'] ); } } // Retrieve RDF if (($rdf = $this->getRDFFromLink($link)) !== false) { // Get PING attribute if (($uri = $this->getAttributeFromRDF($rdf, 'trackback:ping')) !== false) { // Get TITLE attribute if (($title = $this->getAttributeFromRDF($rdf, 'dc:title')) !== false) { // Get CREATOR attribute if (($author = $this->getAttributeFromRDF($rdf, 'dc:creator')) !== false) { $title = $author. ": " . $title; } $uri = $this->_decode_entities($uri); $title = $this->_decode_entities($title); // Store in cache $res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','".addslashes($uri)."','".addslashes($title)."')"); return array ( $uri, $title ); } else { $uri = html_entity_decode($uri, ENT_COMPAT); // Store in cache $res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','".addslashes($uri)."','')"); return array ( $uri, $uri ); } } } // Store in cache $res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','','')"); return array ('', ''); } /* * Detect links used in HTML code */ function getPermaLinksFromText($text) { $links = array(); if (preg_match_all('/]+)>/', $text, $array, PREG_SET_ORDER)) { for ($i = 0; $i < count($array); $i++) { preg_match('/href="http:\/\/(.+)"/', $array[$i][1], $matches); $links['http://'.$matches[1]] = 1; } } return array_keys($links); } /* * Retrieve RDF code from external link */ function getRDFFromLink($link) { if ($content = $this->getContents($link)) { preg_match_all('/()/sm', $content, $rdfs, PREG_SET_ORDER); if (count($rdfs) > 1) { for ($i = 0; $i < count($rdfs); $i++) { if (preg_match('|dc:identifier="'.preg_quote($link).'"|ms',$rdfs[$i][1])) { return $rdfs[$i][1]; } } } else { // No need to check the identifier return $rdfs[0][1]; } } return false; } /** * Retrieve the contents of an external (X)HTML document */ function getContents($link) { // Use cURL extention if available if (function_exists("curl_init")) { // Make HEAD request $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $link); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers = curl_exec($ch); curl_close($ch); // Check if the link points to a (X)HTML document if (preg_match('/Content-Type: (text\/html|application\/xhtml+xml)/i', $headers)) { return $this->retrieveUrl ($link); } return false; } else { return $this->retrieveUrl ($link); } } /* * Get a single attribute from RDF */ function getAttributeFromRDF($rdf, $attribute) { if (preg_match('/'.$attribute.'="([^"]+)"/', $rdf, $matches)) { return $matches[1]; } return false; } /**************************************************************************************/ /* Internal helper functions for dealing with external file retrieval */ function retrieveUrl ($url) { if (function_exists('curl_init')) { // Set options $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 20); // Retrieve response $raw = curl_exec($ch); $info = curl_getinfo($ch); // Split into headers and contents $headers = substr($raw, 0, $info['header_size']); $contents = substr($raw, $info['header_size']); curl_close($ch); } elseif ($fp = @fopen ($url, "r")) { $contents = fread($fp, 8192); $headers = ''; fclose($fp); } // Next normalize the encoding to UTF8... $contents = $this->_convert_to_utf8_auto($contents, $headers); return $contents; } /**************************************************************************************/ /* Internal helper functions for dealing with encodings and entities */ var $entities_cp1251 = array ( '€' => '€', '‚' => '‚', 'ƒ' => 'ƒ', '„' => '„', '…' => '…', '†' => '†', '‡' => '‡', 'ˆ' => 'ˆ', '‰' => '‰', 'Š' => 'Š', '‹' => '‹', 'Œ' => 'Œ', 'Ž' => 'Ž', '‘' => '‘', '’' => '’', '“' => '“', '”' => '”', '•' => '•', '–' => '–', '—' => '—', '˜' => '˜', '™' => '™', 'š' => 'š', '›' => '›', 'œ' => 'œ', 'ž' => 'ž', 'Ÿ' => 'Ÿ', ); var $entities_default = array ( '"' => '"', '&' => '&', ''' => ''', '<' => '<', '>' => '>', ); var $entities_latin = array ( ' ' => ' ', '¡' => '¡', '¢' => '¢', '£' => '£', '¤' => '¤', '¥' => '¥', '¦' => '¦', '§' => '§', '¨' => '¨', '©' => '©', 'ª' => 'ª', '«' => '«', '¬' => '¬', '­' => '­', '®' => '®', '¯' => '¯', '°' => '°', '±' => '±', '²' => '²', '³' => '³', '´' => '´', 'µ' => 'µ', '¶' => '¶', '·' => '·', '¸' => '¸', '¹' => '¹', 'º' => 'º', '»' => '»', '¼' => '¼', '½' => '½', '¾' => '¾', '¿' => '¿', 'À' => 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ð' => 'Ð', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', '×' => '×', 'Ø' => 'Ø', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'Þ' => 'Þ', 'ß' => 'ß', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'æ' => 'æ', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ð' => 'ð', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', '÷' => '÷', 'ø' => 'ø', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'þ' => 'þ', 'ÿ' => 'ÿ', ); var $entities_extended = array ( 'Œ' => 'Œ', 'œ' => 'å', 'Š' => 'Š', 'š' => 'š', 'Ÿ' => 'Ÿ', 'ˆ' => 'ˆ', '˜' => '˜', '&esnp;' => ' ', ' ' => ' ', ' ' => ' ', '‌' => '‌', '‍' => '‍', '‎' => '‎', '‏' => '‏', '–' => '–', '—' => '—', '‘' => '‘', '’' => '’', '‚' => '‚', '“' => '“', '”' => '”', '„' => '„', '†' => '†', '‡' => '‡', '‰' => '‰', '‹' => '‹', '›' => '›', '€' => '€', 'ƒ' => 'ƒ', 'Α' => 'Α', 'Β' => 'Β', 'Γ' => 'Γ', 'Δ' => 'Δ', 'Ε' => 'Ε', 'Ζ' => 'Ζ', 'Η' => 'Η', 'Θ' => 'Θ', 'Ι' => 'Ι', 'Κ' => 'Κ', 'Λ' => 'Λ', 'Μ' => 'Μ', 'Ν' => 'Ν', 'Ξ' => 'Ξ', 'Ο' => 'Ο', 'Π' => 'Π', 'Ρ' => 'Ρ', 'Σ' => 'Σ', 'Τ' => 'Τ', 'Υ' => 'Υ', 'Φ' => 'Φ', 'Χ' => 'Χ', 'Ψ' => 'Ψ', 'Ω' => 'Ω', 'α' => 'α', 'β' => 'β', 'γ' => 'γ', 'δ' => 'δ', 'ε' => 'ε', 'ζ' => 'ζ', 'η' => 'η', 'θ' => 'θ', 'ι' => 'ι', 'κ' => 'κ', 'λ' => 'λ', 'μ' => 'μ', 'ν' => 'ν', 'ξ' => 'ξ', 'ο' => 'ο', 'π' => 'π', 'ρ' => 'ρ', 'ς' => 'ς', 'σ' => 'σ', 'τ' => 'τ', 'υ' => 'υ', 'φ' => 'φ', 'χ' => 'χ', 'ψ' => 'ψ', 'ω' => 'ω', 'ϑ' => 'ϑ', 'ϒ' => 'ϒ', 'ϖ' => 'ϖ', '•' => '•', '…' => '…', '′' => '′', '″' => '″', '‾' => '‾', '⁄' => '⁄', '℘' => '℘', 'ℑ' => 'ℑ', 'ℜ' => 'ℜ', '™' => '™', 'ℵ' => 'ℵ', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '↔' => '↔', '↵' => '↵', '⇐' => '⇐', '⇑' => '⇑', '⇒' => '⇒', '⇓' => '⇓', '⇔' => '⇔', '∀' => '∀', '∂' => '∂', '∃' => '∃', '∅' => '∅', '∇' => '∇', '∈' => '∈', '∉' => '∉', '∋' => '∋', '∏' => '∏', '∑' => '∑', '−' => '−', '∗' => '∗', '√' => '√', '∝' => '∝', '∞' => '∞', '∠' => '∠', '∧' => '∧', '∨' => '∨', '∩' => '∩', '∪' => '∪', '∫' => '∫', '∴' => '∴', '∼' => '∼', '≅' => '≅', '≈' => '≈', '≠' => '≠', '≡' => '≡', '≤' => '≤', '≥' => '≥', '⊂' => '⊂', '⊃' => '⊃', '⊄' => '⊄', '⊆' => '⊆', '⊇' => '⊇', '⊕' => '⊕', '⊗' => '⊗', '⊥' => '⊥', '⋅' => '⋅', '⌈' => '⌈', '⌉' => '⌉', '⌊' => '⌊', '⌋' => '⌋', '⟨' => '〈', '⟩' => '〉', '◊' => '◊', '♠' => '♠', '♣' => '♣', '♥' => '♥', '♦' => '♦', ); function _detect_encoding($string) { if (!ereg("[\x80-\xFF]", $string) && !ereg("\x1B", $string)) return 'US-ASCII'; if (!ereg("[\x80-\xFF]", $string) && ereg("\x1B", $string)) return 'ISO-2022-JP'; if (preg_match("/^([\x01-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF][\x80-\xBF])+$/", $string) == 1) return 'UTF-8'; if (preg_match("/^([\x01-\x7F]|\x8E[\xA0-\xDF]|\x8F[xA1-\xFE][\xA1-\xFE]|[\xA1-\xFE][\xA1-\xFE])+$/", $string) == 1) return 'EUC-JP'; if (preg_match("/^([\x01-\x7F]|[\xA0-\xDF]|[\x81-\xFC][\x40-\xFC])+$/", $string) == 1) return 'Shift_JIS'; return 'ISO-8859-1'; } function _convert_to_utf8($contents, $encoding) { $done = false; if (!$done && function_exists('iconv')) { $result = @iconv($encoding, 'UTF-8//IGNORE', $contents); if ($result) { $contents = $result; $done = true; } } if(!$done && function_exists('mb_convert_encoding')) { @mb_substitute_character('none'); $result = @mb_convert_encoding($contents, 'UTF-8', $encoding ); if ($result) { $contents = $result; } } return $contents; } function _convert_to_utf8_auto($contents, $headers = '') { /* IN: string in unknown encoding, headers received during transfer * OUT: string in UTF-8 encoding */ $str = substr($contents, 0, 4096); $len = strlen($str); $pos = 0; $out = ''; while ($pos < $len) { $ord = ord($str[$pos]); if ($ord > 32 && $ord < 128) $out .= $str[$pos]; $pos++; } // Detection of encoding, check headers if (preg_match ("/;\s*charset=([^\n]+)/is", $headers, $regs)) $encoding = strtoupper(trim($regs[1])); // Then check meta inside document if (preg_match ("/;\s*charset=([^\"']+)/is", $out, $regs)) $encoding = strtoupper(trim($regs[1])); // Then check xml declaration if (preg_match("/<\?xml.+encoding\s*=\s*[\"|']([^\"']+)[\"|']\s*\?>/i", $out, $regs)) $encoding = strtoupper(trim($regs[1])); // Converts return $this->_convert_to_utf8($contents, $encoding); } function _decode_entities($string) { /* IN: string in UTF-8 containing entities * OUT: string in UTF-8 without entities */ /// Convert all hexadecimal entities to decimal entities $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', "'&#'.hexdec('\\1').';'", $string); // Deal with invalid cp1251 numeric entities $string = strtr($string, $this->entities_cp1251); // Convert all named entities to numeric entities $string = strtr($string, $this->entities_default); $string = strtr($string, $this->entities_latin); $string = strtr($string, $this->entities_extended); // Convert all numeric entities to UTF-8 $string = preg_replace('/&#([0-9]+);/e', "'&#x'.dechex('\\1').';'", $string); $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', "NP_Trackback::_hex_to_utf8('\\1')", $string); return $string; } function _hex_to_utf8($s) { /* IN: string containing one hexadecimal Unicode character * OUT: string containing one binary UTF-8 character */ $c = hexdec($s); if ($c < 0x80) { $str = chr($c); } else if ($c < 0x800) { $str = chr(0xC0 | $c>>6) . chr(0x80 | $c & 0x3F); } else if ($c < 0x10000) { $str = chr(0xE0 | $c>>12) . chr(0x80 | $c>>6 & 0x3F) . chr(0x80 | $c & 0x3F); } else if ($c < 0x200000) { $str = chr(0xF0 | $c>>18) . chr(0x80 | $c>>12 & 0x3F) . chr(0x80 | $c>>6 & 0x3F) . chr(0x80 | $c & 0x3F); } return $str; } function _utf8_to_entities($string) { /* IN: string in UTF-8 encoding * OUT: string consisting of only characters ranging from 0x00 to 0x7f, * using numeric entities to represent the other characters */ $len = strlen ($string); $pos = 0; $out = ''; while ($pos < $len) { $ascii = ord (substr ($string, $pos, 1)); if ($ascii >= 0xF0) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xF0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80; $byte[4] = ord(substr ($string, $pos + 3, 1)) - 0x80; $char_code = ($byte[1] << 18) + ($byte[2] << 12) + ($byte[3] << 6) + $byte[4]; $pos += 4; } elseif (($ascii >= 0xE0) && ($ascii < 0xF0)) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xE0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80; $char_code = ($byte[1] << 12) + ($byte[2] << 6) + $byte[3]; $pos += 3; } elseif (($ascii >= 0xC0) && ($ascii < 0xE0)) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xC0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $char_code = ($byte[1] << 6) + $byte[2]; $pos += 2; } else { $char_code = ord(substr ($string, $pos, 1)); $pos += 1; } if ($char_code < 0x80) $out .= chr($char_code); else $out .= '&#'. str_pad($char_code, 5, '0', STR_PAD_LEFT) . ';'; } return $out; } function _utf8_to_javascript($string) { /* IN: string in UTF-8 encoding * OUT: string consisting of only characters ranging from 0x00 to 0x7f, * using javascript escapes to represent the other characters */ $len = strlen ($string); $pos = 0; $out = ''; while ($pos < $len) { $ascii = ord (substr ($string, $pos, 1)); if ($ascii >= 0xF0) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xF0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80; $byte[4] = ord(substr ($string, $pos + 3, 1)) - 0x80; $char_code = ($byte[1] << 18) + ($byte[2] << 12) + ($byte[3] << 6) + $byte[4]; $pos += 4; } elseif (($ascii >= 0xE0) && ($ascii < 0xF0)) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xE0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80; $char_code = ($byte[1] << 12) + ($byte[2] << 6) + $byte[3]; $pos += 3; } elseif (($ascii >= 0xC0) && ($ascii < 0xE0)) { $byte[1] = ord(substr ($string, $pos, 1)) - 0xC0; $byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80; $char_code = ($byte[1] << 6) + $byte[2]; $pos += 2; } else { $char_code = ord(substr ($string, $pos, 1)); $pos += 1; } if ($char_code < 0x80) $out .= chr($char_code); else $out .= '\\u'. str_pad(dechex($char_code), 4, '0', STR_PAD_LEFT); } return $out; } function _cut_string($string, $dl = 0) { $defaultLength = $dl > 0 ? $dl : $this->getOption('defaultLength'); if ($defaultLength < 1) return $string; $border = 6; $count = 0; $lastvalue = 0; for ($i = 0; $i < strlen($string); $i++) { $value = ord($string[$i]); if ($value > 127) { if ($value >= 192 && $value <= 223) $i++; elseif ($value >= 224 && $value <= 239) $i = $i + 2; elseif ($value >= 240 && $value <= 247) $i = $i + 3; if ($lastvalue <= 223 && $value >= 223 && $count >= $defaultLength - $border) { return substr($string, 0, $i) . '...'; } // Chinese and Japanese characters are // wider than Latin characters if ($value >= 224) $count++; } elseif ($string[$i] == '/' || $string[$i] == '?' || $string[$i] == '-' || $string[$i] == ':' || $string[$i] == ',' || $string[$i] == ';') { if ($count >= $defaultLength - $border) return substr($string, 0, $i) . '...'; } elseif ($string[$i] == ' ') { if ($count >= $defaultLength - $border) return substr($string, 0, $i) . '...'; } if ($count == $defaultLength) return substr($string, 0, $i + 1) . '...'; $lastvalue = $value; $count++; } return $string; } /**************************************************************************************/ /* Plugin API calls, for installation, configuration and setup */ function getName() { return 'TrackBack'; } function getAuthor() { return 'rakaz'; } function getURL() { return 'http://www.rakaz.nl/'; } function getVersion() { return '2.0.3'; } function getDescription() { return 'Send trackbacks to other weblogs and receive tracbacks from others.'; } function getTableList() { return array(sql_table("plugin_tb"), sql_table("plugin_tb_lookup")); } function getEventList() { return array('QuickMenu','PostAddItem','AddItemFormExtras','EditItemFormExtras','PreUpdateItem','PrepareItemForEdit', 'BookmarkletExtraHead', 'RetrieveTrackback', 'SendTrackback', 'InitSkinParse'); } function getMinNucleusVersion() { return 200; } function supportsFeature($feature) { switch($feature) { case 'SqlTablePrefix': return 1; case 'HelpPage': return 1; default: return 0; } } function hasAdminArea() { return 1; } function event_QuickMenu(&$data) { global $member, $nucleus, $blogid; // only show to admins if (!$member->isLoggedIn() || !$member->isAdmin()) return; array_push( $data['options'], array( 'title' => 'Trackback', 'url' => $this->getAdminURL(), 'tooltip' => 'Manage your trackbacks' ) ); } function install() { $this->createOption('AcceptPing', 'Accept pings','yesno','yes'); $this->createOption('SendPings', 'Allow sending pings','yesno','yes'); $this->createOption('AutoXMLHttp', 'Auto-detect Trackback URLs as you type', 'yesno', 'yes'); $this->createOption('CheckIDs', 'Only allow valid itemids as trackback-ids','yesno','yes'); $this->createOption('tplHeader', 'Header', 'textarea', "
\n\t
Trackback
\n\n"); $this->createOption('tplEmpty', 'Empty', 'textarea', "\t
\n\t\tThere are currently no trackbacks for this item.\n\t
\n\n"); $this->createOption('tplItem', 'Item', 'textarea', "\t
\n\t\t
<%name%>
\n\t\t
\n\t\t\t<%title%>: <%excerpt%>\n\t\t
\n\t\t
\n\t\t\t<%date%>\n\t\t
\n\t
\n\n"); $this->createOption('tplFooter', 'Footer', 'textarea', "\t
\n\t\tUse this TrackBack url to ping this item (right-click, copy link target).\n\t\tIf your blog does not support Trackbacks you can manually add your trackback by using this form.\n\t
\n
"); $this->createOption('tplTbNone', 'Trackback count (none)', 'text', "No Trackbacks"); $this->createOption('tplTbOne', 'Trackback count (one)', 'text', "1 Trackback"); $this->createOption('tplTbMore', 'Trackback count (more)', 'text', "<%number%> Trackbacks"); $this->createOption('dateFormat', 'Date format', 'text', "%e/%m/%g"); $this->createOption('Notify', 'Send e-mail notification on ping receipt','yesno','no'); $this->createOption('NoNotifyBlocked', 'Don'."'".'t send e-mail notification for blocked pings','yesno','no'); $this->createOption('NotifyEmail', 'Which e-mail address to send these notification to?','text',''); $this->createOption('DropTable', 'Clear the database when uninstalling','yesno','no'); /* Create tables */ mysql_query(" CREATE TABLE IF NOT EXISTS ".sql_table('plugin_tb')." ( `id` INT(11) NOT NULL AUTO_INCREMENT, `tb_id` INT(11) NOT NULL, `url` TEXT NOT NULL, `block` TINYINT(4) NOT NULL, `spam` TINYINT(4) NOT NULL, `link` TINYINT(4) NOT NULL, `title` TEXT, `excerpt` TEXT, `blog_name` TEXT, `timestamp` DATETIME, PRIMARY KEY (`id`) ) "); mysql_query(" CREATE TABLE IF NOT EXISTS ".sql_table('plugin_tb_lookup')." ( `link` TEXT NOT NULL, `url` TEXT NOT NULL, `title` TEXT, PRIMARY KEY (`link` (100)) ) "); } function uninstall() { if ($this->getOption('DropTable') == 'yes') { mysql_query ('DROP TABLE '.sql_table('plugin_tb')); mysql_query ('DROP TABLE '.sql_table('plugin_tb_lookup')); } } function init() { $this->notificationMail = "Your weblog received a new trackback from <%blogname%> for ID <%tb_id%>. Below are the full details:\n\nURL:\t<%url%>\nTitle:\t<%title%>\nExcerpt:\t<%excerpt%>\nBlogname:\t<%blogname%>"; $this->notificationMailTitle = "New Trackback received for ID <%tb_id%>"; } } ?>