Ejemplo n.º 1
0
 /**
  * Match a URL/URI against the rewrite rules stored in the DB.
  * This method is used by the Controller class for parsing
  * requests, and by other classes, such as Pingback, which
  * uses it to determine the post slug for a given URL.
  *
  * Returns the matched RewriteRule object, or false.
  *
  * @param string $from_url URL string to parse
  * @return \Habari\RewriteRule matched rule, or false
  */
 public static function parse($from_url)
 {
     $base_url = Site::get_path('base', true);
     /*
      * Strip out the base URL from the requested URL
      * but only if the base URL isn't /
      */
     if (strpos($from_url, $base_url) === 0) {
         $from_url = MultiByte::substr($from_url, MultiByte::strlen($base_url));
     }
     /* Trim off any leading or trailing slashes */
     $from_url = trim($from_url, '/');
     /* Remove the querystring from the URL */
     if (MultiByte::strpos($from_url, '?') !== false) {
         list($from_url, ) = explode('?', $from_url);
     }
     $url = URL::instance();
     $url->load_rules();
     // Cached in singleton
     /*
      * Run the stub through the regex matcher
      */
     self::$stub = $from_url;
     /** @var RewriteRule $rule */
     foreach ($url->rules as $rule) {
         if ($rule->match($from_url)) {
             $url->matched_rule = $rule;
             /* Stop processing at first matched rule... */
             return $rule;
         }
     }
     return false;
 }
Ejemplo n.º 2
0
 /**
  * Initialize the session handlers
  */
 static function init()
 {
     // the default path for the session cookie is /, but let's make that potentially more restrictive so no one steals our cookehs
     // we also can't use 'null' when we set a secure-only value, because that doesn't mean the same as the default like it should
     $path = Site::get_path('base', true);
     // the default is not to require a secure session
     $secure = false;
     // if we want to always require secure
     if (Config::get('force_secure_session') == true) {
         $secure = true;
     }
     // if this is an HTTPS connection by default we will
     // IIS sets HTTPS == 'off', so we have to check the value too
     if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
         $secure = true;
     }
     // but if we have explicitly disabled it, don't
     // note the ===. not setting it (ie: null) should not be the same as setting it to false
     if (Config::get('force_secure_session') === false) {
         $secure = false;
     }
     // now we've got a path and secure, so set the cookie values
     session_set_cookie_params(null, $path, null, $secure);
     // figure out the session lifetime and let plugins change it
     $lifetime = ini_get('session.gc_maxlifetime');
     self::$lifetime = Plugins::filter('session_lifetime', $lifetime);
     session_set_save_handler(array('Session', 'open'), array('Session', 'close'), array('Session', 'read'), array('Session', 'write'), array('Session', 'destroy'), array('Session', 'gc'));
     // session::write gets called after object destruction, so our class isn't available
     // fix that by registering it as a shutdown function, before objects are destroyed
     register_shutdown_function('session_write_close');
     if (!isset($_SESSION)) {
         session_start();
     }
     return true;
 }
Ejemplo n.º 3
0
 /**
  * Initialize some internal values when plugin initializes
  */
 public function action_init()
 {
     $user_path = HABARI_PATH . '/' . Site::get_path('user', true);
     $this->root = $user_path . 'files';
     //Options::get('simple_file_root');
     $this->url = Options::get('s3_url');
     $this->bucket = Options::get('s3_bucket');
     $this->key = Options::get('s3_key');
     $this->private_key = Options::get('s3_secret');
 }
Ejemplo n.º 4
0
 private function default_paths($force = false)
 {
     // If either the upload directory or the upload URL is empty, fallback to the defaults
     // This behavior can also be forced when needed (for example, resetting the configuration)
     if ($force || empty($this->upload_dir) || empty($this->upload_url)) {
         // By default, we use the same directory as the Habari media silo (user/files)
         $user_path = HABARI_PATH . '/' . Site::get_path('user', true);
         Options::set('metaweblog__upload_dir', $user_path . 'files');
         Options::set('metaweblog__upload_url', Site::get_url('user', true) . 'files');
         // Also, check if the upload directory exist and are writable
         $this->check_upload_dir();
     }
 }
Ejemplo n.º 5
0
 /**
  * Connect to SQLite
  * Overrides the DatabaseConnection to return false if the SQLite file doesn't exist.
  *
  * @param connection_string string a PDO connection string
  * @param db_user string the database user name
  * @param db_pass string the database user password
  * @return boolean True if connection succeeded, false if not.
  */
 public function connect($connect_string, $db_user, $db_pass)
 {
     list($type, $file) = explode(':', $connect_string, 2);
     if ($file == basename($file)) {
         if (file_exists(HABARI_PATH . '/' . $file)) {
             $file = HABARI_PATH . '/' . $file;
         } else {
             $file = HABARI_PATH . '/' . Site::get_path('user', TRUE) . $file;
         }
         $connect_string = implode(':', array($type, $file));
     }
     $conn = parent::connect($connect_string, $db_user, $db_pass);
     $this->exec('PRAGMA synchronous = OFF');
     return $conn;
 }
	/**
	 *
	 * Checks if files directory is usable
	 */
	private function check_files() {
		$user_path = HABARI_PATH . '/' . Site::get_path('user', true);
		$this->root = $user_path . 'files'; //Options::get('simple_file_root');
		$this->url = Site::get_url('user', true) . 'files';  //Options::get('simple_file_url');

		if ( !is_dir( $this->root ) ) {
			if ( is_writable( $user_path ) ) {
				mkdir( $this->root, 0755 );
			}
			else {
				return false;
			}
		}

		return true;
	}
 protected function getTemplateHelperSets()
 {
     // strip the subdirectory out of the theme path, as that will already be part of the base URL
     $themePath = substr(Site::get_path('theme') . '/web', strlen(Site::get_path('base')));
     $sets = array(new sfTemplateHelperAssets($themePath, Site::get_url('habari')), new sfTemplateHelperJavascripts(), new sfTemplateHelperStylesheets());
     $dirs = array($this->themeDirectory . '/lib/helper', dirname(__FILE__) . '/helper');
     foreach ($dirs as $dir) {
         foreach (glob($dir . '/*.php') as $helperPath) {
             include_once $helperPath;
             $helperFilename = basename($helperPath);
             $className = substr($helperFilename, 0, strpos($helperFilename, '.'));
             $sets[] = new $className();
         }
     }
     return $sets;
 }
