<?php
/**
 * MvBlog -- An open source no-nosense blogtool
 *
 * Copyright (C) 2005-2008, Michiel van Baak
 * Michiel van Baak <mvanbaak@users.sourceforge.net>
 *
 * See http://www.mvblog.org for more information on MvBlog.
 * That page also provides Bugtrackers, Filereleases etc.
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2. See the LICENSE file
 * at the top of the source tree.
 *
 * @package MvBlog
 * @author Michiel van Baak
 * @version %%VERSION%%
 * @copyright 2005-2008 Michiel van Baak
 */

/*
 * Start the autoloader, so we never have to include anything
 */
require_once("mvblog_autoloader.php");
$mvblog_AutoLoader = new mvblog_AutoLoader();

$pathInfo = pathinfo(__FILE__);
$mvblog_AutoLoader->registerPath($pathInfo["dirname"], "%s.php", mvblog_AutoLoader::OPT_LOWERCASE);

// Register the AutoLoader object as the autoloader.
function __autoload($className) {
  global $mvblog_AutoLoader;
  $mvblog_AutoLoader->autoload($className);
}

/* Start heavy error reporting if we're on a dev site */
MvBlog_debug::start_development(False);

/* Read the configuration file */
$configfile = dirname(dirname(__FILE__)."../")."/conf/mvblog.ini";
$availSettings = array(
	"general" => array(
		"debug"    => array("type" => mvblog_IniFileReader::TYPE_BOOL,   "default" => "no"),
	),
	"database" => array(
		"database" => array("type" => mvblog_IniFileReader::TYPE_STRING, "default" => "mvblog"),
		"hostname" => array("type" => mvblog_IniFileReader::TYPE_STRING, "default" => "localhost"),
		"username" => array("type" => mvblog_IniFileReader::TYPE_STRING, "default" => "mvblog"),
		"password" => array("type" => mvblog_IniFileReader::TYPE_STRING, "default" => "mvblog"),
		"type"     => array("type" => mvblog_IniFileReader::TYPE_STRING, "default" => "mysql"),
	),
);
$config = new mvblog_IniFileReader($availSettings, $configfile);

/**
 * Class that holds methods to create public site.
 * @package MvBlog
 */
