Merge branch '0.9.x' into mapstraction

This commit is contained in:
Evan Prodromou 2009-11-18 09:20:31 -05:00
commit fa35dab226
9 changed files with 658 additions and 44 deletions

6
README
View File

@ -852,6 +852,12 @@ locale_path: full path to the directory for locale data. Unless you
store all your locale data in one place, you probably store all your locale data in one place, you probably
don't need to use this. don't need to use this.
language: default language for your site. Defaults to US English. language: default language for your site. Defaults to US English.
Note that this is overridden if a user is logged in and has
selected a different language. It is also overridden if the
user is NOT logged in, but their browser requests a different
langauge. Since pretty much everybody's browser requests a
language, that means that changing this setting has little or
no effect in practice.
languages: A list of languages supported on your site. Typically you'd languages: A list of languages supported on your site. Typically you'd
only change this if you wanted to disable support for one only change this if you wanted to disable support for one
or another language: or another language:

View File

@ -47,6 +47,10 @@ if (!defined('STATUSNET')) {
class DesignadminpanelAction extends AdminPanelAction class DesignadminpanelAction extends AdminPanelAction
{ {
/* The default site design */
var $design = null;
/** /**
* Returns the page title * Returns the page title
* *
@ -77,6 +81,8 @@ class DesignadminpanelAction extends AdminPanelAction
function showForm() function showForm()
{ {
$this->design = Design::siteDesign();
$form = new DesignAdminPanelForm($this); $form = new DesignAdminPanelForm($this);
$form->show(); $form->show();
return; return;
@ -90,8 +96,44 @@ class DesignadminpanelAction extends AdminPanelAction
function saveSettings() function saveSettings()
{ {
static $settings = array('theme'); if ($this->arg('save')) {
$this->saveDesignSettings();
} else if ($this->arg('defaults')) {
$this->restoreDefaults();
} else {
$this->success = false;
$this->message = 'Unexpected form submission.';
}
}
/**
* Save the new design settings
*
* @return void
*/
function saveDesignSettings()
{
// Workaround for PHP returning empty $_POST and $_FILES when POST
// length > post_max_size in php.ini
if (empty($_FILES)
&& empty($_POST)
&& ($_SERVER['CONTENT_LENGTH'] > 0)
) {
$msg = _('The server was unable to handle that much POST ' .
'data (%s bytes) due to its current configuration.');
$this->success = false;
$this->msg = $e->getMessage(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
return;
}
// check for an image upload
$bgimage = $this->saveBackgroundImage();
static $settings = array('theme');
$values = array(); $values = array();
foreach ($settings as $setting) { foreach ($settings as $setting) {
@ -99,6 +141,30 @@ class DesignadminpanelAction extends AdminPanelAction
} }
// This throws an exception on validation errors // This throws an exception on validation errors
try {
$bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content'));
$sbcolor = new WebColor($this->trimmed('design_sidebar'));
$tcolor = new WebColor($this->trimmed('design_text'));
$lcolor = new WebColor($this->trimmed('design_links'));
} catch (WebColorException $e) {
$this->success = false;
$this->msg = $e->getMessage();
return;
}
$onoff = $this->arg('design_background-image_onoff');
$on = false;
$off = false;
if ($onoff == 'on') {
$on = true;
} else {
$off = true;
}
$tile = $this->boolean('design_background-image_repeat');
$this->validate($values); $this->validate($values);
@ -112,21 +178,163 @@ class DesignadminpanelAction extends AdminPanelAction
Config::save('site', $setting, $values[$setting]); Config::save('site', $setting, $values[$setting]);
} }
if (isset($bgimage)) {
Config::save('design', 'backgroundimage', $bgimage);
}
Config::save('design', 'backgroundcolor', $bgcolor->intValue());
Config::save('design', 'contentcolor', $ccolor->intValue());
Config::save('design', 'sidebarcolor', $sbcolor->intValue());
Config::save('design', 'textcolor', $tcolor->intValue());
Config::save('design', 'linkcolor', $lcolor->intValue());
// Hack to use Design's bit setter
$scratch = new Design();
$scratch->setDisposition($on, $off, $tile);
Config::save('design', 'disposition', $scratch->disposition);
$config->query('COMMIT'); $config->query('COMMIT');
return; return;
} }
/**
* Delete a design setting
*
* @return mixed $result false if something didn't work
*/
function deleteSetting($section, $setting)
{
$config = new Config();
$config->section = $section;
$config->setting = $setting;
if ($config->find(true)) {
$result = $config->delete();
if (!$result) {
common_log_db_error($config, 'DELETE', __FILE__);
$this->clientError(_("Unable to delete design setting."));
return null;
}
}
return $result;
}
/**
* Restore the default design
*
* @return void
*/
function restoreDefaults()
{
$this->deleteSetting('site', 'theme');
$settings = array(
'theme', 'backgroundimage', 'backgroundcolor', 'contentcolor',
'sidebarcolor', 'textcolor', 'linkcolor', 'disposition'
);
foreach ($settings as $setting) {
$this->deleteSetting('design', $setting);
}
}
/**
* Save the background image if the user uploaded one
*
* @return string $filename the filename of the image
*/
function saveBackgroundImage()
{
$filename = null;
if ($_FILES['design_background-image_file']['error'] ==
UPLOAD_ERR_OK) {
$filepath = null;
try {
$imagefile =
ImageFile::fromUpload('design_background-image_file');
} catch (Exception $e) {
$this->success = false;
$this->msg = $e->getMessage();
return;
}
// Note: site design background image has a special filename
$filename = Design::filename('site-design-background',
image_type_to_extension($imagefile->type),
common_timestamp());
$filepath = Design::path($filename);
move_uploaded_file($imagefile->filepath, $filepath);
// delete any old backround img laying around
if (isset($this->design->backgroundimage)) {
@unlink(Design::path($design->backgroundimage));
}
return $filename;
}
}
/**
* Attempt to validate setting values
*
* @return void
*/
function validate(&$values) function validate(&$values)
{ {
if (!in_array($values['theme'], Theme::listAvailable())) { if (!in_array($values['theme'], Theme::listAvailable())) {
$this->clientError(sprintf(_("Theme not available: %s"), $values['theme'])); $this->clientError(sprintf(_("Theme not available: %s"), $values['theme']));
} }
} }
/**
* Add the Farbtastic stylesheet
*
* @return void
*/
function showStylesheets()
{
parent::showStylesheets();
$this->cssLink('css/farbtastic.css','base','screen, projection, tv');
}
/**
* Add the Farbtastic scripts
*
* @return void
*/
function showScripts()
{
parent::showScripts();
$this->script('js/farbtastic/farbtastic.js');
$this->script('js/userdesign.go.js');
$this->autofocus('design_background-image_file');
}
} }
class DesignAdminPanelForm extends Form class DesignAdminPanelForm extends Form
{ {
/** /**
* ID of the form * ID of the form
* *
@ -149,6 +357,22 @@ class DesignAdminPanelForm extends Form
return 'form_settings'; return 'form_settings';
} }
/**
* HTTP method used to submit the form
*
* For image data we need to send multipart/form-data
* so we set that here too
*
* @return string the method to use for submitting
*/
function method()
{
$this->enctype = 'multipart/form-data';
return 'post';
}
/** /**
* Action of the form * Action of the form
* *
@ -168,21 +392,179 @@ class DesignAdminPanelForm extends Form
function formData() function formData()
{ {
$design = $this->out->design;
$themes = Theme::listAvailable(); $themes = Theme::listAvailable();
asort($themes); asort($themes);
$themes = array_combine($themes, $themes); $themes = array_combine($themes, $themes);
$this->out->elementStart('fieldset', array('id' =>
'settings_design_theme'));
$this->out->element('legend', null, _('Change theme'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
$this->out->elementStart('li');
$this->out->elementStart('li');
$this->out->dropdown('theme', _('Theme'), $this->out->dropdown('theme', _('Theme'),
$themes, _('Theme for the site.'), $themes, _('Theme for the site.'),
true, $this->value('theme')); false, $this->value('theme'));
$this->out->elementEnd('li'); $this->out->elementEnd('li');
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
$this->out->elementStart('fieldset', array('id' =>
'settings_design_background-image'));
$this->out->element('legend', null, _('Change background image'));
$this->out->elementStart('ul', 'form_data');
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'design_background-image_file'),
_('Background'));
$this->out->element('input', array('name' => 'design_background-image_file',
'type' => 'file',
'id' => 'design_background-image_file'));
$this->out->element('p', 'form_guide',
sprintf(_('You can upload a background image for the site. ' .
'The maximum file size is %1$s.'), ImageFile::maxFileSize()));
$this->out->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt()));
$this->out->elementEnd('li');
if (!empty($design->backgroundimage)) {
$this->out->elementStart('li', array('id' =>
'design_background-image_onoff'));
$this->out->element('img', array('src' =>
Design::url($design->backgroundimage)));
$attrs = array('name' => 'design_background-image_onoff',
'type' => 'radio',
'id' => 'design_background-image_on',
'class' => 'radio',
'value' => 'on');
if ($design->disposition & BACKGROUND_ON) {
$attrs['checked'] = 'checked';
}
$this->out->element('input', $attrs);
$this->out->element('label', array('for' => 'design_background-image_on',
'class' => 'radio'),
_('On'));
$attrs = array('name' => 'design_background-image_onoff',
'type' => 'radio',
'id' => 'design_background-image_off',
'class' => 'radio',
'value' => 'off');
if ($design->disposition & BACKGROUND_OFF) {
$attrs['checked'] = 'checked';
}
$this->out->element('input', $attrs);
$this->out->element('label', array('for' => 'design_background-image_off',
'class' => 'radio'),
_('Off'));
$this->out->element('p', 'form_guide', _('Turn background image on or off.'));
$this->out->elementEnd('li');
$this->out->elementStart('li');
$this->out->checkbox('design_background-image_repeat',
_('Tile background image'),
($design->disposition & BACKGROUND_TILE) ? true : false);
$this->out->elementEnd('li');
}
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
$this->out->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->out->element('legend', null, _('Change colours'));
$this->out->elementStart('ul', 'form_data');
try {
$bgcolor = new WebColor($design->backgroundcolor);
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'swatch-1'), _('Background'));
$this->out->element('input', array('name' => 'design_background',
'type' => 'text',
'id' => 'swatch-1',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => ''));
$this->out->elementEnd('li');
$ccolor = new WebColor($design->contentcolor);
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'swatch-2'), _('Content'));
$this->out->element('input', array('name' => 'design_content',
'type' => 'text',
'id' => 'swatch-2',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => ''));
$this->out->elementEnd('li');
$sbcolor = new WebColor($design->sidebarcolor);
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'swatch-3'), _('Sidebar'));
$this->out->element('input', array('name' => 'design_sidebar',
'type' => 'text',
'id' => 'swatch-3',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => ''));
$this->out->elementEnd('li');
$tcolor = new WebColor($design->textcolor);
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'swatch-4'), _('Text'));
$this->out->element('input', array('name' => 'design_text',
'type' => 'text',
'id' => 'swatch-4',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => ''));
$this->out->elementEnd('li');
$lcolor = new WebColor($design->linkcolor);
$this->out->elementStart('li');
$this->out->element('label', array('for' => 'swatch-5'), _('Links'));
$this->out->element('input', array('name' => 'design_links',
'type' => 'text',
'id' => 'swatch-5',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => ''));
$this->out->elementEnd('li');
} catch (WebColorException $e) {
common_log(LOG_ERR, 'Bad color values in site design: ' .
$e->getMessage());
}
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
} }
/** /**
@ -226,6 +608,15 @@ class DesignAdminPanelForm extends Form
function formActions() function formActions()
{ {
$this->out->submit('submit', _('Save'), 'submit', null, _('Save site settings')); $this->out->submit('defaults', _('Use defaults'), 'submit form_action-default',
} 'defaults', _('Restore default designs'));
$this->out->element('input', array('id' => 'settings_design_reset',
'type' => 'reset',
'value' => 'Reset',
'class' => 'submit form_action-primary',
'title' => _('Reset back to default')));
$this->out->submit('save', _('Save'), 'submit form_action-secondary',
'save', _('Save design')); }
} }

View File

@ -571,11 +571,11 @@ create table user_role (
); );
create table login_token ( create table login_token (
user_id integer not null /* comment 'user owning this token'*/ references user (id), user_id integer not null /* comment 'user owning this token'*/ references "user" (id),
token char(32) not null /* comment 'token useable for logging in'*/, token char(32) not null /* comment 'token useable for logging in'*/,
created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created'*/, created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created'*/,
modified timestamp /* comment 'date this record was modified'*/, modified timestamp /* comment 'date this record was modified'*/,
constraint primary key (user_id) primary key (user_id)
); );

