Exemple #1
0
 /**
  * Load and parse RSS file
  *
  * @global string $CONFIG['TIMEZONE']
  * @param string $rss_url
  * @param int $timestamp unix timestamp
  * @return array|false
  */
 private function parse($rss_url, $timestamp = null)
 {
     // Sanity check
     if (!filter_var($rss_url, FILTER_VALIDATE_URL)) {
         return false;
     }
     $timestamp = filter_var($timestamp, FILTER_VALIDATE_INT);
     // --------------------------------------------------------------------
     // Extablish Conditional GET
     // --------------------------------------------------------------------
     $modified = null;
     $opts = array();
     if ($timestamp) {
         date_default_timezone_set('GMT');
         $modified = date('D, d M Y H:i:s', $timestamp) . ' GMT';
         date_default_timezone_set($GLOBALS['CONFIG']['TIMEZONE']);
     }
     if ($modified) {
         // file_get_contents() compatible headers for Conditional GET
         $opts = array('http' => array('header' => "If-Modified-Since: {$modified}\r\n"));
     }
     // --------------------------------------------------------------------
     // Backtrack_limit is too restrictive for complex feeds, boost it
     // --------------------------------------------------------------------
     ini_set('pcre.backtrack_limit', 999999);
     // --------------------------------------------------------------------
     // Parse
     // --------------------------------------------------------------------
     if (ini_get('allow_url_fopen')) {
         // file_get_contents
         ini_set('default_socket_timeout', 30);
         $ctx = stream_context_create($opts);
         $rss_content = @file_get_contents($rss_url, null, $ctx);
     } elseif (function_exists('curl_init')) {
         // cURL
         $ch = curl_init();
         if ($modified) {
             curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['http']['header']);
         }
         curl_setopt($ch, CURLOPT_URL, $rss_url);
         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         $rss_content = curl_exec($ch);
         curl_close($ch);
     } else {
         throw new Exception('No way to retrieve RSS feeds');
     }
     if ($rss_content) {
         // Parse document encoding
         $result['encoding'] = $this->myPregMatch("'encoding=[\\'\"](.*?)[\\'\"]'si", $rss_content);
         if ($result['encoding'] != '') {
             // if document codepage is specified, use it
             // This is used in myPregMatch()
             $this->rsscp = $result['encoding'];
         } else {
             // otherwise use UTF-8
             // This is used in myPregMatch()
             $this->rsscp = 'UTF-8';
         }
         // ---------------------------------------------------------------
         // Parse CHANNEL info
         // ---------------------------------------------------------------
         // Init some variables
         $is_atom = false;
         $out_channel = array();
         preg_match("'<channel.*?>(.*?)</channel>'si", $rss_content, $out_channel);
         if (!count($out_channel)) {
             // Maybe this is an Atom feed? Parse FEED info
             preg_match("'<feed.*?>(.*?)</feed>'si", $rss_content, $out_channel);
             if (count($out_channel)) {
                 $is_atom = true;
             } else {
                 return false;
             }
             // This isn't an RSS/Atom feed, abort
         }
         foreach ($this->channeltags as $channeltag) {
             if ($is_atom && isset($this->channeltags_atom[$channeltag])) {
                 // Atom specific tag
                 if (is_array($this->channeltags_atom[$channeltag])) {
                     foreach ($this->channeltags_atom[$channeltag] as $tmp_tag) {
                         $temp = $this->myPregMatch("'<{$tmp_tag}.*?>(.*?)</{$tmp_tag}>'si", @$out_channel[1]);
                         if (!empty($temp)) {
                             break;
                         }
                     }
                 } else {
                     $temp = $this->myPregMatch("'<{$this->channeltags_atom[$channeltag]}.*?>(.*?)</{$this->channeltags_atom[$channeltag]}>'si", @$out_channel[1]);
                 }
             } else {
                 if ($is_atom && $channeltag == 'link') {
                     // Yet more Atom tom-fuckery
                     $temp = $this->myPregMatch('#<link[\\s]+[^>]*?href[\\s]?=[\\s"\']+(.*?)["\']+.*?/>#si', @$out_channel[1]);
                 } else {
                     // RSS compatible channel tag
                     $temp = $this->myPregMatch("'<{$channeltag}.*?>(.*?)</{$channeltag}>'si", @$out_channel[1]);
                 }
             }
             if (!empty($temp)) {
                 $result[$channeltag] = $temp;
             }
             // Set only if not empty
         }
         // If date_format is specified and lastBuildDate is valid
         if ($this->date_format != '' && isset($result['lastBuildDate']) && ($timestamp = strtotime($result['lastBuildDate'])) !== -1) {
             // convert lastBuildDate to specified date format
             $result['lastBuildDate'] = date($this->date_format, $timestamp);
         }
         // ---------------------------------------------------------------
         // Parse TEXTINPUT info
         // ---------------------------------------------------------------
         $out_textinfo = array();
         preg_match("'<textinput(|[^>]*[^/])>(.*?)</textinput>'si", $rss_content, $out_textinfo);
         // This a little strange regexp means:
         // Look for tag <textinput> with or without any attributes, but skip truncated version <textinput /> (it's not beggining tag)
         if (isset($out_textinfo[2])) {
             foreach ($this->textinputtags as $textinputtag) {
                 $temp = $this->myPregMatch("'<{$textinputtag}.*?>(.*?)</{$textinputtag}>'si", $out_textinfo[2]);
                 if (!empty($temp)) {
                     $result['textinput_' . $textinputtag] = $temp;
                 }
                 // Set only if not empty
             }
         }
         // ---------------------------------------------------------------
         // Parse IMAGE info
         // ---------------------------------------------------------------
         $out_imageinfo = array();
         preg_match("'<image.*?>(.*?)</image>'si", $rss_content, $out_imageinfo);
         if (isset($out_imageinfo[1])) {
             foreach ($this->imagetags as $imagetag) {
                 $temp = $this->myPregMatch("'<{$imagetag}.*?>(.*?)</{$imagetag}>'si", $out_imageinfo[1]);
                 if (!empty($temp)) {
                     $result['image_' . $imagetag] = $temp;
                 }
                 // Set only if not empty
             }
         }
         // ---------------------------------------------------------------
         // Parse ITEMS
         // ---------------------------------------------------------------
         $items = array();
         if ($is_atom) {
             preg_match_all("'<entry(| .*?)>(.*?)</entry>'si", $rss_content, $items);
         } else {
             preg_match_all("'<item(| .*?)>(.*?)</item>'si", $rss_content, $items);
         }
         // RSS
         $rss_items = $items[2];
         $i = 0;
         $result['items'] = array();
         // create array even if there are no items
         foreach ($rss_items as $rss_item) {
             if ($i < $this->items_limit || $this->items_limit == 0) {
                 // ---------------------------------------------------------------
                 // Go through each $itemtags and collect the data
                 // ---------------------------------------------------------------
                 foreach ($this->itemtags as $itemtag) {
                     if ($itemtag == 'category') {
                         $tmp_funct = 'myPregMatchAll';
                     } else {
                         $tmp_funct = 'myPregMatch';
                     }
                     if ($is_atom && isset($this->itemtags_atom[$itemtag])) {
                         // Atom specific tag
                         if (is_array($this->itemtags_atom[$itemtag])) {
                             foreach ($this->itemtags_atom[$itemtag] as $tmp_tag) {
                                 $temp = $this->{$tmp_funct}("'<{$tmp_tag}.*?>(.*?)</{$tmp_tag}>'si", $rss_item);
                                 if (!empty($temp)) {
                                     break;
                                 }
                             }
                         } else {
                             $temp = $this->{$tmp_funct}("'<{$this->itemtags_atom[$itemtag]}.*?>(.*?)</{$this->itemtags_atom[$itemtag]}>'si", $rss_item);
                         }
                     } else {
                         if ($is_atom && $itemtag == 'link') {
                             // Yet more Atom tom-fuckery
                             $temp = $this->{$tmp_funct}('#<link[\\s]+[^>]*?href[\\s]?=[\\s"\']+(.*?)["\']+.*?/>#si', $rss_item);
                         } else {
                             // RSS compatible item tag
                             $temp = $this->{$tmp_funct}("'<{$itemtag}.*?>(.*?)</{$itemtag}>'si", $rss_item);
                         }
                     }
                     // Check if link is valid
                     if ($itemtag == 'link' && !suxFunct::canonicalizeUrl($temp)) {
                         // Seriously? An invalid URL? And I'm supposed to care?
                         // Why do I feel like this is some sort abusive dad pushing
                         // their kids to play hockey against their wishes thing?
                         $pattern = '#<.*?xml:base[\\s]?=[\\s"\']+(.*?)["\']+#i';
                         $out_baseurl = array();
                         // Attempt 1) Look for xml:base in this node
                         preg_match($pattern, $rss_item, $out_baseurl);
                         if (!isset($out_baseurl[1]) || !suxFunct::canonicalizeUrl($out_baseurl[1])) {
                             // Attempt 2) Look for xml:base anywhere, starting from the begining of the document
                             preg_match($pattern, $rss_content, $out_baseurl);
                             if (!isset($out_baseurl[1]) || !suxFunct::canonicalizeUrl($out_baseurl[1])) {
                                 // Attempt 3) Look for the channel <link> and see if that's a real url
                                 if (isset($result['link']) && suxFunct::canonicalizeUrl($result['link'])) {
                                     $out_baseurl[1] = $result['link'];
                                 }
                             }
                         }
                         if (isset($out_baseurl[1])) {
                             $temp = trim($temp);
                             $temp = trim($temp, '/');
                             $temp2 = parse_url($out_baseurl[1]);
                             if (isset($temp2['port'])) {
                                 $temp2 = "{$temp2['scheme']}://{$temp['host']}:{$temp2['port']}";
                             } else {
                                 $temp2 = "{$temp2['scheme']}://{$temp2['host']}";
                             }
                             $temp = "{$temp2}/{$temp}";
                             $temp = suxFunct::canonicalizeUrl($temp);
                         }
                     }
                     // Stack it
                     if (!empty($temp)) {
                         $result['items'][$i][$itemtag] = $temp;
                     }
                 }
                 // ---------------------------------------------------------------
                 // Make some adjustments
                 // ---------------------------------------------------------------
                 // If date_format is specified and pubDate is valid
                 if ($this->date_format != '' && isset($result['items'][$i]['pubDate']) && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !== -1) {
                     // convert pubDate to specified date format
                     $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp);
                 } else {
                     unset($result['items'][$i]['pubDate']);
                 }
                 // Item counter
                 $i++;
             }
         }
         // Don't trust data from external website, sanitize everything
         array_walk_recursive($result, array($this, 'sanitizeByReference'));
         $result['items_count'] = $i;
         // new dBug($result);
         // exit;
         return $result;
     } else {
         // Error in opening return False
         return false;
     }
 }
 /**
  * for suxValidate, check if a duplicate openid url exists
  *
  * @return bool
  */
 function isDuplicateOpenIDUrl($value, $empty, &$params, &$formvars)
 {
     if (empty($formvars['url'])) {
         return false;
     }
     $user = $this->user->getUserByOpenID(suxFunct::canonicalizeUrl($formvars['url']));
     if ($user) {
         return false;
     } else {
         return true;
     }
 }