Class MvBlog extends MvBlog_common {

	/* contstants */

	/* variables */
	/**
	 * @var string $lang Language of blog. Can be en_US or nl_NL for now
	 */
	public $lang       = "en_US";
	/* }}} */

	/* methods */

	/* __construct {{{ */
	/**
	 * Constructor to set some defaults
	 *
	 * @param string $basedir If set use this directory where MvBlog is located.
	 */
	public function __construct ($basedir="") {
		parent::__construct($basedir."plugins/");
		$this->log = new MvBlog_log($basedir, 0);
	}
	/* }}} */
	/* check_admin_logged_in() {{{ */
	/**
	 * Check to see if the admin session is set
	 */
	public function check_admin_logged_in() {
		if (!$_SESSION["author_id"]) {
			header("Location: login.php");
		}
	}
	/* }}} */
	/* blog_get_title() {{{ */
	/**
	 * get the blog title.
	 *
	 * @return string title or "blog" if no title set
	 */
	public function blog_get_title() {
		if ($this->settings["blogtitle"]) {
			$title = stripslashes($this->settings["blogtitle"]);
		} else {
			$title = "blog";
		}
		return $title;
	}
	/* }}} */
	/* blog_get_description() {{{ */
	/**
	 * Get blogsetting description from database
	 *
	 * @return string The blogdescription
	 */
	public function blog_get_description() {
		if ($this->settings["blogdescription"]) {
			$pagedescription = nl2br(stripslashes($this->settings["blogdescription"]));
		} else {
			$pagedescription = "";
		}
		return $pagedescription;
	}
	/* }}} */
	/* blog_content($start, $limit) {{{ */
	/**
	 *  main function to give user correct html depending on action etc
	 *
	 * @param int $start (optional) Start entry in recordset
	 * @param int $limit (optional) Number of records to show
	 */
	public function blog_content($start=0, $limit=0) {
		/* get limit from database, when no limit given by function call */
		if (!$limit) {
			if ($this->settings["postsperpage"]) {
				$limit = $this->settings["postsperpage"];
			} else {
				/* fall back to something sane if none found. fixes issue #25 */
				/* FB: 20070304: This shouldn't happen anymore, as there are now
								 default settings in MvBlog_common::_get_settings().
								 Keeping it anyway just to be sure/
				*/
				$limit = 20;
			}
		}
		// FB: 20070304: Check if key exists and strstr->strpos()
		// if (strstr($_REQUEST["action"], "view/")) {
		if (array_key_exists("action", $_REQUEST) && strpos($_REQUEST["action"], "view/") !== false) {
			$_REQUEST["id"] = (int)substr($_REQUEST["action"],5);
			$_REQUEST["action"] = "view";
		}

		// Determine the action.
		if (array_key_exists("action", $_REQUEST)) {
			$action = $_REQUEST["action"];
		} else {
			$action = ""; // Will be handled by the 'default' case in the switch below.
		}
		switch ($action) {
			/* user related functions */
			//this one is here for backward compatibiliy. Can be removed in release 4
			case "register_confirm" : $this->user_confirm();         break;
			//new user actions
			case "user_confirm"  : $this->user_confirm();            break;
			case "user_save"     : $this->user_save();               break;
			case "user_new"      : $this->user_edit(1);              break;
			case "user_login"    :
				if (array_key_exists("user", $_REQUEST) && $this->user_login($_REQUEST["user"])) {
					$this->get_articles($start, $limit);
				} else {
					echo gettext("wrong username/pass");
				}
				break;
			case "user_settings" : $this->user_edit(0);                break;
			/* article related functions */
			case "view"         : $this->show_article($_REQUEST["id"]);      break;
			case "viewdossier"  : $this->get_articles($start, $limit, 0, $_REQUEST["id"]);      break;
			case "post_comment" : $this->post_comment($_POST);               break;
			case "rss"          : header("Location: common/rss.php");        break;
			case "archive"      : $this->get_articles($start, $limit, 1);    break;
			case "archive_old"  : $this->get_articles($start, $limit, 4);    break;
			case "archive_cat"  :
				if (array_key_exists("c", $_REQUEST) && $_REQUEST["c"] == "aside") {
					$this->get_articles($start, $limit, 3);
				} else {
					$this->get_articles($start, $limit, 2);
				}
				break;
			default             : $this->get_articles($start, $limit);       break;
		}
	}
	/* }}} */
	/* get_articles($start, $limit, $archive) {{{ */
	/**
	 * show posts in pages or the archive
	 *
	 * @param int $start the starting point in the recordset
	 * @param int $limit the ammount of items to show
	 * @param int $archive type of archive. 0 = none, 1 = archive by date, 2 = archive by category, 3 = archive of asides, 4 = old old old
	 * @param int $dossier if not 0 show info about dossier
	 */
	public function get_articles($start, $limit, $archive=0, $dossier=0) {
		// FB: 20070304: Check key and set a default if not set.
		if (array_key_exists("top", $_REQUEST))
			$top = $_REQUEST["top"];

		if (!isset($top) || empty($top))
			$top = 1;

		//article url base
		if ($this->settings["cleanurl"])
			$link = "post/%d#READMORE";
		else
			$link = "index.php?action=view&amp;id=%d#READMORE";

		//category url base
		if ($this->settings["cleanurl"])
			$catlink = "category/%d";
		else
			$catlink = "index.php?action=archive_cat&amp;c=%d";

		$start = $top-1;

		$max_time = mktime(0, 0, 0, date("m"), date("d")+1, date("Y"));

		$options = array(
			"start"              => $start,
			"limit"              => $limit,
			"max_time"           => $max_time,
			"top"                => $top,
			"archive"            => $archive,
			"dossier"            => $dossier,
			"replace_references" => 1
		);
		foreach ($_REQUEST as $k=>$v)
			$options["urlparams"][$k] = $v;

		$posts = $this->_get_posts($options);

		echo $posts["title"];

		if (array_key_exists("desc", $posts))
			echo $posts["desc"];

		if ($posts["total_count"]) {
			foreach ($posts["posts"] as $row) {
				//get number of comments
				$ccquery = sprintf("SELECT COUNT(*) FROM comments WHERE articles_id = %d", $row["id"]);
				$ccq =& $this->db->query($ccquery);
				$comments_count = $ccq->fetchRow();
				?>
				<div class="log_post">
					<?php if ($row["aside"] !=1) { ?>
						<div class="log_post_head">
							<h1 class="log_post_h1"><a href="<?php echo sprintf($link, $row["id"]); ?>"><?php echo htmlspecialchars(stripslashes($row["title"])); ?></a></h1>
							<h2 class="log_post_h2"><?php echo gettext("category"); ?>:&nbsp;
								<?php
								$categories = explode(",", $row["categories_ids"]);
								foreach ($categories as $v) {
									if (array_key_exists($v, $this->categories) && $this->categories[$v]["icon"] && $this->settings["show_cat_icons"])
										echo "<a href=\"".sprintf($catlink, $v)."\"><img src=\"images/categories/".$this->categories[$v]["icon"]."\" title=\"".htmlspecialchars($this->categories[$v]["name"])."\" alt=\"".htmlspecialchars($this->categories[$v]["name"])."\" class=\"category_icon\" /></a>&nbsp;";
									elseif (array_key_exists($v, $this->categories))
										echo "<a href=\"".sprintf($catlink, $v)."\">".htmlspecialchars($this->categories[$v]["name"])."</a>&nbsp;";
								}
								?>
							</h2>
						</div>
					<?php } ?>
					<div class="log_post_body">
						<?php if ($row["aside"]) { ?>
							<div class="log_post_aside">
						<?php } else { ?>
							<div class="log_post_normal">
						<?php } ?>
							<?php
							$text = $this->plugman->run_hooks("text_output", $row["body_formatted"]);
							if ($this->limit_text($text)) {
								echo $text;
								?><br /><br /><a href="<?php echo sprintf($link, $row["id"]); ?>" class="link_readmore"><?php echo gettext("read more"); ?></a><?php
							} else {
								echo $text;
							}
							?>
						</div>
					</div>
					<div class="log_post_foot">
						<?php if ($row["aside"] !=1) { ?>
							<span class="log_post_commentslink"><a href="<?php echo sprintf($link, $row["id"]); ?>#comments"><?php echo sprintf(ngettext("%d Comment", "%d Comments", $comments_count[0]), $comments_count[0]); ?></a><br /></span>
							<span class="log_post_author"><?php echo gettext("By").": <i>".htmlspecialchars($this->authors[$row["authors_id"]]["fullname"]); ?></i></span>
							<span class="log_post_date">| <?php echo gettext("On").": <i>".date("d-m-Y H:i", $row["date"]); ?></i></span>
							<?php if ($row["last_modified"]) { ?>
								<span class="log_post_author"><br /><?php echo gettext("Last modified by").": <i>".htmlspecialchars($this->authors[$row["modified_by"]]["fullname"]); ?></i></span>
								<span class="log_post_date">| <?php echo gettext("Last modified on").": <i>".date("d-m-Y H:i", $row["last_modified"]); ?></i></span>
							<?php } ?>
						<?php } ?>
					</div>
				</div>
				<?php
			}
			if ($limit) {
				echo "<div class=\"log_nextprev_container\">";
				if ($top > 1)
					echo "<a href=\"".$posts["url_prev"]."\" class=\"link_prev\">".gettext("previous")."</a>&nbsp;&nbsp;";

				if (($start+$limit) > $posts["total_count"])
					$end = $posts["total_count"];
				else
					$end = ($start+$limit);

				echo " ".($start+1)."-".$end." (".$posts["total_count"]." ".gettext("total").") ";
				if (($start+$limit) < $posts["total_count"])
					echo "<a href=\"".$posts["url_next"]."\" class=\"link_next\">".gettext("next")."</a>";

				echo "</div>";
			}
		} else {
			$adminpage = "http://".$_SERVER["SERVER_NAME"].substr($_SERVER["REQUEST_URI"],0,strrpos($_SERVER["REQUEST_URI"],"/"))."/admin/";
			?>
			<div class="log_post">
				<div class="log_post_head">
						<h1 class="log_post_h1">Welcome to MvBlog.</h1>
				</div>
				<div class="log_post_body">
					<div class="log_post_normal">
						<?php if (array_key_exists("action", $_REQUEST) && !empty($_REQUEST["action"])) { ?>
							There are no posts to show here.
						<?php } else { ?>
							If you see this your install of MvBlog has been succesfull. Congratulations!<br />
							You can now add your posts etc via de Admin Interface.<br /> Login at <a href="<?php echo $adminpage; ?>"><?php echo $adminpage; ?></a>
						<?php } ?>
					</div>
				</div>
				<div class="log_post_foot">
					<span class="log_post_author"><i>MvBlog system</i></span>
				</div>
			</div>
			<?php
		}
	}
	/* }}} */
	/* limit_text($text) {{{ */
	/**
	 * limit the length of a message
	 *
	 * @param string &$text the text to limit in length
	 * @return int 1 if truncated, 0 if original string is within limits
	 */
	public function limit_text(&$text) {
		if (strstr($text, "##BREAKPOINT##")) {
			$text = substr($text, 0, strpos($text, "##BREAKPOINT##"));
			return 1;
		} else {
			return 0;
		}
	}
	/* }}} */
	/* show_article($id) {{{ */
	/**
	 * Show an article with all comments etc
	 *
	 * @param int $id The article id to show
	 * @param int $captcha_error if 1 it shows an error
	 */
	public function show_article($id, $captcha_error = 0) {
		//category url base
		if ($this->settings["cleanurl"])
			$catlink = "category/%d";
		else
			$catlink = "index.php?action=archive_cat&amp;c=%d";

		if ($id == "httperror") {
			$row = array(
				"title" => $_REQUEST["error"],
				"body"  => "The requested URL (".$_SERVER["REQUEST_URI"].") was not found.
					<br /><br />If you got here from a link on another page please contact that webmaster.<br />
					If it was in your bookmarks, please update them.<br /><br />
					My best guess is you came from: ".$_SERVER['HTTP_REFERER']."<br /><br />
					In the meantime you might be interested in:<br />
					<a href=\"index.php\" title=\"homepage\">Homepage</a><br />
					<a href=\"common/rss.php\" title=\"rss feed\">RSS feed</a><br />",
				"date"  => time()
			);
			$errormode = 1;
		} else {

			$res =& $this->db->query(sprintf("SELECT * FROM articles WHERE id = %d", $id));

			if (PEAR::isError($res))
				die($res->getMessage());
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			$anoncomments = $row["allowanoncomments"];
			/* we can have a global overwrite for the anon comments */
			if ($this->settings["allowanoncomments"] != 1)
				$anoncomments = 0;
			$errormode = 0;
		}
		?>
		<div class="log_post">
			<div class="log_post_head">
				<?php if ($errormode) { ?>
					<h1 class="log_post_h1_error">
				<?php } else { ?>
					<h1 class="log_post_h1">
				<?php } ?>
					<?php echo htmlspecialchars(stripslashes($row["title"])); ?>
				</h1>
				<?php if (!$errormode) { ?>
					<h2 class="log_post_h2">
						<?php echo gettext("category").": "; ?>
						<?php
						$categories = explode(",", $row["categories_ids"]);
						foreach ($categories as $v) {
							if (array_key_exists($v, $this->categories) && $this->categories[$v]["icon"] && $this->settings["show_cat_icons"])
								echo "<a href=\"".sprintf($catlink, $v)."\"><img src=\"images/categories/".$this->categories[$v]["icon"]."\" title=\"".htmlspecialchars($this->categories[$v]["name"])."\" alt=\"".htmlspecialchars($this->categories[$v]["name"])."\" class=\"category_icon\" /></a>&nbsp;";
							elseif (array_key_exists($v, $this->categories))
								echo "<a href=\"".sprintf($catlink, $v)."\">".htmlspecialchars($this->categories[$v]["name"])."</a>&nbsp;";
						}
						?>
					</h2>
				<?php } ?>
			</div>
			<div class="log_post_body">
				<?php if ($errormode) { ?>
					<div class="log_post_error">
				<?php } else { ?>
					<div class="log_post_normal">
				<?php } ?>
					<?php
					$text = $this->parse_body($row["body"], $row["postformat"]);
					$text = stripslashes(str_replace("##BREAKPOINT##", "<a name=\"READMORE\"></a>", $text));
					$text = $this->replace_num_ref($text);
					$text = $this->replace_dossier_ref($text);
					$text = $this->plugman->run_hooks("text_output", $text);
					echo $text;
					if ($errormode) {
						echo "search ";
						$this->blog_show_search();
					}
					?>
				</div>
			</div>
			<div class="log_post_foot">
				<?php if (!$errormode) { ?>
					<span class="log_post_author"><?php echo htmlspecialchars($this->authors[$row["authors_id"]]["fullname"]); ?></span><br />
				<?php } ?>
				<span class="log_post_date"><?php echo date("d-m-Y H:i", $row["date"]); ?></span><br />
				<?php
				if (!$errormode) {
					$tburi = $this->webroot.sprintf("common/tb.php?id=%d", $row["id"]);
					$rssuri = $this->webroot.sprintf("common/rss.php?mode=comments&articleid=%d", $row["id"]);
					?>
					<span class="log_post_commentsrss"><a href="<?php echo $rssuri; ?>"><?php echo gettext("RSS for comments"); ?></a></span><br />
					<span class="log_post_trackbacklink"><?php echo gettext("URL for trackback"); ?>: <a href="<?php echo $tburi; ?>" title="<?php echo gettext("Copy this link for trackbacs"); ?>"><?php echo $tburi; ?></a></span>
				<?php } ?>
			</div>
		</div>
		<div class="log_dossierinfo">
			<?php
			if ($row["dossier_id"]) {
				echo $this->dossiers[$row["dossier_id"]]["name"];
				$dossierrssuri = $this->webroot.sprintf("common/rss.php?mode=dossier&dossier_id=%d", $row["dossier_id"]);
				echo "&nbsp;&nbsp;<a href=\"".$dossierrssuri."\" class=\"dossier_rss_link\">rss</a>";
				echo "<br />";
				//get dossier articles
				$dq = sprintf("SELECT id, title FROM articles WHERE active=1 AND public=1 AND dossier_id = %d ORDER BY date", $row["dossier_id"]);
				$dr = $this->db->query($dq);
				while ($dossieritem = $dr->fetchRow(MDB2_FETCHMODE_ASSOC)) {
					if ($dossieritem["id"] == $row["id"])
						echo $dossieritem["title"]."<br />";
					else
						echo sprintf("<a href=\"index.php?action=view&amp;id=%d\">%s</a><br />", $dossieritem["id"], $dossieritem["title"]);
				}
			}
			?>
		</div>
		<div class="log_comment">
			<a name="comments"></a>
			<?php
			if (!$errormode) {
				$comments = $this->get_comments($row["id"]);

				/* show empty comment with the text 'no comments' when there are none */
				if (!count($comments)) {
					?>
					<div class="log_comment_head"></div>
					<div class="log_comment_body">
						<?php echo gettext("no comments"); ?>
					</div>
					<div class="log_comment_foot"></div>
					<?php
				}

				foreach ($comments as $comment_id=>$comment) {
					echo $this->show_comment($comment);
				}
			}
			?>
		</div>
		<div class="log_comment" id="commentpreviewdiv" style="visibility: hidden;">
		</div>
		<div class="log_form">
			<?php
			if (!$errormode) {
				$locked = 0;
				if (array_key_exists("blog_user", $_SESSION) || $anoncomments) {
					if (array_key_exists("postinfo", $_COOKIE) && !empty($_COOKIE["postinfo"])) {
						$comment_authorinfo = unserialize(stripslashes($_COOKIE["postinfo"]));
						$comment_save       = 1;
					} else {
						if ((array_key_exists("comment_author", $_POST) && !empty($_POST["comment_author"]))
							&& (array_key_exists("comment_save_info", $_POST) && !empty($_POST["comment_save_info"]))) {
							$comment_authorinfo["author"] = htmlspecialchars(stripslashes($_POST["comment_author"]));
							$comment_authorinfo["email"]  = htmlspecialchars(stripslashes($_POST["comment_email"]));
							$comment_authorinfo["url"]    = htmlspecialchars(stripslashes($_POST["comment_url"]));
						} elseif (array_key_exists("author_email", $_SESSION) && !empty($_SESSION["author_email"])) {
							$comment_authorinfo["author"] = htmlspecialchars(stripslashes($_SESSION["author_fullname"]));
							$comment_authorinfo["email"]  = htmlspecialchars(stripslashes($_SESSION["author_email"]));
							$comment_authorinfo["url"]    = htmlspecialchars(stripslashes($_SESSION["author_website"]));
							$locked = 1;
						} elseif (array_key_exists("blog_user", $_SESSION) && !empty($_SESSION["blog_user"])) {
							$comment_authorinfo["author"] = htmlspecialchars(stripslashes($_SESSION["blog_user"]["realname"]));
							if ($_SESSION["blog_user"]["email_public"])
								$comment_authorinfo["email"] = htmlspecialchars(stripslashes($_SESSION["blog_user"]["email"]));
							else
								$comment_authorinfo["email"] = "";
							$comment_authorinfo["url"]    = htmlspecialchars(stripslashes($_SESSION["blog_user"]["website"]));
							$locked = 1;
						} else {
							$comment_authorinfo["url"] = "http://";
							$comment_save              = 0;
						}
					}
					if ($captcha_error) {
						echo "You did not supply a correct text for the image check.";
					}
					?>
					<form name="comment" id="commentform" method="post" action="index.php">
					<input type="hidden" name="action" value="post_comment" />
					<input type="hidden" name="id" id="id" value="" />
					<input type="hidden" name="articles_id" value="<?php echo (int)$id; ?>" />
					<table><tr>
						<td class="log_form_name"><?php echo gettext("name"); ?>:</td>
						<td class="log_form_value">
							<?php if ($locked == 1) { ?>
								<?php echo $comment_authorinfo["author"]; ?>
								<input type="hidden" name="comment_author" value="<?php echo $comment_authorinfo["author"]; ?>" />
							<?php } else { ?>
								<input type="text" name="comment_author" size="30" value="<?php echo (array_key_exists("author", $comment_authorinfo))?$comment_authorinfo["author"]:""; ?>" />
							<?php } ?>
						</td>
					</tr><tr>
						<td class="log_form_name"><?php echo gettext("email"); ?>:</td>
						<td class="log_form_value">
							<?php if ($locked == 1) { ?>
								<?php echo $comment_authorinfo["email"]; ?>
								<input type="hidden" name="comment_email" value="<?php echo $comment_authorinfo["email"]; ?>" />
							<?php } else { ?>
								<input type="text" name="comment_email" size="30" value="<?php echo (array_key_exists("email", $comment_authorinfo))?$comment_authorinfo["email"]:""; ?>" />
							<?php } ?>
						</td>
					</tr><tr>
						<td class="log_form_name"><?php echo gettext("url"); ?>:</td>
						<td class="log_form_value">
							<?php if ($locked == 1) { ?>
								<?php echo $comment_authorinfo["url"]; ?>
								<input type="hidden" name="comment_url" value="<?php echo $comment_authorinfo["url"]; ?>" />
							<?php } else { ?>
								<input type="text" name="comment_url" size="30" value="<?php echo $comment_authorinfo["url"]; ?>" />
							<?php } ?>
						</td>
					</tr><tr>
						<td class="log_form_name"><?php echo gettext("title"); ?>:</td>
						<td class="log_form_value"><input type="text" name="comment_title" size="30" value="<?php if (array_key_exists("comment_title", $_POST)) echo $_POST["comment_title"]; ?>" /></td>
					<?php if ($locked == 0) { ?>
						</tr><tr>
							<td class="log_form_name"><?php echo gettext("save my info"); ?></td>
							<td class="log_form_value"><input type="checkbox" name="comment_save_info" value="1" <?php if ($comment_save) { echo "checked=\"checked\""; } ?> /></td>
					<?php } ?>
					</tr><tr>
						<td colspan="2" class="log_form_value">
							<?php
								echo gettext("You can use bbcode to format your text.")."&nbsp;";
								echo gettext("Supported bbcode tags").":<br />";
								echo "[b][i][u][url=http...][quote][code][strike][email][img]<br />";
							?>
							<textarea name="comment_content" rows="20" cols="50"><?php if (array_key_exists("comment_content", $_POST)) echo $_POST["comment_content"]; ?></textarea><br />
							<?php
								if ($anoncomments && !array_key_exists("blog_user", $_SESSION) && !array_key_exists("author_email", $_SESSION)) {
									$captcha = $this->plugman->run_hooks("captcha_output", "");
									echo $captcha;
									echo "<input type=\"hidden\" name=\"checkcap\" value=\"1\" />\n";
								}
							?>
							<script type="text/javascript" language="Javascript1.2" src="common/js/xmlhttp.js"></script>
							<script type="text/javascript" language="Javascript1.2">
								function previewComment() {
									var commentform = document.getElementById('commentform');
									var title = escape(commentform.comment_title.value);
									var comment = escape(commentform.comment_content.value);
									var name = escape(commentform.comment_author.value);
									var email = escape(commentform.comment_email.value);
									var website = escape(commentform.comment_url.value);
									var previewurl = 'common/previewcomment.php?action=show_comment_preview&title=' + title + '&comment=' + comment + '&name=' + name + '&email=' + email + '&website=' + website;
									document.getElementById('commentpreviewdiv').innerHTML = loadXMLContent(previewurl);
									document.getElementById('commentpreviewdiv').style.visibility='visible';
								}
							</script>
							<input type="button" onclick="javascript: previewComment();" value="<?php echo gettext("preview comment"); ?>" />
							<input type="submit" value="<?php echo gettext("post comment"); ?>" />
						</td>
					</tr></table>
					</form>
				<?php } ?>
			<?php } ?>
		</div>
		<?php
	}
	/* }}} */
	/* show_comment {{{ */
	/**
	 * Format the output for a comment.
	 *
	 * @param array $commentdata The data for this comment
	 */
	public function show_comment($commentdata) {
		$output ="";
		$output .= "<div class=\"log_comment_head\">\n";
		$output .= "\t<span class=\"log_comment_subject\">\n";
		$output .= "\t\t<h1 class=\"log_comment_h1\">".$commentdata["title"]."</h1>\n";
		$output .= "\t</span>\n";
		$output .= "</div>\n";
		$output .= "<div class=\"log_comment_body\">\n";
		$output .= "\t".$commentdata["comment"]."\n";
		$output .= "</div>\n";
		$output .= "<div class=\"log_comment_foot\">\n";
		$output .= "\t<span class=\"log_comment_author\">\n";
		$output .= "\t\t".gettext("posted by").": ".$commentdata["name"];
		if ($commentdata["ip"])
			$output .= "&nbsp;(".$commentdata["ip"].")&nbsp;";
		if (array_key_exists("hdate", $commentdata))
			$output .= gettext("on").": ".$commentdata["hdate"]."\n";
		else
			$output .= gettext("on").": ".date("d-m-Y H:i")."\n";
		$output .= "\t</span>\n";
		if ($commentdata["email"])
			$output .= "\t<br /><span class=\"log_comment_email\"><a href=\"mailto:".$commentdata["email"]."\">".$commentdata["email"]."</a></span>\n";
		if ($commentdata["website"] && $commentdata["website"] != "http://")
			$output .= "\t<span class=\"log_comment_website\"><a href=\"".$commentdata["website"]."\">".$commentdata["website"]."</a></span>\n";
		$output .= "</div>\n";

		return $output;
	}
	/* }}} */
	/* get_comments {{{ */
	/**
	 * Get all comments associated with a post
	 * The output will be suitable for direct flushing to client
	 *
	 * @param int $article_id The article id where the comments are attached to
	 * @return array all comments in an array
	 */
	public function get_comments($article_id) {
		$comments = array();
		$res =& $this->db->query(sprintf("SELECT * FROM comments WHERE articles_id = %d ORDER BY date", $article_id));
		if (PEAR::isError($res)) {
			die($res->getMessage());
		}
		while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) {
			$comments[$row["id"]]["title"]   = htmlspecialchars(stripslashes($row["title"]));
			$comments[$row["id"]]["comment"] = nl2br($this->parse_bbcode(htmlspecialchars($this->strip_invalid_xml(stripslashes($row["comment"])))));
			$comments[$row["id"]]["name"]    = htmlspecialchars(stripslashes($row["name"]));
			$comments[$row["id"]]["ip"]      = $this->obfuscate_ip($row["ip"]);
			$comments[$row["id"]]["date"]    = $row["date"];
			$comments[$row["id"]]["hdate"]   = date("d-m-Y H:i", $row["date"]);
			$comments[$row["id"]]["email"]   = htmlspecialchars(stripslashes($row["email"]));
			$comments[$row["id"]]["website"] = htmlspecialchars(stripslashes($row["website"]));
		}
		return $comments;
	}
	/* }}} */
	/* obfuscate_ip($ip)  {{{ */
	/**
	 * obfuscate ip $ip addresses so we are privacy friendly
	 *
	 * @param string the ip address to obfuscate
	 * @return string the ip with the last octet replaced by X
	 */
	//------------------------------------------
	function obfuscate_ip($ip) {
		if (strrpos($ip, ".")) {
			$return = substr($ip, 0, strrpos($ip, ".")).".x";
		} elseif (strrpos($ip, ":")) {
			$return = substr($ip, 0, strrpos($ip, ":")).":x";
		}
		return $return;
	}
	/* }}} */
	/* blog_show_login() {{{ */
	/**
	 * Show login screen or username
	 */
	public function blog_show_login() {
		if (!array_key_exists("blog_user", $_SESSION)) {
			?>
			<form name="user_login" action="index.php" method="post">
				<input type="hidden" name="action" value="user_login" />
				<?php echo gettext("username"); ?>: <input type="text" name="user[username]" value="" /><br />
				<?php echo gettext("password"); ?>: <input type="password" name="user[password]" value="" /><br />
				<input type="submit" name="login" value="<?php echo gettext("login"); ?>" />&nbsp;&nbsp;
				<a href="index.php?action=user_new"><?php echo gettext("Register"); ?></a>
			</form>
			<?php
		} else {
			if (array_key_exists("author_name", $_SESSION) && $_SESSION["author_name"]) {
				$realname = htmlspecialchars(stripslashes($_SESSION["author_fullname"]));
			} else {
				$realname = htmlspecialchars(stripslashes($_SESSION["blog_user"]["realname"]));
			}
			echo gettext("You are logged in as").":<br />".$realname;
		}
	}
	/* }}} */
	/* blog_default_links() {{{ */
	/**
	 * show default menu links
	 */
	public function blog_default_links() {
		?>
		<ul id="default_list_container">
			<li class="default_list_item"><a href="index.php" title="home"><?php echo gettext("Home"); ?></a></li>
			<li class="default_list_item"><a href="common/rss.php" title="rss"><?php echo gettext("RSS"); ?></a></li>
			<li class="default_list_item"><a href="common/rss.php?mode=comments" title="comments rss"><?php echo gettext("RSS comments"); ?></a></li>
			<?php if (array_key_exists("author_id", $_SESSION) && !empty($_SESSION["author_id"])) { ?>
				<li class="default_list_item"><a href="admin/index.php" title="admin"><?php echo gettext("Admin"); ?></a></li>
			<?php } ?>
			<?php if (array_key_exists("blog_user", $_SESSION) && !array_key_exists("author_id", $_SESSION)) { ?>
				<li class="default_list_item"><a href="index.php?action=user_settings" title="settings"><?php echo gettext("Settings"); ?></a></li>
			<?php } ?>
		</ul>
		<?php
		$pluginsdata = $this->plugman->run_hooks("menu_default_output", "");
		echo $pluginsdata;
	}
	/* }}} */
	/* blog_show_styleswitcher() {{{ */
	/**
	 * show dropdown with styles
	 *
	 * This function opens the dir styles/
	 * for every dir in there that contains a file index.css
	 * it puts the dirname in the dropdown. It also has an onchange
	 * javascript function attached so it will reload the blog with the new
	 * style applied.
	 *
	 * @return bool false if the styledir cannot be opened
	 */
	public function blog_show_styleswitcher() {
		if ($dh = opendir("style")) {
			while (false !== ($v = readdir($dh))) {
				if (is_dir("style/".$v) && file_exists("style/".$v."/index.css")) {
					$stylename[] = $v;
				}
			}
			if (count($stylename)) {
				?>
				<select name="styleswitchselect" id="styleswitchselect" onchange="switchstyle();">
					<?php
					foreach ($stylename as $v) {
						if ($v == $_SESSION["style"]) { $selected="selected=\"selected\""; } else { $selected=""; }
						echo "<option value=\"".$v."\" ".$selected.">".$v."</option>\n";
					}
					?>
				</select>
				<script language="Javascript1.2" type="text/javascript" src="common/js/styleswitcher.js"></script>
				<?php
			}
		} else {
			return false;
		}
	}
	/* }}} */
	/* blog_archive_links($amount) {{{ */
	/**
	 * show 'month archive' menu links
	 *
	 * @param int $amount The number of months to show
	 */
	public function blog_archive_links($amount=5) {
		if ($this->settings["cleanurl"])
			$link = "archive/";
		else
			$link = "index.php?action=archive&amp;m=";
		$output = "<ul id=\"archive_list_container\">\n";
		for ($i=0; $i<$amount; $i++) {
			$month = date("m") - $i;
			$start = mktime(0,0,0,$month,1,date("Y"));
			if ($month == date("m")) {
				$end = mktime(0, 0, 0, $month, date("d")+1, date("Y"));
			} else {
				$end = mktime(0,0,0,$month+1,1,date("Y"))-1;
			}
			$query = "SELECT COUNT(*) FROM articles WHERE date between $start and $end";
			$res =& $this->db->query($query);
			$row = $res->fetchRow();

			$output .= "\t<li class=\"archive_list_item\">\n";
			$output .= "\t\t<a href=\"".$link.date("mY", mktime(0,0,0,$month,1,date("Y")))."\">\n";
			$output .= "\t\t\t".str_replace(" ", "&nbsp;", date("F Y", $start))."\n";
			$output .= "\t\t</a>&nbsp;(".$row[0].")\n";
			$output .= "\t</li>\n";
		}
		$query = sprintf("SELECT COUNT(*) FROM articles WHERE date < %d", $start);
		$res =& $this->db->query($query);
		$row = $res->fetchRow();
		$output .= "\t<li class=\"archive_list_item\">\n";
		$output .= sprintf("\t\t<a href=\"index.php?action=archive_old&fromts=%d\">\n", $start);
		$output .= "\t\t\t".gettext("older")."\n";
		$output .= sprintf("\t\t</a>&nbsp;(%d)\n", $row[0]);
		$output .= "\t</li>\n";
		$output .= "</ul>\n";
		$output = $this->plugman->run_hooks("menu_archive_output", $output);
		echo $output;
	}
	/* }}} */
	/* blog_cats_links() {{{ */
	/**
	 * show 'categories' archive menu links
	 */
	public function blog_cats_links() {
		if ($this->settings["cleanurl"])
			$link = "category/";
		else
			$link = "index.php?action=archive_cat&amp;c=";
		$max_time = mktime(0, 0, 0, date("m"), date("d")+1, date("Y"));
		?><ul id="category_list_container"><?php
		$this->categories[] = "asides";
		foreach ($this->categories as $k=>$v) {
			if (!$k) continue;
			if ($v == "asides") {
				$r =& $this->db->query("SELECT COUNT(*) FROM articles WHERE aside=1 AND date <= $max_time");
				$count = $r->fetchRow();
				?><li class="category_list_item"><a href="index.php?action=archive_cat&amp;c=aside">asides</a>&nbsp;(<?php echo $count[0]; ?>)</li><?php
			} else {
				$q  = sprintf("SELECT COUNT(*) FROM articles WHERE aside=0 AND date <= %d", $max_time);
				$q .= sprintf(" AND (categories_ids like '%1\$d,%%' OR categories_ids like '%%,%1\$d' OR categories_ids like '%%,%1\$d,%%' OR categories_ids = '%1\$d')", $k);
				$r =& $this->db->query($q);
				$count = $r->fetchRow();
				?>
				<li class="category_list_item">
					<a href="<?php echo $link.$k; ?>"><?php echo str_replace(" ", "&nbsp;", stripslashes($v["name"])); ?></a>
					&nbsp;(<?php echo $count[0];?>)
				</li>
				<?php
			}
		}
		?></ul><?php
	}
	/* }}} */
	/* blog_show_search() {{{ */
	/**
	 * show livesearchbox
	 */
	public function blog_show_search() {
		?>
		<form name="searchform" action="" id="searchform" method="post" onsubmit="if (this.submitted) return true; else return false;">
			<input type="text" name="search" alt="seach" id="search" />
		</form>
		<div id="searchresults"></div>
		<script src="common/js/liveRequest.js" type="text/javascript" language="javascript1.2"></script>
		<?php
	}
	/* }}} */
	/* blog_show_menulinks() {{{ */
	/**
	 * get usersupplied sidebar menu entries
	 */
	public function blog_show_menulinks() {
		$res =& $this->db->query("SELECT * FROM menulinks ORDER BY sortorder,linktitle");
		if ($res->numRows()) {
			echo "<ul id=\"link_list_container\">\n";
			while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC)) {
				if($row["image"]) {
					echo "\t<li class=\"link_list_item\"><a href=\"".htmlspecialchars(stripslashes($row["url"]))."\"><img src=\"".stripslashes($row["image"])."\" alt=\"".stripslashes($row["linktitle"])."\" /></a></li>\n";
				} else {
					echo "\t<li class=\"link_list_item\"><a href=\"".htmlspecialchars(stripslashes($row["url"]))."\">".stripslashes($row["linktitle"])."</a></li>\n";
				}
			}
			echo "</ul>\n";
		}
	}
	/* }}} */
	/* blog_show_dossierlinks {{{ */
	/**
	 * Show list of dossiers.
	 */
	public function blog_show_dossierlinks() {
		if (count($this->dossiers) > 1) {
			echo "<ul id=\"dossier_list_container\">\n";
			foreach ($this->dossiers as $did=>$dossier) {
				if ($did == 0) continue;
				echo "<li class=\"dossier_list_item\"><a href=\"index.php?action=viewdossier&id=".$did."\">".$dossier["name"]."</a></li>\n";
			}
			echo "</ul>\n";
		}
	}
	/* }}} */
	/* post_comment($postdata) {{{ */
	/**
	 * store comment in database and optionally mail author of post
	 *
	 * If the user checked the 'mail' box in the admin this
	 * function will also send a mail to the author of the post.
	 *
	 * @param array $postdata content of the comment entry form
	 */
	public function post_comment($postdata) {
		/* sanitize data */
		$sanitize_options_body         = array("space" => 1, "bbcode" => 1);
		$sanitize_options_all          = array("space" => 1);
		$sanitize_options_url          = array("url"   => 1);
		$sanitize_options_email        = array("email" => 1);
		if (array_key_exists("checkcap", $postdata) && $postdata["checkcap"]) {
			$captcha_check = $this->plugman->run_hooks("captcha_check", $postdata);
			if ($captcha_check) {
				$captcha_error = 0;
			} else {
				$captcha_error = 1;
			}

			/* check if name and email address are already in the database */
			/** @todo: make this some spiffy AJAX thingie */
			$sql = sprintf("SELECT COUNT(*) AS count FROM blog_users WHERE realname = '%s' OR email = '%s';",
				trim($postdata["comment_author"]), trim($postdata["comment_email"]));
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["count"])
				die("username and/or email address belong to a registered user");
			/* same for blogadmins */
			$sql = sprintf("SELECT COUNT(*) AS count FROM authors WHERE fullname = '%s' OR email = '%s';",
				trim($postdata["comment_author"]), trim($postdata["comment_email"]));
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["count"])
				die("username and/or email address belong to a registered user");
		} else {
			$captcha_error = 0;
		}
		if ($captcha_error == 0) {
			$postdata["articles_id"]       = $this->_sanitize($postdata["articles_id"],     $sanitize_options_all);
			$postdata["comment_save_info"] = (array_key_exists("comment_save_info", $postdata))?$this->_sanitize($postdata["comment_save_info"]):0;
			$postdata["comment_author"]    = $this->_sanitize($postdata["comment_author"],  $sanitize_options_all);
			$postdata["comment_email"]     = $this->_sanitize($postdata["comment_email"],   $sanitize_options_email);
			$postdata["comment_url"]       = $this->_sanitize($postdata["comment_url"],     $sanitize_options_url);
			$postdata["comment_title"]     = $this->_sanitize($postdata["comment_title"],   $sanitize_options_all);
			$postdata["comment_content"]   = $this->_sanitize($postdata["comment_content"], $sanitize_options_body);

			/* check if post exists */
			$sql = sprintf("SELECT COUNT(*) AS count FROM articles WHERE id = %d", $postdata["articles_id"]);
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["count"] == 0) { die(gettext("no valid article given")); }
			/* check for anon comments on non-anon comments enabled post/blog */
			if ((array_key_exists("blog_user", $_SESSION) && $_SESSION["blog_user"]["user_id"]) || (array_key_exists("author_id", $_SESSION) && $_SESSION["author_id"])) {
				$anon_user = false;
			} else {
				$anon_user = true;
			}
			if ($this->settings["allowanoncomments"])
				$global_anon = true;
			else
				$global_anon = false;
			if (!$global_anon && $anon_user)
				die(gettext("no anonymous comments allowed."));

			/* global is ok, check single post */
			$sql = sprintf("SELECT allowanoncomments FROM articles WHERE id = %d", $postdata["articles_id"]);
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["allowanoncomments"] != 1 && $anon_user)
				die(gettext("no anonymous comments allowed."));

			if ($postdata["comment_save_info"]) {
				$cookie_info = array(
					"author" => $postdata["comment_author"],
					"email"  => $postdata["comment_email"],
					"url"    => $postdata["comment_url"]
				);
				$cookie_info_ser = serialize($cookie_info);
				setcookie("postinfo", $cookie_info_ser, time()+(60*60*24*365));
			}
			$query_str  = "INSERT INTO comments (name, email, website, title, comment, ip, date, articles_id) VALUES (";
			$query_str .= "'%s', '%s', '%s', '%s', '%s', '%s', %d, %d)";
			$query = sprintf($query_str,
				$postdata["comment_author"],
				$postdata["comment_email"],
				$postdata["comment_url"],
				$postdata["comment_title"],
				$postdata["comment_content"],
				$_SERVER["REMOTE_ADDR"],
				mktime(),
				$postdata["articles_id"]
			);
			$res =& $this->db->exec($query);
			//see if we should mail this comment to the author
			$sql = "SELECT mail_comments FROM articles WHERE id=".(int)$postdata["articles_id"];
			$res =& $this->db->query($sql);
			$row = $res->fetchRow();
			if ($row[0]==1) {
				//get author from article post
				$res =& $this->db->query("SELECT * FROM articles WHERE id=".(int)$postdata["articles_id"]);
				$post_info = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
				//get author email addy
				$query = "SELECT email FROM authors WHERE id=".(int)$post_info["authors_id"];
				$res =& $this->db->query($query);
				$email = $res->fetchRow();
				$author_email = $email[0];
				$subject = "[MvBlog] Comment: \"".$post_info["title"]."\"";
				$body  = "New comment on your post #".$post_info["id"]." \"".$post_info["title"]."\"\n";
				$body .= "Author: ".$postdata["comment_author"]."(".$_SERVER["REMOTE_ADDR"].") <".$postdata["comment_email"]."> (".$postdata["comment_url"].")\n";
				$body .= "Title: ".$postdata["comment_title"]."\n";
				$body .= "Comment: ".$postdata["comment_content"]."\n\n";
				mail($author_email, $subject, $body, "From: mvblog@three-dimensional.net\r\nX-Mailer: MvBlog");
			}
		}
		$this->show_article($postdata["articles_id"], $captcha_error);
	}
	/* }}} */
	/* strip_bbcode($data) {{{ */
	/**
	 * strip bbcode from text string
	 *
	 * @param string $data the text that can contain bbcode
	 * @return string the text stripped from bbcode
	 */
	public function strip_bbcode($data) {

		$string = htmlspecialchars($data);
		/* Strip useless newlines so [code] will appear correct */
		$string = str_replace("\r", "", $string);
		$string = str_replace("\n", "<br />", $string);

		$patterns = array(
			'`\[ul\](.+?)\[/ul\]`is',
			'`\[li\](.+?)\[/li\]`is',
			'`\[quote\](.+?)\[/quote\]`is',
			'`\[indent](.+?)\[/indent\]`is',
			'`\[code](.+?)\[/code\]`is',
			'`\[b\](.+?)\[/b\]`is',
			'`\[i\](.+?)\[/i\]`is',
			'`\[u\](.+?)\[/u\]`is',
			'`\[strike\](.+?)\[/strike\]`is',
			'`\[color=#([0-9]{6})\](.+?)\[/color\]`is',
			'`\[email\](.+?)\[/email\]`is',
			'`\[img\](.+?)\[/img\]`is',
			'`\[url=([a-z0-9]+://)([\w\-]+\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^ \"\n\r\t<]*?)?)\](.*?)\[/url\]`si',
			'`\[url\]([a-z0-9]+?://){1}([\w\-]+\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^ \"\n\r\t<]*)?)\[/url\]`si',
			'`\[url\]((www|ftp)\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^ \"\n\r\t<]*?)?)\[/url\]`si',
			'`\[flash=([0-9]+),([0-9]+)\](.+?)\[/flash\]`is',
			'`\[size=([1-6]+)\](.+?)\[/size\]`is'
		);

		$replaces =  array(
			'\1',
			'* \1',
			'\1',
			'\\1',
			'\\1',
			'\\1',
			'\\1',
			'\\1',
			'\\1',
			'\2',
			'\1',
			'',
			'\6',
			'\1\2',
			'\1',
			'',
			'\2'
		);

		$prev_string = "";
		while ($prev_string != $string) {
			$prev_string = $string;
			$string = preg_replace($patterns, $replaces , $string);
		}
		return(stripslashes($string));
	}
	/* }}} */
	/* user_login($userdata) {{{ */
	/**
	 * Login user so they can post comments etc
	 *
	 * @param array $userdata At least key username and key password
	 * @return bool true on succesfull login, otherwise false
	 */
	public function user_login($userdata) {
		$usernamecheck = $passwordcheck = 0;
		if (array_key_exists("username", $userdata) && !empty($userdata["username"])) {
			$usernamecheck = 1;
		}
		if (array_key_exists("password", $userdata) && !empty($userdata["password"])) {
			$passwordcheck = 1;
		}
		if ($usernamecheck == 1 && $passwordcheck == 1) {
			/* do the actual checking */
			$sql = sprintf("SELECT * FROM blog_users WHERE active = 1 AND username = '%s' AND password = '%s'",
				$this->_sanitize($userdata["username"]),
				$this->_sanitize($userdata["password"], array("bbcode" => 1))
			);
			$res = $this->db->query($sql);
			if ($res->numRows() == 1) {
				$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
				$_SESSION["blog_user"]["user_id"]  = $row["id"];
				$_SESSION["blog_user"]["realname"] = $row["realname"];
				$_SESSION["blog_user"]["username"] = $row["username"];
				$_SESSION["blog_user"]["email"]    = $row["email"];
				$_SESSION["blog_user"]["website"]  = $row["website"];
				$this->log->add_log(mktime(), $row["id"], 2, sprintf("User %s logged in", $row["username"]));
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	/* }}} */
	/* user_edit {{{ */
	/**
	 * Form to alter user information. Can be used for both new users and editing settings
	 *
	 * @param int $register if set, register a new user, otherwise it's a logged in user wanting to alter settings.
	 */
	public function user_edit($register = 1) {
		?>
		<div class="log_post">
			<div class="log_posthead">
					<h1>
						<?php
						if ($register)
							echo gettext("Registration process");
						else
							echo gettext("Settings");
						?>
					</h1>
			</div>
			<div class="log_postbody">
				<?php
				//debug
				//print_r($_SESSION["blog_user"]);
				//$_SESSION["blog_user"]["email_public"] = 1;
				if ($register) {
					echo gettext("Register here.")."<br />";
					echo gettext("Registering an account gives you extra privileges like commenting on posts.")."<br />";
					echo gettext("The exact privileges you get depend on the plugins loaded.");
				} elseif (array_key_exists("saved", $_REQUEST)) {
					echo gettext("Settings succesfully saved.");
				}
				?>
				<form name="register" method="post" action="index.php">
				<input type="hidden" name="action" value="user_save" />
				<?php if (!$register) echo "<input type=\"hidden\" name=\"reg[userid]\" value=\"".$_SESSION["blog_user"]["user_id"]."\" />"; ?>
				<table><tr>
					<td><?php echo gettext("username"); ?></td>
					<td>
						<?php
						if ($register)
							echo "<input type=\"text\" name=\"reg[username]\" />";
						else
							echo $_SESSION["blog_user"]["username"];
						?>
					</td>
				</tr><tr>
					<td><?php echo gettext("password"); ?></td>
					<td><input type="password" name="reg[password]" value="" /></td>
				</tr><tr>
					<td><?php echo gettext("real name"); ?></td>
					<td><input type="text" name="reg[realname]" value="<?php echo (!$register)?$_SESSION["blog_user"]["realname"]:""; ?>" /></td>
				</tr><tr>
					<td><?php echo gettext("email"); ?></td>
					<td><input type="text" name="reg[email]" value="<?php echo (!$register)?$_SESSION["blog_user"]["email"]:""; ?>" /></td>
				</tr><tr>
					<td><?php echo gettext("show email on website"); ?></td>
					<td><input type="checkbox" name="reg[email_public]" value="1" <?php echo (!$register && array_key_exists("email_public", $_SESSION["blog_user"]) && $_SESSION["blog_user"]["email_public"])?"checked=\"checked\"":""; ?> /></td>
				</tr><tr>
					<td><?php echo gettext("website"); ?></td>
					<td><input type="text" name="reg[website]" value="<?php echo (!$register)?$_SESSION["blog_user"]["website"]:""; ?>" /></td>
				</tr><tr>
					<td colspan="2"><input type="submit" value="<?php echo ($register)?gettext("register"):gettext("save"); ?>" /></td>
				</tr></table>
				</form>
			</div>
		</div>
		<?php
	}
	/* }}} */
	/* user_save() {{{ */
	public function user_save() {
		if (array_key_exists("userid", $_REQUEST["reg"])) {
			if ($_SESSION["blog_user"]["user_id"] != $_REQUEST["reg"]["userid"])
				die("This is not ok. request and session have different user id information. Possible hack attempt.");
			$register = 0;
		} else {
			$register = 1;
		}
		/* sanitize input */
		if ($register)
			$username = $this->_sanitize($_REQUEST["reg"]["username"]);
		if ($_REQUEST["reg"]["password"])
			$password = $this->_sanitize($_REQUEST["reg"]["password"], array("bbcode" => 1));
		else
			$password = "";
		$realname = $this->_sanitize($_REQUEST["reg"]["realname"], array("space"  => 1));
		$email    = $this->_sanitize($_REQUEST["reg"]["email"],    array("email"  => 1));
		$website  = $this->_sanitize($_REQUEST["reg"]["website"],  array("url"    => 1));
		$email_public = (array_key_exists("email_public", $_REQUEST["reg"]))?1:0;

		if ($register) {
			$regcode  = md5(mktime().$username.$email.$website);
			/* check to see if user is already there */
			/** @todo Should be implemented in input form as AJAX call */
			$sql = sprintf("SELECT COUNT(*) AS count FROM blog_users WHERE username = '%s'", $username);
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["count"] > 0) {
				die(gettext("username already registered"));
			}
			/* build query to store into db */
			$sql = sprintf("INSERT INTO blog_users (username, password, realname, email, website, regcode, email_public) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', %d)",
				$username, $password, $realname,
				$email, $website, $regcode, $email_public
			);
			$logmsg = sprintf("User %s registered", $username);
		} else {
			if ($password)
				$passwdq = sprintf(", password = '%s'", $password);
			else
				$passwdq = "";
			$_SESSION["blog_user"]["realname"]     = $realname;
			$_SESSION["blog_user"]["email"]        = $email;
			$_SESSION["blog_user"]["email_public"] = $email_public;
			$_SESSION["blog_user"]["website"]      = $website;
			$sql = sprintf("UPDATE blog_users SET realname = '%s'%s, email = '%s', website = '%s', email_public = %d WHERE id = %d",
				$realname, $passwdq, $email, $website, $email_public, $_SESSION["blog_user"]["user_id"]);
			$logmsg = sprintf("User %d:%s updated", $_SESSION["blog_user"]["id"], $_SESSION["blog_user"]["username"]);
		}
		$this->db->exec($sql);
		$this->log->add_log(mktime(), 0, 2, $logmsg);
		if ($register) {
			if (array_key_exists("HTTPS", $_SERVER) && $_SERVER["HTTPS"] == "on")
				$proto = "https";
			else
				$proto = "http";

			$confirmuri = $proto."://".$_SERVER["SERVER_NAME"].substr($_SERVER["PHP_SELF"],0,strrpos($_SERVER["PHP_SELF"], "/"))."/index.php?action=register_confirm&code=$regcode&email=$email";

			$mail_subject = gettext("Your MvBlog registration.");
			$mail_body    = gettext("Thank you for registering your username")." ".$username." ".gettext("with password")." ".$password."\n";
			$mail_body   .= gettext("Copy/paste the following link in your browsers addressbar to finish the registration process.")."\n\n";
			$mail_body   .= $confirmuri."\n\n";
			$mail_from    = "register@mvblog.org";
			mail($email, $mail_subject, $mail_body, "From: $mail_from", "-f$mail_from");
			?>
			<div class="log_post">
				<div class="log_posthead">
						<h1><?php echo gettext("Registration process"); ?></h1>
				</div>
				<div class="log_postbody">
					<?php
						echo gettext("You should receive an email message on the address you specified within minutes.")."<br />";
						echo gettext("This email contains information on how to activate your account. Once activated you can login and enjoy the extra privileges.")."<br /><br />";
						echo gettext("Thank you for registering with MvBlog.");
					?>
				</div>
			</div>
			<?php
		} else {
			header("Location: index.php?action=user_settings&saved=1");
		}
	}
	/* }}} */
	/* user_confirm() {{{ */
	/**
	 * Check confirmation after registering a new account
	 */
	public function user_confirm() {
		$check = 0;
		if (array_key_exists("code", $_REQUEST) && !empty($_REQUEST["code"])) {
			if (array_key_exists("email", $_REQUEST) && !empty($_REQUEST["email"])) {
				$check = 1;
			}
		}
		if ($check == 1) {
			/* check code and email against database */
			$email   = $this->_sanitize($_REQUEST["email"], array("email" => 1));
			$regcode = $this->_sanitize($_REQUEST["code"]);
			$sql = sprintf("SELECT COUNT(*) as count FROM blog_users WHERE active=0 AND email = '%s' AND regcode = '%s'",
				$email, $regcode);
			$res =& $this->db->query($sql);
			$row = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
			if ($row["count"] == 1) {
				/* all is ok, activate account */
				$sql = sprintf("UPDATE blog_users SET active=1 WHERE email='%s' AND regcode='%s'", $email, $regcode);
				$res =& $this->db->exec($sql);
				$body = gettext("Registration complete!")."<br />".gettext("You can now login.");
			} else {
				/* no record found in database, print warning */
				$body = gettext("No valid entry given. Try again or register again.");
			}
		}
		?>
		<div class="log_post">
			<div class="log_posthead">
				<h1><?php echo gettext("Registration process"); ?></h1>
			</div>
			<div class="log_postbody">
				<?php
				if ($check == 1) {
					echo $body;
				} else {

				echo gettext("Enter your email address and confirmation code below.");
				?>
				<form name="regconfirm" method="post" action="index.php">
				<input type="hidden" name="action" value="user_confirm">
				<table><tr>
					<td><?php echo gettext("email"); ?></td>
					<td><input type="text" name="email" /></td>
				</tr><tr>
					<td><?php echo gettext("code"); ?></td>
					<td><input type="text" name="code" /></td>
				</tr><tr>
					<td colspan="2"><input type="submit" value="<?php echo gettext("confirm"); ?>" /></td>
				</tr></table>
				</form>
				<?php } ?>
			</div>
		</div>
		<?php
	}
	/* }}} */
}
?>