View File

@ -67,7 +67,7 @@ class Form extends Widget
{ {
$attributes = array('id' => $this->id(), $attributes = array('id' => $this->id(),
'class' => $this->formClass(), 'class' => $this->formClass(),
'method' => 'post', 'method' => $this->method(),
'action' => $this->action()); 'action' => $this->action());
if (!empty($this->enctype)) { if (!empty($this->enctype)) {
@ -119,6 +119,18 @@ class Form extends Widget
{ {
} }
/**
* HTTP method used to submit the form
*
* Defaults to post. Subclasses can override if they need to.
*
* @return string the method to use for submitting
*/
function method()
{
return 'post';
}
/** /**
* Buttons for form actions * Buttons for form actions
* *

View File

@ -46,6 +46,7 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin
public $options=null; public $options=null;
public $filter=null; public $filter=null;
public $scope=null; public $scope=null;
public $password_encoding=null;
public $attributes=array(); public $attributes=array();
function onInitializePlugin(){ function onInitializePlugin(){
@ -68,10 +69,6 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin
function checkPassword($username, $password) function checkPassword($username, $password)
{ {
$ldap = $this->ldap_get_connection();
if(!$ldap){
return false;
}
$entry = $this->ldap_get_user($username); $entry = $this->ldap_get_user($username);
if(!$entry){ if(!$entry){
return false; return false;
@ -109,8 +106,38 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin
function changePassword($username,$oldpassword,$newpassword) function changePassword($username,$oldpassword,$newpassword)
{ {
//TODO implement this if(! isset($this->attributes['password']) || !isset($this->password_encoding)){
throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); //throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time'));
return false;
}
$entry = $this->ldap_get_user($username);
if(!$entry){
return false;
}else{
$config = $this->ldap_get_config();
$config['binddn']=$entry->dn();
$config['bindpw']=$oldpassword;
if($ldap = $this->ldap_get_connection($config)){
$entry = $this->ldap_get_user($username,array(),$ldap);
$newCryptedPassword = $this->hashPassword($newpassword, $this->password_encoding);
if ($newCryptedPassword===false) {
return false;
}
if($this->password_encoding=='ad') {
//TODO I believe this code will work once this bug is fixed: http://pear.php.net/bugs/bug.php?id=16796
$oldCryptedPassword = $this->hashPassword($oldpassword, $this->password_encoding);
$entry->delete( array($this->attributes['password'] => $oldCryptedPassword ));
}
$entry->replace( array($this->attributes['password'] => $newCryptedPassword ), true);
if( Net_LDAP2::isError($entry->upate()) ) {
return false;
}
return true;
}else{
return false;
}
}
return false; return false;
} }
@ -153,8 +180,10 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin
* $param array $attributes LDAP attributes to retrieve * $param array $attributes LDAP attributes to retrieve
* @return string DN * @return string DN
*/ */
function ldap_get_user($username,$attributes=array()){ function ldap_get_user($username,$attributes=array(),$ldap=null){
if($ldap==null) {
$ldap = $this->ldap_get_connection(); $ldap = $this->ldap_get_connection();
}
$filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username); $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username);
$options = array( $options = array(
'scope' => 'sub', 'scope' => 'sub',
@ -177,4 +206,123 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin
return false; return false;
} }
} }
/**
* Code originaly from the phpLDAPadmin development team
* http://phpldapadmin.sourceforge.net/
*
* Hashes a password and returns the hash based on the specified enc_type.
*
* @param string $passwordClear The password to hash in clear text.
* @param string $encodageType Standard LDAP encryption type which must be one of
* crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, or clear.
* @return string The hashed password.
*
*/
function hashPassword( $passwordClear, $encodageType )
{
$encodageType = strtolower( $encodageType );
switch( $encodageType ) {
case 'crypt':
$cryptedPassword = '{CRYPT}' . crypt($passwordClear,$this->randomSalt(2));
break;
case 'ext_des':
// extended des crypt. see OpenBSD crypt man page.
if ( ! defined( 'CRYPT_EXT_DES' ) || CRYPT_EXT_DES == 0 ) {return FALSE;} //Your system crypt library does not support extended DES encryption.
$cryptedPassword = '{CRYPT}' . crypt( $passwordClear, '_' . $this->randomSalt(8) );
break;
case 'md5crypt':
if( ! defined( 'CRYPT_MD5' ) || CRYPT_MD5 == 0 ) {return FALSE;} //Your system crypt library does not support md5crypt encryption.
$cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$1$' . $this->randomSalt(9) );
break;
case 'blowfish':
if( ! defined( 'CRYPT_BLOWFISH' ) || CRYPT_BLOWFISH == 0 ) {return FALSE;} //Your system crypt library does not support blowfish encryption.
$cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$2a$12$' . $this->randomSalt(13) ); // hardcoded to second blowfish version and set number of rounds
break;
case 'md5':
$cryptedPassword = '{MD5}' . base64_encode( pack( 'H*' , md5( $passwordClear) ) );
break;
case 'sha':
if( function_exists('sha1') ) {
// use php 4.3.0+ sha1 function, if it is available.
$cryptedPassword = '{SHA}' . base64_encode( pack( 'H*' , sha1( $passwordClear) ) );
} elseif( function_exists( 'mhash' ) ) {
$cryptedPassword = '{SHA}' . base64_encode( mhash( MHASH_SHA1, $passwordClear) );
} else {
return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes.
}
break;
case 'ssha':
if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) {
mt_srand( (double) microtime() * 1000000 );
$salt = mhash_keygen_s2k( MHASH_SHA1, $passwordClear, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 );
$cryptedPassword = "{SSHA}".base64_encode( mhash( MHASH_SHA1, $passwordClear.$salt ).$salt );
} else {
return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes.
}
break;
case 'smd5':
if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) {
mt_srand( (double) microtime() * 1000000 );
$salt = mhash_keygen_s2k( MHASH_MD5, $passwordClear, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 );
$cryptedPassword = "{SMD5}".base64_encode( mhash( MHASH_MD5, $passwordClear.$salt ).$salt );
} else {
return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes.
}
break;
case 'ad':
$cryptedPassword = '';
$passwordClear = "\"" . $passwordClear . "\"";
$len = strlen($passwordClear);
for ($i = 0; $i < $len; $i++) {
$cryptedPassword .= "{$passwordClear{$i}}\000";
}
case 'clear':
default:
$cryptedPassword = $passwordClear;
}
return $cryptedPassword;
}
/**
* Code originaly from the phpLDAPadmin development team
* http://phpldapadmin.sourceforge.net/
*
* Used to generate a random salt for crypt-style passwords. Salt strings are used
* to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses
* not only the user's password but also a randomly generated string. The string is
* stored as the first N characters of the hash for reference of hashing algorithms later.
*
* --- added 20021125 by bayu irawan <bayuir@divnet.telkom.co.id> ---
* --- ammended 20030625 by S C Rigler <srigler@houston.rr.com> ---
*
* @param int $length The length of the salt string to generate.
* @return string The generated salt string.
*/
function randomSalt( $length )
{
$possible = '0123456789'.
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'./';
$str = "";
mt_srand((double)microtime() * 1000000);
while( strlen( $str ) < $length )
$str .= substr( $possible, ( rand() % strlen( $possible ) ), 1 );
return $str;
}
} }