Exemple #3
0
 /**
  * trust a url
  * @param int $id user id
  * @param string $id url
  * @return bool
  */
 private function trustUrl($id, $url)
 {
     if (!filter_var($id, FILTER_VALIDATE_INT) || $id < 1) {
         return false;
     }
     $url = suxFunct::canonicalizeUrl($url);
     $trusted = array('users_id' => $id, 'auth_url' => $url);
     $query = suxDB::prepareCountQuery($this->db_table_trust, $trusted);
     $st = $this->db->prepare($query);
     $st->execute($trusted);
     if (!$st->fetchColumn()) {
         $query = suxDB::prepareInsertQuery($this->db_table_trust, $trusted);
         $st = $this->db->prepare($query);
         $st->execute($trusted);
     }
 }
Exemple #4
0
 /**
  * Constructor
  *
  * @param string $key PDO dsn key
  */
 function __construct($id)
 {
     // Declare objects
     $this->msg = new suxThreadedMessages();
     $this->bookmarks = new suxBookmarks();
     $this->r = new blogRenderer($this->module);
     // Renderer
     suxValidate::register_object('this', $this);
     // Register self to validator
     parent::__construct();
     // Let the parent do the rest
     // Declare properties
     $this->id = $id;
     $this->msg->setPublished(null);
     $this->bookmarks->setPublished(null);
     // If feature is turned off, then redirect
     if ($GLOBALS['CONFIG']['FEATURE']['auto_bookmark'] == false) {
         suxFunct::redirect(suxFunct::getPreviousURL());
     }
     // Redirect if not logged in
     if (empty($_SESSION['users_id'])) {
         suxFunct::redirect(suxFunct::makeUrl('/user/register'));
     }
     // --------------------------------------------------------------------
     // Scan post for href links
     // --------------------------------------------------------------------
     $msg = $this->msg->getByID($id);
     if (!$msg) {
         suxFunct::redirect(suxFunct::getPreviousURL());
     }
     // No message, skip
     if ($msg['users_id'] != $_SESSION['users_id']) {
         suxFunct::redirect(suxFunct::getPreviousURL());
     }
     // Not the user's message, skip
     $matches = array();
     $pattern = '#<a[\\s]+[^>]*?href[\\s]?=[\\s"\']+(.*?)["\']+.*?>([^<]+|.*?)?</a>#si';
     // href pattern
     preg_match_all($pattern, $msg['body_html'], $matches);
     $count = count($matches[1]);
     if (!$count) {
         suxFunct::redirect(suxFunct::getPreviousURL());
     }
     //  No links, skip
     // Limit the amount of time we wait for a connection to a remote server to 5 seconds
     ini_set('default_socket_timeout', 5);
     for ($i = 0; $i < $count; ++$i) {
         if (mb_substr($matches[1][$i], 0, 7) == 'http://' || mb_substr($matches[1][$i], 0, 8) == 'https://') {
             // Basic info
             $url = suxFunct::canonicalizeUrl($matches[1][$i]);
             if (!filter_var($url, FILTER_VALIDATE_URL) || $this->bookmarks->getByID($url)) {
                 continue;
             }
             // skip it
             $title = strip_tags($matches[2][$i]);
             $body = null;
             if (!$this->r->detectPOST()) {
                 $tmp = $this->bookmarks->fetchUrlInfo($url);
                 if ($tmp) {
                     $title = $tmp['title'];
                     $body = $tmp['description'];
                 }
             }
             // Add to array for use in template
             $this->arr['found_links'][$url] = array('title' => $title, 'body' => $body);
         }
     }
     $count = count(@$this->arr['found_links']);
     if (!$count) {
         suxFunct::redirect(suxFunct::getPreviousURL());
     }
     //  No links, skip
 }
