CodeIgniter installed
[living-lab-site.git] / system / libraries / Trackback.php
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
new file mode 100755 (executable)
index 0000000..b0a7678
--- /dev/null
@@ -0,0 +1,548 @@
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package            CodeIgniter
+ * @author             ExpressionEngine Dev Team
+ * @copyright  Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license            http://codeigniter.com/user_guide/license.html
+ * @link               http://codeigniter.com
+ * @since              Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Trackback Class
+ *
+ * Trackback Sending/Receiving Class
+ *
+ * @package            CodeIgniter
+ * @subpackage Libraries
+ * @category   Trackbacks
+ * @author             ExpressionEngine Dev Team
+ * @link               http://codeigniter.com/user_guide/libraries/trackback.html
+ */
+class CI_Trackback {
+
+       var $time_format        = 'local';
+       var $charset            = 'UTF-8';
+       var $data                       = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => '');
+       var $convert_ascii      = TRUE;
+       var $response           = '';
+       var $error_msg          = array();
+
+       /**
+        * Constructor
+        *
+        * @access      public
+        */
+       public function __construct()
+       {
+               log_message('debug', "Trackback Class Initialized");
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Send Trackback
+        *
+        * @access      public
+        * @param       array
+        * @return      bool
+        */
+       function send($tb_data)
+       {
+               if ( ! is_array($tb_data))
+               {
+                       $this->set_error('The send() method must be passed an array');
+                       return FALSE;
+               }
+
+               // Pre-process the Trackback Data
+               foreach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item)
+               {
+                       if ( ! isset($tb_data[$item]))
+                       {
+                               $this->set_error('Required item missing: '.$item);
+                               return FALSE;
+                       }
+
+                       switch ($item)
+                       {
+                               case 'ping_url' : $$item = $this->extract_urls($tb_data[$item]);
+                                       break;
+                               case 'excerpt'  : $$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));
+                                       break;
+                               case 'url'              : $$item = str_replace('&#45;', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));
+                                       break;
+                               default                 : $$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item])));
+                                       break;
+                       }
+
+                       // Convert High ASCII Characters
+                       if ($this->convert_ascii == TRUE)
+                       {
+                               if ($item == 'excerpt')
+                               {
+                                       $$item = $this->convert_ascii($$item);
+                               }
+                               elseif ($item == 'title')
+                               {
+                                       $$item = $this->convert_ascii($$item);
+                               }
+                               elseif ($item == 'blog_name')
+                               {
+                                       $$item = $this->convert_ascii($$item);
+                               }
+                       }
+               }
+
+               // Build the Trackback data string
+               $charset = ( ! isset($tb_data['charset'])) ? $this->charset : $tb_data['charset'];
+
+               $data = "url=".rawurlencode($url)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($blog_name)."&excerpt=".rawurlencode($excerpt)."&charset=".rawurlencode($charset);
+
+               // Send Trackback(s)
+               $return = TRUE;
+               if (count($ping_url) > 0)
+               {
+                       foreach ($ping_url as $url)
+                       {
+                               if ($this->process($url, $data) == FALSE)
+                               {
+                                       $return = FALSE;
+                               }
+                       }
+               }
+
+               return $return;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Receive Trackback  Data
+        *
+        * This function simply validates the incoming TB data.
+        * It returns FALSE on failure and TRUE on success.
+        * If the data is valid it is set to the $this->data array
+        * so that it can be inserted into a database.
+        *
+        * @access      public
+        * @return      bool
+        */
+       function receive()
+       {
+               foreach (array('url', 'title', 'blog_name', 'excerpt') as $val)
+               {
+                       if ( ! isset($_POST[$val]) OR $_POST[$val] == '')
+                       {
+                               $this->set_error('The following required POST variable is missing: '.$val);
+                               return FALSE;
+                       }
+
+                       $this->data['charset'] = ( ! isset($_POST['charset'])) ? 'auto' : strtoupper(trim($_POST['charset']));
+
+                       if ($val != 'url' && function_exists('mb_convert_encoding'))
+                       {
+                               $_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']);
+                       }
+
+                       $_POST[$val] = ($val != 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);
+
+                       if ($val == 'excerpt')
+                       {
+                               $_POST['excerpt'] = $this->limit_characters($_POST['excerpt']);
+                       }
+
+                       $this->data[$val] = $_POST[$val];
+               }
+
+               return TRUE;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Send Trackback Error Message
+        *
+        * Allows custom errors to be set.  By default it
+        * sends the "incomplete information" error, as that's
+        * the most common one.
+        *
+        * @access      public
+        * @param       string
+        * @return      void
+        */
+       function send_error($message = 'Incomplete Information')
+       {
+               echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>";
+               exit;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Send Trackback Success Message
+        *
+        * This should be called when a trackback has been
+        * successfully received and inserted.
+        *
+        * @access      public
+        * @return      void
+        */
+       function send_success()
+       {
+               echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>0</error>\n</response>";
+               exit;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Fetch a particular item
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function data($item)
+       {
+               return ( ! isset($this->data[$item])) ? '' : $this->data[$item];
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Process Trackback
+        *
+        * Opens a socket connection and passes the data to
+        * the server.  Returns TRUE on success, FALSE on failure
+        *
+        * @access      public
+        * @param       string
+        * @param       string
+        * @return      bool
+        */
+       function process($url, $data)
+       {
+               $target = parse_url($url);
+
+               // Open the socket
+               if ( ! $fp = @fsockopen($target['host'], 80))
+               {
+                       $this->set_error('Invalid Connection: '.$url);
+                       return FALSE;
+               }
+
+               // Build the path
+               $ppath = ( ! isset($target['path'])) ? $url : $target['path'];
+
+               $path = (isset($target['query']) && $target['query'] != "") ? $ppath.'?'.$target['query'] : $ppath;
+
+               // Add the Trackback ID to the data string
+               if ($id = $this->get_id($url))
+               {
+                       $data = "tb_id=".$id."&".$data;
+               }
+
+               // Transfer the data
+               fputs ($fp, "POST " . $path . " HTTP/1.0\r\n" );
+               fputs ($fp, "Host: " . $target['host'] . "\r\n" );
+               fputs ($fp, "Content-type: application/x-www-form-urlencoded\r\n" );
+               fputs ($fp, "Content-length: " . strlen($data) . "\r\n" );
+               fputs ($fp, "Connection: close\r\n\r\n" );
+               fputs ($fp, $data);
+
+               // Was it successful?
+               $this->response = "";
+
+               while ( ! feof($fp))
+               {
+                       $this->response .= fgets($fp, 128);
+               }
+               @fclose($fp);
+
+
+               if (stristr($this->response, '<error>0</error>') === FALSE)
+               {
+                       $message = 'An unknown error was encountered';
+
+                       if (preg_match("/<message>(.*?)<\/message>/is", $this->response, $match))
+                       {
+                               $message = trim($match['1']);
+                       }
+
+                       $this->set_error($message);
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Extract Trackback URLs
+        *
+        * This function lets multiple trackbacks be sent.
+        * It takes a string of URLs (separated by comma or
+        * space) and puts each URL into an array
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function extract_urls($urls)
+       {
+               // Remove the pesky white space and replace with a comma.
+               $urls = preg_replace("/\s*(\S+)\s*/", "\\1,", $urls);
+
+               // If they use commas get rid of the doubles.
+               $urls = str_replace(",,", ",", $urls);
+
+               // Remove any comma that might be at the end
+               if (substr($urls, -1) == ",")
+               {
+                       $urls = substr($urls, 0, -1);
+               }
+
+               // Break into an array via commas
+               $urls = preg_split('/[,]/', $urls);
+
+               // Removes duplicates
+               $urls = array_unique($urls);
+
+               array_walk($urls, array($this, 'validate_url'));
+
+               return $urls;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Validate URL
+        *
+        * Simply adds "http://" if missing
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function validate_url($url)
+       {
+               $url = trim($url);
+
+               if (substr($url, 0, 4) != "http")
+               {
+                       $url = "http://".$url;
+               }
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Find the Trackback URL's ID
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function get_id($url)
+       {
+               $tb_id = "";
+
+               if (strpos($url, '?') !== FALSE)
+               {
+                       $tb_array = explode('/', $url);
+                       $tb_end   = $tb_array[count($tb_array)-1];
+
+                       if ( ! is_numeric($tb_end))
+                       {
+                               $tb_end  = $tb_array[count($tb_array)-2];
+                       }
+
+                       $tb_array = explode('=', $tb_end);
+                       $tb_id  = $tb_array[count($tb_array)-1];
+               }
+               else
+               {
+                       $url = rtrim($url, '/');
+
+                       $tb_array = explode('/', $url);
+                       $tb_id  = $tb_array[count($tb_array)-1];
+
+                       if ( ! is_numeric($tb_id))
+                       {
+                               $tb_id  = $tb_array[count($tb_array)-2];
+                       }
+               }
+
+               if ( ! preg_match ("/^([0-9]+)$/", $tb_id))
+               {
+                       return FALSE;
+               }
+               else
+               {
+                       return $tb_id;
+               }
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Convert Reserved XML characters to Entities
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function convert_xml($str)
+       {
+               $temp = '__TEMP_AMPERSANDS__';
+
+               $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str);
+               $str = preg_replace("/&(\w+);/",  "$temp\\1;", $str);
+
+               $str = str_replace(array("&","<",">","\"", "'", "-"),
+                                                       array("&amp;", "&lt;", "&gt;", "&quot;", "&#39;", "&#45;"),
+                                                       $str);
+
+               $str = preg_replace("/$temp(\d+);/","&#\\1;",$str);
+               $str = preg_replace("/$temp(\w+);/","&\\1;", $str);
+
+               return $str;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Character limiter
+        *
+        * Limits the string based on the character count. Will preserve complete words.
+        *
+        * @access      public
+        * @param       string
+        * @param       integer
+        * @param       string
+        * @return      string
+        */
+       function limit_characters($str, $n = 500, $end_char = '&#8230;')
+       {
+               if (strlen($str) < $n)
+               {
+                       return $str;
+               }
+
+               $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
+
+               if (strlen($str) <= $n)
+               {
+                       return $str;
+               }
+
+               $out = "";
+               foreach (explode(' ', trim($str)) as $val)
+               {
+                       $out .= $val.' ';
+                       if (strlen($out) >= $n)
+                       {
+                               return trim($out).$end_char;
+                       }
+               }
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * High ASCII to Entities
+        *
+        * Converts Hight ascii text and MS Word special chars
+        * to character entities
+        *
+        * @access      public
+        * @param       string
+        * @return      string
+        */
+       function convert_ascii($str)
+       {
+               $count  = 1;
+               $out    = '';
+               $temp   = array();
+
+               for ($i = 0, $s = strlen($str); $i < $s; $i++)
+               {
+                       $ordinal = ord($str[$i]);
+
+                       if ($ordinal < 128)
+                       {
+                               $out .= $str[$i];
+                       }
+                       else
+                       {
+                               if (count($temp) == 0)
+                               {
+                                       $count = ($ordinal < 224) ? 2 : 3;
+                               }
+
+                               $temp[] = $ordinal;
+
+                               if (count($temp) == $count)
+                               {
+                                       $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64);
+
+                                       $out .= '&#'.$number.';';
+                                       $count = 1;
+                                       $temp = array();
+                               }
+                       }
+               }
+
+               return $out;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Set error message
+        *
+        * @access      public
+        * @param       string
+        * @return      void
+        */
+       function set_error($msg)
+       {
+               log_message('error', $msg);
+               $this->error_msg[] = $msg;
+       }
+
+       // --------------------------------------------------------------------
+
+       /**
+        * Show error messages
+        *
+        * @access      public
+        * @param       string
+        * @param       string
+        * @return      string
+        */
+       function display_errors($open = '<p>', $close = '</p>')
+       {
+               $str = '';
+               foreach ($this->error_msg as $val)
+               {
+                       $str .= $open.$val.$close;
+               }
+
+               return $str;
+       }
+
+}
+// END Trackback Class
+
+/* End of file Trackback.php */
+/* Location: ./system/libraries/Trackback.php */
\ No newline at end of file