Ejemplo n.º 8
0
 public function action_template_header()
 {
     $modified = Stack::get_sorted_stack('template_header_javascript');
     foreach ($modified as $key => $value) {
         Stack::remove('template_header_javascript', $key);
     }
     Stack::add('template_header_javascript', Site::get_url('user') . "/files/minified.js", 'Minified');
     if (!Cache::has(self::$cache_name . '_js') || !Cache::has(self::$cache_name . '_css')) {
         set_include_path(dirname(__FILE__) . '/min/lib' . PATH_SEPARATOR . get_include_path());
         require_once 'Minify/Source.php';
         require_once 'Minify/HTML.php';
         require_once 'Minify/CSS.php';
         require_once 'Minify/HTML.php';
         require_once 'Minify.php';
         require_once 'Minify/Cache/File.php';
     }
     if (!Cache::has(self::$cache_name . '_js')) {
         $js_stack = array();
         foreach ($modified as $js) {
             $js_stack[] = Site::get_path('base') . str_replace(Site::get_url('habari') . '/', '', $js);
         }
         $options = array('files' => $js_stack, 'encodeOutput' => false, 'quiet' => true, 'maxAge' => 86400);
         $result = Minify::serve('Files', $options);
         file_put_contents(site::get_dir('user') . '/files/minified.js', $result['content']);
         Cache::set(self::$cache_name . '_js', 'true');
     }
     /* CSS */
     $modified = Stack::get_sorted_stack('template_stylesheet');
     $tmp = array();
     foreach ($modified as $key => $value) {
         $tmp[] = $value[0];
         Stack::remove('template_stylesheet', $key);
     }
     Stack::add('template_stylesheet', array(Site::get_url('user') . "/files/minified.css", 'screen'), 'style');
     if (!Cache::has(self::$cache_name . '_css')) {
         $css_stack = array();
         foreach ($tmp as $css) {
             $css_stack[] = Site::get_path('base') . str_replace(Site::get_url('habari') . '/', '', $css);
         }
         $options = array('files' => $css_stack, 'encodeOutput' => false, 'quiet' => true, 'maxAge' => 86400);
         // handle request
         $result = Minify::serve('Files', $options);
         file_put_contents(site::get_dir('user') . '/files/minified.css', $result['content']);
         Cache::set(self::$cache_name . '_css', 'true');
     }
 }
Ejemplo n.º 9
0
 /**
  * Connect to SQLite
  * Overrides the DatabaseConnection to return false if the SQLite file doesn't exist.
  *
  * @param connection_string string a PDO connection string
  * @param db_user string the database user name
  * @param db_pass string the database user password
  * @return boolean True if connection succeeded, false if not.
  */
 public function connect($connect_string, $db_user, $db_pass)
 {
     list($type, $file) = explode(':', $connect_string, 2);
     if ($file == basename($file)) {
         if (file_exists(HABARI_PATH . '/' . $file)) {
             $file = HABARI_PATH . '/' . $file;
         } else {
             $file = HABARI_PATH . '/' . Site::get_path('user', true) . $file;
         }
         $connect_string = implode(':', array($type, $file));
     }
     if (file_exists($file) && !is_writable($file)) {
         die(_t('Database file "%s" must be writable.', array($file)));
     }
     $conn = parent::connect($connect_string, $db_user, $db_pass);
     $this->exec('PRAGMA synchronous = OFF');
     return $conn;
 }
Ejemplo n.º 10
0
 /**
  * Loads a theme's metadata from an XML file in theme's
  * directory.
  *
  * @param theme Name of theme to retrieve metadata about
  */
 public function info($theme)
 {
     $xml_file = Site::get_path('user') . '/themes/' . $theme . '/theme.xml';
     if ($xml_content = file_get_contents($xml_file)) {
         $theme_data = new SimpleXMLElement($xml_file);
         // Is it a valid theme xml file?
         if (isset($theme_data->theme)) {
             $valid_named_elements = array('name', 'version', 'template_engine', 'theme_dir');
             // Assigns based on wether or not it's a valid named element.
             foreach ($theme_data->theme->children() as $key => $value) {
                 $key = strtolower($key);
                 if (in_array($key, $valid_named_elements)) {
                     $this->{$key} = $value;
                 } else {
                     $this->config_vars[$key] = $value;
                 }
             }
         }
     }
 }
Ejemplo n.º 11
0
 /**
  * Initialize the session handlers
  */
 public static function init()
 {
     // the default path for the session cookie is /, but let's make that potentially more restrictive so no one steals our cookehs
     // we also can't use 'null' when we set a secure-only value, because that doesn't mean the same as the default like it should
     $path = Site::get_path('base', true);
     // the default is not to require a secure session
     $secure = false;
     // if we want to always require secure
     if (Config::get('force_secure_session') == true) {
         $secure = true;
     }
     // if this is an HTTPS connection by default we will
     // IIS sets HTTPS == 'off', so we have to check the value too
     if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
         $secure = true;
     }
     // but if we have explicitly disabled it, don't
     // note the ===. not setting it (ie: null) should not be the same as setting it to false
     if (Config::get('force_secure_session') === false) {
         $secure = false;
     }
     // now we've got a path and secure, so set the cookie values
     session_set_cookie_params(null, $path, null, $secure);
     // figure out the session lifetime and let plugins change it
     $lifetime = ini_get('session.gc_maxlifetime');
     self::$lifetime = Plugins::filter('session_lifetime', $lifetime);
     //$_SESSION = new SessionStorage();
     if (isset($_COOKIE[self::HABARI_SESSION_COOKIE_NAME])) {
         self::$session_id = $_COOKIE[self::HABARI_SESSION_COOKIE_NAME];
         self::read();
         self::$stored_session_hash = self::session_data_hash();
     }
     // make sure we check whether or not we should write the session after the page is rendered
     register_shutdown_function(Method::create('\\Habari\\Session', 'shutdown'));
     // process the write queue
     register_shutdown_function(Method::create('\\Habari\\Session', 'process_queue'));
     return true;
 }