Exemple #5
0
 /**
  * Saves a bookmark to the database
  *
  * @param int $users_id users_id
  * @param array $url required keys => (url, title, body) optional keys => (id, published_on, draft)
  * @param int $trusted passed on to sanitizeHtml()
  * @return int insert id
  */
 function save($users_id, array $url, $trusted = -1)
 {
     // -------------------------------------------------------------------
     // Sanitize
     // -------------------------------------------------------------------
     if (!filter_var($users_id, FILTER_VALIDATE_INT) || $users_id < 1) {
         throw new Exception('Invalid user id');
     }
     if (!isset($url['url']) || !isset($url['title']) || !isset($url['body'])) {
         throw new Exception('Invalid $url array');
     }
     if (!filter_var($url['url'], FILTER_VALIDATE_URL)) {
         throw new Exception('Invalid url');
     }
     // Users id
     $clean['users_id'] = $users_id;
     // Canonicalize Url
     $clean['url'] = suxFunct::canonicalizeUrl($url['url']);
     // No HTML in title
     $clean['title'] = strip_tags($url['title']);
     // Sanitize HTML in body
     $clean['body_html'] = suxFunct::sanitizeHtml($url['body'], $trusted);
     // Convert and copy body to UTF-8 plaintext
     $converter = new suxHtml2UTF8($clean['body_html']);
     $clean['body_plaintext'] = $converter->getText();
     // Id
     if (isset($url['id'])) {
         if (!filter_var($url['id'], FILTER_VALIDATE_INT) || $url['id'] < 1) {
             throw new Exception('Invalid id');
         } else {
             $clean['id'] = $url['id'];
         }
     } else {
         $query = "SELECT id FROM {$this->db_table} WHERE url = ? ";
         $st = $this->db->prepare($query);
         $st->execute(array($clean['url']));
         $edit = $st->fetch(PDO::FETCH_ASSOC);
         if ($edit) {
             $clean['id'] = $edit['id'];
         }
     }
     // Publish date
     if (isset($url['published_on'])) {
         // ISO 8601 date format
         // regex must match '2008-06-18 16:53:29' or '2008-06-18T16:53:29-04:00'
         $regex = '/^(\\d{4})-(0[0-9]|1[0,1,2])-([0,1,2][0-9]|3[0,1]).+(\\d{2}):(\\d{2}):(\\d{2})/';
         if (!preg_match($regex, $url['published_on'])) {
             throw new Exception('Invalid date');
         }
         $clean['published_on'] = $url['published_on'];
     } else {
         $clean['published_on'] = date('Y-m-d H:i:s');
     }
     // Draft, boolean / tinyint
     $clean['draft'] = false;
     if (isset($url['draft']) && $url['draft']) {
         $clean['draft'] = true;
     }
     // We now have the $clean[] array
     // --------------------------------------------------------------------
     // Go!
     // --------------------------------------------------------------------
     // http://bugs.php.net/bug.php?id=44597
     // As of 5.2.6 you still can't use this function's $input_parameters to
     // pass a boolean to PostgreSQL. To do that, you'll have to call
     // bindParam() with explicit types for *each* parameter in the query.
     // Annoying much? This sucks more than you can imagine.
     if (isset($clean['id'])) {
         // UPDATE
         unset($clean['users_id']);
         // Don't override the original submitter
         $query = suxDB::prepareUpdateQuery($this->db_table, $clean);
         $st = $this->db->prepare($query);
         if ($this->db_driver == 'pgsql') {
             $st->bindParam(':id', $clean['id'], PDO::PARAM_INT);
             $st->bindParam(':url', $clean['url'], PDO::PARAM_STR);
             $st->bindParam(':title', $clean['title'], PDO::PARAM_STR);
             $st->bindParam(':body_html', $clean['body_html'], PDO::PARAM_STR);
             $st->bindParam(':body_plaintext', $clean['body_plaintext'], PDO::PARAM_STR);
             $st->bindParam(':published_on', $clean['published_on'], PDO::PARAM_STR);
             $st->bindParam(':draft', $clean['draft'], PDO::PARAM_BOOL);
             $st->execute();
         } else {
             $st->execute($clean);
         }
     } else {
         // INSERT
         $query = suxDB::prepareInsertQuery($this->db_table, $clean);
         $st = $this->db->prepare($query);
         if ($this->db_driver == 'pgsql') {
             $st->bindParam(':users_id', $clean['users_id'], PDO::PARAM_INT);
             $st->bindParam(':url', $clean['url'], PDO::PARAM_STR);
             $st->bindParam(':title', $clean['title'], PDO::PARAM_STR);
             $st->bindParam(':body_html', $clean['body_html'], PDO::PARAM_STR);
             $st->bindParam(':body_plaintext', $clean['body_plaintext'], PDO::PARAM_STR);
             $st->bindParam(':published_on', $clean['published_on'], PDO::PARAM_STR);
             $st->bindParam(':draft', $clean['draft'], PDO::PARAM_BOOL);
             $st->execute();
         } else {
             $st->execute($clean);
         }
         if ($this->db_driver == 'pgsql') {
             $clean['id'] = $this->db->lastInsertId("{$this->db_table}_id_seq");
         } else {
             $clean['id'] = $this->db->lastInsertId();
         }
     }
     return $clean['id'];
 }