View File

@ -18,6 +18,9 @@ email_changeable (true): Are users allowed to change their email address?
(true or false) (true or false)
password_changeable (true): Are users allowed to change their passwords? password_changeable (true): Are users allowed to change their passwords?
(true or false) (true or false)
password_encoding: required if users are to be able to change their passwords
Possible values are: crypt, ext_des, md5crypt, blowfish, md5, sha, ssha,
smd5, ad, clear
host*: LDAP server name to connect to. You can provide several hosts in an host*: LDAP server name to connect to. You can provide several hosts in an
array in which case the hosts are tried from left to right. array in which case the hosts are tried from left to right.
@ -47,6 +50,7 @@ attributes: an array that relates StatusNet user attributes to LDAP ones
fullname fullname
homepage homepage
location location
password: required if users are to be able to change their passwords
* required * required
default values are in (parenthesis) default values are in (parenthesis)
@ -67,10 +71,12 @@ addPlugin('ldapAuthentication', array(
'bindpw'=>'password', 'bindpw'=>'password',
'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc',
'host'=>array('server1', 'server2'), 'host'=>array('server1', 'server2'),
'password_encoding'=>'ad',
'attributes'=>array( 'attributes'=>array(
'username'=>'sAMAccountName', 'username'=>'sAMAccountName',
'nickname'=>'sAMAccountName', 'nickname'=>'sAMAccountName',
'email'=>'mail', 'email'=>'mail',
'fullname'=>'displayName') 'fullname'=>'displayName',
'password'=>'unicodePwd')
)); ));