Ejemplo n.º 12
0
 /**
  * Add a comment to the site
  *
  * @param mixed $post A Post object instance or Post object id
  * @param string $name The commenter's name
  * @param string $email The commenter's email address
  * @param string $url The commenter's website URL
  * @param string $content The comment content
  * @param array $extra An associative array of extra values that should be considered
  */
 function add_comment($post, $name = null, $email = null, $url = null, $content = null, $extra = null)
 {
     if (is_numeric($post)) {
         $post = Post::get(array('id' => $post));
     }
     if (!$post instanceof Post) {
         // Not sure what you're trying to pull here, but that's no good
         header('HTTP/1.1 403 Forbidden', true, 403);
         die;
     }
     // let's do some basic sanity checking on the submission
     if (1 == Options::get('comments_require_id') && (empty($name) || empty($email))) {
         Session::error(_t('Both name and e-mail address must be provided.'));
     }
     if (empty($content)) {
         Session::error(_t('You did not provide any content for your comment!'));
     }
     if (Session::has_errors()) {
         // save whatever was provided in session data
         Session::add_to_set('comment', $name, 'name');
         Session::add_to_set('comment', $email, 'email');
         Session::add_to_set('comment', $url, 'url');
         Session::add_to_set('comment', $content, 'content');
         // now send them back to the form
         Utils::redirect($post->permalink . '#respond');
     }
     if ($post->info->comments_disabled) {
         // comments are disabled, so let's just send
         // them back to the post's permalink
         Session::error(_t('Comments on this post are disabled!'));
         Utils::redirect($post->permalink);
     }
     /* Sanitize data */
     foreach (array('name', 'url', 'email', 'content') as $k) {
         ${$k} = InputFilter::filter(${$k});
     }
     /* Sanitize the URL */
     if (!empty($url)) {
         $parsed = InputFilter::parse_url($url);
         if ($parsed['is_relative']) {
             // guess if they meant to use an absolute link
             $parsed = InputFilter::parse_url('http://' . $url);
             if (!$parsed['is_error']) {
                 $url = InputFilter::glue_url($parsed);
             } else {
                 // disallow relative URLs
                 $url = '';
             }
         }
         if ($parsed['is_pseudo'] || $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') {
             // allow only http(s) URLs
             $url = '';
         } else {
             // reconstruct the URL from the error-tolerant parsing
             // http:moeffju.net/blog/ -> http://moeffju.net/blog/
             $url = InputFilter::glue_url($parsed);
         }
     }
     if (preg_match('/^\\p{Z}*$/u', $content)) {
         Session::error(_t('Comment contains only whitespace/empty comment'));
         Utils::redirect($post->permalink);
     }
     /* Create comment object*/
     $comment = new Comment(array('post_id' => $post->id, 'name' => $name, 'email' => $email, 'url' => $url, 'ip' => sprintf("%u", ip2long($_SERVER['REMOTE_ADDR'])), 'content' => $content, 'status' => Comment::STATUS_UNAPPROVED, 'date' => HabariDateTime::date_create(), 'type' => Comment::COMMENT));
     // Should this really be here or in a default filter?
     // In any case, we should let plugins modify the status after we set it here.
     $user = User::identify();
     if ($user->loggedin && $comment->email == $user->email) {
         $comment->status = Comment::STATUS_APPROVED;
     }
     // Users need to have permission to add comments
     if (!$user->can('comment')) {
         Session::error(_t('You do not have permission to create comments.'));
         Utils::redirect($post->permalink);
     }
     // Allow themes to work with comment hooks
     Themes::create();
     // Allow plugins to change comment data and add commentinfo based on plugin-added form fields
     Plugins::act('comment_accepted', $comment, $this->handler_vars, $extra);
     $spam_rating = 0;
     $spam_rating = Plugins::filter('spam_filter', $spam_rating, $comment, $this->handler_vars, $extra);
     $comment->insert();
     $anchor = '';
     // If the comment was saved
     if ($comment->id && $comment->status != Comment::STATUS_SPAM) {
         $anchor = '#comment-' . $comment->id;
         // store in the user's session that this comment is pending moderation
         if ($comment->status == Comment::STATUS_UNAPPROVED) {
             Session::notice(_t('Your comment is pending moderation.'), 'comment_' . $comment->id);
         }
         // if no cookie exists, we should set one
         // but only if the user provided some details
         $cookie = 'comment_' . Options::get('GUID');
         if (!User::identify()->loggedin && !isset($_COOKIE[$cookie]) && (!empty($name) || !empty($email) || !empty($url))) {
             $cookie_content = $comment->name . '#' . $comment->email . '#' . $comment->url;
             $site_url = Site::get_path('base', true);
             setcookie($cookie, $cookie_content, time() + 31536000, $site_url);
         }
     }
     // Return the commenter to the original page.
     Utils::redirect($post->permalink . $anchor);
 }
Ejemplo n.º 13
0
	function upload( $photo, $title = '', $description = '', $tags = '', $perms = '', $async = 1, &$info = null )
	{
		$store = HABARI_PATH . '/' . Site::get_path( 'user' ) . '/cache';
		if ( !is_dir( $store ) ){
			mkdir( $store, 0777 );
		}
		$params = array( 'auth_token' => $this->cachedToken() );
		$url = InputFilter::parse_url( 'file://' . $photo );
		if ( isset( $url['scheme'] ) ){
			$localphoto = fopen( HABARI_PATH . '/' . $photo, 'r' );
			$store = tempnam( $store, 'G2F' );
			file_put_contents( $store, $localphoto );
			fclose( $localphoto );
			$params['photo'] = $store;
		}
		else{
			$params['photo'] = $photo;
		}

		$info = filesize( $params['photo'] );

		if ( $title ){
			$params['title'] = $title;
		}

		if ( $description ){
			$params['description'] = $description;
		}

		if ( $tags ){
			$params['tags'] = $tags;
		}

		if ( $perms ){
			if ( isset( $perms['is_public'] ) ){
				$params['is_public'] = $perms['is_public'];
			}
			if ( isset( $perms['is_friend'] ) ){
				$params['is_friend'] = $perms['is_friend'];
			}
			if ( isset( $perms['is_family'] ) ){
				$params['is_family'] = $perms['is_family'];
			}
		}

		if ( $async ){
			$params['async'] = $async;
		}
		// call the upload method.
		$xml = $this->call( 'upload', $params );

		if ( $store ){
			unlink( $store );
		}

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}

		if ( $async ){
			return( (string)$xml->ticketid );
		}
		else{
			return( (string)$xml->photoid );
		}
	}
 public function action_template_header()
 {
     //Cache::expire( self::$cache_name . '_js' );
     //Cache::expire( self::$cache_name . '_css' );
     // try to disable output_compression (may not have an effect)
     ini_set('zlib.output_compression', '0');
     $modified_js = Stack::get_sorted_stack('template_header_javascript');
     foreach ($modified_js as $key => $value) {
         Stack::remove('template_header_javascript', $key);
     }
     Stack::add('template_header_javascript', Site::get_url('user') . '/files/minified.js', 'Minified');
     $modified_css = Stack::get_sorted_stack('template_stylesheet');
     $css = array();
     foreach ($modified_css as $key => $value) {
         $css[] = $value[0];
         Stack::remove('template_stylesheet', $key);
     }
     Stack::add('template_stylesheet', array(Site::get_url('user') . "/files/minified.css", 'screen'), 'style');
     /*
      * If we have the files or the cache havent expired don't create new files.
      */
     if (!file_exists(site::get_dir('user') . '/files/minified.css') || !file_exists(site::get_dir('user') . '/files/minified.js') || (!Cache::has(self::$cache_name . '_js') || !Cache::has(self::$cache_name . '_css'))) {
         /* Taken from min/index.php */
         define('MINIFY_MIN_DIR', dirname(__FILE__) . '/min/');
         // load config
         require MINIFY_MIN_DIR . '/config.php';
         // setup include path
         set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
         require 'Minify.php';
         Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
         Minify::setCache(isset($min_cachePath) ? $min_cachePath : '', $min_cacheFileLocking);
         if ($min_documentRoot) {
             $_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
         } elseif (0 === stripos(PHP_OS, 'win')) {
             Minify::setDocRoot();
             // IIS may need help
         }
         $min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
         // Using jsmin+ 1.3
         $min_serveOptions['minifiers']['application/x-javascript'] = array('JSMinPlus', 'minify');
         /* Javascript */
         if (!Cache::has(self::$cache_name . '_js') || !file_exists(site::get_dir('user') . '/files/minified.js')) {
             $js_stack = array();
             foreach ($modified_js as $js) {
                 $js_stack[] = Site::get_path('base') . str_replace(Site::get_url('habari') . '/', '', $js);
             }
             $options = array('files' => $js_stack, 'encodeOutput' => false, 'quiet' => true);
             $result = Minify::serve('Files', $options);
             file_put_contents(site::get_dir('user') . '/files/minified.js', $result['content']);
             Cache::set(self::$cache_name . '_js', 'true', Options::get('minification__expire'));
         }
         /* CSS */
         if (!Cache::has(self::$cache_name . '_css') || !file_exists(site::get_dir('user') . '/files/minified.css')) {
             $css_stack = array();
             foreach ($css as $file) {
                 $css_stack[] = Site::get_path('base') . str_replace(Site::get_url('habari') . '/', '', $file);
             }
             $options = array('files' => $css_stack, 'encodeOutput' => false, 'quiet' => true);
             // handle request
             $result = Minify::serve('Files', $options);
             file_put_contents(site::get_dir('user') . '/files/minified.css', $result['content']);
             Cache::set(self::$cache_name . '_css', 'true', Options::get('minification__expire'));
         }
     }
 }
