- Logins (sessions) now work. (There are no links to logout.php, so if you want to

logout you'll have to type it manually)

- Add comment is started, but doesn't actually do any data insertion yet

- We need CSS pretty badly


git-svn-id: svn://10.0.0.236/trunk@188027 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bugzilla%micropipes.com
2006-01-23 01:24:47 +00:00
parent f1becef2d4
commit d833635216
8 changed files with 527 additions and 11 deletions

View File

@@ -2,6 +2,91 @@
/**
* Add a comment to any Addon.
*
* @todo require session authentication.
* @package amo
* @subpackage docs
*
* Variables:
* $_GET['id'] = Addon ID (integer)
*/
startProcessing('addcomment.tpl', null, null, 'nonav');
require_once 'includes.php';
session_start();
if ((!array_key_exists('id', $_GET)) || !is_numeric($_GET['id'])) {
triggerError('There was an error processing your request.');
}
//This is a secure page, so we'll check the session
if (!$_auth->validSession()) {
//id is already verified to be numeric from above
header('Location: '.WEB_PATH."/login.php?dest=comment&id={$_GET['id']}");
exit;
}
// If there are errors, this will be populated
$_errors = array();
// They're posting a comment
if (isset($_POST['c_submit'])) {
if (! (array_key_exists('c_rating', $_POST)
&& array_key_exists('c_title', $_POST)
&& array_key_exists('c_comments', $_POST))) {
//This should never happen, but hey...
triggerError('There was an error processing your request.');
}
$_c_rating = mysql_real_escape_string($_POST['c_rating']);
$_c_title = mysql_real_escape_string($_POST['c_title']);
$_c_comments = mysql_real_escape_string($_POST['c_comments']);
// This is used in the template. If 'true' is returned, an error will be
// printed in the template (using booleans instead of strings here keeps the
// error messages in the template).
$_errors['c_rating'] = !is_numeric($_c_rating);
$_errors['c_title'] = empty($_c_title);
$_errors['c_comments'] = empty($_c_comments);
foreach ($_errors as $error) {
if ($error !== false) {
$_bad_input = true;
} else {
$_bad_input = false;
}
}
// If bad_input is true, we'll skip the rest of the processing and dump them
// back out to the from with an error.
if ($_bad_input === false) {
// @todo this
// Put it in the database
// Drop significant stuff in the session
// header() them to somewhere else
}
}
$addon = new AddOn($_GET['id']);
// Put values back into the form - something went wrong (or they haven't hit 'submit' yet).
$c_rating_value = array_key_exists('c_rating', $_POST) ? $_POST['c_rating'] : '';
$c_title_value = array_key_exists('c_title', $_POST) ? $_POST['c_title'] : '';
$c_comments_value = array_key_exists('c_comments', $_POST) ? $_POST['c_comments'] : '';
// Assign template variables.
$tpl->assign(
array( 'title' => 'Add Comment',
'currentTab' => null,
'rate_select_value' => array('','5','4','3','2','1','0'),
'rate_select_name' => array('Rating:','5 stars', '4 stars', '3 stars', '2 stars', '1 star', '0 stars'),
'addon' => $addon,
'c_errors' => $_errors,
'c_rating_value' => $c_rating_value,
'c_title_value' => $c_title_value,
'c_comments_value' => $c_comments_value
)
);
?>

View File

@@ -0,0 +1,54 @@
<?php
/**
* Page that validates whether a user is logged in. If they aren't, it will prompt
* them for their username/pass
*
* @package amo
* @subpackage docs
*
*/
startProcessing('login.tpl', null, null, 'nonav');
require_once 'includes.php';
// When the template is drawn, if this isn't null, it will print out a "failure to
// authenticate, try again" message.
$login_error = null;
$valid_destinations = array ('comment' => WEB_PATH.'/addcomment.php');
if (!empty($_POST['username']) && !empty($_POST['password'])) {
if ($_auth->authenticate($_POST['username'], $_POST['password'])) {
session_start();
$_auth->createSession();
if (array_key_exists('dest', $_GET) && array_key_exists($_GET['dest'], $valid_destinations)) {
$_next_page = $valid_destinations[$_GET['dest']];
} else {
triggerError('There was an error processing your request.');
}
/* Right now $_GET['id'] is needed for all pages, but potentially you could
* login and not need it, so this should handle all cases. */
if (array_key_exists('id', $_GET) && is_numeric($_GET['id'])) {
$_addon = "?id={$_GET['id']}";
} else {
$_addon = '';
}
header("Location: {$_next_page}{$_addon}");
exit;
} else {
$login_error = true;
}
}
// Assign template variables.
$tpl->assign(
array( 'title' => 'Firefox Add-ons Login',
'currentTab' => null,
'login_error' => $login_error
)
);
?>

View File

@@ -0,0 +1,23 @@
<?php
/**
* This will delete a session if the user has one.
*
* @package amo
* @subpackage docs
*
*/
startProcessing('logout.tpl', null, null, 'nonav');
require_once 'includes.php';
session_start();
session_destroy();
// Assign template variables.
$tpl->assign(
array( 'title' => 'Firefox Add-ons',
'currentTab' => null
)
);
?>

View File

@@ -4,6 +4,7 @@ require_once('DB.php'); // PEAR::DB
require_once('Auth.php'); // PEAR::Auth
require_once(LIB.'/amo.class.php');
require_once(LIB.'/addon.class.php');
require_once(LIB.'/auth.class.php');
require_once(LIB.'/error.php');
require_once(LIB.'/rdf.class.php');
require_once(LIB.'/rss.class.php');
@@ -38,14 +39,15 @@ class AMO_SQL extends SQL
$db = new AMO_SQL();
if (USE_DB_SESSIONS)
{
$amo_session_handler = new AMO_Session($db);
session_set_save_handler(array(&$amo_session_handler, '_open'),
array(&$amo_session_handler, '_close'),
array(&$amo_session_handler, '_read'),
array(&$amo_session_handler, '_write'),
array(&$amo_session_handler, '_destroy'),
array(&$amo_session_handler, '_gc'));
}
// Setup the session for the secure pages
$_auth = new AMO_Auth();
session_set_save_handler(
array(&$_auth, "_openSession"),
array(&$_auth, "_closeSession"),
array(&$_auth, "_readSession"),
array(&$_auth, "_writeSession"),
array(&$_auth, "_destroySession"),
array(&$_auth, "_gcSession")
);
?>

View File

@@ -0,0 +1,35 @@
<h1>{$addon->Name|escape} - Firefox Extension</h1>
<p>{$addon->Name|escape} {$addon->Version|escape}, by {$addon->UserName|escape} released on {$addon->DateUpdated|date_format:"%B %d, %Y"}</p>
<h2 class="first">Your comments about {$addon->Name|escape}</h2>
<div class="front-section">
<form id="commentform" name="commentform" method="post" action="">
<label for="c_rating">Rating:</label>
<select id="c_rating" name="c_rating">
{html_options values=$rate_select_value output=$rate_select_name selected=$c_rating_value}
</select>
{if $c_errors.c_rating}
<div>
<p>Please choose a rating.</p>
</div>
{/if}
<label for="c_title">Title:</label>
<input type="text" id="c_title" name="c_title" value="{$c_title_value|escape}"/>
{if $c_errors.c_title}
<div>
<p>Please provide a title with your comments.</p>
</div>
{/if}
<label for="c_comments">Comments:</label>
<textarea id="c_comments" name="c_comments">{$c_comments_value|escape}</textarea>
{if $c_errors.c_comments}
<div>
<p>Please include some valid comments.</p>
</div>
{/if}
<input type="submit" id="c_submit" name="c_submit" value="Post" />
<p>All fields are required.</p>
</form>
</div>

View File

@@ -0,0 +1,20 @@
<h1 class="first">Login</h1>
<div class="front-section">
{if $login_error}
<div>
<p>You were not successfully logged in. Check your e-mail address and
password and try again.</p>
</div>
{/if}
<form id="front-login" method="post" action="" title="Login to Firefox Add-ons">
<div>
<label for="username" title="E-Mail Address">E-Mail Address:</label>
<input id="username" name="username" type="text" accesskey="u" size="40">
<label for="password" title="Password">Password:</label>
<input id="password" name="password" type="password" accesskey="p" size="40">
<input type="submit" value="Go">
</div>
</form>
</div>

View File

@@ -0,0 +1,6 @@
<h1 class="first">Logout</h1>
<div class="front-section">
Your login information has been forgotten.
</div>

View File

@@ -0,0 +1,291 @@
<?php
/**
* Authentication class. Will handle all session functions. Note that database
* layout is hardcoded into this class. If this class is used anywhere but AMO, it
* will need that pulled out and put into class variables (for example, column names,
* etc.)
*
* Class is roughly based on some examples from php.net
*
* @package amo
* @subpackage lib
*
*/
require_once 'amo.class.php';
class AMO_Auth extends AMO_Object{
/**
* How long the sessions should be.
* @access private
* @var int;
*/
var $_expires = 0;
/**
* UserID of the person logging in
* @access private
* @var int;
*/
var $_user_id = null;
/**
* Name of the user table
* @access private
* @var string;
*/
var $_user_table = 'userprofiles';
/**
* Name of the sessions table to store data in.
* @access private
* @var string;
*/
var $_session_table = 'session_data';
/**
* Constructor for the AMO Authentication object
* @access public
*/
function AMO_Auth()
{
parent::AMO_Object();
$this->_expires = get_cfg_var('session.gc_maxlifetime');
}
/**
* Dummy function, we don't need it but session_set_save_handler() requires it
* @access private
* @param string path to save files (NOT USED)
* @param string name of file (NOT USED)
* @return bool true
*/
function _openSession($path, $name)
{
return true;
}
/**
* This function will actually create the row in the database for the function.
* session_start() needs to be called before this function.
* @access private
* @return bool true
*/
function createSession()
{
if (is_null($this->_user_id)) {
// We're storing the userid in this object (it get's put in there when
// the person authenticates. If the field is empty, there isn't really
// any point to starting a session, so we just return.
return false;
}
// technically, none of these should need escaping, but hey...
$_id = mysql_real_escape_string(session_id());
$_user_id = mysql_real_escape_string($this->_user_id);
$_expires = mysql_real_escape_string(time() + $this->_expires);
$_sql = "INSERT INTO `{$this->_session_table}`
( `sess_id`,
`sess_user_id`,
`sess_expires`,
`sess_data`
) VALUES (
'{$_id}',
'{$_user_id}',
'{$_expires}',
''
)";
$this->db->query($_sql);
return true;
}
/**
* Dummy function, we don't need it but session_set_save_handler() requires it
* @access private
* @return bool true
*/
function _closeSession()
{
return true;
}
/**
* Pulls data from the session (database in our case)
* @access private
* @param string session id
* @return string with data from session, or empty on empty session or failure
*/
function _readSession($id)
{
$_id = mysql_real_escape_string($id);
$_sql = "SELECT
`sess_data`
FROM
`{$this->_session_table}`
WHERE
`sess_id`={$_id}
AND
`sess_expires` > CURRENT_TIMESTAMP()";
$this->db->query($_sql, SQL_INIT, SQL_ASSOC);
if (!empty($this->db->record)){
return $this->db->record;
} else {
return '';
}
}
/**
* Push data into the session (into the database)
* @access private
* @param string session id
* @param string data to store
* @return bool true on success, false on failure
*/
function _writeSession($id, $data)
{
if (is_null($this->_user_id)) {
// We're storing the userid in this object (it get's put in there when
// the person authenticates. If the field is empty, there isn't really
// any point to starting a session, so we just return.
return false;
}
// An extra check, otherwise session_start() would start valid sessions
if ($this->validSession()){
$_id = mysql_real_escape_string($id);
$_user_id = mysql_real_escape_string($this->_user_id);
$_data = mysql_real_escape_string($data);
$_expires = mysql_real_escape_string(time() + $this->_expires);
$_sql = "REPLACE INTO
`{$this->_session_table}`
( `sess_id`,
`sess_user_id`,
`sess_expires`,
`sess_data`
) VALUES (
'{$_id}',
'{$_user_id},
'{$_expires}',
'{$_data}'
)";
$this->db->query($_sql, SQL_INIT, SQL_ASSOC);
return true;
}
return false;
}
/**
* Checks if the current session is valid or not. session_start() needs to be
* called before this.
* @access public
* @return bool true if valid, false if not
*/
function validSession()
{
$_session_id = mysql_real_escape_string(session_id());
$_sql = "SELECT
`sess_id`
FROM
`{$this->_session_table}`
WHERE
`sess_id` = '{$_session_id}'
LIMIT 1";
$this->db->query($_sql, SQL_INIT, SQL_ASSOC);
if (!empty($this->db->record)){
return true;
} else {
return false;
}
}
/**
* Checks if the user should be able to start a session with us (looks them up
* in the user table)
* @access public
* @param string $username
* @param string $password
* @return bool true on success, false on failure
*/
function authenticate($username,$password)
{
if (empty($username)||empty($password)) {
return false;
}
$_username = trim(mysql_real_escape_string($username));
$_password = trim(mysql_real_escape_string($password));
$_sql = "SELECT
`UserID`
FROM
`{$this->_user_table}`
WHERE
`UserEmail`='{$_username}'
AND
`UserPass`=MD5('{$_password}')
AND
`UserMode` != 'D'
LIMIT 1";
$this->db->query($_sql, SQL_INIT, SQL_ASSOC);
if (!empty($this->db->record)) {
$_record = $this->db->record;
$this->_user_id = $_record['UserID'];
return true;
} else {
return false;
}
}
/**
* Destroys the current session
* @access private
* @param string session id
* @return bool true
*/
function _destroySession($id)
{
$_id = mysql_real_escape_string($id);
$_sql = "DELETE FROM
`{$this->_session_table}`
WHERE
`sess_id` ='{$_id}'";
$this->db->query($_sql);
$this->_user_id = null;
$_COOKIE = array();
$_SESSION = array();
setcookie(session_name(), '', time()-42000, '/');
return true;
}
/**
* Clean out stale sessions
* @access private
* @return bool true
*/
function _gcSession()
{
$_sql = "DELETE FROM
`{$this->_session_table}`
WHERE
`sess_expires` < CURRENT_TIMESTAMP()";
$this->db->query($_sql);
return true;
}
}
?>