View File

@ -34,6 +34,8 @@ RealtimeUpdate = {
_favorurl: '', _favorurl: '',
_deleteurl: '', _deleteurl: '',
_updatecounter: 0, _updatecounter: 0,
_maxnotices: 50,
_windowhasfocus: true,
init: function(userid, replyurl, favorurl, deleteurl) init: function(userid, replyurl, favorurl, deleteurl)
{ {
@ -44,13 +46,16 @@ RealtimeUpdate = {
DT = document.title; DT = document.title;
$(window).blur(function() { $(window).bind('focus', function(){ RealtimeUpdate._windowhasfocus = true; });
$(window).bind('blur', function() {
$('#notices_primary .notice').removeClass('mark-top'); $('#notices_primary .notice').removeClass('mark-top');
$('#notices_primary .notice:first').addClass('mark-top'); $('#notices_primary .notice:first').addClass('mark-top');
RealtimeUpdate._updatecounter = 0; RealtimeUpdate._updatecounter = 0;
document.title = DT; document.title = DT;
RealtimeUpdate._windowhasfocus = false;
return false; return false;
}); });
@ -58,7 +63,6 @@ RealtimeUpdate = {
receive: function(data) receive: function(data)
{ {
setTimeout(function() {
id = data.id; id = data.id;
// Don't add it if it already exists // Don't add it if it already exists
@ -70,11 +74,21 @@ RealtimeUpdate = {
$("#notices_primary .notices").prepend(noticeItem); $("#notices_primary .notices").prepend(noticeItem);
$("#notices_primary .notice:first").css({display:"none"}); $("#notices_primary .notice:first").css({display:"none"});
$("#notices_primary .notice:first").fadeIn(1000); $("#notices_primary .notice:first").fadeIn(1000);
SN.U.NoticeReply();
if ($('#notices_primary .notice').length > RealtimeUpdate._maxnotices) {
$("#notices_primary .notice:last .form_disfavor").unbind('submit');
$("#notices_primary .notice:last .form_favor").unbind('submit');
$("#notices_primary .notice:last .notice_reply").unbind('click');
$("#notices_primary .notice:last").remove();
}
SN.U.NoticeReply();
SN.U.NoticeFavor();
if (RealtimeUpdate._windowhasfocus === false) {
RealtimeUpdate._updatecounter += 1; RealtimeUpdate._updatecounter += 1;
document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; document.title = '('+RealtimeUpdate._updatecounter+') ' + DT;
}, 500); }
}, },
makeNoticeItem: function(data) makeNoticeItem: function(data)
@ -178,9 +192,9 @@ RealtimeUpdate = {
}); });
$('#showstream #notices_primary').css({'margin-top':'18px'}); $('#showstream #notices_primary').css({'margin-top':'18px'});
RT.click(function() { RT.bind('click', function() {
window.open(url, window.open(url,
timeline, '',
'toolbar=no,resizable=yes,scrollbars=yes,status=yes,width=500,height=550'); 'toolbar=no,resizable=yes,scrollbars=yes,status=yes,width=500,height=550');
return false; return false;
@ -208,6 +222,12 @@ RealtimeUpdate = {
'left':'auto', 'left':'auto',
'right':'0' 'right':'0'
}); });
$('.notices .entry-title a, .notices .entry-content a').bind('click', function() {
window.open(this.href, '');
return false;
});
} }
} }