Ejemplo n.º 15
0
 /**
  * Receive a Pingback via XMLRPC
  * @param array $params An array of XMLRPC parameters from the remote call
  * @return string The success state of the pingback
  */
 public function xmlrpc_pingback__ping($params)
 {
     try {
         list($source_uri, $target_uri) = $params;
         // This should really be done by an Habari core function
         $target_parse = InputFilter::parse_url($target_uri);
         $target_stub = $target_parse['path'];
         $base_url = Site::get_path('base', TRUE);
         if ('/' != $base_url) {
             $target_stub = str_replace($base_url, '', $target_stub);
         }
         $target_stub = trim($target_stub, '/');
         if (strpos($target_stub, '?') !== FALSE) {
             list($target_stub, $query_string) = explode('?', $target_stub);
         }
         // Can this be used as a target?
         $target_slug = URL::parse($target_stub)->named_arg_values['slug'];
         if ($target_slug === FALSE) {
             throw new XMLRPCException(33);
         }
         // Does the target exist?
         $target_post = Post::get(array('slug' => $target_slug));
         if ($target_post === FALSE) {
             throw new XMLRPCException(32);
         }
         // Is comment allowed?
         if ($target_post->info->comments_disabled) {
             throw new XMLRPCException(33);
         }
         // Is this Pingback already registered?
         if (Comments::get(array('post_id' => $target_post->id, 'url' => $source_uri, 'type' => Comment::PINGBACK))->count() > 0) {
             throw new XMLRPCException(48);
         }
         // Retrieve source contents
         $rr = new RemoteRequest($source_uri);
         $rr->execute();
         if (!$rr->executed()) {
             throw new XMLRPCException(16);
         }
         $source_contents = $rr->get_response_body();
         // encoding is converted into internal encoding.
         // @todo check BOM at beginning of file before checking for a charset attribute
         $habari_encoding = MultiByte::hab_encoding();
         if (preg_match("/<meta[^>]+charset=([A-Za-z0-9\\-\\_]+)/i", $source_contents, $matches) !== FALSE && strtolower($habari_encoding) != strtolower($matches[1])) {
             $ret = MultiByte::convert_encoding($source_contents, $habari_encoding, $matches[1]);
             if ($ret !== FALSE) {
                 $source_contents = $ret;
             }
         }
         // Find the page's title
         preg_match('/<title>(.*)<\\/title>/is', $source_contents, $matches);
         $source_title = $matches[1];
         // Find the reciprocal links and their context
         preg_match('/<body[^>]*>(.+)<\\/body>/is', $source_contents, $matches);
         $source_contents_filtered = preg_replace('/\\s{2,}/is', ' ', strip_tags($matches[1], '<a>'));
         if (!preg_match('%.{0,100}?<a[^>]*?href\\s*=\\s*("|\'|)' . $target_uri . '\\1[^>]*?' . '>(.+?)</a>.{0,100}%s', $source_contents_filtered, $source_excerpt)) {
             throw new XMLRPCException(17);
         }
         /** Sanitize Data */
         $source_excerpt = '...' . InputFilter::filter($source_excerpt[0]) . '...';
         $source_title = InputFilter::filter($source_title);
         $source_uri = InputFilter::filter($source_uri);
         /* Sanitize the URL */
         if (!empty($source_uri)) {
             $parsed = InputFilter::parse_url($source_uri);
             if ($parsed['is_relative']) {
                 // guess if they meant to use an absolute link
                 $parsed = InputFilter::parse_url('http://' . $source_uri);
                 if (!$parsed['is_error']) {
                     $source_uri = InputFilter::glue_url($parsed);
                 } else {
                     // disallow relative URLs
                     $source_uri = '';
                 }
             }
             if ($parsed['is_pseudo'] || $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') {
                 // allow only http(s) URLs
                 $source_uri = '';
             } else {
                 // reconstruct the URL from the error-tolerant parsing
                 // http:moeffju.net/blog/ -> http://moeffju.net/blog/
                 $source_uri = InputFilter::glue_url($parsed);
             }
         }
         // Add a new pingback comment
         $pingback = new Comment(array('post_id' => $target_post->id, 'name' => $source_title, 'email' => '', 'url' => $source_uri, 'ip' => sprintf("%u", ip2long($_SERVER['REMOTE_ADDR'])), 'content' => $source_excerpt, 'status' => Comment::STATUS_UNAPPROVED, 'date' => HabariDateTime::date_create(), 'type' => Comment::PINGBACK));
         $pingback->insert();
         // Respond to the Pingback
         return 'The pingback has been registered';
     } catch (XMLRPCException $e) {
         $e->output_fault_xml();
     }
 }