Exemple #6
0
 /**
  * Constructs a widget
  *
  * @global string $CONFIG['PATH']
  * @param string $title a title
  * @param string $content html content
  * @param string $url URL for the title
  * @param string $image path to image (http://)
  * @param string $caption caption for image
  * @param string $url2 another url, for image
  * @param string $floater class for image encapsulation
  * @return string the html code
  */
 function widget($title, $content, $url = null, $image = null, $caption = null, $url2 = null, $floater = 'floatright')
 {
     // Sanitize / Filter
     if ($url) {
         $url = suxFunct::canonicalizeUrl($url);
         if (!filter_var($url, FILTER_VALIDATE_URL)) {
             $url = null;
         }
     }
     if ($image) {
         $image = suxFunct::canonicalizeUrl($image);
         if (!filter_var($image, FILTER_VALIDATE_URL)) {
             $image = null;
         }
         // The server can be crippled if getimagesize() recursively points
         // to itself (example: . $image = /index.php) so we enforce image
         // extensions to avoid this
         if (!preg_match('/\\.(jpe?g|gif|png)$/i', $image)) {
             $image = null;
         }
     }
     if ($url2) {
         $url2 = suxFunct::canonicalizeUrl($url2);
         if (!filter_var($url2, FILTER_VALIDATE_URL)) {
             $url2 = null;
         }
     }
     // Image manipulation
     $size = $image ? @getimagesize($image) : null;
     if ($size) {
         $image = "<img src='{$image}' alt='' {$size[3]} />";
     } else {
         $image = null;
     }
     // Makeshift renderer object
     $r['arr']['size'] = $size;
     $r['text']['title'] = $title;
     $r['text']['image'] = $image;
     $r['text']['caption'] = $caption;
     $r['text']['content'] = $content;
     $r['text']['floater'] = $floater;
     $r['text']['url_title'] = $url;
     $r['text']['url_image'] = $url;
     if ($url2) {
         $r['text']['url_image'] = $url2;
     }
     $r = (object) $r;
     // Template
     $tpl = new suxTemplate('globals');
     $tpl->assignByRef('r', $r);
     return $tpl->fetch('widget.tpl');
 }