View File

@ -122,8 +122,15 @@ float:left;
.form_settings .form_data input { .form_settings .form_data input {
margin-left:1.795%; margin-left:1.795%;
float:left; float:left;
}
.form_settings .form_data input {
width:39%; width:39%;
} }
.form_settings .form_data input.submit,
.form_settings .form_data input.checkbox,
.form_settings .form_data input.radio {
width:auto;
}
.form_settings .form_data textarea { .form_settings .form_data textarea {
width:63%; width:63%;
} }
@ -165,7 +172,8 @@ font-weight:bold;
#form_password_recover legend, #form_password_recover legend,
#form_password_change legend, #form_password_change legend,
.form_entity_block legend, .form_entity_block legend,
#form_filter_bytag legend { #form_filter_bytag legend,
#settings_design_theme legend {
display:none; display:none;
} }
@ -558,7 +566,7 @@ font-weight:bold;
/* entity_profile */ /* entity_profile */
.entity_profile { .entity_profile {
position:relative; position:relative;
width:74.702%; width:73%;
min-height:123px; min-height:123px;
float:left; float:left;
margin-bottom:18px; margin-bottom:18px;
@ -629,9 +637,9 @@ font-style:italic;
/*entity_actions*/ /*entity_actions*/
.entity_actions { .entity_actions {
float:right; float:right;
margin-left:2.35%; margin-left:2%;
margin-bottom:18px; margin-bottom:18px;
width:21%; min-width:21%;
} }
.entity_actions h2 { .entity_actions h2 {
display:none; display:none;
@ -1325,16 +1333,16 @@ clear:both;
margin-bottom:0; margin-bottom:0;
} }
#form_settings_design #settings_design_background-image img { #settings_design_background-image img {
max-width:480px; max-width:480px;
max-height:480px; max-height:480px;
} }
#form_settings_design #settings_design_color .form_data, #settings_design_color .form_data,
#form_settings_design #color-picker { #color-picker {
float:left; float:left;
} }
#form_settings_design #settings_design_color .form_data { #settings_design_color .form_data {
width:400px; width:400px;
margin-right:28px; margin-right:28px;
} }

