diff options
author | Evan Prodromou <evan@status.net> | 2009-11-18 09:20:31 -0500 |
---|---|---|
committer | Evan Prodromou <evan@status.net> | 2009-11-18 09:20:31 -0500 |
commit | fa35dab2265aba78f7c704c34eaef4100bddfd70 (patch) | |
tree | d12a78861162672e87e0c1330133d09aff651009 | |
parent | 1cc10aaef63830ead662d8a962373554a949c951 (diff) | |
parent | 007418fdab8f9f0c718a18568bfbf4377bb85364 (diff) |
Merge branch '0.9.x' into mapstraction
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | actions/designadminpanel.php | 401 | ||||
-rw-r--r-- | db/statusnet_pg.sql | 4 | ||||
-rw-r--r-- | lib/form.php | 14 | ||||
-rw-r--r-- | plugins/LdapAuthentication/LdapAuthenticationPlugin.php | 164 | ||||
-rw-r--r-- | plugins/LdapAuthentication/README | 8 | ||||
-rw-r--r-- | plugins/Realtime/realtimeupdate.js | 50 | ||||
-rw-r--r-- | theme/base/css/display.css | 24 | ||||
-rw-r--r-- | theme/default/css/display.css | 29 |
9 files changed, 657 insertions, 43 deletions
@@ -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 don't need to use this. 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 only change this if you wanted to disable support for one or another language: diff --git a/actions/designadminpanel.php b/actions/designadminpanel.php index dcf5605af..d1aadc8c2 100644 --- a/actions/designadminpanel.php +++ b/actions/designadminpanel.php @@ -47,6 +47,10 @@ if (!defined('STATUSNET')) { class DesignadminpanelAction extends AdminPanelAction { + + /* The default site design */ + var $design = null; + /** * Returns the page title * @@ -77,6 +81,8 @@ class DesignadminpanelAction extends AdminPanelAction function showForm() { + $this->design = Design::siteDesign(); + $form = new DesignAdminPanelForm($this); $form->show(); return; @@ -90,8 +96,44 @@ class DesignadminpanelAction extends AdminPanelAction 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(); foreach ($settings as $setting) { @@ -99,6 +141,30 @@ class DesignadminpanelAction extends AdminPanelAction } // 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); @@ -112,21 +178,163 @@ class DesignadminpanelAction extends AdminPanelAction 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'); 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) { if (!in_array($values['theme'], Theme::listAvailable())) { $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 { + /** * ID of the form * @@ -150,6 +358,22 @@ class DesignAdminPanelForm extends Form } /** + * 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 * * @return string URL of the action @@ -168,21 +392,179 @@ class DesignAdminPanelForm extends Form function formData() { + + $design = $this->out->design; + $themes = Theme::listAvailable(); asort($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('li'); + $this->out->elementStart('li'); $this->out->dropdown('theme', _('Theme'), $themes, _('Theme for the site.'), - true, $this->value('theme')); + false, $this->value('theme')); + $this->out->elementEnd('li'); + $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() { - $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')); } } diff --git a/db/statusnet_pg.sql b/db/statusnet_pg.sql index 7b0e5313c..8dbaf8598 100644 --- a/db/statusnet_pg.sql +++ b/db/statusnet_pg.sql @@ -571,11 +571,11 @@ create table user_role ( ); 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'*/, created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created'*/, modified timestamp /* comment 'date this record was modified'*/, - constraint primary key (user_id) + primary key (user_id) ); diff --git a/lib/form.php b/lib/form.php index 87b7a5cba..868c986b9 100644 --- a/lib/form.php +++ b/lib/form.php @@ -67,7 +67,7 @@ class Form extends Widget { $attributes = array('id' => $this->id(), 'class' => $this->formClass(), - 'method' => 'post', + 'method' => $this->method(), 'action' => $this->action()); if (!empty($this->enctype)) { @@ -120,6 +120,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 * * Submit and cancel buttons (or whatever) diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 865154730..ad5dd3a02 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -46,6 +46,7 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin public $options=null; public $filter=null; public $scope=null; + public $password_encoding=null; public $attributes=array(); function onInitializePlugin(){ @@ -68,10 +69,6 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin function checkPassword($username, $password) { - $ldap = $this->ldap_get_connection(); - if(!$ldap){ - return false; - } $entry = $this->ldap_get_user($username); if(!$entry){ return false; @@ -109,8 +106,38 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin function changePassword($username,$oldpassword,$newpassword) { - //TODO implement this - throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); + if(! isset($this->attributes['password']) || !isset($this->password_encoding)){ + //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; } @@ -153,8 +180,10 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin * $param array $attributes LDAP attributes to retrieve * @return string DN */ - function ldap_get_user($username,$attributes=array()){ - $ldap = $this->ldap_get_connection(); + function ldap_get_user($username,$attributes=array(),$ldap=null){ + if($ldap==null) { + $ldap = $this->ldap_get_connection(); + } $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username); $options = array( 'scope' => 'sub', @@ -177,4 +206,123 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin 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; + } } diff --git a/plugins/LdapAuthentication/README b/plugins/LdapAuthentication/README index dc3f4ba88..2226159c2 100644 --- a/plugins/LdapAuthentication/README +++ b/plugins/LdapAuthentication/README @@ -18,6 +18,9 @@ email_changeable (true): Are users allowed to change their email address? (true or false) password_changeable (true): Are users allowed to change their passwords? (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 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 homepage location + password: required if users are to be able to change their passwords * required default values are in (parenthesis) @@ -67,10 +71,12 @@ addPlugin('ldapAuthentication', array( 'bindpw'=>'password', 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', 'host'=>array('server1', 'server2'), + 'password_encoding'=>'ad', 'attributes'=>array( 'username'=>'sAMAccountName', 'nickname'=>'sAMAccountName', 'email'=>'mail', - 'fullname'=>'displayName') + 'fullname'=>'displayName', + 'password'=>'unicodePwd') )); diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 9b9991b9e..d1cf1d507 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -34,6 +34,8 @@ RealtimeUpdate = { _favorurl: '', _deleteurl: '', _updatecounter: 0, + _maxnotices: 50, + _windowhasfocus: true, init: function(userid, replyurl, favorurl, deleteurl) { @@ -44,13 +46,16 @@ RealtimeUpdate = { 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:first').addClass('mark-top'); RealtimeUpdate._updatecounter = 0; document.title = DT; + RealtimeUpdate._windowhasfocus = false; return false; }); @@ -58,23 +63,32 @@ RealtimeUpdate = { receive: function(data) { - setTimeout(function() { - id = data.id; + id = data.id; + + // Don't add it if it already exists + if ($("#notice-"+id).length > 0) { + return; + } + + var noticeItem = RealtimeUpdate.makeNoticeItem(data); + $("#notices_primary .notices").prepend(noticeItem); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(1000); - // Don't add it if it already exists - if ($("#notice-"+id).length > 0) { - return; - } + 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(); + } - var noticeItem = RealtimeUpdate.makeNoticeItem(data); - $("#notices_primary .notices").prepend(noticeItem); - $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(1000); - SN.U.NoticeReply(); + SN.U.NoticeReply(); + SN.U.NoticeFavor(); + if (RealtimeUpdate._windowhasfocus === false) { RealtimeUpdate._updatecounter += 1; document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; - }, 500); + } }, makeNoticeItem: function(data) @@ -178,9 +192,9 @@ RealtimeUpdate = { }); $('#showstream #notices_primary').css({'margin-top':'18px'}); - RT.click(function() { + RT.bind('click', function() { window.open(url, - timeline, + '', 'toolbar=no,resizable=yes,scrollbars=yes,status=yes,width=500,height=550'); return false; @@ -208,6 +222,12 @@ RealtimeUpdate = { 'left':'auto', 'right':'0' }); + + $('.notices .entry-title a, .notices .entry-content a').bind('click', function() { + window.open(this.href, ''); + + return false; + }); } } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 96e169d6d..e5f5df68c 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -122,8 +122,15 @@ float:left; .form_settings .form_data input { margin-left:1.795%; float:left; +} +.form_settings .form_data input { 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 { width:63%; } @@ -165,7 +172,8 @@ font-weight:bold; #form_password_recover legend, #form_password_change legend, .form_entity_block legend, -#form_filter_bytag legend { +#form_filter_bytag legend, +#settings_design_theme legend { display:none; } @@ -558,7 +566,7 @@ font-weight:bold; /* entity_profile */ .entity_profile { position:relative; -width:74.702%; +width:73%; min-height:123px; float:left; margin-bottom:18px; @@ -629,9 +637,9 @@ font-style:italic; /*entity_actions*/ .entity_actions { float:right; -margin-left:2.35%; +margin-left:2%; margin-bottom:18px; -width:21%; +min-width:21%; } .entity_actions h2 { display:none; @@ -1325,16 +1333,16 @@ clear:both; margin-bottom:0; } -#form_settings_design #settings_design_background-image img { +#settings_design_background-image img { max-width:480px; max-height:480px; } -#form_settings_design #settings_design_color .form_data, -#form_settings_design #color-picker { +#settings_design_color .form_data, +#color-picker { float:left; } -#form_settings_design #settings_design_color .form_data { +#settings_design_color .form_data { width:400px; margin-right:28px; } diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 8799b0b09..6edc66ad2 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -135,7 +135,8 @@ button.close, .form_group_leave input.submit, .form_user_unsubscribe 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-repeat:no-repeat; background-color:transparent; @@ -178,6 +179,12 @@ background-color:rgba(255, 255, 255, 0.7); #site_nav_local_views .current a { 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 { background-color:#F7E8E8; @@ -216,7 +223,8 @@ background-position:0 1px; .form_group_join input.submit, .form_group_leave input.submit, .form_user_subscribe input.submit, -.form_user_unsubscribe input.submit { +.form_user_unsubscribe input.submit, +.entity_subscribe a { background-color:#AAAAAA; color:#FFFFFF; } @@ -225,7 +233,8 @@ color:#FFFFFF; background-position:5px -1246px; } .form_group_join input.submit, -.form_user_subscribe input.submit { +.form_user_subscribe input.submit, +.entity_subscribe a { background-position:5px -1181px; } @@ -328,3 +337,17 @@ background-position:10% -187px; .pagination .nav_next a { 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%; +} + |