Exemple #7
0
 /**
  *  Helper function called by preg_replace() on link replacement.
  *
  *  Maintains an internal list of links to be displayed at the end of the
  *  text, with numeric indices to the original point in the text they
  *  appeared. Also makes an effort at identifying and handling absolute
  *  and relative links.
  *
  *  @param string $link URL of the link
  *  @param string $display Part of the text to associate number with
  *  @return string
  */
 private function buildLinkList($link, $display)
 {
     if (mb_substr($link, 0, 7) == 'http://' || mb_substr($link, 0, 8) == 'https://' || mb_substr($link, 0, 7) == 'mailto:') {
         // Absolute href links
         $link = suxFunct::canonicalizeUrl($link);
         $this->link_count++;
         $this->link_list .= "[" . $this->link_count . "] {$link}\n";
         $additional = ' [' . $this->link_count . ']';
     } elseif (mb_substr($link, 0, 11) == 'javascript:') {
         // Ignore javascript links
         $additional = '';
     } else {
         // Relative href links
         $this->link_count++;
         $this->link_list .= "[" . $this->link_count . "] ";
         if (mb_substr($link, 0, 1) != '/') {
             $link = '/' . $link;
         }
         $link = suxFunct::canonicalizeUrl($this->url . $link);
         $this->link_list .= "{$link}\n";
         $additional = ' [' . $this->link_count . ']';
     }
     return $display . $additional;
 }
Exemple #8
0
 /**
  * Detach an openid from system
  *
  * @param string $openid_url url
  */
 function detachOpenID($openid_url)
 {
     // Canonicalize url
     $openid_url = suxFunct::canonicalizeUrl($openid_url);
     $query = "DELETE FROM {$this->db_table_openid} WHERE openid_url = ? ";
     $st = $this->db->prepare($query);
     $st->execute(array($openid_url));
 }