View File

@ -135,7 +135,8 @@ button.close,
.form_group_leave input.submit, .form_group_leave input.submit,
.form_user_unsubscribe input.submit, .form_user_unsubscribe input.submit,
.form_group_join input.submit, .form_group_join input.submit,
.form_user_subscribe input.submit { .form_user_subscribe input.submit,
.entity_subscribe a {
background-image:url(../../base/images/icons/icons-01.gif); background-image:url(../../base/images/icons/icons-01.gif);
background-repeat:no-repeat; background-repeat:no-repeat;
background-color:transparent; background-color:transparent;
@ -178,6 +179,12 @@ background-color:rgba(255, 255, 255, 0.7);
#site_nav_local_views .current a { #site_nav_local_views .current a {
text-shadow: rgba(194,194,194,0.5) 1px 1px 1px; text-shadow: rgba(194,194,194,0.5) 1px 1px 1px;
} }
.processing {
background-image:url(../../base/images/icons/icon_processing.gif);
background-repeat:no-repeat;
background-position:47% 47%;
}
.error { .error {
background-color:#F7E8E8; background-color:#F7E8E8;
@ -216,7 +223,8 @@ background-position:0 1px;
.form_group_join input.submit, .form_group_join input.submit,
.form_group_leave input.submit, .form_group_leave input.submit,
.form_user_subscribe input.submit, .form_user_subscribe input.submit,
.form_user_unsubscribe input.submit { .form_user_unsubscribe input.submit,
.entity_subscribe a {
background-color:#AAAAAA; background-color:#AAAAAA;
color:#FFFFFF; color:#FFFFFF;
} }
@ -225,7 +233,8 @@ color:#FFFFFF;
background-position:5px -1246px; background-position:5px -1246px;
} }
.form_group_join input.submit, .form_group_join input.submit,
.form_user_subscribe input.submit { .form_user_subscribe input.submit,
.entity_subscribe a {
background-position:5px -1181px; background-position:5px -1181px;
} }
@ -328,3 +337,17 @@ background-position:10% -187px;
.pagination .nav_next a { .pagination .nav_next a {
background-position:105% -252px; background-position:105% -252px;
} }
.pagination .nav .processing {
background-image:url(../../base/images/icons/icon_processing.gif);
box-shadow:none;
-moz-box-shadow:none;
-webkit-box-shadow:none;
outline:none;
}
.pagination .nav_next a.processing {
background-position:90% 47%;
}
.pagination .nav_prev a.processing {
background-position:10% 47%;
}