Ejemplo n.º 16
0
	/**
	 * out_path echos a URL path
	 * @param string the URL path to display
	 * @param bool whether or not to include a trailing slash.  Default: No
	 */
	public static function out_path( $path, $trail = false )
	{
		echo Site::get_path( $path, $trail );
	}
 /**
  * Initialise the file paths
  * 
  */
 protected function init_backend()
 {
     $this->_root_path = Options::get(self::PATH_OPTION);
     if (!$this->_root_path) {
         // default to this directory
         $this->_root_path = HABARI_PATH . '/' . Site::get_path('user', true) . '/plugins/multisearch/indexes/';
         Options::set(self::PATH_OPTION, $this->_root_path);
     }
     if (Options::get(self::ENGINE_OPTION)) {
         $this->load_backend(Options::get(self::ENGINE_OPTION));
     }
 }
Ejemplo n.º 18
0
 /**
  * function add_comment
  * adds a comment to a post, if the comment content is not NULL
  * @param array An associative array of content found in the $_POST array
  */
 public function act_add_comment()
 {
     Utils::check_request_method(array('POST'));
     $defaults = array('name' => '', 'email' => '', 'url' => '', 'content' => '');
     // We need to get the post anyway to redirect back to the post page.
     $post = Post::get(array('id' => $this->handler_vars['id']));
     if (!$post) {
         // trying to comment on a non-existent post?  Weirdo.
         header('HTTP/1.1 403 Forbidden', true, 403);
         die;
     }
     // make sure all our default values are set so we don't throw undefined index errors
     foreach ($defaults as $k => $v) {
         if (!isset($this->handler_vars[$k])) {
             $this->handler_vars[$k] = $v;
         }
     }
     // let's do some basic sanity checking on the submission
     if (1 == Options::get('comments_require_id') && (empty($this->handler_vars['name']) || empty($this->handler_vars['email']))) {
         Session::error(_t('Both name and e-mail address must be provided.'));
     }
     if (empty($this->handler_vars['content'])) {
         Session::error(_t('You did not provide any content for your comment!'));
     }
     if (Session::has_errors()) {
         // save whatever was provided in session data
         Session::add_to_set('comment', $this->handler_vars['name'], 'name');
         Session::add_to_set('comment', $this->handler_vars['email'], 'email');
         Session::add_to_set('comment', $this->handler_vars['url'], 'url');
         Session::add_to_set('comment', $this->handler_vars['content'], 'content');
         // now send them back to the form
         Utils::redirect($post->permalink . '#respond');
     }
     if ($post->info->comments_disabled) {
         // comments are disabled, so let's just send
         // them back to the post's permalink
         Session::error(_t('Comments on this post are disabled!'));
         Utils::redirect($post->permalink);
     }
     /* Sanitize data */
     foreach ($defaults as $k => $v) {
         $this->handler_vars[$k] = InputFilter::filter($this->handler_vars[$k]);
     }
     /* Sanitize the URL */
     if (!empty($this->handler_vars['url'])) {
         $url = $this->handler_vars['url'];
         $parsed = InputFilter::parse_url($url);
         if ($parsed['is_relative']) {
             // guess if they meant to use an absolute link
             $parsed = InputFilter::parse_url('http://' . $url);
             if (!$parsed['is_error']) {
                 $url = InputFilter::glue_url($parsed);
             } else {
                 // disallow relative URLs
                 $url = '';
             }
         }
         if ($parsed['is_pseudo'] || $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') {
             // allow only http(s) URLs
             $url = '';
         } else {
             // reconstruct the URL from the error-tolerant parsing
             // http:moeffju.net/blog/ -> http://moeffju.net/blog/
             $url = InputFilter::glue_url($parsed);
         }
         $this->handler_vars['url'] = $url;
     }
     if (preg_match('/^\\p{Z}*$/u', $this->handler_vars['content'])) {
         Session::error(_t('Comment contains only whitespace/empty comment'));
         Utils::redirect($post->permalink);
     }
     /* Create comment object*/
     $comment = new Comment(array('post_id' => $this->handler_vars['id'], 'name' => $this->handler_vars['name'], 'email' => $this->handler_vars['email'], 'url' => $this->handler_vars['url'], 'ip' => sprintf("%u", ip2long($_SERVER['REMOTE_ADDR'])), 'content' => $this->handler_vars['content'], 'status' => Comment::STATUS_UNAPPROVED, 'date' => HabariDateTime::date_create(), 'type' => Comment::COMMENT));
     // Should this really be here or in a default filter?
     // In any case, we should let plugins modify the status after we set it here.
     $user = User::identify();
     if ($user->loggedin && $comment->email == $user->email) {
         $comment->status = Comment::STATUS_APPROVED;
     }
     // Allow themes to work with comment hooks
     Themes::create();
     $spam_rating = 0;
     $spam_rating = Plugins::filter('spam_filter', $spam_rating, $comment, $this->handler_vars);
     $comment->insert();
     $anchor = '';
     // If the comment was saved
     if ($comment->id) {
         $anchor = '#comment-' . $comment->id;
         // store in the user's session that this comment is pending moderation
         if ($comment->status == Comment::STATUS_UNAPPROVED) {
             Session::notice(_t('Your comment is pending moderation.'), 'comment_' . $comment->id);
         }
         // if no cookie exists, we should set one
         // but only if the user provided some details
         $cookie = 'comment_' . Options::get('GUID');
         if (!isset($_COOKIE[$cookie]) && (!empty($this->handler_vars['name']) || !empty($this->handler_vars['email']) || !empty($this->handler_vars['url']))) {
             $cookie_content = $comment->name . '#' . $comment->email . '#' . $comment->url;
             $site_url = Site::get_path('base', true);
             setcookie($cookie, $cookie_content, time() + 31536000, $site_url);
         }
     }
     // Return the commenter to the original page.
     Utils::redirect($post->permalink . $anchor);
 }
 /**
  * Returns an array of URLs correlating to each directory found in the
  * default Habari Silo path in the form:
  *
  * URL => "Habari Silo:/path/to/dir/"
  *
  * This is for use in a <select> form element.
  *
  * @access private
  * @return array
  */
 private static function siloDirs()
 {
     // Get a list of all the directories available in the loaded Habari Silo
     $user_path = HABARI_PATH . '/' . Site::get_path('user') . '/files/';
     // Default Habari silo path
     $user_url = Site::get_url('user') . '/files/';
     // Default Habari Silo URL
     $dirs = array($user_url => 'Habari Silo:/ ');
     $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($user_path), RecursiveIteratorIterator::SELF_FIRST);
     foreach ($objects as $name => $object) {
         if ($object->isDir()) {
             if ($object->getFilename() != '.deriv') {
                 // Exclude the .deriv dirs created by Habari Silo plugin
                 $newname = str_replace($user_path, '', $name) . '/';
                 $newurl = str_replace($user_path, $user_url, $name) . '/';
                 $dirs[$newurl] = 'Habari Silo:/' . $newname;
             }
         }
     }
     return $dirs;
 }
