diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Minz/Configuration.php | 28 | ||||
| -rw-r--r-- | lib/Minz/Extension.php | 2 | ||||
| -rw-r--r-- | lib/Minz/ModelPdo.php | 15 | ||||
| -rw-r--r-- | lib/Minz/Request.php | 72 | ||||
| -rw-r--r-- | lib/Minz/Session.php | 6 | ||||
| -rw-r--r-- | lib/Minz/Url.php | 17 | ||||
| -rw-r--r-- | lib/Minz/View.php | 1 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie.php | 168 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Cache/File.php | 12 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Decode/HTML/Entities.php | 1 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/File.php | 16 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Item.php | 42 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Locator.php | 2 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Misc.php | 18 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Parse/Date.php | 6 | ||||
| -rwxr-xr-x | lib/SimplePie/SimplePie/Registry.php | 4 | ||||
| -rw-r--r-- | lib/SimplePie/SimplePie/Sanitize.php | 3 | ||||
| -rw-r--r-- | lib/lib_rss.php | 100 |
18 files changed, 332 insertions, 181 deletions
diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index ab5bb4fc2..d695d4a53 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -39,7 +39,7 @@ class Minz_Configuration { throw new Minz_FileNotExistException($filename); } - $data = @include($filename); + $data = include($filename); if (is_array($data)) { return $data; } else { @@ -85,11 +85,6 @@ class Minz_Configuration { private $data = array(); /** - * The default values, an empty array by default. - */ - private $data_default = array(); - - /** * An object which help to set good values in configuration. */ private $configuration_setter = null; @@ -119,21 +114,22 @@ class Minz_Configuration { $configuration_setter = null) { $this->namespace = $namespace; $this->config_filename = $config_filename; + $this->default_filename = $default_filename; + $this->_configurationSetter($configuration_setter); + + if (!is_null($this->default_filename)) { + $this->data = self::load($this->default_filename); + } try { - $this->data = self::load($this->config_filename); + $this->data = array_replace_recursive( + $this->data, self::load($this->config_filename) + ); } catch (Minz_FileNotExistException $e) { - if (is_null($default_filename)) { + if (is_null($this->default_filename)) { throw $e; } } - - $this->default_filename = $default_filename; - if (!is_null($this->default_filename)) { - $this->data_default = self::load($this->default_filename); - } - - $this->_configurationSetter($configuration_setter); } /** @@ -160,8 +156,6 @@ class Minz_Configuration { return $this->data[$key]; } elseif (!is_null($default)) { return $default; - } elseif (isset($this->data_default[$key])) { - return $this->data_default[$key]; } else { Minz_Log::warning($key . ' does not exist in configuration'); return null; diff --git a/lib/Minz/Extension.php b/lib/Minz/Extension.php index d7ee8fe81..78b8a2725 100644 --- a/lib/Minz/Extension.php +++ b/lib/Minz/Extension.php @@ -168,7 +168,7 @@ class Minz_Extension { $url = '/ext.php?f=' . $file_name_url . '&t=' . $type . '&' . $mtime; - return Minz_Url::display($url); + return Minz_Url::display($url, 'php'); } /** diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index ac7a1bed7..25999f02b 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -53,21 +53,19 @@ class Minz_ModelPdo { $this->current_user = $currentUser; self::$sharedCurrentUser = $currentUser; + $driver_options = isset($conf->db['pdo_options']) && is_array($conf->db['pdo_options']) ? $conf->db['pdo_options'] : array(); + try { $type = $db['type']; if ($type === 'mysql') { $string = 'mysql:host=' . $db['host'] . ';dbname=' . $db['base'] . ';charset=utf8'; - $driver_options = array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', - ); + $driver_options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8'; $this->prefix = $db['prefix'] . $currentUser . '_'; } elseif ($type === 'sqlite') { $string = 'sqlite:' . join_path(DATA_PATH, 'users', $currentUser, 'db.sqlite'); - $driver_options = array( - //PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - ); + //$driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION; $this->prefix = ''; } else { throw new Minz_PDOConnectionException( @@ -134,4 +132,9 @@ class MinzPDO extends PDO { MinzPDO::check($statement); return parent::exec($statement); } + + public function query($statement) { + MinzPDO::check($statement); + return parent::query($statement); + } } diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index 6db2e9c7a..effb9943c 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -85,44 +85,58 @@ class Minz_Request { } /** - * Retourn le nom de domaine du site + * Try to guess the base URL from $_SERVER information + * + * @return the base url (e.g. http://example.com/) */ - public static function getDomainName() { - return $_SERVER['HTTP_HOST']; - } + public static function guessBaseUrl() { + $url = 'http'; - /** - * Détermine la base de l'url - * @return la base de l'url - */ - public static function getBaseUrl() { - $conf = Minz_Configuration::get('system'); - $defaultBaseUrl = $conf->base_url; - if (!empty($defaultBaseUrl)) { - return $defaultBaseUrl; - } elseif (isset($_SERVER['REQUEST_URI'])) { - return dirname($_SERVER['REQUEST_URI']) . '/'; + if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { + $https = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https'; } else { - return '/'; + $https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'; } - } - /** - * Récupère l'URI de la requête - * @return l'URI - */ - public static function getURI() { - if (isset($_SERVER['REQUEST_URI'])) { - $base_url = self::getBaseUrl(); - $uri = $_SERVER['REQUEST_URI']; + if (!empty($_SERVER['HTTP_HOST'])) { + $host = $_SERVER['HTTP_HOST']; + } elseif (!empty($_SERVER['SERVER_NAME'])) { + $host = $_SERVER['SERVER_NAME']; + } else { + $host = 'localhost'; + } - $len_base_url = strlen($base_url); - $real_uri = substr($uri, $len_base_url); + if (!empty($_SERVER['HTTP_X_FORWARDED_PORT'])) { + $port = intval($_SERVER['HTTP_X_FORWARDED_PORT']); + } elseif (!empty($_SERVER['SERVER_PORT'])) { + $port = intval($_SERVER['SERVER_PORT']); } else { - $real_uri = ''; + $port = $https ? 443 : 80; } - return $real_uri; + if ($https) { + $url .= 's://' . $host . ($port == 443 ? '' : ':' . $port); + } else { + $url .= '://' . $host . ($port == 80 ? '' : ':' . $port); + } + if (isset($_SERVER['REQUEST_URI'])) { + $path = $_SERVER['REQUEST_URI']; + $url .= substr($path, -1) === '/' ? substr($path, 0, -1) : dirname($path); + } + + return filter_var($url, FILTER_SANITIZE_URL); + } + + /** + * Return the base_url from configuration and add a suffix if given. + * + * @param $base_url_suffix a string to add at base_url (default: empty string) + * @return the base_url with a suffix. + */ + public static function getBaseUrl($base_url_suffix = '') { + $conf = Minz_Configuration::get('system'); + $url = rtrim($conf->base_url, '/\\') . $base_url_suffix; + return filter_var($url, FILTER_SANITIZE_URL); } /** diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index 058685ada..057e7746a 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -66,8 +66,10 @@ class Minz_Session { */ public static function keepCookie($l) { // Get the script_name (e.g. /p/i/index.php) and keep only the path. - $cookie_dir = empty($_SERVER['SCRIPT_NAME']) ? '' : $_SERVER['SCRIPT_NAME']; - $cookie_dir = dirname($cookie_dir); + $cookie_dir = empty($_SERVER['REQUEST_URI']) ? '/' : $_SERVER['REQUEST_URI']; + if (substr($cookie_dir, -1) !== '/') { + $cookie_dir = dirname($cookie_dir) . '/'; + } session_set_cookie_params($l, $cookie_dir, '', false, true); } diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php index af555a277..4279b045b 100644 --- a/lib/Minz/Url.php +++ b/lib/Minz/Url.php @@ -10,7 +10,6 @@ class Minz_Url { * $url['c'] = controller * $url['a'] = action * $url['params'] = tableau des paramètres supplémentaires - * $url['protocol'] = protocole à utiliser (http par défaut) * ou comme une chaîne de caractère * @param $encodage pour indiquer comment encoder les & (& ou & pour html) * @return l'url formatée @@ -19,26 +18,24 @@ class Minz_Url { $isArray = is_array($url); if ($isArray) { - $url = self::checkUrl ($url); + $url = self::checkUrl($url); } $url_string = ''; if ($absolute) { - if ($isArray && isset ($url['protocol'])) { - $protocol = $url['protocol']; - } elseif (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { - $protocol = 'https:'; - } else { - $protocol = 'http:'; + $url_string = Minz_Request::getBaseUrl(PUBLIC_TO_INDEX_PATH); + if ($url_string === PUBLIC_TO_INDEX_PATH) { + $url_string = Minz_Request::guessBaseUrl(); } - $url_string = $protocol . '//' . Minz_Request::getDomainName () . Minz_Request::getBaseUrl (); } else { $url_string = $isArray ? '.' : PUBLIC_RELATIVE; } if ($isArray) { - $url_string .= self::printUri ($url, $encodage); + $url_string .= self::printUri($url, $encodage); + } elseif ($encodage === 'html') { + $url_string = Minz_Helper::htmlspecialchars_utf8($url_string . $url); } else { $url_string .= $url; } diff --git a/lib/Minz/View.php b/lib/Minz/View.php index ff5cce4a5..8c5230ab6 100644 --- a/lib/Minz/View.php +++ b/lib/Minz/View.php @@ -91,6 +91,7 @@ class Minz_View { * Construit le layout */ public function buildLayout () { + header('Content-Type: text/html; charset=UTF-8'); $this->includeFile(self::LAYOUT_PATH_NAME . self::LAYOUT_FILENAME); } diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index c4872b5be..6c0962a9f 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -75,6 +75,12 @@ define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>'); /** + * Use syslog to report HTTP requests done by SimplePie. + * @see SimplePie::set_syslog() + */ +define('SIMPLEPIE_SYSLOG', true); //FreshRSS + +/** * No Autodiscovery * @see SimplePie::set_autodiscovery_level() */ @@ -450,7 +456,7 @@ class SimplePie * @see SimplePie::subscribe_url() * @access private */ - public $permanent_url = null; //FreshRSS + public $permanent_url = null; /** * @var object Instance of SimplePie_File to use as a feed @@ -474,6 +480,13 @@ class SimplePie public $timeout = 10; /** + * @var array Custom curl options + * @see SimplePie::set_curl_options() + * @access private + */ + public $curl_options = array(); + + /** * @var bool Forces fsockopen() to be used for remote files instead * of cURL, even if a new enough version is installed * @see SimplePie::force_fsockopen() @@ -623,6 +636,12 @@ class SimplePie public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); /** + * Use syslog to report HTTP requests done by SimplePie. + * @see SimplePie::set_syslog() + */ + public $syslog_enabled = SIMPLEPIE_SYSLOG; + + /** * The SimplePie class contains feed level data and options * * To use SimplePie, create the SimplePie object with no parameters. You can @@ -742,7 +761,7 @@ class SimplePie else { $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1)); - $this->permanent_url = $this->feed_url; //FreshRSS + $this->permanent_url = $this->feed_url; } } @@ -757,7 +776,7 @@ class SimplePie if ($file instanceof SimplePie_File) { $this->feed_url = $file->url; - $this->permanent_url = $this->feed_url; //FreshRSS + $this->permanent_url = $this->feed_url; $this->file =& $file; return true; } @@ -795,6 +814,19 @@ class SimplePie { $this->timeout = (int) $timeout; } + + /** + * Set custom curl options + * + * This allows you to change default curl options + * + * @since 1.0 Beta 3 + * @param array $curl_options Curl options to add to default settings + */ + public function set_curl_options(array $curl_options = array()) + { + $this->curl_options = $curl_options; + } /** * Force SimplePie to use fsockopen() instead of cURL @@ -1136,7 +1168,7 @@ class SimplePie $this->sanitize->strip_attributes($attribs); } - public function add_attributes($attribs = '') + public function add_attributes($attribs = '') //FreshRSS { if ($attribs === '') { @@ -1146,6 +1178,14 @@ class SimplePie } /** + * Use syslog to report HTTP requests done by SimplePie. + */ + public function set_syslog($value = SIMPLEPIE_SYSLOG) //FreshRSS + { + $this->syslog_enabled = $value == true; + } + + /** * Set the output encoding * * Allows you to override SimplePie's output to match that of your webpage. @@ -1231,7 +1271,8 @@ class SimplePie $this->enable_exceptions = $enable; } - function cleanMd5($rss) { //FreshRSS + function cleanMd5($rss) + { return md5(preg_replace(array('#<(lastBuildDate|pubDate|updated|feedDate|dc:date|slash:comments)>[^<]+</\\1>#', '#<!--.+?-->#s'), '', $rss)); } @@ -1276,7 +1317,7 @@ class SimplePie // Pass whatever was set with config options over to the sanitizer. // Pass the classes in for legacy support; new classes should use the registry instead $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache')); - $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen); + $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options); if (!empty($this->multifeed_url)) { @@ -1321,7 +1362,7 @@ class SimplePie // Fetch the data via SimplePie_File into $this->raw_data if (($fetched = $this->fetch_data($cache)) === true) { - return $this->data['mtime']; //FreshRSS + return $this->data['mtime']; } elseif ($fetched === false) { return false; @@ -1329,7 +1370,8 @@ class SimplePie list($headers, $sniffed) = $fetched; - if (isset($this->data['md5'])) { //FreshRSS + if (isset($this->data['md5'])) + { $md5 = $this->data['md5']; } } @@ -1413,8 +1455,8 @@ class SimplePie $this->data['headers'] = $headers; } $this->data['build'] = SIMPLEPIE_BUILD; - $this->data['mtime'] = time(); //FreshRSS - $this->data['md5'] = empty($md5) ? $this->cleanMd5($this->raw_data) : $md5; //FreshRSS + $this->data['mtime'] = time(); + $this->data['md5'] = empty($md5) ? $this->cleanMd5($this->raw_data) : $md5; // Cache the file if caching is enabled if ($cache && !$cache->save($this)) @@ -1429,7 +1471,7 @@ class SimplePie if (isset($parser)) { // We have an error, just set SimplePie_Misc::error to it and quit - $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column()); + $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d, encoding %s, URL: %s', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column(), $encoding, $this->feed_url); } else { @@ -1455,7 +1497,8 @@ class SimplePie { // Load the Cache $this->data = $cache->load(); - if ($cache->mtime() + $this->cache_duration > time()) { //FreshRSS + if ($cache->mtime() + $this->cache_duration > time()) + { $this->raw_data = false; return true; // If the cache is still valid, just return true } @@ -1491,65 +1534,58 @@ class SimplePie } } // Check if the cache has been updated - else //if ($cache->mtime() + $this->cache_duration < time()) //FreshRSS removed + else { - // If we have last-modified and/or etag set - //if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) //FreshRSS removed + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + if (isset($this->data['headers']['last-modified'])) { - $headers = array( - 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', - ); - if (isset($this->data['headers']['last-modified'])) - { - $headers['if-modified-since'] = $this->data['headers']['last-modified']; - } - if (isset($this->data['headers']['etag'])) - { - $headers['if-none-match'] = $this->data['headers']['etag']; - } + $headers['if-modified-since'] = $this->data['headers']['last-modified']; + } + if (isset($this->data['headers']['etag'])) + { + $headers['if-none-match'] = $this->data['headers']['etag']; + } - $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen)); //FreshRSS + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); - if ($file->success) + if ($file->success) + { + if ($file->status_code === 304) { - if ($file->status_code === 304) - { - $cache->touch(); - return true; - } + $cache->touch(); + return true; } - else + } + else + { + $cache->touch(); + $this->error = $file->error; + return !empty($this->data); + } + + $md5 = $this->cleanMd5($file->body); + if ($this->data['md5'] === $md5) { + if ($this->syslog_enabled) { - $cache->touch(); //FreshRSS - $this->error = $file->error; //FreshRSS - return !empty($this->data); //FreshRSS - //unset($file); //FreshRSS removed + syslog(LOG_DEBUG, 'SimplePie MD5 cache match for ' . SimplePie_Misc::url_remove_credentials($this->feed_url)); } - } - { //FreshRSS - $md5 = $this->cleanMd5($file->body); - if ($this->data['md5'] === $md5) { - // syslog(LOG_DEBUG, 'SimplePie MD5 cache match for ' . $this->feed_url); - $cache->touch(); - return true; //Content unchanged even though server did not send a 304 - } else { - // syslog(LOG_DEBUG, 'SimplePie MD5 cache no match for ' . $this->feed_url); - $this->data['md5'] = $md5; + $cache->touch(); + return true; //Content unchanged even though server did not send a 304 + } else { + if ($this->syslog_enabled) + { + syslog(LOG_DEBUG, 'SimplePie MD5 cache no match for ' . SimplePie_Misc::url_remove_credentials($this->feed_url)); } + $this->data['md5'] = $md5; } } - //// If the cache is still valid, just return true - //else //FreshRSS removed - //{ - // $this->raw_data = false; - // return true; - //} - } - // If the cache is empty, delete it + } + // If the cache is empty else { - //$cache->unlink(); //FreshRSS removed - $cache->touch(); //FreshRSS + $cache->touch(); //To keep the date/time of the last tentative update $this->data = array(); } } @@ -1565,7 +1601,7 @@ class SimplePie $headers = array( 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ); - $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen)); + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); } } // If the file connection has an error, set SimplePie::error to that and quit @@ -1582,15 +1618,15 @@ class SimplePie if (!$locate->is_feed($file)) { - $copyStatusCode = $file->status_code; //FreshRSS - $copyContentType = $file->headers['content-type']; //FreshRSS + $copyStatusCode = $file->status_code; + $copyContentType = $file->headers['content-type']; // We need to unset this so that if SimplePie::set_file() has been called that object is untouched unset($file); try { if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))) { - $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`"; //FreshRSS + $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`"; $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); return false; } @@ -1605,8 +1641,8 @@ class SimplePie if ($cache) { $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD); - $this->data['mtime'] = time(); //FreshRSS - $this->data['md5'] = empty($md5) ? $this->cleanMd5($file->body) : $md5; //FreshRSS + $this->data['mtime'] = time(); + $this->data['md5'] = empty($md5) ? $this->cleanMd5($file->body) : $md5; if (!$cache->save($this)) { trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); @@ -1619,7 +1655,7 @@ class SimplePie } $this->raw_data = $file->body; - $this->permanent_url = $file->permanent_url; //FreshRSS + $this->permanent_url = $file->permanent_url; $headers = $file->headers; $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file)); $sniffed = $sniffer->get_type(); @@ -1823,7 +1859,7 @@ class SimplePie */ public function subscribe_url($permanent = false) { - if ($permanent) //FreshRSS + if ($permanent) { if ($this->permanent_url !== null) { diff --git a/lib/SimplePie/SimplePie/Cache/File.php b/lib/SimplePie/SimplePie/Cache/File.php index cb4b528c4..72e75a4b6 100644 --- a/lib/SimplePie/SimplePie/Cache/File.php +++ b/lib/SimplePie/SimplePie/Cache/File.php @@ -136,11 +136,7 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base */ public function mtime() { - //if (file_exists($this->name)) //FreshRSS removed - { - return @filemtime($this->name); //FreshRSS - } - //return false; //FreshRSS removed + return @filemtime($this->name); } /** @@ -150,11 +146,7 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base */ public function touch() { - //if (file_exists($this->name)) //FreshRSS removed - { - return @touch($this->name); //FreshRSS - } - //return false; //FreshRSS removed + return @touch($this->name); } /** diff --git a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php index cde06c884..46b3a1dff 100644 --- a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php +++ b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php @@ -169,7 +169,6 @@ class SimplePie_Decode_HTML_Entities case "\x09": case "\x0A": case "\x0B": - case "\x0B": case "\x0C": case "\x20": case "\x3C": diff --git a/lib/SimplePie/SimplePie/File.php b/lib/SimplePie/SimplePie/File.php index 9625af2a9..45994d102 100644 --- a/lib/SimplePie/SimplePie/File.php +++ b/lib/SimplePie/SimplePie/File.php @@ -66,7 +66,7 @@ class SimplePie_File var $method = SIMPLEPIE_FILE_SOURCE_NONE; var $permanent_url; //FreshRSS - public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) + public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array(), $syslog_enabled = SIMPLEPIE_SYSLOG) { if (class_exists('idna_convert')) { @@ -75,11 +75,14 @@ class SimplePie_File $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); } $this->url = $url; - $this->permanent_url = $url; //FreshRSS + $this->permanent_url = $url; $this->useragent = $useragent; if (preg_match('/^http(s)?:\/\//i', $url)) { - // syslog(LOG_INFO, 'SimplePie GET ' . $url); //FreshRSS + if ($syslog_enabled) + { + syslog(LOG_INFO, 'SimplePie GET ' . SimplePie_Misc::url_remove_credentials($url)); //FreshRSS + } if ($useragent === null) { $useragent = ini_get('user_agent'); @@ -110,12 +113,15 @@ class SimplePie_File curl_setopt($fp, CURLOPT_REFERER, $url); curl_setopt($fp, CURLOPT_USERAGENT, $useragent); curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); - curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false); //FreshRSS if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>=')) { curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects); } + foreach ($curl_options as $curl_param => $curl_value) + { + curl_setopt($fp, $curl_param, $curl_value); + } $this->headers = curl_exec($fp); if (curl_errno($fp) === 23 || curl_errno($fp) === 61) @@ -146,7 +152,7 @@ class SimplePie_File $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); $previousStatusCode = $this->status_code; $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); - $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; //FreshRSS + $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; return; } } diff --git a/lib/SimplePie/SimplePie/Item.php b/lib/SimplePie/SimplePie/Item.php index 7bd96c15f..27e93456e 100644 --- a/lib/SimplePie/SimplePie/Item.php +++ b/lib/SimplePie/SimplePie/Item.php @@ -406,6 +406,30 @@ class SimplePie_Item return null; } } + + /** + * Get the media:thumbnail of the item + * + * Uses `<media:thumbnail>` + * + * + * @return array|null + */ + public function get_thumbnail() + { + if (!isset($this->data['thumbnail'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + $this->data['thumbnail'] = $return[0]['attribs']['']; + } + else + { + $this->data['thumbnail'] = null; + } + } + return $this->data['thumbnail']; + } /** * Get a category for the item @@ -738,31 +762,31 @@ class SimplePie_Item { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) { $this->data['date']['raw'] = $return[0]['data']; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) { $this->data['date']['raw'] = $return[0]['data']; } @@ -2733,7 +2757,9 @@ class SimplePie_Item { foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) { - $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + if (isset($thumbnail['attribs']['']['url'])) { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } } if (is_array($thumbnails)) { diff --git a/lib/SimplePie/SimplePie/Locator.php b/lib/SimplePie/SimplePie/Locator.php index 4e5f7c1ca..ba4a843b0 100644 --- a/lib/SimplePie/SimplePie/Locator.php +++ b/lib/SimplePie/SimplePie/Locator.php @@ -148,7 +148,7 @@ class SimplePie_Locator { $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); $sniffed = $sniffer->get_type(); - if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml', 'application/x-rss+xml'))) //FreshRSS + if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml', 'application/x-rss+xml'))) { return true; } diff --git a/lib/SimplePie/SimplePie/Misc.php b/lib/SimplePie/SimplePie/Misc.php index 5a263a2e5..9e7ac4fa8 100644 --- a/lib/SimplePie/SimplePie/Misc.php +++ b/lib/SimplePie/SimplePie/Misc.php @@ -79,8 +79,8 @@ class SimplePie_Misc public static function absolutize_url($relative, $base) { - if (substr($relative, 0, 2) === '//') //FreshRSS: disable absolutize_url for "//www.example.net" which will pick HTTP or HTTPS automatically - { + if (substr($relative, 0, 2) === '//') + {//Allow protocol-relative URLs "//www.example.net" which will pick HTTP or HTTPS automatically return $relative; } $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative); @@ -128,7 +128,7 @@ class SimplePie_Misc { $attribs[$j][2] = $attribs[$j][1]; } - $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8'); //FreshRSS + $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8'); } } } @@ -142,7 +142,7 @@ class SimplePie_Misc foreach ($element['attribs'] as $key => $value) { $key = strtolower($key); - $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"'; //FreshRSS + $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"'; } if ($element['self_closing']) { @@ -2240,5 +2240,15 @@ function embed_wmedia(width, height, link) { { // No-op } + + /** + * Sanitize a URL by removing HTTP credentials. + * @param $url the URL to sanitize. + * @return the same URL without HTTP credentials. + */ + public static function url_remove_credentials($url) //FreshRSS + { + return preg_replace('#^(https?://)[^/:@]+:[^/:@]+@#i', '$1', $url); + } } diff --git a/lib/SimplePie/SimplePie/Parse/Date.php b/lib/SimplePie/SimplePie/Parse/Date.php index ba7c0703e..50bb5cffa 100644 --- a/lib/SimplePie/SimplePie/Parse/Date.php +++ b/lib/SimplePie/SimplePie/Parse/Date.php @@ -173,7 +173,7 @@ class SimplePie_Parse_Date 'aug' => 8, 'august' => 8, 'sep' => 9, - 'september' => 8, + 'september' => 9, 'oct' => 10, 'october' => 10, 'nov' => 11, @@ -331,8 +331,8 @@ class SimplePie_Parse_Date 'CCT' => 23400, 'CDT' => -18000, 'CEDT' => 7200, - 'CEST' => 7200, //FreshRSS 'CET' => 3600, + 'CEST' => 7200, 'CGST' => -7200, 'CGT' => -10800, 'CHADT' => 49500, @@ -721,7 +721,7 @@ class SimplePie_Parse_Date { $output .= substr($string, $position, $pos - $position); $position = $pos + 1; - if ($string[$pos - 1] !== '\\') + if ($pos === 0 || $string[$pos - 1] !== '\\') { $depth++; while ($depth && $position < $length) diff --git a/lib/SimplePie/SimplePie/Registry.php b/lib/SimplePie/SimplePie/Registry.php index bd9c1f535..dac55e34e 100755 --- a/lib/SimplePie/SimplePie/Registry.php +++ b/lib/SimplePie/SimplePie/Registry.php @@ -113,7 +113,7 @@ class SimplePie_Registry */ public function register($type, $class, $legacy = false) { - if (!is_subclass_of($class, $this->default[$type])) + if (!@is_subclass_of($class, $this->default[$type])) { return false; } @@ -222,4 +222,4 @@ class SimplePie_Registry $result = call_user_func_array(array($class, $method), $parameters); return $result; } -}
\ No newline at end of file +} diff --git a/lib/SimplePie/SimplePie/Sanitize.php b/lib/SimplePie/SimplePie/Sanitize.php index 168a5e2e8..a6863ec03 100644 --- a/lib/SimplePie/SimplePie/Sanitize.php +++ b/lib/SimplePie/SimplePie/Sanitize.php @@ -249,6 +249,7 @@ class SimplePie_Sanitize { if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) { + $data = htmlspecialchars_decode($data, ENT_QUOTES); if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) { $type |= SIMPLEPIE_CONSTRUCT_HTML; @@ -279,7 +280,7 @@ class SimplePie_Sanitize $document->loadHTML($data); restore_error_handler(); - $xpath = new DOMXPath($document); //FreshRSS + $xpath = new DOMXPath($document); // Strip comments if ($this->strip_comments) diff --git a/lib/lib_rss.php b/lib/lib_rss.php index e5fe73041..2a23fca45 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -38,7 +38,7 @@ function classAutoloader($class) { include(APP_PATH . '/Models/' . $components[1] . '.php'); return; case 3: //Controllers, Exceptions - @include(APP_PATH . '/' . $components[2] . 's/' . $components[1] . $components[2] . '.php'); + include(APP_PATH . '/' . $components[2] . 's/' . $components[1] . $components[2] . '.php'); return; } } elseif (strpos($class, 'Minz') === 0) { @@ -51,6 +51,21 @@ function classAutoloader($class) { spl_autoload_register('classAutoloader'); //</Auto-loading> +function idn_to_puny($url) { + if (function_exists('idn_to_ascii')) { + $parts = parse_url($url); + if (!empty($parts['host'])) { + $idn = $parts['host']; + $puny = idn_to_ascii($idn); + $pos = strpos($url, $idn); + if ($pos !== false) { + return substr_replace($url, $puny, $pos, strlen($idn)); + } + } + } + return $url; +} + function checkUrl($url) { if (empty ($url)) { return ''; @@ -58,6 +73,7 @@ function checkUrl($url) { if (!preg_match ('#^https?://#i', $url)) { $url = 'http://' . $url; } + $url = idn_to_puny($url); //PHP bug #53474 IDN if (filter_var($url, FILTER_VALIDATE_URL) || (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($url, '-') > 0) && //PHP bug #51192 ($url === filter_var($url, FILTER_SANITIZE_URL)))) { @@ -67,6 +83,33 @@ function checkUrl($url) { } } + +/** + * Test if a given server address is publicly accessible. + * + * Note: for the moment it tests only if address is corresponding to a + * localhost address. + * + * @param $address the address to test, can be an IP or a URL. + * @return true if server is accessible, false else. + * @todo improve test with a more valid technique (e.g. test with an external server?) + */ +function server_is_public($address) { + $host = parse_url($address, PHP_URL_HOST); + + $is_public = !in_array($host, array( + '127.0.0.1', + 'localhost', + 'localhost.localdomain', + '[::1]', + 'localhost6', + 'localhost6.localdomain6', + )); + + return $is_public; +} + + function format_number($n, $precision = 0) { // number_format does not seem to be Unicode-compatible return str_replace(' ', ' ', //Espace fine insécable @@ -123,9 +166,11 @@ function customSimplePie() { $limits = $system_conf->limits; $simplePie = new SimplePie(); $simplePie->set_useragent(_t('gen.freshrss') . '/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ') ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION); + $simplePie->set_syslog($system_conf->simplepie_syslog_enabled); $simplePie->set_cache_location(CACHE_PATH); $simplePie->set_cache_duration($limits['cache_duration']); $simplePie->set_timeout($limits['timeout']); + $simplePie->set_curl_options($system_conf->curl_options); $simplePie->strip_htmltags(array( 'base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', @@ -178,17 +223,27 @@ function sanitizeHTML($data, $base = '') { /* permet de récupérer le contenu d'un article pour un flux qui n'est pas complet */ function get_content_by_parsing ($url, $path) { - require_once (LIB_PATH . '/lib_phpQuery.php'); + require_once(LIB_PATH . '/lib_phpQuery.php'); - Minz_Log::notice('FreshRSS GET ' . url_remove_credentials($url)); - $html = file_get_contents ($url); + Minz_Log::notice('FreshRSS GET ' . SimplePie_Misc::url_remove_credentials($url)); + $html = file_get_contents($url); if ($html) { - $doc = phpQuery::newDocument ($html); - $content = $doc->find ($path); + $doc = phpQuery::newDocument($html); + $content = $doc->find($path); + + foreach (pq('img[data-src]') as $img) { + $imgP = pq($img); + $dataSrc = $imgP->attr('data-src'); + if (strlen($dataSrc) > 4) { + $imgP->attr('src', $dataSrc); + $imgP->removeAttr('data-src'); + } + } + return sanitizeHTML($content->__toString(), $url); } else { - throw new Exception (); + throw new Exception(); } } @@ -239,6 +294,22 @@ function listUsers() { /** + * Return if the maximum number of registrations has been reached. + * + * Note a max_regstrations of 0 means there is no limit. + * + * @return true if number of users >= max registrations, false else. + */ +function max_registrations_reached() { + $system_conf = Minz_Configuration::get('system'); + $limit_registrations = $system_conf->limits['max_registrations']; + $number_accounts = count(listUsers()); + + return $limit_registrations > 0 && $number_accounts >= $limit_registrations; +} + + +/** * Register and return the configuration for a given user. * * Note this function has been created to generate temporary configuration @@ -430,12 +501,11 @@ function array_remove(&$array, $value) { $array = array_diff($array, array($value)); } - -/** - * Sanitize a URL by removing HTTP credentials. - * @param $url the URL to sanitize. - * @return the same URL without HTTP credentials. - */ -function url_remove_credentials($url) { - return preg_replace('/[^\/]*:[^:]*@/', '', $url); +//RFC 4648 +function base64url_encode($data) { + return strtr(rtrim(base64_encode($data), '='), '+/', '-_'); +} +//RFC 4648 +function base64url_decode($data) { + return base64_decode(strtr($data, '-_', '+/')); } |