Ejemplo n.º 20
0
 /**
  * Parses the requested URL.  Automatically
  * translates URLs coming in from mod_rewrite and parses
  * out any action and parameters in the slug.
  */
 public static function parse_request()
 {
     /* Local scope variable caching */
     $controller = Controller::instance();
     /* Grab the base URL from the Site class */
     $controller->base_url = Site::get_path('base', true);
     /* If we're installed in a directory subsite, add that to the base_url */
     //		$controller->base_url .= Site::$config_urldir;
     /* Start with the entire URL coming from web server... */
     if (isset($_SERVER['REQUEST_URI'])) {
         $start_url = $_SERVER['REQUEST_URI'];
     } else {
         $start_url = $_SERVER['SCRIPT_NAME'];
         if (isset($_SERVER['PATH_INFO'])) {
             $start_url .= $_SERVER['PATH_INFO'];
         }
         // the query string is included in REQUEST_URI, we only need to append it if we're building the URI ourselves
         if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') {
             $start_url .= '?' . $_SERVER['QUERY_STRING'];
         }
     }
     /* Strip out the base URL from the requested URL */
     /* but only if the base URL isn't / */
     if ('/' != $controller->base_url) {
         if (substr($controller->base_url, -1) == '/') {
             $controller->base_url = substr($controller->base_url, 0, -1);
         }
         $start_url = preg_replace('#^' . preg_quote($controller->base_url, '#') . '#i', '', $start_url);
     }
     // undo &amp;s
     $start_url = str_replace('&amp;', '&', $start_url);
     /* Trim off any leading or trailing slashes */
     $start_url = trim($start_url, '/');
     /* Allow plugins to rewrite the stub before it's passed through the rules */
     $start_url = Plugins::filter('rewrite_request', $start_url);
     $controller->stub = $start_url;
     /* Grab the URL filtering rules from DB */
     $matched_rule = URL::parse($controller->stub);
     if ($matched_rule === false) {
         $matched_rule = URL::set_404();
     }
     /* OK, we have a matching rule.  Set the action and create a handler */
     $controller->action = $matched_rule->action;
     $handler = $matched_rule->handler;
     // @todo This is pretty kludgy.  If there's no namespace in the handler class, add one.
     if (strpos($handler, '\\') === false) {
         $handler = '\\Habari\\' . $handler;
     }
     $controller->handler = new $handler();
     /* Insert the regexed submatches as the named parameters */
     $controller->handler->handler_vars['entire_match'] = $matched_rule->entire_match;
     // The entire matched string is returned at index 0
     $controller->handler->handler_vars['matched_rule'] = $matched_rule;
     foreach ($matched_rule->named_arg_values as $named_arg_key => $named_arg_value) {
         $controller->handler->handler_vars[$named_arg_key] = $named_arg_value;
     }
     /* Also, we musn't forget to add the GET and POST vars into the action's settings array */
     $handler_vars = new SuperGlobal($controller->handler->handler_vars);
     //$handler_vars = $handler_vars->merge( $_GET, $_POST );
     $controller->handler->handler_vars = $handler_vars;
     return true;
 }
Ejemplo n.º 21
0
	/**
	 * Receive a Pingback via XMLRPC
	 * @param array $params An array of XMLRPC parameters from the remote call
	 * @return string The success state of the pingback
	 */
	public function xmlrpc_pingback__ping( $params )
	{
		try {
			list( $source_uri, $target_uri )= $params;

			// This should really be done by an Habari core function
			$target_parse = InputFilter::parse_url( $target_uri );
			$target_stub = $target_parse['path'];
			$base_url = Site::get_path( 'base', true );

			if ( '/' != $base_url) {
				$target_stub = str_replace( $base_url, '', $target_stub );
			}

			$target_stub = trim( $target_stub, '/' );

			if ( strpos( $target_stub, '?' ) !== false ) {
				list( $target_stub, $query_string )= explode( '?', $target_stub );
			}

			// Can this be used as a target?
			$target_slug = URL::parse( $target_stub )->named_arg_values['slug'];

			if ( $target_slug === false ) {
				throw new XMLRPCException( 33 );
			}

			// Does the target exist?
			$target_post = Post::get( array( 'slug' => $target_slug ) );

			if ( $target_post === false ) {
				throw new XMLRPCException( 32 );
			}

			// Is comment allowed?
			if ( $target_post->info->comments_disabled ) {
				throw new XMLRPCException( 33 );
			}

			// Is this Pingback already registered?
			if ( Comments::get( array( 'post_id' => $target_post->id, 'url' => $source_uri, 'type' => Comment::PINGBACK ) )->count() > 0 ) {
				throw new XMLRPCException( 48 );
			}

			// Retrieve source contents
			try {
				$rr = new RemoteRequest( $source_uri );
				$rr->execute();
				if ( ! $rr->executed() ) {
					throw new XMLRPCException( 16 );
				}
				$source_contents = $rr->get_response_body();
				$headers = $rr->get_response_headers();
			}
			catch ( XMLRPCException $e ) {
				// catch our special type of exception and re-throw it
				throw $e;
			}
			catch ( Exception $e ) {
				throw new XMLRPCException( -32300 );
			}

			// Encoding is converted into internal encoding.
			// First, detect the source string's encoding
			$habari_encoding = strtoupper( MultiByte::hab_encoding() );
			$source_encoding = 'Windows-1252';
			// Is the charset in the headers?
			if ( isset( $headers['Content-Type'] ) && strpos( $headers['Content-Type'], 'charset' ) !== false ) {
				// This regex should be changed to meet the HTTP spec at some point
				if ( preg_match("/charset[\x09\x0A\x0C\x0D\x20]*=[\x09\x0A\x0C\x0D\x20]*('?)([A-Za-z0-9\-\_]+)\1/i", $headers['Content-Type'], $matches ) ) {
					$source_encoding = strtoupper( $matches[2] );
				}
			}
			// Can we tell the charset from the stream itself?
			else if ( ( $enc = MultiByte::detect_bom_encoding( $source_contents ) ) !== false ) {
				$source_encoding = $enc;
			}
			// Is the charset in a meta tag?
			else if ( preg_match( "/<meta[^>]+charset[\x09\x0A\x0C\x0D\x20]*=[\x09\x0A\x0C\x0D\x20]*([\"']?)([A-Za-z0-9\-\_]+)\1/i", $source_contents, $matches ) ) {
				$source_encoding = strtoupper( $matches[2] );
				if (in_array($source_encoding, array("UTF-16", "UTF-16BE", "UTF-16LE"))) {
					$source_encoding = "UTF-8";
				}
			}
			// Then, convert the string
			$ret = MultiByte::convert_encoding( $source_contents, $habari_encoding, $source_encoding );
			if ( $ret !== false ) {
				$source_contents = $ret;
			}

			// Find the page's title
			preg_match( '/<title>(.*)<\/title>/is', $source_contents, $matches );
			$source_title = $matches[1];

			// Find the reciprocal links and their context
			preg_match( '/<body[^>]*>(.+)<\/body>/is', $source_contents, $matches );
			$source_contents_filtered = preg_replace( '/\s{2,}/is', ' ', strip_tags( $matches[1], '<a>' ) );

			// Get rid of all the non-recriprocal links
			$ht = new HTMLTokenizer( trim( $source_contents_filtered ) );
			$set = $ht->parse();
			$all_links = $set->slice( 'a', array() );
			$keep_links = $set->slice( 'a', array( 'href' => $target_uri ) );
			$bad_links = array_diff( $all_links, $keep_links );
			foreach( $bad_links as $link ) {
				$link->tokenize_replace( '' );
				$set->replace_slice( $link );
			}
			$source_contents_filtered = (string)$set;

			// Get the excerpt
			if ( !preg_match( '%.{0,100}?<a[^>]*?href\\s*=\\s*("|\'|)' . $target_uri . '\\1[^>]*?'.'>(.+?)</a>.{0,100}%s', $source_contents_filtered, $source_excerpt ) ) {
				throw new XMLRPCException( 17 );
			}

			/** Sanitize Data */
			$source_excerpt = '&hellip;' . InputFilter::filter( $source_excerpt[0] ) . '&hellip;';
			$source_title = InputFilter::filter($source_title);
			$source_uri = InputFilter::filter($source_uri);

			/* Sanitize the URL */
			if (!empty($source_uri)) {
				$parsed = InputFilter::parse_url( $source_uri );
				if ( $parsed['is_relative'] ) {
					// guess if they meant to use an absolute link
					$parsed = InputFilter::parse_url( 'http://' . $source_uri );
					if ( ! $parsed['is_error'] ) {
						$source_uri = InputFilter::glue_url( $parsed );
					}
					else {
						// disallow relative URLs
						$source_uri = '';
					}
				}
				if ( $parsed['is_pseudo'] || ( $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https' ) ) {
					// allow only http(s) URLs
					$source_uri = '';
				}
				else {
					// reconstruct the URL from the error-tolerant parsing
					// http:moeffju.net/blog/ -> http://moeffju.net/blog/
					$source_uri = InputFilter::glue_url( $parsed );
				}
			}

			// Add a new pingback comment
			$pingback = new Comment( array(
				'post_id'	=>	$target_post->id,
				'name'		=>	$source_title,
				'email'		=>	'',
				'url'		=>	$source_uri,
				'ip'		=>	Utils::get_ip(),
				'content'	=>	$source_excerpt,
				'status'	=>	Comment::STATUS_UNAPPROVED,
				'date'		=>	HabariDateTime::date_create(),
				'type' 		=> 	Comment::PINGBACK,
				) );

			$pingback->insert();

			// Respond to the Pingback
			return 'The pingback has been registered';
		}
		catch ( XMLRPCException $e ) {
			$e->output_fault_xml();
		}
	}
Ejemplo n.º 22
0
 /**
  * Validate database credentials for SQLite
  * Try to connect and verify if database name exists
  */
 public function ajax_check_sqlite_credentials()
 {
     $db_file = $_POST['file'];
     $xml = new \SimpleXMLElement('<response></response>');
     // Missing anything?
     if (!isset($db_file)) {
         $xml->addChild('status', 0);
         $xml_error = $xml->addChild('error');
         $xml_error->addChild('id', '#databasefile');
         $xml_error->addChild('message', _t('The database file was left empty.'));
     }
     if (!isset($xml_error)) {
         if ($db_file == basename($db_file)) {
             // The filename was given without a path
             $db_file = Site::get_path('user', true) . $db_file;
         }
         if (!is_writable(dirname($db_file))) {
             $xml->addChild('status', 0);
             $xml_error = $xml->addChild('error');
             $xml_error->addChild('id', '#databasefile');
             $xml_error->addChild('message', _t('Cannot write to %s directory. SQLite requires that the directory that holds the DB file be writable by the web server.', array(dirname($db_file))));
         } elseif (file_exists(Site::get_path('user', true) . $db_file) && !is_writable(Site::get_path('user', true) . $db_file)) {
             $xml->addChild('status', 0);
             $xml_error = $xml->addChild('error');
             $xml_error->addChild('id', '#databasefile');
             $xml_error->addChild('message', _t('Cannot write to %s. The SQLite data file is not writable by the web server.', array($db_file)));
         } else {
             // Can we connect to the DB?
             $pdo = 'sqlite:' . $db_file;
             $connect = DB::connect($pdo, null, null);
             // Disconnect, but no longer delete the file - it could already have contents!
             DB::disconnect();
             switch ($connect) {
                 case true:
                     // We were able to connect to an existing database file.
                     $xml->addChild('status', 1);
                     break;
                 default:
                     // We can't create the database file, send an error message.
                     $xml->addChild('status', 0);
                     $xml_error = $xml->addChild('error');
                     // TODO: Add error codes handling for user-friendly messages
                     $xml_error->addChild('id', '#databasefile');
                     $xml_error->addChild('message', $connect->getMessage());
             }
         }
     }
     $xml = $xml->asXML();
     ob_clean();
     header("Content-type: application/xml");
     header("Cache-Control: no-cache");
     print $xml;
 }
 /**
  * function action_user_logout
  * removes the persistent cookie when the user logs out
  * @param user User the user that is logging out
  **/
 public function action_user_logout($user)
 {
     $cookiename = 'P_' . md5(Options::get('GUID') . '_Persistence');
     if (!isset($_COOKIE[$cookiename])) {
         return;
     }
     $cookie = $_COOKIE[$cookiename];
     $info = 'persistence_' . $cookie;
     // remove the info record for this cookie
     unset($user->info->{$info});
     // commit the change
     $user->update();
     // remove the cookie from the user's PC
     setcookie($cookiename, 'empty', time() - 3600, Site::get_path(' base', true));
 }
Ejemplo n.º 24
0
 /**
  * Parses the requested URL.  Automatically
  * translates URLs coming in from mod_rewrite and parses
  * out any action and parameters in the slug.
  */
 public static function parse_request()
 {
     /* Local scope variable caching */
     $controller = Controller::instance();
     /* Grab the base URL from the Site class */
     $controller->base_url = Site::get_path('base', true);
     /* Start with the entire URL coming from web server... */
     $start_url = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['SCRIPT_NAME'] . (isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '') . (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' ? '?' . $_SERVER['QUERY_STRING'] : '');
     /* Strip out the base URL from the requested URL */
     /* but only if the base URL isn't / */
     if ('/' != $controller->base_url) {
         $start_url = str_replace($controller->base_url, '', $start_url);
     }
     // undo &amp;s
     $start_url = str_replace('&amp;', '&', $start_url);
     /* Trim off any leading or trailing slashes */
     $start_url = trim($start_url, '/');
     /* Allow plugins to rewrite the stub before it's passed through the rules */
     $start_url = Plugins::filter('rewrite_request', $start_url);
     $controller->stub = $start_url;
     /* Grab the URL filtering rules from DB */
     $matched_rule = URL::parse($controller->stub);
     if ($matched_rule === FALSE) {
         $matched_rule = URL::set_404();
     }
     /* OK, we have a matching rule.  Set the action and create a handler */
     $controller->action = $matched_rule->action;
     $controller->handler = new $matched_rule->handler();
     /* Insert the regexed submatches as the named parameters */
     $controller->handler->handler_vars['entire_match'] = $matched_rule->entire_match;
     // The entire matched string is returned at index 0
     foreach ($matched_rule->named_arg_values as $named_arg_key => $named_arg_value) {
         $controller->handler->handler_vars[$named_arg_key] = $named_arg_value;
     }
     /* Also, we musn't forget to add the GET and POST vars into the action's settings array */
     $handler_vars = new SuperGlobal($controller->handler->handler_vars);
     $handler_vars = $handler_vars->merge($_GET, $_POST);
     $controller->handler->handler_vars = $handler_vars;
     return true;
 }
Ejemplo n.º 25
0
 /**
  * Add a comment to the site
  *
  * @param mixed $post A Post object instance or Post object id
  * @param string $name The commenter's name
  * @param string $email The commenter's email address
  * @param string $url The commenter's website URL
  * @param string $content The comment content
  * @param array $extra An associative array of extra values that should be considered
  */
 function add_comment($post, $name = null, $email = null, $url = null, $content = null, $extra = null)
 {
     if (is_numeric($post)) {
         $post = Post::get(array('id' => $post));
     }
     if (!$post instanceof Post) {
         // Not sure what you're trying to pull here, but that's no good
         header('HTTP/1.1 403 Forbidden', true, 403);
         die;
     }
     /* Sanitize data */
     foreach (array('name', 'url', 'email', 'content') as $k) {
         ${$k} = InputFilter::filter(${$k});
     }
     // there should never be any HTML in the name, so do some extra filtering on it
     $name = strip_tags(html_entity_decode($name, ENT_QUOTES, 'UTF-8'));
     /* Sanitize the URL */
     if (!empty($url)) {
         $parsed = InputFilter::parse_url($url);
         if ($parsed['is_relative']) {
             // guess if they meant to use an absolute link
             $parsed = InputFilter::parse_url('http://' . $url);
             if (!$parsed['is_error']) {
                 $url = InputFilter::glue_url($parsed);
             } else {
                 // disallow relative URLs
                 $url = '';
             }
         }
         if ($parsed['is_pseudo'] || $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') {
             // allow only http(s) URLs
             $url = '';
         } else {
             // reconstruct the URL from the error-tolerant parsing
             // http:moeffju.net/blog/ -> http://moeffju.net/blog/
             $url = InputFilter::glue_url($parsed);
         }
     }
     /* Create comment object*/
     $comment = new Comment(array('post_id' => $post->id, 'name' => $name, 'email' => $email, 'url' => $url, 'ip' => Utils::get_ip(), 'content' => $content, 'status' => Comment::status('approved'), 'date' => DateTime::create(), 'type' => Comment::type('comment')));
     // Should this really be here or in a default filter?
     // In any case, we should let plugins modify the status after we set it here.
     $user = User::identify();
     if ($user->loggedin && $comment->email == $user->email) {
         $comment->status = 'approved';
     }
     // Allow themes to work with comment hooks
     Themes::create();
     // Allow plugins to change comment data and add commentinfo based on plugin-added form fields
     Plugins::act('comment_accepted', $comment, $this->handler_vars, $extra);
     $spam_rating = 0;
     $spam_rating = Plugins::filter('spam_filter', $spam_rating, $comment, $this->handler_vars, $extra);
     if ($spam_rating >= Options::get('spam_percentage', 100)) {
         $comment->status = 'spam';
     }
     $comment->insert();
     $anchor = '';
     // If the comment was saved
     if ($comment->id && $comment->status != 'spam') {
         $anchor = '#comment-' . $comment->id;
         // store in the user's session that this comment is pending moderation
         if ($comment->status == 'unapproved') {
             Session::notice(_t('Your comment is pending moderation.'), 'comment_' . $comment->id);
         }
         // if no cookie exists, we should set one
         // but only if the user provided some details
         $cookie_name = 'comment_' . Options::get('public-GUID');
         // build the string we store for the cookie
         $cookie_content = implode('#', array($comment->name, $comment->email, $comment->url));
         // if the user is not logged in and there is no cookie OR the cookie differs from the current set
         if (User::identify()->loggedin == false && (!isset($_COOKIE[$cookie_name]) || $_COOKIE[$cookie_name] != $cookie_content)) {
             // update the cookie
             setcookie($cookie_name, $cookie_content, time() + DateTime::YEAR, Site::get_path('base', true));
         }
     }
     // Return the commenter to the original page.
     Utils::redirect($post->permalink . $anchor);
 }