From 3a44885b7ffcdcbb1b5cc8e972a3f89dd02b4c74 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 20:50:08 -0400 Subject: reformat designsettings.php --- actions/designsettings.php | 84 ++++++++-------------------------------------- 1 file changed, 14 insertions(+), 70 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 315e5a199..8d8e5bad8 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -33,8 +33,6 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/accountsettingsaction.php'; - - class DesignsettingsAction extends AccountSettingsAction { /** @@ -82,8 +80,8 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->element('label', array('for' => 'design_ background-image_file'), - _('Upload file')); + $this->element('label', array('for' => 'design_ background-image_file'), + _('Upload file')); $this->element('input', array('name' => 'design_background-image_file', 'type' => 'file', 'id' => 'design_background-image_file')); @@ -101,11 +99,11 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementStart('ul', 'form_data'); //This is a JSON object in the DB field. Here for testing. Remove later. - $userSwatch = '{"body":{"background-color":"#F0F2F5"}, - "#content":{"background-color":"#FFFFFF"}, - "#aside_primary":{"background-color":"#CEE1E9"}, - "html body":{"color":"#000000"}, - "a":{"color":"#002E6E"}}'; + $userSwatch = '{"body":{"background-color":"#F0F2F5"},'. + '"#content":{"background-color":"#FFFFFF"},'. + '"#aside_primary":{"background-color":"#CEE1E9"},'. + '"html body":{"color":"#000000"},'. + '"a":{"color":"#002E6E"}}'; //Default theme swatch -- Where should this be stored? $defaultSwatch = array('body' => array('background-color' => '#F0F2F5'), @@ -147,14 +145,13 @@ class DesignsettingsAction extends AccountSettingsAction 'title' => _('Reset back to default'))); $this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design')); -/*TODO: Check submitted form values: -json_encode(form values) -if submitted Swatch == DefaultSwatch, don't store in DB. -else store in BD -*/ + /*TODO: Check submitted form values: + json_encode(form values) + if submitted Swatch == DefaultSwatch, don't store in DB. + else store in BD + */ $this->elementEnd('fieldset'); $this->elementEnd('form'); - } /** @@ -168,63 +165,10 @@ else store in BD function handlePost() { - /* - // CSRF protection - - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } - - $user = common_current_user(); - assert(!is_null($user)); // should already be checked - - // FIXME: scrub input - - $newpassword = $this->arg('newpassword'); - $confirm = $this->arg('confirm'); - - # Some validation - - if (strlen($newpassword) < 6) { - $this->showForm(_('Password must be 6 or more characters.')); - return; - } else if (0 != strcmp($newpassword, $confirm)) { - $this->showForm(_('Passwords don\'t match.')); - return; - } - - if ($user->password) { - $oldpassword = $this->arg('oldpassword'); - - if (!common_check_user($user->nickname, $oldpassword)) { - $this->showForm(_('Incorrect old password')); - return; - } - } - - $original = clone($user); - - $user->password = common_munge_password($newpassword, $user->id); - - $val = $user->validate(); - if ($val !== true) { - $this->showForm(_('Error saving user; invalid.')); - return; - } - - if (!$user->update($original)) { - $this->serverError(_('Can\'t save new password.')); - return; - } - - $this->showForm(_('Password saved.'), true); - */ + // TODO: implement this + return; } - /** * Add the Farbtastic stylesheet * -- cgit v1.2.3-54-g00ecf From 2f0fe8e33ae29557911a0d1896a2c1b9725b5e55 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 20:54:07 -0400 Subject: add design table to DB --- db/laconica.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/db/laconica.sql b/db/laconica.sql index 0b20bc172..d42c20e2a 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -482,3 +482,13 @@ create table file_to_post ( unique(file_id, post_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table design ( + id integer primary key auto_increment comment 'design ID', + backgroundcolor integer comment 'main background color', + contentcolor integer comment 'content area background color', + sidebarcolor integer comment 'sidebar background color', + textcolor integer comment 'text color', + linkcolor integer comment 'link color', + backgroundimage varchar(255) comment 'background image, if any' +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; -- cgit v1.2.3-54-g00ecf From c63622f05e1a29c6739952e626965c18c913829c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 21:10:00 -0400 Subject: add design classes --- classes/Design.php | 47 +++++++++++++++++++++++++++++++++++++++++++++++ classes/laconica.ini | 12 ++++++++++++ 2 files changed, 59 insertions(+) create mode 100755 classes/Design.php diff --git a/classes/Design.php b/classes/Design.php new file mode 100755 index 000000000..cca41ce0c --- /dev/null +++ b/classes/Design.php @@ -0,0 +1,47 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +/** + * Table Definition for design + */ + +require_once 'classes/Memcached_DataObject'; + +class Design extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'design'; // table name + public $id; // int(4) primary_key not_null + public $backgroundcolor; // int(4) + public $contentcolor; // int(4) + public $sidebarcolor; // int(4) + public $textcolor; // int(4) + public $linkcolor; // int(4) + public $backgroundimage; // varchar(255) + + /* Static get */ + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/laconica.ini b/classes/laconica.ini index 92bbb35d4..105bc9ec8 100644 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -37,6 +37,18 @@ modified = 384 [consumer__keys] consumer_key = K +[design] +id = 129 +backgroundcolor = 1 +contentcolor = 1 +sidebarcolor = 1 +textcolor = 1 +linkcolor = 1 +backgroundimage = 2 + +[design__keys] +id = N + [fave] notice_id = 129 user_id = 129 -- cgit v1.2.3-54-g00ecf From 21aad16b58e98f61aded9c102adaef7616a6728f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 21:10:27 -0400 Subject: fix x bit on Design.php --- classes/Design.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 classes/Design.php diff --git a/classes/Design.php b/classes/Design.php old mode 100755 new mode 100644 -- cgit v1.2.3-54-g00ecf From 748c744a02ab12f36a275d9020c1b2b5ead9f002 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 23:13:09 -0400 Subject: add a method to Design to show custom CSS --- classes/Design.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/classes/Design.php b/classes/Design.php index cca41ce0c..c1b6f73e0 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -44,4 +44,14 @@ class Design extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function showCSS($out) + { + $out->element('stylesheet', array('type' => 'text/css'), + 'body { background-color: #' . dechex($this->backgroundcolor) . '} '."\n". + '#content { background-color #' . dechex($this->contentcolor) . '} '."\n". + '#aside_primary { background-color #'. dechex($this->sidebarcolor) .'} '."\n". + 'html body { color: #'. dechex($this->textcolor) .'} '."\n". + 'a { color: #' . dechex($this->linkcolor) . '} '."\n"); + } } -- cgit v1.2.3-54-g00ecf From 3f5252c168de7c0a1ffb9625e3926543c5586c6e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 23:43:08 -0400 Subject: add fields to support designs for users --- classes/laconica.ini | 3 +++ 1 file changed, 3 insertions(+) mode change 100644 => 100755 classes/laconica.ini diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100644 new mode 100755 index 105bc9ec8..450af3621 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -1,3 +1,4 @@ + [avatar] profile_id = 129 original = 17 @@ -425,6 +426,8 @@ urlshorteningservice = 2 inboxed = 17 created = 142 modified = 384 +design_id = 1 +viewdesigns = 17 [user__keys] id = K -- cgit v1.2.3-54-g00ecf From 78564c21d46d56a2cf413b9ba804d5a60430f06e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 May 2009 23:43:38 -0400 Subject: schema changes for user support of designs --- db/laconica.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db/laconica.sql b/db/laconica.sql index d42c20e2a..c87340e8e 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -41,6 +41,7 @@ create table sms_carrier ( /* local users */ create table user ( + id integer primary key comment 'foreign key to profile table' references profile (id), nickname varchar(64) unique key comment 'nickname or username, duped in profile', password varchar(255) comment 'salted password, can be null for OpenID users', @@ -71,6 +72,8 @@ create table user ( inboxed tinyint default 0 comment 'has an inbox been created for this user?', created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', + design_id integer comment 'id of a design' references design(id), + viewdesigns tinyint default 1 comment 'whether to view user-provided designs', index user_smsemail_idx (smsemail) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; -- cgit v1.2.3-54-g00ecf From d92a018cd2b199213cbd66f27dbabb460d3d55c9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 22:44:01 -0400 Subject: get a design for each page --- lib/action.php | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index 6a69d2651..e8aba5b89 100644 --- a/lib/action.php +++ b/lib/action.php @@ -224,6 +224,16 @@ class Action extends HTMLOutputter // lawsuit 'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" />getDesign(); + if (!empty($design)) { + $cur = common_current_user(); + if (empty($cur) || $cur->viewdesigns) { + $design->showCSS($this); + } + } + Event::handle('EndShowDesign', array($this, $design)); + } Event::handle('EndShowStyles', array($this)); } } @@ -248,7 +258,6 @@ class Action extends HTMLOutputter // lawsuit 'src' => common_path('js/jquery.joverlay.min.js')), ' '); - Event::handle('EndShowJQueryScripts', array($this)); } if (Event::handle('StartShowLaconicaScripts', array($this))) { @@ -1095,4 +1104,19 @@ class Action extends HTMLOutputter // lawsuit 'title' => _('Previous'))); } } + + /** + * A design for this action + * + * A design (colors and background) for the current page. May be + * the user's design, or a group's design, or a site design. + * + * @return array Feed object to show in head and links + */ + + function getDesign() + { + // XXX: return site design by default + return null; + } } -- cgit v1.2.3-54-g00ecf From 4ec5ea510cd5be39c13c2cf3bc9f9c1c8ac5df82 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:09:01 -0400 Subject: fix return value documentation for getDesign --- lib/action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index e8aba5b89..55fb7c089 100644 --- a/lib/action.php +++ b/lib/action.php @@ -1111,7 +1111,7 @@ class Action extends HTMLOutputter // lawsuit * A design (colors and background) for the current page. May be * the user's design, or a group's design, or a site design. * - * @return array Feed object to show in head and links + * @return Design a design object to use */ function getDesign() -- cgit v1.2.3-54-g00ecf From eaac0f8e58774a67fd9257ee0cd46c786cb5718b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:09:33 -0400 Subject: add an action base class for actions that show the owner's design --- lib/ownerdesignaction.php | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 lib/ownerdesignaction.php diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php new file mode 100644 index 000000000..c47633bdb --- /dev/null +++ b/lib/ownerdesignaction.php @@ -0,0 +1,72 @@ +. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Base class for actions that use the page owner's design + * + * Some pages have a clear "owner" -- like the profile page, subscriptions + * pages, etc. This superclass uses that owner's chosen design for the page + * design. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ + +class OwnerDesignAction extends Action { + + /** The user for this page. */ + + var $user = null; + + /** + * A design for this action + * + * if the user attribute has been set, returns that user's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + if (empty($this->user)) { + return null; + } + + return $this->user->getDesign(); + } +} -- cgit v1.2.3-54-g00ecf From 63ad980767fc10053eea5a5ca009dda65af42de8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:11:36 -0400 Subject: current user design action --- lib/currentuserdesignaction.php | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 lib/currentuserdesignaction.php diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php new file mode 100644 index 000000000..297525655 --- /dev/null +++ b/lib/currentuserdesignaction.php @@ -0,0 +1,69 @@ +. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Base class for actions that use the current user's design + * + * Some pages (settings in particular) use the current user's chosen + * design. This superclass returns that design. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ + +class CurrentUserDesignAction extends Action +{ + /** + * A design for this action + * + * if the user attribute has been set, returns that user's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + $cur = common_current_user(); + + if (empty($cur)) { + return null; + } + + return $cur->getDesign(); + } +} -- cgit v1.2.3-54-g00ecf From b0e92c75cc19a91e1ea4bbb8009f6f66dc56231b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:16:52 -0400 Subject: move design items before timestamps --- db/laconica.sql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/db/laconica.sql b/db/laconica.sql index c87340e8e..2ad482aba 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -70,11 +70,12 @@ create table user ( autosubscribe tinyint default 0 comment 'automatically subscribe to users who subscribe to us', urlshorteningservice varchar(50) default 'ur1.ca' comment 'service to use for auto-shortening URLs', inboxed tinyint default 0 comment 'has an inbox been created for this user?', - created datetime not null comment 'date this record was created', - modified timestamp comment 'date this record was modified', design_id integer comment 'id of a design' references design(id), viewdesigns tinyint default 1 comment 'whether to view user-provided designs', + created datetime not null comment 'date this record was created', + modified timestamp comment 'date this record was modified', + index user_smsemail_idx (smsemail) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; -- cgit v1.2.3-54-g00ecf From 91fc1e36bc268aa2bd7345206cd0e520d91aac26 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:26:29 -0400 Subject: update User.php with new design-related fields --- classes/User.php | 7 +++---- classes/laconica.ini | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/classes/User.php b/classes/User.php index ea8ba4081..22090b986 100644 --- a/classes/User.php +++ b/classes/User.php @@ -62,14 +62,13 @@ class User extends Memcached_DataObject public $autosubscribe; // tinyint(1) public $urlshorteningservice; // varchar(50) default_ur1.ca public $inboxed; // tinyint(1) + public $design_id; // int(4) + public $viewdesigns; // tinyint(1) default_1 public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) - { - return Memcached_DataObject::staticGet('User',$k,$v); - } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('User',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE diff --git a/classes/laconica.ini b/classes/laconica.ini index 450af3621..07aa016fe 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -424,10 +424,10 @@ uri = 2 autosubscribe = 17 urlshorteningservice = 2 inboxed = 17 -created = 142 -modified = 384 design_id = 1 viewdesigns = 17 +created = 142 +modified = 384 [user__keys] id = K -- cgit v1.2.3-54-g00ecf From 705abf31ee65b821f1c64921005f1814cc83733c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:27:42 -0400 Subject: add getDesign to User --- classes/User.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/classes/User.php b/classes/User.php index 22090b986..8cc8285f1 100644 --- a/classes/User.php +++ b/classes/User.php @@ -684,4 +684,9 @@ class User extends Memcached_DataObject return ($cnt > 0); } + + function getDesign() + { + return Design::staticGet('id', $this->design_id); + } } -- cgit v1.2.3-54-g00ecf From d7e3bab0b81fa7cd7f120e4ff53f89c70c18bad5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:34:05 -0400 Subject: fix require_once in Design.php --- classes/Design.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Design.php b/classes/Design.php index c1b6f73e0..bb1e917e3 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -23,7 +23,7 @@ if (!defined('LACONICA')) { exit(1); } * Table Definition for design */ -require_once 'classes/Memcached_DataObject'; +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; class Design extends Memcached_DataObject { -- cgit v1.2.3-54-g00ecf From 9c2f04afc6e70032da5aeb0441e6e0a9b0ffe253 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:35:04 -0400 Subject: make some of the actions show the user's design --- actions/replies.php | 3 +-- actions/showfavorites.php | 5 +---- actions/usergroups.php | 3 +-- lib/galleryaction.php | 3 +-- lib/profileaction.php | 3 +-- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/actions/replies.php b/actions/replies.php index dfb520d64..5d84f6428 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -45,9 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class RepliesAction extends Action +class RepliesAction extends OwnerDesignAction { - var $user = null; var $page = null; /** diff --git a/actions/showfavorites.php b/actions/showfavorites.php index eed62a2ab..839f083dd 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -45,10 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class ShowfavoritesAction extends Action +class ShowfavoritesAction extends OwnerDesignAction { - /** User we're getting the faves of */ - var $user = null; /** Page of the faves we're on */ var $page = null; @@ -161,7 +159,6 @@ class ShowfavoritesAction extends Action $this->page, 'showfavorites', array('nickname' => $this->user->nickname)); } - /** * show the personal group nav * diff --git a/actions/usergroups.php b/actions/usergroups.php index e3088dcbd..7ead6e6e4 100644 --- a/actions/usergroups.php +++ b/actions/usergroups.php @@ -46,9 +46,8 @@ require_once INSTALLDIR.'/lib/grouplist.php'; * @link http://laconi.ca/ */ -class UsergroupsAction extends Action +class UsergroupsAction extends OwnerDesignAction { - var $user = null; var $page = null; var $profile = null; diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 8fa11a756..498c82851 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -27,10 +27,9 @@ require_once INSTALLDIR.'/lib/profilelist.php'; define('AVATARS_PER_PAGE', 80); -class GalleryAction extends Action +class GalleryAction extends OwnerDesignAction { var $profile = null; - var $user = null; var $page = null; var $tag = null; diff --git a/lib/profileaction.php b/lib/profileaction.php index a3437ff4d..a14d3846e 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -47,9 +47,8 @@ require_once INSTALLDIR.'/lib/groupminilist.php'; * @link http://laconi.ca/ */ -class ProfileAction extends Action +class ProfileAction extends OwnerDesignAction { - var $user = null; var $page = null; var $profile = null; var $tag = null; -- cgit v1.2.3-54-g00ecf From 91e088d341bc51a41ec310502f85bf0d2398bd90 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:40:11 -0400 Subject: make some actions CurrentUserDesignActions --- lib/mailbox.php | 8 ++++---- lib/settingsaction.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/mailbox.php b/lib/mailbox.php index 01bbf5721..766510a47 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -47,11 +47,11 @@ define('MESSAGES_PER_PAGE', 20); * @see OutboxAction */ -class MailboxAction extends PersonalAction +class MailboxAction extends CurrentUserDesignAction { var $page = null; - function prepare($args) + function prepare($args) { parent::prepare($args); @@ -265,12 +265,12 @@ class MailboxAction extends PersonalAction * Returns either the name (and link) of the API client that posted the notice, * or one of other other channels. * - * @param string $source the source of the message + * @param string $source the source of the message * * @return void */ - function showSource($source) + function showSource($source) { $source_name = _($source); switch ($source) { diff --git a/lib/settingsaction.php b/lib/settingsaction.php index db20c5804..17d3a2f64 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -43,7 +43,7 @@ if (!defined('LACONICA')) { * @see Widget */ -class SettingsAction extends Action +class SettingsAction extends CurrentUserDesignAction { /** * A message for the user. -- cgit v1.2.3-54-g00ecf From d60c399d825dc373630042d12f90c01886cc32f5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:40:27 -0400 Subject: remove old, unused PersonalAction and StreamAction --- lib/attachmentlist.php | 2 -- lib/noticelist.php | 2 -- lib/personal.php | 60 -------------------------------------------------- lib/stream.php | 32 --------------------------- 4 files changed, 96 deletions(-) delete mode 100644 lib/personal.php delete mode 100644 lib/stream.php diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 9485fe3d6..8d6d19f2a 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -46,7 +46,6 @@ if (!defined('LACONICA')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * @see Notice - * @see StreamAction * @see NoticeListItem * @see ProfileNoticeList */ @@ -203,7 +202,6 @@ class AttachmentListItem extends Widget if ($this->attachment->url !== $this->title()) $this->out->element('span', null, " ({$this->attachment->url})"); - $this->out->elementEnd('h4'); } diff --git a/lib/noticelist.php b/lib/noticelist.php index a52132171..ba3526509 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -49,7 +49,6 @@ require_once INSTALLDIR.'/lib/disfavorform.php'; * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * @see Notice - * @see StreamAction * @see NoticeListItem * @see ProfileNoticeList */ @@ -231,7 +230,6 @@ else $this->out->elementStart('p', array('class' => 'entry-attachments', 'style' => "float: right; width: $width_att; background: url($clip) no-repeat; text-align: right; height: $height;")); $this->out->element('a', array('class' => $att_class, 'style' => "text-decoration: none; padding-top: $top; display: block; height: $height;", 'href' => $href, 'title' => "# of attachments: $count"), $count === 1 ? '' : $count); - $this->out->elementEnd('p'); } diff --git a/lib/personal.php b/lib/personal.php deleted file mode 100644 index f92732375..000000000 --- a/lib/personal.php +++ /dev/null @@ -1,60 +0,0 @@ -. - * - * @category Personal - * @package Laconica - * @author Evan Prodromou - * @author Sarven Capadisli - * @copyright 2008-2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -if (!defined('LACONICA')) { - exit(1); -} - -/** - * Base class for user profile page - * - * @category Personal - * @package Laconica - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -class PersonalAction extends Action -{ - - var $user = null; - - function isReadOnly($args) - { - return true; - } - - function handle($args) - { - parent::handle($args); - } - -} diff --git a/lib/stream.php b/lib/stream.php deleted file mode 100644 index 0cb9e0bf4..000000000 --- a/lib/stream.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -if (!defined('LACONICA')) { exit(1); } - -require_once(INSTALLDIR.'/lib/personal.php'); -require_once(INSTALLDIR.'/lib/noticelist.php'); - -class StreamAction extends PersonalAction -{ - function show_notice_list($notice) - { - $nl = new NoticeList($notice); - return $nl->show(); - } -} -- cgit v1.2.3-54-g00ecf From 6335c9cf59b384da24506c4a3f799315fbbc4b09 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:42:19 -0400 Subject: make invite use the current user's design --- actions/invite.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/invite.php b/actions/invite.php index 7e52cdbcc..c793f5824 100644 --- a/actions/invite.php +++ b/actions/invite.php @@ -19,7 +19,7 @@ if (!defined('LACONICA')) { exit(1); } -class InviteAction extends Action +class InviteAction extends CurrentUserDesignAction { var $mode = null; var $error = null; -- cgit v1.2.3-54-g00ecf From b3628b78448266fda2368f1317e70d1cca45ac17 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 27 May 2009 14:49:20 -0400 Subject: start using design object --- actions/designsettings.php | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 8d8e5bad8..da8894042 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -98,28 +98,18 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change colours')); $this->elementStart('ul', 'form_data'); - //This is a JSON object in the DB field. Here for testing. Remove later. - $userSwatch = '{"body":{"background-color":"#F0F2F5"},'. - '"#content":{"background-color":"#FFFFFF"},'. - '"#aside_primary":{"background-color":"#CEE1E9"},'. - '"html body":{"color":"#000000"},'. - '"a":{"color":"#002E6E"}}'; - - //Default theme swatch -- Where should this be stored? - $defaultSwatch = array('body' => array('background-color' => '#F0F2F5'), - '#content' => array('background-color' => '#FFFFFF'), - '#aside_primary' => array('background-color' => '#CEE1E9'), - 'html body' => array('color' => '#000000'), - 'a' => array('color' => '#002E6E')); - - $userSwatch = ($userSwatch) ? json_decode($userSwatch, true) : $defaultSwatch; - - $s = 0; + $design = $user->getDesign(); + + if (empty($design)) { + $design = $this->defaultDesign(); + } + $labelSwatch = array('Background', 'Content', 'Sidebar', 'Text', 'Links'); + foreach($userSwatch as $propertyvalue => $value) { $foo = array_values($value); $this->elementStart('li'); @@ -150,6 +140,7 @@ class DesignsettingsAction extends AccountSettingsAction if submitted Swatch == DefaultSwatch, don't store in DB. else store in BD */ + $this->elementEnd('fieldset'); $this->elementEnd('form'); } -- cgit v1.2.3-54-g00ecf From ce6285d0fc117c36716b9b3a74a11d1bfd4e45f3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 12 Jun 2009 09:47:57 -0700 Subject: push length check to Notice class --- classes/Notice.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index b4c86ebeb..bca4b22c4 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -123,7 +123,12 @@ class Notice extends Memcached_DataObject $profile = Profile::staticGet($profile_id); - $final = common_shorten_links($content); + $final = common_shorten_links($content); + + if (mb_strlen($final) > 140) { + common_log(LOG_INFO, 'Rejecting notice that is too long.'); + return _('Problem saving notice. Too long.'); + } if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); -- cgit v1.2.3-54-g00ecf From 1c41afbd36580e2d5ad110bfb5ae0da53a7895b2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 12 Jun 2009 09:48:12 -0700 Subject: check results of add in maildaemon.php --- scripts/maildaemon.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index b9facec1a..9dd647bf4 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -66,7 +66,13 @@ class MailerDaemon return true; } $msg = $this->cleanup_msg($msg); - $this->add_notice($user, $msg); + $err = $this->add_notice($user, $msg); + if (is_string($err)) { + $this->error($from, $err); + return false; + } else { + return true; + } } function error($from, $msg) @@ -130,17 +136,15 @@ class MailerDaemon function add_notice($user, $msg) { - // should test - // $msg_shortened = common_shorten_links($msg); - // if (mb_strlen($msg_shortened) > 140) ERROR and STOP $notice = Notice::saveNew($user->id, $msg, 'mail'); if (is_string($notice)) { $this->log(LOG_ERR, $notice); - return; + return $notice; } common_broadcast_notice($notice); $this->log(LOG_INFO, 'Added notice ' . $notice->id . ' from user ' . $user->nickname); + return true; } function parse_message($fname) -- cgit v1.2.3-54-g00ecf From 946d016df2a5e0af5e1b4b983b30c113dd02b4ea Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 14 Jun 2009 02:03:50 -0700 Subject: Reworked output for design settings page --- actions/designsettings.php | 164 +++++++++++++++++++++++++++++++++++---------- lib/common.php | 7 ++ 2 files changed, 136 insertions(+), 35 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 66476e677..8595cbc4c 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -22,6 +22,7 @@ * @category Settings * @package Laconica * @author Sarven Capadisli + * @author Zach Copley * @copyright 2008-2009 Control Yourself, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ @@ -104,42 +105,73 @@ class DesignsettingsAction extends AccountSettingsAction $design = $this->defaultDesign(); } - $labelSwatch = array('Background', - 'Content', - 'Sidebar', - 'Text', - 'Links'); - - foreach($userSwatch as $propertyvalue => $value) { - $foo = array_values($value); - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-'.$s), _($labelSwatch[$s])); - $this->element('input', array('name' => 'swatch-'.$s, //prefer swatch[$s] ? - 'type' => 'text', - 'id' => 'swatch-'.$s, - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $foo[0])); - $this->elementEnd('li'); - $s++; - } + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-5'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-5', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->backgroundcolor)); + $this->elementEnd('li'); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->contentcolor)); + $this->elementEnd('li'); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->sidebarcolor)); + $this->elementEnd('li'); - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->textcolor)); + $this->elementEnd('li'); - $this->element('input', array('id' => 'settings_design_reset', - 'type' => 'reset', - 'value' => 'Reset', - 'class' => 'submit form_action-primary', - 'title' => _('Reset back to default'))); - $this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design')); + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->linkcolor)); - /*TODO: Check submitted form values: - json_encode(form values) - if submitted Swatch == DefaultSwatch, don't store in DB. - else store in BD - */ + $this->elementEnd('li'); + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->element('input', array('id' => 'settings_design_reset', + 'type' => 'reset', + 'value' => 'Reset', + 'class' => 'submit form_action-primary', + 'title' => _('Reset back to default'))); + + $this->submit('save', _('Save'), 'submit form_action-secondary', + 'save', _('Save design')); $this->elementEnd('fieldset'); $this->elementEnd('form'); @@ -156,8 +188,21 @@ class DesignsettingsAction extends AccountSettingsAction function handlePost() { - // TODO: implement this - return; + // CSRF protection + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } + + if ($this->arg('save')) { + $this->saveDesign(); + } else if ($this->arg('reset')) { + $this->resetDesign(); + } else { + $this->showForm(_('Unexpected form submission.')); + } } /** @@ -196,4 +241,53 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('script', array('type' => 'text/javascript', 'src' => $farbtasticGo)); } + + /** + * Get a default user design + * + * @return Design design + */ + + function defaultDesign() + { + $defaults = common_config('site', 'design'); + + $design = new Design(); + $design->backgroundcolor = $defaults['backgroundcolor']; + $design->contentcolor = $defaults['contentcolor']; + $design->sidebarcolor = $defaults['sidebarcolor']; + $design->textcolor = $defaults['textcolor']; + $design->linkcolor = $defaults['linkcolor']; + $design->backgroundimage = $defaults['backgroundimage']; + + return $design; + } + + /** + * Save the user's design settings + * + * @return void + */ + + function saveDesign() + { + $user = common_current_user(); + + + + $this->showForm(_('Design preferences saved.'), true); + } + + /** + * Reset design settings to previous saved value if any, or + * the defaults + * + * @return void + */ + + function resetDesign() + { + $this->showForm(_('Design preferences reset.'), true); + } + } diff --git a/lib/common.php b/lib/common.php index 5aafdfe0e..a55fb264e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -72,6 +72,13 @@ $config = 'server' => $_server, 'theme' => 'default', 'skin' => 'default', + 'design' => + array('backgroundcolor' => '#F0F2F5', + 'contentcolor' => '#FFFFFF', + 'sidebarcolor' => '#CEE1E9', + 'textcolor' => '#000000', + 'linkcolor' => '#002E6E', + 'backgroundimage' => null), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From 754b610ac4e4478cd36e5826f6bbfcad0531b7aa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 12:04:45 -0700 Subject: added group_block table to database --- db/laconica.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/db/laconica.sql b/db/laconica.sql index a11e31692..3ffe1ed81 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -482,3 +482,13 @@ create table file_to_post ( unique(file_id, post_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table group_block ( + group_id integer not null comment 'group profile is blocked from' references user_group (id), + blocked integer not null comment 'profile that is blocked' references profile (id), + blocker integer not null comment 'user making the block' references user (id), + modified timestamp comment 'date of blocking', + + constraint primary key (group_id, blocked) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; -- cgit v1.2.3-54-g00ecf From 85b74d846dda8781c7e713b403c1229124480d12 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 12:06:22 -0700 Subject: create DB_DataObject classes for group block --- classes/Group_block.php | 23 +++++++++++++++++++++++ classes/laconica.ini | 11 +++++++++++ 2 files changed, 34 insertions(+) create mode 100755 classes/Group_block.php mode change 100644 => 100755 classes/laconica.ini diff --git a/classes/Group_block.php b/classes/Group_block.php new file mode 100755 index 000000000..437046a9c --- /dev/null +++ b/classes/Group_block.php @@ -0,0 +1,23 @@ + Date: Sun, 14 Jun 2009 12:07:12 -0700 Subject: fix perms on Group_block classes --- classes/Group_block.php | 0 classes/laconica.ini | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 classes/Group_block.php mode change 100755 => 100644 classes/laconica.ini diff --git a/classes/Group_block.php b/classes/Group_block.php old mode 100755 new mode 100644 diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100755 new mode 100644 -- cgit v1.2.3-54-g00ecf From 7c772e1d634badcbb9960f5a8c4398ae2f8cdd57 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 14 Jun 2009 15:48:46 -0400 Subject: Removed another bit of dead (commented out) code. --- lib/noticelist.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/noticelist.php b/lib/noticelist.php index fadc238a4..c312292ab 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -206,24 +206,10 @@ class NoticeListItem extends Widget return 'shownotice' !== $this->out->args['action']; } -/* - function attachmentCount($discriminant = true) { - $file_oembed = new File_oembed; - $query = "select count(*) as c from file_oembed join file_to_post on file_oembed.file_id = file_to_post.file_id where post_id=" . $this->notice->id; - $file_oembed->query($query); - $file_oembed->fetch(); - return intval($file_oembed->c); - } -*/ - - function showWithAttachment() { - } - function showNoticeInfo() { $this->out->elementStart('div', 'entry-content'); $this->showNoticeLink(); -// $this->showWithAttachment(); $this->showNoticeSource(); $this->showContext(); $this->out->elementEnd('div'); -- cgit v1.2.3-54-g00ecf From 21e89d6f724fe8d54788a73b4b8325fdef647af3 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 14 Jun 2009 16:06:52 -0400 Subject: Commented all .sql fields for file/url related tables. --- db/laconica.sql | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/db/laconica.sql b/db/laconica.sql index a11e31692..7f52a5ef7 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -427,49 +427,50 @@ create table group_inbox ( create table file ( id integer primary key auto_increment, - url varchar(255), mimetype varchar(50), - size integer, - title varchar(255), - date integer(11), - protected integer(1), + url varchar(255) comment 'destination URL after following redirections', + mimetype varchar(50) comment 'mime type of resource', + size integer comment 'size of resource when available', + title varchar(255) comment 'title of resource when available', + date integer(11) comment 'date of resource according to http query', + protected integer(1) comment 'true when URL is private (needs login)', unique(url) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; create table file_oembed ( id integer primary key auto_increment, - file_id integer, - version varchar(20), - type varchar(20), - provider varchar(50), - provider_url varchar(255), - width integer, - height integer, - html text, - title varchar(255), - author_name varchar(50), - author_url varchar(255), - url varchar(255), + file_id integer comment 'oEmbed for that URL/file' references file (id), + version varchar(20) comment 'oEmbed spec. version', + type varchar(20) comment 'oEmbed type: photo, video, link, rich', + provider varchar(50) comment 'name of this oEmbed provider', + provider_url varchar(255) comment 'URL of this oEmbed provider', + width integer comment 'width of oEmbed resource when available', + height integer comment 'height of oEmbed resource when available', + html text comment 'html representation of this oEmbed resource when applicable', + title varchar(255) comment 'title of oEmbed resource when available', + author_name varchar(50) comment 'author name for this oEmbed resource', + author_url varchar(255) comment 'author URL for this oEmbed resource', + url varchar(255) comment 'URL for this oEmbed resource when applicable (photo, link)', unique(file_id) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; create table file_redirection ( id integer primary key auto_increment, - url varchar(255), - file_id integer, - redirections integer, - httpcode integer, + url varchar(255) comment 'short URL (or any other kind of redirect) for file (id)', + file_id integer comment 'short URL for what URL/file' references file (id), + redirections integer comment 'redirect count', + httpcode integer comment 'HTTP status code (20x, 30x, etc.)', unique(url) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table file_thumbnail ( id integer primary key auto_increment, - file_id integer, - url varchar(255), - width integer, - height integer, + file_id integer comment 'thumbnail for what URL/file' references file (id), + url varchar(255) comment 'URL of thumbnail', + width integer comment 'width of thumbnail', + height integer comment 'height of thumbnail', unique(file_id), unique(url) @@ -477,8 +478,8 @@ create table file_thumbnail ( create table file_to_post ( id integer primary key auto_increment, - file_id integer, - post_id integer, + file_id integer comment 'id of URL/file' references file (id), + post_id integer comment 'id of the notice it belongs to' references notice (id), unique(file_id, post_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; -- cgit v1.2.3-54-g00ecf From 9addfeacfdacf1eb8c6a90a636f468e4aeb0e9fe Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 14:01:11 -0700 Subject: better handling of PEAR errors --- index.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/index.php b/index.php index 4eff99dff..f5b32ea09 100644 --- a/index.php +++ b/index.php @@ -48,13 +48,18 @@ function handleError($error) $logmsg .= " : ". $error->getDebugInfo(); } common_log(LOG_ERR, $logmsg); - $msg = sprintf(_('The database for %s isn\'t responding correctly, '. - 'so the site won\'t work properly. '. - 'The site admins probably know about the problem, '. - 'but you can contact them at %s to make sure. '. - 'Otherwise, wait a few minutes and try again.'), - common_config('site', 'name'), - common_config('site', 'email')); + if ($error instanceof DB_DataObject_Error) { + $msg = sprintf(_('The database for %s isn\'t responding correctly, '. + 'so the site won\'t work properly. '. + 'The site admins probably know about the problem, '. + 'but you can contact them at %s to make sure. '. + 'Otherwise, wait a few minutes and try again.'), + common_config('site', 'name'), + common_config('site', 'email')); + } else { + $msg = _('An important error occured, probably related to email setup. '. + 'Check logfiles for more info..'); + } $dac = new DBErrorAction($msg, 500); $dac->showPage(); @@ -70,7 +75,7 @@ function main() global $user, $action, $config; Snapshot::check(); - + if (!_have_config()) { $msg = sprintf(_("No configuration file found. Try running ". "the installation program first.")); -- cgit v1.2.3-54-g00ecf From c2dae24701a22cd2362ebe1a96828cd7945c6b5a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 14:52:26 -0700 Subject: Break profilelist into a recipe Expanded the ProfileList class so it worked more like a recipe. This helps to get rid of a lot of special cases and simplifies the code. It also makes it possible to do things like group block. --- actions/groupmembers.php | 14 +++- actions/showgroup.php | 2 +- actions/subscribers.php | 32 ++++++--- actions/subscriptions.php | 34 ++++++++-- lib/peoplesearchresults.php | 15 +++-- lib/profileaction.php | 4 +- lib/profilelist.php | 154 +++++++++++++++++++++++++------------------- lib/profileminilist.php | 23 ++----- 8 files changed, 172 insertions(+), 106 deletions(-) diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 21e5ebbaa..53fee3129 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -127,7 +127,7 @@ class GroupmembersAction extends Action $members = $this->group->getMembers($offset, $limit); if ($members) { - $member_list = new ProfileList($members, null, $this); + $member_list = new GroupMemberList($members, $this->group, $this); $cnt = $member_list->show(); } @@ -138,3 +138,15 @@ class GroupmembersAction extends Action array('nickname' => $this->group->nickname)); } } + +class GroupMemberList extends ProfileList { + + var $group = null; + + function __construct($profile, $group=null, $action=null) + { + parent::__construct($profile, $action); + + $this->group = $group; + } +} diff --git a/actions/showgroup.php b/actions/showgroup.php index 29b6fa1e6..3ce45adc6 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -344,7 +344,7 @@ class ShowgroupAction extends Action $this->element('h2', null, _('Members')); - $pml = new ProfileMiniList($member, null, $this); + $pml = new ProfileMiniList($member, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); diff --git a/actions/subscribers.php b/actions/subscribers.php index 4482de9a7..66ac00fb1 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -130,18 +130,34 @@ class SubscribersAction extends GalleryAction } } -class SubscribersList extends ProfileList +class SubscribersList extends SubscriptionList { - function showBlockForm() + function newListItem($profile) { - $bf = new BlockForm($this->out, $this->profile, - array('action' => 'subscribers', - 'nickname' => $this->owner->nickname)); - $bf->show(); + return new SubscribersListItem($profile, $this->owner, $this->action); } +} - function isReadOnly($args) +class SubscribersListItem extends SubscriptionListItem +{ + function showActions() { - return true; + $this->startActions(); + $this->showSubscribeButton(); + // Relevant code! + $this->showBlockForm(); + $this->endActions(); + } + + function showBlockForm() + { + $user = common_current_user(); + + if (!empty($user) && $this->owner->id == $user->id) { + $bf = new BlockForm($this->out, $this->profile, + array('action' => 'subscribers', + 'nickname' => $this->owner->nickname)); + $bf->show(); + } } } diff --git a/actions/subscriptions.php b/actions/subscriptions.php index 095b18ad8..4124abea4 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -137,22 +137,46 @@ class SubscriptionsAction extends GalleryAction } } -class SubscriptionsList extends ProfileList +// XXX SubscriptionsList and SubscriptionList are dangerously close + +class SubscriptionsList extends SubscriptionList { - function showOwnerControls($profile) + function newListItem($profile) + { + return new SubscriptionsListItem($profile, $this->owner, $this->action); + } +} + +class SubscriptionsListItem extends SubscriptionListItem +{ + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + $this->showTags(); + // Relevant portion! + $this->showOwnerControls(); + $this->endProfile(); + } + + function showOwnerControls() { $sub = Subscription::pkeyGet(array('subscriber' => $this->owner->id, - 'subscribed' => $profile->id)); + 'subscribed' => $this->profile->id)); if (!$sub) { return; } - $this->out->elementStart('form', array('id' => 'subedit-' . $profile->id, + $this->out->elementStart('form', array('id' => 'subedit-' . $this->profile->id, 'method' => 'post', 'class' => 'form_subscription_edit', 'action' => common_local_url('subedit'))); $this->out->hidden('token', common_session_token()); - $this->out->hidden('profile', $profile->id); + $this->out->hidden('profile', $this->profile->id); $this->out->checkbox('jabber', _('Jabber'), $sub->jabber); $this->out->checkbox('sms', _('SMS'), $sub->sms); $this->out->submit('save', _('Save')); diff --git a/lib/peoplesearchresults.php b/lib/peoplesearchresults.php index d3f840852..9d9d17299 100644 --- a/lib/peoplesearchresults.php +++ b/lib/peoplesearchresults.php @@ -56,20 +56,25 @@ class PeopleSearchResults extends ProfileList function __construct($profile, $terms, $action) { - parent::__construct($profile, $terms, $action); + parent::__construct($profile, $action); + $this->terms = array_map('preg_quote', array_map('htmlspecialchars', $terms)); + $this->pattern = '/('.implode('|',$terms).')/i'; } - function highlight($text) + function newProfileItem($profile) { - return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); + return new PeopleSearchResultItem($profile, $this->action); } +} - function isReadOnly($args) +class PeopleSearchResultItem extends ProfileListItem +{ + function highlight($text) { - return true; + return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); } } diff --git a/lib/profileaction.php b/lib/profileaction.php index a3437ff4d..298f34b22 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -110,7 +110,7 @@ class ProfileAction extends Action $this->element('h2', null, _('Subscriptions')); if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); + $pml = new ProfileMiniList($profile, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); @@ -139,7 +139,7 @@ class ProfileAction extends Action $this->element('h2', null, _('Subscribers')); if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); + $pml = new ProfileMiniList($profile, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); diff --git a/lib/profilelist.php b/lib/profilelist.php index a4cc23555..e2faf10af 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -49,23 +49,19 @@ class ProfileList extends Widget { /** Current profile, profile query. */ var $profile = null; - /** Owner of this list */ - var $owner = null; /** Action object using us. */ var $action = null; - function __construct($profile, $owner=null, $action=null) + function __construct($profile, $action=null) { parent::__construct($action); $this->profile = $profile; - $this->owner = $owner; $this->action = $action; } function show() { - $this->out->elementStart('ul', 'profiles'); $cnt = 0; @@ -75,7 +71,8 @@ class ProfileList extends Widget if($cnt > PROFILES_PER_PAGE) { break; } - $this->showProfile(); + $pli = $this->newListItem($this->profile); + $pli->show(); } $this->out->elementEnd('ul'); @@ -83,16 +80,59 @@ class ProfileList extends Widget return $cnt; } - function showProfile() + function newListItem($profile) + { + return new ProfileListItem($this->profile, $this->action); + } +} + +class ProfileListItem extends Widget +{ + /** Current profile. */ + var $profile = null; + /** Action object using us. */ + var $action = null; + + function __construct($profile, $action) + { + parent::__construct($action); + + $this->profile = $profile; + $this->action = $action; + } + + function show() + { + $this->startItem(); + $this->showProfile(); + $this->showActions(); + $this->endItem(); + } + + function startItem() { $this->out->elementStart('li', array('class' => 'profile', 'id' => 'profile-' . $this->profile->id)); + } - $user = common_current_user(); - $is_own = !is_null($user) && isset($this->owner) && ($user->id === $this->owner->id); + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + $this->endProfile(); + } + function startProfile() + { $this->out->elementStart('div', 'entity_profile vcard'); + } + function showAvatar() + { $avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE); $this->out->elementStart('a', array('href' => $this->profile->profileurl, 'class' => 'url')); @@ -108,7 +148,10 @@ class ProfileList extends Widget $this->out->raw($this->highlight($this->profile->nickname)); $this->out->elementEnd('span'); $this->out->elementEnd('a'); + } + function showFullName() + { if (!empty($this->profile->fullname)) { $this->out->elementStart('dl', 'entity_fn'); $this->out->element('dt', null, 'Full name'); @@ -119,6 +162,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showLocation() + { if (!empty($this->profile->location)) { $this->out->elementStart('dl', 'entity_location'); $this->out->element('dt', null, _('Location')); @@ -127,6 +174,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showHomepage() + { if (!empty($this->profile->homepage)) { $this->out->elementStart('dl', 'entity_url'); $this->out->element('dt', null, _('URL')); @@ -138,6 +189,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showBio() + { if (!empty($this->profile->bio)) { $this->out->elementStart('dl', 'entity_note'); $this->out->element('dt', null, _('Note')); @@ -146,57 +201,33 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } - # If we're on a list with an owner (subscriptions or subscribers)... - - if ($this->owner) { - # Get tags - $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); - - $this->out->elementStart('dl', 'entity_tags'); - $this->out->elementStart('dt'); - if ($is_own) { - $this->out->element('a', array('href' => common_local_url('tagother', - array('id' => $this->profile->id))), - _('Tags')); - } else { - $this->out->text(_('Tags')); - } - $this->out->elementEnd('dt'); - $this->out->elementStart('dd'); - if ($tags) { - $this->out->elementStart('ul', 'tags xoxo'); - foreach ($tags as $tag) { - $this->out->elementStart('li'); - $this->out->element('span', 'mark_hash', '#'); - $this->out->element('a', array('rel' => 'tag', - 'href' => common_local_url($this->action->trimmed('action'), - array('nickname' => $this->owner->nickname, - 'tag' => $tag))), - $tag); - $this->out->elementEnd('li'); - } - $this->out->elementEnd('ul'); - } else { - $this->out->text(_('(none)')); - } - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); - } - - if ($is_own) { - $this->showOwnerControls($this->profile); - } - + function endProfile() + { $this->out->elementEnd('div'); + } - $this->out->elementStart('div', 'entity_actions'); + function showActions() + { + $this->startActions(); + $this->showSubscribeButton(); + $this->endActions(); + } + function startActions() + { + $this->out->elementStart('div', 'entity_actions'); $this->out->elementStart('ul'); + } + function showSubscribeButton() + { // Is this a logged-in user, looking at someone else's // profile? + $user = common_current_user(); + if (!empty($user) && $this->profile->id != $user->id) { $this->out->elementStart('li', 'entity_subscribe'); if ($user->isSubscribed($this->profile)) { @@ -207,33 +238,22 @@ class ProfileList extends Widget $sf->show(); } $this->out->elementEnd('li'); - $this->out->elementStart('li', 'entity_block'); - if ($user->id == $this->owner->id) { - $this->showBlockForm(); - } - $this->out->elementEnd('li'); } + } + function endActions() + { $this->out->elementEnd('ul'); - $this->out->elementEnd('div'); - - $this->out->elementEnd('li'); } - /* Override this in subclasses. */ - - function showOwnerControls($profile) + function endItem() { - return; + $this->out->elementEnd('li'); } function highlight($text) { return htmlspecialchars($text); } - - function showBlockForm() - { - } } diff --git a/lib/profileminilist.php b/lib/profileminilist.php index 57496d0e9..f11cae8a5 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -47,26 +47,15 @@ define('PROFILES_PER_MINILIST', 27); class ProfileMiniList extends ProfileList { - function show() + function newListItem($profile) { - $this->out->elementStart('ul', 'entities users xoxo'); - - $cnt = 0; - - while ($this->profile->fetch()) { - $cnt++; - if($cnt > PROFILES_PER_MINILIST) { - break; - } - $this->showProfile(); - } - - $this->out->elementEnd('ul'); - - return $cnt; + return new ProfileMiniListItem($profile, $this->action); } +} - function showProfile() +class ProfileMiniListItem extends ProfileListItem +{ + function show() { $this->out->elementStart('li', 'vcard'); $this->out->elementStart('a', array('title' => $this->profile->getBestName(), -- cgit v1.2.3-54-g00ecf From b6ef8e735b8deeaf3e11a03574888a479b1679b7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 14:53:42 -0700 Subject: base class SubscriptionList for some actions --- lib/subscriptionlist.php | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 lib/subscriptionlist.php diff --git a/lib/subscriptionlist.php b/lib/subscriptionlist.php new file mode 100644 index 000000000..23da64cca --- /dev/null +++ b/lib/subscriptionlist.php @@ -0,0 +1,131 @@ +. + * + * @category Public + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/profilelist.php'; + +/** + * Widget to show a list of subscriptions + * + * @category Public + * @package Laconica + * @author Zach Copley + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionList extends ProfileList +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner=null, $action=null) + { + parent::__construct($profile, $action); + + $this->owner = $owner; + } + + function newListItem($profile) + { + return new SubscriptionListItem($profile, $this->owner, $this->action); + } +} + +class SubscriptionListItem extends ProfileListItem +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner, $action) + { + parent::__construct($profile, $action); + + $this->owner = $owner; + } + + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + // Relevant portion! + $this->showTags(); + $this->endProfile(); + } + + function isOwn() + { + $user = common_current_user(); + return (!empty($user) && ($this->owner->id == $user->id)); + } + + function showTags() + { + $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); + + $this->out->elementStart('dl', 'entity_tags'); + $this->out->elementStart('dt'); + if ($this->isOwn()) { + $this->out->element('a', array('href' => common_local_url('tagother', + array('id' => $this->profile->id))), + _('Tags')); + } else { + $this->out->text(_('Tags')); + } + $this->out->elementEnd('dt'); + $this->out->elementStart('dd'); + if ($tags) { + $this->out->elementStart('ul', 'tags xoxo'); + foreach ($tags as $tag) { + $this->out->elementStart('li'); + $this->out->element('span', 'mark_hash', '#'); + $this->out->element('a', array('rel' => 'tag', + 'href' => common_local_url($this->action->trimmed('action'), + array('nickname' => $this->owner->nickname, + 'tag' => $tag))), + $tag); + $this->out->elementEnd('li'); + } + $this->out->elementEnd('ul'); + } else { + $this->out->text(_('(none)')); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); + } +} -- cgit v1.2.3-54-g00ecf From b6dee88e5d0a0ed58391ccb8868f4afbf631342a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:08:00 -0700 Subject: add UI for blocking a user from a group --- actions/groupmembers.php | 170 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 53fee3129..079dad9e9 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -139,14 +139,180 @@ class GroupmembersAction extends Action } } -class GroupMemberList extends ProfileList { +class GroupMemberList extends ProfileList +{ + var $group = null; + + function __construct($profile, $group, $action) + { + parent::__construct($profile, $action); + + $this->group = $group; + } + + function newListItem($profile) + { + return new GroupMemberListItem($profile, $this->group, $this->action); + } +} +class GroupMemberListItem extends ProfileListItem +{ var $group = null; - function __construct($profile, $group=null, $action=null) + function __construct($profile, $group, $action) { parent::__construct($profile, $action); $this->group = $group; } + + function showActions() + { + $this->startActions(); + $this->showSubscribeButton(); + $this->showGroupBlockForm(); + $this->endActions(); + } + + function showGroupBlockForm() + { + $user = common_current_user(); + + if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { + $bf = new GroupBlockForm($this->out, $this->profile, + array('action' => 'groupmembers', + 'nickname' => $this->group->nickname)); + $bf->show(); + } + + } +} + +/** + * Form for blocking a user from a group + * + * @category Form + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see BlockForm + */ + +class GroupBlockForm extends Form +{ + /** + * Profile of user to block + */ + + var $profile = null; + + /** + * Group to block the user from + */ + + var $group = null; + + /** + * Return-to args + */ + + var $args = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Profile $profile profile of user to block + * @param User_group $group group to block user from + * @param array $args return-to args + */ + + function __construct($out=null, $profile=null, $group=null, $args=null) + { + parent::__construct($out); + + $this->profile = $profile; + $this->group = $group; + $this->args = $args; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + // This should be unique for the page. + return 'block-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_group_block'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('groupblock'); + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Block user from group')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('blockto-' . $this->profile->id, + $this->profile->id, + 'blockto'); + $this->out->hidden('blockgroup-' . $this->group->id, + $this->group->id, + 'blockgroup'); + if ($this->args) { + foreach ($this->args as $k => $v) { + $this->out->hidden('returnto-' . $k, $v); + } + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Block'), 'submit', null, _('Block this user')); + } } -- cgit v1.2.3-54-g00ecf From d3a0c524cce9be65b8e45280168cf3584a60f81c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:40:42 -0700 Subject: Make group block work --- actions/groupblock.php | 215 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 actions/groupblock.php diff --git a/actions/groupblock.php b/actions/groupblock.php new file mode 100644 index 000000000..93662da79 --- /dev/null +++ b/actions/groupblock.php @@ -0,0 +1,215 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Block a user from a group + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class GroupblockAction extends Action +{ + var $profile = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + + function prepare($args) + { + parent::prepare($args); + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return false; + } + $token = $this->trimmed('token'); + if (empty($token) || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. Try again, please.')); + return; + } + $id = $this->trimmed('blockto'); + if (empty($id)) { + $this->clientError(_('No profile specified.')); + return false; + } + $this->profile = Profile::staticGet('id', $id); + if (empty($this->profile)) { + $this->clientError(_('No profile with that ID.')); + return false; + } + $group_id = $this->trimmed('blockgroup'); + if (empty($group_id)) { + $this->clientError(_('No group specified.')); + return false; + } + $this->group = User_group::staticGet('id', $group_id); + if (empty($this->group)) { + $this->clientError(_('No such group.')); + return false; + } + $user = common_current_user(); + if (!$user->isAdmin($this->group)) { + $this->clientError(_('Only an admin can block group members.'), 401); + return false; + } + if (Group_block::isBlocked($this->group, $this->profile)) { + $this->clientError(_('User is already blocked from group.')); + return false; + } + // XXX: could have proactive blocks, but we don't have UI for it. + if (!$this->profile->isMember($this->group)) { + $this->clientError(_('User is not a member of group.')); + return false; + } + return true; + } + + /** + * Handle request + * + * Shows a page with list of favorite notices + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + function handle($args) + { + parent::handle($args); + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + if ($this->arg('no')) { + common_redirect(common_local_url('groupmembers', + array('nickname' => $this->group->nickname)), + 303); + } elseif ($this->arg('yes')) { + $this->blockProfile(); + } elseif ($this->arg('blockto')) { + $this->showPage(); + } + } + } + + function showContent() { + $this->areYouSureForm(); + } + + function title() { + return _('Block user from group'); + } + + function showNoticeForm() { + // nop + } + + /** + * Confirm with user. + * + * Shows a confirmation form. + * + * @return void + */ + + function areYouSureForm() + { + $id = $this->profile->id; + $this->element('p', null, + sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '. + 'They will be removed from the group, unable to post, and '. + 'unable to subscribe to the group in the future.'), + $this->profile->getBestName(), + $this->group->getBestName())); + $this->elementStart('form', array('id' => 'block-' . $id, + 'method' => 'post', + 'class' => 'block', + 'action' => common_local_url('groupblock'))); + $this->hidden('token', common_session_token()); + $this->hidden('blockto-' . $this->profile->id, + $this->profile->id, + 'blockto'); + $this->hidden('blockgroup-' . $this->group->id, + $this->group->id, + 'blockgroup'); + foreach ($this->args as $k => $v) { + if (substr($k, 0, 9) == 'returnto-') { + $this->hidden($k, $v); + } + } + $this->submit('no', _('No')); + $this->submit('yes', _('Yes')); + $this->elementEnd('form'); + } + + /** + * Actually block a user. + * + * @return void + */ + + function blockProfile() + { + $block = Group_block::blockProfile($this->group, $this->profile, + common_current_user()); + + if (empty($block)) { + $this->serverError(_("Database error blocking user from group.")); + return false; + } + + // Now, gotta figure where we go back to + foreach ($this->args as $k => $v) { + if ($k == 'returnto-action') { + $action = $v; + } elseif (substr($k, 0, 9) == 'returnto-') { + $args[substr($k, 9)] = $v; + } + } + + if ($action) { + common_redirect(common_local_url($action, $args), 303); + } else { + common_redirect(common_local_url('groupmembers', + array('nickname' => $this->group->nickname)), + 303); + } + } +} + -- cgit v1.2.3-54-g00ecf From 1c87532912b63effc047da2913e55a6551d8f629 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:47:39 -0700 Subject: The rest of the things necessary to make group block work Link to the group block form. Hide join button if the current user is blocked. --- actions/groupmembers.php | 2 +- actions/joingroup.php | 5 ++++ actions/showgroup.php | 2 +- classes/Group_block.php | 76 ++++++++++++++++++++++++++++++++++++++++++++++-- classes/User_group.php | 5 ++++ lib/grouplist.php | 2 +- lib/router.php | 8 ++--- 7 files changed, 91 insertions(+), 9 deletions(-) diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 079dad9e9..150b60a54 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -180,7 +180,7 @@ class GroupMemberListItem extends ProfileListItem $user = common_current_user(); if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { - $bf = new GroupBlockForm($this->out, $this->profile, + $bf = new GroupBlockForm($this->out, $this->profile, $this->group, array('action' => 'groupmembers', 'nickname' => $this->group->nickname)); $bf->show(); diff --git a/actions/joingroup.php b/actions/joingroup.php index a5d82ddc7..0e4f96eaf 100644 --- a/actions/joingroup.php +++ b/actions/joingroup.php @@ -96,6 +96,11 @@ class JoingroupAction extends Action return false; } + if (Group_block::isBlocked($this->group, $cur->getProfile())) { + $this->clientError(_('You have been blocked from that group by the admin.'), 403); + return false; + } + return true; } diff --git a/actions/showgroup.php b/actions/showgroup.php index 3ce45adc6..537f09278 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -283,7 +283,7 @@ class ShowgroupAction extends Action if ($cur->isMember($this->group)) { $lf = new LeaveForm($this, $this->group); $lf->show(); - } else { + } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) { $jf = new JoinForm($this, $this->group); $jf->show(); } diff --git a/classes/Group_block.php b/classes/Group_block.php index 437046a9c..d945fd57a 100644 --- a/classes/Group_block.php +++ b/classes/Group_block.php @@ -1,10 +1,29 @@ . */ -require_once 'classes/Memcached_DataObject'; -class Group_block extends Memcached_DataObject +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Group_block extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -20,4 +39,57 @@ class Group_block extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function &pkeyGet($kv) + { + return Memcached_DataObject::pkeyGet('Group_block', $kv); + } + + static function isBlocked($group, $profile) + { + $block = Group_block::pkeyGet(array('group_id' => $group->id, + 'blocked' => $profile->id)); + return !empty($block); + } + + static function blockProfile($group, $profile, $blocker) + { + // Insert the block + + $block = new Group_block(); + + $block->query('BEGIN'); + + $block->group_id = $group->id; + $block->blocked = $profile->id; + $block->blocker = $blocker->id; + + $result = $block->insert(); + + if (!$result) { + common_log_db_error($block, 'INSERT', __FILE__); + return null; + } + + // Delete membership if any + + $member = new Group_member(); + + $member->group_id = $group->id; + $member->profile_id = $profile->id; + + if ($member->find(true)) { + $result = $member->delete(); + if (!$result) { + common_log_db_error($member, 'DELETE', __FILE__); + return null; + } + } + + // Commit, since both have been done + + $block->query('COMMIT'); + + return $block; + } } diff --git a/classes/User_group.php b/classes/User_group.php index a135015ba..1be34b60b 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -137,4 +137,9 @@ class User_group extends Memcached_DataObject common_debug(common_log_objstring($this)); return $this->update($orig); } + + function getBestName() + { + return ($this->fullname) ? $this->fullname : $this->nickname; + } } diff --git a/lib/grouplist.php b/lib/grouplist.php index 1b8547499..1ded5160b 100644 --- a/lib/grouplist.php +++ b/lib/grouplist.php @@ -166,7 +166,7 @@ class GroupList extends Widget if ($user->isMember($this->group)) { $lf = new LeaveForm($this->out, $this->group); $lf->show(); - } else { + } else if (!Group_block::isBlocked($this->group, $user->getProfile())) { $jf = new JoinForm($this->out, $this->group); $jf->show(); } diff --git a/lib/router.php b/lib/router.php index 456d1793e..469d9a171 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,7 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'subedit'); + 'block', 'subedit', 'groupblock'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -164,10 +164,10 @@ class Router array('action' => 'newnotice'), array('replyto' => '[A-Za-z0-9_-]+')); - $m->connect('notice/:notice/file', - array('action' => 'file'), + $m->connect('notice/:notice/file', + array('action' => 'file'), array('notice' => '[0-9]+')); - + $m->connect('notice/:notice', array('action' => 'shownotice'), array('notice' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From 203a5aba67c3bd9e2848d90b1778240b387aeda3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:54:22 -0700 Subject: Some UI improvements for blocking and unblocking Add unblock to the router table, so unblocking will work at all. Block form and unblock form return to subscribers list, not subscriptions list, by default. showstream action sends its parameters to block and unblock forms to better return to the right page. --- actions/block.php | 2 +- actions/showstream.php | 8 ++++++-- actions/unblock.php | 2 +- lib/router.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/actions/block.php b/actions/block.php index 34f991dc6..0efee5932 100644 --- a/actions/block.php +++ b/actions/block.php @@ -180,7 +180,7 @@ class BlockAction extends Action if ($action) { common_redirect(common_local_url($action, $args), 303); } else { - common_redirect(common_local_url('subscriptions', + common_redirect(common_local_url('subscribers', array('nickname' => $cur->nickname)), 303); } diff --git a/actions/showstream.php b/actions/showstream.php index c1a2c337a..641228bc7 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -308,10 +308,14 @@ class ShowstreamAction extends ProfileAction $blocked = $cur->hasBlocked($this->profile); $this->elementStart('li', 'entity_block'); if ($blocked) { - $ubf = new UnblockForm($this, $this->profile); + $ubf = new UnblockForm($this, $this->profile, + array('action' => 'showstream', + 'nickname' => $this->profile->nickname)); $ubf->show(); } else { - $bf = new BlockForm($this, $this->profile); + $bf = new BlockForm($this, $this->profile, + array('action' => 'showstream', + 'nickname' => $this->profile->nickname)); $bf->show(); } $this->elementEnd('li'); diff --git a/actions/unblock.php b/actions/unblock.php index 8573b2a87..6e671c9dd 100644 --- a/actions/unblock.php +++ b/actions/unblock.php @@ -118,7 +118,7 @@ class UnblockAction extends Action if ($action) { common_redirect(common_local_url($action, $args), 303); } else { - common_redirect(common_local_url('subscriptions', + common_redirect(common_local_url('subscribers', array('nickname' => $cur->nickname)), 303); } diff --git a/lib/router.php b/lib/router.php index 12590b790..748966567 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,7 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'subedit'); + 'block', 'unblock', 'subedit'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); -- cgit v1.2.3-54-g00ecf From f8da15bf41b07a46b1fbe5323e2b8136d42c5b31 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 16:17:44 -0700 Subject: Allow users to be unblocked from a group List users who are blocked from joining a group. Add a form to let them be unblocked. Add an action that removes the block. Includes changes to group and groupblock classes. --- actions/blockedfromgroup.php | 313 +++++++++++++++++++++++++++++++++++++++++++ actions/groupunblock.php | 149 ++++++++++++++++++++ classes/Group_block.php | 20 +++ classes/User_group.php | 23 ++++ lib/groupnav.php | 6 + lib/router.php | 7 +- 6 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 actions/blockedfromgroup.php create mode 100644 actions/groupunblock.php diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php new file mode 100644 index 000000000..1b7b31784 --- /dev/null +++ b/actions/blockedfromgroup.php @@ -0,0 +1,313 @@ +. + * + * @category Group + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * List of profiles blocked from this group + * + * @category Group + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class BlockedfromgroupAction extends Action +{ + var $page = null; + + function isReadOnly($args) + { + return true; + } + + function prepare($args) + { + parent::prepare($args); + $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; + + $nickname_arg = $this->arg('nickname'); + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + $args = array('nickname' => $nickname); + if ($this->page != 1) { + $args['page'] = $this->page; + } + common_redirect(common_local_url('blockedfromgroup', $args), 301); + return false; + } + + if (!$nickname) { + $this->clientError(_('No nickname'), 404); + return false; + } + + $this->group = User_group::staticGet('nickname', $nickname); + + if (!$this->group) { + $this->clientError(_('No such group'), 404); + return false; + } + + return true; + } + + function title() + { + if ($this->page == 1) { + return sprintf(_('%s blocked profiles'), + $this->group->nickname); + } else { + return sprintf(_('%s blocked profiles, page %d'), + $this->group->nickname, + $this->page); + } + } + + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + function showPageNotice() + { + $this->element('p', 'instructions', + _('A list of the users blocked from joining this group.')); + } + + function showLocalNav() + { + $nav = new GroupNav($this, $this->group); + $nav->show(); + } + + function showContent() + { + $offset = ($this->page-1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + + $cnt = 0; + + $blocked = $this->group->getBlocked($offset, $limit); + + if ($blocked) { + $blocked_list = new GroupBlockList($blocked, $this->group, $this); + $cnt = $blocked_list->show(); + } + + $blocked->free(); + + $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, + $this->page, 'blockedfromgroup', + array('nickname' => $this->group->nickname)); + } +} + +class GroupBlockList extends ProfileList +{ + var $group = null; + + function __construct($profile, $group, $action) + { + parent::__construct($profile, $action); + + $this->group = $group; + } + + function newListItem($profile) + { + return new GroupBlockListItem($profile, $this->group, $this->action); + } +} + +class GroupBlockListItem extends ProfileListItem +{ + var $group = null; + + function __construct($profile, $group, $action) + { + parent::__construct($profile, $action); + + $this->group = $group; + } + + function showActions() + { + $this->startActions(); + $this->showGroupUnblockForm(); + $this->endActions(); + } + + function showGroupUnblockForm() + { + $user = common_current_user(); + + if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { + $bf = new GroupUnblockForm($this->out, $this->profile, $this->group, + array('action' => 'blockedfromgroup', + 'nickname' => $this->group->nickname)); + $bf->show(); + } + } +} + +/** + * Form for unblocking a user from a group + * + * @category Form + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see UnblockForm + */ + +class GroupUnblockForm extends Form +{ + /** + * Profile of user to block + */ + + var $profile = null; + + /** + * Group to block the user from + */ + + var $group = null; + + /** + * Return-to args + */ + + var $args = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Profile $profile profile of user to block + * @param User_group $group group to block user from + * @param array $args return-to args + */ + + function __construct($out=null, $profile=null, $group=null, $args=null) + { + parent::__construct($out); + + $this->profile = $profile; + $this->group = $group; + $this->args = $args; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + // This should be unique for the page. + return 'unblock-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_group_unblock'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('groupunblock'); + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Unblock user from group')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('unblockto-' . $this->profile->id, + $this->profile->id, + 'unblockto'); + $this->out->hidden('unblockgroup-' . $this->group->id, + $this->group->id, + 'unblockgroup'); + if ($this->args) { + foreach ($this->args as $k => $v) { + $this->out->hidden('returnto-' . $k, $v); + } + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Unblock'), 'submit', null, _('Unblock this user')); + } +} diff --git a/actions/groupunblock.php b/actions/groupunblock.php new file mode 100644 index 000000000..a0bcb01f9 --- /dev/null +++ b/actions/groupunblock.php @@ -0,0 +1,149 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Unlock a user from a group + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class GroupunblockAction extends Action +{ + var $profile = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + + function prepare($args) + { + parent::prepare($args); + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return false; + } + $token = $this->trimmed('token'); + if (empty($token) || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. Try again, please.')); + return; + } + $id = $this->trimmed('unblockto'); + if (empty($id)) { + $this->clientError(_('No profile specified.')); + return false; + } + $this->profile = Profile::staticGet('id', $id); + if (empty($this->profile)) { + $this->clientError(_('No profile with that ID.')); + return false; + } + $group_id = $this->trimmed('unblockgroup'); + if (empty($group_id)) { + $this->clientError(_('No group specified.')); + return false; + } + $this->group = User_group::staticGet('id', $group_id); + if (empty($this->group)) { + $this->clientError(_('No such group.')); + return false; + } + $user = common_current_user(); + if (!$user->isAdmin($this->group)) { + $this->clientError(_('Only an admin can unblock group members.'), 401); + return false; + } + if (!Group_block::isBlocked($this->group, $this->profile)) { + $this->clientError(_('User is not blocked from group.')); + return false; + } + return true; + } + + /** + * Handle request + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->unblockProfile(); + } + } + + /** + * Unblock a user. + * + * @return void + */ + + function unblockProfile() + { + $result = Group_block::unblockProfile($this->group, $this->profile); + + if (!$result) { + $this->serverError(_('Error removing the block.')); + return; + } + + foreach ($this->args as $k => $v) { + if ($k == 'returnto-action') { + $action = $v; + } else if (substr($k, 0, 9) == 'returnto-') { + $args[substr($k, 9)] = $v; + } + } + + if ($action) { + common_redirect(common_local_url($action, $args), 303); + } else { + common_redirect(common_local_url('blockedfromgroup', + array('nickname' => $this->group->nickname)), + 303); + } + } +} + diff --git a/classes/Group_block.php b/classes/Group_block.php index d945fd57a..4c583d8e2 100644 --- a/classes/Group_block.php +++ b/classes/Group_block.php @@ -92,4 +92,24 @@ class Group_block extends Memcached_DataObject return $block; } + + static function unblockProfile($group, $profile) + { + $block = Group_block::pkeyGet(array('group_id' => $group->id, + 'blocked' => $profile->id)); + + if (empty($block)) { + return null; + } + + $result = $block->delete(); + + if (!$result) { + common_log_db_error($block, 'DELETE', __FILE__); + return null; + } + + return true; + } + } diff --git a/classes/User_group.php b/classes/User_group.php index 1be34b60b..9f9977755 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -125,6 +125,29 @@ class User_group extends Memcached_DataObject return $members; } + function getBlocked($offset=0, $limit=null) + { + $qry = + 'SELECT profile.* ' . + 'FROM profile JOIN group_block '. + 'ON profile.id = group_block.blocked ' . + 'WHERE group_block.group_id = %d ' . + 'ORDER BY group_block.modified DESC '; + + if ($limit != null) { + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + } + + $blocked = new Profile(); + + $blocked->query(sprintf($qry, $this->id)); + return $blocked; + } + function setOriginal($filename) { $imagefile = new ImageFile($this->id, Avatar::path($filename)); diff --git a/lib/groupnav.php b/lib/groupnav.php index 90bdc1014..194247982 100644 --- a/lib/groupnav.php +++ b/lib/groupnav.php @@ -95,6 +95,12 @@ class GroupNav extends Widget $cur = common_current_user(); if ($cur && $cur->isAdmin($this->group)) { + $this->out->menuItem(common_local_url('blockedfromgroup', array('nickname' => + $nickname)), + _('Blocked'), + sprintf(_('%s blocked users'), $nickname), + $action_name == 'blockedfromgroup', + 'nav_group_blocked'); $this->out->menuItem(common_local_url('editgroup', array('nickname' => $nickname)), _('Admin'), diff --git a/lib/router.php b/lib/router.php index 3d870e565..e10871bc0 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,8 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'unblock', 'subedit', 'groupblock'); + 'block', 'unblock', 'subedit', + 'groupblock', 'groupunblock'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -228,6 +229,10 @@ class Router array('nickname' => '[a-zA-Z0-9]+')); } + $m->connect('group/:nickname/blocked', + array('action' => 'blockedfromgroup'), + array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:id/id', array('action' => 'groupbyid'), array('id' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From 0bc9b2e730bb6368d36ba5bb3f2df1bf1432adad Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 15 Jun 2009 03:21:15 +0000 Subject: Cross-browser notice_attach --- lib/noticeform.php | 4 ++-- theme/base/css/display.css | 20 +++++++++++--------- theme/base/css/ie.css | 9 +++++++++ theme/default/css/ie.css | 7 ++++++- theme/identica/css/ie.css | 7 ++++++- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/lib/noticeform.php b/lib/noticeform.php index 3212f382a..0ad365856 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -148,12 +148,12 @@ class NoticeForm extends Form $this->out->element('dd', array('id' => 'notice_text-count'), '140'); $this->out->elementEnd('dl'); - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); - $this->out->element('label', array('for' => 'notice_data-attach'), _('Attach')); + $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); $this->out->element('input', array('id' => 'notice_data-attach', 'type' => 'file', 'name' => 'attach', 'title' => _('Attach a file'))); + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index dc275e19f..060fdfd0d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -445,6 +445,8 @@ width:80.789%; height:67px; line-height:1.5; padding:7px 7px 16px 7px; +position:relative; +z-index:2; } #form_notice label { display:block; @@ -452,23 +454,23 @@ float:left; font-size:1.3em; margin-bottom:7px; } -#form_notice label[for=notice_data-attach] { -text-indent:-9999px; -} #form_notice label[for=notice_data-attach], #form_notice #notice_data-attach { position:absolute; top:25px; -right:49px; +cursor:pointer; +} +#form_notice label[for=notice_data-attach] { +text-indent:-9999px; +left:394px; width:16px; height:16px; -cursor:pointer; } #form_notice #notice_data-attach { -text-indent:-279px; -} -#form_notice #notice_submit label { -display:none; +left:183px; +padding:0; + +height:16px; } #form_notice .form_note { position:absolute; diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index 8183fee67..d1b0558ec 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -8,6 +8,15 @@ top:0; #form_notice textarea { width:78%; } +#form_notice .form_note + label { +position:absolute; +top:25px; +left:380px; +text-indent:-9999px; +height:16px; +width:16px; +display:block; +} #form_notice #notice_action-submit { width:17%; max-width:17%; diff --git a/theme/default/css/ie.css b/theme/default/css/ie.css index 2b06768ea..6501f4e48 100644 --- a/theme/default/css/ie.css +++ b/theme/default/css/ie.css @@ -3,7 +3,12 @@ .notice-options input.submit { color:#fff; } - #site_nav_local_views a { background-color:#ACCCDA; } +#form_notice .form_note + label { +background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +} +#form_notice #notice_data-attach { +filter: alpha(opacity=0); +} \ No newline at end of file diff --git a/theme/identica/css/ie.css b/theme/identica/css/ie.css index 2f463bb44..69db16aad 100644 --- a/theme/identica/css/ie.css +++ b/theme/identica/css/ie.css @@ -3,7 +3,12 @@ .notice-options input.submit { color:#fff; } - #site_nav_local_views a { background-color:#D0DFE7; } +#form_notice .form_note + label { +background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +} +#form_notice #notice_data-attach { +filter: alpha(opacity=0); +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 0deb2928e649c358ce1046028dcca4dabc4b3aa6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 21:40:47 -0700 Subject: add a table for group aliases --- db/laconica.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/db/laconica.sql b/db/laconica.sql index bc824fc4d..b8c0824f5 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -493,3 +493,13 @@ create table group_block ( constraint primary key (group_id, blocked) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table group_alias ( + + alias varchar(64) primary key comment 'additional nickname for the group', + group_id integer not null comment 'group profile is blocked from' references user_group (id), + modified timestamp comment 'date alias was created', + + index group_alias_group_id_idx (group_id) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; -- cgit v1.2.3-54-g00ecf From 2d63daa71c6ec8ac5fb34004075417c4bb0c6e19 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 21:52:31 -0700 Subject: Added Group_alias class --- classes/Group_alias.php | 41 +++++++++++++++++++++++++++++++++++++++++ classes/laconica.ini | 8 ++++++++ 2 files changed, 49 insertions(+) create mode 100755 classes/Group_alias.php mode change 100644 => 100755 classes/laconica.ini diff --git a/classes/Group_alias.php b/classes/Group_alias.php new file mode 100755 index 000000000..e801e50e1 --- /dev/null +++ b/classes/Group_alias.php @@ -0,0 +1,41 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Group_alias extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'group_alias'; // table name + public $alias; // varchar(64) primary_key not_null + public $group_id; // int(4) not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Group_alias',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100644 new mode 100755 index 8e4e78b79..df292bbff --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -158,6 +158,14 @@ id = K service = K uri = U +[group_alias] +alias = 130 +group_id = 129 +modified = 384 + +[group_alias__keys] +alias = K + [group_block] group_id = 129 blocked = 129 -- cgit v1.2.3-54-g00ecf From a4055fc2f9a79aa9aa2321e132a7133c088859cd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 21:53:09 -0700 Subject: fixup perms for classes --- classes/Group_alias.php | 0 classes/laconica.ini | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 classes/Group_alias.php mode change 100755 => 100644 classes/laconica.ini diff --git a/classes/Group_alias.php b/classes/Group_alias.php old mode 100755 new mode 100644 diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100755 new mode 100644 -- cgit v1.2.3-54-g00ecf From 23fd58b74c7d37b56c7fee897a485729061196d5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 21:53:29 -0700 Subject: fix perms for classes/statusnet.ini --- classes/statusnet.ini | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 classes/statusnet.ini diff --git a/classes/statusnet.ini b/classes/statusnet.ini old mode 100755 new mode 100644 -- cgit v1.2.3-54-g00ecf From ee8dd62038993c184b704df08a3ab1fbcf0c04ac Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:07:27 -0700 Subject: try to get the right class for profileminilist --- lib/profilelist.php | 17 +++++++++++++++-- lib/profileminilist.php | 5 +++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/profilelist.php b/lib/profilelist.php index e2faf10af..bd866bed7 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -61,9 +61,24 @@ class ProfileList extends Widget } function show() + { + $this->startList(); + $this->showProfiles(); + $this->endList(); + } + + function startList() { $this->out->elementStart('ul', 'profiles'); + } + function endList() + { + $this->out->elementEnd('ul'); + } + + function showProfiles() + { $cnt = 0; while ($this->profile->fetch()) { @@ -75,8 +90,6 @@ class ProfileList extends Widget $pli->show(); } - $this->out->elementEnd('ul'); - return $cnt; } diff --git a/lib/profileminilist.php b/lib/profileminilist.php index f11cae8a5..0c02e2735 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -47,6 +47,11 @@ define('PROFILES_PER_MINILIST', 27); class ProfileMiniList extends ProfileList { + function startList() + { + $this->out->elementStart('ul', 'entity users xoxo'); + } + function newListItem($profile) { return new ProfileMiniListItem($profile, $this->action); -- cgit v1.2.3-54-g00ecf From bef643352d573235aedbdd93125e93c42edb306b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:09:04 -0700 Subject: return count from show --- lib/profilelist.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/profilelist.php b/lib/profilelist.php index bd866bed7..a604230f8 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -63,8 +63,9 @@ class ProfileList extends Widget function show() { $this->startList(); - $this->showProfiles(); + $cnt = $this->showProfiles(); $this->endList(); + return $cnt; } function startList() -- cgit v1.2.3-54-g00ecf From 7097804eeb0c648391544f55e32bd66bc35bcdb1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:09:17 -0700 Subject: typo in profileminilist class --- lib/profileminilist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/profileminilist.php b/lib/profileminilist.php index 0c02e2735..09bef6f7c 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -49,7 +49,7 @@ class ProfileMiniList extends ProfileList { function startList() { - $this->out->elementStart('ul', 'entity users xoxo'); + $this->out->elementStart('ul', 'entities users xoxo'); } function newListItem($profile) -- cgit v1.2.3-54-g00ecf From 2f3c4f8812d389df40cf62b8967cf3e359ad5663 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:16:24 -0700 Subject: add correct li for css magic for block stuff --- actions/blockedfromgroup.php | 2 ++ actions/groupmembers.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php index 1b7b31784..541ebcfd9 100644 --- a/actions/blockedfromgroup.php +++ b/actions/blockedfromgroup.php @@ -176,10 +176,12 @@ class GroupBlockListItem extends ProfileListItem $user = common_current_user(); if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { + $this->out->elementStart('li', 'entity_block'); $bf = new GroupUnblockForm($this->out, $this->profile, $this->group, array('action' => 'blockedfromgroup', 'nickname' => $this->group->nickname)); $bf->show(); + $this->out->elementEnd('li'); } } } diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 150b60a54..65790b7ca 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -180,10 +180,12 @@ class GroupMemberListItem extends ProfileListItem $user = common_current_user(); if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { + $this->out->elementStart('li', 'entity_block'); $bf = new GroupBlockForm($this->out, $this->profile, $this->group, array('action' => 'groupmembers', 'nickname' => $this->group->nickname)); $bf->show(); + $this->out->elementEnd('li'); } } -- cgit v1.2.3-54-g00ecf From e18504d1d246c48f64964e176c9134e56cd20db9 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 15 Jun 2009 05:38:18 +0000 Subject: Styles for group block --- theme/base/css/display.css | 2 ++ theme/default/css/display.css | 8 +++++++- theme/identica/css/display.css | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 060fdfd0d..0cbd0d774 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -618,6 +618,8 @@ display:block; .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_send-a-message a, .entity_edit a, .form_user_nudge input.submit, diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 34f6b3b8a..166e62157 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -57,6 +57,8 @@ a, div.notice-options input, .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_send-a-message a, .form_user_nudge input.submit, .entity_nudge p, @@ -148,6 +150,8 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_user_nudge input.submit, .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_nudge p { background-position: 0 40%; background-repeat: no-repeat; @@ -177,7 +181,9 @@ background-image:url(../../base/images/icons/twotone/green/quote.gif); background-image:url(../../base/images/icons/twotone/green/mail.gif); } .form_user_block input.submit, -.form_user_unblock input.submit { +.form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit { background-image:url(../../base/images/icons/twotone/green/shield.gif); } diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 8a03a4d77..cab42f16f 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -57,6 +57,8 @@ a, div.notice-options input, .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_send-a-message a, .form_user_nudge input.submit, .entity_nudge p, @@ -148,6 +150,8 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_user_nudge input.submit, .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_nudge p { background-position: 0 40%; background-repeat: no-repeat; @@ -177,7 +181,9 @@ background-image:url(../../base/images/icons/twotone/green/quote.gif); background-image:url(../../base/images/icons/twotone/green/mail.gif); } .form_user_block input.submit, -.form_user_unblock input.submit { +.form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit { background-image:url(../../base/images/icons/twotone/green/shield.gif); } -- cgit v1.2.3-54-g00ecf From ecbd7718d57fc427d2aeac885d8be0321b3cf1fe Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 23:37:24 -0700 Subject: Code for adding and saving group aliases Added code to add and save group aliases. Like tags, aliases are free-texted in to the group admin page. configurable max number of aliases, default is three. --- README | 8 ++++++- actions/editgroup.php | 59 ++++++++++++++++++++++++++++++++++++++++++++++--- actions/newgroup.php | 51 +++++++++++++++++++++++++++++++++++++++++- classes/User_group.php | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/common.php | 2 ++ lib/groupeditform.php | 11 ++++++++- 6 files changed, 185 insertions(+), 6 deletions(-) diff --git a/README b/README index 2099f94d6..8fb4a941c 100644 --- a/README +++ b/README @@ -1196,7 +1196,6 @@ reporturl: URL to post statistics to. Defaults to Laconica developers' set 'run' to 'never' than to set this value to something nonsensical. - attachments ----------- @@ -1226,6 +1225,13 @@ user_quota: total size in bytes a user can store on this server. Each user monthly_quota: total size permitted in the current month. This is the total size in bytes that a user can upload each month. +group +----- + +Options for group functionality. + +maxaliases: maximum number of aliases a group can have. Default 3. Set + to 0 or less to prevent aliases in a group. Troubleshooting =============== diff --git a/actions/editgroup.php b/actions/editgroup.php index 39dad0465..29a7bce43 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -171,6 +171,7 @@ class EditgroupAction extends Action $homepage = $this->trimmed('homepage'); $description = $this->trimmed('description'); $location = $this->trimmed('location'); + $aliasstring = $this->trimmed('aliases'); if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, @@ -201,6 +202,39 @@ class EditgroupAction extends Action return; } + if (!empty($aliasstring)) { + $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring))); + } else { + $aliases = array(); + } + + if (count($aliases) > common_config('group', 'maxaliases')) { + $this->showForm(sprintf(_('Too many aliases! Maximum %d.'), + common_config('group', 'maxaliases'))); + return; + } + + foreach ($aliases as $alias) { + if (!Validate::string($alias, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias)); + return; + } + if ($this->nicknameExists($alias)) { + $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), + $alias)); + return; + } + // XXX assumes alphanum nicknames + if (strcmp($alias, $nickname) == 0) { + $this->showForm(_('Alias can\'t be the same as nickname.')); + return; + } + } + + $this->group->query('BEGIN'); + $orig = clone($this->group); $this->group->nickname = $nickname; @@ -217,6 +251,14 @@ class EditgroupAction extends Action $this->serverError(_('Could not update group.')); } + $result = $this->group->setAliases($aliases); + + if (!$result) { + $this->serverError(_('Could not create aliases.')); + } + + $this->group->query('COMMIT'); + if ($this->group->nickname != $orig->nickname) { common_redirect(common_local_url('editgroup', array('nickname' => $nickname)), @@ -229,9 +271,20 @@ class EditgroupAction extends Action function nicknameExists($nickname) { $group = User_group::staticGet('nickname', $nickname); - return (!is_null($group) && - $group != false && - $group->id != $this->group->id); + + if (!empty($group) && + $group->id != $this->group->id) { + return true; + } + + $alias = Group_alias::staticGet('alias', $nickname); + + if (!empty($alias) && + $alias->group_id != $this->group->id) { + return true; + } + + return false; } } diff --git a/actions/newgroup.php b/actions/newgroup.php index 67cd6b2f1..0289e77c2 100644 --- a/actions/newgroup.php +++ b/actions/newgroup.php @@ -123,6 +123,7 @@ class NewgroupAction extends Action $homepage = $this->trimmed('homepage'); $description = $this->trimmed('description'); $location = $this->trimmed('location'); + $aliasstring = $this->trimmed('aliases'); if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, @@ -153,6 +154,37 @@ class NewgroupAction extends Action return; } + if (!empty($aliasstring)) { + $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring))); + } else { + $aliases = array(); + } + + if (count($aliases) > common_config('group', 'maxaliases')) { + $this->showForm(sprintf(_('Too many aliases! Maximum %d.'), + common_config('group', 'maxaliases'))); + return; + } + + foreach ($aliases as $alias) { + if (!Validate::string($alias, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias)); + return; + } + if ($this->nicknameExists($alias)) { + $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), + $alias)); + return; + } + // XXX assumes alphanum nicknames + if (strcmp($alias, $nickname) == 0) { + $this->showForm(_('Alias can\'t be the same as nickname.')); + return; + } + } + $cur = common_current_user(); // Checked in prepare() above @@ -177,6 +209,12 @@ class NewgroupAction extends Action $this->serverError(_('Could not create group.')); } + $result = $group->setAliases($aliases); + + if (!$result) { + $this->serverError(_('Could not create aliases.')); + } + $member = new Group_member(); $member->group_id = $group->id; @@ -199,7 +237,18 @@ class NewgroupAction extends Action function nicknameExists($nickname) { $group = User_group::staticGet('nickname', $nickname); - return (!is_null($group) && $group != false); + + if (!empty($group)) { + return true; + } + + $alias = Group_alias::staticGet('alias', $nickname); + + if (!empty($alias)) { + return true; + } + + return false; } } diff --git a/classes/User_group.php b/classes/User_group.php index 9f9977755..0fcfee8c6 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -165,4 +165,64 @@ class User_group extends Memcached_DataObject { return ($this->fullname) ? $this->fullname : $this->nickname; } + + function getAliases() + { + $aliases = array(); + + // XXX: cache this + + $alias = new Group_alias(); + + $alias->group_id = $this->id; + + if ($alias->find()) { + while ($alias->fetch()) { + $aliases[] = $alias->alias; + } + } + + $alias->free(); + + return $aliases; + } + + function setAliases($newaliases) { + + $newaliases = array_unique($newaliases); + + $oldaliases = $this->getAliases(); + + # Delete stuff that's old that not in new + + $to_delete = array_diff($oldaliases, $newaliases); + + # Insert stuff that's in new and not in old + + $to_insert = array_diff($newaliases, $oldaliases); + + $alias = new Group_alias(); + + $alias->group_id = $this->id; + + foreach ($to_delete as $delalias) { + $alias->alias = $delalias; + $result = $alias->delete(); + if (!$result) { + common_log_db_error($alias, 'DELETE', __FILE__); + return false; + } + } + + foreach ($to_insert as $insalias) { + $alias->alias = $insalias; + $result = $alias->insert(); + if (!$result) { + common_log_db_error($alias, 'INSERT', __FILE__); + return false; + } + } + + return true; + } } diff --git a/lib/common.php b/lib/common.php index 6bf4ad21f..b4e87445e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -198,6 +198,8 @@ $config = 'user_quota' => 50000000, 'monthly_quota' => 15000000, ), + 'group' => + array('maxaliases' => 3), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/groupeditform.php b/lib/groupeditform.php index ca674f3c8..7e8d6eea3 100644 --- a/lib/groupeditform.php +++ b/lib/groupeditform.php @@ -111,7 +111,6 @@ class GroupEditForm extends Form } } - /** * Name of the form * @@ -157,6 +156,16 @@ class GroupEditForm extends Form ($this->out->arg('location')) ? $this->out->arg('location') : $this->group->location, _('Location for the group, if any, like "City, State (or Region), Country"')); $this->out->elementEnd('li'); + if (common_config('group', 'maxaliases') > 0) { + $aliases = (empty($this->group)) ? array() : $this->group->getAliases(); + $this->out->elementStart('li'); + $this->out->input('aliases', _('Aliases'), + ($this->out->arg('aliases')) ? $this->out->arg('aliases') : + (!empty($aliases)) ? implode(' ', $aliases) : '', + sprintf(_('Extra nicknames for the group, comma- or space- separated, max %d'), + common_config('group', 'maxaliases')));; + $this->out->elementEnd('li'); + } $this->out->elementEnd('ul'); } -- cgit v1.2.3-54-g00ecf From 1b6b00a6d05ad646a9137a872af8d8fdeeaf260f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 23:43:47 -0700 Subject: Link and distribute notices tagged for a group alias Correctly link and distribute notices tagged for a group alias. Added a helper function, getForNickname(), to User_group, to make it easier to get a group by its nickname or aliases. --- classes/Notice.php | 6 +++--- classes/User_group.php | 14 ++++++++++++++ lib/util.php | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 78786b27d..68602b1f7 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -752,16 +752,16 @@ class Notice extends Memcached_DataObject foreach (array_unique($match[1]) as $nickname) { /* XXX: remote groups. */ - $group = User_group::staticGet('nickname', $nickname); + $group = User_group::getForNickname($nickname); - if (!$group) { + if (empty($group)) { continue; } // we automatically add a tag for every group name, too $tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($nickname), - 'notice_id' => $this->id)); + 'notice_id' => $this->id)); if (is_null($tag)) { $this->saveTag($nickname); diff --git a/classes/User_group.php b/classes/User_group.php index 0fcfee8c6..1a24124bb 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -225,4 +225,18 @@ class User_group extends Memcached_DataObject return true; } + + static function getForNickname($nickname) + { + $nickname = common_canonical_nickname($nickname); + $group = User_group::staticGet('nickname', $nickname); + if (!empty($group)) { + return $group; + } + $alias = Group_alias::staticGet('alias', $nickname); + if (!empty($alias)) { + return User_group::staticGet('id', $alias->group_id); + } + return null; + } } diff --git a/lib/util.php b/lib/util.php index b3a94a5a0..49c6ae108 100644 --- a/lib/util.php +++ b/lib/util.php @@ -591,7 +591,7 @@ function common_at_link($sender_id, $nickname) function common_group_link($sender_id, $nickname) { $sender = Profile::staticGet($sender_id); - $group = User_group::staticGet('nickname', common_canonical_nickname($nickname)); + $group = User_group::getForNickname($nickname); if ($group && $sender->isMember($group)) { $attrs = array('href' => $group->permalink(), 'class' => 'url'); -- cgit v1.2.3-54-g00ecf From dda4493af72870d61774c8389dbbab13c2dfbbc7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 23:51:38 -0700 Subject: show aliases when showing a group --- actions/showgroup.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/actions/showgroup.php b/actions/showgroup.php index 537f09278..357f579d8 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -272,6 +272,17 @@ class ShowgroupAction extends Action $this->elementEnd('dl'); } + if (common_config('group', 'maxaliases') > 0) { + $aliases = $this->group->getAliases(); + + if (!empty($aliases)) { + $this->elementStart('dl', 'entity_aliases'); + $this->element('dt', null, _('Aliases')); + $this->element('dd', 'aliases', implode(' ', $aliases)); + $this->elementEnd('dl'); + } + } + $this->elementEnd('div'); $this->elementStart('div', 'entity_actions'); -- cgit v1.2.3-54-g00ecf From 2b8a767770119165ab9c9ce62ea3512c2fb3b049 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 00:59:15 -0700 Subject: make admins of groups --- actions/groupmembers.php | 143 +++++++++++++++++++++++++++++++++++++++++++++++ lib/router.php | 4 ++ 2 files changed, 147 insertions(+) diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 65790b7ca..abfad3f0d 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -171,10 +171,26 @@ class GroupMemberListItem extends ProfileListItem { $this->startActions(); $this->showSubscribeButton(); + $this->showMakeAdminForm(); $this->showGroupBlockForm(); $this->endActions(); } + function showMakeAdminForm() + { + $user = common_current_user(); + + if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group) && + !$this->profile->isAdmin($this->group)) { + $this->out->elementStart('li', 'entity_make_admin'); + $maf = new MakeAdminForm($this->out, $this->profile, $this->group, + array('action' => 'groupmembers', + 'nickname' => $this->group->nickname)); + $maf->show(); + $this->out->elementEnd('li'); + } + + } function showGroupBlockForm() { $user = common_current_user(); @@ -318,3 +334,130 @@ class GroupBlockForm extends Form $this->out->submit('submit', _('Block'), 'submit', null, _('Block this user')); } } + +/** + * Form for making a user an admin for a group + * + * @category Form + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class MakeAdminForm extends Form +{ + /** + * Profile of user to block + */ + + var $profile = null; + + /** + * Group to block the user from + */ + + var $group = null; + + /** + * Return-to args + */ + + var $args = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Profile $profile profile of user to block + * @param User_group $group group to block user from + * @param array $args return-to args + */ + + function __construct($out=null, $profile=null, $group=null, $args=null) + { + parent::__construct($out); + + $this->profile = $profile; + $this->group = $group; + $this->args = $args; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + // This should be unique for the page. + return 'makeadmin-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_make_admin'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('makeadmin', array('nickname' => $this->group->nickname)); + } + + /** + * Legend of the Form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, _('Make user an admin of the group')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('profileid-' . $this->profile->id, + $this->profile->id, + 'profileid'); + $this->out->hidden('groupid-' . $this->group->id, + $this->group->id, + 'groupid'); + if ($this->args) { + foreach ($this->args as $k => $v) { + $this->out->hidden('returnto-' . $k, $v); + } + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Make Admin'), 'submit', null, _('Make this user an admin')); + } +} diff --git a/lib/router.php b/lib/router.php index e10871bc0..0fbaba9ed 100644 --- a/lib/router.php +++ b/lib/router.php @@ -233,6 +233,10 @@ class Router array('action' => 'blockedfromgroup'), array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:nickname/makeadmin', + array('action' => 'makeadmin'), + array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:id/id', array('action' => 'groupbyid'), array('id' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From 528ceec3fe351cfa3f5050159b2c9e37357e162a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 05:44:36 -0700 Subject: makeadmin action --- actions/makeadmin.php | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 actions/makeadmin.php diff --git a/actions/makeadmin.php b/actions/makeadmin.php new file mode 100644 index 000000000..899c23ae4 --- /dev/null +++ b/actions/makeadmin.php @@ -0,0 +1,166 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Make another user an admin of a group + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class MakeadminAction extends Action +{ + var $profile = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + + function prepare($args) + { + parent::prepare($args); + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return false; + } + $token = $this->trimmed('token'); + if (empty($token) || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. Try again, please.')); + return; + } + $id = $this->trimmed('profileid'); + if (empty($id)) { + $this->clientError(_('No profile specified.')); + return false; + } + $this->profile = Profile::staticGet('id', $id); + if (empty($this->profile)) { + $this->clientError(_('No profile with that ID.')); + return false; + } + $group_id = $this->trimmed('groupid'); + if (empty($group_id)) { + $this->clientError(_('No group specified.')); + return false; + } + $this->group = User_group::staticGet('id', $group_id); + if (empty($this->group)) { + $this->clientError(_('No such group.')); + return false; + } + $user = common_current_user(); + if (!$user->isAdmin($this->group)) { + $this->clientError(_('Only an admin can make another user an admin.'), 401); + return false; + } + if ($this->profile->isAdmin($this->group)) { + $this->clientError(sprintf(_('%s is already an admin for group "%s".'), + $this->profile->getBestName(), + $this->group->getBestName()), + 401); + return false; + } + return true; + } + + /** + * Handle request + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->makeAdmin(); + } + } + + /** + * Make user an admin + * + * @return void + */ + + function makeAdmin() + { + $member = Group_member::pkeyGet(array('group_id' => $this->group->id, + 'profile_id' => $this->profile->id)); + + if (empty($member)) { + $this->serverError(_('Can\'t get membership record for %s in group %s'), + $this->profile->getBestName(), + $this->group->getBestName()); + } + + $orig = clone($member); + + $member->is_admin = 1; + + $result = $member->update($orig); + + if (!$result) { + common_log_db_error($member, 'UPDATE', __FILE__); + $this->serverError(_('Can\'t make %s an admin for group %s'), + $this->profile->getBestName(), + $this->group->getBestName()); + } + + foreach ($this->args as $k => $v) { + if ($k == 'returnto-action') { + $action = $v; + } else if (substr($k, 0, 9) == 'returnto-') { + $args[substr($k, 9)] = $v; + } + } + + if ($action) { + common_redirect(common_local_url($action, $args), 303); + } else { + common_redirect(common_local_url('groupmembers', + array('nickname' => $this->group->nickname)), + 303); + } + } +} -- cgit v1.2.3-54-g00ecf From eb6a60ef8833d0a34768f2717f2a34fdcd52e5ce Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 08:54:52 -0700 Subject: updates to Status_network --- classes/Status_network.php | 25 +++++++++++++++++++++---- classes/statusnet.ini | 5 +++-- db/site.sql | 6 +++++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index f7747f71d..d2b942bfb 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -12,11 +12,13 @@ class Status_network extends DB_DataObject public $nickname; // varchar(64) primary_key not_null public $hostname; // varchar(255) unique_key public $pathname; // varchar(255) unique_key - public $sitename; // varchar(255) public $dbhost; // varchar(255) public $dbuser; // varchar(255) public $dbpass; // varchar(255) public $dbname; // varchar(255) + public $sitename; // varchar(255) + public $theme; // varchar(255) + public $logo; // varchar(255) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP @@ -37,13 +39,19 @@ class Status_network extends DB_DataObject return true; } - static function setupSite($servername, $pathname) + static function setupSite($servername, $pathname, $wildcard) { global $config; - $parts = explode('.', $servername); + // XXX I18N, probably not crucial for hostnames + // XXX This probably needs a tune up - $sn = Status_network::staticGet('nickname', $parts[0]); + if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) { + $parts = explode('.', $servername); + $sn = Status_network::staticGet('nickname', strtolower($parts[0])); + } else { + $sn = Status_network::staticGet('hostname', strtolower($servername)); + } if (!empty($sn)) { $dbhost = (empty($sn->dbhost)) ? 'localhost' : $sn->dbhost; @@ -52,7 +60,16 @@ class Status_network extends DB_DataObject $dbname = (empty($sn->dbname)) ? $sn->nickname : $sn->dbname; $config['db']['database'] = "mysqli://$dbuser:$dbpass@$dbhost/$dbname"; + $config['site']['name'] = $sn->sitename; + + if (!empty($sn->theme)) { + $config['site']['theme'] = $sn->theme; + } + if (!empty($sn->logo)) { + $config['site']['logo'] = $sn->logo; + } + return true; } else { return false; diff --git a/classes/statusnet.ini b/classes/statusnet.ini index a70cd4122..8123265e4 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -1,13 +1,14 @@ - [status_network] nickname = 130 hostname = 2 pathname = 2 -sitename = 2 dbhost = 2 dbuser = 2 dbpass = 2 dbname = 2 +sitename = 2 +theme = 2 +logo = 2 created = 142 modified = 384 diff --git a/db/site.sql b/db/site.sql index 660ba475b..a9f64e5a5 100644 --- a/db/site.sql +++ b/db/site.sql @@ -5,12 +5,16 @@ create table status_network ( nickname varchar(64) primary key comment 'nickname', hostname varchar(255) unique key comment 'alternate hostname if any', pathname varchar(255) unique key comment 'alternate pathname if any', - sitename varchar(255) comment 'display name', + dbhost varchar(255) comment 'database host', dbuser varchar(255) comment 'database username', dbpass varchar(255) comment 'database password', dbname varchar(255) comment 'database name', + sitename varchar(255) comment 'display name', + theme varchar(255) comment 'theme name', + logo varchar(255) comment 'site logo', + created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified' -- cgit v1.2.3-54-g00ecf From c077ad0775218e6aa8660ba97129ad74b5d54773 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 10:45:50 -0700 Subject: Configurable avatar directory Avatar directory and path are configurable. --- README | 6 ++++++ classes/Avatar.php | 30 +++++++++++++++++++++++++++--- lib/common.php | 4 +++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README b/README index 8fb4a941c..5b6b847c8 100644 --- a/README +++ b/README @@ -1008,6 +1008,12 @@ avatar For configuring avatar access. +dir: Directory to look for avatar files and to put them into. + Defaults to avatar subdirectory of install directory; if + you change it, make sure to change path, too. +path: Path to avatars. Defaults to path for avatar subdirectory, + but you can change it if you wish. Note that this will + be included with the avatar server, too. server: If set, defines another server where avatars are stored in the root directory. Note that the 'avatar' subdir still has to be writeable. You'd typically use this to split HTTP requests on diff --git a/classes/Avatar.php b/classes/Avatar.php index db9d78e47..5e8b315fe 100644 --- a/classes/Avatar.php +++ b/classes/Avatar.php @@ -55,19 +55,43 @@ class Avatar extends Memcached_DataObject static function path($filename) { - return INSTALLDIR . '/avatar/' . $filename; + $dir = common_config('avatar', 'dir'); + + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } + + return $dir . $filename; } static function url($filename) { - return common_path('avatar/'.$filename); + $path = common_config('avatar', 'path'); + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('avatar', 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + // XXX: protocol + + return 'http://'.$server.$path.$filename; } function displayUrl() { $server = common_config('avatar', 'server'); if ($server) { - return 'http://'.$server.'/'.$this->filename; + return Avatar::url($this->filename); } else { return $this->url; } diff --git a/lib/common.php b/lib/common.php index b4e87445e..ab61c812f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -108,7 +108,9 @@ $config = 'profile' => array('banned' => array()), 'avatar' => - array('server' => null), + array('server' => null, + 'dir' => INSTALLDIR . '/avatar/', + 'path' => $_path . '/avatar/'), 'public' => array('localonly' => true, 'blacklist' => array(), -- cgit v1.2.3-54-g00ecf From 807d84d448fb453de777d7a1ef938150bb03de3e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 12:57:08 -0700 Subject: Small fix to correct the order of defined color prefs --- actions/designsettings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 8595cbc4c..dba983fdf 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -106,10 +106,10 @@ class DesignsettingsAction extends AccountSettingsAction } $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-5'), _('Background')); + $this->element('label', array('for' => 'swatch-0'), _('Background')); $this->element('input', array('name' => 'design_background', 'type' => 'text', - 'id' => 'swatch-5', + 'id' => 'swatch-0', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', -- cgit v1.2.3-54-g00ecf From d6ff702d7f0937451c8595c7b3cbfb9f2813a07b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 13:34:52 -0700 Subject: Return network from network setup function Return the network from the network setup function. Also, special-case for when we get a server name the same as the wildcard. --- classes/Status_network.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index d2b942bfb..96b6d9a05 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -43,12 +43,19 @@ class Status_network extends DB_DataObject { global $config; + $sn = null; + // XXX I18N, probably not crucial for hostnames // XXX This probably needs a tune up if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) { - $parts = explode('.', $servername); - $sn = Status_network::staticGet('nickname', strtolower($parts[0])); + // special case for exact match + if (0 == strncmp($servername, $wildcard)) { + $sn = Status_network::staticGet('nickname', ''); + } else { + $parts = explode('.', $servername); + $sn = Status_network::staticGet('nickname', strtolower($parts[0])); + } } else { $sn = Status_network::staticGet('hostname', strtolower($servername)); } @@ -70,9 +77,9 @@ class Status_network extends DB_DataObject $config['site']['logo'] = $sn->logo; } - return true; + return $sn; } else { - return false; + return null; } } } -- cgit v1.2.3-54-g00ecf From 2f693c4c9453fc61bea960ba8767fdf68e5130cd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 15 Jun 2009 21:02:12 +0000 Subject: Updated swatch numbering --- actions/designsettings.php | 21 ++++++++++----------- js/farbtastic/farbtastic.go.js | 12 ++++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index dba983fdf..46a5843f8 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -106,10 +106,10 @@ class DesignsettingsAction extends AccountSettingsAction } $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-0'), _('Background')); + $this->element('label', array('for' => 'swatch-1'), _('Background')); $this->element('input', array('name' => 'design_background', 'type' => 'text', - 'id' => 'swatch-0', + 'id' => 'swatch-1', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -117,10 +117,10 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('li'); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('label', array('for' => 'swatch-2'), _('Content')); $this->element('input', array('name' => 'design_content', 'type' => 'text', - 'id' => 'swatch-1', + 'id' => 'swatch-2', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -128,10 +128,10 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('li'); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); $this->element('input', array('name' => 'design_sidebar', 'type' => 'text', - 'id' => 'swatch-2', + 'id' => 'swatch-3', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -139,10 +139,10 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('li'); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('label', array('for' => 'swatch-4'), _('Text')); $this->element('input', array('name' => 'design_text', 'type' => 'text', - 'id' => 'swatch-3', + 'id' => 'swatch-4', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -150,15 +150,14 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('li'); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('label', array('for' => 'swatch-5'), _('Links')); $this->element('input', array('name' => 'design_links', 'type' => 'text', - 'id' => 'swatch-4', + 'id' => 'swatch-5', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', 'value' => $design->linkcolor)); - $this->elementEnd('li'); $this->elementEnd('ul'); diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 0149eca7d..4e0493b40 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -10,19 +10,19 @@ $(document).ready(function() { function UpdateColors(S) { C = $(S).val(); switch (parseInt(S.id.slice(-1))) { - case 0: default: + case 1: default: $('body').css({'background-color':C}); break; - case 1: - $('#content').css({'background-color':C}); - break; case 2: - $('#aside_primary').css({'background-color':C}); + $('#content').css({'background-color':C}); break; case 3: - $('body').css({'color':C}); + $('#aside_primary').css({'background-color':C}); break; case 4: + $('html body').css({'color':C}); + break; + case 5: $('a').css({'color':C}); break; } -- cgit v1.2.3-54-g00ecf From 6532f0dff63576c94debe521d1ff8d9f594fe422 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 14:29:25 -0700 Subject: strncmp -> strcasecmp --- classes/Status_network.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index 96b6d9a05..bf05ad61e 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -50,7 +50,7 @@ class Status_network extends DB_DataObject if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) { // special case for exact match - if (0 == strncmp($servername, $wildcard)) { + if (0 == strcasecmp($servername, $wildcard)) { $sn = Status_network::staticGet('nickname', ''); } else { $parts = explode('.', $servername); -- cgit v1.2.3-54-g00ecf From 01c03223c2c559deec0191dd7a100e152981e1e2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 15:13:24 -0700 Subject: Script to set up new status networks --- scripts/setup.cfg.sample | 11 +++++++++++ scripts/setup_status_network.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 scripts/setup.cfg.sample create mode 100644 scripts/setup_status_network.sh diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample new file mode 100644 index 000000000..4194bc146 --- /dev/null +++ b/scripts/setup.cfg.sample @@ -0,0 +1,11 @@ +# CONFIGURATION FILE for setup_status_network.sh + +# Base database name; full name will include nickname + +export DBBASE=_example_net +export USERBASE=_example_net +export ADMIN=root +export ADMINPASS=yourpassword +export SITEDB=example_net_site +export AVATARBASE=/var/www/avatar.example.net + diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh new file mode 100644 index 000000000..d80612b94 --- /dev/null +++ b/scripts/setup_status_network.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +source ./setup.cfg + +export nickname=$1 +export sitename=$2 + +export password=`pwgen 20` +export database=$nickname$DBBASE +export username=$nickname$USERBASE + +# Create the db + +mysqladmin -u $ADMIN --password=$ADMINPASS create $database + +for f in laconica.sql sms_carrier.sql foreign_services.sql notice_source.sql; do + mysql -u $ADMIN --password=$ADMINPASS $database < ../db/$f; +done + +mysql -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS + +GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'localhost' IDENTIFIED BY '$password'; +GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'%' IDENTIFIED BY '$password'; +INSERT INTO status_network (nickname, dbhost, dbuser, dbpass, dbname, sitename, created) +VALUES ('$nickname', '$DBHOST', '$username', '$password', '$database', '$sitename', now()); + +ENDOFCOMMANDS + +mkdir $AVATARBASE/$nickname +chmod a+w $AVATARBASE/$nickname -- cgit v1.2.3-54-g00ecf From 177e4adf40bd41fc711c91fc6d16729b7f1b5796 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 15:13:49 -0700 Subject: change mods for setup script --- scripts/setup_status_network.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/setup_status_network.sh diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh old mode 100644 new mode 100755 -- cgit v1.2.3-54-g00ecf From 12cd87cd7b7c207b6f9c30996f0fabb019d6fd76 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:50:14 +0000 Subject: Missing call to getProfile() caused verify_credentials to fail. --- actions/twitapiusers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 13a8746cd..21a56a9a5 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -58,7 +58,7 @@ class TwitapiusersAction extends TwitterapiAction return; } - $twitter_user = $this->twitter_user_array($profile, true); + $twitter_user = $this->twitter_user_array($user->getProfile(), true); if ($apidata['content-type'] == 'xml') { $this->init_document('xml'); -- cgit v1.2.3-54-g00ecf From fd290fc3f9a40a0d3be4e4ffc7d11846bf5295b8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:09:40 -0700 Subject: allow a configured base for cache keys --- README | 7 +++++++ lib/common.php | 1 + lib/util.php | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README b/README index 5b6b847c8..57ff72f66 100644 --- a/README +++ b/README @@ -1106,6 +1106,13 @@ database data in memcached . enabled: Set to true to enable. Default false. server: a string with the hostname of the memcached server. Can also be an array of hostnames, if you've got more than one server. +base: memcached uses key-value pairs to store data. We build long, + funny-looking keys to make sure we don't have any conflicts. The + base of the key is usually a simplified version of the site name + (like "Identi.ca" => "identica"), but you can overwrite this if + you need to. You can safely ignore it if you only have one + Laconica site using your memcached server. +port: Port to connect to; defaults to 11211. sphinx ------ diff --git a/lib/common.php b/lib/common.php index ab61c812f..51204cede 100644 --- a/lib/common.php +++ b/lib/common.php @@ -152,6 +152,7 @@ $config = 'memcached' => array('enabled' => false, 'server' => 'localhost', + 'base' => null, 'port' => 11211), 'ping' => array('notify' => array()), diff --git a/lib/util.php b/lib/util.php index 49c6ae108..1d5708bd6 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1322,7 +1322,13 @@ function common_session_token() function common_cache_key($extra) { - return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra; + $base_key = common_config('memcached', 'base'); + + if (empty($base_key)) { + $base_key = common_keyize(common_config('site', 'name')); + } + + return 'laconica:' . $base_key . ':' . $extra; } function common_keyize($str) -- cgit v1.2.3-54-g00ecf From fbed704f3b6a8237e815be9586eb753cc78d20c3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:22:08 -0700 Subject: don't show create-a-group link if not logged in --- actions/groups.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/actions/groups.php b/actions/groups.php index 26b52a5fc..b49d80f37 100644 --- a/actions/groups.php +++ b/actions/groups.php @@ -100,11 +100,13 @@ class GroupsAction extends Action function showContent() { - $this->elementStart('p', array('id' => 'new_group')); - $this->element('a', array('href' => common_local_url('newgroup'), - 'class' => 'more'), - _('Create a new group')); - $this->elementEnd('p'); + if (common_logged_in()) { + $this->elementStart('p', array('id' => 'new_group')); + $this->element('a', array('href' => common_local_url('newgroup'), + 'class' => 'more'), + _('Create a new group')); + $this->elementEnd('p'); + } $offset = ($this->page-1) * GROUPS_PER_PAGE; $limit = GROUPS_PER_PAGE + 1; -- cgit v1.2.3-54-g00ecf From 587b7a8b2ad0b260cc3159da260a4d439c2a5f0c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:40:53 -0700 Subject: redirect on non-canonical server name --- classes/Status_network.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/classes/Status_network.php b/classes/Status_network.php index bf05ad61e..eef27d765 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -61,6 +61,9 @@ class Status_network extends DB_DataObject } if (!empty($sn)) { + if (!empty($sn->hostname) && 0 != strcasecmp($sn->hostname, $servername)) { + $sn->redirectToHostname(); + } $dbhost = (empty($sn->dbhost)) ? 'localhost' : $sn->dbhost; $dbuser = (empty($sn->dbuser)) ? $sn->nickname : $sn->dbuser; $dbpass = $sn->dbpass; @@ -82,4 +85,29 @@ class Status_network extends DB_DataObject return null; } } + + // Code partially mooked from http://www.richler.de/en/php-redirect/ + // (C) 2006 by Heiko Richler http://www.richler.de/ + // LGPL + + function redirectToHostname() + { + $destination = 'http://'.$this->hostname; + $destination .= $_SERVER['REQUEST_URI']. + $_SERVER['QUERY_STRING']; + + $old = 'http'. + (($_SERVER['HTTPS'] == 'on') ? 'S' : ''). + '://'. + $_SERVER['HTTP_HOST']. + $_SERVER['REQUEST_URI']. + $_SERVER['QUERY_STRING']; + if ($old == $destination) { // this would be a loop! + // error_log(...) ? + return false; + } + + common_redirect($destination, 301); + // shouldn't get here + } } -- cgit v1.2.3-54-g00ecf From 2f82a3d44c4fbb0d9c552a2652e341ec882787c1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:43:39 -0700 Subject: forgot some functions aren't available at status time --- classes/Status_network.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index eef27d765..128721f41 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -107,7 +107,11 @@ class Status_network extends DB_DataObject return false; } - common_redirect($destination, 301); - // shouldn't get here + header('HTTP/1.1 301 Moved Permanently'); + header("Location: $destination"); + + print "$destination\n"; + + exit; } } -- cgit v1.2.3-54-g00ecf From f80966324560d4309b3bb2d6d357719e1e90e6aa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:51:49 -0700 Subject: a little better query handling in redirect code --- classes/Status_network.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index 128721f41..03e8f4525 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -93,8 +93,19 @@ class Status_network extends DB_DataObject function redirectToHostname() { $destination = 'http://'.$this->hostname; - $destination .= $_SERVER['REQUEST_URI']. - $_SERVER['QUERY_STRING']; + $destination .= $_SERVER['REQUEST_URI']; + + $args = $_GET; + + if (isset($args['p'])) { + unset($args['p']); + } + + $query = http_build_query($args); + + if (strlen($query) > 0) { + $destination .= '?' . $query; + } $old = 'http'. (($_SERVER['HTTPS'] == 'on') ? 'S' : ''). -- cgit v1.2.3-54-g00ecf From 8c24a3bc92484d19ed4ba489d2d7b1172f4b355d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:55:01 -0700 Subject: a little better query handling in redirect code --- classes/Status_network.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index 03e8f4525..17b688740 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -95,18 +95,6 @@ class Status_network extends DB_DataObject $destination = 'http://'.$this->hostname; $destination .= $_SERVER['REQUEST_URI']; - $args = $_GET; - - if (isset($args['p'])) { - unset($args['p']); - } - - $query = http_build_query($args); - - if (strlen($query) > 0) { - $destination .= '?' . $query; - } - $old = 'http'. (($_SERVER['HTTPS'] == 'on') ? 'S' : ''). '://'. -- cgit v1.2.3-54-g00ecf From bd8f9a979acb1607e00499dfba223a51b57596af Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 02:33:10 +0000 Subject: Converts user entry in the form of '#1B2' into '#11BB22' for user design swatches --- js/farbtastic/farbtastic.go.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 4e0493b40..2f202ced1 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -59,7 +59,9 @@ $(document).ready(function() { swatches .each(SynchColors) .blur(function() { - $(this).val($(this).val().toUpperCase()); + tv = $(this).val(); + $(this).val(tv.toUpperCase()); + (tv.length == 4) ? ((tv[0] == '#') ? $(this).val('#'+tv[1]+tv[1]+tv[2]+tv[2]+tv[3]+tv[3]) : '') : ''; }) .focus(function() { $('#color-picker').show(); -- cgit v1.2.3-54-g00ecf From 20d93508776398627f5aff64b83bd20a362cb45d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 20:21:33 -0700 Subject: User design setting save now --- actions/designsettings.php | 256 ++++++++++++++++++++++++++++++++------------- lib/webcolor.php | 191 +++++++++++++++++++++++++++++++++ 2 files changed, 373 insertions(+), 74 deletions(-) create mode 100644 lib/webcolor.php diff --git a/actions/designsettings.php b/actions/designsettings.php index dba983fdf..0f7c27194 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -32,7 +32,8 @@ if (!defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/WebColor.php'; class DesignsettingsAction extends AccountSettingsAction { @@ -81,7 +82,7 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->element('label', array('for' => 'design_background-image_file'), + $this->element('label', array('for' => 'design_background-image_file'), _('Upload file')); $this->element('input', array('name' => 'design_background-image_file', 'type' => 'file', @@ -105,61 +106,79 @@ class DesignsettingsAction extends AccountSettingsAction $design = $this->defaultDesign(); } - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-0'), _('Background')); - $this->element('input', array('name' => 'design_background', - 'type' => 'text', - 'id' => 'swatch-0', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->backgroundcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Content')); - $this->element('input', array('name' => 'design_content', - 'type' => 'text', - 'id' => 'swatch-1', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->contentcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); - $this->element('input', array('name' => 'design_sidebar', - 'type' => 'text', - 'id' => 'swatch-2', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->sidebarcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Text')); - $this->element('input', array('name' => 'design_text', - 'type' => 'text', - 'id' => 'swatch-3', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->textcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Links')); - $this->element('input', array('name' => 'design_links', - 'type' => 'text', - 'id' => 'swatch-4', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->linkcolor)); - - $this->elementEnd('li'); + try { + + $bgcolor = new WebColor($design->backgroundcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-0'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-0', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $bgcolor->hexValue())); + $this->elementEnd('li'); + + + $ccolor = new WebColor($design->contentcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $ccolor->hexValue())); + $this->elementEnd('li'); + + $sbcolor = new WebColor($design->sidebarcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $sbcolor->hexValue())); + $this->elementEnd('li'); + + $tcolor = new WebColor($design->textcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $tcolor->hexValue())); + $this->elementEnd('li'); + + $lcolor = new WebColor($design->linkcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $lcolor->hexValue())); + + $this->elementEnd('li'); + + } catch (WebColorException $e) { + common_log(LOG_ERR, 'Bad color values in design ID: ' . + $design->id); + } $this->elementEnd('ul'); $this->elementEnd('fieldset'); @@ -169,7 +188,7 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => 'Reset', 'class' => 'submit form_action-primary', 'title' => _('Reset back to default'))); - + $this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design')); @@ -241,40 +260,129 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('script', array('type' => 'text/javascript', 'src' => $farbtasticGo)); } - + /** * Get a default user design * - * @return Design design + * @return Design design */ - + function defaultDesign() { $defaults = common_config('site', 'design'); $design = new Design(); - $design->backgroundcolor = $defaults['backgroundcolor']; - $design->contentcolor = $defaults['contentcolor']; - $design->sidebarcolor = $defaults['sidebarcolor']; - $design->textcolor = $defaults['textcolor']; - $design->linkcolor = $defaults['linkcolor']; - $design->backgroundimage = $defaults['backgroundimage']; + + try { + + $color = new WebColor(); + + $color->parseColor($defaults['backgroundcolor']); + $design->backgroundcolor = $color->intValue(); + + $color->parseColor($defaults['contentcolor']); + $design->contentcolor = $color->intValue(); + + $color->parseColor($defaults['sidebarcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['textcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['linkcolor']); + $design->linkcolor = $color->intValue(); + + $design->backgroundimage = $defaults['backgroundimage']; + + } catch (WebColorException $e) { + common_log(LOG_ERR, _('Bad default color settings: ' . + $e->getMessage())); + } return $design; } /** - * Save the user's design settings + * Save or update the user's design settings * * @return void */ - + function saveDesign() { $user = common_current_user(); - - - + + 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->showForm($e->getMessage()); + return; + } + + $design = User::getDesign(); + + if (!isset($design)) { + + $original = clone($design); + + $original->backgroundcolor = $bgcolor->intValue(); + $original->contentcolor = $ccolor->intValue(); + $original->sidebarcolor = $sbcolor->intValue(); + $original->textcolor = $tcolor->intValue(); + $original->linkcolor = $lcolor->intValue(); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + // update design + } else { + + $user->query('BEGIN'); + + // save new design + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $defaults['backgroundimage']; + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($user); + $user->design_id = $id; + $result = $user->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $user->query('ROLLBACK'); + return; + } + + $user->query('COMMIT'); + + } + $this->showForm(_('Design preferences saved.'), true); } @@ -282,9 +390,9 @@ class DesignsettingsAction extends AccountSettingsAction * Reset design settings to previous saved value if any, or * the defaults * - * @return void + * @return void */ - + function resetDesign() { $this->showForm(_('Design preferences reset.'), true); diff --git a/lib/webcolor.php b/lib/webcolor.php new file mode 100644 index 000000000..65713d26e --- /dev/null +++ b/lib/webcolor.php @@ -0,0 +1,191 @@ +. + * + * @category Personal + * @package Laconica + * @author Zach Copley + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +class WebColor { + + // XXX: Maybe make getters and setters for r,g,b values and tuples, + // e.g.: to support this kinda CSS representation: rgb(255,0,0) + // http://www.w3.org/TR/CSS21/syndata.html#color-units + + var $red = 0; + var $green = 0; + var $blue = 0; + + /** + * Constructor + * + * @return nothing + */ + + function __construct($color = null) + { + if (isset($color)) { + $this->parseColor($color); + } + } + + /** + * Parses input to and tries to determine whether the color + * is being specified via an integer or hex tuple and sets + * the RGB instance variables accordingly. + * + * XXX: Maybe support (r,g,b) style, and array? + * + * @param mixed $color + * + * @return nothing + */ + + function parseColor($color) { + + if (is_numeric($color)) { + $this->setIntColor($color); + } else { + + // XXX named colors + + // XXX: probably should do even more validation + + if (preg_match('/(#([0-9A-Fa-f]{3,6})\b)/u', $color) > 0) { + $this->setHexColor($color); + } else { + $errmsg = _('%s is not a valid color!'); + throw new WebColorException(sprintf($errmsg, $color)); + } + } + } + + /** + * @param string $name + * + * @return nothing + */ + + function setNamedColor($name) + { + // XXX Implement this + } + + + /** + * Sets the RGB color values from a a hex tuple + * + * @param string $hexcolor + * + * @return nothing + */ + + function setHexColor($hexcolor) { + + if ($hexcolor[0] == '#') { + $hexcolor = substr($hexcolor, 1); + } + + if (strlen($hexcolor) == 6) { + list($r, $g, $b) = array($hexcolor[0].$hexcolor[1], + $hexcolor[2].$hexcolor[3], + $hexcolor[4].$hexcolor[5]); + } elseif (strlen($hexcolor) == 3) { + list($r, $g, $b) = array($hexcolor[0].$hexcolor[0], + $hexcolor[1].$hexcolor[1], + $hexcolor[2].$hexcolor[2]); + } else { + return false; + } + + $this->red = hexdec($r); + $this->green = hexdec($g); + $this->blue = hexdec($b); + + } + + /** + * Sets the RGB color values from a 24-bit integer + * + * @param int $intcolor + * + * @return nothing + */ + + function setIntColor($intcolor) + { + // We could do 32 bit and have an alpha channel because + // Sarven wants one real bad, but nah. + + $this->red = $intcolor >> 16; + $this->green = $intcolor >> 8 & 0xFF; + $this->blue = $intcolor & 0xFF; + + } + + /** + * Returns a hex tuple of the RGB color useful for output in HTML + * + * @return string + */ + + function hexValue() { + + $hexcolor = (strlen(dechex($this->red)) < 2 ? '0' : '' ) . + dechex($this->red); + $hexcolor .= (strlen(dechex($this->green)) < 2 ? '0' : '') . + dechex($this->green); + $hexcolor .= (strlen(dechex($this->blue)) < 2 ? '0' : '') . + dechex($this->blue); + + return $hexcolor; + + } + + /** + * Returns a 24-bit packed integer representation of the RGB color + * for convenient storage in the DB + * + * XXX: probably could just use hexdec() instead + * + * @return int + */ + + function intValue() + { + $intcolor = 256 * 256 * $this->red + 256 * $this->green + $this->blue; + return $intcolor; + } + +} + +class WebColorException extends Exception +{ +} + +?> \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 94fec28610a62fcf6d33c6ec1f451dadb5ca9b18 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 20:29:30 -0700 Subject: User design setting save --- actions/designsettings.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 0f7c27194..dedf19db8 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -111,10 +111,10 @@ class DesignsettingsAction extends AccountSettingsAction $bgcolor = new WebColor($design->backgroundcolor); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-0'), _('Background')); + $this->element('label', array('for' => 'swatch-1'), _('Background')); $this->element('input', array('name' => 'design_background', 'type' => 'text', - 'id' => 'swatch-0', + 'id' => 'swatch-1', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -125,10 +125,10 @@ class DesignsettingsAction extends AccountSettingsAction $ccolor = new WebColor($design->contentcolor); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('label', array('for' => 'swatch-2'), _('Content')); $this->element('input', array('name' => 'design_content', 'type' => 'text', - 'id' => 'swatch-1', + 'id' => 'swatch-2', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -138,10 +138,10 @@ class DesignsettingsAction extends AccountSettingsAction $sbcolor = new WebColor($design->sidebarcolor); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); $this->element('input', array('name' => 'design_sidebar', 'type' => 'text', - 'id' => 'swatch-2', + 'id' => 'swatch-3', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -151,10 +151,10 @@ class DesignsettingsAction extends AccountSettingsAction $tcolor = new WebColor($design->textcolor); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('label', array('for' => 'swatch-4'), _('Text')); $this->element('input', array('name' => 'design_text', 'type' => 'text', - 'id' => 'swatch-3', + 'id' => 'swatch-4', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', @@ -164,10 +164,10 @@ class DesignsettingsAction extends AccountSettingsAction $lcolor = new WebColor($design->linkcolor); $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('label', array('for' => 'swatch-5'), _('Links')); $this->element('input', array('name' => 'design_links', 'type' => 'text', - 'id' => 'swatch-4', + 'id' => 'swatch-5', 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', -- cgit v1.2.3-54-g00ecf From 2c7f0534ca26b9c9461d920bb23765b282e6fdbc Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 04:03:08 +0000 Subject: Typo/lowercased WebColor to webcolor in required_once --- actions/designsettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index dedf19db8..b7f9cda98 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -33,7 +33,7 @@ if (!defined('LACONICA')) { } require_once INSTALLDIR . '/lib/accountsettingsaction.php'; -require_once INSTALLDIR . '/lib/WebColor.php'; +require_once INSTALLDIR . '/lib/webcolor.php'; class DesignsettingsAction extends AccountSettingsAction { -- cgit v1.2.3-54-g00ecf From e7e3709ae0294b8400b85d87f2ebeade5b31858d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 21:21:33 -0700 Subject: Throw an WebColorException if wrong # of hex chars --- lib/webcolor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/webcolor.php b/lib/webcolor.php index 65713d26e..aaf31d990 100644 --- a/lib/webcolor.php +++ b/lib/webcolor.php @@ -120,7 +120,8 @@ class WebColor { $hexcolor[1].$hexcolor[1], $hexcolor[2].$hexcolor[2]); } else { - return false; + $errmsg = _('%s is not a valid color! Use 3 or 6 hex chars.'); + throw new WebColorException(sprintf($errmsg, $hexcolor)); } $this->red = hexdec($r); -- cgit v1.2.3-54-g00ecf From 0a886868fb25ec1e2500ea2be0ea06c73cb0b2b2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 21:33:56 -0700 Subject: Add some basic memcached handling to status_network Status_network can't be a subclass of Memcached_DataObject -- the latter is too entrenched in Laconica's memc handling functions, which aren't loaded when Status_network is running! But the importance of caching these values can't be overstated. So, a considerably slimmed-down version of the Memcached_DataObject code is transcribed into Status_network. --- classes/Status_network.php | 88 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index 17b688740..d54364df5 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -1,9 +1,29 @@ . */ -class Status_network extends DB_DataObject +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Status_network extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -28,7 +48,10 @@ class Status_network extends DB_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - static function setupDB($dbhost, $dbuser, $dbpass, $dbname) + static $cache = null; + static $base = null; + + static function setupDB($dbhost, $dbuser, $dbpass, $dbname, $servers) { global $config; @@ -36,7 +59,60 @@ class Status_network extends DB_DataObject $config['db']['ini_'.$dbname] = INSTALLDIR.'/classes/statusnet.ini'; $config['db']['table_status_network'] = $dbname; - return true; + self::$cache = new Memcache(); + + if (is_array($servers)) { + foreach($servers as $server) { + self::$cache->addServer($server); + } + } else { + self::$cache->addServer($servers); + } + + self::$base = $dbname; + } + + static function cacheKey($k, $v) { + return 'laconica:' . self::$base . ':status_network:'.$k.':'.$v; + } + + static function memGet($k, $v) + { + $ck = self::cacheKey($k, $v); + + $sn = self::$cache->get($ck); + + if (empty($sn)) { + $sn = self::staticGet($k, $v); + if (!empty($sn)) { + self::$cache->set($ck, $sn); + } + } + + return $sn; + } + + function decache() + { + $keys = array('nickname', 'hostname', 'pathname'); + foreach ($keys as $k) { + $ck = self::cacheKey($k, $this->$k); + self::$cache->delete($ck); + } + } + + function update($orig=null) + { + if (is_object($orig)) { + $orig->decache(); # might be different keys + } + return parent::update($orig); + } + + function delete() + { + $this->decache(); # while we still have the values! + return parent::delete(); } static function setupSite($servername, $pathname, $wildcard) @@ -51,13 +127,13 @@ class Status_network extends DB_DataObject if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) { // special case for exact match if (0 == strcasecmp($servername, $wildcard)) { - $sn = Status_network::staticGet('nickname', ''); + $sn = self::memGet('nickname', ''); } else { $parts = explode('.', $servername); - $sn = Status_network::staticGet('nickname', strtolower($parts[0])); + $sn = self::memGet('nickname', strtolower($parts[0])); } } else { - $sn = Status_network::staticGet('hostname', strtolower($servername)); + $sn = self::memGet('hostname', strtolower($servername)); } if (!empty($sn)) { -- cgit v1.2.3-54-g00ecf From 39117bf88c7eca88824f702eabdac94e583af66b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 21:55:56 -0700 Subject: forgot to disinherit Memcached_DataObject in Status_network --- classes/Status_network.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/classes/Status_network.php b/classes/Status_network.php index d54364df5..f8d6756b6 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -21,9 +21,7 @@ if (!defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; - -class Status_network extends Memcached_DataObject +class Status_network extends DB_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ -- cgit v1.2.3-54-g00ecf From ef99f83963ba598b1e52224ce80a7d8a8e84a96f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:13:35 -0700 Subject: Output custom stylesheets on design sub-Actions --- classes/Design.php | 2 +- lib/currentuserdesignaction.php | 16 ++++++++++++++++ lib/ownerdesignaction.php | 13 +++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/classes/Design.php b/classes/Design.php index bb1e917e3..4f6b2a844 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -47,7 +47,7 @@ class Design extends Memcached_DataObject function showCSS($out) { - $out->element('stylesheet', array('type' => 'text/css'), + $out->element('style', array('type' => 'text/css'), 'body { background-color: #' . dechex($this->backgroundcolor) . '} '."\n". '#content { background-color #' . dechex($this->contentcolor) . '} '."\n". '#aside_primary { background-color #'. dechex($this->sidebarcolor) .'} '."\n". diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 297525655..40502bc77 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -47,6 +47,20 @@ if (!defined('LACONICA')) { class CurrentUserDesignAction extends Action { + + /** + * Show the user's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + $design->showCSS($this); + } + /** * A design for this action * @@ -66,4 +80,6 @@ class CurrentUserDesignAction extends Action return $cur->getDesign(); } + + } diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index c47633bdb..b6b30a606 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -52,6 +52,19 @@ class OwnerDesignAction extends Action { var $user = null; + /** + * Show the owner's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + $design->showCSS($this); + } + /** * A design for this action * -- cgit v1.2.3-54-g00ecf From 4652f316cf9cb94fb5f0ae8003d7bb9e2bdcdaee Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:27:59 -0700 Subject: Design class now uses WebColor class for outputting hex colors --- classes/Design.php | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/classes/Design.php b/classes/Design.php index 4f6b2a844..9bfdcd1c3 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -17,13 +17,16 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} /** * Table Definition for design */ -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; +require_once INSTALLDIR . '/lib/webcolor.php'; class Design extends Memcached_DataObject { @@ -47,11 +50,25 @@ class Design extends Memcached_DataObject function showCSS($out) { + try { + + $bgcolor = new WebColor($this->backgroundcolor); + $ccolor = new WebColor($this->contentcolor); + $sbcolor = new WebColor($this->sidebarcolor); + $tcolor = new WebColor($this->textcolor); + $lcolor = new WebColor($this->linkcolor); + + } catch (WebColorException $e) { + // This shouldn't happen + common_log(LOG_ERR, "Unable to create color for design $id.", + __FILE__); + } + $out->element('style', array('type' => 'text/css'), - 'body { background-color: #' . dechex($this->backgroundcolor) . '} '."\n". - '#content { background-color #' . dechex($this->contentcolor) . '} '."\n". - '#aside_primary { background-color #'. dechex($this->sidebarcolor) .'} '."\n". - 'html body { color: #'. dechex($this->textcolor) .'} '."\n". - 'a { color: #' . dechex($this->linkcolor) . '} '."\n"); + 'body { background-color: #' . $bgcolor->hexValue() . '} '."\n". + '#content { background-color #' . $ccolor->hexValue() . '} '."\n". + '#aside_primary { background-color #'. $sbcolor->hexValue() .'} '."\n". + 'html body { color: #'. $tcolor->hexValue() .'} '."\n". + 'a { color: #' . $lcolor->hexValue() . '} '."\n"); } } -- cgit v1.2.3-54-g00ecf From f3199c1369bb017d5e1548343a0fd56bededb69b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:39:53 -0700 Subject: Some fixups to the CSS output of showCSS() --- classes/Design.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/classes/Design.php b/classes/Design.php index 9bfdcd1c3..f4128ee39 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -65,9 +65,9 @@ class Design extends Memcached_DataObject } $out->element('style', array('type' => 'text/css'), - 'body { background-color: #' . $bgcolor->hexValue() . '} '."\n". - '#content { background-color #' . $ccolor->hexValue() . '} '."\n". - '#aside_primary { background-color #'. $sbcolor->hexValue() .'} '."\n". + 'html, body { background-color: #' . $bgcolor->hexValue() . '} '."\n". + '#content { background-color: #' . $ccolor->hexValue() . '} '."\n". + '#aside_primary { background-color: #'. $sbcolor->hexValue() .'} '."\n". 'html body { color: #'. $tcolor->hexValue() .'} '."\n". 'a { color: #' . $lcolor->hexValue() . '} '."\n"); } -- cgit v1.2.3-54-g00ecf From 37cafad2e071bbfe8a733bba22fb68bbf5220051 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:43:06 -0700 Subject: Another minor tweak to showCSS() CSS output --- classes/Design.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classes/Design.php b/classes/Design.php index f4128ee39..8bb527761 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -66,7 +66,8 @@ class Design extends Memcached_DataObject $out->element('style', array('type' => 'text/css'), 'html, body { background-color: #' . $bgcolor->hexValue() . '} '."\n". - '#content { background-color: #' . $ccolor->hexValue() . '} '."\n". + '#content, #site_nav_local_views .current a { background-color: #' . + $ccolor->hexValue() . '} '."\n". '#aside_primary { background-color: #'. $sbcolor->hexValue() .'} '."\n". 'html body { color: #'. $tcolor->hexValue() .'} '."\n". 'a { color: #' . $lcolor->hexValue() . '} '."\n"); -- cgit v1.2.3-54-g00ecf From c3c30aa0eafd42cf6544cb32614ffe164bfd9ca2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 23:18:54 -0700 Subject: Check to make sure a design exists before trying to display it --- lib/currentuserdesignaction.php | 5 ++++- lib/ownerdesignaction.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 40502bc77..7c2520cf6 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -58,7 +58,10 @@ class CurrentUserDesignAction extends Action parent::showStylesheets(); $design = $this->getDesign(); - $design->showCSS($this); + + if (!empty($design)) { + $design->showCSS($this); + } } /** diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index b6b30a606..424474f42 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -62,7 +62,10 @@ class OwnerDesignAction extends Action { parent::showStylesheets(); $design = $this->getDesign(); - $design->showCSS($this); + + if (!empty($design)) { + $design->showCSS($this); + } } /** -- cgit v1.2.3-54-g00ecf From 93205cac099e143b7e5dd22a17f6eda6a82d49cf Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 06:24:29 +0000 Subject: Connects html, body and content, navigation background colors --- js/farbtastic/farbtastic.go.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 2f202ced1..9bf740825 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -11,10 +11,10 @@ $(document).ready(function() { C = $(S).val(); switch (parseInt(S.id.slice(-1))) { case 1: default: - $('body').css({'background-color':C}); + $('html, body').css({'background-color':C}); break; case 2: - $('#content').css({'background-color':C}); + $('#content, #site_nav_local_views .current a').css({'background-color':C}); break; case 3: $('#aside_primary').css({'background-color':C}); -- cgit v1.2.3-54-g00ecf From 5daa0e358f0a75261e3240820cd6bcf7a57504fc Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 06:32:17 +0000 Subject: Using neutral colour for notice hover --- theme/default/css/display.css | 4 ++-- theme/identica/css/display.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 166e62157..06cf9fb26 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -228,8 +228,8 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li.hover { -background-color:#fcfcfc; +.notices li:hover { +background-color:rgba(194, 194, 194, 0.025); } .notices .notices { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index cab42f16f..0332a6f1e 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -228,8 +228,8 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li.hover { -background-color:#fcfcfc; +.notices li:hover { +background-color:rgba(194, 194, 194, 0.025); } .notices .notices { -- cgit v1.2.3-54-g00ecf From c98179378be7c8903a6ba7a9fe37bf6683219555 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 07:45:19 +0000 Subject: Revert "Using neutral colour for notice hover" This reverts commit 5daa0e358f0a75261e3240820cd6bcf7a57504fc. --- theme/default/css/display.css | 4 ++-- theme/identica/css/display.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 06cf9fb26..166e62157 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -228,8 +228,8 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li:hover { -background-color:rgba(194, 194, 194, 0.025); +.notices li.hover { +background-color:#fcfcfc; } .notices .notices { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 0332a6f1e..cab42f16f 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -228,8 +228,8 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li:hover { -background-color:rgba(194, 194, 194, 0.025); +.notices li.hover { +background-color:#fcfcfc; } .notices .notices { -- cgit v1.2.3-54-g00ecf From 6d5d0b3472038b0a2cbe86c7df5f062853164dec Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 00:56:32 -0700 Subject: Update wasn't ever getting called --- actions/designsettings.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index b7f9cda98..c5aa8c1d3 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -325,17 +325,17 @@ class DesignsettingsAction extends AccountSettingsAction return; } - $design = User::getDesign(); + $design = $user->getDesign(); - if (!isset($design)) { + if (!empty($design)) { $original = clone($design); - $original->backgroundcolor = $bgcolor->intValue(); - $original->contentcolor = $ccolor->intValue(); - $original->sidebarcolor = $sbcolor->intValue(); - $original->textcolor = $tcolor->intValue(); - $original->linkcolor = $lcolor->intValue(); + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); $result = $design->update($original); -- cgit v1.2.3-54-g00ecf From c74a079e47e1ad71bdb92f8659626730b1b0cae3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 19:40:23 +0000 Subject: UI updates: Added box-shadow to local views, input focus, content Removed borders from local views, content, aside_primary Some cleaning --- theme/base/css/display.css | 11 +---------- theme/default/css/display.css | 44 ++++++++++++++++++++++++++++-------------- theme/identica/css/display.css | 44 ++++++++++++++++++++++++++++-------------- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 0cbd0d774..3595d6aa3 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -303,10 +303,6 @@ padding:4px 11px; -moz-border-radius-topright:4px; -webkit-border-top-left-radius:4px; -webkit-border-top-right-radius:4px; -border-width:1px; -border-style:solid; -border-bottom:0; -text-shadow: 2px 2px 2px #ddd; font-weight:bold; } #site_nav_local_views .nav { @@ -396,8 +392,6 @@ border-radius:7px; -moz-border-radius-topleft:0; -webkit-border-radius:7px; -webkit-border-top-left-radius:0; -border-style:solid; -border-width:1px; } #shownotice #content { min-height:0; @@ -413,13 +407,11 @@ float:left; width:27.917%; min-height:259px; float:left; -margin-left:0.385%; +margin-left:0.7%; padding:1.795%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; -border-width:1px; -border-style:solid; } #form_notice { @@ -469,7 +461,6 @@ height:16px; #form_notice #notice_data-attach { left:183px; padding:0; - height:16px; } #form_notice .form_note { diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 166e62157..148ce6e60 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -19,7 +19,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:7.18%; +margin-right:7.1%; } input, textarea, select, option { @@ -27,7 +27,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; } input, textarea, select, .entity_remote_subscribe { -border-color:#aaa; +border-color:#AAAAAA; } #filter_tags ul li { border-color:#C3D6DF; @@ -47,10 +47,13 @@ background-color:#A9BF4F; input:focus, textarea:focus, select:focus, #form_notice.warning #notice_data-text { border-color:#A9BF4F; +box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); } input.submit, .entity_remote_subscribe { -color:#fff; +color:#FFFFFF; } a, @@ -79,10 +82,10 @@ background-color:#CEE1E9; } #notice_text-count { -color:#333; +color:#333333; } #form_notice.warning #notice_text-count { -color:#000; +color:#000000; } #form_notice label[for=notice_data-attach] { background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; @@ -92,27 +95,38 @@ opacity:0; } #form_notice.processing #notice_action-submit { -background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } +#content { +box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +-moz-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +-webkit-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +} #content, #site_nav_local_views a, #aside_primary { -border-color:#fff; +border-color:#FFFFFF; } #content, #site_nav_local_views .current a { -background-color:#fff; +background-color:#FFFFFF; } #site_nav_local_views a { -background-color:rgba(255, 255, 255, 0.2); +background-color:rgba(194, 194, 194, 0.4); +box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); +-moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); +-webkit-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); } #site_nav_local_views a:hover { 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; +} .error { background-color:#F7E8E8; @@ -123,8 +137,8 @@ background-color:#EFF3DC; #anon_notice { background-color:#C3D6DF; -color:#fff; -border-color:#fff; +color:#FFFFFF; +border-color:#FFFFFF; } #showstream #anon_notice { @@ -162,7 +176,7 @@ background-color:transparent; .form_user_subscribe input.submit, .form_user_unsubscribe input.submit { background-color:#A9BF4F; -color:#fff; +color:#FFFFFF; } .form_user_unsubscribe input.submit, .form_group_leave input.submit, @@ -214,7 +228,7 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r .notices div.entry-content, .notices div.notice-options, .notices li.hover .notices div.entry-content, -.notices li.hover .notices div.notice-options { +.notices li.hover .notices div.notice-options { opacity:0.4; } .notices li.hover div.entry-content, @@ -222,14 +236,14 @@ opacity:0.4; opacity:1; } div.entry-content { -color:#333; +color:#333333; } div.notice-options a, div.notice-options input { font-family:sans-serif; } .notices li.hover { -background-color:#fcfcfc; +background-color:#FCFCFC; } .notices .notices { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index cab42f16f..ff538f1f1 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -19,7 +19,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:7.18%; +margin-right:7.1%; } input, textarea, select, option { @@ -27,10 +27,10 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; } input, textarea, select, .entity_remote_subscribe { -border-color:#aaa; +border-color:#AAAAAA; } #filter_tags ul li { -border-color:#ddd; +border-color:#DDDDDD; } .form_settings input.form_action-primary { @@ -47,10 +47,13 @@ background-color:#9BB43E; input:focus, textarea:focus, select:focus, #form_notice.warning #notice_data-text { border-color:#9BB43E; +box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); } input.submit, .entity_remote_subscribe { -color:#fff; +color:#FFFFFF; } a, @@ -79,10 +82,10 @@ background-color:#CEE1E9; } #notice_text-count { -color:#333; +color:#333333; } #form_notice.warning #notice_text-count { -color:#000; +color:#000000; } #form_notice label[for=notice_data-attach] { background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; @@ -92,27 +95,38 @@ opacity:0; } #form_notice.processing #notice_action-submit { -background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } +#content { +box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +-moz-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +-webkit-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); +} #content, #site_nav_local_views a, #aside_primary { -border-color:#fff; +border-color:#FFFFFF; } #content, #site_nav_local_views .current a { -background-color:#fff; +background-color:#FFFFFF; } #site_nav_local_views a { -background-color:rgba(135, 180, 200, 0.3); +background-color:rgba(194, 194, 194, 0.4); +box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); +-moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); +-webkit-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); } #site_nav_local_views a:hover { 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; +} .error { background-color:#F7E8E8; @@ -123,8 +137,8 @@ background-color:#EFF3DC; #anon_notice { background-color:#87B4C8; -color:#fff; -border-color:#fff; +color:#FFFFFF; +border-color:#FFFFFF; } #showstream #anon_notice { @@ -162,7 +176,7 @@ background-color:transparent; .form_user_subscribe input.submit, .form_user_unsubscribe input.submit { background-color:#9BB43E; -color:#fff; +color:#FFFFFF; } .form_user_unsubscribe input.submit, .form_group_leave input.submit, @@ -222,14 +236,14 @@ opacity:0.4; opacity:1; } div.entry-content { -color:#333; +color:#333333; } div.notice-options a, div.notice-options input { font-family:sans-serif; } .notices li.hover { -background-color:#fcfcfc; +background-color:#FCFCFC; } .notices .notices { -- cgit v1.2.3-54-g00ecf From c8e3e0d7166abc5acce78d8d6c984764e4c2f7bc Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 20:56:12 +0000 Subject: More contrast for tabs --- theme/default/css/display.css | 2 +- theme/identica/css/display.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 148ce6e60..12efedf01 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -116,7 +116,7 @@ background-color:#FFFFFF; } #site_nav_local_views a { -background-color:rgba(194, 194, 194, 0.4); +background-color:rgba(194, 194, 194, 0.5); box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); -moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); -webkit-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index ff538f1f1..fb64013be 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -116,7 +116,7 @@ background-color:#FFFFFF; } #site_nav_local_views a { -background-color:rgba(194, 194, 194, 0.4); +background-color:rgba(194, 194, 194, 0.5); box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); -moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); -webkit-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5); -- cgit v1.2.3-54-g00ecf From fcc86840369c45b0146cc1f3fcd3686e880dea6e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 21:10:14 +0000 Subject: Minor margin value change --- theme/default/css/display.css | 2 +- theme/identica/css/display.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 12efedf01..1ad823a5c 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -19,7 +19,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:7.1%; +margin-right:7.2%; } input, textarea, select, option { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index fb64013be..bc7ac80fb 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -19,7 +19,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:7.1%; +margin-right:7.2%; } input, textarea, select, option { -- cgit v1.2.3-54-g00ecf From 3974ab633c1f75fee71a3a74f7088ca2927468c9 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 16 Jun 2009 21:47:58 +0000 Subject: Brought back borders for content, navigation, aside_primary but applied transparent colour instead, hence not visible. This way, other laconica instances make use of the border if they change only the colour. --- theme/base/css/display.css | 9 ++++++++- theme/default/css/display.css | 2 +- theme/identica/css/display.css | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 3595d6aa3..49907058e 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -303,6 +303,9 @@ padding:4px 11px; -moz-border-radius-topright:4px; -webkit-border-top-left-radius:4px; -webkit-border-top-right-radius:4px; +border-width:1px; +border-style:solid; +border-bottom:0; font-weight:bold; } #site_nav_local_views .nav { @@ -392,6 +395,8 @@ border-radius:7px; -moz-border-radius-topleft:0; -webkit-border-radius:7px; -webkit-border-top-left-radius:0; +border-width:1px; +border-style:solid; } #shownotice #content { min-height:0; @@ -407,11 +412,13 @@ float:left; width:27.917%; min-height:259px; float:left; -margin-left:0.7%; +margin-left:0.5%; padding:1.795%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; +border-width:1px; +border-style:solid; } #form_notice { diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 1ad823a5c..f0d6dace8 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -108,7 +108,7 @@ box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); #content, #site_nav_local_views a, #aside_primary { -border-color:#FFFFFF; +border-color:transparent; } #content, #site_nav_local_views .current a { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index bc7ac80fb..25a01abe0 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -108,7 +108,7 @@ box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3); #content, #site_nav_local_views a, #aside_primary { -border-color:#FFFFFF; +border-color:transparent; } #content, #site_nav_local_views .current a { -- cgit v1.2.3-54-g00ecf From 54697e52989c8d7dc9e1295679e6c0ef676642e0 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 16 Jun 2009 19:38:27 -0400 Subject: Removed more dead code. --- actions/attachment.php | 42 ------------------------------------------ actions/attachment_ajax.php | 41 ----------------------------------------- 2 files changed, 83 deletions(-) diff --git a/actions/attachment.php b/actions/attachment.php index 16ee723d9..e4dc0e054 100644 --- a/actions/attachment.php +++ b/actions/attachment.php @@ -98,48 +98,6 @@ class AttachmentAction extends Action return $a->title(); } - /** - * Last-modified date for page - * - * When was the content of this page last modified? Based on notice, - * profile, avatar. - * - * @return int last-modified date as unix timestamp - */ -/* - function lastModified() - { - return max(strtotime($this->notice->created), - strtotime($this->profile->modified), - ($this->avatar) ? strtotime($this->avatar->modified) : 0); - } -*/ - - /** - * An entity tag for this page - * - * Shows the ETag for the page, based on the notice ID and timestamps - * for the notice, profile, and avatar. It's weak, since we change - * the date text "one hour ago", etc. - * - * @return string etag - */ -/* - function etag() - { - $avtime = ($this->avatar) ? - strtotime($this->avatar->modified) : 0; - - return 'W/"' . implode(':', array($this->arg('action'), - common_language(), - $this->notice->id, - strtotime($this->notice->created), - strtotime($this->profile->modified), - $avtime)) . '"'; - } -*/ - - /** * Handle input * diff --git a/actions/attachment_ajax.php b/actions/attachment_ajax.php index 3d83393c5..5d6773010 100644 --- a/actions/attachment_ajax.php +++ b/actions/attachment_ajax.php @@ -74,46 +74,5 @@ class Attachment_ajaxAction extends AttachmentAction } $this->elementEnd('div'); } - - /** - * Last-modified date for page - * - * When was the content of this page last modified? Based on notice, - * profile, avatar. - * - * @return int last-modified date as unix timestamp - */ -/* - function lastModified() - { - return max(strtotime($this->notice->created), - strtotime($this->profile->modified), - ($this->avatar) ? strtotime($this->avatar->modified) : 0); - } -*/ - - /** - * An entity tag for this page - * - * Shows the ETag for the page, based on the notice ID and timestamps - * for the notice, profile, and avatar. It's weak, since we change - * the date text "one hour ago", etc. - * - * @return string etag - */ -/* - function etag() - { - $avtime = ($this->avatar) ? - strtotime($this->avatar->modified) : 0; - - return 'W/"' . implode(':', array($this->arg('action'), - common_language(), - $this->notice->id, - strtotime($this->notice->created), - strtotime($this->profile->modified), - $avtime)) . '"'; - } -*/ } -- cgit v1.2.3-54-g00ecf From bc1f877f6e84929b7f2722f57858cfad8508fea5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 19:17:37 -0700 Subject: Design settings now save and displays backgrounds --- actions/designsettings.php | 69 +++++++++++++++++++++++++++++++++++++++++----- classes/Design.php | 63 +++++++++++++++++++++++++++++++++++++----- lib/common.php | 4 +++ 3 files changed, 122 insertions(+), 14 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index c5aa8c1d3..aa6915b98 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -56,7 +56,8 @@ class DesignsettingsAction extends AccountSettingsAction function getInstructions() { - return _('Customize the way your profile looks with a background image and a colour palette of your choice.'); + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); } /** @@ -71,14 +72,16 @@ class DesignsettingsAction extends AccountSettingsAction { $user = common_current_user(); $this->elementStart('form', array('method' => 'post', + 'enctype' => 'multipart/form-data', 'id' => 'form_settings_design', 'class' => 'form_settings', 'action' => - common_local_url('designsettings'))); + common_local_url('designsettings'))); $this->elementStart('fieldset'); $this->hidden('token', common_session_token()); - $this->elementStart('fieldset', array('id' => 'settings_design_background-image')); + $this->elementStart('fieldset', array('id' => + 'settings_design_background-image')); $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); @@ -87,7 +90,8 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('input', array('name' => 'design_background-image_file', 'type' => 'file', 'id' => 'design_background-image_file')); - $this->element('p', 'form_guide', _('You can upload your personal background image. The maximum file size is 2Mb.')); + $this->element('p', 'form_guide', _('You can upload your personal ' . + 'background image. The maximum file size is 2Mb.')); $this->element('input', array('name' => 'MAX_FILE_SIZE', 'type' => 'hidden', 'id' => 'MAX_FILE_SIZE', @@ -207,6 +211,20 @@ class DesignsettingsAction extends AccountSettingsAction function handlePost() { + // XXX: Robin's workaround for a bug in PHP where $_POST + // and $_FILE are empty in the case that the uploaded + // file is bigger than PHP is configured to handle. + + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { + + $msg = _('The server was unable to handle that much POST ' . + 'data (%s bytes) due to its current configuration.'); + + $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); + } + } + // CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { @@ -310,8 +328,6 @@ class DesignsettingsAction extends AccountSettingsAction function saveDesign() { - $user = common_current_user(); - try { $bgcolor = new WebColor($this->trimmed('design_background')); @@ -325,6 +341,7 @@ class DesignsettingsAction extends AccountSettingsAction return; } + $user = common_current_user(); $design = $user->getDesign(); if (!empty($design)) { @@ -336,6 +353,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; $result = $design->update($original); @@ -358,7 +376,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $defaults['backgroundimage']; + $design->backgroundimage = $filepath; $id = $design->insert(); @@ -383,6 +401,43 @@ class DesignsettingsAction extends AccountSettingsAction } + // Now that we have a Design ID we can add a file to the design. + // XXX: This is an additional DB hit, but figured having the image + // associated with the Design rather than the User was worth + // it. -- Zach + + if ($_FILES['design_background-image_file']['error'] == + UPLOAD_ERR_OK) { + + $filepath = null; + + try { + $imagefile = + ImageFile::fromUpload('design_background-image_file'); + } catch (Exception $e) { + $this->showForm($e->getMessage()); + return; + } + + $filename = Design::filename($design->id, + image_type_to_extension($imagefile->type), + common_timestamp()); + + $filepath = Design::path($filename); + + move_uploaded_file($imagefile->filepath, $filepath); + + $original = clone($design); + $design->backgroundimage = $filename; + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + } + $this->showForm(_('Design preferences saved.'), true); } diff --git a/classes/Design.php b/classes/Design.php index 8bb527761..f5c87b489 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -64,12 +64,61 @@ class Design extends Memcached_DataObject __FILE__); } - $out->element('style', array('type' => 'text/css'), - 'html, body { background-color: #' . $bgcolor->hexValue() . '} '."\n". - '#content, #site_nav_local_views .current a { background-color: #' . - $ccolor->hexValue() . '} '."\n". - '#aside_primary { background-color: #'. $sbcolor->hexValue() .'} '."\n". - 'html body { color: #'. $tcolor->hexValue() .'} '."\n". - 'a { color: #' . $lcolor->hexValue() . '} '."\n"); + $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; + $css .= '#content, #site_nav_local_views .current a { background-color: #'; + $css .= $ccolor->hexValue() . '} '."\n"; + $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; + $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; + $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; + + if (!empty($this->backgroundimage)) { + + $css .= 'body { background-image:url(' . + Design::url($this->backgroundimage) . + '); background-repeat:no-repeat; }' . "\n"; + } + + $out->element('style', array('type' => 'text/css'), $css); + + } + + static function filename($id, $extension, $extra=null) + { + return $id . (($extra) ? ('-' . $extra) : '') . $extension; + } + + static function path($filename) + { + $dir = common_config('background', 'dir'); + + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } + + return $dir . $filename; } + + static function url($filename) + { + $path = common_config('background', 'path'); + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('background', 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + // XXX: protocol + + return 'http://'.$server.$path.$filename; + } + } diff --git a/lib/common.php b/lib/common.php index 1381d8047..0e710625c 100644 --- a/lib/common.php +++ b/lib/common.php @@ -119,6 +119,10 @@ $config = array('server' => null, 'dir' => INSTALLDIR . '/avatar/', 'path' => $_path . '/avatar/'), + 'background' => + array('server' => null, + 'dir' => INSTALLDIR . '/background/', + 'path' => $_path . '/background/'), 'public' => array('localonly' => true, 'blacklist' => array(), -- cgit v1.2.3-54-g00ecf From 90344e55d46f07e69ff0800552d28ea90b11764a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 19:23:06 -0700 Subject: Add background dir --- .gitignore | 1 + background/.gitignore | 0 2 files changed, 1 insertion(+) create mode 100644 background/.gitignore diff --git a/.gitignore b/.gitignore index 3418d8ee5..8a7f5c65c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ avatar/* +background/* files/* file/* _darcs/* diff --git a/background/.gitignore b/background/.gitignore new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.3-54-g00ecf From befbfc9c73a75bac9d7dac4a4b7a21bd515ce1b4 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 16 Jun 2009 23:10:17 -0400 Subject: Moved url handling to its proper place, from newnotice to Notice.php --- actions/newnotice.php | 19 ------------------- classes/Notice.php | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 02976a2ae..72ccd8c32 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -231,7 +231,6 @@ class NewnoticeAction extends Action if (isset($mimetype)) { $this->storeFile($notice, $mimetype); } - $this->saveUrls($notice); common_broadcast_notice($notice); if ($this->boolean('ajax')) { @@ -284,24 +283,6 @@ class NewnoticeAction extends Action } } - /** save all urls in the notice to the db - * - * follow redirects and save all available file information - * (mimetype, date, size, oembed, etc.) - * - * @param class $notice Notice to pull URLs from - * - * @return void - */ - function saveUrls($notice, $uploaded = null) { - common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id); - } - - function saveUrl($data) { - list($url, $notice_id) = $data; - $zzz = File::processNew($url, $notice_id); - } - /** * Show an Ajax-y error message * diff --git a/classes/Notice.php b/classes/Notice.php index 68602b1f7..770b5d78b 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -217,6 +217,7 @@ class Notice extends Memcached_DataObject $notice->addToInboxes(); $notice->saveGroups(); + $notice->saveUrls(); $notice->query('COMMIT'); @@ -231,6 +232,24 @@ class Notice extends Memcached_DataObject return $notice; } + /** save all urls in the notice to the db + * + * follow redirects and save all available file information + * (mimetype, date, size, oembed, etc.) + * + * @param class $notice Notice to pull URLs from + * + * @return void + */ + function saveUrls() { + common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id); + } + + function saveUrl($data) { + list($url, $notice_id) = $data; + File::processNew($url, $notice_id); + } + static function checkDupes($profile_id, $content) { $profile = Profile::staticGet($profile_id); if (!$profile) { -- cgit v1.2.3-54-g00ecf From 7845fe3100375f0dc7c2515cfa935187efa1c0c8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 16 Jun 2009 21:00:53 -0700 Subject: typos in README; dependencies --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 57ff72f66..3279f7bba 100644 --- a/README +++ b/README @@ -178,8 +178,8 @@ and the URLs are listed here for your convenience. - Facebook library. Used for the Facebook application. - PEAR Services_oEmbed. Used for some multimedia integration. - PEAR HTTP_Request is an oEmbed dependency. -- PEAR Validat is an oEmbed dependency.e -- PEAR Net_URL is an oEmbed dependency.2 +- PEAR Validate is an oEmbed dependency. +- PEAR Net_URL2 is an oEmbed dependency. A design goal of Laconica is that the basic Web functionality should work on even the most restrictive commercial hosting services. -- cgit v1.2.3-54-g00ecf From bea2fa15060e03d818db043122bf9529d2b77662 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 04:09:30 +0000 Subject: Added form option to tile background image and to turn it on and off --- actions/designsettings.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/actions/designsettings.php b/actions/designsettings.php index aa6915b98..e97d01ceb 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -97,6 +97,34 @@ class DesignsettingsAction extends AccountSettingsAction 'id' => 'MAX_FILE_SIZE', 'value' => ImageFile::maxFileSizeInt())); $this->elementEnd('li'); + + $this->elementStart('li', array('id' => 'design_background-image_onoff')); + $this->element('input', array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_on', + 'class' => 'radio', + 'value' => 'true', + 'checked'=> 'checked')); + $this->element('label', array('for' => 'design_background-image_on', + 'class' => 'radio'), + _('On')); + $this->element('input', array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_off', + 'class' => 'radio', + 'value' => 'false')); + $this->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), + _('Off')); + $this->element('p', 'form_guide', _('Turn background image on or off.')); + $this->elementEnd('li'); + + $this->elementStart('li'); + $this->checkbox('design_background-image_repeat', + _('Tile background image'), + false, null, true, false); + $this->elementEnd('li'); + $this->elementEnd('ul'); $this->elementEnd('fieldset'); -- cgit v1.2.3-54-g00ecf From a592ee6b99596d16da513c0ce8174aae3f3063cd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 04:33:01 +0000 Subject: Init styles for tile and image use on/off for user design settings --- theme/base/css/display.css | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 0cbd0d774..5b69b4f3d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -77,7 +77,8 @@ margin:0 0 18px 0; form label { font-weight:bold; } -input.checkbox { +input.checkbox, +input.radio { position:relative; top:2px; left:0; @@ -168,7 +169,8 @@ margin-bottom:0; margin-bottom:11px; } -.form_settings input.checkbox { +.form_settings input.checkbox, +.form_settings input.radio { margin-top:3px; margin-left:0; } @@ -180,13 +182,19 @@ margin-left:11px; float:left; width:90%; } - +.form_settings label.radio { +margin-top:0; +margin-right:47px; +margin-left:11px; +width:auto; +} #form_login p.form_guide, #form_register #settings_rememberme p.form_guide, #form_openid_login #settings_rememberme p.form_guide, #settings_twitter_remove p.form_guide, -#form_search ul.form_data #q { +#form_search ul.form_data #q, +#design_background-image_onoff p.form_guide { margin-left:0; } -- cgit v1.2.3-54-g00ecf From 7b7f11942885666bfe1f03dd6f34e36a82a08484 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 21:36:15 -0700 Subject: Added background image tile flag to Design --- classes/Design.php | 19 ++++++++++--------- classes/laconica.ini | 1 + db/laconica.sql | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/classes/Design.php b/classes/Design.php index f5c87b489..acc94d196 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -41,6 +41,7 @@ class Design extends Memcached_DataObject public $textcolor; // int(4) public $linkcolor; // int(4) public $backgroundimage; // varchar(255) + public $tile; // tinyint(1) /* Static get */ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } @@ -63,23 +64,23 @@ class Design extends Memcached_DataObject common_log(LOG_ERR, "Unable to create color for design $id.", __FILE__); } - + $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; $css .= '#content, #site_nav_local_views .current a { background-color: #'; $css .= $ccolor->hexValue() . '} '."\n"; $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; - + if (!empty($this->backgroundimage)) { - - $css .= 'body { background-image:url(' . - Design::url($this->backgroundimage) . + + $css .= 'body { background-image:url(' . + Design::url($this->backgroundimage) . '); background-repeat:no-repeat; }' . "\n"; } - + $out->element('style', array('type' => 'text/css'), $css); - + } static function filename($id, $extension, $extra=null) @@ -97,7 +98,7 @@ class Design extends Memcached_DataObject return $dir . $filename; } - + static function url($filename) { $path = common_config('background', 'path'); @@ -120,5 +121,5 @@ class Design extends Memcached_DataObject return 'http://'.$server.$path.$filename; } - + } diff --git a/classes/laconica.ini b/classes/laconica.ini index c04ae758f..569681984 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -46,6 +46,7 @@ sidebarcolor = 1 textcolor = 1 linkcolor = 1 backgroundimage = 2 +tile = 17 [design__keys] id = N diff --git a/db/laconica.sql b/db/laconica.sql index bd95d1ade..1f302de16 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -495,7 +495,8 @@ create table design ( sidebarcolor integer comment 'sidebar background color', textcolor integer comment 'text color', linkcolor integer comment 'link color', - backgroundimage varchar(255) comment 'background image, if any' + backgroundimage varchar(255) comment 'background image, if any', + tile tinyint default 0 comment 'tile background image' ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table group_block ( -- cgit v1.2.3-54-g00ecf From 90b2b3f9d19196a6961fb7a115b48b2cbdf966ce Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 16 Jun 2009 21:37:04 -0700 Subject: names for Notice is_local states --- classes/Notice.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index 68602b1f7..333832d0b 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -29,6 +29,11 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; define('NOTICE_CACHE_WINDOW', 61); +define('NOTICE_LOCAL_PUBLIC', 1); +define('NOTICE_REMOTE_OMB', 0); +define('NOTICE_LOCAL_NONPUBLIC', -1); +define('NOTICE_GATEWAY', -2); + class Notice extends Memcached_DataObject { ###START_AUTOCODE @@ -793,7 +798,7 @@ class Notice extends Memcached_DataObject $inbox = new Notice_inbox(); $UT = common_config('db','type')=='pgsql'?'"user"':'user'; $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' . - "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " . + "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', " . NOTICE_INBOX_SOURCE_GROUP . " " . "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " . 'WHERE group_member.group_id = ' . $group->id . ' ' . 'AND NOT EXISTS (SELECT user_id, notice_id ' . -- cgit v1.2.3-54-g00ecf From 312fd855324b680c45b71c683b9589f24e1b31a9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 16 Jun 2009 21:37:19 -0700 Subject: names for Notice_inbox source values --- classes/Notice_inbox.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 673e187c7..367a35f1f 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -25,6 +25,10 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; define('INBOX_CACHE_WINDOW', 101); +define('NOTICE_INBOX_SOURCE_SUB', 1); +define('NOTICE_INBOX_SOURCE_GROUP', 2); +define('NOTICE_INBOX_SOURCE_GATEWAY', -1); + class Notice_inbox extends Memcached_DataObject { ###START_AUTOCODE -- cgit v1.2.3-54-g00ecf From d1ae3176b638a8342f0d3cfb4ac071623c639575 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 22:18:25 -0700 Subject: Enable tiling of background imgs for Designs --- actions/designsettings.php | 20 +++++++++++++------- classes/Design.php | 25 ++++++++++++++----------- lib/common.php | 3 ++- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index e97d01ceb..866d8aaeb 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -71,6 +71,12 @@ class DesignsettingsAction extends AccountSettingsAction function showContent() { $user = common_current_user(); + $design = $user->getDesign(); + + if (empty($design)) { + $design = $this->defaultDesign(); + } + $this->elementStart('form', array('method' => 'post', 'enctype' => 'multipart/form-data', 'id' => 'form_settings_design', @@ -122,7 +128,7 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementStart('li'); $this->checkbox('design_background-image_repeat', _('Tile background image'), - false, null, true, false); + $design->tile); $this->elementEnd('li'); $this->elementEnd('ul'); @@ -132,12 +138,6 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change colours')); $this->elementStart('ul', 'form_data'); - $design = $user->getDesign(); - - if (empty($design)) { - $design = $this->defaultDesign(); - } - try { $bgcolor = new WebColor($design->backgroundcolor); @@ -340,6 +340,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->backgroundimage = $defaults['backgroundimage']; + $deisng->tile = $defaults['tile']; + } catch (WebColorException $e) { common_log(LOG_ERR, _('Bad default color settings: ' . $e->getMessage())); @@ -369,6 +371,8 @@ class DesignsettingsAction extends AccountSettingsAction return; } + $tile = $this->boolean('design_background-image_repeat'); + $user = common_current_user(); $design = $user->getDesign(); @@ -382,6 +386,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; + $design->tile = $tile; $result = $design->update($original); @@ -405,6 +410,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; + $design->tile = $tile; $id = $design->insert(); diff --git a/classes/Design.php b/classes/Design.php index acc94d196..4ea176677 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -41,7 +41,7 @@ class Design extends Memcached_DataObject public $textcolor; // int(4) public $linkcolor; // int(4) public $backgroundimage; // varchar(255) - public $tile; // tinyint(1) + public $tile; // tinyint(1) /* Static get */ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } @@ -64,23 +64,26 @@ class Design extends Memcached_DataObject common_log(LOG_ERR, "Unable to create color for design $id.", __FILE__); } - + $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; $css .= '#content, #site_nav_local_views .current a { background-color: #'; $css .= $ccolor->hexValue() . '} '."\n"; $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; - + if (!empty($this->backgroundimage)) { - - $css .= 'body { background-image:url(' . - Design::url($this->backgroundimage) . - '); background-repeat:no-repeat; }' . "\n"; + + $repeat = ($this->tile) ? 'background-repeat:repeat;' : + 'background-repeat:no-repeat;'; + + $css .= 'body { background-image:url(' . + Design::url($this->backgroundimage) . + '); ' . $repeat . ' }' . "\n"; } - + $out->element('style', array('type' => 'text/css'), $css); - + } static function filename($id, $extension, $extra=null) @@ -98,7 +101,7 @@ class Design extends Memcached_DataObject return $dir . $filename; } - + static function url($filename) { $path = common_config('background', 'path'); @@ -121,5 +124,5 @@ class Design extends Memcached_DataObject return 'http://'.$server.$path.$filename; } - + } diff --git a/lib/common.php b/lib/common.php index 0e710625c..629fee25b 100644 --- a/lib/common.php +++ b/lib/common.php @@ -78,7 +78,8 @@ $config = 'sidebarcolor' => '#CEE1E9', 'textcolor' => '#000000', 'linkcolor' => '#002E6E', - 'backgroundimage' => null), + 'backgroundimage' => null, + 'tile' => true), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From 9aebcf442616c5b39ac2ea19ef011c2347a3bec3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 05:18:59 +0000 Subject: IE7/8 CSS update for user design --- theme/base/css/ie.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index d1b0558ec..da200388e 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -1,8 +1,6 @@ /* IE specific styles */ -legend { -margin-left:-7px; -} -input.checkbox { +input.checkbox, +input.radio { top:0; } #form_notice textarea { -- cgit v1.2.3-54-g00ecf From a0618b0e33e20700b243d696f2bf139f1167ec93 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 22:57:28 -0700 Subject: Show a background img in settings form --- actions/designsettings.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/actions/designsettings.php b/actions/designsettings.php index 866d8aaeb..a97235e67 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -105,6 +105,12 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('li'); $this->elementStart('li', array('id' => 'design_background-image_onoff')); + + if (!empty($design->backgroundimage)) { + $this->element('img', array('src' => + Design::url($design->backgroundimage))); + } + $this->element('input', array('name' => 'design_background-image_onoff', 'type' => 'radio', 'id' => 'design_background-image_on', -- cgit v1.2.3-54-g00ecf From 7148ea86dff5754fcf0c28023cff52137843f2d9 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 06:23:57 +0000 Subject: Dynamically tile background image and turn background image on or off in user design --- actions/designsettings.php | 4 +- js/farbtastic/farbtastic.go.js | 87 ----------- js/farbtastic/farbtastic.js | 329 ----------------------------------------- js/userdesign.go.js | 99 +++++++++++++ 4 files changed, 101 insertions(+), 418 deletions(-) delete mode 100644 js/farbtastic/farbtastic.go.js delete mode 100644 js/farbtastic/farbtastic.js create mode 100644 js/userdesign.go.js diff --git a/actions/designsettings.php b/actions/designsettings.php index a97235e67..fbec3fc67 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -305,12 +305,12 @@ class DesignsettingsAction extends AccountSettingsAction parent::showScripts(); $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); - $farbtasticGo = common_path('js/farbtastic/farbtastic.go.js'); + $userDesignGo = common_path('js/userdesign.go.js'); $this->element('script', array('type' => 'text/javascript', 'src' => $farbtasticPack)); $this->element('script', array('type' => 'text/javascript', - 'src' => $farbtasticGo)); + 'src' => $userDesignGo)); } /** diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js deleted file mode 100644 index 9bf740825..000000000 --- a/js/farbtastic/farbtastic.go.js +++ /dev/null @@ -1,87 +0,0 @@ -/** Init for Farbtastic library and page setup - * - * @package Laconica - * @author Sarven Capadisli - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ -$(document).ready(function() { - function UpdateColors(S) { - C = $(S).val(); - switch (parseInt(S.id.slice(-1))) { - case 1: default: - $('html, body').css({'background-color':C}); - break; - case 2: - $('#content, #site_nav_local_views .current a').css({'background-color':C}); - break; - case 3: - $('#aside_primary').css({'background-color':C}); - break; - case 4: - $('html body').css({'color':C}); - break; - case 5: - $('a').css({'color':C}); - break; - } - } - - function UpdateFarbtastic(e) { - f.linked = e; - f.setColor(e.value); - } - - function UpdateSwatch(e) { - $(e).css({"background-color": e.value, - "color": f.hsl[2] > 0.5 ? "#000": "#fff"}); - } - - function SynchColors(e) { - var S = f.linked; - var C = f.color; - - if (S && S.value && S.value != C) { - S.value = C; - UpdateSwatch(S); - UpdateColors(S); - } - } - - function Init() { - $('#settings_design_color').append('
'); - $('#color-picker').hide(); - - f = $.farbtastic('#color-picker', SynchColors); - swatches = $('#settings_design_color .swatch'); - - swatches - .each(SynchColors) - .blur(function() { - tv = $(this).val(); - $(this).val(tv.toUpperCase()); - (tv.length == 4) ? ((tv[0] == '#') ? $(this).val('#'+tv[1]+tv[1]+tv[2]+tv[2]+tv[3]+tv[3]) : '') : ''; - }) - .focus(function() { - $('#color-picker').show(); - UpdateFarbtastic(this); - }) - .change(function() { - UpdateFarbtastic(this); - UpdateSwatch(this); - UpdateColors(this); - }).change(); - } - - var f, swatches; - Init(); - $('#form_settings_design').bind('reset', function(){ - setTimeout(function(){ - swatches.each(function(){UpdateColors(this);}); - $('#color-picker').remove(); - swatches.unbind(); - Init(); - },10); - }); -}); diff --git a/js/farbtastic/farbtastic.js b/js/farbtastic/farbtastic.js deleted file mode 100644 index 24a377803..000000000 --- a/js/farbtastic/farbtastic.js +++ /dev/null @@ -1,329 +0,0 @@ -// $Id: farbtastic.js,v 1.2 2007/01/08 22:53:01 unconed Exp $ -// Farbtastic 1.2 - -jQuery.fn.farbtastic = function (callback) { - $.farbtastic(this, callback); - return this; -}; - -jQuery.farbtastic = function (container, callback) { - var container = $(container).get(0); - return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); -} - -jQuery._farbtastic = function (container, callback) { - // Store farbtastic object - var fb = this; - - // Insert markup - $(container).html('
'); - var e = $('.farbtastic', container); - fb.wheel = $('.wheel', container).get(0); - // Dimensions - fb.radius = 84; - fb.square = 100; - fb.width = 194; - - // Fix background PNGs in IE6 - if (navigator.appVersion.match(/MSIE [0-6]\./)) { - $('*', e).each(function () { - if (this.currentStyle.backgroundImage != 'none') { - var image = this.currentStyle.backgroundImage; - image = this.currentStyle.backgroundImage.substring(5, image.length - 2); - $(this).css({ - 'backgroundImage': 'none', - 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" - }); - } - }); - } - - /** - * Link to the given element(s) or callback. - */ - fb.linkTo = function (callback) { - // Unbind previous nodes - if (typeof fb.callback == 'object') { - $(fb.callback).unbind('keyup', fb.updateValue); - } - - // Reset color - fb.color = null; - - // Bind callback or elements - if (typeof callback == 'function') { - fb.callback = callback; - } - else if (typeof callback == 'object' || typeof callback == 'string') { - fb.callback = $(callback); - fb.callback.bind('keyup', fb.updateValue); - if (fb.callback.get(0).value) { - fb.setColor(fb.callback.get(0).value); - } - } - return this; - } - fb.updateValue = function (event) { - if (this.value && this.value != fb.color) { - fb.setColor(this.value); - } - } - - /** - * Change color with HTML syntax #123456 - */ - fb.setColor = function (color) { - var unpack = fb.unpack(color); - if (fb.color != color && unpack) { - fb.color = color; - fb.rgb = unpack; - fb.hsl = fb.RGBToHSL(fb.rgb); - fb.updateDisplay(); - } - return this; - } - - /** - * Change color with HSL triplet [0..1, 0..1, 0..1] - */ - fb.setHSL = function (hsl) { - fb.hsl = hsl; - fb.rgb = fb.HSLToRGB(hsl); - fb.color = fb.pack(fb.rgb); - fb.updateDisplay(); - return this; - } - - ///////////////////////////////////////////////////// - - /** - * Retrieve the coordinates of the given event relative to the center - * of the widget. - */ - fb.widgetCoords = function (event) { - var x, y; - var el = event.target || event.srcElement; - var reference = fb.wheel; - - if (typeof event.offsetX != 'undefined') { - // Use offset coordinates and find common offsetParent - var pos = { x: event.offsetX, y: event.offsetY }; - - // Send the coordinates upwards through the offsetParent chain. - var e = el; - while (e) { - e.mouseX = pos.x; - e.mouseY = pos.y; - pos.x += e.offsetLeft; - pos.y += e.offsetTop; - e = e.offsetParent; - } - - // Look for the coordinates starting from the wheel widget. - var e = reference; - var offset = { x: 0, y: 0 } - while (e) { - if (typeof e.mouseX != 'undefined') { - x = e.mouseX - offset.x; - y = e.mouseY - offset.y; - break; - } - offset.x += e.offsetLeft; - offset.y += e.offsetTop; - e = e.offsetParent; - } - - // Reset stored coordinates - e = el; - while (e) { - e.mouseX = undefined; - e.mouseY = undefined; - e = e.offsetParent; - } - } - else { - // Use absolute coordinates - var pos = fb.absolutePosition(reference); - x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x; - y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y; - } - // Subtract distance to middle - return { x: x - fb.width / 2, y: y - fb.width / 2 }; - } - - /** - * Mousedown handler - */ - fb.mousedown = function (event) { - // Capture mouse - if (!document.dragging) { - $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup); - document.dragging = true; - } - - // Check which area is being dragged - var pos = fb.widgetCoords(event); - fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square; - - // Process - fb.mousemove(event); - return false; - } - - /** - * Mousemove handler - */ - fb.mousemove = function (event) { - // Get coordinates relative to color picker center - var pos = fb.widgetCoords(event); - - // Set new HSL parameters - if (fb.circleDrag) { - var hue = Math.atan2(pos.x, -pos.y) / 6.28; - if (hue < 0) hue += 1; - fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]); - } - else { - var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5)); - var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5)); - fb.setHSL([fb.hsl[0], sat, lum]); - } - return false; - } - - /** - * Mouseup handler - */ - fb.mouseup = function () { - // Uncapture mouse - $(document).unbind('mousemove', fb.mousemove); - $(document).unbind('mouseup', fb.mouseup); - document.dragging = false; - } - - /** - * Update the markers and styles - */ - fb.updateDisplay = function () { - // Markers - var angle = fb.hsl[0] * 6.28; - $('.h-marker', e).css({ - left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px', - top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px' - }); - - $('.sl-marker', e).css({ - left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px', - top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px' - }); - - // Saturation/Luminance gradient - $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5]))); - - // Linked elements or callback - if (typeof fb.callback == 'object') { - // Set background/foreground color - $(fb.callback).css({ - backgroundColor: fb.color, - color: fb.hsl[2] > 0.5 ? '#000' : '#fff' - }); - - // Change linked value - $(fb.callback).each(function() { - if (this.value && this.value != fb.color) { - this.value = fb.color; - } - }); - } - else if (typeof fb.callback == 'function') { - fb.callback.call(fb, fb.color); - } - } - - /** - * Get absolute position of element - */ - fb.absolutePosition = function (el) { - var r = { x: el.offsetLeft, y: el.offsetTop }; - // Resolve relative to offsetParent - if (el.offsetParent) { - var tmp = fb.absolutePosition(el.offsetParent); - r.x += tmp.x; - r.y += tmp.y; - } - return r; - }; - - /* Various color utility functions */ - fb.pack = function (rgb) { - var r = Math.round(rgb[0] * 255); - var g = Math.round(rgb[1] * 255); - var b = Math.round(rgb[2] * 255); - return '#' + (r < 16 ? '0' : '') + r.toString(16) + - (g < 16 ? '0' : '') + g.toString(16) + - (b < 16 ? '0' : '') + b.toString(16); - } - - fb.unpack = function (color) { - if (color.length == 7) { - return [parseInt('0x' + color.substring(1, 3)) / 255, - parseInt('0x' + color.substring(3, 5)) / 255, - parseInt('0x' + color.substring(5, 7)) / 255]; - } - else if (color.length == 4) { - return [parseInt('0x' + color.substring(1, 2)) / 15, - parseInt('0x' + color.substring(2, 3)) / 15, - parseInt('0x' + color.substring(3, 4)) / 15]; - } - } - - fb.HSLToRGB = function (hsl) { - var m1, m2, r, g, b; - var h = hsl[0], s = hsl[1], l = hsl[2]; - m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s; - m1 = l * 2 - m2; - return [this.hueToRGB(m1, m2, h+0.33333), - this.hueToRGB(m1, m2, h), - this.hueToRGB(m1, m2, h-0.33333)]; - } - - fb.hueToRGB = function (m1, m2, h) { - h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - if (h * 2 < 1) return m2; - if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; - return m1; - } - - fb.RGBToHSL = function (rgb) { - var min, max, delta, h, s, l; - var r = rgb[0], g = rgb[1], b = rgb[2]; - min = Math.min(r, Math.min(g, b)); - max = Math.max(r, Math.max(g, b)); - delta = max - min; - l = (min + max) / 2; - s = 0; - if (l > 0 && l < 1) { - s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); - } - h = 0; - if (delta > 0) { - if (max == r && max != g) h += (g - b) / delta; - if (max == g && max != b) h += (2 + (b - r) / delta); - if (max == b && max != r) h += (4 + (r - g) / delta); - h /= 6; - } - return [h, s, l]; - } - - // Install mousedown handler (the others are set on the document on-demand) - $('*', e).mousedown(fb.mousedown); - - // Init color - fb.setColor('#000000'); - - // Set linked elements/callback - if (callback) { - fb.linkTo(callback); - } -} \ No newline at end of file diff --git a/js/userdesign.go.js b/js/userdesign.go.js new file mode 100644 index 000000000..b54b492cc --- /dev/null +++ b/js/userdesign.go.js @@ -0,0 +1,99 @@ +/** Init for Farbtastic library and page setup + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ +$(document).ready(function() { + function UpdateColors(S) { + C = $(S).val(); + switch (parseInt(S.id.slice(-1))) { + case 1: default: + $('html, body').css({'background-color':C}); + break; + case 2: + $('#content, #site_nav_local_views .current a').css({'background-color':C}); + break; + case 3: + $('#aside_primary').css({'background-color':C}); + break; + case 4: + $('html body').css({'color':C}); + break; + case 5: + $('a').css({'color':C}); + break; + } + } + + function UpdateFarbtastic(e) { + f.linked = e; + f.setColor(e.value); + } + + function UpdateSwatch(e) { + $(e).css({"background-color": e.value, + "color": f.hsl[2] > 0.5 ? "#000": "#fff"}); + } + + function SynchColors(e) { + var S = f.linked; + var C = f.color; + + if (S && S.value && S.value != C) { + S.value = C; + UpdateSwatch(S); + UpdateColors(S); + } + } + + function InitFarbtastic() { + $('#settings_design_color').append('
'); + $('#color-picker').hide(); + + f = $.farbtastic('#color-picker', SynchColors); + swatches = $('#settings_design_color .swatch'); + + swatches + .each(SynchColors) + .blur(function() { + tv = $(this).val(); + $(this).val(tv.toUpperCase()); + (tv.length == 4) ? ((tv[0] == '#') ? $(this).val('#'+tv[1]+tv[1]+tv[2]+tv[2]+tv[3]+tv[3]) : '') : ''; + }) + .focus(function() { + $('#color-picker').show(); + UpdateFarbtastic(this); + }) + .change(function() { + UpdateFarbtastic(this); + UpdateSwatch(this); + UpdateColors(this); + }).change(); + } + + var f, swatches; + InitFarbtastic(); + $('#form_settings_design').bind('reset', function(){ + setTimeout(function(){ + swatches.each(function(){UpdateColors(this);}); + $('#color-picker').remove(); + swatches.unbind(); + InitFarbtastic(); + },10); + }); + + $('#design_background-image_off').focus(function() { + $('body').css({'background-image':'none'}); + }); + $('#design_background-image_on').focus(function() { + var bis = $('#design_background-image_onoff img')[0].src; + $('body').css({'background-image':'url('+bis+')'}); + }); + + $('#design_background-image_repeat').click(function() { + ($(this)[0].checked) ? $('body').css({'background-repeat':'repeat'}) : $('body').css({'background-repeat':'no-repeat'}); + }); +}); \ No newline at end of file -- cgit v1.2.3-54-g00ecf From ea5d46a94d377675eb06dc57757d0e4c743f8a54 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 06:38:21 +0000 Subject: It was accidently removed --- js/farbtastic/farbtastic.js | 345 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 js/farbtastic/farbtastic.js diff --git a/js/farbtastic/farbtastic.js b/js/farbtastic/farbtastic.js new file mode 100644 index 000000000..d8b5ad9cd --- /dev/null +++ b/js/farbtastic/farbtastic.js @@ -0,0 +1,345 @@ +/** + * Farbtastic Color Picker 1.2 + * © 2008 Steven Wittens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +jQuery.fn.farbtastic = function (callback) { + $.farbtastic(this, callback); + return this; +}; + +jQuery.farbtastic = function (container, callback) { + var container = $(container).get(0); + return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); +} + +jQuery._farbtastic = function (container, callback) { + // Store farbtastic object + var fb = this; + + // Insert markup + $(container).html('
'); + var e = $('.farbtastic', container); + fb.wheel = $('.wheel', container).get(0); + // Dimensions + fb.radius = 84; + fb.square = 100; + fb.width = 194; + + // Fix background PNGs in IE6 + if (navigator.appVersion.match(/MSIE [0-6]\./)) { + $('*', e).each(function () { + if (this.currentStyle.backgroundImage != 'none') { + var image = this.currentStyle.backgroundImage; + image = this.currentStyle.backgroundImage.substring(5, image.length - 2); + $(this).css({ + 'backgroundImage': 'none', + 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" + }); + } + }); + } + + /** + * Link to the given element(s) or callback. + */ + fb.linkTo = function (callback) { + // Unbind previous nodes + if (typeof fb.callback == 'object') { + $(fb.callback).unbind('keyup', fb.updateValue); + } + + // Reset color + fb.color = null; + + // Bind callback or elements + if (typeof callback == 'function') { + fb.callback = callback; + } + else if (typeof callback == 'object' || typeof callback == 'string') { + fb.callback = $(callback); + fb.callback.bind('keyup', fb.updateValue); + if (fb.callback.get(0).value) { + fb.setColor(fb.callback.get(0).value); + } + } + return this; + } + fb.updateValue = function (event) { + if (this.value && this.value != fb.color) { + fb.setColor(this.value); + } + } + + /** + * Change color with HTML syntax #123456 + */ + fb.setColor = function (color) { + var unpack = fb.unpack(color); + if (fb.color != color && unpack) { + fb.color = color; + fb.rgb = unpack; + fb.hsl = fb.RGBToHSL(fb.rgb); + fb.updateDisplay(); + } + return this; + } + + /** + * Change color with HSL triplet [0..1, 0..1, 0..1] + */ + fb.setHSL = function (hsl) { + fb.hsl = hsl; + fb.rgb = fb.HSLToRGB(hsl); + fb.color = fb.pack(fb.rgb); + fb.updateDisplay(); + return this; + } + + ///////////////////////////////////////////////////// + + /** + * Retrieve the coordinates of the given event relative to the center + * of the widget. + */ + fb.widgetCoords = function (event) { + var x, y; + var el = event.target || event.srcElement; + var reference = fb.wheel; + + if (typeof event.offsetX != 'undefined') { + // Use offset coordinates and find common offsetParent + var pos = { x: event.offsetX, y: event.offsetY }; + + // Send the coordinates upwards through the offsetParent chain. + var e = el; + while (e) { + e.mouseX = pos.x; + e.mouseY = pos.y; + pos.x += e.offsetLeft; + pos.y += e.offsetTop; + e = e.offsetParent; + } + + // Look for the coordinates starting from the wheel widget. + var e = reference; + var offset = { x: 0, y: 0 } + while (e) { + if (typeof e.mouseX != 'undefined') { + x = e.mouseX - offset.x; + y = e.mouseY - offset.y; + break; + } + offset.x += e.offsetLeft; + offset.y += e.offsetTop; + e = e.offsetParent; + } + + // Reset stored coordinates + e = el; + while (e) { + e.mouseX = undefined; + e.mouseY = undefined; + e = e.offsetParent; + } + } + else { + // Use absolute coordinates + var pos = fb.absolutePosition(reference); + x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x; + y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y; + } + // Subtract distance to middle + return { x: x - fb.width / 2, y: y - fb.width / 2 }; + } + + /** + * Mousedown handler + */ + fb.mousedown = function (event) { + // Capture mouse + if (!document.dragging) { + $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup); + document.dragging = true; + } + + // Check which area is being dragged + var pos = fb.widgetCoords(event); + fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square; + + // Process + fb.mousemove(event); + return false; + } + + /** + * Mousemove handler + */ + fb.mousemove = function (event) { + // Get coordinates relative to color picker center + var pos = fb.widgetCoords(event); + + // Set new HSL parameters + if (fb.circleDrag) { + var hue = Math.atan2(pos.x, -pos.y) / 6.28; + if (hue < 0) hue += 1; + fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]); + } + else { + var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5)); + var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5)); + fb.setHSL([fb.hsl[0], sat, lum]); + } + return false; + } + + /** + * Mouseup handler + */ + fb.mouseup = function () { + // Uncapture mouse + $(document).unbind('mousemove', fb.mousemove); + $(document).unbind('mouseup', fb.mouseup); + document.dragging = false; + } + + /** + * Update the markers and styles + */ + fb.updateDisplay = function () { + // Markers + var angle = fb.hsl[0] * 6.28; + $('.h-marker', e).css({ + left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px', + top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px' + }); + + $('.sl-marker', e).css({ + left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px', + top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px' + }); + + // Saturation/Luminance gradient + $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5]))); + + // Linked elements or callback + if (typeof fb.callback == 'object') { + // Set background/foreground color + $(fb.callback).css({ + backgroundColor: fb.color, + color: fb.hsl[2] > 0.5 ? '#000' : '#fff' + }); + + // Change linked value + $(fb.callback).each(function() { + if (this.value && this.value != fb.color) { + this.value = fb.color; + } + }); + } + else if (typeof fb.callback == 'function') { + fb.callback.call(fb, fb.color); + } + } + + /** + * Get absolute position of element + */ + fb.absolutePosition = function (el) { + var r = { x: el.offsetLeft, y: el.offsetTop }; + // Resolve relative to offsetParent + if (el.offsetParent) { + var tmp = fb.absolutePosition(el.offsetParent); + r.x += tmp.x; + r.y += tmp.y; + } + return r; + }; + + /* Various color utility functions */ + fb.pack = function (rgb) { + var r = Math.round(rgb[0] * 255); + var g = Math.round(rgb[1] * 255); + var b = Math.round(rgb[2] * 255); + return '#' + (r < 16 ? '0' : '') + r.toString(16) + + (g < 16 ? '0' : '') + g.toString(16) + + (b < 16 ? '0' : '') + b.toString(16); + } + + fb.unpack = function (color) { + if (color.length == 7) { + return [parseInt('0x' + color.substring(1, 3)) / 255, + parseInt('0x' + color.substring(3, 5)) / 255, + parseInt('0x' + color.substring(5, 7)) / 255]; + } + else if (color.length == 4) { + return [parseInt('0x' + color.substring(1, 2)) / 15, + parseInt('0x' + color.substring(2, 3)) / 15, + parseInt('0x' + color.substring(3, 4)) / 15]; + } + } + + fb.HSLToRGB = function (hsl) { + var m1, m2, r, g, b; + var h = hsl[0], s = hsl[1], l = hsl[2]; + m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s; + m1 = l * 2 - m2; + return [this.hueToRGB(m1, m2, h+0.33333), + this.hueToRGB(m1, m2, h), + this.hueToRGB(m1, m2, h-0.33333)]; + } + + fb.hueToRGB = function (m1, m2, h) { + h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + if (h * 2 < 1) return m2; + if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; + return m1; + } + + fb.RGBToHSL = function (rgb) { + var min, max, delta, h, s, l; + var r = rgb[0], g = rgb[1], b = rgb[2]; + min = Math.min(r, Math.min(g, b)); + max = Math.max(r, Math.max(g, b)); + delta = max - min; + l = (min + max) / 2; + s = 0; + if (l > 0 && l < 1) { + s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); + } + h = 0; + if (delta > 0) { + if (max == r && max != g) h += (g - b) / delta; + if (max == g && max != b) h += (2 + (b - r) / delta); + if (max == b && max != r) h += (4 + (r - g) / delta); + h /= 6; + } + return [h, s, l]; + } + + // Install mousedown handler (the others are set on the document on-demand) + $('*', e).mousedown(fb.mousedown); + + // Init color + fb.setColor('#000000'); + + // Set linked elements/callback + if (callback) { + fb.linkTo(callback); + } +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 0e4d8c416db4c838e94df3df77c2e4b14a0e1851 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 07:49:41 +0000 Subject: Removed NoticeHover from JavaScript for speed gain. Using CSS instead to handle the notice hover state. The difference is only seen in the conversation page. --- js/util.js | 13 +------------ theme/default/css/display.css | 13 +++++++------ theme/identica/css/display.css | 13 +++++++------ 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/js/util.js b/js/util.js index fd2500d44..ce0c20d31 100644 --- a/js/util.js +++ b/js/util.js @@ -230,21 +230,10 @@ $(document).ready(function(){ }; $("#form_notice").ajaxForm(PostNotice); $("#form_notice").each(addAjaxHidden); - NoticeHover(); NoticeReply(); NoticeAttachments(); }); - -function NoticeHover() { - function mouseHandler(e) { - $(e.target).closest('li.hentry')[(e.type === 'mouseover') ? 'addClass' : 'removeClass']('hover'); - }; - $('#content .notices').mouseover(mouseHandler); - $('#content .notices').mouseout(mouseHandler); -} - - function NoticeReply() { if ($('#notice_data-text').length > 0) { $('#content .notice').each(function() { @@ -319,4 +308,4 @@ function NoticeAttachments() { $(this).closest(".entry-title").removeClass('ov'); } ); -} +} \ No newline at end of file diff --git a/theme/default/css/display.css b/theme/default/css/display.css index f0d6dace8..8dd5ca32c 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -226,13 +226,11 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r } .notices div.entry-content, -.notices div.notice-options, -.notices li.hover .notices div.entry-content, -.notices li.hover .notices div.notice-options { +.notices div.notice-options { opacity:0.4; } -.notices li.hover div.entry-content, -.notices li.hover div.notice-options { +.notices li:hover div.entry-content, +.notices li:hover div.notice-options { opacity:1; } div.entry-content { @@ -242,9 +240,12 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li.hover { +.notices li:hover { background-color:#FCFCFC; } +#conversation .notices li:hover { +background-color:transparent; +} .notices .notices { background-color:rgba(200, 200, 200, 0.050); diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 25a01abe0..975702faa 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -226,13 +226,11 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r } .notices div.entry-content, -.notices div.notice-options, -.notices li.hover .notices div.entry-content, -.notices li.hover .notices div.notice-options { +.notices div.notice-options { opacity:0.4; } -.notices li.hover div.entry-content, -.notices li.hover div.notice-options { +.notices li:hover div.entry-content, +.notices li:hover div.notice-options { opacity:1; } div.entry-content { @@ -242,9 +240,12 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li.hover { +.notices li:hover { background-color:#FCFCFC; } +#conversation .notices li:hover { +background-color:transparent; +} .notices .notices { background-color:rgba(200, 200, 200, 0.050); -- cgit v1.2.3-54-g00ecf From 4c640aace978a2a57b6d2d4658febde3f9826efa Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 08:14:01 +0000 Subject: Updated markup yes/no form actions to be consistent with the rest of the site --- actions/block.php | 17 ++++++++++------- actions/groupblock.php | 17 ++++++++++------- theme/base/css/display.css | 3 ++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/actions/block.php b/actions/block.php index 0efee5932..441016d4e 100644 --- a/actions/block.php +++ b/actions/block.php @@ -125,16 +125,18 @@ class BlockAction extends Action function areYouSureForm() { $id = $this->profile->id; + $this->elementStart('form', array('id' => 'block-' . $id, + 'method' => 'post', + 'class' => 'form_settings form_entity_block', + 'action' => common_local_url('block'))); + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + $this->element('legend', _('Block user')); $this->element('p', null, _('Are you sure you want to block this user? '. 'Afterwards, they will be unsubscribed from you, '. 'unable to subscribe to you in the future, and '. 'you will not be notified of any @-replies from them.')); - $this->elementStart('form', array('id' => 'block-' . $id, - 'method' => 'post', - 'class' => 'block', - 'action' => common_local_url('block'))); - $this->hidden('token', common_session_token()); $this->element('input', array('id' => 'blockto-' . $id, 'name' => 'blockto', 'type' => 'hidden', @@ -144,8 +146,9 @@ class BlockAction extends Action $this->hidden($k, $v); } } - $this->submit('no', _('No')); - $this->submit('yes', _('Yes')); + $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); + $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); + $this->elementEnd('fieldset'); $this->elementEnd('form'); } diff --git a/actions/groupblock.php b/actions/groupblock.php index 93662da79..28685b1d5 100644 --- a/actions/groupblock.php +++ b/actions/groupblock.php @@ -151,17 +151,19 @@ class GroupblockAction extends Action function areYouSureForm() { $id = $this->profile->id; + $this->elementStart('form', array('id' => 'block-' . $id, + 'method' => 'post', + 'class' => 'form_settings form_entity_block', + 'action' => common_local_url('groupblock'))); + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + $this->element('legend', null, _('Block user')); $this->element('p', null, sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '. 'They will be removed from the group, unable to post, and '. 'unable to subscribe to the group in the future.'), $this->profile->getBestName(), $this->group->getBestName())); - $this->elementStart('form', array('id' => 'block-' . $id, - 'method' => 'post', - 'class' => 'block', - 'action' => common_local_url('groupblock'))); - $this->hidden('token', common_session_token()); $this->hidden('blockto-' . $this->profile->id, $this->profile->id, 'blockto'); @@ -173,8 +175,9 @@ class GroupblockAction extends Action $this->hidden($k, $v); } } - $this->submit('no', _('No')); - $this->submit('yes', _('Yes')); + $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); + $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); + $this->elementEnd('fieldset'); $this->elementEnd('form'); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 49907058e..403a9c37f 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -154,7 +154,8 @@ font-weight:bold; #form_invite legend, #form_notice_delete legend, #form_password_recover legend, -#form_password_change legend { +#form_password_change legend, +.form_entity_block legend { display:none; } -- cgit v1.2.3-54-g00ecf From 85a4e32f30fcc1b081cde7c8e0267b4fd0c83e16 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 17 Jun 2009 09:03:59 +0000 Subject: Updated input submit for making a user admin of a group --- theme/base/css/display.css | 3 ++- theme/base/images/icons/twotone/green/admin.gif | Bin 0 -> 100 bytes theme/default/css/display.css | 9 +++++++-- theme/identica/css/display.css | 9 +++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 theme/base/images/icons/twotone/green/admin.gif diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 403a9c37f..9e35d015d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -622,7 +622,8 @@ display:block; .entity_send-a-message a, .entity_edit a, .form_user_nudge input.submit, -.entity_nudge p { +.entity_nudge p, +.form_make_admin input.submit { border:0; padding-left:20px; } diff --git a/theme/base/images/icons/twotone/green/admin.gif b/theme/base/images/icons/twotone/green/admin.gif new file mode 100644 index 000000000..10fa431ce Binary files /dev/null and b/theme/base/images/icons/twotone/green/admin.gif differ diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 8dd5ca32c..935116a74 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -65,7 +65,8 @@ div.notice-options input, .entity_send-a-message a, .form_user_nudge input.submit, .entity_nudge p, -.form_settings input.form_action-primary { +.form_settings input.form_action-primary, +.form_make_admin input.submit { color:#002E6E; } @@ -166,7 +167,8 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_user_unblock input.submit, .form_group_block input.submit, .form_group_unblock input.submit, -.entity_nudge p { +.entity_nudge p, +.form_make_admin input.submit { background-position: 0 40%; background-repeat: no-repeat; background-color:transparent; @@ -200,6 +202,9 @@ background-image:url(../../base/images/icons/twotone/green/mail.gif); .form_group_unblock input.submit { background-image:url(../../base/images/icons/twotone/green/shield.gif); } +.form_make_admin input.submit { +background-image:url(../../base/images/icons/twotone/green/admin.gif); +} /* NOTICES */ .notice .attachment { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 975702faa..6845fda5f 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -65,7 +65,8 @@ div.notice-options input, .entity_send-a-message a, .form_user_nudge input.submit, .entity_nudge p, -.form_settings input.form_action-primary { +.form_settings input.form_action-primary, +.form_make_admin input.submit { color:#002E6E; } @@ -166,7 +167,8 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_user_unblock input.submit, .form_group_block input.submit, .form_group_unblock input.submit, -.entity_nudge p { +.entity_nudge p, +.form_make_admin input.submit { background-position: 0 40%; background-repeat: no-repeat; background-color:transparent; @@ -200,6 +202,9 @@ background-image:url(../../base/images/icons/twotone/green/mail.gif); .form_group_unblock input.submit { background-image:url(../../base/images/icons/twotone/green/shield.gif); } +.form_make_admin input.submit { +background-image:url(../../base/images/icons/twotone/green/admin.gif); +} /* NOTICES */ .notice .attachment { -- cgit v1.2.3-54-g00ecf From 76cbeff33c9659cacbb57943056aabcb1517ca5c Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 02:35:51 -0700 Subject: Update background image settings to use bitflags --- actions/designsettings.php | 100 +++++++++++++++++++++++++++------------------ classes/Design.php | 33 +++++++++++++-- classes/laconica.ini | 2 +- db/laconica.sql | 2 +- lib/common.php | 2 +- 5 files changed, 93 insertions(+), 46 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index fbec3fc67..3dfaddd7b 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -104,37 +104,52 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => ImageFile::maxFileSizeInt())); $this->elementEnd('li'); - $this->elementStart('li', array('id' => 'design_background-image_onoff')); - if (!empty($design->backgroundimage)) { + + $this->elementStart('li', array('id' => 'design_background-image_onoff')); + $this->element('img', array('src' => Design::url($design->backgroundimage))); - } - $this->element('input', array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_on', - 'class' => 'radio', - 'value' => 'true', - 'checked'=> 'checked')); - $this->element('label', array('for' => 'design_background-image_on', - 'class' => 'radio'), - _('On')); - $this->element('input', array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_off', - 'class' => 'radio', - 'value' => 'false')); - $this->element('label', array('for' => 'design_background-image_off', - 'class' => 'radio'), - _('Off')); - $this->element('p', 'form_guide', _('Turn background image on or off.')); - $this->elementEnd('li'); + $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->element('input', $attrs); + + $this->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->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), + _('Off')); + $this->element('p', 'form_guide', _('Turn background image on or off.')); + $this->elementEnd('li'); + } $this->elementStart('li'); $this->checkbox('design_background-image_repeat', _('Tile background image'), - $design->tile); + ($design->disposition & BACKGROUND_TILE) ? true : false ); $this->elementEnd('li'); $this->elementEnd('ul'); @@ -159,7 +174,6 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => '#' . $bgcolor->hexValue())); $this->elementEnd('li'); - $ccolor = new WebColor($design->contentcolor); $this->elementStart('li'); @@ -346,7 +360,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->backgroundimage = $defaults['backgroundimage']; - $deisng->tile = $defaults['tile']; + $deisng->disposition = $defaults['disposition']; } catch (WebColorException $e) { common_log(LOG_ERR, _('Bad default color settings: ' . @@ -377,7 +391,23 @@ class DesignsettingsAction extends AccountSettingsAction return; } - $tile = $this->boolean('design_background-image_repeat'); + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } $user = common_current_user(); $design = $user->getDesign(); @@ -392,7 +422,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; - $design->tile = $tile; + + $design->setDisposition($on, $off, $tile); $result = $design->update($original); @@ -416,7 +447,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; - $design->tile = $tile; + + $design->setDisposition($on, $off, $tile); $id = $design->insert(); @@ -481,16 +513,4 @@ class DesignsettingsAction extends AccountSettingsAction $this->showForm(_('Design preferences saved.'), true); } - /** - * Reset design settings to previous saved value if any, or - * the defaults - * - * @return void - */ - - function resetDesign() - { - $this->showForm(_('Design preferences reset.'), true); - } - } diff --git a/classes/Design.php b/classes/Design.php index 4ea176677..5b28bf014 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -21,6 +21,10 @@ if (!defined('LACONICA')) { exit(1); } +define('BACKGROUND_ON', 1); +define('BACKGROUND_OFF', 2); +define('BACKGROUND_TILE', 4); + /** * Table Definition for design */ @@ -41,7 +45,7 @@ class Design extends Memcached_DataObject public $textcolor; // int(4) public $linkcolor; // int(4) public $backgroundimage; // varchar(255) - public $tile; // tinyint(1) + public $disposition; // tinyint(1) default_1 /* Static get */ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } @@ -72,9 +76,11 @@ class Design extends Memcached_DataObject $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; - if (!empty($this->backgroundimage)) { + if (!empty($this->backgroundimage) && + $this->disposition & BACKGROUND_ON) { - $repeat = ($this->tile) ? 'background-repeat:repeat;' : + $repeat = ($this->disposition & BACKGROUND_TILE) ? + 'background-repeat:repeat;' : 'background-repeat:no-repeat;'; $css .= 'body { background-image:url(' . @@ -125,4 +131,25 @@ class Design extends Memcached_DataObject return 'http://'.$server.$path.$filename; } + function setDisposition($on, $off, $tile) + { + if ($on) { + $this->disposition |= BACKGROUND_ON; + } else { + $this->disposition &= ~BACKGROUND_ON; + } + + if ($off) { + $this->disposition |= BACKGROUND_OFF; + } else { + $this->disposition &= ~BACKGROUND_OFF; + } + + if ($tile) { + $this->disposition |= BACKGROUND_TILE; + } else { + $this->disposition &= ~BACKGROUND_TILE; + } + } + } diff --git a/classes/laconica.ini b/classes/laconica.ini index 569681984..1a650aba5 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -46,7 +46,7 @@ sidebarcolor = 1 textcolor = 1 linkcolor = 1 backgroundimage = 2 -tile = 17 +disposition = 17 [design__keys] id = N diff --git a/db/laconica.sql b/db/laconica.sql index 1f302de16..b018afec8 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -496,7 +496,7 @@ create table design ( textcolor integer comment 'text color', linkcolor integer comment 'link color', backgroundimage varchar(255) comment 'background image, if any', - tile tinyint default 0 comment 'tile background image' + disposition tinyint default 1 comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image' ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table group_block ( diff --git a/lib/common.php b/lib/common.php index 629fee25b..bcf2e5d0c 100644 --- a/lib/common.php +++ b/lib/common.php @@ -79,7 +79,7 @@ $config = 'textcolor' => '#000000', 'linkcolor' => '#002E6E', 'backgroundimage' => null, - 'tile' => true), + 'disposition' => 1), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From 2866d00517b1ccfd7585f5fc2da1ed2fcf52bdfd Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 02:58:35 -0700 Subject: Fix sidebar color bug default design --- actions/designsettings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 3dfaddd7b..adc09c7b0 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -353,14 +353,14 @@ class DesignsettingsAction extends AccountSettingsAction $design->sidebarcolor = $color->intValue(); $color->parseColor($defaults['textcolor']); - $design->sidebarcolor = $color->intValue(); + $design->textcolor = $color->intValue(); $color->parseColor($defaults['linkcolor']); $design->linkcolor = $color->intValue(); $design->backgroundimage = $defaults['backgroundimage']; - $deisng->disposition = $defaults['disposition']; + $design->disposition = $defaults['disposition']; } catch (WebColorException $e) { common_log(LOG_ERR, _('Bad default color settings: ' . -- cgit v1.2.3-54-g00ecf From ac3cccefb53579b01618d5ef728e883dae752fd2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 03:02:43 -0700 Subject: Default to image being on, no tile after upload --- actions/designsettings.php | 1 + 1 file changed, 1 insertion(+) diff --git a/actions/designsettings.php b/actions/designsettings.php index adc09c7b0..047059e04 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -501,6 +501,7 @@ class DesignsettingsAction extends AccountSettingsAction $original = clone($design); $design->backgroundimage = $filename; + $design->setDisposition(true, false, false); $result = $design->update($original); if ($result === false) { -- cgit v1.2.3-54-g00ecf From af4b18b1e2ef8aded26fc4788c571012da04d1cf Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 03:05:48 -0700 Subject: Uppercase hex color values --- lib/webcolor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webcolor.php b/lib/webcolor.php index aaf31d990..f3ca6e94a 100644 --- a/lib/webcolor.php +++ b/lib/webcolor.php @@ -164,7 +164,7 @@ class WebColor { $hexcolor .= (strlen(dechex($this->blue)) < 2 ? '0' : '') . dechex($this->blue); - return $hexcolor; + return strtoupper($hexcolor); } -- cgit v1.2.3-54-g00ecf From 2fbd141361b6ddab0e036b52fc23f2bfcdfd0075 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 08:21:53 -0700 Subject: correct arguments for ProfileList --- actions/featured.php | 5 ++--- actions/peopletag.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/actions/featured.php b/actions/featured.php index 79eba2aa6..04365687d 100644 --- a/actions/featured.php +++ b/actions/featured.php @@ -32,7 +32,7 @@ if (!defined('LACONICA')) { exit(1); } -require_once(INSTALLDIR.'/lib/profilelist.php'); +require_once INSTALLDIR.'/lib/profilelist.php'; require_once INSTALLDIR.'/lib/publicgroupnav.php'; /** @@ -107,7 +107,6 @@ class FeaturedAction extends Action $featured_nicks = common_config('nickname', 'featured'); - if (count($featured_nicks) > 0) { $quoted = array(); @@ -136,7 +135,7 @@ class FeaturedAction extends Action $cnt = $profile->find(); if ($cnt > 0) { - $featured = new ProfileList($profile, null, $this); + $featured = new ProfileList($profile, $this); $featured->show(); } diff --git a/actions/peopletag.php b/actions/peopletag.php index 5add75485..dd3c1c089 100644 --- a/actions/peopletag.php +++ b/actions/peopletag.php @@ -124,7 +124,7 @@ class PeopletagAction extends Action $profile->query(sprintf($qry, $this->tag, $lim)); - $pl = new ProfileList($profile, null, $this); + $pl = new ProfileList($profile, $this); $cnt = $pl->show(); $this->pagination($this->page > 1, -- cgit v1.2.3-54-g00ecf From 19d39b20294bad8dc14df26e76756c558a5083cf Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 12:31:35 -0700 Subject: Store better data about twitter statuses We mark Twitter statuses with flags so they don't get shown in the wrong places. --- scripts/twitterstatusfetcher.php | 111 +++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index 9287b6d73..d332fb555 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -1,6 +1,6 @@ #!/usr/bin/env php + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ class TwitterStatusFetcher extends Daemon { + private $_children = array(); - private $children = array(); + /** + * Name of this daemon + * + * @return string Name of the daemon. + */ function name() { return ('twitterstatusfetcher.generic'); } + /** + * Run the daemon + * + * @return void + */ + function run() { do { $flinks = $this->refreshFlinks(); - foreach ($flinks as $f){ + foreach ($flinks as $f) { // We have to disconnect from the DB before forking so // each sub-process will open its own connection and @@ -73,10 +98,11 @@ class TwitterStatusFetcher extends Daemon // Parent if (defined('SCRIPT_DEBUG')) { - common_debug("Parent: forked new status fetcher process " . $pid); + common_debug("Parent: forked new status ". + " fetcher process " . $pid); } - $this->children[] = $pid; + $this->_children[] = $pid; } else { @@ -86,41 +112,41 @@ class TwitterStatusFetcher extends Daemon } // Remove child from ps list as it finishes - while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { + while (($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { if (defined('SCRIPT_DEBUG')) { common_debug("Child $c finished."); } - $this->remove_ps($this->children, $c); + $this->removePs($this->_children, $c); } // Wait! We have too many damn kids. - if (sizeof($this->children) > MAXCHILDREN) { + if (sizeof($this->_children) > MAXCHILDREN) { if (defined('SCRIPT_DEBUG')) { common_debug('Too many children. Waiting...'); } - if (($c = pcntl_wait($status, WUNTRACED)) > 0){ + if (($c = pcntl_wait($status, WUNTRACED)) > 0) { if (defined('SCRIPT_DEBUG')) { common_debug("Finished waiting for $c"); } - $this->remove_ps($this->children, $c); + $this->removePs($this->_children, $c); } } } // Remove all children from the process list before restarting - while(($c = pcntl_wait($status, WUNTRACED)) > 0) { + while (($c = pcntl_wait($status, WUNTRACED)) > 0) { if (defined('SCRIPT_DEBUG')) { common_debug("Child $c finished."); } - $this->remove_ps($this->children, $c); + $this->removePs($this->_children, $c); } // Rest for a bit before we fetch more statuses @@ -137,10 +163,18 @@ class TwitterStatusFetcher extends Daemon } while (true); } - function refreshFlinks() { + /** + * Refresh the foreign links for this user + * + * @return void + */ + function refreshFlinks() + { $flink = new Foreign_link(); + $flink->service = 1; // Twitter + $flink->orderBy('last_noticesync'); $cnt = $flink->find(); @@ -166,7 +200,18 @@ class TwitterStatusFetcher extends Daemon return $flinks; } - function remove_ps(&$plist, $ps){ + /** + * Unknown + * + * @param array &$plist unknown. + * @param string $ps unknown. + * + * @return unknown + * @todo document + */ + + function removePs(&$plist, $ps) + { for ($i = 0; $i < sizeof($plist); $i++) { if ($plist[$i] == $ps) { unset($plist[$i]); @@ -178,7 +223,6 @@ class TwitterStatusFetcher extends Daemon function getTimeline($flink) { - if (empty($flink)) { common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); @@ -247,23 +291,32 @@ class TwitterStatusFetcher extends Daemon return null; } + // XXX: change of screen name? + $uri = 'http://twitter.com/' . $status->user->screen_name . '/status/' . $status->id; $notice = Notice::staticGet('uri', $uri); // check to see if we've already imported the status - if (!$notice) { - $created = strftime('%Y-%m-%d %H:%M:%S', - strtotime($status->created_at));; - - $notice = Notice::saveNew($id, $status->text, 'twitter', - -2, null, $uri, $created); + if (!$notice) { - if (defined('SCRIPT_DEBUG')) { - common_debug("Saved status $status->id" . - " as notice $notice->id."); + $notice = new Notice(); + + $notice->profile_id = $id; + $notice->uri = $uri; + $notice->created = strftime('%Y-%m-%d %H:%M:%S', + strtotime($status->created_at)); + $notice->content = common_shorten_links($status->text); // XXX + $notice->rendered = common_render_content($notice->content, $notice); + $notice->source = 'twitter'; + $notice->reply_to = null; // XXX lookup reply + $notice->is_local = NOTICE_GATEWAY; + + if (Event::handle('StartNoticeSave', array(&$notice))) { + $id = $notice->insert(); + Event::handle('EndNoticeSave', array($notice)); } } @@ -271,9 +324,11 @@ class TwitterStatusFetcher extends Daemon 'user_id' => $flink->user_id))) { // Add to inbox $inbox = new Notice_inbox(); - $inbox->user_id = $flink->user_id; + + $inbox->user_id = $flink->user_id; $inbox->notice_id = $notice->id; - $inbox->created = $notice->created; + $inbox->created = $notice->created; + $inbox->source = NOTICE_INBOX_SOURCE_GATEWAY; // From a private source $inbox->insert(); } -- cgit v1.2.3-54-g00ecf From 1505e3a4c3dda7030bb92a2071ec58af2972bed7 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 17 Jun 2009 16:21:50 -0400 Subject: Fixed recent attachment bug that required URLs to be posted twice to be taken into account. --- classes/File.php | 2 -- classes/Notice.php | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/classes/File.php b/classes/File.php index 24ab11b8e..08320faf8 100644 --- a/classes/File.php +++ b/classes/File.php @@ -79,7 +79,6 @@ class File extends Memcached_DataObject && ('text/html' === substr($redir_data['type'], 0, 9)) && ($oembed_data = File_oembed::_getOembed($given_url)) && isset($oembed_data['json'])) { - File_oembed::saveNew($oembed_data['json'], $file_id); } return $x; @@ -98,7 +97,6 @@ class File extends Memcached_DataObject if ($redir_url === $given_url) { $x = File::saveNew($redir_data, $given_url); $file_id = $x->id; - } else { $x = File::processNew($redir_url, $notice_id); $file_id = $x->id; diff --git a/classes/Notice.php b/classes/Notice.php index 770b5d78b..e0bb90ba6 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -218,6 +218,12 @@ class Notice extends Memcached_DataObject $notice->addToInboxes(); $notice->saveGroups(); $notice->saveUrls(); + $orig2 = clone($notice); + $notice->rendered = common_render_content($final, $notice); + if (!$notice->update($orig2)) { + common_log_db_error($notice, 'UPDATE', __FILE__); + return _('Problem saving notice.'); + } $notice->query('COMMIT'); @@ -237,8 +243,6 @@ class Notice extends Memcached_DataObject * follow redirects and save all available file information * (mimetype, date, size, oembed, etc.) * - * @param class $notice Notice to pull URLs from - * * @return void */ function saveUrls() { -- cgit v1.2.3-54-g00ecf From 28d02ec8cdd0278c802c8fee30acddecca9ca01f Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 17 Jun 2009 16:44:33 -0400 Subject: Make oohembed endpoint configurable. --- README | 8 ++++++++ classes/File_oembed.php | 2 +- config.php.sample | 1 + lib/common.php | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README b/README index 3279f7bba..7b22e3c5e 100644 --- a/README +++ b/README @@ -1246,6 +1246,14 @@ Options for group functionality. maxaliases: maximum number of aliases a group can have. Default 3. Set to 0 or less to prevent aliases in a group. + +oohembed +-------- + +oEmbed endpoint for multimedia attachments (links in posts). + +endpoint: oohembed endpoint using http://oohembed.com/ software. + Troubleshooting =============== diff --git a/classes/File_oembed.php b/classes/File_oembed.php index f1b2cb13c..6bf972f8f 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -53,7 +53,7 @@ class File_oembed extends Memcached_DataObject function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') { - $cmd = 'http://oohembed.com/oohembed/?url=' . urlencode($url); + $cmd = common_config('oohembed', 'endpoint') . '?url=' . urlencode($url); if (is_int($maxwidth)) $cmd .= "&maxwidth=$maxwidth"; if (is_int($maxheight)) $cmd .= "&maxheight=$maxheight"; if (is_string($format)) $cmd .= "&format=$format"; diff --git a/config.php.sample b/config.php.sample index 636f4cf8e..ed70f85fb 100644 --- a/config.php.sample +++ b/config.php.sample @@ -223,3 +223,4 @@ $config['sphinx']['port'] = 3312; // $config['attachments']['user_quota'] = 50000000; // $config['attachments']['monthly_quota'] = 15000000; +// $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; diff --git a/lib/common.php b/lib/common.php index 51204cede..9c015a15d 100644 --- a/lib/common.php +++ b/lib/common.php @@ -203,6 +203,7 @@ $config = ), 'group' => array('maxaliases' => 3), + 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/') ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); -- cgit v1.2.3-54-g00ecf From b58dc5e96117bdb4de899d37c6eb94ebf1c3dfe6 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 17 Jun 2009 16:55:01 -0400 Subject: Added config option to enable or disable file uploads with notices. --- README | 1 + config.php.sample | 1 + lib/common.php | 1 + lib/noticeform.php | 18 +++++++++++------- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/README b/README index 7b22e3c5e..5aa7270ee 100644 --- a/README +++ b/README @@ -1223,6 +1223,7 @@ supported: an array of mime types you accept to store and distribute, like 'image/gif', 'video/mpeg', 'audio/mpeg', etc. Make sure you setup your server to properly reckognize the types you want to support. +uploads: false to disable uploading files with notices (true by default). For quotas, be sure you've set the upload_max_filesize and post_max_size in php.ini to be large enough to handle your upload. In httpd.conf diff --git a/config.php.sample b/config.php.sample index ed70f85fb..7649c5262 100644 --- a/config.php.sample +++ b/config.php.sample @@ -222,5 +222,6 @@ $config['sphinx']['port'] = 3312; // $config['attachments']['file_quota'] = 5000000; // $config['attachments']['user_quota'] = 50000000; // $config['attachments']['monthly_quota'] = 15000000; +// $config['attachments']['uploads'] = true; // $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; diff --git a/lib/common.php b/lib/common.php index 9c015a15d..bbd9f78c3 100644 --- a/lib/common.php +++ b/lib/common.php @@ -200,6 +200,7 @@ $config = 'file_quota' => 5000000, 'user_quota' => 50000000, 'monthly_quota' => 15000000, + 'uploads' => true, ), 'group' => array('maxaliases' => 3), diff --git a/lib/noticeform.php b/lib/noticeform.php index 0ad365856..a36b7f31f 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -90,7 +90,9 @@ class NoticeForm extends Form $this->user = common_current_user(); } - $this->enctype = 'multipart/form-data'; + if (common_config('attachments', 'uploads')) { + $this->enctype = 'multipart/form-data'; + } } /** @@ -148,12 +150,14 @@ class NoticeForm extends Form $this->out->element('dd', array('id' => 'notice_text-count'), '140'); $this->out->elementEnd('dl'); - $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); - $this->out->element('input', array('id' => 'notice_data-attach', - 'type' => 'file', - 'name' => 'attach', - 'title' => _('Attach a file'))); - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); + if (common_config('attachments', 'uploads')) { + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); + $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); + $this->out->element('input', array('id' => 'notice_data-attach', + 'type' => 'file', + 'name' => 'attach', + 'title' => _('Attach a file'))); + } if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); } -- cgit v1.2.3-54-g00ecf From 7e25a7f3aa2a308ddfc141e2e88fd52c042cb931 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 14:32:36 -0700 Subject: Output XML and JSON error msgs for API calls --- lib/twitterapi.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 569bc6d7a..269b60efc 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -545,7 +545,7 @@ class TwitterapiAction extends Action $this->init_twitter_atom(); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); break; } @@ -573,13 +573,13 @@ class TwitterapiAction extends Action $this->end_twitter_rss(); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); break; } return; } - function client_error($msg, $code = 400, $content_type = 'json') + function clientError($msg, $code = 400, $content_type = 'json') { static $status = array(400 => 'Bad Request', @@ -666,7 +666,7 @@ class TwitterapiAction extends Action $this->show_json_objects($profile_array); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); return; } return; -- cgit v1.2.3-54-g00ecf From 8992e8fa7a3c694cc9d424b3e50cf4d87519fa28 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 14:34:04 -0700 Subject: Ticket 1612 - make destory (and create) favorites work via API --- actions/twitapifavorites.php | 65 +++++++++++++++++++++++++++++++++++++++----- lib/router.php | 3 +- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php index 8656adbe8..2266ba11c 100644 --- a/actions/twitapifavorites.php +++ b/actions/twitapifavorites.php @@ -34,6 +34,11 @@ class TwitapifavoritesAction extends TwitterapiAction $user = $this->get_user($apidata['api_arg'], $apidata); if (empty($user)) { + if ($apidata['content-type'] == 'xml') { + $this->show_single_xml_status($notice); + } elseif ($apidata['content-type'] == 'json') { + $this->show_single_json_status($notice); + } $this->clientError('Not Found', 404, $apidata['content-type']); return; } @@ -91,7 +96,6 @@ class TwitapifavoritesAction extends TwitterapiAction // Check for RESTfulness if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { - // XXX: Twitter just prints the err msg, no XML / JSON. $this->clientError(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']); return; @@ -102,10 +106,9 @@ class TwitapifavoritesAction extends TwitterapiAction return; } - $user = $apidata['user']; // Always the auth user - + $user = $apidata['user']; // Always the auth user $notice_id = $apidata['api_arg']; - $notice = Notice::staticGet($notice_id); + $notice = Notice::staticGet($notice_id); if (empty($notice)) { $this->clientError(_('No status found with that ID.'), @@ -115,7 +118,7 @@ class TwitapifavoritesAction extends TwitterapiAction // XXX: Twitter lets you fave things repeatedly via api. if ($user->hasFave($notice)) { - $this->clientError(_('This notice is already a favorite!'), + $this->clientError(_('This status is already a favorite!'), 403, $apidata['content-type']); return; } @@ -123,7 +126,7 @@ class TwitapifavoritesAction extends TwitterapiAction $fave = Fave::addNew($user, $notice); if (empty($fave)) { - $this->serverError(_('Could not create favorite.')); + $this->clientError(_('Could not create favorite.')); return; } @@ -141,7 +144,55 @@ class TwitapifavoritesAction extends TwitterapiAction function destroy($args, $apidata) { parent::handle($args); - $this->serverError(_('API method under construction.'), $code=501); + + // Check for RESTfulness + if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { + $this->clientError(_('This method requires a POST or DELETE.'), + 400, $apidata['content-type']); + return; + } + + if (!in_array($apidata['content-type'], array('xml', 'json'))) { + $this->clientError(_('API method not found!'), $code = 404); + return; + } + + $user = $apidata['user']; // Always the auth user + $notice_id = $apidata['api_arg']; + $notice = Notice::staticGet($notice_id); + + if (empty($notice)) { + $this->clientError(_('No status found with that ID.'), + 404, $apidata['content-type']); + return; + } + + $fave = new Fave(); + $fave->user_id = $this->id; + $fave->notice_id = $notice->id; + + if (!$fave->find(true)) { + $this->clientError(_('That status is not a favorite!'), + 403, $apidata['content-type']); + return; + } + + $result = $fave->delete(); + + if (!$result) { + common_log_db_error($fave, 'DELETE', __FILE__); + $this->clientError(_('Could not delete favorite.'), 404); + return; + } + + $user->blowFavesCache(); + + if ($apidata['content-type'] == 'xml') { + $this->show_single_xml_status($notice); + } elseif ($apidata['content-type'] == 'json') { + $this->show_single_json_status($notice); + } + } // XXX: these two funcs swiped from faves. diff --git a/lib/router.php b/lib/router.php index 0fbaba9ed..8b6f63618 100644 --- a/lib/router.php +++ b/lib/router.php @@ -351,7 +351,8 @@ class Router $m->connect('api/favorites/:method/:argument', array('action' => 'api', - 'apiaction' => 'favorites')); + 'apiaction' => 'favorites', + array('method' => '(create|destroy)'))); $m->connect('api/favorites/:argument', array('action' => 'api', -- cgit v1.2.3-54-g00ecf From 07f5797f2fd1a425027190d424e359a1b4c4c8be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 15:04:57 -0700 Subject: Make the personal tag streams actually work --- actions/showstream.php | 2 +- classes/Notice.php | 6 ++++++ classes/Profile.php | 37 +++++++++++++++++++------------------ 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/actions/showstream.php b/actions/showstream.php index 72316b259..cd5d4bb70 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -370,7 +370,7 @@ class ShowstreamAction extends ProfileAction { $notice = empty($this->tag) ? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1) - : $this->user->getTaggedNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null, $this->tag); + : $this->user->getTaggedNotices($this->tag, ($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null); $pnl = new ProfileNoticeList($notice, $this); $cnt = $pnl->show(); diff --git a/classes/Notice.php b/classes/Notice.php index 6c5558d88..50242300d 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -375,6 +375,12 @@ class Notice extends Memcached_DataObject if ($tag->find()) { while ($tag->fetch()) { $tag->blowCache($blowLast); + $ck = 'profile:notice_ids_tagged:' . $this->profile_id . ':' . $tag->tag; + + $cache->delete($ck); + if ($blowLast) { + $cache->delete($ck . ';last'); + } } } $tag->free(); diff --git a/classes/Profile.php b/classes/Profile.php index 4a459b974..2f432ae8e 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -153,18 +153,16 @@ class Profile extends Memcached_DataObject return null; } - function getTaggedNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null, $tag=null) + function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { - // XXX: I'm not sure this is going to be any faster. It probably isn't. $ids = Notice::stream(array($this, '_streamTaggedDirect'), - array(), - 'profile:notice_ids:' . $this->id, - $offset, $limit, $since_id, $before_id, $since, $tag); - common_debug(print_r($ids, true)); + array($tag), + 'profile:notice_ids_tagged:' . $this->id . ':' . $tag, + $offset, $limit, $since_id, $max_id, $since); return Notice::getStreamByIds($ids); } - function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { // XXX: I'm not sure this is going to be any faster. It probably isn't. $ids = Notice::stream(array($this, '_streamDirect'), @@ -175,18 +173,23 @@ class Profile extends Memcached_DataObject return Notice::getStreamByIds($ids); } - function _streamTaggedDirect($offset, $limit, $since_id, $before_id, $since=null, $tag=null) + function _streamTaggedDirect($tag, $offset, $limit, $since_id, $max_id, $since) { - common_debug('_streamTaggedDirect()'); + // XXX It would be nice to do this without a join + $notice = new Notice(); - $notice->profile_id = $this->id; - $query = "select id from notice join notice_tag on id=notice_id where tag='" . $notice->escape($tag) . "' and profile_id=" . $notice->escape($notice->profile_id); + + $query = + "select id from notice join notice_tag on id=notice_id where tag='". + $notice->escape($tag) . + "' and profile_id=" . $notice->escape($this->id); + if ($since_id != 0) { $query .= " and id > $since_id"; } - if ($before_id != 0) { - $query .= " and id < $before_id"; + if ($max_id != 0) { + $query .= " and id < $max_id"; } if (!is_null($since)) { @@ -198,21 +201,19 @@ class Profile extends Memcached_DataObject if (!is_null($offset)) { $query .= " limit $offset, $limit"; } + $notice->query($query); + $ids = array(); while ($notice->fetch()) { - common_debug(print_r($notice, true)); $ids[] = $notice->id; } return $ids; } - - - - function _streamDirect($offset, $limit, $since_id, $before_id, $since = null) + function _streamDirect($offset, $limit, $since_id, $max_id, $since = null) { $notice = new Notice(); -- cgit v1.2.3-54-g00ecf From 2187ec7056a23e76c756f354bf41e3835ba8d103 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 15:20:44 -0700 Subject: hide group name and aliases in group tag cloud section --- lib/grouptagcloudsection.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/grouptagcloudsection.php b/lib/grouptagcloudsection.php index 5d68af28b..9b7a10f6b 100644 --- a/lib/grouptagcloudsection.php +++ b/lib/grouptagcloudsection.php @@ -32,7 +32,7 @@ if (!defined('LACONICA')) { } /** - * Personal tag cloud section + * Group tag cloud section * * @category Widget * @package Laconica @@ -64,12 +64,27 @@ class GroupTagCloudSection extends TagCloudSection $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; } + $names = $this->group->getAliases(); + + $names = array_merge(array($this->group->nickname), $names); + + // XXX This is dumb. + + $quoted = array(); + + foreach ($names as $name) { + $quoted[] = "\"$name\""; + } + + $namestring = implode(',', $quoted); + $qry = 'SELECT notice_tag.tag, '. $weightexpr . ' as weight ' . 'FROM notice_tag JOIN notice ' . 'ON notice_tag.notice_id = notice.id ' . 'JOIN group_inbox on group_inbox.notice_id = notice.id ' . 'WHERE group_inbox.group_id = %d ' . + 'AND notice_tag.tag not in (%s) '. 'GROUP BY notice_tag.tag ' . 'ORDER BY weight DESC '; @@ -85,9 +100,9 @@ class GroupTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, common_config('tag', 'dropoff'), - $this->group->id), + $this->group->id, + $namestring), 3600); return $tag; } - } -- cgit v1.2.3-54-g00ecf From 85b4c24188502ce3f8cef32cfba37ab91c8a648f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 16:30:16 -0700 Subject: add dbhost argument for status network setup --- scripts/setup.cfg.sample | 1 + scripts/setup_status_network.sh | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample index 4194bc146..450b9c30a 100644 --- a/scripts/setup.cfg.sample +++ b/scripts/setup.cfg.sample @@ -2,6 +2,7 @@ # Base database name; full name will include nickname +export DBHOST=masterdb.example.net export DBBASE=_example_net export USERBASE=_example_net export ADMIN=root diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index d80612b94..e1d14593f 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -11,13 +11,13 @@ export username=$nickname$USERBASE # Create the db -mysqladmin -u $ADMIN --password=$ADMINPASS create $database +mysqladmin -h $DBHOST -u $ADMIN --password=$ADMINPASS create $database for f in laconica.sql sms_carrier.sql foreign_services.sql notice_source.sql; do - mysql -u $ADMIN --password=$ADMINPASS $database < ../db/$f; + mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $database < ../db/$f; done -mysql -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS +mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'localhost' IDENTIFIED BY '$password'; GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'%' IDENTIFIED BY '$password'; -- cgit v1.2.3-54-g00ecf From 4fc4c0a74bd08f568a55d65660ca2e5170165905 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 17:13:59 -0700 Subject: Remove stale reference to deprecated personal.php --- lib/mailbox.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/mailbox.php b/lib/mailbox.php index 766510a47..b282ce368 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -31,8 +31,6 @@ if (!defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/personal.php'; - define('MESSAGES_PER_PAGE', 20); /** -- cgit v1.2.3-54-g00ecf From b0591cd98219cf523d35884015ee9f82c2aa9e09 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 17:29:57 -0700 Subject: Make MailboxAction read only --- lib/mailbox.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/mailbox.php b/lib/mailbox.php index b282ce368..f1f6e98c1 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -295,4 +295,17 @@ class MailboxAction extends CurrentUserDesignAction return; } + /** + * Mailbox actions are read only + * + * @param array $args other arguments + * + * @return boolean + */ + + function isReadOnly($args) + { + return true; + } + } -- cgit v1.2.3-54-g00ecf From 5854fe194a35e1bbf2feb6db415f54f33def2dd9 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 01:04:12 +0000 Subject: Placed a check to make sure there is a reply button in a notice before applying the dynamic action --- js/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/util.js b/js/util.js index ce0c20d31..854d25060 100644 --- a/js/util.js +++ b/js/util.js @@ -235,7 +235,7 @@ $(document).ready(function(){ }); function NoticeReply() { - if ($('#notice_data-text').length > 0) { + if ($('#notice_data-text').length > 0 && $('.notice_reply').length > 0) { $('#content .notice').each(function() { var notice = $(this)[0]; $($('.notice_reply', notice)[0]).click(function() { @@ -308,4 +308,4 @@ function NoticeAttachments() { $(this).closest(".entry-title").removeClass('ov'); } ); -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf From 06240450ef4818a8a74748ada297d1d55d18b967 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 18:05:12 -0700 Subject: Have user favorites page show user's design --- actions/showfavorites.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 865045337..01f38a892 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class ShowfavoritesAction extends Action +class ShowfavoritesAction extends CurrentUserDesignAction { /** User we're getting the faves of */ var $user = null; -- cgit v1.2.3-54-g00ecf From 77185dd4c67761afbe670a15928c523f4de2842b Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 01:10:48 +0000 Subject: A little more specific selector for notice reply --- js/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/util.js b/js/util.js index 854d25060..17ae4c071 100644 --- a/js/util.js +++ b/js/util.js @@ -235,7 +235,7 @@ $(document).ready(function(){ }); function NoticeReply() { - if ($('#notice_data-text').length > 0 && $('.notice_reply').length > 0) { + if ($('#notice_data-text').length > 0 && $('#content .notice_reply').length > 0) { $('#content .notice').each(function() { var notice = $(this)[0]; $($('.notice_reply', notice)[0]).click(function() { -- cgit v1.2.3-54-g00ecf From d8b0fcbc50248e493dfda288fe538ea58ef66acf Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 01:28:02 +0000 Subject: Removed height:100% for better background image repetition --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 2153ce9a0..99f2d9ece 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -12,7 +12,7 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 87.5%; background-color:#fff; height:100%; } +html { font-size: 87.5%; background-color:#fff; } body { background-color:#fff; color:#000; -- cgit v1.2.3-54-g00ecf From 00736bddd199b2a43820367c3476b9e9ec84c0db Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 01:39:37 +0000 Subject: Fix for background image repetition for various page heights --- classes/Design.php | 8 ++++---- theme/base/css/display.css | 4 ++-- theme/default/css/display.css | 1 - theme/identica/css/display.css | 1 - 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/classes/Design.php b/classes/Design.php index 5b28bf014..da4b670be 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -69,12 +69,12 @@ class Design extends Memcached_DataObject __FILE__); } - $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; + $css = 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n"; $css .= '#content, #site_nav_local_views .current a { background-color: #'; $css .= $ccolor->hexValue() . '} '."\n"; - $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; - $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; - $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; + $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n"; + $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n"; + $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n"; if (!empty($this->backgroundimage) && $this->disposition & BACKGROUND_ON) { diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 99f2d9ece..e1b92edce 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -12,9 +12,9 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 87.5%; background-color:#fff; } +html { font-size: 87.5%; height:100%; } body { -background-color:#fff; +background-color:#FFFFFF; color:#000; font-family:sans-serif; font-size:1em; diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 935116a74..881e264da 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -9,7 +9,6 @@ @import url(../../base/css/display.css); -html, body, a:active { background-color:#C3D6DF; diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 6845fda5f..ad57a0f0e 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -9,7 +9,6 @@ @import url(../../base/css/display.css); -html, body, a:active { background-color:#F0F2F5; -- cgit v1.2.3-54-g00ecf From f36d90a7556da192df1afe5ba24fa32e276f4dc7 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 01:41:53 +0000 Subject: Minor removal --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index e1b92edce..d6ecef2fc 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -12,7 +12,7 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 87.5%; height:100%; } +html { font-size: 87.5%; } body { background-color:#FFFFFF; color:#000; -- cgit v1.2.3-54-g00ecf From 5d8d3e318411b8f640e2cd4f8f2cd97fa80d3c82 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 04:33:32 +0000 Subject: Updated pigeonthoughts theme to reflect 0.8 design requirements --- theme/pigeonthoughts/css/base.css | 158 ++++++++++++++++++++++++++++++----- theme/pigeonthoughts/css/display.css | 125 ++++++++++++++++++--------- 2 files changed, 221 insertions(+), 62 deletions(-) diff --git a/theme/pigeonthoughts/css/base.css b/theme/pigeonthoughts/css/base.css index 08427d3c8..9866e2d2c 100644 --- a/theme/pigeonthoughts/css/base.css +++ b/theme/pigeonthoughts/css/base.css @@ -12,9 +12,9 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 87.5%; background-color:#fff; } +html { font-size: 87.5%; } body { -background-color:#fff; +background-color:#FFFFFF; color:#000; font-family:sans-serif; font-size:1em; @@ -78,7 +78,8 @@ margin:0 0 18px 0; form label { font-weight:bold; } -input.checkbox { +input.checkbox, +input.radio { position:relative; top:2px; left:0; @@ -155,7 +156,8 @@ font-weight:bold; #form_invite legend, #form_notice_delete legend, #form_password_recover legend, -#form_password_change legend { +#form_password_change legend, +.form_entity_block legend { display:none; } @@ -181,13 +183,19 @@ margin-left:11px; float:left; width:90%; } - +.form_settings label.radio { +margin-top:0; +margin-right:47px; +margin-left:11px; +width:auto; +} #form_login p.form_guide, #form_register #settings_rememberme p.form_guide, #form_openid_login #settings_rememberme p.form_guide, #settings_twitter_remove p.form_guide, -#form_search ul.form_data #q { +#form_search ul.form_data #q, +#design_background-image_onoff p.form_guide { margin-left:0; } @@ -375,10 +383,10 @@ margin-bottom:1em; } #content { -width:50.009%; +width:49.009%; min-height:259px; float:left; -margin-left:18px; +padding:0 18px; } #shownotice #content { min-height:0; @@ -421,6 +429,8 @@ width:80.789%; height:46px; line-height:1.5; padding:7px 7px 16px 7px; +position:relative; +z-index:2; } #form_notice label { display:block; @@ -428,8 +438,22 @@ float:left; font-size:1.3em; margin-bottom:7px; } -#form_notice #notice_submit label { -display:none; +#form_notice label[for=notice_data-attach], +#form_notice #notice_data-attach { +position:absolute; +top:25px; +cursor:pointer; +} +#form_notice label[for=notice_data-attach] { +text-indent:-9999px; +left:394px; +width:16px; +height:16px; +} +#form_notice #notice_data-attach { +left:183px; +padding:0; +height:16px; } #form_notice .form_note { position:absolute; @@ -509,12 +533,15 @@ margin-bottom:4px; .entity_profile .entity_nickname { margin-left:11px; display:inline; -font-weight:bold; } .entity_profile .entity_nickname { margin-left:0; } - +.entity_profile .fn, +.entity_profile .nickname { +font-size:1.1em; +font-weight:bold; +} .entity_profile .entity_fn dd:before { content: "("; font-weight:normal; @@ -574,10 +601,13 @@ display:block; .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_send-a-message a, .entity_edit a, .form_user_nudge input.submit, -.entity_nudge p { +.entity_nudge p, +.form_make_admin input.submit { border:0; padding-left:20px; } @@ -640,6 +670,7 @@ list-style-type:none; float:left; margin-right:7px; margin-bottom:7px; +display:inline; } .section .entities li .photo { margin-right:0; @@ -712,12 +743,17 @@ float:left; width:96.41%; border-width:1px; border-style:solid; -padding:1.795%; margin-bottom:11px; } .notices li { list-style-type:none; } +.notices .notices { +margin-top:7px; +margin-left:5%; +width:95%; +float:left; +} #aside_primary .notice, #aside_primary .profile { @@ -773,6 +809,9 @@ float:left; width:100%; overflow:hidden; } +.notice .entry-title.ov { +overflow:visible; +} #shownotice .notice .entry-title { font-size:2.2em; } @@ -797,7 +836,7 @@ clear:left; float:left; font-size:0.95em; margin-left:59px; -width:65%; +width:60%; } #showstream .notice div.entry-content, #shownotice .notice div.entry-content { @@ -827,15 +866,12 @@ display:inline-block; text-transform:lowercase; } - .notice-options { -padding-left:2%; -float:left; -width:50%; position:relative; font-size:0.95em; -width:12.5%; +width:90px; float:right; +margin-right:11px; } .notice-options a { @@ -896,6 +932,74 @@ border:0; padding:0; } +.notice .attachment { +position:relative; +padding-left:16px; +} +#attachments .attachment { +padding-left:0; +} +.notice .attachment img { +position:absolute; +top:18px; +left:0; +z-index:99; +} +#shownotice .notice .attachment img { +position:static; +} + +#attachments { +clear:both; +float:left; +width:100%; +margin-top:18px; +} +#attachments dt { +font-weight:bold; +font-size:1.3em; +margin-bottom:4px; +} + +#attachments ol li { +margin-bottom:18px; +list-style-type:decimal; +float:left; +clear:both; +} + +#jOverlayContent, +#jOverlayContent #content, +#jOverlayContent #content_inner { +width: auto !important; +margin-bottom:0; +} +#jOverlayContent #content { +padding:11px; +min-height:auto; +} +#jOverlayContent .external span { +display:block; +margin-bottom:11px; +} +#jOverlayContent button { +position:absolute; +top:0; +right:0; +width:29px; +height:29px; +text-align:center; +font-weight:bold; +padding:0; +} +#jOverlayContent h1 { +max-width:475px; +} +#jOverlayContent #content { +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} #usergroups #new_group { float: left; @@ -1019,8 +1123,6 @@ margin-left:18px; } - - /* TOP_POSTERS */ .section tbody td { padding-right:11px; @@ -1140,6 +1242,18 @@ width:400px; margin-right:28px; } +#settings_design_color .form_data li { +width:33%; +} +#settings_design_color .form_data label { +float:none; +display:block; +} +#settings_design_color .form_data .swatch { +padding:11px; +margin-left:0; +} + .instructions ul { list-style-position:inside; } diff --git a/theme/pigeonthoughts/css/display.css b/theme/pigeonthoughts/css/display.css index af31cf78d..af562964d 100644 --- a/theme/pigeonthoughts/css/display.css +++ b/theme/pigeonthoughts/css/display.css @@ -10,7 +10,7 @@ @import url(base.css); html { -background:#fff url(../images/illustrations/illu_pigeons-01.png) no-repeat 0 100%; +background:url(../images/illustrations/illu_pigeons-01.png) no-repeat 0 100%; } body, @@ -30,10 +30,10 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; } input, textarea, select, .entity_remote_subscribe { -border-color:#aaa; +border-color:#AAAAAA; } #filter_tags ul li { -border-color:#ddd; +border-color:#DDDDDD; } .form_settings input.form_action-primary { @@ -50,35 +50,41 @@ background-color:#8F0000; input:focus, textarea:focus, select:focus, #form_notice.warning #notice_data-text { border-color:#8F0000; +box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); +-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); } input.submit, .entity_remote_subscribe { -color:#fff; +color:#FFFFFF; } a, div.notice-options input, .form_user_block input.submit, .form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit, .entity_send-a-message a, .form_user_nudge input.submit, .entity_nudge p, -.form_settings input.form_action-primary { -color:#000; +.form_settings input.form_action-primary, +.form_make_admin input.submit { +color:#000000; } .notice, .profile { -border-color:#000; +border-color:#000000; } .notice a, .profile a { -color:#fff; +color:#FFFFFF; } .notice:nth-child(3n-1), .profile:nth-child(3n-1) { -border-color:#fff; +border-color:#FFFFFF; } .notice:nth-child(3n-1) a, .profile:nth-child(3n-1) a { @@ -90,7 +96,7 @@ border-color:#7F1114; } .notice:nth-child(3n) a, .profile:nth-child(3n) a { -color:#000; +color:#000000; } .aside .section .notice, @@ -100,30 +106,30 @@ color:#000; .aside .section .notice:nth-child(3n), .aside .section .profile:nth-child(3n) { background-color:transparent; -color:#000; +color:#000000; } .aside .section { -border-color:#fff; -background-color:#fff; -color:#000; +border-color:#FFFFFF; +background-color:#FFFFFF; +color:#000000; } .aside .section:nth-child(n) { -border-color:#000; -background-color:#000; -color:#fff; +border-color:#000000; +background-color:#000000; +color:#FFFFFF; } .aside .section:nth-child(3n-1) { -border-color:#fff; -background-color:#fff; -color:#000; +border-color:#FFFFFF; +background-color:#FFFFFF; +color:#000000; } .aside .section:nth-child(3n) { background-color:#7F1114; border-color:#7F1114; -color:#000; +color:#000000; } .aside .section a { color:#7F1114; @@ -132,7 +138,7 @@ color:#7F1114; color:#7F1114; } .aside .section:nth-child(3n) a { -color:#fff; +color:#FFFFFF; } @@ -145,33 +151,43 @@ background:url(../images/illustrations/illu_pigeons-02.png) no-repeat 10% 100%; } #notice_text-count { -color:#333; +color:#333333; } #form_notice.warning #notice_text-count { -color:#000; +color:#000000; +} +#form_notice label[for=notice_data-attach] { +background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +} +#form_notice #notice_data-attach { +opacity:0; } + #form_notice.processing #notice_action-submit { -background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } #content, #site_nav_local_views a { -border-color:#fff; +border-color:#FFFFFF; } #site_nav_local_views .current a { background-color:rgba(143, 0, 0, 0.8); -color:#fff; +color:#FFFFFF; } #site_nav_local_views a { -background-color:rgba(255, 255, 255, 0.3); +background-color:rgba(255, 255, 255, 0.5); } #site_nav_local_views a:hover { -background-color:#fff; +background-color:rgba(255, 255, 255, 0.9); color:#8F0000; } +#site_nav_local_views .current a { +text-shadow: rgba(194,194,194,0.5) 1px 1px 1px; +} .error { background-color:#F7E8E8; @@ -181,7 +197,7 @@ background-color:#EFF3DC; } #anon_notice { -color:#000; +color:#000000; } @@ -204,7 +220,10 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_user_nudge input.submit, .form_user_block input.submit, .form_user_unblock input.submit, -.entity_nudge p { +.form_group_block input.submit, +.form_group_unblock input.submit, +.entity_nudge p, +.form_make_admin input.submit { background-position: 0 40%; background-repeat: no-repeat; background-color:transparent; @@ -214,7 +233,7 @@ background-color:transparent; .form_user_subscribe input.submit, .form_user_unsubscribe input.submit { background-color:#8F0000; -color:#fff; +color:#FFFFFF; } .form_user_unsubscribe input.submit, .form_group_leave input.submit, @@ -233,15 +252,22 @@ background-image:url(../../base/images/icons/twotone/green/quote.gif); background-image:url(../../base/images/icons/twotone/green/mail.gif); } .form_user_block input.submit, -.form_user_unblock input.submit { +.form_user_unblock input.submit, +.form_group_block input.submit, +.form_group_unblock input.submit { background-image:url(../../base/images/icons/twotone/green/shield.gif); } +.form_make_admin input.submit { +background-image:url(../../base/images/icons/twotone/green/admin.gif); +} /* NOTICES */ -.notices li.over { -background-color:#fcfcfc; +.notice .attachment { +background:transparent url(../../base/images/icons/twotone/green/clip-02.gif) no-repeat 0 45%; +} +#attachments .attachment { +background:none; } - .notice-options .notice_reply a, .notice-options form input.submit { background-color:transparent; @@ -263,17 +289,36 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r .notices div.notice-options { opacity:0.4; } -.notices li.hover div.entry-content, -.notices li.hover div.notice-options { +.notices li:hover div.entry-content, +.notices li:hover div.notice-options { opacity:1; } div.entry-content { -color:#333; +color:#333333; } div.notice-options a, div.notice-options input { font-family:sans-serif; } +.notices li:hover { +background-color:transparent; +} +#conversation .notices li:hover { +background-color:transparent; +} + +.notices .notices { +background-color:rgba(200, 200, 200, 0.050); +} +.notices .notices .notices { +background-color:rgba(200, 200, 200, 0.100); +} +.notices .notices .notices .notices { +background-color:rgba(200, 200, 200, 0.150); +} +.notices .notices .notices .notices .notices { +background-color:rgba(200, 200, 200, 0.300); +} /*END: NOTICES */ #new_group a { @@ -283,7 +328,7 @@ background:transparent url(../../base/images/icons/twotone/green/news.gif) no-re .pagination .nav_prev a, .pagination .nav_next a { background-repeat:no-repeat; -border-color:#000; +border-color:#000000; } .pagination .nav_prev a { background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); -- cgit v1.2.3-54-g00ecf From ca537919888e2a82365265a1f6f744db182f30f1 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 04:54:12 +0000 Subject: Using notice hover only on content area --- theme/identica/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index ad57a0f0e..09ad4c972 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -244,7 +244,7 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li:hover { +#content .notices li:hover { background-color:#FCFCFC; } #conversation .notices li:hover { -- cgit v1.2.3-54-g00ecf From 2b3746013eb5daa323b2740d30e222f0d88c2d9c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 04:55:41 +0000 Subject: Updated themes for notice hover on content area --- theme/default/css/display.css | 2 +- theme/pigeonthoughts/css/display.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 881e264da..7e8b84b4c 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -244,7 +244,7 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li:hover { +#content .notices li:hover { background-color:#FCFCFC; } #conversation .notices li:hover { diff --git a/theme/pigeonthoughts/css/display.css b/theme/pigeonthoughts/css/display.css index af562964d..01af500bf 100644 --- a/theme/pigeonthoughts/css/display.css +++ b/theme/pigeonthoughts/css/display.css @@ -300,7 +300,7 @@ div.notice-options a, div.notice-options input { font-family:sans-serif; } -.notices li:hover { +#content .notices li:hover { background-color:transparent; } #conversation .notices li:hover { -- cgit v1.2.3-54-g00ecf From dff43c03e4cdd76419a430f0942e9eacf30e13b7 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 22:16:09 -0700 Subject: Add design_id to User_group --- classes/User_group.php | 7 +++++++ classes/laconica.ini | 1 + db/laconica.sql | 1 + 3 files changed, 9 insertions(+) diff --git a/classes/User_group.php b/classes/User_group.php index 1a24124bb..8a56b9e52 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -19,6 +19,7 @@ class User_group extends Memcached_DataObject public $homepage_logo; // varchar(255) public $stream_logo; // varchar(255) public $mini_logo; // varchar(255) + public $design_id; // int(4) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP @@ -239,4 +240,10 @@ class User_group extends Memcached_DataObject } return null; } + + function getDesign() + { + return Design::staticGet('id', $this->design_id); + } + } diff --git a/classes/laconica.ini b/classes/laconica.ini index 1a650aba5..5ced15885 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -468,6 +468,7 @@ original_logo = 2 homepage_logo = 2 stream_logo = 2 mini_logo = 2 +design_id = 1 created = 142 modified = 384 diff --git a/db/laconica.sql b/db/laconica.sql index b018afec8..8d1d47d38 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -387,6 +387,7 @@ create table user_group ( homepage_logo varchar(255) comment 'homepage (profile) size logo', stream_logo varchar(255) comment 'stream-sized logo', mini_logo varchar(255) comment 'mini logo', + design_id integer comment 'id of a design' references design(id), created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', -- cgit v1.2.3-54-g00ecf From ba3a484a655f93329463465d224dfc6ae6494434 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 18 Jun 2009 00:12:53 -0700 Subject: order notices in a conversation --- actions/conversation.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actions/conversation.php b/actions/conversation.php index 20c68986c..d3fc5b6a9 100644 --- a/actions/conversation.php +++ b/actions/conversation.php @@ -217,6 +217,8 @@ class ConversationTree extends NoticeList $this->out->elementStart('ol', array('class' => 'notices')); + sort($children); + foreach ($children as $child) { $this->showNoticePlus($child); } -- cgit v1.2.3-54-g00ecf From 57274d21ba554e43c6fcd90555388a60d3de014d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 02:01:06 -0700 Subject: Group theming. --- actions/blockedfromgroup.php | 2 +- actions/designsettings.php | 517 ------------------------------------------ actions/editgroup.php | 6 +- actions/groupblock.php | 17 +- actions/grouplogo.php | 2 +- actions/groupmembers.php | 2 +- actions/showgroup.php | 5 +- lib/accountsettingsaction.php | 2 +- lib/designsettings.php | 402 ++++++++++++++++++++++++++++++++ lib/groupnav.php | 6 + lib/router.php | 4 +- 11 files changed, 427 insertions(+), 538 deletions(-) delete mode 100644 actions/designsettings.php create mode 100644 lib/designsettings.php diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php index 541ebcfd9..5c1eab354 100644 --- a/actions/blockedfromgroup.php +++ b/actions/blockedfromgroup.php @@ -41,7 +41,7 @@ if (!defined('LACONICA')) { * @link http://laconi.ca/ */ -class BlockedfromgroupAction extends Action +class BlockedfromgroupAction extends GroupDesignAction { var $page = null; diff --git a/actions/designsettings.php b/actions/designsettings.php deleted file mode 100644 index 047059e04..000000000 --- a/actions/designsettings.php +++ /dev/null @@ -1,517 +0,0 @@ -. - * - * @category Settings - * @package Laconica - * @author Sarven Capadisli - * @author Zach Copley - * @copyright 2008-2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -if (!defined('LACONICA')) { - exit(1); -} - -require_once INSTALLDIR . '/lib/accountsettingsaction.php'; -require_once INSTALLDIR . '/lib/webcolor.php'; - -class DesignsettingsAction extends AccountSettingsAction -{ - /** - * Title of the page - * - * @return string Title of the page - */ - - function title() - { - return _('Profile design'); - } - - /** - * Instructions for use - * - * @return instructions for use - */ - - function getInstructions() - { - return _('Customize the way your profile looks ' . - 'with a background image and a colour palette of your choice.'); - } - - /** - * Content area of the page - * - * Shows a form for changing the password - * - * @return void - */ - - function showContent() - { - $user = common_current_user(); - $design = $user->getDesign(); - - if (empty($design)) { - $design = $this->defaultDesign(); - } - - $this->elementStart('form', array('method' => 'post', - 'enctype' => 'multipart/form-data', - 'id' => 'form_settings_design', - 'class' => 'form_settings', - 'action' => - common_local_url('designsettings'))); - $this->elementStart('fieldset'); - $this->hidden('token', common_session_token()); - - $this->elementStart('fieldset', array('id' => - 'settings_design_background-image')); - $this->element('legend', null, _('Change background image')); - $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->element('label', array('for' => 'design_background-image_file'), - _('Upload file')); - $this->element('input', array('name' => 'design_background-image_file', - 'type' => 'file', - 'id' => 'design_background-image_file')); - $this->element('p', 'form_guide', _('You can upload your personal ' . - 'background image. The maximum file size is 2Mb.')); - $this->element('input', array('name' => 'MAX_FILE_SIZE', - 'type' => 'hidden', - 'id' => 'MAX_FILE_SIZE', - 'value' => ImageFile::maxFileSizeInt())); - $this->elementEnd('li'); - - if (!empty($design->backgroundimage)) { - - $this->elementStart('li', array('id' => 'design_background-image_onoff')); - - $this->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->element('input', $attrs); - - $this->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->element('input', $attrs); - - $this->element('label', array('for' => 'design_background-image_off', - 'class' => 'radio'), - _('Off')); - $this->element('p', 'form_guide', _('Turn background image on or off.')); - $this->elementEnd('li'); - } - - $this->elementStart('li'); - $this->checkbox('design_background-image_repeat', - _('Tile background image'), - ($design->disposition & BACKGROUND_TILE) ? true : false ); - $this->elementEnd('li'); - - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - $this->elementStart('fieldset', array('id' => 'settings_design_color')); - $this->element('legend', null, _('Change colours')); - $this->elementStart('ul', 'form_data'); - - try { - - $bgcolor = new WebColor($design->backgroundcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Background')); - $this->element('input', array('name' => 'design_background', - 'type' => 'text', - 'id' => 'swatch-1', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $bgcolor->hexValue())); - $this->elementEnd('li'); - - $ccolor = new WebColor($design->contentcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Content')); - $this->element('input', array('name' => 'design_content', - 'type' => 'text', - 'id' => 'swatch-2', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $ccolor->hexValue())); - $this->elementEnd('li'); - - $sbcolor = new WebColor($design->sidebarcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); - $this->element('input', array('name' => 'design_sidebar', - 'type' => 'text', - 'id' => 'swatch-3', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $sbcolor->hexValue())); - $this->elementEnd('li'); - - $tcolor = new WebColor($design->textcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Text')); - $this->element('input', array('name' => 'design_text', - 'type' => 'text', - 'id' => 'swatch-4', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $tcolor->hexValue())); - $this->elementEnd('li'); - - $lcolor = new WebColor($design->linkcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-5'), _('Links')); - $this->element('input', array('name' => 'design_links', - 'type' => 'text', - 'id' => 'swatch-5', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $lcolor->hexValue())); - - $this->elementEnd('li'); - - } catch (WebColorException $e) { - common_log(LOG_ERR, 'Bad color values in design ID: ' . - $design->id); - } - - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - $this->element('input', array('id' => 'settings_design_reset', - 'type' => 'reset', - 'value' => 'Reset', - 'class' => 'submit form_action-primary', - 'title' => _('Reset back to default'))); - - $this->submit('save', _('Save'), 'submit form_action-secondary', - 'save', _('Save design')); - - $this->elementEnd('fieldset'); - $this->elementEnd('form'); - } - - /** - * Handle a post - * - * Validate input and save changes. Reload the form with a success - * or error message. - * - * @return void - */ - - function handlePost() - { - // XXX: Robin's workaround for a bug in PHP where $_POST - // and $_FILE are empty in the case that the uploaded - // file is bigger than PHP is configured to handle. - - if ($_SERVER['REQUEST_METHOD'] == 'POST') { - if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { - - $msg = _('The server was unable to handle that much POST ' . - 'data (%s bytes) due to its current configuration.'); - - $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); - } - } - - // CSRF protection - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } - - if ($this->arg('save')) { - $this->saveDesign(); - } else if ($this->arg('reset')) { - $this->resetDesign(); - } else { - $this->showForm(_('Unexpected form submission.')); - } - } - - /** - * Add the Farbtastic stylesheet - * - * @return void - */ - - function showStylesheets() - { - parent::showStylesheets(); - $farbtasticStyle = - common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION); - - $this->element('link', array('rel' => 'stylesheet', - 'type' => 'text/css', - 'href' => $farbtasticStyle, - 'media' => 'screen, projection, tv')); - } - - /** - * Add the Farbtastic scripts - * - * @return void - */ - - function showScripts() - { - parent::showScripts(); - - $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); - $userDesignGo = common_path('js/userdesign.go.js'); - - $this->element('script', array('type' => 'text/javascript', - 'src' => $farbtasticPack)); - $this->element('script', array('type' => 'text/javascript', - 'src' => $userDesignGo)); - } - - /** - * Get a default user design - * - * @return Design design - */ - - function defaultDesign() - { - $defaults = common_config('site', 'design'); - - $design = new Design(); - - try { - - $color = new WebColor(); - - $color->parseColor($defaults['backgroundcolor']); - $design->backgroundcolor = $color->intValue(); - - $color->parseColor($defaults['contentcolor']); - $design->contentcolor = $color->intValue(); - - $color->parseColor($defaults['sidebarcolor']); - $design->sidebarcolor = $color->intValue(); - - $color->parseColor($defaults['textcolor']); - $design->textcolor = $color->intValue(); - - $color->parseColor($defaults['linkcolor']); - $design->linkcolor = $color->intValue(); - - $design->backgroundimage = $defaults['backgroundimage']; - - $design->disposition = $defaults['disposition']; - - } catch (WebColorException $e) { - common_log(LOG_ERR, _('Bad default color settings: ' . - $e->getMessage())); - } - - return $design; - } - - /** - * Save or update the user's design settings - * - * @return void - */ - - function saveDesign() - { - 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->showForm($e->getMessage()); - return; - } - - $onoff = $this->arg('design_background-image_onoff'); - - $on = false; - $off = false; - $tile = false; - - if ($onoff == 'on') { - $on = true; - } else { - $off = true; - } - - $repeat = $this->boolean('design_background-image_repeat'); - - if ($repeat) { - $tile = true; - } - - $user = common_current_user(); - $design = $user->getDesign(); - - if (!empty($design)) { - - $original = clone($design); - - $design->backgroundcolor = $bgcolor->intValue(); - $design->contentcolor = $ccolor->intValue(); - $design->sidebarcolor = $sbcolor->intValue(); - $design->textcolor = $tcolor->intValue(); - $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; - - $design->setDisposition($on, $off, $tile); - - $result = $design->update($original); - - if ($result === false) { - common_log_db_error($design, 'UPDATE', __FILE__); - $this->showForm(_('Couldn\'t update your design.')); - return; - } - - // update design - } else { - - $user->query('BEGIN'); - - // save new design - $design = new Design(); - - $design->backgroundcolor = $bgcolor->intValue(); - $design->contentcolor = $ccolor->intValue(); - $design->sidebarcolor = $sbcolor->intValue(); - $design->textcolor = $tcolor->intValue(); - $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; - - $design->setDisposition($on, $off, $tile); - - $id = $design->insert(); - - if (empty($id)) { - common_log_db_error($id, 'INSERT', __FILE__); - $this->showForm(_('Unable to save your design settings!')); - return; - } - - $original = clone($user); - $user->design_id = $id; - $result = $user->update($original); - - if (empty($result)) { - common_log_db_error($original, 'UPDATE', __FILE__); - $this->showForm(_('Unable to save your design settings!')); - $user->query('ROLLBACK'); - return; - } - - $user->query('COMMIT'); - - } - - // Now that we have a Design ID we can add a file to the design. - // XXX: This is an additional DB hit, but figured having the image - // associated with the Design rather than the User was worth - // it. -- Zach - - if ($_FILES['design_background-image_file']['error'] == - UPLOAD_ERR_OK) { - - $filepath = null; - - try { - $imagefile = - ImageFile::fromUpload('design_background-image_file'); - } catch (Exception $e) { - $this->showForm($e->getMessage()); - return; - } - - $filename = Design::filename($design->id, - image_type_to_extension($imagefile->type), - common_timestamp()); - - $filepath = Design::path($filename); - - move_uploaded_file($imagefile->filepath, $filepath); - - $original = clone($design); - $design->backgroundimage = $filename; - $design->setDisposition(true, false, false); - $result = $design->update($original); - - if ($result === false) { - common_log_db_error($design, 'UPDATE', __FILE__); - $this->showForm(_('Couldn\'t update your design.')); - return; - } - } - - $this->showForm(_('Design preferences saved.'), true); - } - -} diff --git a/actions/editgroup.php b/actions/editgroup.php index 29a7bce43..6aa6f8b11 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -23,6 +23,7 @@ * @package Laconica * @author Evan Prodromou * @author Sarven Capadisli + * @author Zach Copley * @copyright 2008-2009 Control Yourself, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ @@ -40,14 +41,15 @@ if (!defined('LACONICA')) { * @category Group * @package Laconica * @author Evan Prodromou + * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ */ -class EditgroupAction extends Action +class EditgroupAction extends GroupDesignAction { + var $msg; - var $group = null; function title() { diff --git a/actions/groupblock.php b/actions/groupblock.php index 28685b1d5..93662da79 100644 --- a/actions/groupblock.php +++ b/actions/groupblock.php @@ -151,19 +151,17 @@ class GroupblockAction extends Action function areYouSureForm() { $id = $this->profile->id; - $this->elementStart('form', array('id' => 'block-' . $id, - 'method' => 'post', - 'class' => 'form_settings form_entity_block', - 'action' => common_local_url('groupblock'))); - $this->elementStart('fieldset'); - $this->hidden('token', common_session_token()); - $this->element('legend', null, _('Block user')); $this->element('p', null, sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '. 'They will be removed from the group, unable to post, and '. 'unable to subscribe to the group in the future.'), $this->profile->getBestName(), $this->group->getBestName())); + $this->elementStart('form', array('id' => 'block-' . $id, + 'method' => 'post', + 'class' => 'block', + 'action' => common_local_url('groupblock'))); + $this->hidden('token', common_session_token()); $this->hidden('blockto-' . $this->profile->id, $this->profile->id, 'blockto'); @@ -175,9 +173,8 @@ class GroupblockAction extends Action $this->hidden($k, $v); } } - $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); - $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); - $this->elementEnd('fieldset'); + $this->submit('no', _('No')); + $this->submit('yes', _('Yes')); $this->elementEnd('form'); } diff --git a/actions/grouplogo.php b/actions/grouplogo.php index fe6127da2..8f6158dac 100644 --- a/actions/grouplogo.php +++ b/actions/grouplogo.php @@ -50,7 +50,7 @@ define('MAX_ORIGINAL', 480); * @link http://laconi.ca/ */ -class GrouplogoAction extends Action +class GrouplogoAction extends GroupDesignAction { var $mode = null; var $imagefile = null; diff --git a/actions/groupmembers.php b/actions/groupmembers.php index abfad3f0d..d132cdf96 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php'; * @link http://laconi.ca/ */ -class GroupmembersAction extends Action +class GroupmembersAction extends GroupDesignAction { var $page = null; diff --git a/actions/showgroup.php b/actions/showgroup.php index 357f579d8..b6a0f4844 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -47,10 +47,9 @@ define('MEMBERS_PER_SECTION', 27); * @link http://laconi.ca/ */ -class ShowgroupAction extends Action +class ShowgroupAction extends GroupDesignAction { - /** group we're viewing. */ - var $group = null; + /** page we're viewing. */ var $page = null; diff --git a/lib/accountsettingsaction.php b/lib/accountsettingsaction.php index 86800d2a3..4ab50abce 100644 --- a/lib/accountsettingsaction.php +++ b/lib/accountsettingsaction.php @@ -115,7 +115,7 @@ class AccountSettingsNav extends Widget 'openidsettings' => array(_('OpenID'), _('Add or remove OpenIDs')), - 'designsettings' => + 'userdesignsettings' => array(_('Design'), _('Design your profile')), 'othersettings' => diff --git a/lib/designsettings.php b/lib/designsettings.php new file mode 100644 index 000000000..6aa6bb2f1 --- /dev/null +++ b/lib/designsettings.php @@ -0,0 +1,402 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/webcolor.php'; + +class DesignSettingsAction extends AccountSettingsAction +{ + + var $submitaction = null; + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Profile design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); + } + + function showDesignForm($design) + { + + $this->elementStart('form', array('method' => 'post', + 'enctype' => 'multipart/form-data', + 'id' => 'form_settings_design', + 'class' => 'form_settings', + 'action' => $this->submitaction)); + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + + $this->elementStart('fieldset', array('id' => + 'settings_design_background-image')); + $this->element('legend', null, _('Change background image')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->element('label', array('for' => 'design_background-image_file'), + _('Upload file')); + $this->element('input', array('name' => 'design_background-image_file', + 'type' => 'file', + 'id' => 'design_background-image_file')); + $this->element('p', 'form_guide', _('You can upload your personal ' . + 'background image. The maximum file size is 2Mb.')); + $this->element('input', array('name' => 'MAX_FILE_SIZE', + 'type' => 'hidden', + 'id' => 'MAX_FILE_SIZE', + 'value' => ImageFile::maxFileSizeInt())); + $this->elementEnd('li'); + + if (!empty($design->backgroundimage)) { + + $this->elementStart('li', array('id' => 'design_background-image_onoff')); + + $this->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->element('input', $attrs); + + $this->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->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), + _('Off')); + $this->element('p', 'form_guide', _('Turn background image on or off.')); + $this->elementEnd('li'); + } + + $this->elementStart('li'); + $this->checkbox('design_background-image_repeat', + _('Tile background image'), + ($design->disposition & BACKGROUND_TILE) ? true : false ); + $this->elementEnd('li'); + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->elementStart('fieldset', array('id' => 'settings_design_color')); + $this->element('legend', null, _('Change colours')); + $this->elementStart('ul', 'form_data'); + + try { + + $bgcolor = new WebColor($design->backgroundcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $bgcolor->hexValue())); + $this->elementEnd('li'); + + $ccolor = new WebColor($design->contentcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $ccolor->hexValue())); + $this->elementEnd('li'); + + $sbcolor = new WebColor($design->sidebarcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $sbcolor->hexValue())); + $this->elementEnd('li'); + + $tcolor = new WebColor($design->textcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $tcolor->hexValue())); + $this->elementEnd('li'); + + $lcolor = new WebColor($design->linkcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-5'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-5', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $lcolor->hexValue())); + + $this->elementEnd('li'); + + } catch (WebColorException $e) { + common_log(LOG_ERR, 'Bad color values in design ID: ' . + $design->id); + } + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->element('input', array('id' => 'settings_design_reset', + 'type' => 'reset', + 'value' => 'Reset', + 'class' => 'submit form_action-primary', + 'title' => _('Reset back to default'))); + + $this->submit('save', _('Save'), 'submit form_action-secondary', + 'save', _('Save design')); + + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + + /** + * Handle a post + * + * Validate input and save changes. Reload the form with a success + * or error message. + * + * @return void + */ + + function handlePost() + { + // XXX: Robin's workaround for a bug in PHP where $_POST + // and $_FILE are empty in the case that the uploaded + // file is bigger than PHP is configured to handle. + + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { + + $msg = _('The server was unable to handle that much POST ' . + 'data (%s bytes) due to its current configuration.'); + + $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); + } + } + + // CSRF protection + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } + + if ($this->arg('save')) { + $this->saveDesign(); + } else if ($this->arg('reset')) { + $this->resetDesign(); + } else { + $this->showForm(_('Unexpected form submission.')); + } + } + + /** + * Add the Farbtastic stylesheet + * + * @return void + */ + + function showStylesheets() + { + parent::showStylesheets(); + $farbtasticStyle = + common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION); + + $this->element('link', array('rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => $farbtasticStyle, + 'media' => 'screen, projection, tv')); + } + + /** + * Add the Farbtastic scripts + * + * @return void + */ + + function showScripts() + { + parent::showScripts(); + + $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); + $userDesignGo = common_path('js/userdesign.go.js'); + + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticPack)); + $this->element('script', array('type' => 'text/javascript', + 'src' => $userDesignGo)); + } + + /** + * Get a default user design + * + * @return Design design + */ + + function defaultDesign() + { + $defaults = common_config('site', 'design'); + + $design = new Design(); + + try { + + $color = new WebColor(); + + $color->parseColor($defaults['backgroundcolor']); + $design->backgroundcolor = $color->intValue(); + + $color->parseColor($defaults['contentcolor']); + $design->contentcolor = $color->intValue(); + + $color->parseColor($defaults['sidebarcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['textcolor']); + $design->textcolor = $color->intValue(); + + $color->parseColor($defaults['linkcolor']); + $design->linkcolor = $color->intValue(); + + $design->backgroundimage = $defaults['backgroundimage']; + + $design->disposition = $defaults['disposition']; + + } catch (WebColorException $e) { + common_log(LOG_ERR, _('Bad default color settings: ' . + $e->getMessage())); + } + + return $design; + } + + function saveBackgroundImage($design) { + + // Now that we have a Design ID we can add a file to the design. + // XXX: This is an additional DB hit, but figured having the image + // associated with the Design rather than the User was worth + // it. -- Zach + + if ($_FILES['design_background-image_file']['error'] == + UPLOAD_ERR_OK) { + + $filepath = null; + + try { + $imagefile = + ImageFile::fromUpload('design_background-image_file'); + } catch (Exception $e) { + $this->showForm($e->getMessage()); + return; + } + + $filename = Design::filename($design->id, + image_type_to_extension($imagefile->type), + common_timestamp()); + + $filepath = Design::path($filename); + + move_uploaded_file($imagefile->filepath, $filepath); + + $original = clone($design); + $design->backgroundimage = $filename; + $design->setDisposition(true, false, false); + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + } + } + +} diff --git a/lib/groupnav.php b/lib/groupnav.php index 194247982..9e530c447 100644 --- a/lib/groupnav.php +++ b/lib/groupnav.php @@ -113,6 +113,12 @@ class GroupNav extends Widget sprintf(_('Add or edit %s logo'), $nickname), $action_name == 'grouplogo', 'nav_group_logo'); + $this->out->menuItem(common_local_url('groupdesignsettings', array('nickname' => + $nickname)), + _('Design'), + sprintf(_('Add or edit %s design'), $nickname), + $action_name == 'groupdesignsettings', + 'nav_group_design'); } $this->out->elementEnd('ul'); } diff --git a/lib/router.php b/lib/router.php index 8b6f63618..1f39c60dc 100644 --- a/lib/router.php +++ b/lib/router.php @@ -132,7 +132,7 @@ class Router // settings foreach (array('profile', 'avatar', 'password', 'openid', 'im', - 'email', 'sms', 'twitter', 'design', 'other') as $s) { + 'email', 'sms', 'twitter', 'userdesign', 'other') as $s) { $m->connect('settings/'.$s, array('action' => $s.'settings')); } @@ -223,7 +223,7 @@ class Router array('nickname' => '[a-zA-Z0-9]+')); } - foreach (array('members', 'logo', 'rss') as $n) { + foreach (array('members', 'logo', 'rss', 'designsettings') as $n) { $m->connect('group/:nickname/'.$n, array('action' => 'group'.$n), array('nickname' => '[a-zA-Z0-9]+')); -- cgit v1.2.3-54-g00ecf From 3f032bc36e2c624a895c584479c8f423e62bba73 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 02:16:39 -0700 Subject: Left out some new user and group theming file in the previous commit --- actions/groupdesignsettings.php | 330 ++++++++++++++++++++++++++++++++++++++++ actions/userdesignsettings.php | 208 +++++++++++++++++++++++++ lib/groupdesignaction.php | 87 +++++++++++ 3 files changed, 625 insertions(+) create mode 100644 actions/groupdesignsettings.php create mode 100644 actions/userdesignsettings.php create mode 100644 lib/groupdesignaction.php diff --git a/actions/groupdesignsettings.php b/actions/groupdesignsettings.php new file mode 100644 index 000000000..7270bc8f7 --- /dev/null +++ b/actions/groupdesignsettings.php @@ -0,0 +1,330 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/designsettings.php'; + +class GroupDesignSettingsAction extends DesignSettingsAction +{ + var $group = null; + + /** + * Prepare to run + */ + + function prepare($args) + { + parent::prepare($args); + + if (!common_config('inboxes','enabled')) { + $this->serverError(_('Inboxes must be enabled for groups to work')); + return false; + } + + if (!common_logged_in()) { + $this->clientError(_('You must be logged in to edit a group.')); + return false; + } + + $nickname_arg = $this->trimmed('nickname'); + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + $args = array('nickname' => $nickname); + common_redirect(common_local_url('groupdesignsettings', $args), 301); + return false; + } + + if (!$nickname) { + $this->clientError(_('No nickname'), 404); + return false; + } + + $groupid = $this->trimmed('groupid'); + + if ($groupid) { + $this->group = User_group::staticGet('id', $groupid); + } else { + $this->group = User_group::staticGet('nickname', $nickname); + } + + if (!$this->group) { + $this->clientError(_('No such group'), 404); + return false; + } + + $cur = common_current_user(); + + if (!$cur->isAdmin($this->group)) { + $this->clientError(_('You must be an admin to edit the group'), 403); + return false; + } + + $this->submitaction = common_local_url('groupdesignsettings', + array('nickname' => $this->group->nickname)); + + return true; + } + + /** + * A design for this action + * + * if the group attribute has been set, returns that group's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + + if (empty($this->group)) { + return null; + } + + return $this->group->getDesign(); + } + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Group design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your group looks ' . + 'with a background image and a colour palette of your choice.'); + } + + /** + * Override to show group nav stuff + * + * @return nothing + */ + + function showLocalNav() + { + $nav = new GroupNav($this, $this->group); + $nav->show(); + } + + /** + * Get the design we want to edit + * + * @return Design + */ + + function getWorkingDesign() { + + $design = null; + + if (isset($this->group)) { + $design = $this->group->getDesign(); + } + + if (empty($design)) { + $design = $this->defaultDesign(); + } + + return $design; + } + + /** + * Content area of the page + * + * Shows a form for changing the design + * + * @return void + */ + + function showContent() + { + $this->showDesignForm($this->getWorkingDesign()); + } + + /** + * Save or update the group's design settings + * + * @return void + */ + + function saveDesign() + { + 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->showForm($e->getMessage()); + return; + } + + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } + + $design = $this->group->getDesign(); + + if (!empty($design)) { + + // update design + + $original = clone($design); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + } else { + + $this->group->query('BEGIN'); + + // save new design + + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($this->group); + $this->group->design_id = $id; + $result = $this->group->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $this->group->query('ROLLBACK'); + return; + } + + $this->group->query('COMMIT'); + + } + + $this->saveBackgroundImage($design); + + $this->showForm(_('Design preferences saved.'), true); + } + + /** + * Handle input and output a page (overrided) + * + * @param array $args $_REQUEST arguments + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return; + } else if (!common_is_real_login()) { + // Cookie theft means that automatic logins can't + // change important settings or see private info, and + // _all_ our settings are important + common_set_returnto($this->selfUrl()); + $user = common_current_user(); + if ($user->hasOpenID()) { + common_redirect(common_local_url('openidlogin'), 303); + } else { + common_redirect(common_local_url('login'), 303); + } + } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->handlePost(); + } else { + $this->showForm(); + } + } + +} diff --git a/actions/userdesignsettings.php b/actions/userdesignsettings.php new file mode 100644 index 000000000..d6088aa9d --- /dev/null +++ b/actions/userdesignsettings.php @@ -0,0 +1,208 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/designsettings.php'; + +class UserDesignSettingsAction extends DesignSettingsAction +{ + + function prepare($args) + { + parent::prepare($args); + $this->submitaction = common_local_url('userdesignsettings'); + return true; + } + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Profile design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); + } + + /** + * Get the design we want to edit + * + * @return Design + */ + + function getWorkingDesign() { + + $user = common_current_user(); + $design = $user->getDesign(); + + if (empty($design)) { + $design = $this->defaultDesign(); + } + + return $design; + } + + /** + * Content area of the page + * + * Shows a form for changing the design + * + * @return void + */ + + function showContent() + { + $this->showDesignForm($this->getWorkingDesign()); + } + + /** + * Save or update the user's design settings + * + * @return void + */ + + function saveDesign() + { + 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->showForm($e->getMessage()); + return; + } + + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } + + $user = common_current_user(); + $design = $user->getDesign(); + + if (!empty($design)) { + + $original = clone($design); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + // update design + } else { + + $user->query('BEGIN'); + + // save new design + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($user); + $user->design_id = $id; + $result = $user->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $user->query('ROLLBACK'); + return; + } + + $user->query('COMMIT'); + + } + + $this->saveBackgroundImage($design); + + $this->showForm(_('Design preferences saved.'), true); + } +} diff --git a/lib/groupdesignaction.php b/lib/groupdesignaction.php new file mode 100644 index 000000000..bc95921f1 --- /dev/null +++ b/lib/groupdesignaction.php @@ -0,0 +1,87 @@ +. + * + * @category Action + * @package Laconica + * @author Zach Copley + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Base class for actions that use a group's design + * + * Pages related to groups can be themed with a design. + * This superclass returns that design. + * + * @category Action + * @package Laconica + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ +class GroupDesignAction extends Action { + + /** The group in question */ + var $group = null; + + /** + * Show the groups's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + + if (!empty($design)) { + $design->showCSS($this); + } + } + + /** + * A design for this action + * + * if the group attribute has been set, returns that group's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + + if (empty($this->group)) { + return null; + } + + return $this->group->getDesign(); + } + +} -- cgit v1.2.3-54-g00ecf From 65b4cfbb54f5b44820dd02bb9c3c2ca98dbbd321 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 18 Jun 2009 06:02:12 -0400 Subject: Display more oembed info in attachment popup. --- lib/attachmentlist.php | 36 ++++++++++++++++++++++++++++++++++++ theme/base/css/display.css | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 45e4fa319..a781c3092 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -244,6 +244,42 @@ class AttachmentListItem extends Widget class Attachment extends AttachmentListItem { + function showLink() { + $this->out->elementStart('a', $this->linkAttr()); + $this->out->element('span', null, $this->linkTitle()); + $this->showRepresentation(); + $this->out->elementEnd('a'); + + if (empty($this->oembed->author_name) && empty($this->oembed->provider)) { + return; + } + + $this->out->elementStart('dl', 'oembed_info'); + + if (!empty($this->oembed->author_name)) { + $this->out->element('dt', null, _('Author:')); + + $this->out->elementStart('dd'); + if (empty($this->oembed->author_url)) { + $this->out->text($this->oembed->author_name); + } else { + $this->out->element('a', array('href' => $this->oembed->author_url), $this->oembed->author_name); + } + $this->out->elementEnd('dd'); + } + if (!empty($this->oembed->provider)) { + $this->out->element('dt', null, _('Provider:')); + $this->out->elementStart('dd'); + if (empty($this->oembed->provider_url)) { + $this->out->text($this->oembed->provider); + } else { + $this->out->element('a', array('href' => $this->oembed->provider_url), $this->oembed->provider); + } + $this->out->elementEnd('dd'); + } + $this->out->elementEnd('dl'); + } + function show() { $this->showNoticeAttachment(); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 9e35d015d..dd787f5e2 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1276,3 +1276,9 @@ display:none; .guide { clear:both; } + +dl.oembed_info dt, +dl.oembed_info dd { +display: inline; +} + -- cgit v1.2.3-54-g00ecf From 65457e73bfc8fe04ad57acce7800cd7640f30e7e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 10:49:45 -0700 Subject: Config option for bidirectional Twitter bridge --- config.php.sample | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.php.sample b/config.php.sample index 7649c5262..529164108 100644 --- a/config.php.sample +++ b/config.php.sample @@ -153,6 +153,9 @@ $config['sphinx']['port'] = 3312; // Twitter integration source attribute. Note: default is Laconica // $config['integration']['source'] = 'Laconica'; +// Enable bidirectional Twitter bridge +// $config['twitterbridge']['enabled'] = true; + // Edit throttling. Off by default. If turned on, you can only post 20 notices // every 10 minutes. Admins may want to play with the settings to minimize inconvenience for // real users without getting uncontrollable floods from spammers or runaway bots. -- cgit v1.2.3-54-g00ecf From 3f54840b51d5565fdeb7057661ff730bc0e41833 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 18 Jun 2009 11:45:48 -0700 Subject: Only show twitter msgs in your own inbox --- actions/all.php | 8 ++++++- actions/allrss.php | 8 +++++++ actions/facebookhome.php | 58 ++++++++++++++++++++++-------------------------- classes/Notice.php | 2 ++ classes/Notice_inbox.php | 13 +++++++---- classes/User.php | 29 +++++++++++++++++++++++- 6 files changed, 81 insertions(+), 37 deletions(-) diff --git a/actions/all.php b/actions/all.php index 03179a246..80fc9d54b 100644 --- a/actions/all.php +++ b/actions/all.php @@ -98,7 +98,13 @@ class AllAction extends ProfileAction function showContent() { - $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + $cur = common_current_user(); + + if (!empty($cur) && $cur->id == $this->user->id) { + $notice = $this->user->noticeInbox(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + } else { + $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + } $nl = new NoticeList($notice, $this); diff --git a/actions/allrss.php b/actions/allrss.php index 45f3946a6..88a4745c9 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -81,6 +81,14 @@ class AllrssAction extends Rss10Action */ function getNotices($limit=0) { + $cur = common_current_user(); + + if (!empty($cur) && $cur->id == $user->id) { + $notice = $this->user->noticeInbox(0, $limit); + } else { + $notice = $this->user->noticesWithFriends(0, $limit); + } + $user = $this->user; $notice = $user->noticesWithFriends(0, $limit); $notices = array(); diff --git a/actions/facebookhome.php b/actions/facebookhome.php index 00b35ef68..f74b786d1 100644 --- a/actions/facebookhome.php +++ b/actions/facebookhome.php @@ -21,29 +21,28 @@ if (!defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/lib/facebookaction.php'; - class FacebookhomeAction extends FacebookAction { var $page = null; - + function prepare($argarray) - { + { parent::prepare($argarray); - + $this->page = $this->trimmed('page'); - + if (!$this->page) { $this->page = 1; } - + return true; } function handle($args) { - parent::handle($args); - + parent::handle($args); + // If the user has opted not to initially allow the app to have // Facebook status update permission, store that preference. Only // promt the user the first time she uses the app @@ -73,7 +72,7 @@ class FacebookhomeAction extends FacebookAction $this->updateProfileBox($notice); } - if ($this->arg('status_submit') == 'Send') { + if ($this->arg('status_submit') == 'Send') { $this->saveNewNotice(); } @@ -81,7 +80,7 @@ class FacebookhomeAction extends FacebookAction // Facebook status update permission? Then show the main page // of the app $this->showPage(); - + } else { // User hasn't authenticated yet, prompt for creds @@ -89,12 +88,12 @@ class FacebookhomeAction extends FacebookAction } } - + function login() { - + $this->showStylesheets(); - + $nickname = common_canonical_nickname($this->trimmed('nickname')); $password = $this->arg('password'); @@ -141,13 +140,12 @@ class FacebookhomeAction extends FacebookAction $this->facebook->api_client->data_setUserPreference( FACEBOOK_PROMPTED_UPDATE_PREF, 'false'); } - function showNoticeForm() { $post_action = "$this->app_uri/index.php"; - - $notice_form = new FacebookNoticeForm($this, $post_action, null, + + $notice_form = new FacebookNoticeForm($this, $post_action, null, $post_action, $this->user); $notice_form->show(); } @@ -163,9 +161,8 @@ class FacebookhomeAction extends FacebookAction function showContent() { - $notice = $this->user->noticesWithFriends(($this->page-1) * - NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - + $notice = $this->user->noticeInbox(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + $nl = new NoticeList($notice, $this); $cnt = $nl->show(); @@ -176,7 +173,7 @@ class FacebookhomeAction extends FacebookAction function showNoticeList($notice) { - + $nl = new NoticeList($notice, $this); return $nl->show(); } @@ -201,16 +198,16 @@ class FacebookhomeAction extends FacebookAction $this->elementStart('ul', array('id' => 'fb-permissions-list')); $this->elementStart('li', array('id' => 'fb-permissions-item')); - + $next = urlencode("$this->app_uri/index.php"); $api_key = common_config('facebook', 'apikey'); - + $auth_url = 'http://www.facebook.com/authorize.php?api_key=' . - $api_key . '&v=1.0&ext_perm=status_update&next=' . $next . + $api_key . '&v=1.0&ext_perm=status_update&next=' . $next . '&next_cancel=' . $next . '&submit=skip'; - + $this->elementStart('span', array('class' => 'facebook-button')); - $this->element('a', array('href' => $auth_url), + $this->element('a', array('href' => $auth_url), sprintf(_('Okay, do it!'), $this->app_name)); $this->elementEnd('span'); @@ -225,7 +222,7 @@ class FacebookhomeAction extends FacebookAction $this->elementEnd('div'); } - + /** * Generate pagination links * @@ -239,11 +236,11 @@ class FacebookhomeAction extends FacebookAction */ function pagination($have_before, $have_after, $page, $action, $args=null) { - + // Does a little before-after block for next/prev page - + // XXX: Fix so this uses common_local_url() if possible. - + if ($have_before || $have_after) { $this->elementStart('div', array('class' => 'pagination')); $this->elementStart('dl', null); @@ -254,7 +251,7 @@ class FacebookhomeAction extends FacebookAction if ($have_before) { $pargs = array('page' => $page-1); $newargs = $args ? array_merge($args, $pargs) : $pargs; - $this->elementStart('li', array('class' => 'nav_prev')); + $this->elementStart('li', array('class' => 'nav_prev')); $this->element('a', array('href' => "$action?page=$newargs[page]", 'rel' => 'prev'), _('After')); $this->elementEnd('li'); @@ -274,6 +271,5 @@ class FacebookhomeAction extends FacebookAction $this->elementEnd('div'); } } - } diff --git a/classes/Notice.php b/classes/Notice.php index e621805df..93a1a1a4d 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -406,8 +406,10 @@ class Notice extends Memcached_DataObject while ($user->fetch()) { $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id)); + $cache->delete(common_cache_key('notice_inbox:by_user_own:'.$user->id)); if ($blowLast) { $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id.';last')); + $cache->delete(common_cache_key('notice_inbox:by_user_own:'.$user->id.';last')); } } $user->free(); diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 367a35f1f..4ca2e9ae3 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -47,20 +47,25 @@ class Notice_inbox extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function stream($user_id, $offset, $limit, $since_id, $max_id, $since) + function stream($user_id, $offset, $limit, $since_id, $max_id, $since, $own=false) { return Notice::stream(array('Notice_inbox', '_streamDirect'), - array($user_id), - 'notice_inbox:by_user:'.$user_id, + array($user_id, $own), + ($own) ? 'notice_inbox:by_user:'.$user_id : + 'notice_inbox:by_user_own:'.$user_id, $offset, $limit, $since_id, $max_id, $since); } - function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since) + function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id, $since) { $inbox = new Notice_inbox(); $inbox->user_id = $user_id; + if (!$own) { + $inbox->whereAdd('source != ' . NOTICE_INBOX_SOURCE_GATEWAY); + } + if ($since_id != 0) { $inbox->whereAdd('notice_id > ' . $since_id); } diff --git a/classes/User.php b/classes/User.php index c7eede94e..e8c8c5a75 100644 --- a/classes/User.php +++ b/classes/User.php @@ -437,6 +437,33 @@ class User extends Memcached_DataObject // Complicated code, depending on whether we support inboxes yet // XXX: make this go away when inboxes become mandatory + if ($enabled === false || + ($enabled == 'transitional' && $this->inboxed == 0)) { + $qry = + 'SELECT notice.* ' . + 'FROM notice JOIN subscription ON notice.profile_id = subscription.subscribed ' . + 'WHERE subscription.subscriber = %d ' . + 'AND notice.is_local != ' . NOTICE_GATEWAY; + return Notice::getStream(sprintf($qry, $this->id), + 'user:notices_with_friends:' . $this->id, + $offset, $limit, $since_id, $before_id, + $order, $since); + } else if ($enabled === true || + ($enabled == 'transitional' && $this->inboxed == 1)) { + + $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, false); + + return Notice::getStreamByIds($ids); + } + } + + function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + { + $enabled = common_config('inboxes', 'enabled'); + + // Complicated code, depending on whether we support inboxes yet + // XXX: make this go away when inboxes become mandatory + if ($enabled === false || ($enabled == 'transitional' && $this->inboxed == 0)) { $qry = @@ -450,7 +477,7 @@ class User extends Memcached_DataObject } else if ($enabled === true || ($enabled == 'transitional' && $this->inboxed == 1)) { - $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); + $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, true); return Notice::getStreamByIds($ids); } -- cgit v1.2.3-54-g00ecf From 730c173238841cdc4d52bb074e53d4a74f7871bf Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 18:48:19 +0000 Subject: Updated markup and CSS for attachment_view --- lib/attachmentlist.php | 62 ++++++++++++++++++++++++++-------------------- theme/base/css/display.css | 22 +++++++++++----- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index c80c0c418..7bd441bf4 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -210,7 +210,7 @@ class AttachmentListItem extends Widget function showRepresentation() { $thumbnail = File_thumbnail::staticGet('file_id', $this->attachment->id); if (!empty($thumbnail)) { - $this->out->element('img', array('alt' => 'nothing to say', 'src' => $thumbnail->url, 'width' => $thumbnail->width, 'height' => $thumbnail->height)); + $this->out->element('img', array('alt' => '', 'src' => $thumbnail->url, 'width' => $thumbnail->width, 'height' => $thumbnail->height)); } } @@ -244,39 +244,47 @@ class AttachmentListItem extends Widget class Attachment extends AttachmentListItem { function showLink() { + $this->out->elementStart('div', array('id' => 'attachment_view', + 'class' => 'hentry')); + $this->out->elementStart('div', 'entry-title'); $this->out->elementStart('a', $this->linkAttr()); $this->out->element('span', null, $this->linkTitle()); $this->showRepresentation(); $this->out->elementEnd('a'); - - if (empty($this->oembed->author_name) && empty($this->oembed->provider)) { - return; - } - - $this->out->elementStart('dl', 'oembed_info'); - - if (!empty($this->oembed->author_name)) { - $this->out->element('dt', null, _('Author:')); - - $this->out->elementStart('dd'); - if (empty($this->oembed->author_url)) { - $this->out->text($this->oembed->author_name); - } else { - $this->out->element('a', array('href' => $this->oembed->author_url), $this->oembed->author_name); + $this->out->elementEnd('div'); + + if ($this->oembed->author_name || $this->oembed->provider) { + $this->out->elementStart('div', array('id' => 'oembed_info', + 'class' => 'entry-content')); + if (!empty($this->oembed->author_name)) { + $this->out->elementStart('dl', 'vcard author'); + $this->out->element('dt', null, _('Author')); + $this->out->elementStart('dd', 'fn'); + if (empty($this->oembed->author_url)) { + $this->out->text($this->oembed->author_name); + } else { + $this->out->element('a', array('href' => $this->oembed->author_url, + 'class' => 'url'), $this->oembed->author_name); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); } - $this->out->elementEnd('dd'); - } - if (!empty($this->oembed->provider)) { - $this->out->element('dt', null, _('Provider:')); - $this->out->elementStart('dd'); - if (empty($this->oembed->provider_url)) { - $this->out->text($this->oembed->provider); - } else { - $this->out->element('a', array('href' => $this->oembed->provider_url), $this->oembed->provider); + if (!empty($this->oembed->provider)) { + $this->out->elementStart('dl', 'vcard'); + $this->out->element('dt', null, _('Provider')); + $this->out->elementStart('dd', 'fn'); + if (empty($this->oembed->provider_url)) { + $this->out->text($this->oembed->provider); + } else { + $this->out->element('a', array('href' => $this->oembed->provider_url, + 'class' => 'url'), $this->oembed->provider); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); } - $this->out->elementEnd('dd'); + $this->out->elementEnd('div'); } - $this->out->elementEnd('dl'); + $this->out->elementEnd('div'); } function show() { diff --git a/theme/base/css/display.css b/theme/base/css/display.css index daf5ada1c..8957a5b40 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1018,6 +1018,22 @@ border-radius:7px; -webkit-border-radius:7px; } +#attachment_view #oembed_info { +margin-top:11px; +} +#attachment_view #oembed_info dt, +#attachment_view #oembed_info dd { +float:left; +} +#attachment_view #oembed_info dt { +clear:left; +margin-right:11px; +font-weight:bold; +} +#attachment_view #oembed_info dt:after { +content: ":"; +} + #usergroups #new_group { float: left; margin-right: 2em; @@ -1284,9 +1300,3 @@ display:none; .guide { clear:both; } - -dl.oembed_info dt, -dl.oembed_info dd { -display: inline; -} - -- cgit v1.2.3-54-g00ecf From 23d6d19e75f273bf6e72fbcbbf8e6789f77d07ff Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 19:03:44 +0000 Subject: Better attachment view check --- lib/attachmentlist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 7bd441bf4..a2446a886 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -253,7 +253,7 @@ class Attachment extends AttachmentListItem $this->out->elementEnd('a'); $this->out->elementEnd('div'); - if ($this->oembed->author_name || $this->oembed->provider) { + if (!empty($this->oembed->author_name) || !empty($this->oembed->provider)) { $this->out->elementStart('div', array('id' => 'oembed_info', 'class' => 'entry-content')); if (!empty($this->oembed->author_name)) { -- cgit v1.2.3-54-g00ecf From e0fb15c185f4ca81743937c27557c9402ba59071 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 19:19:19 +0000 Subject: Make sure we have a DB connection before setting its charset --- classes/Memcached_DataObject.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 33ac70dd0..f945e94ff 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -242,13 +242,16 @@ class Memcached_DataObject extends DB_DataObject if (common_config('db', 'type') == 'mysql' && common_config('db', 'utf8')) { $conn = $DB->connection; - if ($DB instanceof DB_mysqli) { - mysqli_set_charset($conn, 'utf8'); - } else if ($DB instanceof DB_mysql) { - mysql_set_charset('utf8', $conn); + if (!empty($conn)) { + if ($DB instanceof DB_mysqli) { + mysqli_set_charset($conn, 'utf8'); + } else if ($DB instanceof DB_mysql) { + mysql_set_charset('utf8', $conn); + } } } } return $result; } + } -- cgit v1.2.3-54-g00ecf From 597df6a2345ad61e7e0f21277d97866bdb2116a4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 18 Jun 2009 16:19:26 -0700 Subject: better calculation of path --- lib/common.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index eb8a2b873..702da8235 100644 --- a/lib/common.php +++ b/lib/common.php @@ -55,13 +55,25 @@ require_once(INSTALLDIR.'/lib/language.php'); require_once(INSTALLDIR.'/lib/event.php'); require_once(INSTALLDIR.'/lib/plugin.php'); +function _sn_to_path($sn) +{ + $past_root = substr($sn, 1); + $last_slash = strrpos($past_root, '/'); + if ($last_slash > 0) { + $p = substr($past_root, 0, $last_slash); + } else { + $p = ''; + } + return $p; +} + // try to figure out where we are $_server = array_key_exists('SERVER_NAME', $_SERVER) ? strtolower($_SERVER['SERVER_NAME']) : null; $_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? - substr($_SERVER['SCRIPT_NAME'], 1, strrpos($_SERVER['SCRIPT_NAME'], '/') - 1) : + _sn_to_path($_SERVER['SCRIPT_NAME']) : null; // default configuration, overwritten in config.php -- cgit v1.2.3-54-g00ecf From 5d3e47e501bffb30d90d648263c78ef22b047a40 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 18 Jun 2009 16:21:03 -0700 Subject: remove path from install; better autodetection now --- install.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/install.php b/install.php index 133f2b30f..7ceae4460 100644 --- a/install.php +++ b/install.php @@ -36,7 +36,7 @@ function main() function checkPrereqs() { $pass = true; - + if (file_exists(INSTALLDIR.'/config.php')) { ?>

Config file "config.php" already exists.

@@ -116,11 +115,6 @@ function showForm() disable

Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.

-
  • - - -

    Site path, following the "/" after the domain name in the URL. Empty is fine. Field should be filled automatically.

    -
  • @@ -167,7 +161,6 @@ function handlePost() $username = $_POST['username']; $password = $_POST['password']; $sitename = $_POST['sitename']; - $path = $_POST['path']; $fancy = !empty($_POST['fancy']); ?>
    @@ -176,7 +169,7 @@ function handlePost()
      "); return $res; -- cgit v1.2.3-54-g00ecf From e506f82cdf8d88186c425a3f58e15b5126fdb248 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 16:51:06 -0700 Subject: Better avatar handling - pull in any missing Twitter avatars --- config.php.sample | 3 +++ scripts/twitterstatusfetcher.php | 23 ++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/config.php.sample b/config.php.sample index 529164108..d42bac9a6 100644 --- a/config.php.sample +++ b/config.php.sample @@ -154,6 +154,9 @@ $config['sphinx']['port'] = 3312; // $config['integration']['source'] = 'Laconica'; // Enable bidirectional Twitter bridge +// +// NOTE: if you enable this you must also set $config['avatar']['path'] +// // $config['twitterbridge']['enabled'] = true; // Edit throttling. Off by default. If turned on, you can only post 20 notices diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index 9287b6d73..93a4ce92b 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -38,6 +38,9 @@ define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/daemon.php'); +// NOTE: an Avatar path MUST be set in config.php for this +// script to work: e.g.: $config['avatar']['path'] = '/laconica/avatar'; + class TwitterStatusFetcher extends Daemon { @@ -358,11 +361,11 @@ class TwitterStatusFetcher extends Daemon $oldname = $profile->getAvatar(48)->filename; - if ($newname != $oldname) { + if ($newname != $oldname || $this->missingAvatarFile($profile)) { if (defined('SCRIPT_DEBUG')) { common_debug('Avatar for Twitter user ' . - "$profile->nickname has changed."); + "$profile->nickname has changed, or was missing locally."); common_debug("old: $oldname new: $newname"); } @@ -383,6 +386,21 @@ class TwitterStatusFetcher extends Daemon } } + function missingAvatarFile($profile) { + + foreach (array(24, 48, 73) as $size) { + + $filename = $profile->getAvatar($size)->filename; + $avatarpath = Avatar::path($filename); + + if (file_exists($avatarpath) == FALSE) { + return true; + } + } + + return false; + } + function getMediatype($ext) { $mediatype = null; @@ -447,7 +465,6 @@ class TwitterStatusFetcher extends Daemon if (defined('SCRIPT_DEBUG')) { common_debug("Deleting $size avatar for $profile->nickname."); } - @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); $avatar->delete(); } -- cgit v1.2.3-54-g00ecf From cb0047b1442d8a5303abdb11cddcdd2a77b8ad8e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 19:21:17 -0700 Subject: This time, twitterstatusfetcher really DOES update changed and missing avatars! --- scripts/twitterstatusfetcher.php | 61 ++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index 93a4ce92b..88605c349 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -351,38 +351,59 @@ class TwitterStatusFetcher extends Daemon } } - function checkAvatar($user, $profile) + function checkAvatar($twitter_user, $profile) { global $config; - $path_parts = pathinfo($user->profile_image_url); - $newname = 'Twitter_' . $user->id . '_' . + $path_parts = pathinfo($twitter_user->profile_image_url); + + $newname = 'Twitter_' . $twitter_user->id . '_' . $path_parts['basename']; $oldname = $profile->getAvatar(48)->filename; - if ($newname != $oldname || $this->missingAvatarFile($profile)) { + if ($newname != $oldname) { if (defined('SCRIPT_DEBUG')) { common_debug('Avatar for Twitter user ' . - "$profile->nickname has changed, or was missing locally."); + "$profile->nickname has changed."); common_debug("old: $oldname new: $newname"); } - $img_root = substr($path_parts['basename'], 0, -11); - $ext = $path_parts['extension']; - $mediatype = $this->getMediatype($ext); + $this->updateAvatars($twitter_user, $profile); + } - foreach (array('mini', 'normal', 'bigger') as $size) { - $url = $path_parts['dirname'] . '/' . - $img_root . '_' . $size . ".$ext"; - $filename = 'Twitter_' . $user->id . '_' . - $img_root . "_$size.$ext"; + if ($this->missingAvatarFile($profile)) { - if ($this->fetchAvatar($url, $filename)) { - $this->updateAvatar($profile->id, $size, $mediatype, $filename); - } + if (defined('SCRIPT_DEBUG')) { + common_debug('Twitter user ' . $profile->nickname . + ' is missing one or more local avatars.'); + common_debug("old: $oldname new: $newname"); } + + $this->updateAvatars($twitter_user, $profile); + } + + } + + function updateAvatars($twitter_user, $profile) { + + global $config; + + $path_parts = pathinfo($twitter_user->profile_image_url); + + $img_root = substr($path_parts['basename'], 0, -11); + $ext = $path_parts['extension']; + $mediatype = $this->getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $twitter_user->id . '_' . + $img_root . "_$size.$ext"; + + $this->updateAvatar($profile->id, $size, $mediatype, $filename); + $this->fetchAvatar($url, $filename); } } @@ -451,7 +472,7 @@ class TwitterStatusFetcher extends Daemon $profile = Profile::staticGet($profile_id); - if (!$profile) { + if (empty($profile)) { if (defined('SCRIPT_DEBUG')) { common_debug("Couldn't get profile: $profile_id!"); } @@ -461,10 +482,8 @@ class TwitterStatusFetcher extends Daemon $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); $avatar = $profile->getAvatar($sizes[$size]); + // Delete the avatar, if present if ($avatar) { - if (defined('SCRIPT_DEBUG')) { - common_debug("Deleting $size avatar for $profile->nickname."); - } $avatar->delete(); } @@ -509,7 +528,7 @@ class TwitterStatusFetcher extends Daemon $id = $avatar->insert(); - if (!$id) { + if (empty($id)) { common_log_db_error($avatar, 'INSERT', __FILE__); return null; } -- cgit v1.2.3-54-g00ecf From 1c2cf108118b3d5cfebd0e266099505810e6d850 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 19 Jun 2009 15:54:24 +0000 Subject: Includes a sioc:reply_to link between notices. It helps with things like http://danbri.org/words/2009/06/16/415 Thanks to Toby Inkster for the patch: http://buzzword.org.uk/2009/laconica-0.7.3-sioc-reply_to.patch --- lib/rssaction.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/rssaction.php b/lib/rssaction.php index eafdbf131..08b333d97 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -212,6 +212,11 @@ class Rss10Action extends Action $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri.'#acct')); $this->element('laconica:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); + if ($notice->reply_to) { + $replyurl = common_local_url('shownotice', + array('notice' => $notice->reply_to)); + $this->element('sioc:reply_to', array('rdf:resource' => $replyurl)); + } $this->elementEnd('item'); $this->creators[$creator_uri] = $profile; } -- cgit v1.2.3-54-g00ecf From 9be54a3dcf6520781c1c64897a28cfaca6fd66fb Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 19 Jun 2009 16:04:14 +0000 Subject: Minor indenting --- lib/rssaction.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rssaction.php b/lib/rssaction.php index 08b333d97..6f6c9a8cb 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -213,8 +213,7 @@ class Rss10Action extends Action $this->element('laconica:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); if ($notice->reply_to) { - $replyurl = common_local_url('shownotice', - array('notice' => $notice->reply_to)); + $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to)); $this->element('sioc:reply_to', array('rdf:resource' => $replyurl)); } $this->elementEnd('item'); -- cgit v1.2.3-54-g00ecf From f5b24133cb63b8fd8ec2a989b77bd075dd77367f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 19 Jun 2009 14:40:32 -0700 Subject: Add twitterstatusfetcher to the list of daemons to stop --- scripts/stopdaemons.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index 2134b4ab0..9f1696bf2 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,7 +24,8 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ + twitterstatusfetcher; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do -- cgit v1.2.3-54-g00ecf From b8f3f32f3f12339c3838fcfc883815d63a36dca7 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 19 Jun 2009 20:21:57 -0700 Subject: Keep Twitter gateway notices from leaking thru MySQL notice search --- lib/search_engines.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/search_engines.php b/lib/search_engines.php index 7b9dbb618..0f405afbd 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -118,12 +118,20 @@ class MySQLSearch extends SearchEngine } return true; } else if ('identica_notices' === $this->table) { - $this->target->whereAdd('MATCH(content) ' . - 'AGAINST (\''.addslashes($q).'\' IN BOOLEAN MODE)'); + + // Don't show imported notices + $this->target->whereAdd('notice.is_local != ' . NOTICE_GATEWAY); + if (strtolower($q) != $q) { + $this->target->whereAdd("( MATCH(content) AGAINST ('" . addslashes($q) . + "' IN BOOLEAN MODE)) OR ( MATCH(content) " . + "AGAINST ('" . addslashes(strtolower($q)) . + "' IN BOOLEAN MODE))"); + } else { $this->target->whereAdd('MATCH(content) ' . - 'AGAINST (\''.addslashes(strtolower($q)).'\' IN BOOLEAN MODE)', 'OR'); + 'AGAINST (\''.addslashes($q).'\' IN BOOLEAN MODE)'); } + return true; } else { throw new ServerException('Unknown table: ' . $this->table); @@ -138,6 +146,9 @@ class PGSearch extends SearchEngine if ('identica_people' === $this->table) { return $this->target->whereAdd('textsearch @@ plainto_tsquery(\''.addslashes($q).'\')'); } else if ('identica_notices' === $this->table) { + + // XXX: We need to filter out gateway notices (notice.is_local = -2) --Zach + return $this->target->whereAdd('to_tsvector(\'english\', content) @@ plainto_tsquery(\''.addslashes($q).'\')'); } else { throw new ServerException('Unknown table: ' . $this->table); -- cgit v1.2.3-54-g00ecf From 054e4459b2b2701158cd183dc1eb04c454e04bff Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sat, 20 Jun 2009 18:22:05 +0000 Subject: Position of max_file_size position helps IE --- lib/noticeform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/noticeform.php b/lib/noticeform.php index a36b7f31f..4e2a2edd6 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -151,12 +151,12 @@ class NoticeForm extends Form '140'); $this->out->elementEnd('dl'); if (common_config('attachments', 'uploads')) { - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); $this->out->element('input', array('id' => 'notice_data-attach', 'type' => 'file', 'name' => 'attach', 'title' => _('Attach a file'))); + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); } if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); -- cgit v1.2.3-54-g00ecf From 198afa0a1d61c4db2cf6b66e5801af506462ab9b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 14:58:47 -0700 Subject: change scripts to take server and path from commandline --- lib/common.php | 27 +++++++++++++++++++-------- scripts/enjitqueuehandler.php | 14 ++++++++------ scripts/facebookqueuehandler.php | 11 ++++++++--- scripts/jabberqueuehandler.php | 5 +++++ scripts/maildaemon.php | 6 +++++- scripts/ombqueuehandler.php | 11 ++++++++--- scripts/pingqueuehandler.php | 5 +++++ scripts/publicqueuehandler.php | 9 +++++++-- scripts/smsqueuehandler.php | 9 +++++++-- scripts/synctwitterfriends.php | 5 +++++ scripts/triminboxes.php | 9 +++++++-- scripts/twitterqueuehandler.php | 11 ++++++++--- scripts/twitterstatusfetcher.php | 7 ++++++- scripts/xmppconfirmhandler.php | 9 +++++++-- scripts/xmppdaemon.php | 6 +++++- 15 files changed, 110 insertions(+), 34 deletions(-) diff --git a/lib/common.php b/lib/common.php index 702da8235..17eed71cd 100644 --- a/lib/common.php +++ b/lib/common.php @@ -67,14 +67,25 @@ function _sn_to_path($sn) return $p; } -// try to figure out where we are - -$_server = array_key_exists('SERVER_NAME', $_SERVER) ? - strtolower($_SERVER['SERVER_NAME']) : - null; -$_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? - _sn_to_path($_SERVER['SCRIPT_NAME']) : - null; +// try to figure out where we are. $server and $path +// can be set by including module, else we guess based +// on HTTP info. + +if (isset($server)) { + $_server = $server; +} else { + $_server = array_key_exists('SERVER_NAME', $_SERVER) ? + strtolower($_SERVER['SERVER_NAME']) : + null; +} + +if (isset($path)) { + $_path = $path; +} else { + $_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? + _sn_to_path($_SERVER['SCRIPT_NAME']) : + null; +} // default configuration, overwritten in config.php diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 40f60da5d..37fef0b04 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,7 +40,6 @@ set_error_handler('common_error_handler'); class EnjitQueueHandler extends QueueHandler { - function transport() { return 'enjit'; @@ -60,7 +64,6 @@ class EnjitQueueHandler extends QueueHandler return "skipped"; } - # # Build an Atom message from the notice # @@ -93,8 +96,8 @@ class EnjitQueueHandler extends QueueHandler $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); - - curl_setopt($ch, CURLOPT_HEADER, 1); + + curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1) ; curl_setopt($ch, CURLOPT_POSTFIELDS, $data); @@ -103,7 +106,7 @@ class EnjitQueueHandler extends QueueHandler # # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - # curl_setopt($ch, CURLOPT_VERBOSE, 1); + # curl_setopt($ch, CURLOPT_VERBOSE, 1); $result = curl_exec($ch); @@ -115,7 +118,6 @@ class EnjitQueueHandler extends QueueHandler return $code; } - } diff --git a/scripts/facebookqueuehandler.php b/scripts/facebookqueuehandler.php index c6859cb21..c24a22596 100755 --- a/scripts/facebookqueuehandler.php +++ b/scripts/facebookqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/facebookutil.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class FacebookQueueHandler extends QueueHandler { - + function transport() { return 'facebook'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -51,7 +56,7 @@ class FacebookQueueHandler extends QueueHandler { return facebookBroadcastNotice($notice); } - + function finish() { } diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index 8b6e974c0..454c67f7b 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index 9dd647bf4..0b9ab0deb 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 1) ? $argv[1] : null; +$path = ($argc > 2) ? $argv[2] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once('Mail/mimeDecode.php'); @@ -36,7 +41,6 @@ require_once('Mail/mimeDecode.php'); class MailerDaemon { - function __construct() { } diff --git a/scripts/ombqueuehandler.php b/scripts/ombqueuehandler.php index cdcea51dc..6abc6d7f1 100755 --- a/scripts/ombqueuehandler.php +++ b/scripts/ombqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/omb.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class OmbQueueHandler extends QueueHandler { - + function transport() { return 'omb'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -56,7 +61,7 @@ class OmbQueueHandler extends QueueHandler return omb_broadcast_remote_subscribers($notice); } } - + function finish() { } diff --git a/scripts/pingqueuehandler.php b/scripts/pingqueuehandler.php index ada6ecdba..372c550f5 100644 --- a/scripts/pingqueuehandler.php +++ b/scripts/pingqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/ping.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index b0fa22d43..7e09454d1 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class PublicQueueHandler extends XmppQueueHandler { - + function transport() { return 'public'; } - + function handle_notice($notice) { try { diff --git a/scripts/smsqueuehandler.php b/scripts/smsqueuehandler.php index 38f2f11fe..ed6dbd2ad 100755 --- a/scripts/smsqueuehandler.php +++ b/scripts/smsqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,7 +40,7 @@ set_error_handler('common_error_handler'); class SmsQueueHandler extends QueueHandler { - + function transport() { return 'sms'; @@ -51,7 +56,7 @@ class SmsQueueHandler extends QueueHandler { return mail_broadcast_notice_sms($notice); } - + function finish() { } diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index bd08ba58d..dea3f9700 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -30,6 +30,11 @@ define('LACONICA', true); // Uncomment this to get useful console output //define('SCRIPT_DEBUG', true); +// Preset the server at the command line + +$server = ($argc > 1) ? $argv[1] : null; +$path = ($argc > 2) ? $argv[2] : null; + require_once(INSTALLDIR . '/lib/common.php'); // Make a lockfile diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php index 0d2eaeaf0..0d545b326 100644 --- a/scripts/triminboxes.php +++ b/scripts/triminboxes.php @@ -32,6 +32,11 @@ mb_internal_encoding('UTF-8'); define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); $user = new User(); @@ -74,10 +79,10 @@ while ($user->fetch()) { $delay = 3.0 * ($finish - $start); print "Delaying $delay seconds..."; - + // Wait to let slaves catch up usleep($delay * 1000000); - + print "DONE.\n"; } diff --git a/scripts/twitterqueuehandler.php b/scripts/twitterqueuehandler.php index 7da4f1e20..8c8a59d6a 100755 --- a/scripts/twitterqueuehandler.php +++ b/scripts/twitterqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/twitter.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class TwitterQueueHandler extends QueueHandler { - + function transport() { return 'twitter'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -51,7 +56,7 @@ class TwitterQueueHandler extends QueueHandler { return broadcast_twitter($notice); } - + function finish() { } diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index 20f42cef8..2863207b0 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -33,7 +33,12 @@ define('MAXCHILDREN', 2); define('POLL_INTERVAL', 60); // in seconds // Uncomment this to get useful logging -define('SCRIPT_DEBUG', true); +// define('SCRIPT_DEBUG', true); + +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; require_once INSTALLDIR . '/lib/common.php'; require_once INSTALLDIR . '/lib/daemon.php'; diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index 7f39235fe..fee902320 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); @@ -39,12 +44,12 @@ class XmppConfirmHandler extends XmppQueueHandler { var $_id = 'confirm'; - + function class_name() { return 'XmppConfirmHandler'; } - + function run() { if (!$this->start()) { diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index b79fa1b3b..468a163d2 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/daemon.php'); @@ -39,7 +44,6 @@ set_error_handler('common_error_handler'); class XMPPDaemon extends Daemon { - function XMPPDaemon($resource=null) { static $attrs = array('server', 'port', 'user', 'password', 'host'); -- cgit v1.2.3-54-g00ecf From 27aaabb5f2829d983bcedb6b637558ba143b718b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 15:49:42 -0700 Subject: ignore config.php.* --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8a7f5c65c..f4c2bba5f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ config-*.php good-config.php lac08.log php.log +config.php.* -- cgit v1.2.3-54-g00ecf From 793a6a1155996a7bcdc068fc891e7063934bdb19 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 16:00:04 -0700 Subject: change Controlez-Vous to Control Yourself --- actions/accesstoken.php | 2 +- actions/all.php | 2 +- actions/allrss.php | 2 +- actions/api.php | 2 +- actions/avatarbynickname.php | 2 +- actions/block.php | 2 +- actions/disfavor.php | 2 +- actions/doc.php | 2 +- actions/facebookhome.php | 2 +- actions/facebookinvite.php | 2 +- actions/facebooklogin.php | 2 +- actions/facebookremove.php | 2 +- actions/facebooksettings.php | 2 +- actions/favor.php | 2 +- actions/favoritesrss.php | 2 +- actions/file.php | 2 +- actions/finishopenidlogin.php | 2 +- actions/finishremotesubscribe.php | 2 +- actions/foaf.php | 2 +- actions/groupblock.php | 2 +- actions/groupsearch.php | 2 +- actions/groupunblock.php | 2 +- actions/invite.php | 2 +- actions/logout.php | 2 +- actions/makeadmin.php | 2 +- actions/microsummary.php | 2 +- actions/noticesearch.php | 2 +- actions/noticesearchrss.php | 2 +- actions/nudge.php | 2 +- actions/openidlogin.php | 2 +- actions/opensearch.php | 2 +- actions/peoplesearch.php | 2 +- actions/postnotice.php | 2 +- actions/publicrss.php | 2 +- actions/publicxrds.php | 2 +- actions/recoverpassword.php | 2 +- actions/remotesubscribe.php | 2 +- actions/repliesrss.php | 2 +- actions/requesttoken.php | 2 +- actions/subedit.php | 2 +- actions/subscribe.php | 2 +- actions/sup.php | 2 +- actions/tag.php | 2 +- actions/tagother.php | 2 +- actions/tagrss.php | 2 +- actions/twitapiaccount.php | 2 +- actions/twitapiblocks.php | 2 +- actions/twitapidirect_messages.php | 2 +- actions/twitapifavorites.php | 2 +- actions/twitapifriendships.php | 2 +- actions/twitapihelp.php | 2 +- actions/twitapinotifications.php | 2 +- actions/twitapistatuses.php | 2 +- actions/twitapiusers.php | 2 +- actions/unblock.php | 2 +- actions/unsubscribe.php | 2 +- actions/updateprofile.php | 2 +- actions/userauthorization.php | 2 +- actions/userbyid.php | 2 +- actions/userrss.php | 2 +- actions/xrds.php | 2 +- classes/File.php | 2 +- classes/File_oembed.php | 2 +- classes/File_redirection.php | 2 +- classes/File_thumbnail.php | 2 +- classes/File_to_post.php | 2 +- classes/Group_block.php | 2 +- classes/Memcached_DataObject.php | 2 +- classes/Notice.php | 2 +- classes/Notice_tag.php | 2 +- classes/Profile.php | 2 +- classes/Profile_block.php | 2 +- classes/Remote_profile.php | 2 +- classes/Subscription.php | 2 +- index.php | 2 +- install.php | 2 +- lib/Shorturl_api.php | 2 +- lib/arraywrapper.php | 2 +- lib/channel.php | 2 +- lib/clienterroraction.php | 2 +- lib/command.php | 2 +- lib/commandinterpreter.php | 2 +- lib/common.php | 2 +- lib/daemon.php | 2 +- lib/dberroraction.php | 2 +- lib/error.php | 2 +- lib/facebookutil.php | 2 +- lib/galleryaction.php | 2 +- lib/oauthstore.php | 2 +- lib/omb.php | 2 +- lib/openid.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/queuehandler.php | 2 +- lib/search_engines.php | 2 +- lib/searchaction.php | 2 +- lib/servererroraction.php | 2 +- lib/subs.php | 2 +- lib/twitter.php | 2 +- lib/twitterapi.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- scripts/enjitqueuehandler.php | 2 +- scripts/facebookqueuehandler.php | 2 +- scripts/fixup_hashtags.php | 2 +- scripts/fixup_inboxes.php | 2 +- scripts/fixup_notices_rendered.php | 2 +- scripts/fixup_replies.php | 2 +- scripts/getpiddir.php | 2 +- scripts/getvaliddaemons.php | 2 +- scripts/inbox_users.php | 2 +- scripts/jabberqueuehandler.php | 2 +- scripts/maildaemon.php | 2 +- scripts/ombqueuehandler.php | 2 +- scripts/pingqueuehandler.php | 2 +- scripts/publicqueuehandler.php | 2 +- scripts/setpassword.php | 2 +- scripts/smsqueuehandler.php | 2 +- scripts/sphinx-cron.sh | 2 +- scripts/sphinx-indexer.sh | 2 +- scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 2 +- scripts/synctwitterfriends.php | 2 +- scripts/twitterqueuehandler.php | 2 +- scripts/twitterstatusfetcher.php | 2 +- scripts/uncache_users.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- scripts/xmppdaemon.php | 2 +- 127 files changed, 127 insertions(+), 127 deletions(-) diff --git a/actions/accesstoken.php b/actions/accesstoken.php index 46b43c702..01aa77574 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -12,7 +12,7 @@ * @link http://laconi.ca/ * * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Controlez-Vous, Inc. + * Copyright (C) 2008, Control Yourself, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/actions/all.php b/actions/all.php index 80fc9d54b..f436fabd1 100644 --- a/actions/all.php +++ b/actions/all.php @@ -1,7 +1,7 @@ Date: Sat, 20 Jun 2009 16:12:55 -0700 Subject: Update copyright dates in files modified in 2009 --- actions/accesstoken.php | 2 +- actions/all.php | 2 +- actions/allrss.php | 2 +- actions/api.php | 2 +- actions/avatarbynickname.php | 2 +- actions/block.php | 2 +- actions/disfavor.php | 2 +- actions/doc.php | 2 +- actions/facebookhome.php | 2 +- actions/facebookinvite.php | 2 +- actions/facebooklogin.php | 2 +- actions/facebookremove.php | 2 +- actions/facebooksettings.php | 2 +- actions/favor.php | 2 +- actions/favoritesrss.php | 2 +- actions/file.php | 2 +- actions/finishopenidlogin.php | 2 +- actions/finishremotesubscribe.php | 2 +- actions/foaf.php | 2 +- actions/groupblock.php | 2 +- actions/groupsearch.php | 2 +- actions/groupunblock.php | 2 +- actions/invite.php | 2 +- actions/logout.php | 2 +- actions/makeadmin.php | 2 +- actions/microsummary.php | 2 +- actions/noticesearch.php | 2 +- actions/noticesearchrss.php | 2 +- actions/nudge.php | 2 +- actions/openidlogin.php | 2 +- actions/opensearch.php | 2 +- actions/peoplesearch.php | 2 +- actions/postnotice.php | 2 +- actions/publicrss.php | 2 +- actions/publicxrds.php | 2 +- actions/recoverpassword.php | 2 +- actions/remotesubscribe.php | 2 +- actions/repliesrss.php | 2 +- actions/requesttoken.php | 2 +- actions/subedit.php | 2 +- actions/subscribe.php | 2 +- actions/sup.php | 2 +- actions/tag.php | 2 +- actions/tagother.php | 2 +- actions/tagrss.php | 2 +- actions/twitapiaccount.php | 2 +- actions/twitapiblocks.php | 2 +- actions/twitapidirect_messages.php | 2 +- actions/twitapifavorites.php | 2 +- actions/twitapifriendships.php | 2 +- actions/twitapihelp.php | 2 +- actions/twitapinotifications.php | 2 +- actions/twitapistatuses.php | 2 +- actions/twitapiusers.php | 2 +- actions/unblock.php | 2 +- actions/unsubscribe.php | 2 +- actions/updateprofile.php | 2 +- actions/userauthorization.php | 2 +- actions/userbyid.php | 2 +- actions/userrss.php | 2 +- actions/xrds.php | 2 +- classes/File.php | 2 +- classes/File_oembed.php | 2 +- classes/File_redirection.php | 2 +- classes/File_thumbnail.php | 2 +- classes/File_to_post.php | 2 +- classes/Group_block.php | 2 +- classes/Memcached_DataObject.php | 2 +- classes/Notice.php | 2 +- classes/Notice_tag.php | 2 +- classes/Profile.php | 2 +- classes/Profile_block.php | 2 +- classes/Remote_profile.php | 2 +- classes/Subscription.php | 2 +- index.php | 2 +- lib/Shorturl_api.php | 2 +- lib/arraywrapper.php | 2 +- lib/channel.php | 2 +- lib/clienterroraction.php | 2 +- lib/command.php | 2 +- lib/commandinterpreter.php | 2 +- lib/common.php | 2 +- lib/daemon.php | 2 +- lib/dberroraction.php | 2 +- lib/error.php | 2 +- lib/facebookutil.php | 2 +- lib/galleryaction.php | 2 +- lib/oauthstore.php | 2 +- lib/omb.php | 2 +- lib/openid.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/queuehandler.php | 2 +- lib/search_engines.php | 2 +- lib/searchaction.php | 2 +- lib/servererroraction.php | 2 +- lib/subs.php | 2 +- lib/twitter.php | 2 +- lib/twitterapi.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- scripts/enjitqueuehandler.php | 2 +- scripts/facebookqueuehandler.php | 2 +- scripts/fixup_hashtags.php | 2 +- scripts/fixup_inboxes.php | 2 +- scripts/fixup_notices_rendered.php | 2 +- scripts/fixup_replies.php | 2 +- scripts/getpiddir.php | 2 +- scripts/getvaliddaemons.php | 2 +- scripts/inbox_users.php | 2 +- scripts/jabberqueuehandler.php | 2 +- scripts/maildaemon.php | 2 +- scripts/ombqueuehandler.php | 2 +- scripts/pingqueuehandler.php | 2 +- scripts/publicqueuehandler.php | 2 +- scripts/setpassword.php | 2 +- scripts/smsqueuehandler.php | 2 +- scripts/sphinx-cron.sh | 2 +- scripts/sphinx-indexer.sh | 2 +- scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 2 +- scripts/synctwitterfriends.php | 2 +- scripts/twitterqueuehandler.php | 2 +- scripts/twitterstatusfetcher.php | 2 +- scripts/uncache_users.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- scripts/xmppdaemon.php | 2 +- 126 files changed, 126 insertions(+), 126 deletions(-) diff --git a/actions/accesstoken.php b/actions/accesstoken.php index 01aa77574..2a8cd1713 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -12,7 +12,7 @@ * @link http://laconi.ca/ * * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Control Yourself, Inc. + * Copyright (C) 2008, 2009, Control Yourself, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/actions/all.php b/actions/all.php index f436fabd1..f06ead2a8 100644 --- a/actions/all.php +++ b/actions/all.php @@ -1,7 +1,7 @@ Date: Sun, 21 Jun 2009 11:11:12 -0700 Subject: add collecta.com link --- lib/searchaction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/searchaction.php b/lib/searchaction.php index bb2d50572..34fe9373f 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -148,10 +148,10 @@ You can also try your search on other engines: * [Tweet scan](http://www.tweetscan.com/indexi.php?s=%s) * [Google](http://www.google.com/search?q=site%%3A%%%%site.server%%%%+%s) * [Yahoo](http://search.yahoo.com/search?p=site%%3A%%%%site.server%%%%+%s) - +* [Collecta](http://collecta.com/#q=%s) E_O_T -), $qe, $qe, $qe, $qe); +), $qe, $qe, $qe, $qe, $qe); $this->elementStart('dl', array('id' => 'help_search', 'class' => 'help')); $this->element('dt', null, _('Search help')); $this->elementStart('dd', 'instructions'); -- cgit v1.2.3-54-g00ecf From 02a4ca9e2ea46cb82829dc65e76efc36b0ec470b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 21 Jun 2009 21:38:16 -0700 Subject: got rid of 'skin' concept a while ago --- lib/common.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index a4da25157..361759d0a 100644 --- a/lib/common.php +++ b/lib/common.php @@ -83,7 +83,6 @@ $config = array('name' => 'Just another Laconica microblog', 'server' => $_server, 'theme' => 'default', - 'skin' => 'default', 'design' => array('backgroundcolor' => '#F0F2F5', 'contentcolor' => '#FFFFFF', -- cgit v1.2.3-54-g00ecf From 876ab059273a5f223170d6b2c0b9b4342b06c50f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 21 Jun 2009 21:50:35 -0700 Subject: Add like for search --- README | 13 ++++++++++++- classes/Memcached_DataObject.php | 9 ++++++++- lib/common.php | 4 +++- lib/search_engines.php | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/README b/README index 5aa7270ee..0c500acb8 100644 --- a/README +++ b/README @@ -1247,7 +1247,6 @@ Options for group functionality. maxaliases: maximum number of aliases a group can have. Default 3. Set to 0 or less to prevent aliases in a group. - oohembed -------- @@ -1255,6 +1254,18 @@ oEmbed endpoint for multimedia attachments (links in posts). endpoint: oohembed endpoint using http://oohembed.com/ software. +search +------ + +Some stuff for search. + +type: type of search. Ignored if PostgreSQL or Sphinx are enabled. Can either + be 'fulltext' (default) or 'like'. The former is faster and more efficient + but requires the lame old MyISAM engine for MySQL. The latter + will work with InnoDB but could be miserably slow on large + systems. We'll probably add another type sometime in the future, + with our own indexing system (maybe like MediaWiki's). + Troubleshooting =============== diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 2d5a73554..f7cbb9d5b 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -193,7 +193,14 @@ class Memcached_DataObject extends DB_DataObject // unable to connect to sphinx' search daemon if (!$connected) { if ('mysql' === common_config('db', 'type')) { - $search_engine = new MySQLSearch($this, $table); + $type = common_config('search', 'type'); + if ($type == 'like') { + $search_engine = new MySQLLikeSearch($this, $table); + } else if ($type == 'fulltext') { + $search_engine = new MySQLSearch($this, $table); + } else { + throw new ServerException('Unknown search type: ' . $type); + } } else { $search_engine = new PGSearch($this, $table); } diff --git a/lib/common.php b/lib/common.php index 361759d0a..14f5c7a7f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -228,7 +228,9 @@ $config = ), 'group' => array('maxaliases' => 3), - 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/') + 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/'), + 'search' => + array('type' => 'fulltext'), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/search_engines.php b/lib/search_engines.php index c98e8ed87..5c84d7c6b 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -131,6 +131,28 @@ class MySQLSearch extends SearchEngine } } +class MySQLLikeSearch extends SearchEngine +{ + function query($q) + { + if ('identica_people' === $this->table) { + $qry = sprintf('(nickname LIKE "%%%1$s%%" OR '. + ' fullname LIKE "%%%1$s%%" OR '. + ' location LIKE "%%%1$s%%" OR '. + ' bio LIKE "%%%1$s%%" OR '. + ' homepage LIKE "%%%1$s%%")', addslashes($q)); + } else if ('identica_notices' === $this->table) { + $qry = sprintf('content LIKE "%%%1$s%%"', addslashes($q)); + } else { + throw new ServerException('Unknown table: ' . $this->table); + } + + $this->target->whereAdd($qry); + + return true; + } +} + class PGSearch extends SearchEngine { function query($q) -- cgit v1.2.3-54-g00ecf From 7cf0a4c6472ab05a0963c003d8c3ecb59237ee67 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 09:31:55 -0700 Subject: theme dir, path configurable --- README | 13 ++++++++++--- lib/common.php | 4 +++- lib/theme.php | 36 +++++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/README b/README index 0c500acb8..cd663d931 100644 --- a/README +++ b/README @@ -1039,9 +1039,16 @@ theme ----- server: Like avatars, you can speed up page loading by pointing the - theme file lookup to another server (virtual or real). The - theme server's root path should map to the Laconica "theme" - subdirectory. Defaults to NULL. + theme file lookup to another server (virtual or real). + Defaults to NULL, meaning to use the site server. +dir: Directory where theme files are stored. Used to determine + whether to show parts of a theme file. Defaults to the theme + subdirectory of the install directory. +path: Path part of theme URLs, before the theme name. Relative to the + theme server. It may make sense to change this path when upgrading, + (using version numbers as the path) to make sure that all files are + reloaded by caching clients or proxies. Defaults to null, + which means to use the site path + '/theme'. xmpp ---- diff --git a/lib/common.php b/lib/common.php index 14f5c7a7f..0333030e1 100644 --- a/lib/common.php +++ b/lib/common.php @@ -140,7 +140,9 @@ $config = 'blacklist' => array(), 'autosource' => array()), 'theme' => - array('server' => null), + array('server' => null, + 'dir' => null, + 'path'=> null), 'throttle' => array('enabled' => false, // whether to throttle edits; false by default 'count' => 20, // number of allowed messages in timespan diff --git a/lib/theme.php b/lib/theme.php index 0d8824822..2fe6ab69b 100644 --- a/lib/theme.php +++ b/lib/theme.php @@ -43,10 +43,14 @@ if (!defined('LACONICA')) { function theme_file($relative, $theme=null) { - if (!$theme) { + if (empty($theme)) { $theme = common_config('site', 'theme'); } - return INSTALLDIR.'/theme/'.$theme.'/'.$relative; + $dir = common_config('theme', 'dir'); + if (empty($dir)) { + $dir = INSTALLDIR.'/theme'; + } + return $dir.'/'.$theme.'/'.$relative; } /** @@ -60,13 +64,31 @@ function theme_file($relative, $theme=null) function theme_path($relative, $theme=null) { - if (!$theme) { + if (empty($theme)) { $theme = common_config('site', 'theme'); } + + $path = common_config('theme', 'path'); + + if (empty($path)) { + $path = common_config('site', 'path') . '/theme/'; + } + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + $server = common_config('theme', 'server'); - if ($server) { - return 'http://'.$server.'/'.$theme.'/'.$relative; - } else { - return common_path('theme/'.$theme.'/'.$relative); + + if (empty($server)) { + $server = common_config('site', 'server'); } + + // XXX: protocol + + return 'http://'.$server.$path.$theme.'/'.$relative; } -- cgit v1.2.3-54-g00ecf From 7b269a6712ac740c961634b0c165e6f74f420236 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 22 Jun 2009 17:18:09 +0000 Subject: Layout fix for IE6 --- theme/base/css/ie6.css | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/theme/base/css/ie6.css b/theme/base/css/ie6.css index 76a82c004..dde4d6fc7 100644 --- a/theme/base/css/ie6.css +++ b/theme/base/css/ie6.css @@ -5,6 +5,12 @@ margin-left:7px; address .fn { display:none; } + +#wrap { +width:1003px; +margin:0 auto; +} + #content { width:70%; } @@ -26,5 +32,6 @@ margin-bottom:123px; width:20%; } .notice div.entry-content { -width:63%; +width:50%; +margin-left:30px; } -- cgit v1.2.3-54-g00ecf From 4c09d10025796c824c7f5d5f08a1750e4c92ba9e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 22 Jun 2009 12:24:59 -0700 Subject: Keep gateway notices from leaking thru Sphinx search-engine --- sphinx.conf.sample | 82 +++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/sphinx.conf.sample b/sphinx.conf.sample index b79adf15c..8204b9db6 100644 --- a/sphinx.conf.sample +++ b/sphinx.conf.sample @@ -4,68 +4,68 @@ source src1 { - type = mysql - sql_host = localhost - sql_user = USERNAME - sql_pass = PASSWORD - sql_db = identi_ca - sql_port = 3306 - sql_query = SELECT id, UNIX_TIMESTAMP(created) as created_ts, nickname, fullname, location, bio, homepage FROM profile - sql_query_info = SELECT * FROM profile where id = $id - sql_attr_timestamp = created_ts + type = mysql + sql_host = localhost + sql_user = USERNAME + sql_pass = PASSWORD + sql_db = identi_ca + sql_port = 3306 + sql_query = SELECT id, UNIX_TIMESTAMP(created) as created_ts, nickname, fullname, location, bio, homepage FROM profile + sql_query_info = SELECT * FROM profile where id = $id + sql_attr_timestamp = created_ts } source src2 { - type = mysql - sql_host = localhost - sql_user = USERNAME - sql_pass = PASSWORD - sql_db = identi_ca - sql_port = 3306 - sql_query = SELECT id, UNIX_TIMESTAMP(created) as created_ts, content FROM notice - sql_query_info = SELECT * FROM notice where id = $id - sql_attr_timestamp = created_ts + type = mysql + sql_host = localhost + sql_user = USERNAME + sql_pass = PASSWORD + sql_db = identi_ca + sql_port = 3306 + sql_query = SELECT id, UNIX_TIMESTAMP(created) as created_ts, content FROM notice + sql_query_info = SELECT * FROM notice where notice.id = $id AND notice.is_local != -2 + sql_attr_timestamp = created_ts } index identica_notices { - source = src2 - path = DIRECTORY/data/identica_notices - docinfo = extern - charset_type = utf-8 - min_word_len = 3 - stopwords = DIRECTORY/data/stopwords-en.txt + source = src2 + path = DIRECTORY/data/identica_notices + docinfo = extern + charset_type = utf-8 + min_word_len = 3 + stopwords = DIRECTORY/data/stopwords-en.txt } index identica_people { - source = src1 - path = DIRECTORY/data/identica_people - docinfo = extern - charset_type = utf-8 - min_word_len = 3 - stopwords = DIRECTORY/data/stopwords-en.txt + source = src1 + path = DIRECTORY/data/identica_people + docinfo = extern + charset_type = utf-8 + min_word_len = 3 + stopwords = DIRECTORY/data/stopwords-en.txt } indexer { - mem_limit = 32M + mem_limit = 32M } searchd { - port = 3312 - log = DIRECTORY/log/searchd.log - query_log = DIRECTORY/log/query.log - read_timeout = 5 - max_children = 30 - pid_file = DIRECTORY/log/searchd.pid - max_matches = 1000 - seamless_rotate = 1 - preopen_indexes = 0 - unlink_old = 1 + port = 3312 + log = DIRECTORY/log/searchd.log + query_log = DIRECTORY/log/query.log + read_timeout = 5 + max_children = 30 + pid_file = DIRECTORY/log/searchd.pid + max_matches = 1000 + seamless_rotate = 1 + preopen_indexes = 0 + unlink_old = 1 } -- cgit v1.2.3-54-g00ecf From 15e4cbebab5d640b0261f0e6c0366ebb49d72d7a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 13:14:15 -0700 Subject: fixing up conversations --- scripts/fixup_conversations.php | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 scripts/fixup_conversations.php diff --git a/scripts/fixup_conversations.php b/scripts/fixup_conversations.php new file mode 100755 index 000000000..d4a47cfee --- /dev/null +++ b/scripts/fixup_conversations.php @@ -0,0 +1,79 @@ +#!/usr/bin/env php +. + */ + +# Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +common_log(LOG_INFO, 'Fixing up conversations.'); + +$notice = new Notice(); +$notice->whereAdd('conversation is null'); +$notice->orderBy('id'); + +$cnt = $notice->find(); + +print "Found $cnt notices.\n"; + +while ($notice->fetch()) { + + print "$notice->id =>"; + + $orig = clone($notice); + + if (empty($notice->reply_to)) { + $notice->conversation = $notice->id; + } else { + $reply = Notice::staticGet('id', $notice->reply_to); + + if (empty($reply)) { + common_log(LOG_WARNING, "Replied-to notice $notice->reply_to not found."); + $notice->conversation = $notice->id; + } else if (empty($reply->conversation)) { + common_log(LOG_WARNING, "Replied-to notice $reply->id has no conversation ID."); + $notice->conversation = $notice->id; + } else { + $notice->conversation = $reply->conversation; + } + } + + print "$notice->conversation"; + + $result = $notice->update($orig); + + if (!$result) { + common_log_db_error($notice, 'UPDATE', __FILE__); + continue; + } + + print ".\n"; +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); -- cgit v1.2.3-54-g00ecf From 05e51228020fecaa894523b5159bc412d48e5b19 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 14:19:41 -0700 Subject: Database changes for file tables Some minor database changes for file tables. Namely: * Added a timestamp to all tables * Added a filename column for local files * Change some tables that had unnecessary auto-increment primary keys when they had another unique column that should act as the primary key * Change engine from MyISAM to InnoDB for a couple of files. Also, rebuilt the DB_DataObject files for all these tables. --- classes/File.php | 10 ++++++---- classes/File_oembed.php | 10 +++++----- classes/File_redirection.php | 10 +++++----- classes/File_thumbnail.php | 8 ++++---- classes/File_to_post.php | 6 +++--- classes/laconica.ini | 30 +++++++++++++++++------------- db/laconica.sql | 31 ++++++++++++++++++------------- 7 files changed, 58 insertions(+), 47 deletions(-) diff --git a/classes/File.php b/classes/File.php index 890536035..800041d5d 100644 --- a/classes/File.php +++ b/classes/File.php @@ -36,13 +36,15 @@ class File extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'file'; // table name - public $id; // int(11) not_null primary_key group_by + public $id; // int(4) primary_key not_null public $url; // varchar(255) unique_key public $mimetype; // varchar(50) - public $size; // int(11) group_by + public $size; // int(4) public $title; // varchar(255) - public $date; // int(11) group_by - public $protected; // int(1) group_by + public $date; // int(4) + public $protected; // int(4) + public $filename; // varchar(255) + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File',$k,$v); } diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 2e8e851cd..f9ca14e3c 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -31,19 +31,19 @@ class File_oembed extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'file_oembed'; // table name - public $id; // int(11) not_null primary_key group_by - public $file_id; // int(11) unique_key group_by + public $file_id; // int(4) primary_key not_null public $version; // varchar(20) public $type; // varchar(20) public $provider; // varchar(50) public $provider_url; // varchar(255) - public $width; // int(11) group_by - public $height; // int(11) group_by - public $html; // blob(65535) blob + public $width; // int(4) + public $height; // int(4) + public $html; // text() public $title; // varchar(255) public $author_name; // varchar(50) public $author_url; // varchar(255) public $url; // varchar(255) + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_oembed',$k,$v); } diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 0d6e2a700..13f02f8e5 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -36,11 +36,11 @@ class File_redirection extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'file_redirection'; // table name - public $id; // int(11) not_null primary_key group_by - public $url; // varchar(255) unique_key - public $file_id; // int(11) group_by - public $redirections; // int(11) group_by - public $httpcode; // int(11) group_by + public $url; // varchar(255) primary_key not_null + public $file_id; // int(4) + public $redirections; // int(4) + public $httpcode; // int(4) + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_redirection',$k,$v); } diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php index 2908549da..40d85b258 100644 --- a/classes/File_thumbnail.php +++ b/classes/File_thumbnail.php @@ -31,11 +31,11 @@ class File_thumbnail extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'file_thumbnail'; // table name - public $id; // int(11) not_null primary_key group_by - public $file_id; // int(11) unique_key group_by + public $file_id; // int(4) primary_key not_null public $url; // varchar(255) unique_key - public $width; // int(11) group_by - public $height; // int(11) group_by + public $width; // int(4) + public $height; // int(4) + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_thumbnail',$k,$v); } diff --git a/classes/File_to_post.php b/classes/File_to_post.php index 9362faaae..bb5f4e6e4 100644 --- a/classes/File_to_post.php +++ b/classes/File_to_post.php @@ -31,9 +31,9 @@ class File_to_post extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'file_to_post'; // table name - public $id; // int(11) not_null primary_key group_by - public $file_id; // int(11) multiple_key group_by - public $post_id; // int(11) group_by + public $file_id; // int(4) primary_key not_null + public $post_id; // int(4) primary_key not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_to_post',$k,$v); } diff --git a/classes/laconica.ini b/classes/laconica.ini index 5ced15885..7e9b2b791 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -68,13 +68,14 @@ size = 1 title = 2 date = 1 protected = 1 +filename = 2 +modified = 384 [file__keys] id = N [file_oembed] -id = 129 -file_id = 1 +file_id = 129 version = 2 type = 2 provider = 2 @@ -86,37 +87,40 @@ title = 2 author_name = 2 author_url = 2 url = 2 +modified = 384 [file_oembed__keys] -id = N +file_id = K [file_redirection] -id = 129 -url = 2 +url = 130 file_id = 1 redirections = 1 httpcode = 1 +modified = 384 [file_redirection__keys] -id = N +url = K [file_thumbnail] -id = 129 -file_id = 1 +file_id = 129 url = 2 width = 1 height = 1 +modified = 384 [file_thumbnail__keys] -id = N +file_id = K +url = U [file_to_post] -id = 129 -file_id = 1 -post_id = 1 +file_id = 129 +post_id = 129 +modified = 384 [file_to_post__keys] -id = N +file_id = K +post_id = K [foreign_link] user_id = 129 diff --git a/db/laconica.sql b/db/laconica.sql index 8d1d47d38..95796d5cc 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -431,6 +431,7 @@ create table group_inbox ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table file ( + id integer primary key auto_increment, url varchar(255) comment 'destination URL after following redirections', mimetype varchar(50) comment 'mime type of resource', @@ -438,13 +439,15 @@ create table file ( title varchar(255) comment 'title of resource when available', date integer(11) comment 'date of resource according to http query', protected integer(1) comment 'true when URL is private (needs login)', + filename varchar(255) comment 'if a local file, name of the file', + + modified timestamp comment 'date this record was modified', unique(url) -) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; create table file_oembed ( - id integer primary key auto_increment, - file_id integer comment 'oEmbed for that URL/file' references file (id), + file_id integer primary key comment 'oEmbed for that URL/file' references file (id), version varchar(20) comment 'oEmbed spec. version', type varchar(20) comment 'oEmbed type: photo, video, link, rich', provider varchar(50) comment 'name of this oEmbed provider', @@ -456,37 +459,39 @@ create table file_oembed ( author_name varchar(50) comment 'author name for this oEmbed resource', author_url varchar(255) comment 'author URL for this oEmbed resource', url varchar(255) comment 'URL for this oEmbed resource when applicable (photo, link)', + modified timestamp comment 'date this record was modified' - unique(file_id) -) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; create table file_redirection ( - id integer primary key auto_increment, - url varchar(255) comment 'short URL (or any other kind of redirect) for file (id)', + + url varchar(255) primary key comment 'short URL (or any other kind of redirect) for file (id)', file_id integer comment 'short URL for what URL/file' references file (id), redirections integer comment 'redirect count', httpcode integer comment 'HTTP status code (20x, 30x, etc.)', + modified timestamp comment 'date this record was modified' - unique(url) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table file_thumbnail ( - id integer primary key auto_increment, - file_id integer comment 'thumbnail for what URL/file' references file (id), + + file_id integer primary key comment 'thumbnail for what URL/file' references file (id), url varchar(255) comment 'URL of thumbnail', width integer comment 'width of thumbnail', height integer comment 'height of thumbnail', + modified timestamp comment 'date this record was modified', - unique(file_id), unique(url) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table file_to_post ( - id integer primary key auto_increment, + file_id integer comment 'id of URL/file' references file (id), post_id integer comment 'id of the notice it belongs to' references notice (id), + modified timestamp comment 'date this record was modified', + + constraint primary key (file_id, post_id) - unique(file_id, post_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table design ( -- cgit v1.2.3-54-g00ecf From 2e9fc34d4f6483ad08e6e5a1b778ee096cb6a5c1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 14:24:40 -0700 Subject: change staticGet() from DB_DataObject to Memcached_DataObject for file classes --- classes/File.php | 2 +- classes/File_oembed.php | 2 +- classes/File_redirection.php | 2 +- classes/File_thumbnail.php | 2 +- classes/File_to_post.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/classes/File.php b/classes/File.php index 800041d5d..47af1c550 100644 --- a/classes/File.php +++ b/classes/File.php @@ -47,7 +47,7 @@ class File extends Memcached_DataObject public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE diff --git a/classes/File_oembed.php b/classes/File_oembed.php index f9ca14e3c..51ee57b29 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -46,7 +46,7 @@ class File_oembed extends Memcached_DataObject public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_oembed',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File_oembed',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 13f02f8e5..edd915c1e 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -43,7 +43,7 @@ class File_redirection extends Memcached_DataObject public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_redirection',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File_redirection',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php index 40d85b258..21dcad571 100644 --- a/classes/File_thumbnail.php +++ b/classes/File_thumbnail.php @@ -38,7 +38,7 @@ class File_thumbnail extends Memcached_DataObject public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_thumbnail',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File_thumbnail',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE diff --git a/classes/File_to_post.php b/classes/File_to_post.php index bb5f4e6e4..db0a8d216 100644 --- a/classes/File_to_post.php +++ b/classes/File_to_post.php @@ -36,7 +36,7 @@ class File_to_post extends Memcached_DataObject public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_to_post',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File_to_post',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE -- cgit v1.2.3-54-g00ecf From 09e24af6832d6a4ce5605be23e3469c5b33a3efe Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 22 Jun 2009 21:36:04 +0000 Subject: Add upload location to attachments config section --- lib/common.php | 67 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/lib/common.php b/lib/common.php index 0333030e1..b773f5f89 100644 --- a/lib/common.php +++ b/lib/common.php @@ -191,38 +191,41 @@ $config = array('run' => 'web', 'frequency' => 10000, 'reporturl' => 'http://laconi.ca/stats/report'), - 'attachments' => - array('supported' => array('image/png', - 'image/jpeg', - 'image/gif', - 'image/svg+xml', - 'audio/mpeg', - 'audio/x-speex', - 'application/ogg', - 'application/pdf', - 'application/vnd.oasis.opendocument.text', - 'application/vnd.oasis.opendocument.text-template', - 'application/vnd.oasis.opendocument.graphics', - 'application/vnd.oasis.opendocument.graphics-template', - 'application/vnd.oasis.opendocument.presentation', - 'application/vnd.oasis.opendocument.presentation-template', - 'application/vnd.oasis.opendocument.spreadsheet', - 'application/vnd.oasis.opendocument.spreadsheet-template', - 'application/vnd.oasis.opendocument.chart', - 'application/vnd.oasis.opendocument.chart-template', - 'application/vnd.oasis.opendocument.image', - 'application/vnd.oasis.opendocument.image-template', - 'application/vnd.oasis.opendocument.formula', - 'application/vnd.oasis.opendocument.formula-template', - 'application/vnd.oasis.opendocument.text-master', - 'application/vnd.oasis.opendocument.text-web', - 'application/x-zip', - 'application/zip', - 'text/plain', - 'video/mpeg', - 'video/mp4', - 'video/quicktime', - 'video/mpeg'), + 'attachments' => + array('server' => null, + 'dir' => INSTALLDIR . '/file/', + 'path' => $_path . '/file/', + 'supported' => array('image/png', + 'image/jpeg', + 'image/gif', + 'image/svg+xml', + 'audio/mpeg', + 'audio/x-speex', + 'application/ogg', + 'application/pdf', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.text-template', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.graphics-template', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.presentation-template', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.spreadsheet-template', + 'application/vnd.oasis.opendocument.chart', + 'application/vnd.oasis.opendocument.chart-template', + 'application/vnd.oasis.opendocument.image', + 'application/vnd.oasis.opendocument.image-template', + 'application/vnd.oasis.opendocument.formula', + 'application/vnd.oasis.opendocument.formula-template', + 'application/vnd.oasis.opendocument.text-master', + 'application/vnd.oasis.opendocument.text-web', + 'application/x-zip', + 'application/zip', + 'text/plain', + 'video/mpeg', + 'video/mp4', + 'video/quicktime', + 'video/mpeg'), 'file_quota' => 5000000, 'user_quota' => 50000000, 'monthly_quota' => 15000000, -- cgit v1.2.3-54-g00ecf From 79dcf0871fee6dfa3835d12f55d1099a716a6f4c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 14:55:55 -0700 Subject: Add Console_Getopt --- extlib/Console/Getopt.php | 290 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 extlib/Console/Getopt.php diff --git a/extlib/Console/Getopt.php b/extlib/Console/Getopt.php new file mode 100644 index 000000000..bb9d69ca2 --- /dev/null +++ b/extlib/Console/Getopt.php @@ -0,0 +1,290 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } elseif ($arg == '-') { + // - is stdin + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) { + /* Else use the next argument. */; + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } else { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _isShortOpt($arg) + { + return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); + } + + /** + * @access private + * + */ + function _isLongOpt($arg) + { + return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && + preg_match('/[a-zA-Z]+$/', substr($arg, 2)); + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg, 2); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + $long_opt_name = str_replace('=', '', $long_opt); + + /* Option doesn't match. Go on to the next one. */ + if ($long_opt_name != $opt) { + continue; + } + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($i + 1 < count($long_options)) { + $next_option_rest = substr($long_options[$i + 1], $opt_len); + } else { + $next_option_rest = ''; + } + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len) && + $next_option_rest != '' && + $next_option_rest{0} != '=') { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument --$opt"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> -- cgit v1.2.3-54-g00ecf From e14322672cc24adc27efc2aeaafee60ef03ab650 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 14:56:53 -0700 Subject: note about Console_Getopt --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index cd663d931..de1099600 100644 --- a/README +++ b/README @@ -180,6 +180,7 @@ and the URLs are listed here for your convenience. - PEAR HTTP_Request is an oEmbed dependency. - PEAR Validate is an oEmbed dependency. - PEAR Net_URL2 is an oEmbed dependency. +- Console_GetOpt for parsing command-line options. A design goal of Laconica is that the basic Web functionality should work on even the most restrictive commercial hosting services. -- cgit v1.2.3-54-g00ecf From 9171f16b730176717b0b9abf84ace10b7a6dddc7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:29:24 -0700 Subject: add commandline.inc for parsing --- lib/common.php | 16 +++++--- scripts/commandline.inc | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 scripts/commandline.inc diff --git a/lib/common.php b/lib/common.php index a8c7634f6..2327dcb0e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -269,14 +269,18 @@ if (function_exists('date_default_timezone_set')) { // server-wide, then vhost-wide, then for a path, // finally for a dir (usually only need one of the last two). -$_config_files = array('/etc/laconica/laconica.php', - '/etc/laconica/'.$_server.'.php'); +if (isset($conffile)) { + $_config_files = array($conffile); +} else { + $_config_files = array('/etc/laconica/laconica.php', + '/etc/laconica/'.$_server.'.php'); -if (strlen($_path) > 0) { - $_config_files[] = '/etc/laconica/'.$_server.'_'.$_path.'.php'; -} + if (strlen($_path) > 0) { + $_config_files[] = '/etc/laconica/'.$_server.'_'.$_path.'.php'; + } -$_config_files[] = INSTALLDIR.'/config.php'; + $_config_files[] = INSTALLDIR.'/config.php'; +} $_have_a_config = false; diff --git a/scripts/commandline.inc b/scripts/commandline.inc new file mode 100644 index 000000000..292005dca --- /dev/null +++ b/scripts/commandline.inc @@ -0,0 +1,107 @@ +. + */ + +// -*- mode: php -*- + +# Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('LACONICA', true); + +// Set various flags so we don't time out on long-running processes + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +// Add extlib to our path so we can get Console_Getopt + +$_extra_path = array(INSTALLDIR.'/extlib/'); + +set_include_path(implode(PATH_SEPARATOR, $_extra_path) . PATH_SEPARATOR . get_include_path()); + +require_once 'Console/Getopt.php'; + +// Note: $shortoptions and $longoptions should be pre-defined! + +$_default_shortoptions = 'qvhc:s:p:'; + +$_default_longoptions = array('quiet', 'verbose', 'help', 'conf=', 'server=', 'path='); + +if (isset($shortoptions)) { + $shortoptions .= $_default_shortoptions; +} else { + $shortoptions = $_default_shortoptions; +} + +if (isset($longoptions)) { + $longoptions = array_merge($longoptions, $_default_longoptions); +} else { + $longoptions = $_default_longoptions; +} + +$parser = new Console_Getopt(); + +list($options, $args) = $parser->getopt($argv, $shortoptions, $longoptions); + +foreach ($options as $option) { + + switch ($option[0]) { + case '--server': + case '-s': + $server = $option[1]; + break; + + case '--path': + case '-p': + $path = $option[1]; + break; + + case '--conf': + case '-c': + $conffile = $option[1]; + break; + + case '--help': + case '-h': + $_default_help_text = << Use as config file + -s --server= Use as server name + -p --path= Use as path name + -h --help Show this message and quit. + +END_OF_DEFAULT; + if (isset($helptext)) { + print $helptext; + } + print $_default_help_text; + exit(0); + } +} + +require_once INSTALLDIR . '/lib/common.php'; -- cgit v1.2.3-54-g00ecf From 00bf031f0ba3c603b2d99808340da97897548b28 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:29:43 -0700 Subject: change fixup_conversations to use commandline.inc --- scripts/fixup_conversations.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/scripts/fixup_conversations.php b/scripts/fixup_conversations.php index d4a47cfee..2cfa422e6 100755 --- a/scripts/fixup_conversations.php +++ b/scripts/fixup_conversations.php @@ -18,16 +18,9 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; common_log(LOG_INFO, 'Fixing up conversations.'); @@ -72,8 +65,3 @@ while ($notice->fetch()) { print ".\n"; } - -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); -- cgit v1.2.3-54-g00ecf From c9ca46f7c125b7a012f8bc85b9a37f1ae7468c77 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:35:27 -0700 Subject: make enjit queue handler take command-line arguments --- scripts/enjitqueuehandler.php | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 15ab3a427..c17b4e27f 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -18,23 +18,22 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i'; +$longoptions = array('id'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_ENJIT_HELP; -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/mail.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/mail.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; set_error_handler('common_error_handler'); @@ -123,7 +122,14 @@ class EnjitQueueHandler extends QueueHandler mb_internal_encoding('UTF-8'); -$id = ($argc > 1) ? $argv[1] : null; +$id = NULL; + +foreach ($options as $option) { + if ($option[0] == '--id' || $option[0] == '-i') { + $id = $option[1]; + break; + } +} $handler = new EnjitQueueHandler($id); -- cgit v1.2.3-54-g00ecf From a81350f6559a59921443d9773eccc9f8cfd96ee1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:41:52 -0700 Subject: functions to check options --- scripts/commandline.inc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/scripts/commandline.inc b/scripts/commandline.inc index 292005dca..8da42873a 100644 --- a/scripts/commandline.inc +++ b/scripts/commandline.inc @@ -105,3 +105,27 @@ END_OF_DEFAULT; } require_once INSTALLDIR . '/lib/common.php'; + +set_error_handler('common_error_handler'); + +function have_option($str) +{ + global $options; + foreach ($options as $option) { + if ($option[0] == $str) { + return true; + } + } + return false; +} + +function get_option_value($str) +{ + global $options; + foreach ($options as $option) { + if ($option[0] == $str) { + return $option[1]; + } + } + return null; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 0b6f3870ad1f77594e8f6dda18465188400aa2e5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:42:16 -0700 Subject: enjitqueuehandler uses functions to check options --- scripts/enjitqueuehandler.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index c17b4e27f..2418d2d1c 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -120,15 +120,12 @@ class EnjitQueueHandler extends QueueHandler } -mb_internal_encoding('UTF-8'); - -$id = NULL; - -foreach ($options as $option) { - if ($option[0] == '--id' || $option[0] == '-i') { - $id = $option[1]; - break; - } +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else { + $id = null; } $handler = new EnjitQueueHandler($id); -- cgit v1.2.3-54-g00ecf From 6a40ba776477ec6e70a523fd3c5a4122a72c3208 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:43:26 -0700 Subject: make enjitqueuehandler use functions and args --- scripts/enjitqueuehandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 2418d2d1c..509134765 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -124,6 +124,8 @@ if (have_option('-i')) { $id = get_option_value('-i'); } else if (have_option('--id')) { $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; } else { $id = null; } -- cgit v1.2.3-54-g00ecf From 032b65b83ab3c76dca4d1935334915de931fef97 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:43:39 -0700 Subject: make facebookqueuehandler use command-line functions and args --- scripts/facebookqueuehandler.php | 42 +++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/scripts/facebookqueuehandler.php b/scripts/facebookqueuehandler.php index f9123db8c..f01e45a3b 100755 --- a/scripts/facebookqueuehandler.php +++ b/scripts/facebookqueuehandler.php @@ -18,29 +18,25 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i'; +$longoptions = array('id'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_FACEBOOK_HELP; -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/facebookutil.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; -set_error_handler('common_error_handler'); +require_once INSTALLDIR . '/lib/facebookutil.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; class FacebookQueueHandler extends QueueHandler { - function transport() { return 'facebook'; @@ -63,13 +59,15 @@ class FacebookQueueHandler extends QueueHandler } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); - -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} $handler = new FacebookQueueHandler($id); -- cgit v1.2.3-54-g00ecf From 273d9e2def8b7ad003d39ca3210b502d8981a8cb Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:47:29 -0700 Subject: jabberqueuehandler uses commandline stuff --- scripts/jabberqueuehandler.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index b848442fd..be0f187a9 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -18,29 +18,26 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'r'; +$longoptions = array('resource'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; + -r --resource Jabber Resource ID -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/jabber.php'); -require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); +END_OF_JABBER_HELP; -set_error_handler('common_error_handler'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/common.php'; +require_once INSTALLDIR . '/lib/jabber.php'; +require_once INSTALLDIR . '/lib/xmppqueuehandler.php'; class JabberQueueHandler extends XmppQueueHandler { - var $conn = null; function transport() @@ -66,12 +63,15 @@ if (common_config('xmpp','enabled')==false) { exit(); } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$resource = ($argc > 1) ? $argv[1] : (common_config('xmpp','resource') . '-queuehandler'); +if (have_option('-r')) { + $resource = get_option_value('-r'); +} else if (have_option('--resource')) { + $resource = get_option_value('--resource'); +} else if (count($args) > 0) { + $resource = $args[0]; +} else { + $resource = null; +} $handler = new JabberQueueHandler($resource); -- cgit v1.2.3-54-g00ecf From d9bebfd6512353690be8bf8cc596a0656ef48ae9 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 22 Jun 2009 22:48:31 +0000 Subject: Attachment upload server and path now configurable --- actions/newnotice.php | 34 +++++++++++++++++++++++------- classes/File.php | 58 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 72ccd8c32..09652d2b3 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -257,23 +257,43 @@ class NewnoticeAction extends Action } function storeFile($notice, $mimetype) { - $filename = basename($_FILES['attach']['name']); - $destination = "file/{$notice->id}-$filename"; - if (move_uploaded_file($_FILES['attach']['tmp_name'], INSTALLDIR . "/$destination")) { + + common_debug("NewnoticeAction::storeFile()"); + + $basename = basename($_FILES['attach']['name']); + + common_debug("Basename: $basename"); + + $filename = File::filename($notice->id, $basename); + + common_debug("filename: $filename"); + + $filepath = File::path($filename); + + common_debug("filepath: $filepath"); + + if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) { + $file = new File; + $file->filename = $filename; + $file->url = common_local_url('file', array('notice' => $notice->id)); - $file->size = filesize(INSTALLDIR . "/$destination"); + + common_debug("file->url =". $file->url); + + $file->size = filesize($filepath); $file->date = time(); $file->mimetype = $mimetype; + if ($file_id = $file->insert()) { $file_redir = new File_redirection; - $file_redir->url = common_path($destination); + $file_redir->url = File::url($filename); $file_redir->file_id = $file_id; $file_redir->insert(); $f2p = new File_to_post; - $f2p->file_id = $file_id; - $f2p->post_id = $notice->id; + $f2p->file_id = $file_id; + $f2p->post_id = $notice->id; $f2p->insert(); } else { $this->clientError(_('There was a database error while saving your file. Please try again.')); diff --git a/classes/File.php b/classes/File.php index 47af1c550..1de136240 100644 --- a/classes/File.php +++ b/classes/File.php @@ -30,7 +30,7 @@ require_once INSTALLDIR.'/classes/File_to_post.php'; * Table Definition for file */ -class File extends Memcached_DataObject +class File extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -38,12 +38,12 @@ class File extends Memcached_DataObject public $__table = 'file'; // table name public $id; // int(4) primary_key not_null public $url; // varchar(255) unique_key - public $mimetype; // varchar(50) - public $size; // int(4) - public $title; // varchar(255) - public $date; // int(4) - public $protected; // int(4) - public $filename; // varchar(255) + public $mimetype; // varchar(50) + public $size; // int(4) + public $title; // varchar(255) + public $date; // int(4) + public $protected; // int(4) + public $filename; // varchar(255) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ @@ -116,7 +116,7 @@ class File extends Memcached_DataObject $x = File::staticGet($file_id); if (empty($x)) die('Impossible!'); } - + File_to_post::processNew($file_id, $notice_id); return $x; } @@ -145,5 +145,47 @@ class File extends Memcached_DataObject } return true; } + + // where should the file go? + + static function filename($notice_id, $basename) + { + return $notice_id . '-' . $basename; + } + + static function path($filename) + { + $dir = common_config('attachments', 'dir'); + + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } + + return $dir . $filename; + } + + static function url($filename) + { + $path = common_config('attachments', 'path'); + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('attachments', 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + // XXX: protocol + + return 'http://'.$server.$path.$filename; + } + } -- cgit v1.2.3-54-g00ecf From ef88758a374a47fb377aa5ceb41b0276558d3d33 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:49:08 -0700 Subject: ombqueuehandler uses commandline --- scripts/ombqueuehandler.php | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/scripts/ombqueuehandler.php b/scripts/ombqueuehandler.php index 4c5890f57..131b6513c 100755 --- a/scripts/ombqueuehandler.php +++ b/scripts/ombqueuehandler.php @@ -18,23 +18,22 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i'; +$longoptions = array('id'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_FACEBOOK_HELP; -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/omb.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/omb.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; set_error_handler('common_error_handler'); @@ -73,12 +72,15 @@ class OmbQueueHandler extends QueueHandler } } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} $handler = new OmbQueueHandler($id); -- cgit v1.2.3-54-g00ecf From 3cbdc684546544a2ba71ba36897b1ca24df92548 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:51:03 -0700 Subject: better help for ombqueuehandler --- scripts/ombqueuehandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ombqueuehandler.php b/scripts/ombqueuehandler.php index 131b6513c..deb5f8d7d 100755 --- a/scripts/ombqueuehandler.php +++ b/scripts/ombqueuehandler.php @@ -23,12 +23,12 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); $shortoptions = 'i'; $longoptions = array('id'); -$helptext = << Date: Mon, 22 Jun 2009 15:51:14 -0700 Subject: pingqueuehandler uses commandline --- scripts/pingqueuehandler.php | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/pingqueuehandler.php b/scripts/pingqueuehandler.php index 84ef9be27..1bde4bc5f 100644 --- a/scripts/pingqueuehandler.php +++ b/scripts/pingqueuehandler.php @@ -18,25 +18,22 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i'; +$longoptions = array('id'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; + -i --id Identity (default none) -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/ping.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +END_OF_PING_HELP; -set_error_handler('common_error_handler'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/ping.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; class PingQueueHandler extends QueueHandler { @@ -57,12 +54,15 @@ class PingQueueHandler extends QueueHandler { } } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : NULL; +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} $handler = new PingQueueHandler($id); -- cgit v1.2.3-54-g00ecf From 07cb587cda7f47db0b048576b79773d1ea9b6376 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:53:11 -0700 Subject: publicqueuehandler uses commandline --- scripts/publicqueuehandler.php | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index 017174ed8..c10c67910 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -18,25 +18,22 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'r'; +$longoptions = array('resource'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; + -r --resource Jabber Resource ID -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/jabber.php'); -require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); +END_OF_PUBLIC_HELP; -set_error_handler('common_error_handler'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/jabber.php'; +require_once INSTALLDIR . '/lib/xmppqueuehandler.php'; class PublicQueueHandler extends XmppQueueHandler { @@ -64,12 +61,15 @@ if (common_config('xmpp','enabled')==false) { exit(); } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$resource = ($argc > 1) ? $argv[1] : (common_config('xmpp','resource') . '-public'); +if (have_option('-r')) { + $resource = get_option_value('-r'); +} else if (have_option('--resource')) { + $resource = get_option_value('--resource'); +} else if (count($args) > 0) { + $resource = $args[0]; +} else { + $resource = null; +} $handler = new PublicQueueHandler($resource); -- cgit v1.2.3-54-g00ecf From f0e6e4b0ff8eec45a8c9e4b081d81b1d40c4b2bc Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:55:05 -0700 Subject: reportsnapshot.php supports commandline --- scripts/reportsnapshot.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/scripts/reportsnapshot.php b/scripts/reportsnapshot.php index e332d856c..c644b557f 100644 --- a/scripts/reportsnapshot.php +++ b/scripts/reportsnapshot.php @@ -18,20 +18,13 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(1); -} +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); +$helptext = << Date: Mon, 22 Jun 2009 16:00:05 -0700 Subject: add a function to show help --- scripts/commandline.inc | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/scripts/commandline.inc b/scripts/commandline.inc index 8da42873a..a245b2f16 100644 --- a/scripts/commandline.inc +++ b/scripts/commandline.inc @@ -65,6 +65,28 @@ $parser = new Console_Getopt(); list($options, $args) = $parser->getopt($argv, $shortoptions, $longoptions); +function show_help() +{ + global $helptext; + + $_default_help_text = << Use as config file + -s --server= Use as server name + -p --path= Use as path name + -h --help Show this message and quit. + +END_OF_DEFAULT; + if (isset($helptext)) { + print $helptext; + } + print $_default_help_text; + exit(0); +} + foreach ($options as $option) { switch ($option[0]) { @@ -85,22 +107,7 @@ foreach ($options as $option) { case '--help': case '-h': - $_default_help_text = << Use as config file - -s --server= Use as server name - -p --path= Use as path name - -h --help Show this message and quit. - -END_OF_DEFAULT; - if (isset($helptext)) { - print $helptext; - } - print $_default_help_text; - exit(0); + show_help(); } } -- cgit v1.2.3-54-g00ecf From 7721839efdf3a9b42ac94559425578a2285b042e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:00:19 -0700 Subject: setpassword.php uses commandline.inc --- scripts/setpassword.php | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/scripts/setpassword.php b/scripts/setpassword.php index c417f741a..b70689f03 100755 --- a/scripts/setpassword.php +++ b/scripts/setpassword.php @@ -18,30 +18,23 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(1); -} +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); +$helptext = << -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); +Sets the password of user with name to -require_once(INSTALLDIR . '/lib/common.php'); +END_OF_PASSWORD_HELP; -if ($argc != 3) { - print "USAGE: setpassword.php \n"; - print "Sets the password of user with name to \n"; - exit(1); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +if (count($args) < 2) { + show_help(); } -$nickname = $argv[1]; -$password = $argv[2]; +$nickname = $args[0]; +$password = $args[1]; if (mb_strlen($password) < 6) { print "Password must be 6 characters or more.\n"; -- cgit v1.2.3-54-g00ecf From 164ddf01c5d9259340b0fa2f4accc7b06c2c5379 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:04:35 -0700 Subject: Revert "note about Console_Getopt" This reverts commit e14322672cc24adc27efc2aeaafee60ef03ab650. Don't need it! --- README | 1 - 1 file changed, 1 deletion(-) diff --git a/README b/README index de1099600..cd663d931 100644 --- a/README +++ b/README @@ -180,7 +180,6 @@ and the URLs are listed here for your convenience. - PEAR HTTP_Request is an oEmbed dependency. - PEAR Validate is an oEmbed dependency. - PEAR Net_URL2 is an oEmbed dependency. -- Console_GetOpt for parsing command-line options. A design goal of Laconica is that the basic Web functionality should work on even the most restrictive commercial hosting services. -- cgit v1.2.3-54-g00ecf From 9fbb29111b8892d5ee1022f05019b7c99f8b8f12 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:04:50 -0700 Subject: Revert "Add Console_Getopt" This reverts commit 79dcf0871fee6dfa3835d12f55d1099a716a6f4c. --- extlib/Console/Getopt.php | 290 ---------------------------------------------- 1 file changed, 290 deletions(-) delete mode 100644 extlib/Console/Getopt.php diff --git a/extlib/Console/Getopt.php b/extlib/Console/Getopt.php deleted file mode 100644 index bb9d69ca2..000000000 --- a/extlib/Console/Getopt.php +++ /dev/null @@ -1,290 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $ - -require_once 'PEAR.php'; - -/** - * Command-line options parsing class. - * - * @author Andrei Zmievski - * - */ -class Console_Getopt { - /** - * Parses the command-line options. - * - * The first parameter to this function should be the list of command-line - * arguments without the leading reference to the running program. - * - * The second parameter is a string of allowed short options. Each of the - * option letters can be followed by a colon ':' to specify that the option - * requires an argument, or a double colon '::' to specify that the option - * takes an optional argument. - * - * The third argument is an optional array of allowed long options. The - * leading '--' should not be included in the option name. Options that - * require an argument should be followed by '=', and options that take an - * option argument should be followed by '=='. - * - * The return value is an array of two elements: the list of parsed - * options and the list of non-option command-line arguments. Each entry in - * the list of parsed options is a pair of elements - the first one - * specifies the option, and the second one specifies the option argument, - * if there was one. - * - * Long and short options can be mixed. - * - * Most of the semantics of this function are based on GNU getopt_long(). - * - * @param array $args an array of command-line arguments - * @param string $short_options specifies the list of allowed short options - * @param array $long_options specifies the list of allowed long options - * - * @return array two-element array containing the list of parsed options and - * the non-option arguments - * - * @access public - * - */ - function getopt2($args, $short_options, $long_options = null) - { - return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); - } - - /** - * This function expects $args to start with the script name (POSIX-style). - * Preserved for backwards compatibility. - * @see getopt2() - */ - function getopt($args, $short_options, $long_options = null) - { - return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); - } - - /** - * The actual implementation of the argument parsing code. - */ - function doGetopt($version, $args, $short_options, $long_options = null) - { - // in case you pass directly readPHPArgv() as the first arg - if (PEAR::isError($args)) { - return $args; - } - if (empty($args)) { - return array(array(), array()); - } - $opts = array(); - $non_opts = array(); - - settype($args, 'array'); - - if ($long_options) { - sort($long_options); - } - - /* - * Preserve backwards compatibility with callers that relied on - * erroneous POSIX fix. - */ - if ($version < 2) { - if (isset($args[0]{0}) && $args[0]{0} != '-') { - array_shift($args); - } - } - - reset($args); - while (list($i, $arg) = each($args)) { - - /* The special element '--' means explicit end of - options. Treat the rest of the arguments as non-options - and end the loop. */ - if ($arg == '--') { - $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); - break; - } - - if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { - $non_opts = array_merge($non_opts, array_slice($args, $i)); - break; - } elseif (strlen($arg) > 1 && $arg{1} == '-') { - $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); - if (PEAR::isError($error)) - return $error; - } elseif ($arg == '-') { - // - is stdin - $non_opts = array_merge($non_opts, array_slice($args, $i)); - break; - } else { - $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); - if (PEAR::isError($error)) - return $error; - } - } - - return array($opts, $non_opts); - } - - /** - * @access private - * - */ - function _parseShortOption($arg, $short_options, &$opts, &$args) - { - for ($i = 0; $i < strlen($arg); $i++) { - $opt = $arg{$i}; - $opt_arg = null; - - /* Try to find the short option in the specifier string. */ - if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') - { - return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); - } - - if (strlen($spec) > 1 && $spec{1} == ':') { - if (strlen($spec) > 2 && $spec{2} == ':') { - if ($i + 1 < strlen($arg)) { - /* Option takes an optional argument. Use the remainder of - the arg string if there is anything left. */ - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } - } else { - /* Option requires an argument. Use the remainder of the arg - string if there is anything left. */ - if ($i + 1 < strlen($arg)) { - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } else if (list(, $opt_arg) = each($args)) { - /* Else use the next argument. */; - if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { - return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); - } - } else { - return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); - } - } - } - - $opts[] = array($opt, $opt_arg); - } - } - - /** - * @access private - * - */ - function _isShortOpt($arg) - { - return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); - } - - /** - * @access private - * - */ - function _isLongOpt($arg) - { - return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && - preg_match('/[a-zA-Z]+$/', substr($arg, 2)); - } - - /** - * @access private - * - */ - function _parseLongOption($arg, $long_options, &$opts, &$args) - { - @list($opt, $opt_arg) = explode('=', $arg, 2); - $opt_len = strlen($opt); - - for ($i = 0; $i < count($long_options); $i++) { - $long_opt = $long_options[$i]; - $opt_start = substr($long_opt, 0, $opt_len); - $long_opt_name = str_replace('=', '', $long_opt); - - /* Option doesn't match. Go on to the next one. */ - if ($long_opt_name != $opt) { - continue; - } - - $opt_rest = substr($long_opt, $opt_len); - - /* Check that the options uniquely matches one of the allowed - options. */ - if ($i + 1 < count($long_options)) { - $next_option_rest = substr($long_options[$i + 1], $opt_len); - } else { - $next_option_rest = ''; - } - if ($opt_rest != '' && $opt{0} != '=' && - $i + 1 < count($long_options) && - $opt == substr($long_options[$i+1], 0, $opt_len) && - $next_option_rest != '' && - $next_option_rest{0} != '=') { - return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); - } - - if (substr($long_opt, -1) == '=') { - if (substr($long_opt, -2) != '==') { - /* Long option requires an argument. - Take the next argument if one wasn't specified. */; - if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { - return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); - } - if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { - return PEAR::raiseError("Console_Getopt: option requires an argument --$opt"); - } - } - } else if ($opt_arg) { - return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); - } - - $opts[] = array('--' . $opt, $opt_arg); - return; - } - - return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); - } - - /** - * Safely read the $argv PHP array across different PHP configurations. - * Will take care on register_globals and register_argc_argv ini directives - * - * @access public - * @return mixed the $argv PHP array or PEAR error if not registered - */ - function readPHPArgv() - { - global $argv; - if (!is_array($argv)) { - if (!@is_array($_SERVER['argv'])) { - if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { - return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); - } - return $GLOBALS['HTTP_SERVER_VARS']['argv']; - } - return $_SERVER['argv']; - } - return $argv; - } - -} - -?> -- cgit v1.2.3-54-g00ecf From 18ba41e0a4edd734d0bd6a991f5f9f301cd6e908 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:18:41 -0700 Subject: Revert "Revert "Add Console_Getopt"" This reverts commit 9fbb29111b8892d5ee1022f05019b7c99f8b8f12. --- extlib/Console/Getopt.php | 290 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 extlib/Console/Getopt.php diff --git a/extlib/Console/Getopt.php b/extlib/Console/Getopt.php new file mode 100644 index 000000000..bb9d69ca2 --- /dev/null +++ b/extlib/Console/Getopt.php @@ -0,0 +1,290 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } elseif ($arg == '-') { + // - is stdin + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) { + /* Else use the next argument. */; + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } else { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _isShortOpt($arg) + { + return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); + } + + /** + * @access private + * + */ + function _isLongOpt($arg) + { + return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && + preg_match('/[a-zA-Z]+$/', substr($arg, 2)); + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg, 2); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + $long_opt_name = str_replace('=', '', $long_opt); + + /* Option doesn't match. Go on to the next one. */ + if ($long_opt_name != $opt) { + continue; + } + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($i + 1 < count($long_options)) { + $next_option_rest = substr($long_options[$i + 1], $opt_len); + } else { + $next_option_rest = ''; + } + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len) && + $next_option_rest != '' && + $next_option_rest{0} != '=') { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument --$opt"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> -- cgit v1.2.3-54-g00ecf From 10cc0e157e86a51c5671630af267e4c9dd459619 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:18:50 -0700 Subject: Revert "Revert "note about Console_Getopt"" This reverts commit 164ddf01c5d9259340b0fa2f4accc7b06c2c5379. --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index cd663d931..de1099600 100644 --- a/README +++ b/README @@ -180,6 +180,7 @@ and the URLs are listed here for your convenience. - PEAR HTTP_Request is an oEmbed dependency. - PEAR Validate is an oEmbed dependency. - PEAR Net_URL2 is an oEmbed dependency. +- Console_GetOpt for parsing command-line options. A design goal of Laconica is that the basic Web functionality should work on even the most restrictive commercial hosting services. -- cgit v1.2.3-54-g00ecf From 118ab60cedb071dcab03d14d9d467556f5b5b15c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:26:18 -0700 Subject: change sitemap.php to use commandline.inc --- scripts/sitemap.php | 133 ++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 62 deletions(-) diff --git a/scripts/sitemap.php b/scripts/sitemap.php index 39eb859bb..88ca2ba7a 100755 --- a/scripts/sitemap.php +++ b/scripts/sitemap.php @@ -1,10 +1,37 @@ +#!/usr/bin/env php . + */ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/util.php'); +$shortoptions = 'f:d:u:'; + +$helptext = << Use as output file + -d Use for new sitemaps + -u Use as root for URLs + +END_OF_SITEMAP_HELP; + +require_once INSTALLDIR . '/scripts/commandline.inc'; $output_paths = parse_args(); @@ -13,11 +40,11 @@ notices_map(); user_map(); index_map(); -# ------------------------------------------------------------------------------ -# Main functions: get data out and turn them into sitemaps -# ------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ +// Main functions: get data out and turn them into sitemaps +// ------------------------------------------------------------------------------ -# Generate index sitemap of all other sitemaps. +// Generate index sitemap of all other sitemaps. function index_map() { global $output_paths; @@ -26,7 +53,7 @@ function index_map() foreach (glob("$output_dir*.xml") as $file_name) { - # Just the file name please. + // Just the file name please. $file_name = preg_replace("|$output_dir|", '', $file_name); $index_urls .= sitemap( @@ -40,7 +67,7 @@ function index_map() write_file($output_paths['index_file'], sitemapindex($index_urls)); } -# Generate sitemap of standard site elements. +// Generate sitemap of standard site elements. function standard_map() { global $output_paths; @@ -61,7 +88,7 @@ function standard_map() ) ); - $docs = array('about', 'faq', 'contact', 'im', 'openid', 'openmublog', + $docs = array('about', 'faq', 'contact', 'im', 'openid', 'openmublog', 'privacy', 'source', 'badge'); foreach($docs as $title) { @@ -79,7 +106,7 @@ function standard_map() write_file($urlset_path, urlset($standard_map_urls)); } -# Generate sitemaps of all notices. +// Generate sitemaps of all notices. function notices_map() { global $output_paths; @@ -93,14 +120,14 @@ function notices_map() while ($notices->fetch()) { - # Maximum 50,000 URLs per sitemap file. + // Maximum 50,000 URLs per sitemap file. if ($notice_count == 50000) { $notice_count = 0; $map_count++; } - # remote notices have an URL - + // remote notices have an URL + if (!$notices->url && $notices->uri) { $notice = array( 'url' => ($notices->uri) ? $notices->uri : common_local_url('shownotice', array('notice' => $notices->id)), @@ -114,11 +141,11 @@ function notices_map() } } - # Make full sitemaps from the lists and save them. + // Make full sitemaps from the lists and save them. array_to_map($notice_list, 'notice'); } -# Generate sitemaps of all users. +// Generate sitemaps of all users. function user_map() { global $output_paths; @@ -132,7 +159,7 @@ function user_map() while ($users->fetch()) { - # Maximum 50,000 URLs per sitemap file. + // Maximum 50,000 URLs per sitemap file. if ($user_count == 50000) { $user_count = 0; $map_count++; @@ -140,7 +167,7 @@ function user_map() $user_args = array('nickname' => $users->nickname); - # Define parameters for generating elements. + // Define parameters for generating elements. $user = array( 'url' => common_local_url('showstream', $user_args), 'changefreq' => 'daily', @@ -183,8 +210,8 @@ function user_map() 'priority' => '0.5', ); - # Construct a element for each user facet and add it - # to our existing list of those. + // Construct a element for each user facet and add it + // to our existing list of those. $user_list[$map_count] .= url($user); $user_rss_list[$map_count] .= url($user_rss); $all_list[$map_count] .= url($all); @@ -196,9 +223,9 @@ function user_map() $user_count++; } - # Make full sitemaps from the lists and save them. - # Possible factoring: put all the lists into a master array, thus allowing - # calling with single argument (i.e., array_to_map('user')). + // Make full sitemaps from the lists and save them. + // Possible factoring: put all the lists into a master array, thus allowing + // calling with single argument (i.e., array_to_map('user')). array_to_map($user_list, 'user'); array_to_map($user_rss_list, 'user_rss'); array_to_map($all_list, 'all'); @@ -208,14 +235,14 @@ function user_map() array_to_map($foaf_list, 'foaf'); } -# ------------------------------------------------------------------------------ -# XML generation functions -# ------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ +// XML generation functions +// ------------------------------------------------------------------------------ -# Generate a element. +// Generate a element. function url($url_args) { - $url = preg_replace('/&/', '&', $url_args['url']); # escape ampersands for XML + $url = preg_replace('/&/', '&', $url_args['url']); // escape ampersands for XML $lastmod = $url_args['lastmod']; $changefreq = $url_args['changefreq']; $priority = $url_args['priority']; @@ -246,7 +273,7 @@ function url($url_args) function sitemap($sitemap_args) { - $url = preg_replace('/&/', '&', $sitemap_args['url']); # escape ampersands for XML + $url = preg_replace('/&/', '&', $sitemap_args['url']); // escape ampersands for XML $lastmod = $sitemap_args['lastmod']; if (is_null($url)) { @@ -265,7 +292,7 @@ function sitemap($sitemap_args) return $sitemap_out; } -# Generate a element. +// Generate a element. function urlset($urlset_text) { $urlset = '' . "\n" . @@ -276,7 +303,7 @@ function urlset($urlset_text) return $urlset; } -# Generate a element. +// Generate a element. function sitemapindex($sitemapindex_text) { $sitemapindex = '' . "\n" . @@ -287,49 +314,31 @@ function sitemapindex($sitemapindex_text) return $sitemapindex; } -# Generate a sitemap from an array containing elements and write it to a file. +// Generate a sitemap from an array containing elements and write it to a file. function array_to_map($url_list, $filename_prefix) { global $output_paths; if ($url_list) { - # $map_urls is a long string containing concatenated elements. + // $map_urls is a long string containing concatenated elements. while (list($map_idx, $map_urls) = each($url_list)) { $urlset_path = $output_paths['output_dir'] . "$filename_prefix-$map_idx.xml"; - + write_file($urlset_path, urlset($map_urls)); } } } -# ------------------------------------------------------------------------------ -# Internal functions -# ------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ +// Internal functions +// ------------------------------------------------------------------------------ -# Parse command line arguments. +// Parse command line arguments. function parse_args() { - $args = getopt('f:d:u:'); - - if (is_null($args[f]) && is_null($args[d]) && is_null($args[u])) { - error('Mandatory arguments: -f -d -u '); - } - - if (is_null($args[f])) { - error('You must specify an index file name with the -f option.'); - } - - if (is_null($args[d])) { - error('You must specify a directory for the output file with the -d option.'); - } - - if (is_null($args[u])) { - error('You must specify a URL for the directory where the sitemaps will be kept with the -u option.'); - } - - $index_file = $args[f]; - $output_dir = $args[d]; - $output_url = $args[u]; + $index_file = get_option_value('f'); + $output_dir = get_option_value('d'); + $output_url = get_option_value('u'); if (file_exists($output_dir)) { if (is_writable($output_dir) === false) { @@ -348,7 +357,7 @@ function parse_args() return $paths; } -# Ensure paths end with a "/". +// Ensure paths end with a "/". function trailing_slash($path) { if (preg_match('/\/$/', $path) == 0) { @@ -358,7 +367,7 @@ function trailing_slash($path) return $path; } -# Write data to disk. +// Write data to disk. function write_file($path, $data) { if (is_null($path)) { @@ -376,7 +385,7 @@ function write_file($path, $data) } } -# Display an error message and exit. +// Display an error message and exit. function error ($error_msg) { if (is_null($error_msg)) { -- cgit v1.2.3-54-g00ecf From 8525165dc90954fcad32d44cbee4ef811eb2aece Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:29:01 -0700 Subject: change smsqueuehandler to use commandline --- scripts/smsqueuehandler.php | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/scripts/smsqueuehandler.php b/scripts/smsqueuehandler.php index 0366d4c4c..c793ee550 100755 --- a/scripts/smsqueuehandler.php +++ b/scripts/smsqueuehandler.php @@ -18,29 +18,25 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i::'; +$longoptions = array('id::'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_SMS_HELP; -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/mail.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; -set_error_handler('common_error_handler'); +require_once INSTALLDIR . '/lib/mail.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; class SmsQueueHandler extends QueueHandler { - function transport() { return 'sms'; @@ -62,12 +58,15 @@ class SmsQueueHandler extends QueueHandler } } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} $handler = new SmsQueueHandler($id); -- cgit v1.2.3-54-g00ecf From 1951246d67dfe41f2dfa722d1487baedf74c3081 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:31:13 -0700 Subject: synctwitterfriends.php uses commandline.inc --- scripts/synctwitterfriends.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index 7f418894e..fe53ff44d 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -18,24 +18,16 @@ * along with this program. If not, see . */ -// Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); // Uncomment this to get useful console output -//define('SCRIPT_DEBUG', true); -// Preset the server at the command line +$helptext = << 1) ? $argv[1] : null; -$path = ($argc > 2) ? $argv[2] : null; +END_OF_TWITTER_HELP; -require_once(INSTALLDIR . '/lib/common.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; // Make a lockfile $lockfilename = lockFilename(); -- cgit v1.2.3-54-g00ecf From 0582381c6631cb8b8e914cebbcf2e387b947c83f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:34:56 -0700 Subject: triminboxes.php uses commandline.inc --- scripts/triminboxes.php | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php index 0d545b326..5575dd4fc 100644 --- a/scripts/triminboxes.php +++ b/scripts/triminboxes.php @@ -18,31 +18,37 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(1); -} +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); +$shortoptions = 'u::'; +$longoptions = array('start-user-id::'); -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); +$helptext = << + --start-user-id= User ID to start after. Default is all. -$server = ($argc > 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_TRIM_HELP; -require_once(INSTALLDIR . '/lib/common.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +$id = null; + +if (have_option('-u')) { + $id = get_option_value('-u'); +} else if (have_option('--start-user-id')) { + $id = get_option_value('--start-user-id'); +} else { + $id = null; +} $user = new User(); -if ($argc > 1) { - $user->whereAdd('id > ' . $argv[1]); + +if (!empty($id)) { + $user->whereAdd('id > ' . $id); } + $cnt = $user->find(); while ($user->fetch()) { -- cgit v1.2.3-54-g00ecf From 1691998de87c8f3a0d8e79d633be8ed9f956ce51 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:35:10 -0700 Subject: make id optional for enjitqueuehandler --- scripts/enjitqueuehandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 509134765..05e1d9366 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -20,8 +20,8 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'i'; -$longoptions = array('id'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << Date: Mon, 22 Jun 2009 16:37:15 -0700 Subject: twitterqueuehandler.php uses commandline.inc --- scripts/twitterqueuehandler.php | 42 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/scripts/twitterqueuehandler.php b/scripts/twitterqueuehandler.php index d6fb17cc8..826e12c75 100755 --- a/scripts/twitterqueuehandler.php +++ b/scripts/twitterqueuehandler.php @@ -18,29 +18,25 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'i::'; +$longoptions = array('id::'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +END_OF_ENJIT_HELP; -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/twitter.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; -set_error_handler('common_error_handler'); +require_once INSTALLDIR . '/lib/twitter.php'; +require_once INSTALLDIR . '/lib/queuehandler.php'; class TwitterQueueHandler extends QueueHandler { - function transport() { return 'twitter'; @@ -63,13 +59,15 @@ class TwitterQueueHandler extends QueueHandler } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); - -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; +if (have_option('-i')) { + $id = get_option_value('-i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} $handler = new TwitterQueueHandler($id); -- cgit v1.2.3-54-g00ecf From fa5e4f88c9671456c171613a682d89c5681e576a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:39:21 -0700 Subject: twitterstatusfetcher.php uses commandline.inc --- scripts/twitterstatusfetcher.php | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index c18261b5b..5ffdda58f 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -18,27 +18,19 @@ * along with this program. If not, see . */ -// Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); // Tune number of processes and how often to poll Twitter // XXX: Should these things be in config.php? define('MAXCHILDREN', 2); define('POLL_INTERVAL', 60); // in seconds -// Uncomment this to get useful logging -// define('SCRIPT_DEBUG', true); +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; +require_once INSTALLDIR.'/scripts/commandline.inc'; require_once INSTALLDIR . '/lib/common.php'; require_once INSTALLDIR . '/lib/daemon.php'; @@ -631,10 +623,6 @@ class TwitterStatusFetcher extends Daemon } } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); declare(ticks = 1); $fetcher = new TwitterStatusFetcher(); -- cgit v1.2.3-54-g00ecf From de033bce88842c931180c332d8fec3df9b5ff342 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:44:20 -0700 Subject: uncache_users.php uses commandline.inc --- scripts/uncache_users.php | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/scripts/uncache_users.php b/scripts/uncache_users.php index e35ea81ea..b0b576eb4 100644 --- a/scripts/uncache_users.php +++ b/scripts/uncache_users.php @@ -17,32 +17,27 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -# Abort if called from a web server - -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} +$helptext = << -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); +Uncache users listed in an ID file, default 'ids.txt'. -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); +ENDOFHELP; -require_once(INSTALLDIR . '/lib/common.php'); +require_once INSTALLDIR.'/scripts/commandline.inc'; -$id_file = ($argc > 1) ? $argv[1] : 'ids.txt'; +$id_file = (count($args) > 1) ? $args[0] : 'ids.txt'; common_log(LOG_INFO, 'Updating user inboxes.'); $ids = file($id_file); +$memc = common_memcache(); + foreach ($ids as $id) { - + $user = User::staticGet('id', $id); if (!$user) { @@ -51,9 +46,7 @@ foreach ($ids as $id) { } $user->decache(); - - $memc = common_memcache(); - + $memc->delete(common_cache_key('user:notices_with_friends:'. $user->id)); $memc->delete(common_cache_key('user:notices_with_friends:'. $user->id . ';last')); } -- cgit v1.2.3-54-g00ecf From 010d168aaa908073d03be66259042f921dfb861e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:44:29 -0700 Subject: correctly detect default short options --- scripts/commandline.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/commandline.inc b/scripts/commandline.inc index a245b2f16..4a7757fb9 100644 --- a/scripts/commandline.inc +++ b/scripts/commandline.inc @@ -91,22 +91,22 @@ foreach ($options as $option) { switch ($option[0]) { case '--server': - case '-s': + case 's': $server = $option[1]; break; case '--path': - case '-p': + case 'p': $path = $option[1]; break; case '--conf': - case '-c': + case 'c': $conffile = $option[1]; break; case '--help': - case '-h': + case 'h': show_help(); } } -- cgit v1.2.3-54-g00ecf From 3fc2cfb7f81cca483be7255e20245c8fea2fe0d8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:48:04 -0700 Subject: fix have_options arguments --- scripts/facebookqueuehandler.php | 8 ++++---- scripts/jabberqueuehandler.php | 10 +++++----- scripts/ombqueuehandler.php | 8 ++++---- scripts/pingqueuehandler.php | 8 ++++---- scripts/publicqueuehandler.php | 8 ++++---- scripts/smsqueuehandler.php | 4 ++-- scripts/triminboxes.php | 4 ++-- scripts/twitterqueuehandler.php | 4 ++-- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/scripts/facebookqueuehandler.php b/scripts/facebookqueuehandler.php index f01e45a3b..05a35577f 100755 --- a/scripts/facebookqueuehandler.php +++ b/scripts/facebookqueuehandler.php @@ -20,8 +20,8 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'i'; -$longoptions = array('id'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index be0f187a9..a44993236 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -20,13 +20,13 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r'; -$longoptions = array('resource'); +$shortoptions = 'r::'; +$longoptions = array('resource::'); $helptext = << 0) { diff --git a/scripts/ombqueuehandler.php b/scripts/ombqueuehandler.php index deb5f8d7d..1587192b6 100755 --- a/scripts/ombqueuehandler.php +++ b/scripts/ombqueuehandler.php @@ -20,8 +20,8 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'i'; -$longoptions = array('id'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { diff --git a/scripts/pingqueuehandler.php b/scripts/pingqueuehandler.php index 1bde4bc5f..23678ea4b 100644 --- a/scripts/pingqueuehandler.php +++ b/scripts/pingqueuehandler.php @@ -20,8 +20,8 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'i'; -$longoptions = array('id'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index c10c67910..58ecc1745 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -20,8 +20,8 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r'; -$longoptions = array('resource'); +$shortoptions = 'r::'; +$longoptions = array('resource::'); $helptext = << 0) { diff --git a/scripts/smsqueuehandler.php b/scripts/smsqueuehandler.php index c793ee550..94b846d98 100755 --- a/scripts/smsqueuehandler.php +++ b/scripts/smsqueuehandler.php @@ -58,8 +58,8 @@ class SmsQueueHandler extends QueueHandler } } -if (have_option('-i')) { - $id = get_option_value('-i'); +if (have_option('i')) { + $id = get_option_value('i'); } else if (have_option('--id')) { $id = get_option_value('--id'); } else if (count($args) > 0) { diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php index 5575dd4fc..b2135d682 100644 --- a/scripts/triminboxes.php +++ b/scripts/triminboxes.php @@ -35,8 +35,8 @@ require_once INSTALLDIR.'/scripts/commandline.inc'; $id = null; -if (have_option('-u')) { - $id = get_option_value('-u'); +if (have_option('u')) { + $id = get_option_value('u'); } else if (have_option('--start-user-id')) { $id = get_option_value('--start-user-id'); } else { diff --git a/scripts/twitterqueuehandler.php b/scripts/twitterqueuehandler.php index 826e12c75..00e735d98 100755 --- a/scripts/twitterqueuehandler.php +++ b/scripts/twitterqueuehandler.php @@ -59,8 +59,8 @@ class TwitterQueueHandler extends QueueHandler } -if (have_option('-i')) { - $id = get_option_value('-i'); +if (have_option('i')) { + $id = get_option_value('i'); } else if (have_option('--id')) { $id = get_option_value('--id'); } else if (count($args) > 0) { -- cgit v1.2.3-54-g00ecf From 5b5da5154d5a93bd4c55f43c17c3bd1516b7cc34 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:52:59 -0700 Subject: decache.php uses commandline.inc --- scripts/decache.php | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/scripts/decache.php b/scripts/decache.php index b18eaa2cd..90e1ec63c 100644 --- a/scripts/decache.php +++ b/scripts/decache.php @@ -18,35 +18,26 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(1); -} - -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); +$helptext = << [] +Clears the cache for the object in table with id +If is specified, use that instead of 'id' +ENDOFHELP; -if ($argc < 3 || $argc > 4) { - print "USAGE: decache.php
      []\n"; - print "Clears the cache for the object in table
      with id .\n\n"; - print "If is specified, use that instead of 'id'\n"; - exit(1); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +if (count($args) < 2 || count($args) > 3) { + show_help(); } -$table = $argv[1]; -$id = $argv[2]; -if ($argc > 3) { - $column = $argv[3]; +$table = $args[0]; +$id = $args[1]; +if (count($args) > 2) { + $column = $args[2]; } else { - $colum = 'id'; + $column = 'id'; } $object = Memcached_DataObject::staticGet($table, $column, $id); -- cgit v1.2.3-54-g00ecf From eced917d7965ab9b630bf0fe7ac031ac06ff7939 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 16:54:21 -0700 Subject: getpiddir.php uses commandline.inc --- scripts/getpiddir.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/scripts/getpiddir.php b/scripts/getpiddir.php index d29c95cb0..9927cc6d9 100755 --- a/scripts/getpiddir.php +++ b/scripts/getpiddir.php @@ -18,15 +18,13 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); +$helptext = << Date: Mon, 22 Jun 2009 16:55:55 -0700 Subject: getvaliddaemons.php uses commandline.inc --- scripts/getvaliddaemons.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index a45ff79ab..198ea8fb9 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -25,16 +25,14 @@ * daemon names. */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); +$helptext = << Date: Mon, 22 Jun 2009 16:57:28 -0700 Subject: inbox_users.php uses commandline.inc --- scripts/inbox_users.php | 52 +++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/scripts/inbox_users.php b/scripts/inbox_users.php index 6d3656d2e..4883fea20 100755 --- a/scripts/inbox_users.php +++ b/scripts/inbox_users.php @@ -20,59 +20,55 @@ # Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); +$helptext = << -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); +Update users to use inbox table. Listed in an ID file, default 'ids.txt'. -require_once(INSTALLDIR . '/lib/common.php'); +ENDOFHELP; -$id_file = ($argc > 1) ? $argv[1] : 'ids.txt'; +require_once INSTALLDIR.'/scripts/commandline.inc'; + +$id_file = (count($args) > 1) ? $args[0] : 'ids.txt'; common_log(LOG_INFO, 'Updating user inboxes.'); $ids = file($id_file); foreach ($ids as $id) { - + $user = User::staticGet('id', $id); if (!$user) { common_log(LOG_WARNING, 'No such user: ' . $id); continue; } - + if ($user->inboxed) { common_log(LOG_WARNING, 'Already inboxed: ' . $id); continue; } - + common_log(LOG_INFO, 'Updating inbox for user ' . $user->id); - + $user->query('BEGIN'); - + $old_inbox = new Notice_inbox(); $old_inbox->user_id = $user->id; - + $result = $old_inbox->delete(); - + if (is_null($result) || $result === false) { common_log_db_error($old_inbox, 'DELETE', __FILE__); continue; } $old_inbox->free(); - + $inbox = new Notice_inbox(); - + $result = $inbox->query('INSERT INTO notice_inbox (user_id, notice_id, created) ' . 'SELECT ' . $user->id . ', notice.id, notice.created ' . 'FROM subscription JOIN notice ON subscription.subscribed = notice.profile_id ' . @@ -80,30 +76,30 @@ foreach ($ids as $id) { 'AND notice.created >= subscription.created ' . 'AND NOT EXISTS (SELECT user_id, notice_id ' . 'FROM notice_inbox ' . - 'WHERE user_id = ' . $user->id . ' ' . + 'WHERE user_id = ' . $user->id . ' ' . 'AND notice_id = notice.id) ' . 'ORDER BY notice.created DESC ' . 'LIMIT 0, 1000'); - + if (is_null($result) || $result === false) { common_log_db_error($inbox, 'INSERT', __FILE__); continue; } - + $orig = clone($user); $user->inboxed = 1; $result = $user->update($orig); - + if (!$result) { common_log_db_error($user, 'UPDATE', __FILE__); continue; } - + $user->query('COMMIT'); - + $inbox->free(); unset($inbox); - + if ($cache) { $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); -- cgit v1.2.3-54-g00ecf From 66316c0ce637816f172ffcc680cbb89f393f17e6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 17:00:53 -0700 Subject: fixup_utf8.php uses commandline.inc --- scripts/fixup_utf8.php | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 169376091..8c9a9127f 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -19,21 +19,18 @@ */ # Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(1); -} - -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); -require_once('DB.php'); +$helptext = << + +Fixup records in a database that stored the data incorrectly (pre-0.7.4 for Laconica). + +ENDOFHELP; + +require_once INSTALLDIR.'/scripts/commandline.inc'; +require_once 'DB.php'; class UTF8FixerUpper { @@ -356,9 +353,9 @@ class UTF8FixerUpper } } -$max_date = ($argc > 1) ? $argv[1] : null; -$max_id = ($argc > 2) ? $argv[2] : null; -$min_id = ($argc > 3) ? $argv[3] : null; +$max_date = (count($args) > 0) ? $args[0] : null; +$max_id = (count($args) > 1) ? $args[1] : null; +$min_id = (count($args) > 2) ? $args[2] : null; $fixer = new UTF8FixerUpper(array('max_date' => $max_date, 'max_notice' => $max_id, -- cgit v1.2.3-54-g00ecf From 0b638a233cb97668b340c1321c61b305966805a9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 17:02:40 -0700 Subject: maildaemon.php uses commandline.inc --- scripts/maildaemon.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index dc3ab0b56..cfb11a36f 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -18,21 +18,16 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$helptext = << 1) ? $argv[1] : null; -$path = ($argc > 2) ? $argv[2] : null; +require_once INSTALLDIR.'/scripts/commandline.inc'; -require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once('Mail/mimeDecode.php'); -- cgit v1.2.3-54-g00ecf From ef3251634ca4d62c92a1ea65fcc04989c6bf1df4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 17:04:49 -0700 Subject: xmppconfirmhandler.php uses commandline.inc --- scripts/xmppconfirmhandler.php | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index 217481d65..883934fd6 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -18,31 +18,26 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'r::'; +$longoptions = array('resource::'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; + -r --resource Jabber Resource ID (default to config) -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/jabber.php'); -require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); +END_OF_JABBER_HELP; -set_error_handler('common_error_handler'); +require_once INSTALLDIR.'/scripts/commandline.inc'; +require_once INSTALLDIR . '/lib/jabber.php'; +require_once INSTALLDIR . '/lib/xmppqueuehandler.php'; define('CLAIM_TIMEOUT', 1200); class XmppConfirmHandler extends XmppQueueHandler { - var $_id = 'confirm'; function class_name() @@ -152,12 +147,15 @@ if (common_config('xmpp','enabled')==false) { exit(); } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$resource = ($argc > 1) ? $argv[1] : (common_config('xmpp', 'resource').'-confirm'); +if (have_option('r')) { + $resource = get_option_value('r'); +} else if (have_option('--resource')) { + $resource = get_option_value('--resource'); +} else if (count($args) > 0) { + $resource = $args[0]; +} else { + $resource = null; +} $handler = new XmppConfirmHandler($resource); -- cgit v1.2.3-54-g00ecf From 875e122a24987dcd46c45f0f8823ab2a49dfb031 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 17:07:14 -0700 Subject: xmppdaemon.php uses commandline.inc --- scripts/xmppdaemon.php | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index 0f98becda..661631937 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -18,25 +18,23 @@ * along with this program. If not, see . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -// Preset the server at the command line +$shortoptions = 'r::'; +$longoptions = array('resource::'); + +$helptext = << 2) ? $argv[2] : null; -$path = ($argc > 3) ? $argv[3] : null; + -r --resource Jabber Resource ID (default to config) -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/jabber.php'); -require_once(INSTALLDIR . '/lib/daemon.php'); +END_OF_XMPP_HELP; -set_error_handler('common_error_handler'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +require_once INSTALLDIR . '/lib/common.php'; +require_once INSTALLDIR . '/lib/jabber.php'; +require_once INSTALLDIR . '/lib/daemon.php'; # This is kind of clunky; we create a class to call the global functions # in jabber.php, which create a new XMPP class. A more elegant (?) solution @@ -325,12 +323,15 @@ if (common_config('xmpp','enabled')==false) { exit(); } -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$resource = ($argc > 1) ? $argv[1] : (common_config('xmpp','resource') . '-listen'); +if (have_option('r')) { + $resource = get_option_value('r'); +} else if (have_option('--resource')) { + $resource = get_option_value('--resource'); +} else if (count($args) > 0) { + $resource = $args[0]; +} else { + $resource = null; +} $daemon = new XMPPDaemon($resource); -- cgit v1.2.3-54-g00ecf From ccd9cdd6183ac479ef8e88e61814c3209b428eb3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 05:16:23 -0700 Subject: Add System_Command so MIME type fallback works for uploaded files --- extlib/System/Command.php | 587 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 extlib/System/Command.php diff --git a/extlib/System/Command.php b/extlib/System/Command.php new file mode 100644 index 000000000..f5c3ec6b9 --- /dev/null +++ b/extlib/System/Command.php @@ -0,0 +1,587 @@ + | +// | Author: Dan Allen +// +----------------------------------------------------------------------+ + +// $Id: Command.php,v 1.9 2007/04/20 21:08:48 cconstantine Exp $ + +// }}} +// {{{ includes + +require_once 'PEAR.php'; +require_once 'System.php'; + +// }}} +// {{{ constants + +define('SYSTEM_COMMAND_OK', 1); +define('SYSTEM_COMMAND_ERROR', -1); +define('SYSTEM_COMMAND_NO_SHELL', -2); +define('SYSTEM_COMMAND_INVALID_SHELL', -3); +define('SYSTEM_COMMAND_TMPDIR_ERROR', -4); +define('SYSTEM_COMMAND_INVALID_OPERATOR', -5); +define('SYSTEM_COMMAND_INVALID_COMMAND', -6); +define('SYSTEM_COMMAND_OPERATOR_PLACEMENT',-7); +define('SYSTEM_COMMAND_COMMAND_PLACEMENT', -8); +define('SYSTEM_COMMAND_NOHUP_MISSING', -9); +define('SYSTEM_COMMAND_NO_OUTPUT', -10); +define('SYSTEM_COMMAND_STDERR', -11); +define('SYSTEM_COMMAND_NONZERO_EXIT', -12); + +// }}} + +// {{{ class System_Command + +/** + * The System_Command:: class implements an abstraction for various ways + * of executing commands (directly using the backtick operator, + * as a background task after the script has terminated using + * register_shutdown_function() or as a detached process using nohup). + * + * @author Anders Johannsen + * @author Dan Allen + * @version $Revision: 1.9 $ + */ + +// }}} +class System_Command { + // {{{ properties + + /** + * Array of settings used when creating the shell command + * + * @var array + * @access private + */ + var $options = array(); + + /** + * Array of available shells to use to execute the command + * + * @var array + * @access private + */ + var $shells = array(); + + /** + * Array of available control operators used between commands + * + * @var array + * @access private + */ + var $controlOperators = array(); + + /** + * The system command to be executed + * + * @var string + * @access private + */ + var $systemCommand = null; + + /** + * Previously added part to the command string + * + * @var string + * @access private + */ + var $previousElement = null; + + /** + * Directory for writing stderr output + * + * @var string + * @access private + */ + var $tmpDir = null; + + /** + * To allow the pear error object to accumulate when building + * the command, we use the command status to keep track when + * a pear error is raised + * + * @var int + * @access private + */ + var $commandStatus = 0; + + /** + * Hold initialization PEAR_Error + * + * @var object + * @access private + **/ + var $_initError = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * Defines all necessary constants and sets defaults + * + * @access public + */ + function System_Command($in_shell = null) + { + // Defining constants + $this->options = array( + 'SEQUENCE' => true, + 'SHUTDOWN' => false, + 'SHELL' => $this->which($in_shell), + 'OUTPUT' => true, + 'NOHUP' => false, + 'BACKGROUND' => false, + 'STDERR' => false + ); + + // prepare the available control operators + $this->controlOperators = array( + 'PIPE' => '|', + 'AND' => '&&', + 'OR' => '||', + 'GROUP' => ';', + 'LFIFO' => '<', + 'RFIFO' => '>', + ); + + // List of allowed/available shells + $this->shells = array( + 'sh', + 'bash', + 'zsh', + 'tcsh', + 'csh', + 'ash', + 'sash', + 'esh', + 'ksh' + ); + + // Find the first available shell + if (empty($this->options['SHELL'])) { + foreach ($this->shells as $shell) { + if ($this->options['SHELL'] = $this->which($shell)) { + break; + } + } + + // see if we still have no shell + if (empty($this->options['SHELL'])) { + $this->_initError =& PEAR::raiseError(null, SYSTEM_COMMAND_NO_SHELL, null, E_USER_WARNING, null, 'System_Command_Error', true); + return; + } + } + + // Caputre a temporary directory for capturing stderr from commands + $this->tmpDir = System::tmpdir(); + if (!System::mkDir("-p {$this->tmpDir}")) { + $this->_initError =& PEAR::raiseError(null, SYSTEM_COMMAND_TMPDIR_ERROR, null, E_USER_WARNING, null, 'System_Command_Error', true); + return; + } + } + + // }}} + // {{{ setOption() + + /** + * Sets the value for an option. Each option should be set to true + * or false; except the 'SHELL' option which should be a string + * naming a shell. The options are: + * + * 'SEQUENCE' Allow a sequence command or not (right now this is always on); + * + * 'SHUTDOWN' Execute commands via a shutdown function; + * + * 'SHELL' Path to shell; + * + * 'OUTPUT' Output stdout from process; + * + * 'NOHUP' Use nohup to detach process; + * + * 'BACKGROUND' Run as a background process with &; + * + * 'STDERR' Output on stderr will raise an error, even if + * the command's exit value is zero. The output from + * stderr can be retrieved using the getDebugInfo() + * method of the Pear_ERROR object returned by + * execute().; + * + * @param string $in_option is a case-sensitive string, + * corresponding to the option + * that should be changed + * @param mixed $in_setting is the new value for the option + * @access public + * @return bool true if succes, else false + */ + function setOption($in_option, $in_setting) + { + if ($this->_initError) { + return $this->_initError; + } + + $option = strtoupper($in_option); + + if (!isset($this->options[$option])) { + PEAR::raiseError(null, SYSTEM_COMMAND_ERROR, null, E_USER_NOTICE, null, 'System_Command_Error', true); + return false; + } + + switch ($option) { + case 'OUTPUT': + case 'SHUTDOWN': + case 'SEQUENCE': + case 'BACKGROUND': + case 'STDERR': + $this->options[$option] = !empty($in_setting); + return true; + break; + + case 'SHELL': + if (($shell = $this->which($in_setting)) !== false) { + $this->options[$option] = $shell; + return true; + } + else { + PEAR::raiseError(null, SYSTEM_COMMAND_NO_SHELL, null, E_USER_NOTICE, $in_setting, 'System_Command_Error', true); + return false; + } + break; + + case 'NOHUP': + if (empty($in_setting)) { + $this->options[$option] = false; + } + else if ($location = $this->which('nohup')) { + $this->options[$option] = $location; + } + else { + PEAR::raiseError(null, SYSTEM_COMMAND_NOHUP_MISSING, null, E_USER_NOTICE, null, 'System_Command_Error', true); + return false; + } + break; + } + } + + // }}} + // {{{ pushCommand() + + /** + * Used to push a command onto the running command to be executed + * + * @param string $in_command binary to be run + * @param string $in_argument either an option or argument value, to be handled appropriately + * @param string $in_argument + * @param ... + * + * @access public + * @return boolean true on success {or System_Command_Error Exception} + */ + function pushCommand($in_command) + { + if ($this->_initError) { + return $this->_initError; + } + + if (!is_null($this->previousElement) && !in_array($this->previousElement, $this->controlOperators)) { + $this->commandStatus = -1; + $error = PEAR::raiseError(null, SYSTEM_COMMAND_COMMAND_PLACEMENT, null, E_USER_WARNING, null, 'System_Command_Error', true); + } + + // check for error here + $command = escapeshellcmd($this->which($in_command)); + if ($command === false) { + $error = PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, null, 'System_Command_Error', true); + } + + $argv = func_get_args(); + array_shift($argv); + foreach($argv as $arg) { + if (strpos($arg, '-') === 0) { + $command .= ' ' . $arg; + } + elseif ($arg != '') { + $command .= ' ' . escapeshellarg($arg); + } + } + + $this->previousElement = $command; + $this->systemCommand .= $command; + + return isset($error) ? $error : true; + } + + // }}} + // {{{ pushOperator() + + /** + * Used to push an operator onto the running command to be executed + * + * @param string $in_operator Either string reprentation of operator or system character + * + * @access public + * @return boolean true on success {or System_Command_Error Exception} + */ + function pushOperator($in_operator) + { + if ($this->_initError) { + return $this->_initError; + } + + $operator = isset($this->controlOperators[$in_operator]) ? $this->controlOperators[$in_operator] : $in_operator; + + if (is_null($this->previousElement) || in_array($this->previousElement, $this->controlOperators)) { + $this->commandStatus = -1; + $error = PEAR::raiseError(null, SYSTEM_COMMAND_OPERATOR_PLACEMENT, null, E_USER_WARNING, null, 'System_Command_Error', true); + } + elseif (!in_array($operator, $this->controlOperators)) { + $this->commandStatus = -1; + $error = PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_OPERATOR, null, E_USER_WARNING, $operator, 'System_Command_Error', true); + } + + $this->previousElement = $operator; + $this->systemCommand .= ' ' . $operator . ' '; + return isset($error) ? $error : true; + } + + // }}} + // {{{ execute() + + /** + * Executes the code according to given options + * + * @return bool true if success {or System_Command_Exception} + * + * @access public + */ + function execute() + { + if ($this->_initError) { + return $this->_initError; + } + + // if the command is empty or if the last element was a control operator, we can't continue + if (is_null($this->previousElement) || $this->commandStatus == -1 || in_array($this->previousElement, $this->controlOperators)) { + return PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, $this->systemCommand, 'System_Command_Error', true); + } + + // Warning about impossible mix of options + if (!empty($this->options['OUTPUT'])) { + if (!empty($this->options['SHUTDOWN']) || !empty($this->options['NOHUP'])) { + return PEAR::raiseError(null, SYSTEM_COMMAND_NO_OUTPUT, null, E_USER_WARNING, null, 'System_Command_Error', true); + } + } + + // if this is not going to stdout, then redirect to /dev/null + if (empty($this->options['OUTPUT'])) { + $this->systemCommand .= ' >/dev/null'; + } + + $suffix = ''; + // run a command immune to hangups, with output to a non-tty + if (!empty($this->options['NOHUP'])) { + $this->systemCommand = $this->options['NOHUP'] . $this->systemCommand; + } + // run a background process (only if not nohup) + elseif (!empty($this->options['BACKGROUND'])) { + $suffix = ' &'; + } + + // Register to be run on shutdown + if (!empty($this->options['SHUTDOWN'])) { + $line = "system(\"{$this->systemCommand}$suffix\");"; + $function = create_function('', $line); + register_shutdown_function($function); + return true; + } + else { + // send stderr to a file so that we can reap the error message + $tmpFile = tempnam($this->tmpDir, 'System_Command-'); + $this->systemCommand .= ' 2>' . $tmpFile . $suffix; + $shellPipe = $this->which('echo') . ' ' . escapeshellarg($this->systemCommand) . ' | ' . $this->options['SHELL']; + exec($shellPipe, $result, $returnVal); + + if ($returnVal !== 0) { + // command returned nonzero; that's always an error + $return = PEAR::raiseError(null, SYSTEM_COMMAND_NONZERO_EXIT, null, E_USER_WARNING, null, 'System_Command_Error', true); + } + else if (!$this->options['STDERR']) { + // caller does not care about stderr; return success + $return = implode("\n", $result); + } + else { + // our caller cares about stderr; check stderr output + clearstatcache(); + if (filesize($tmpFile) > 0) { + // the command actually wrote to stderr + $stderr_output = file_get_contents($tmpFile); + $return = PEAR::raiseError(null, SYSTEM_COMMAND_STDERR, null, E_USER_WARNING, $stderr_output, 'System_Command_Error', true); + } else { + // total success; return stdout gathered by exec() + $return = implode("\n", $result); + } + } + + unlink($tmpFile); + return $return; + } + } + + // }}} + // {{{ which() + + /** + * Functionality similiar to unix 'which'. Searches the path + * for the specified program. + * + * @param $cmd name of the executable to search for + * + * @access private + * @return string returns the full path if found, false if not + */ + function which($in_cmd) + { + // only pass non-empty strings to System::which() + if (!is_string($in_cmd) || '' === $in_cmd) { + return(false); + } + + // explicitly pass false as fallback value + return System::which($in_cmd, false); + } + + // }}} + // {{{ reset() + + /** + * Prepare for a new command to be built + * + * @access public + * @return void + */ + function reset() + { + $this->previousElement = null; + $this->systemCommand = null; + $this->commandStatus = 0; + } + + // }}} + // {{{ errorMessage() + + /** + * Return a textual error message for a System_Command error code + * + * @param integer error code + * + * @return string error message, or false if the error code was + * not recognized + */ + function errorMessage($in_value) + { + static $errorMessages; + if (!isset($errorMessages)) { + $errorMessages = array( + SYSTEM_COMMAND_OK => 'no error', + SYSTEM_COMMAND_ERROR => 'unknown error', + SYSTEM_COMMAND_NO_SHELL => 'no shell found', + SYSTEM_COMMAND_INVALID_SHELL => 'invalid shell', + SYSTEM_COMMAND_TMPDIR_ERROR => 'could not create temporary directory', + SYSTEM_COMMAND_INVALID_OPERATOR => 'control operator invalid', + SYSTEM_COMMAND_INVALID_COMMAND => 'invalid system command', + SYSTEM_COMMAND_OPERATOR_PLACEMENT => 'invalid placement of control operator', + SYSTEM_COMMAND_COMMAND_PLACEMENT => 'invalid placement of command', + SYSTEM_COMMAND_NOHUP_MISSING => 'nohup not found on system', + SYSTEM_COMMAND_NO_OUTPUT => 'output not allowed', + SYSTEM_COMMAND_STDERR => 'command wrote to stderr', + SYSTEM_COMMAND_NONZERO_EXIT => 'non-zero exit value from command', + ); + } + + if (System_Command::isError($in_value)) { + $in_value = $in_value->getCode(); + } + + return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[SYSTEM_COMMAND_ERROR]; + } + + // }}} + // {{{ isError() + + /** + * Tell whether a result code from a System_Command method is an error + * + * @param int result code + * + * @return bool whether $in_value is an error + * + * @access public + */ + function isError($in_value) + { + return (is_object($in_value) && + (strtolower(get_class($in_value)) == 'system_command_error' || + is_subclass_of($in_value, 'system_command_error'))); + } + + // }}} +} + +// {{{ class System_Command_Error + +/** + * System_Command_Error constructor. + * + * @param mixed System_Command error code, or string with error message. + * @param integer what "error mode" to operate in + * @param integer what error level to use for $mode & PEAR_ERROR_TRIGGER + * @param mixed additional debug info, such as the last query + * + * @access public + * + * @see PEAR_Error + */ + +// }}} +class System_Command_Error extends PEAR_Error +{ + // {{{ properties + + /** + * Message in front of the error message + * @var string $error_message_prefix + */ + var $error_message_prefix = 'System_Command Error: '; + + // }}} + // {{{ constructor + + function System_Command_Error($code = SYSTEM_COMMAND_ERROR, $mode = PEAR_ERROR_RETURN, + $level = E_USER_NOTICE, $debuginfo = null) + { + if (is_int($code)) { + $this->PEAR_Error(System_Command::errorMessage($code), $code, $mode, $level, $debuginfo); + } else { + $this->PEAR_Error("Invalid error code: $code", SYSTEM_COMMAND_ERROR, $mode, $level, $debuginfo); + } + } + + // }}} +} +?> -- cgit v1.2.3-54-g00ecf From 7bcaa858af31c5c496bc5adc0c73ec333d4c1e63 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 05:35:20 -0700 Subject: make file command configurable --- README | 4 ++++ actions/newnotice.php | 3 +++ lib/common.php | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README b/README index de1099600..1a57d6a80 100644 --- a/README +++ b/README @@ -1232,6 +1232,10 @@ supported: an array of mime types you accept to store and distribute, setup your server to properly reckognize the types you want to support. uploads: false to disable uploading files with notices (true by default). +filecommand: The required MIME_Type library may need to use the 'file' + command. It tries the one in the Web server's path, but if + you're having problems with uploads, try setting this to the + correct value. Note: 'file' must accept '-b' and '-i' options. For quotas, be sure you've set the upload_max_filesize and post_max_size in php.ini to be large enough to handle your upload. In httpd.conf diff --git a/actions/newnotice.php b/actions/newnotice.php index 09652d2b3..b7d9ec1dd 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -116,6 +116,9 @@ class NewnoticeAction extends Action function getUploadedFileType() { require_once 'MIME/Type.php'; + $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); + $cmd = common_config('attachments', 'filecommand'); + $filetype = MIME_Type::autoDetect($_FILES['attach']['tmp_name']); if (in_array($filetype, common_config('attachments', 'supported'))) { return $filetype; diff --git a/lib/common.php b/lib/common.php index 20f1ab35e..76eb4a978 100644 --- a/lib/common.php +++ b/lib/common.php @@ -202,7 +202,7 @@ $config = array('run' => 'web', 'frequency' => 10000, 'reporturl' => 'http://laconi.ca/stats/report'), - 'attachments' => + 'attachments' => array('server' => null, 'dir' => INSTALLDIR . '/file/', 'path' => $_path . '/file/', @@ -241,6 +241,7 @@ $config = 'user_quota' => 50000000, 'monthly_quota' => 15000000, 'uploads' => true, + 'filecommand' => '/usr/bin/file', ), 'group' => array('maxaliases' => 3), -- cgit v1.2.3-54-g00ecf From e2becdb25138350170b58ae8f0d1ecd715533cf5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 07:25:18 -0700 Subject: use a subclass for single notice items to show attachments --- actions/shownotice.php | 28 +++++++++++++++++++++++++++- lib/noticelist.php | 13 ------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/actions/shownotice.php b/actions/shownotice.php index b0d973a99..0d89af5ac 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -209,7 +209,7 @@ class ShownoticeAction extends Action function showContent() { $this->elementStart('ol', array('class' => 'notices xoxo')); - $nli = new NoticeListItem($this->notice, $this); + $nli = new SingleNoticeItem($this->notice, $this); $nli->show(); $this->elementEnd('ol'); } @@ -264,3 +264,29 @@ class ShownoticeAction extends Action } } } + +class SingleNoticeItem extends NoticeListItem +{ + /** + * recipe function for displaying a single notice. + * + * We overload to show attachments. + * + * @return void + */ + + function show() + { + $this->showStart(); + $this->showNotice(); + $this->showNoticeAttachments(); + $this->showNoticeInfo(); + $this->showNoticeOptions(); + $this->showEnd(); + } + + function showNoticeAttachments() { + $al = new AttachmentList($this->notice, $this->out); + $al->show(); + } +} diff --git a/lib/noticelist.php b/lib/noticelist.php index ad792441a..bd4815cd6 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -179,7 +179,6 @@ class NoticeListItem extends Widget { $this->showStart(); $this->showNotice(); - $this->showNoticeAttachments(); $this->showNoticeInfo(); $this->showNoticeOptions(); $this->showEnd(); @@ -193,18 +192,6 @@ class NoticeListItem extends Widget $this->out->elementEnd('div'); } - function showNoticeAttachments() { - if ($this->isUsedInList()) { - return; - } - $al = new AttachmentList($this->notice, $this->out); - $al->show(); - } - - function isUsedInList() { - return 'shownotice' !== $this->out->args['action']; - } - function showNoticeInfo() { $this->out->elementStart('div', 'entry-content'); -- cgit v1.2.3-54-g00ecf From a21a9f26c5f0eb034ea389659dd63ffad400de5b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 07:29:43 -0700 Subject: append uploads to content rather than showing them double --- actions/newnotice.php | 104 +++++++++++++++++++++++++++++++++---------- classes/File.php | 67 +++++++++++++++------------- classes/File_redirection.php | 70 +++-------------------------- lib/noticelist.php | 4 -- lib/util.php | 65 +++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 124 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index b7d9ec1dd..a5f87d1be 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -224,16 +224,40 @@ class NewnoticeAction extends Action } } + if (isset($mimetype)) { + $filename = $this->saveFile($mimetype); + if (empty($filename)) { + $this->clientError(_('Couldn\'t save file.')); + } + $fileurl = File::url($filename); + $short_fileurl = common_shorten_url($fileurl); + $content_shortened .= ' ' . $short_fileurl; + if (mb_strlen($content_shortened) > 140) { + $this->deleteFile($filename); + $this->clientError(_('Max notice size is 140 chars, including attachment URL.')); + } + } + + common_debug("newnotice.php - before Notice::saveNew()"); + $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); + common_debug("newnotice.php - after Notice::saveNew()"); + if (is_string($notice)) { + if (isset($filename)) { + $this->deleteFile($filename); + } $this->clientError($notice); } + common_debug("newnotice.php - after Notice::saveNew()"); + if (isset($mimetype)) { - $this->storeFile($notice, $mimetype); + $this->attachFile($notice, $filename, $mimetype, $short_fileurl); } + common_broadcast_notice($notice); if ($this->boolean('ajax')) { @@ -259,7 +283,13 @@ class NewnoticeAction extends Action } } - function storeFile($notice, $mimetype) { + function saveFile($mimetype) { + + $cur = common_current_user(); + + if (empty($cur)) { + $this->serverError(_('Somehow lost the login in saveFile')); + } common_debug("NewnoticeAction::storeFile()"); @@ -267,7 +297,7 @@ class NewnoticeAction extends Action common_debug("Basename: $basename"); - $filename = File::filename($notice->id, $basename); + $filename = File::filename($cur->getProfile(), $basename, $mimetype); common_debug("filename: $filename"); @@ -276,33 +306,59 @@ class NewnoticeAction extends Action common_debug("filepath: $filepath"); if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) { + return $filename; + } else { + $this->clientError(_('File could not be moved to destination directory.')); + } + } - $file = new File; - $file->filename = $filename; + function deleteFile($filename) + { + $filepath = File::path($filename); + @unlink($filepath); + } - $file->url = common_local_url('file', array('notice' => $notice->id)); + function attachFile($notice, $filename, $mimetype, $short) + { + $file = new File; + $file->filename = $filename; - common_debug("file->url =". $file->url); + $file->url = common_local_url('file', array('notice' => $notice->id)); - $file->size = filesize($filepath); - $file->date = time(); - $file->mimetype = $mimetype; + common_debug("file->url =". $file->url); - if ($file_id = $file->insert()) { - $file_redir = new File_redirection; - $file_redir->url = File::url($filename); - $file_redir->file_id = $file_id; - $file_redir->insert(); + $filepath = File::path($filename); - $f2p = new File_to_post; - $f2p->file_id = $file_id; - $f2p->post_id = $notice->id; - $f2p->insert(); - } else { - $this->clientError(_('There was a database error while saving your file. Please try again.')); - } - } else { - $this->clientError(_('File could not be moved to destination directory.')); + $file->size = filesize($filepath); + $file->date = time(); + $file->mimetype = $mimetype; + + $file_id = $file->insert(); + + if (!$file_id) { + common_log_db_error($file, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); + } + + $file_redir = new File_redirection; + $file_redir->url = File::url($filename); + $file_redir->file_id = $file_id; + + $result = $file_redir->insert(); + + if (!$result) { + common_log_db_error($file_redir, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); + } + + $f2p = new File_to_post; + $f2p->file_id = $file_id; + $f2p->post_id = $notice->id; + $f2p->insert(); + + if (!$result) { + common_log_db_error($f2p, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); } } diff --git a/classes/File.php b/classes/File.php index 1de136240..b98c9e665 100644 --- a/classes/File.php +++ b/classes/File.php @@ -124,8 +124,8 @@ class File extends Memcached_DataObject function isRespectsQuota($user) { if ($_FILES['attach']['size'] > common_config('attachments', 'file_quota')) { return sprintf(_('No file may be larger than %d bytes ' . - 'and the file you sent was %d bytes. Try to upload a smaller version.'), - common_config('attachments', 'file_quota'), $_FILES['attach']['size']); + 'and the file you sent was %d bytes. Try to upload a smaller version.'), + common_config('attachments', 'file_quota'), $_FILES['attach']['size']); } $query = "select sum(size) as total from file join file_to_post on file_to_post.file_id = file.id join notice on file_to_post.post_id = notice.id where profile_id = {$user->id} and file.url like '%/notice/%/file'"; @@ -148,44 +148,49 @@ class File extends Memcached_DataObject // where should the file go? - static function filename($notice_id, $basename) - { - return $notice_id . '-' . $basename; - } - - static function path($filename) - { - $dir = common_config('attachments', 'dir'); + static function filename($profile, $basename, $mimetype) + { + require_once 'MIME/Type/Extension.php'; + $mte = new MIME_Type_Extension(); + $ext = $mte->getExtension($mimetype); + $nickname = $profile->nickname; + $datestamp = strftime('%Y%m%dT%H%M%S', time()); + $random = strtolower(common_confirmation_code(32)); + return "$nickname-$datestamp-$random.$ext"; + } - if ($dir[strlen($dir)-1] != '/') { - $dir .= '/'; - } + static function path($filename) + { + $dir = common_config('attachments', 'dir'); - return $dir . $filename; - } + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } - static function url($filename) - { - $path = common_config('attachments', 'path'); + return $dir . $filename; + } - if ($path[strlen($path)-1] != '/') { - $path .= '/'; - } + static function url($filename) + { + $path = common_config('attachments', 'path'); - if ($path[0] != '/') { - $path = '/'.$path; - } + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } - $server = common_config('attachments', 'server'); + if ($path[0] != '/') { + $path = '/'.$path; + } - if (empty($server)) { - $server = common_config('site', 'server'); - } + $server = common_config('attachments', 'server'); - // XXX: protocol + if (empty($server)) { + $server = common_config('site', 'server'); + } - return 'http://'.$server.$path.$filename; - } + // XXX: protocol + return 'http://'.$server.$path.$filename; + } } diff --git a/classes/File_redirection.php b/classes/File_redirection.php index edd915c1e..c173017e2 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -25,21 +25,20 @@ require_once INSTALLDIR.'/classes/File_oembed.php'; define('USER_AGENT', 'Laconica user agent / file probe'); - /** * Table Definition for file_redirection */ -class File_redirection extends Memcached_DataObject +class File_redirection extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ public $__table = 'file_redirection'; // table name public $url; // varchar(255) primary_key not_null - public $file_id; // int(4) - public $redirections; // int(4) - public $httpcode; // int(4) + public $file_id; // int(4) + public $redirections; // int(4) + public $httpcode; // int(4) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ @@ -48,8 +47,6 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - - function _commonCurl($url, $redirs) { $curlh = curl_init(); curl_setopt($curlh, CURLOPT_URL, $url); @@ -86,8 +83,6 @@ class File_redirection extends Memcached_DataObject return $url; } - - $curlh = File_redirection::_commonCurl($short_url, $redirs); // Don't include body in output curl_setopt($curlh, CURLOPT_NOBODY, true); @@ -143,62 +138,7 @@ class File_redirection extends Memcached_DataObject } function _userMakeShort($long_url, $user) { - if (empty($user)) { - // common current user does not find a user when called from the XMPP daemon - // therefore we'll set one here fix, so that XMPP given URLs may be shortened - $user->urlshorteningservice = 'ur1.ca'; - } - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - switch($user->urlshorteningservice) { - case 'ur1.ca': - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url_service = new LilUrl; - $short_url = $short_url_service->shorten($long_url); - break; - - case '2tu.us': - $short_url_service = new TightUrl; - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url = $short_url_service->shorten($long_url); - break; - - case 'ptiturl.com': - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url_service = new PtitUrl; - $short_url = $short_url_service->shorten($long_url); - break; - - case 'bit.ly': - curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); - $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; - break; - - case 'is.gd': - curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'snipr.com': - curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'metamark.net': - curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'tinyurl.com': - curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - default: - $short_url = false; - } - - curl_close($curlh); - + $short_url = common_shorten_url($long_url); if ($short_url) { $short_url = (string)$short_url; // store it diff --git a/lib/noticelist.php b/lib/noticelist.php index bd4815cd6..6f05c63d6 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -336,10 +336,6 @@ class NoticeListItem extends Widget // versions (>> 0.4.x) $this->out->raw(common_render_content($this->notice->content, $this->notice)); } - $uploaded = $this->notice->getUploadedAttachment(); - if ($uploaded) { - $this->out->element('a', array('href' => $uploaded[0], 'class' => 'attachment', 'id' => 'attachment-' . $uploaded[1]), $uploaded[0]); - } $this->out->elementEnd('p'); } diff --git a/lib/util.php b/lib/util.php index 0aff893fd..1af462516 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1377,3 +1377,68 @@ function common_database_tablename($tablename) //table prefixes could be added here later return $tablename; } + +function common_shorten_url($long_url) +{ + $user = common_current_user(); + if (empty($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $svc = 'ur1.ca'; + } else { + $svc = $user->urlshorteningservice; + } + + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait + curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + + switch($svc) { + case 'ur1.ca': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new LilUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case '2tu.us': + $short_url_service = new TightUrl; + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'ptiturl.com': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new PtitUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'bit.ly': + curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); + $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; + break; + + case 'is.gd': + curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'snipr.com': + curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'metamark.net': + curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'tinyurl.com': + curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + default: + $short_url = false; + } + + curl_close($curlh); + + return $short_url; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From e261a97150684c943ebd6f994f610a2c2d0ba6b6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 07:48:33 -0700 Subject: remove common_debug from newnotice --- actions/newnotice.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index a5f87d1be..4a2c369f0 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -238,13 +238,9 @@ class NewnoticeAction extends Action } } - common_debug("newnotice.php - before Notice::saveNew()"); - $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); - common_debug("newnotice.php - after Notice::saveNew()"); - if (is_string($notice)) { if (isset($filename)) { $this->deleteFile($filename); @@ -252,8 +248,6 @@ class NewnoticeAction extends Action $this->clientError($notice); } - common_debug("newnotice.php - after Notice::saveNew()"); - if (isset($mimetype)) { $this->attachFile($notice, $filename, $mimetype, $short_fileurl); } @@ -291,20 +285,12 @@ class NewnoticeAction extends Action $this->serverError(_('Somehow lost the login in saveFile')); } - common_debug("NewnoticeAction::storeFile()"); - $basename = basename($_FILES['attach']['name']); - common_debug("Basename: $basename"); - $filename = File::filename($cur->getProfile(), $basename, $mimetype); - common_debug("filename: $filename"); - $filepath = File::path($filename); - common_debug("filepath: $filepath"); - if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) { return $filename; } else { @@ -325,8 +311,6 @@ class NewnoticeAction extends Action $file->url = common_local_url('file', array('notice' => $notice->id)); - common_debug("file->url =". $file->url); - $filepath = File::path($filename); $file->size = filesize($filepath); -- cgit v1.2.3-54-g00ecf From 4ca6aa1930f65120162a692c4cb86f5becb4ae7f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 09:16:41 -0700 Subject: a little sql script to drop full-text index and use innodb for profile and notice --- db/innodb.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 db/innodb.sql diff --git a/db/innodb.sql b/db/innodb.sql new file mode 100644 index 000000000..f3ab6cd69 --- /dev/null +++ b/db/innodb.sql @@ -0,0 +1,2 @@ +alter table profile drop index nickname, engine=InnoDB; +alter table notice drop index content, engine=InnoDB; -- cgit v1.2.3-54-g00ecf From 545cbb2c82306872af4a227fd4fc7088da8e9a8c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 09:18:10 -0700 Subject: make pwgen command configurable --- scripts/setup.cfg.sample | 1 + scripts/setup_status_network.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample index 450b9c30a..72e6a21af 100644 --- a/scripts/setup.cfg.sample +++ b/scripts/setup.cfg.sample @@ -9,4 +9,5 @@ export ADMIN=root export ADMINPASS=yourpassword export SITEDB=example_net_site export AVATARBASE=/var/www/avatar.example.net +export PWDGEN="pwdgen 20" diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index e1d14593f..cf9f78315 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -5,7 +5,7 @@ source ./setup.cfg export nickname=$1 export sitename=$2 -export password=`pwgen 20` +export password=`$PWDGEN` export database=$nickname$DBBASE export username=$nickname$USERBASE -- cgit v1.2.3-54-g00ecf From 009e40834c70c0e0b430552d37880a04be327465 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 09:19:54 -0700 Subject: pwgen not pwdgen --- scripts/setup.cfg.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample index 72e6a21af..dd3c2705f 100644 --- a/scripts/setup.cfg.sample +++ b/scripts/setup.cfg.sample @@ -9,5 +9,5 @@ export ADMIN=root export ADMINPASS=yourpassword export SITEDB=example_net_site export AVATARBASE=/var/www/avatar.example.net -export PWDGEN="pwdgen 20" +export PWDGEN="pwgen 20" -- cgit v1.2.3-54-g00ecf From 4d4d951531d9fb6db008c26439eab3b0ba658d79 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 09:20:20 -0700 Subject: add innodb by default to status networks --- scripts/setup_status_network.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index cf9f78315..29ee010ed 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -13,7 +13,7 @@ export username=$nickname$USERBASE mysqladmin -h $DBHOST -u $ADMIN --password=$ADMINPASS create $database -for f in laconica.sql sms_carrier.sql foreign_services.sql notice_source.sql; do +for f in laconica.sql innodb.sql sms_carrier.sql foreign_services.sql notice_source.sql; do mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $database < ../db/$f; done -- cgit v1.2.3-54-g00ecf From e744eba7ebf6f2b057bfd45a9f3b3c4626017c50 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 09:52:31 -0700 Subject: oembed and thumbnail don't need sequences --- classes/File_oembed.php | 29 ++++++++++++++++------------- classes/File_thumbnail.php | 11 ++++++++--- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 51ee57b29..69230e4a4 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -25,24 +25,24 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; * Table Definition for file_oembed */ -class File_oembed extends Memcached_DataObject +class File_oembed extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ public $__table = 'file_oembed'; // table name public $file_id; // int(4) primary_key not_null - public $version; // varchar(20) - public $type; // varchar(20) - public $provider; // varchar(50) - public $provider_url; // varchar(255) - public $width; // int(4) - public $height; // int(4) - public $html; // text() - public $title; // varchar(255) - public $author_name; // varchar(50) - public $author_url; // varchar(255) - public $url; // varchar(255) + public $version; // varchar(20) + public $type; // varchar(20) + public $provider; // varchar(50) + public $provider_url; // varchar(255) + public $width; // int(4) + public $height; // int(4) + public $html; // text() + public $title; // varchar(255) + public $author_name; // varchar(50) + public $author_url; // varchar(255) + public $url; // varchar(255) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ @@ -51,6 +51,10 @@ class File_oembed extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + function sequenceKey() + { + return array(false, false, false); + } function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') { $cmd = common_config('oohembed', 'endpoint') . '?url=' . urlencode($url); @@ -84,4 +88,3 @@ class File_oembed extends Memcached_DataObject } } - diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php index 21dcad571..44b92a2fa 100644 --- a/classes/File_thumbnail.php +++ b/classes/File_thumbnail.php @@ -25,7 +25,7 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; * Table Definition for file_thumbnail */ -class File_thumbnail extends Memcached_DataObject +class File_thumbnail extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -33,8 +33,8 @@ class File_thumbnail extends Memcached_DataObject public $__table = 'file_thumbnail'; // table name public $file_id; // int(4) primary_key not_null public $url; // varchar(255) unique_key - public $width; // int(4) - public $height; // int(4) + public $width; // int(4) + public $height; // int(4) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ @@ -43,6 +43,11 @@ class File_thumbnail extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + function sequenceKey() + { + return array(false, false, false); + } + function saveNew($data, $file_id) { $tn = new File_thumbnail; $tn->file_id = $file_id; -- cgit v1.2.3-54-g00ecf From eb40fbc17ad1efb0a4c51ee00b1e9408d2af382f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 23 Jun 2009 17:05:55 +0000 Subject: On XHR notice post, calls NoticeAttachment to trigger thumbnail and attachment views --- js/util.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/util.js b/js/util.js index 17ae4c071..65a77960a 100644 --- a/js/util.js +++ b/js/util.js @@ -217,6 +217,7 @@ $(document).ready(function(){ $('#'+li.id).css({display:'none'}); $('#'+li.id).fadeIn(2500); NoticeReply(); + NoticeAttachments(); } } $("#notice_data-text").val(""); -- cgit v1.2.3-54-g00ecf From a515c3ce530aba411e0d8f90de071ede90318142 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 10:43:50 -0700 Subject: other base directories --- scripts/setup.cfg.sample | 2 ++ scripts/setup_status_network.sh | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample index dd3c2705f..ef33cd632 100644 --- a/scripts/setup.cfg.sample +++ b/scripts/setup.cfg.sample @@ -9,5 +9,7 @@ export ADMIN=root export ADMINPASS=yourpassword export SITEDB=example_net_site export AVATARBASE=/var/www/avatar.example.net +export BACKGROUNDBASE=/var/www/background.example.net +export FILEBASE=/var/www/file.example.net export PWDGEN="pwgen 20" diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index 29ee010ed..f0bb2cae8 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -26,5 +26,7 @@ VALUES ('$nickname', '$DBHOST', '$username', '$password', '$database', '$sitenam ENDOFCOMMANDS -mkdir $AVATARBASE/$nickname -chmod a+w $AVATARBASE/$nickname +for top in $AVATARBASE $FILEBASE $BACKGROUNDBASE; do + mkdir $top/$nickname + chmod a+w $top/$nickname +done -- cgit v1.2.3-54-g00ecf From e22f73c72bc08aac15ae3eae66ffbb0987d6883e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:14:51 -0700 Subject: use /etc/laconica/setup.cfg instead of local file --- scripts/setup_status_network.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index f0bb2cae8..0261a7f55 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -1,6 +1,6 @@ #!/bin/bash -source ./setup.cfg +source /etc/laconica/setup.cfg export nickname=$1 export sitename=$2 -- cgit v1.2.3-54-g00ecf From a4402eedb32d0933b11070a1f6f681d020ab270f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:22:54 -0700 Subject: use different name for connection and database --- scripts/setup.cfg.sample | 5 ++--- scripts/setup_status_network.sh | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample index ef33cd632..8d03b06f5 100644 --- a/scripts/setup.cfg.sample +++ b/scripts/setup.cfg.sample @@ -1,8 +1,7 @@ # CONFIGURATION FILE for setup_status_network.sh -# Base database name; full name will include nickname - -export DBHOST=masterdb.example.net +export DBHOST=localhost +export DBHOSTNAME=masterdb.example.net export DBBASE=_example_net export USERBASE=_example_net export ADMIN=root diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh index 0261a7f55..17440640e 100755 --- a/scripts/setup_status_network.sh +++ b/scripts/setup_status_network.sh @@ -22,7 +22,7 @@ mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'localhost' IDENTIFIED BY '$password'; GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'%' IDENTIFIED BY '$password'; INSERT INTO status_network (nickname, dbhost, dbuser, dbpass, dbname, sitename, created) -VALUES ('$nickname', '$DBHOST', '$username', '$password', '$database', '$sitename', now()); +VALUES ('$nickname', '$DBHOSTNAME', '$username', '$password', '$database', '$sitename', now()); ENDOFCOMMANDS -- cgit v1.2.3-54-g00ecf From 17319ac5ca01f2780c4deb63d37654543da3c996 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:32:35 -0700 Subject: script to show all sites on a network --- scripts/allsites.php | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 scripts/allsites.php diff --git a/scripts/allsites.php b/scripts/allsites.php new file mode 100644 index 000000000..d6768c278 --- /dev/null +++ b/scripts/allsites.php @@ -0,0 +1,40 @@ +#!/usr/bin/env php +. + */ + +# Abort if called from a web server + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); + +$helptext = <<find()) { + while ($sn->fetch()) { + print "$sn->nickname\n"; + } +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From ec4192edcd72e0bd0f2330a8d69b0d138a37f1f4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:34:16 -0700 Subject: chmod allsites.php --- scripts/allsites.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/allsites.php diff --git a/scripts/allsites.php b/scripts/allsites.php old mode 100644 new mode 100755 -- cgit v1.2.3-54-g00ecf From 83b5e6be0244e8b8c971bcc11103c2e32b54efd6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:40:23 -0700 Subject: script to delete a status network --- scripts/delete_status_network.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 scripts/delete_status_network.sh diff --git a/scripts/delete_status_network.sh b/scripts/delete_status_network.sh new file mode 100644 index 000000000..1cf716849 --- /dev/null +++ b/scripts/delete_status_network.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +source /etc/laconica/setup.cfg + +export nickname=$1 + +export database=$nickname$DBBASE + +# Create the db + +mysqladmin -h $DBHOST -u $ADMIN --password=$ADMINPASS -f drop $database + +mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS + +delete from status_network where nickname = '$nickname'; + +ENDOFCOMMANDS + +for top in $AVATARBASE $FILEBASE $BACKGROUNDBASE; do + rmdir $top/$nickname +done -- cgit v1.2.3-54-g00ecf From 0032fa28f030616a345a2cdbc822235c381f2c12 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:43:20 -0700 Subject: rm -Rf, not rmdir --- scripts/delete_status_network.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/delete_status_network.sh b/scripts/delete_status_network.sh index 1cf716849..32187382c 100644 --- a/scripts/delete_status_network.sh +++ b/scripts/delete_status_network.sh @@ -17,5 +17,5 @@ delete from status_network where nickname = '$nickname'; ENDOFCOMMANDS for top in $AVATARBASE $FILEBASE $BACKGROUNDBASE; do - rmdir $top/$nickname + rm -Rf $top/$nickname done -- cgit v1.2.3-54-g00ecf From 9505ef5bb39875f6090c8ed572391cff415531fd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 11:45:18 -0700 Subject: chmod +x delete_status_network.sh --- scripts/delete_status_network.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/delete_status_network.sh diff --git a/scripts/delete_status_network.sh b/scripts/delete_status_network.sh old mode 100644 new mode 100755 -- cgit v1.2.3-54-g00ecf From 31325f0995bb61413b07f166d253b13fb27d085d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 23 Jun 2009 13:51:23 -0700 Subject: Stop Twitter gateway notices from leaking via user faves pages --- actions/showfavorites.php | 17 ++++++++++++++--- classes/Fave.php | 46 ++++++++++++++++++++++++++++------------------ classes/Notice.php | 2 ++ classes/User.php | 4 ++-- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 01f38a892..b723924a5 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -191,10 +191,21 @@ class ShowfavoritesAction extends CurrentUserDesignAction function showContent() { - $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE, - NOTICES_PER_PAGE + 1); + $cur = common_current_user(); - if (!$notice) { + if (!empty($cur) && $cur->id == $this->user->id) { + + // Show imported/gateway notices as well as local if + // the user is looking at his own favorites + + $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE, + NOTICES_PER_PAGE + 1, true); + } else { + $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE, + NOTICES_PER_PAGE + 1, false); + } + + if (empty($notice)) { $this->serverError(_('Could not retrieve favorite notices.')); return; } diff --git a/classes/Fave.php b/classes/Fave.php index 572334ce4..f4cf6256f 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -37,52 +37,62 @@ class Fave extends Memcached_DataObject return Memcached_DataObject::pkeyGet('Fave', $kv); } - function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE) + function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $own=false) { $ids = Notice::stream(array('Fave', '_streamDirect'), - array($user_id), - 'fave:ids_by_user:'.$user_id, + array($user_id, $own), + ($own) ? 'fave:ids_by_user_own:'.$user_id : + 'fave:by_user:'.$user_id, $offset, $limit); return $ids; } - function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since) + function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id, $since) { $fav = new Fave(); - - $fav->user_id = $user_id; - - $fav->selectAdd(); - $fav->selectAdd('notice_id'); + $qry = null; + + if ($own) { + $qry = 'SELECT fave.* FROM fave '; + $qry .= 'WHERE fave.user_id = ' . $user_id . ' '; + } else { + $qry = 'SELECT fave.* FROM fave '; + $qry .= 'INNER JOIN notice ON fave.notice_id = notice.id '; + $qry .= 'WHERE fave.user_id = ' . $user_id . ' '; + $qry .= 'AND notice.is_local != ' . NOTICE_GATEWAY . ' '; + } if ($since_id != 0) { - $fav->whereAdd('notice_id > ' . $since_id); + $qry .= 'AND notice_id > ' . $since_id . ' '; } if ($max_id != 0) { - $fav->whereAdd('notice_id <= ' . $max_id); + $qry .= 'AND notice_id <= ' . $max_id . ' '; } if (!is_null($since)) { - $fav->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\''); + $qry .= 'AND modified > \'' . date('Y-m-d H:i:s', $since) . '\' '; } // NOTE: we sort by fave time, not by notice time! - $fav->orderBy('modified DESC'); + $qry .= 'ORDER BY modified DESC '; if (!is_null($offset)) { - $fav->limit($offset, $limit); + $qry .= "LIMIT $offset, $limit"; } + $fav->query($qry); + $ids = array(); - if ($fav->find()) { - while ($fav->fetch()) { - $ids[] = $fav->notice_id; - } + while ($fav->fetch()) { + $ids[] = $fav->notice_id; } + $fav->free(); + unset($fav); + return $ids; } } diff --git a/classes/Notice.php b/classes/Notice.php index b6bbf66ca..6f9b73be4 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -471,8 +471,10 @@ class Notice extends Memcached_DataObject if ($fave->find()) { while ($fave->fetch()) { $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id)); + $cache->delete(common_cache_key('fave:by_user_own:'.$fave->user_id)); if ($blowLast) { $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id.';last')); + $cache->delete(common_cache_key('fave:by_user_own:'.$fave->user_id.';last')); } } } diff --git a/classes/User.php b/classes/User.php index e8c8c5a75..a01a3106f 100644 --- a/classes/User.php +++ b/classes/User.php @@ -424,9 +424,9 @@ class User extends Memcached_DataObject } } - function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) + function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE, $own=false) { - $ids = Fave::stream($this->id, $offset, $limit); + $ids = Fave::stream($this->id, $offset, $limit, $own); return Notice::getStreamByIds($ids); } -- cgit v1.2.3-54-g00ecf From 3cfa2ebb05e131be3a85d9af7a14ed9466b291cb Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 23 Jun 2009 21:18:41 +0000 Subject: Updated default colour theme and IE6 colours for transparent values --- theme/default/css/display.css | 24 ++++++++++++------------ theme/default/css/ie.css | 6 +++--- theme/identica/css/ie.css | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 7e8b84b4c..f592e930f 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -11,7 +11,7 @@ body, a:active { -background-color:#C3D6DF; +background-color:#CEE1E9; } body { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; @@ -29,7 +29,7 @@ input, textarea, select, border-color:#AAAAAA; } #filter_tags ul li { -border-color:#C3D6DF; +border-color:#DDDDDD; } .form_settings input.form_action-primary { @@ -40,12 +40,12 @@ input.submit, #form_notice.warning #notice_text-count, .form_settings .form_note, .entity_remote_subscribe { -background-color:#A9BF4F; +background-color:#9BB43E; } input:focus, textarea:focus, select:focus, #form_notice.warning #notice_data-text { -border-color:#A9BF4F; +border-color:#9BB43E; box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); -moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); -webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); @@ -71,14 +71,14 @@ color:#002E6E; .notice, .profile { -border-top-color:#D1D9E4; +border-top-color:#C8D1D5; } .section .profile { -border-top-color:#C3D6DF; +border-top-color:#87B4C8; } #aside_primary { -background-color:#CEE1E9; +background-color:#C8D1D5; } #notice_text-count { @@ -136,13 +136,13 @@ background-color:#EFF3DC; } #anon_notice { -background-color:#C3D6DF; +background-color:#87B4C8; color:#FFFFFF; border-color:#FFFFFF; } #showstream #anon_notice { -background-color:#A9BF4F; +background-color:#9BB43E; } #export_data li a { @@ -176,13 +176,13 @@ background-color:transparent; .form_group_leave input.submit .form_user_subscribe input.submit, .form_user_unsubscribe input.submit { -background-color:#A9BF4F; +background-color:#9BB43E; color:#FFFFFF; } .form_user_unsubscribe input.submit, .form_group_leave input.submit, .form_user_authorization input.reject { -background-color:#C3D6DF; +background-color:#87B4C8; } .entity_edit a { @@ -272,7 +272,7 @@ background:transparent url(../../base/images/icons/twotone/green/news.gif) no-re .pagination .nav_prev a, .pagination .nav_next a { background-repeat:no-repeat; -border-color:#D1D9E4; +border-color:#C8D1D5; } .pagination .nav_prev a { background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); diff --git a/theme/default/css/ie.css b/theme/default/css/ie.css index 6501f4e48..cbbd49ce6 100644 --- a/theme/default/css/ie.css +++ b/theme/default/css/ie.css @@ -1,14 +1,14 @@ /* IE specific styles */ .notice-options input.submit { -color:#fff; +color:#FFFFFF; } #site_nav_local_views a { -background-color:#ACCCDA; +background-color:#C8D1D5; } #form_notice .form_note + label { background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; } #form_notice #notice_data-attach { filter: alpha(opacity=0); -} \ No newline at end of file +} diff --git a/theme/identica/css/ie.css b/theme/identica/css/ie.css index 69db16aad..97cabc30a 100644 --- a/theme/identica/css/ie.css +++ b/theme/identica/css/ie.css @@ -1,14 +1,14 @@ /* IE specific styles */ .notice-options input.submit { -color:#fff; +color:#FFFFFF; } #site_nav_local_views a { -background-color:#D0DFE7; +background-color:#D9DADB; } #form_notice .form_note + label { background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; } #form_notice #notice_data-attach { filter: alpha(opacity=0); -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf From 2d3e990ed47ee1c7130e1febabe7133884a85c80 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 23 Jun 2009 21:26:47 +0000 Subject: Using default theme design values (it was previously set to identica theme) --- lib/common.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common.php b/lib/common.php index 76eb4a978..8eb464d7d 100644 --- a/lib/common.php +++ b/lib/common.php @@ -95,9 +95,9 @@ $config = 'server' => $_server, 'theme' => 'default', 'design' => - array('backgroundcolor' => '#F0F2F5', + array('backgroundcolor' => '#CEE1E9', 'contentcolor' => '#FFFFFF', - 'sidebarcolor' => '#CEE1E9', + 'sidebarcolor' => '#C8D1D5', 'textcolor' => '#000000', 'linkcolor' => '#002E6E', 'backgroundimage' => null, -- cgit v1.2.3-54-g00ecf From 8588d321201b1713a8b95704e9c6abd39eb80609 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 15:00:10 -0700 Subject: pass through server and path args to daemons --- scripts/startdaemons.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 053c4f8ee..4e87694fb 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -23,9 +23,19 @@ DIR=`dirname $0` DAEMONS=`php $DIR/getvaliddaemons.php` +ARGS= + +if [ $# -gt 0 ]; then + ARGS="$ARGS -s$1" +fi + +if [ $# -gt 1 ]; then + ARGS="$ARGS -p$2" +fi + for f in $DAEMONS; do echo -n "Starting $f..."; - php $DIR/$f + php $DIR/$f $ARGS echo "DONE." done -- cgit v1.2.3-54-g00ecf From 57903bf2acafdc4d15bb9af4fba183b37ec47efe Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 23 Jun 2009 15:53:49 -0700 Subject: Make gateway notices available to the auth user in the API --- actions/twitapifavorites.php | 6 +++++- actions/twitapistatuses.php | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php index e40fea91a..8256668f3 100644 --- a/actions/twitapifavorites.php +++ b/actions/twitapifavorites.php @@ -61,7 +61,11 @@ class TwitapifavoritesAction extends TwitterapiAction $since_id = (int)$this->arg('since_id', 0); $since = $this->arg('since'); - $notice = $user->favoriteNotices(($page-1)*$count, $count); + if (!empty($this->auth_user) && $this->auth_user->id == $user->id) { + $notice = $user->favoriteNotices(($page-1)*$count, $count, true); + } else { + $notice = $user->favoriteNotices(($page-1)*$count, $count, false); + } switch($apidata['content-type']) { case 'xml': diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 2bc404063..e1fbc5c76 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -75,8 +75,10 @@ class TwitapistatusesAction extends TwitterapiAction { parent::handle($args); + $this->auth_user = $apidata['user']; $user = $this->get_user($apidata['api_arg'], $apidata); - $this->auth_user = $user; + + common_debug("auth user = " . $this->auth_user->nickname); if (empty($user)) { $this->clientError(_('No such user!'), 404, @@ -100,8 +102,13 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = (int)$this->arg('since_id', 0); $since = $this->arg('since'); - $notice = $user->noticesWithFriends(($page-1)*$count, - $count, $since_id, $max_id,$since); + if (!empty($this->auth_user) && $this->auth_user->id == $user->id) { + $notice = $user->noticeInbox(($page-1)*$count, + $count, $since_id, $max_id, $since); + } else { + $notice = $user->noticesWithFriends(($page-1)*$count, + $count, $since_id, $max_id, $since); + } switch($apidata['content-type']) { case 'xml': -- cgit v1.2.3-54-g00ecf From f88d767f493c5780476450d92ddb8f27a6ea6caa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 16:44:00 -0700 Subject: add args to daemons fetch --- scripts/startdaemons.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 4e87694fb..7609abec4 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -20,9 +20,6 @@ # This program tries to start the daemons for Laconica. # Note that the 'maildaemon' needs to run as a mail filter. -DIR=`dirname $0` -DAEMONS=`php $DIR/getvaliddaemons.php` - ARGS= if [ $# -gt 0 ]; then @@ -33,6 +30,9 @@ if [ $# -gt 1 ]; then ARGS="$ARGS -p$2" fi +DIR=`dirname $0` +DAEMONS=`php $DIR/getvaliddaemons.php $ARGS` + for f in $DAEMONS; do echo -n "Starting $f..."; -- cgit v1.2.3-54-g00ecf From a9bbf29ca6741437f7c27f7a7757b4969d33d279 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 17:08:33 -0700 Subject: use printf instead of echo for startdaemons.sh --- scripts/startdaemons.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 7609abec4..a44362b57 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -35,7 +35,8 @@ DAEMONS=`php $DIR/getvaliddaemons.php $ARGS` for f in $DAEMONS; do - echo -n "Starting $f..."; + printf "Starting $f..."; php $DIR/$f $ARGS - echo "DONE." + printf "DONE.\n" + done -- cgit v1.2.3-54-g00ecf From 98f518b9af43dd07b97373e6e71be08d553bb21b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 24 Jun 2009 00:00:36 -0700 Subject: fix bug in which design background could accidentally get removed --- actions/groupdesignsettings.php | 2 -- actions/userdesignsettings.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/actions/groupdesignsettings.php b/actions/groupdesignsettings.php index 7270bc8f7..79c192ac4 100644 --- a/actions/groupdesignsettings.php +++ b/actions/groupdesignsettings.php @@ -238,7 +238,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; $design->setDisposition($on, $off, $tile); @@ -263,7 +262,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; $design->setDisposition($on, $off, $tile); diff --git a/actions/userdesignsettings.php b/actions/userdesignsettings.php index d6088aa9d..6e745e96f 100644 --- a/actions/userdesignsettings.php +++ b/actions/userdesignsettings.php @@ -149,7 +149,6 @@ class UserDesignSettingsAction extends DesignSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; $design->setDisposition($on, $off, $tile); @@ -174,7 +173,6 @@ class UserDesignSettingsAction extends DesignSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; $design->setDisposition($on, $off, $tile); -- cgit v1.2.3-54-g00ecf From b702461f6942017d1ae4a08c6701998db14ce536 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 24 Jun 2009 00:27:37 -0700 Subject: fix bad function call (needed to be static) --- lib/imagefile.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/imagefile.php b/lib/imagefile.php index 0c93b257e..52e4c4b22 100644 --- a/lib/imagefile.php +++ b/lib/imagefile.php @@ -72,7 +72,8 @@ class ImageFile break; case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: - throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'), $this->maxFileSize())); + throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'), + ImageFile::maxFileSize())); return; case UPLOAD_ERR_PARTIAL: @unlink($_FILES[$param]['tmp_name']); -- cgit v1.2.3-54-g00ecf From d72a90161b1cb748b58454e4c885b1d789ef3eca Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 24 Jun 2009 00:43:48 -0700 Subject: Only show "tile background" setting once an img has been uploaded --- lib/designsettings.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/designsettings.php b/lib/designsettings.php index 6aa6bb2f1..9650679ac 100644 --- a/lib/designsettings.php +++ b/lib/designsettings.php @@ -132,13 +132,13 @@ class DesignSettingsAction extends AccountSettingsAction _('Off')); $this->element('p', 'form_guide', _('Turn background image on or off.')); $this->elementEnd('li'); - } - $this->elementStart('li'); - $this->checkbox('design_background-image_repeat', - _('Tile background image'), - ($design->disposition & BACKGROUND_TILE) ? true : false ); - $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('design_background-image_repeat', + _('Tile background image'), + ($design->disposition & BACKGROUND_TILE) ? true : false ); + $this->elementEnd('li'); + } $this->elementEnd('ul'); $this->elementEnd('fieldset'); @@ -388,7 +388,11 @@ class DesignSettingsAction extends AccountSettingsAction $original = clone($design); $design->backgroundimage = $filename; + + // default to on, no tile + $design->setDisposition(true, false, false); + $result = $design->update($original); if ($result === false) { -- cgit v1.2.3-54-g00ecf From 83407cc3caa2de0f5fd1b60d67357e415096b6ae Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 14:44:02 -0700 Subject: change foreign_user.id to bigint (for Twitter, Facebook, etc.) --- classes/Foreign_user.php | 22 ++++++++++------------ db/laconica.sql | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/classes/Foreign_user.php b/classes/Foreign_user.php index 61727abe5..8b3e03dfb 100644 --- a/classes/Foreign_user.php +++ b/classes/Foreign_user.php @@ -4,42 +4,41 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Foreign_user extends Memcached_DataObject +class Foreign_user extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ public $__table = 'foreign_user'; // table name - public $id; // int(4) primary_key not_null + public $id; // bigint(8) primary_key not_null public $service; // int(4) primary_key not_null public $uri; // varchar(255) unique_key not_null - public $nickname; // varchar(255) + public $nickname; // varchar(255) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ - function staticGet($k,$v=null) - { return Memcached_DataObject::staticGet('Foreign_user',$k,$v); } + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Foreign_user',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - + // XXX: This only returns a 1->1 single obj mapping. Change? Or make // a getForeignUsers() that returns more than one? --Zach - static function getForeignUser($id, $service) { + static function getForeignUser($id, $service) { $fuser = new Foreign_user(); $fuser->whereAdd("service = $service"); $fuser->whereAdd("id = $id"); $fuser->limit(1); - + if ($fuser->find()) { $fuser->fetch(); return $fuser; } - - return null; + + return null; } - + function updateKeys(&$orig) { $parts = array(); @@ -68,5 +67,4 @@ class Foreign_user extends Memcached_DataObject return $result; } - } diff --git a/db/laconica.sql b/db/laconica.sql index 95796d5cc..3f8918de6 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -277,7 +277,7 @@ create table foreign_service ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table foreign_user ( - id int not null comment 'unique numeric key on foreign service', + id bigint not null comment 'unique numeric key on foreign service', service int not null comment 'foreign key to service' references foreign_service(id), uri varchar(255) not null unique key comment 'identifying URI', nickname varchar(255) comment 'nickname on foreign service', -- cgit v1.2.3-54-g00ecf From 936567394ff33d47d645de8071d5c249eb62fa78 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 14:59:36 -0700 Subject: script to upgrade a database from 0.7.4 to 0.8.0 --- db/074to080.sql | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 db/074to080.sql diff --git a/db/074to080.sql b/db/074to080.sql new file mode 100644 index 000000000..ff0819159 --- /dev/null +++ b/db/074to080.sql @@ -0,0 +1,109 @@ +alter table user + add column design_id integer comment 'id of a design' references design(id), + add column viewdesigns tinyint default 1 comment 'whether to view user-provided designs'; + +alter table notice add column + conversation integer comment 'id of root notice in this conversation' references notice (id), + add index notice_conversation_idx (conversation); + +alter table foreign_user + modify column id bigint not null comment 'unique numeric key on foreign service'; + +alter table foreign_link + modify column foreign_id bigint unsigned comment 'link to user on foreign service, if exists'; + +alter table user_group + add column design_id integer comment 'id of a design' references design(id); + +create table file ( + id integer primary key auto_increment, + url varchar(255) comment 'destination URL after following redirections', + mimetype varchar(50) comment 'mime type of resource', + size integer comment 'size of resource when available', + title varchar(255) comment 'title of resource when available', + date integer(11) comment 'date of resource according to http query', + protected integer(1) comment 'true when URL is private (needs login)', + filename varchar(255) comment 'if a local file, name of the file', + modified timestamp comment 'date this record was modified', + + unique(url) +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; + +create table file_oembed ( + file_id integer primary key comment 'oEmbed for that URL/file' references file (id), + version varchar(20) comment 'oEmbed spec. version', + type varchar(20) comment 'oEmbed type: photo, video, link, rich', + provider varchar(50) comment 'name of this oEmbed provider', + provider_url varchar(255) comment 'URL of this oEmbed provider', + width integer comment 'width of oEmbed resource when available', + height integer comment 'height of oEmbed resource when available', + html text comment 'html representation of this oEmbed resource when applicable', + title varchar(255) comment 'title of oEmbed resource when available', + author_name varchar(50) comment 'author name for this oEmbed resource', + author_url varchar(255) comment 'author URL for this oEmbed resource', + url varchar(255) comment 'URL for this oEmbed resource when applicable (photo, link)', + modified timestamp comment 'date this record was modified' + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; + +create table file_redirection ( + + url varchar(255) primary key comment 'short URL (or any other kind of redirect) for file (id)', + file_id integer comment 'short URL for what URL/file' references file (id), + redirections integer comment 'redirect count', + httpcode integer comment 'HTTP status code (20x, 30x, etc.)', + modified timestamp comment 'date this record was modified' + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table file_thumbnail ( + + file_id integer primary key comment 'thumbnail for what URL/file' references file (id), + url varchar(255) comment 'URL of thumbnail', + width integer comment 'width of thumbnail', + height integer comment 'height of thumbnail', + modified timestamp comment 'date this record was modified', + + unique(url) +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table file_to_post ( + + file_id integer comment 'id of URL/file' references file (id), + post_id integer comment 'id of the notice it belongs to' references notice (id), + modified timestamp comment 'date this record was modified', + + constraint primary key (file_id, post_id) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table design ( + id integer primary key auto_increment comment 'design ID', + backgroundcolor integer comment 'main background color', + contentcolor integer comment 'content area background color', + sidebarcolor integer comment 'sidebar background color', + textcolor integer comment 'text color', + linkcolor integer comment 'link color', + backgroundimage varchar(255) comment 'background image, if any', + disposition tinyint default 1 comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image' +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table group_block ( + group_id integer not null comment 'group profile is blocked from' references user_group (id), + blocked integer not null comment 'profile that is blocked' references profile (id), + blocker integer not null comment 'user making the block' references user (id), + modified timestamp comment 'date of blocking', + + constraint primary key (group_id, blocked) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +create table group_alias ( + + alias varchar(64) primary key comment 'additional nickname for the group', + group_id integer not null comment 'group profile is blocked from' references user_group (id), + modified timestamp comment 'date alias was created', + + index group_alias_group_id_idx (group_id) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; -- cgit v1.2.3-54-g00ecf From e3c5d1664f8049b85198cf5c43957a237cb29bcf Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 24 Jun 2009 16:10:28 -0700 Subject: Take out noisy debugging statement --- actions/twitapistatuses.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index e1fbc5c76..555c746cb 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -78,8 +78,6 @@ class TwitapistatusesAction extends TwitterapiAction $this->auth_user = $apidata['user']; $user = $this->get_user($apidata['api_arg'], $apidata); - common_debug("auth user = " . $this->auth_user->nickname); - if (empty($user)) { $this->clientError(_('No such user!'), 404, $apidata['content-type']); -- cgit v1.2.3-54-g00ecf From fa57e717e3bbb01e0c19fcb30f3d67bd596c730f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 00:25:22 +0000 Subject: Moved the attachment representation outside of the anchor so that onclick, it doesn't follow through on the href (e.g., it would play the video in the overlay instead) --- lib/attachmentlist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index a2446a886..60f9a27c0 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -249,8 +249,8 @@ class Attachment extends AttachmentListItem $this->out->elementStart('div', 'entry-title'); $this->out->elementStart('a', $this->linkAttr()); $this->out->element('span', null, $this->linkTitle()); - $this->showRepresentation(); $this->out->elementEnd('a'); + $this->showRepresentation(); $this->out->elementEnd('div'); if (!empty($this->oembed->author_name) || !empty($this->oembed->provider)) { -- cgit v1.2.3-54-g00ecf From 835799ff169387e5b686b2740020dc0e49154bb2 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 00:49:54 +0000 Subject: Separated attachment view components --- lib/attachmentlist.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 60f9a27c0..b5513ade7 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -250,6 +250,9 @@ class Attachment extends AttachmentListItem $this->out->elementStart('a', $this->linkAttr()); $this->out->element('span', null, $this->linkTitle()); $this->out->elementEnd('a'); + $this->out->elementEnd('div'); + + $this->out->elementStart('div', 'entry-content'); $this->showRepresentation(); $this->out->elementEnd('div'); -- cgit v1.2.3-54-g00ecf From 5f1b97e2add1b525401deef290ba29937135d073 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 18:02:17 -0700 Subject: no memcached queue handler --- scripts/getvaliddaemons.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index 198ea8fb9..97c230784 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -38,9 +38,6 @@ if(common_config('xmpp','enabled')) { echo "xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php "; echo "xmppconfirmhandler.php "; } -if(common_config('memcached','enabled')) { - echo "memcachedqueuehandler.php "; -} if(common_config('twitterbridge','enabled')) { echo "twitterstatusfetcher.php "; } -- cgit v1.2.3-54-g00ecf From 63f12c48a8dd7c75093587d78a8fd557330d202e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 19:17:41 -0700 Subject: make stomp server work with username and password --- lib/common.php | 8 ++- lib/queuehandler.php | 15 ++++-- lib/util.php | 146 ++++++++++++++++++++++++++------------------------- 3 files changed, 93 insertions(+), 76 deletions(-) diff --git a/lib/common.php b/lib/common.php index 8eb464d7d..bb1a4255d 100644 --- a/lib/common.php +++ b/lib/common.php @@ -125,7 +125,13 @@ $config = array('appname' => 'laconica', # for syslog 'priority' => 'debug'), # XXX: currently ignored 'queue' => - array('enabled' => false), + array('enabled' => false, + 'subsystem' => 'db', # default to database, or 'stomp' + 'stomp_server' => null, + 'queue_basename' => 'laconica', + 'stomp_username' => null, + 'stomp_password' => null, + ), 'license' => array('url' => 'http://creativecommons.org/licenses/by/3.0/', 'title' => 'Creative Commons Attribution 3.0', diff --git a/lib/queuehandler.php b/lib/queuehandler.php index d5e0150d9..ae403c65e 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -112,12 +112,21 @@ class QueueHandler extends Daemon } function stomp_dispatch() { - require("Stomp.php"); - $con = new Stomp(common_config('queue','stomp_server')); - if (!$con->connect()) { + + // use an external message queue system via STOMP + require_once("Stomp.php"); + + $server = common_config('queue','stomp_server'); + $username = common_config('queue', 'stomp_username'); + $password = common_config('queue', 'stomp_password'); + + $con = new Stomp($server); + + if (!$con->connect($username, $password)) { $this->log(LOG_ERR, 'Failed to connect to queue server'); return false; } + $queue_basename = common_config('queue','queue_basename'); // subscribe to the relevant queue (format: basename-transport) $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport()); diff --git a/lib/util.php b/lib/util.php index 1af462516..30b767c3e 100644 --- a/lib/util.php +++ b/lib/util.php @@ -826,89 +826,91 @@ function common_broadcast_notice($notice, $remote=false) function common_enqueue_notice($notice) { + $transports = array('omb', 'sms', 'public', 'twitter', 'facebook', 'ping'); + + if (common_config('xmpp', 'enabled')) + { + $transports[] = 'jabber'; + } + if (common_config('queue','subsystem') == 'stomp') { - // use an external message queue system via STOMP - require_once("Stomp.php"); - $con = new Stomp(common_config('queue','stomp_server')); - if (!$con->connect()) { - common_log(LOG_ERR, 'Failed to connect to queue server'); - return false; - } - $queue_basename = common_config('queue','queue_basename'); - foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) { - if (!$con->send( - '/queue/'.$queue_basename.'-'.$transport, // QUEUE - $notice->id, // BODY of the message - array ( // HEADERS of the msg - 'created' => $notice->created - ))) { - common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); - return false; - } - common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport); - } - - //send tags as headers, so they can be used as JMS selectors - common_log(LOG_DEBUG, 'searching for tags ' . $notice->id); - $tags = array(); - $tag = new Notice_tag(); - $tag->notice_id = $notice->id; - if ($tag->find()) { - while ($tag->fetch()) { - common_log(LOG_DEBUG, 'tag found = ' . $tag->tag); - array_push($tags,$tag->tag); - } - } - $tag->free(); - - $con->send('/topic/laconica.'.$notice->profile_id, - $notice->content, - array( - 'profile_id' => $notice->profile_id, - 'created' => $notice->created, - 'tags' => implode($tags,' - ') - ) - ); - common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id); - $con->send('/topic/laconica.allusers', - $notice->content, - array( - 'profile_id' => $notice->profile_id, - 'created' => $notice->created, - 'tags' => implode($tags,' - ') - ) - ); - common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id); - $result = true; + common_enqueue_notice_stomp($notice, $transports); } else { - // in any other case, 'internal' - foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) { - $qi = new Queue_item(); - $qi->notice_id = $notice->id; - $qi->transport = $transport; - $qi->created = $notice->created; - $result = $qi->insert(); - if (!$result) { - $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); - common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); - return false; - } - common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); - } + common_enqueue_notice_db($notice, $transports); } return $result; } -function common_post_inbox_transports() +function common_enqueue_notice_stomp($notice, $transports) { - $transports = array('omb', 'sms'); + // use an external message queue system via STOMP + require_once("Stomp.php"); + + $server = common_config('queue','stomp_server'); + $username = common_config('queue', 'stomp_username'); + $password = common_config('queue', 'stomp_password'); - if (common_config('xmpp', 'enabled')) { - $transports = array_merge($transports, array('jabber', 'public')); + $con = new Stomp($server); + + if (!$con->connect($username, $password)) { + common_log(LOG_ERR, 'Failed to connect to queue server'); + return false; } - return $transports; + $queue_basename = common_config('queue','queue_basename'); + + foreach ($transports as $transport) { + $result = $con->send('/queue/'.$queue_basename.'-'.$transport, // QUEUE + $notice->id, // BODY of the message + array ('created' => $notice->created)); + if (!$result) { + common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); + return false; + } + common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport); + } + + //send tags as headers, so they can be used as JMS selectors + common_log(LOG_DEBUG, 'searching for tags ' . $notice->id); + $tags = array(); + $tag = new Notice_tag(); + $tag->notice_id = $notice->id; + if ($tag->find()) { + while ($tag->fetch()) { + common_log(LOG_DEBUG, 'tag found = ' . $tag->tag); + array_push($tags,$tag->tag); + } + } + $tag->free(); + + $con->send('/topic/laconica.'.$notice->profile_id, + $notice->content, + array( + 'profile_id' => $notice->profile_id, + 'created' => $notice->created, + 'tags' => implode($tags,' - ') + ) + ); + common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id); + $con->send('/topic/laconica.allusers', + $notice->content, + array( + 'profile_id' => $notice->profile_id, + 'created' => $notice->created, + 'tags' => implode($tags,' - ') + ) + ); + common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id); + $result = true; +} + +function common_enqueue_notice_db($notice, $transports) +{ + // in any other case, 'internal' + foreach ($transports as $transport) { + common_enqueue_notice_transport($notice, $transport); + } } function common_enqueue_notice_transport($notice, $transport) -- cgit v1.2.3-54-g00ecf From becfd6b3b5da57298137c3349efbd49fe347ccfd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 19:31:12 -0700 Subject: all daemons take an id parameter --- lib/xmppqueuehandler.php | 9 ++++----- scripts/jabberqueuehandler.php | 20 ++++++++++---------- scripts/publicqueuehandler.php | 20 ++++++++++---------- scripts/xmppconfirmhandler.php | 20 ++++++++++---------- scripts/xmppdaemon.php | 22 +++++++++++----------- 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index a078cd9f7..986e09c25 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -22,7 +22,7 @@ if (!defined('LACONICA')) { exit(1); } require_once(INSTALLDIR.'/lib/queuehandler.php'); /** - * Common superclass for all XMPP-using queue handlers. They all need to + * Common superclass for all XMPP-using queue handlers. They all need to * service their message queues on idle, and forward any incoming messages * to the XMPP listener connection. So, we abstract out common code to a * superclass. @@ -30,12 +30,11 @@ require_once(INSTALLDIR.'/lib/queuehandler.php'); class XmppQueueHandler extends QueueHandler { - function start() { # Low priority; we don't want to receive messages $this->log(LOG_INFO, "INITIALIZE"); - $this->conn = jabber_connect($this->_id); + $this->conn = jabber_connect($this->_id.$this->transport()); if ($this->conn) { $this->conn->addEventHandler('message', 'forward_message', $this); $this->conn->addEventHandler('reconnect', 'handle_reconnect', $this); @@ -44,7 +43,7 @@ class XmppQueueHandler extends QueueHandler } return !is_null($this->conn); } - + function handle_reconnect(&$pl) { $this->conn->processUntil('session_start'); @@ -63,7 +62,7 @@ class XmppQueueHandler extends QueueHandler die($e->getMessage()); } } - + function forward_message(&$pl) { if ($pl['type'] != 'chat') { diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index a44993236..5b581629d 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -20,13 +20,13 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r::'; -$longoptions = array('resource::'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { - $resource = $args[0]; + $id = $args[0]; } else { - $resource = null; + $id = null; } -$handler = new JabberQueueHandler($resource); +$handler = new JabberQueueHandler($id); $handler->runOnce(); diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index 58ecc1745..701d50e01 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -20,13 +20,13 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r::'; -$longoptions = array('resource::'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { - $resource = $args[0]; + $id = $args[0]; } else { - $resource = null; + $id = null; } -$handler = new PublicQueueHandler($resource); +$handler = new PublicQueueHandler($id); $handler->runOnce(); diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index 883934fd6..d6821ddef 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -20,13 +20,13 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r::'; -$longoptions = array('resource::'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = << 0) { - $resource = $args[0]; + $id = $args[0]; } else { - $resource = null; + $id = null; } -$handler = new XmppConfirmHandler($resource); +$handler = new XmppConfirmHandler($id); $handler->runOnce(); diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index 661631937..3eecfec29 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -20,13 +20,13 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -$shortoptions = 'r::'; -$longoptions = array('resource::'); +$shortoptions = 'i::'; +$longoptions = array('id::'); $helptext = <<resource = $resource; + $this->resource = $resource . 'daemon'; } else { $this->resource = common_config('xmpp', 'resource') . 'daemon'; } @@ -323,16 +323,16 @@ if (common_config('xmpp','enabled')==false) { exit(); } -if (have_option('r')) { - $resource = get_option_value('r'); -} else if (have_option('--resource')) { - $resource = get_option_value('--resource'); +if (have_option('i')) { + $id = get_option_value('i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); } else if (count($args) > 0) { - $resource = $args[0]; + $id = $args[0]; } else { - $resource = null; + $id = null; } -$daemon = new XMPPDaemon($resource); +$daemon = new XMPPDaemon($id); $daemon->runOnce(); -- cgit v1.2.3-54-g00ecf From 6038420a69096854e386b8e9dcdc5993d7e9af8f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 19:35:19 -0700 Subject: add i argument for all daemons --- scripts/startdaemons.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index a44362b57..8b7451cd7 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -23,7 +23,8 @@ ARGS= if [ $# -gt 0 ]; then - ARGS="$ARGS -s$1" + ID=`echo $1 | sed s/\\\\./_/g` + ARGS="$ARGS -s$1 -i$ID" fi if [ $# -gt 1 ]; then -- cgit v1.2.3-54-g00ecf From 246013d984245737983054abf7496aa3879cfc58 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 24 Jun 2009 19:50:45 -0700 Subject: different args for pid and daemon scripts --- scripts/startdaemons.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 8b7451cd7..9ead20acd 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -20,24 +20,27 @@ # This program tries to start the daemons for Laconica. # Note that the 'maildaemon' needs to run as a mail filter. -ARGS= +ARGSG= +ARGSD= if [ $# -gt 0 ]; then + ARGSG="$ARGSG -s$1" ID=`echo $1 | sed s/\\\\./_/g` - ARGS="$ARGS -s$1 -i$ID" + ARGSD="$ARGSD -s$1 -i$ID" fi if [ $# -gt 1 ]; then - ARGS="$ARGS -p$2" + ARGSD="$ARGSD -p$2" + ARGSG="$ARGSG -p$2" fi DIR=`dirname $0` -DAEMONS=`php $DIR/getvaliddaemons.php $ARGS` +DAEMONS=`php $DIR/getvaliddaemons.php $ARGSG` for f in $DAEMONS; do printf "Starting $f..."; - php $DIR/$f $ARGS + php $DIR/$f $ARGSD printf "DONE.\n" done -- cgit v1.2.3-54-g00ecf From 0c5c8348277e234f5f3d1e0b4956e698a6f95a14 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 03:46:52 +0000 Subject: Slightly more specific selector. Looks only in the notices in the content area --- js/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/util.js b/js/util.js index 65a77960a..221c85120 100644 --- a/js/util.js +++ b/js/util.js @@ -280,13 +280,13 @@ function NoticeAttachments() { timeout : 0 }; - $('a.attachment').click(function() { + $('#content .notice a.attachment').click(function() { $().jOverlay({url: $('address .url')[0].href+'/attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'}); return false; }); var t; - $("body:not(#shownotice) a.thumbnail").hover( + $("body:not(#shownotice) #content .notice a.thumbnail").hover( function() { var anchor = $(this); $("a.thumbnail").children('img').hide(); -- cgit v1.2.3-54-g00ecf From fcb43dd7112740284d2c1cb2708ac6a8a135cbdb Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 06:55:40 +0000 Subject: Added class entry-content to attachment list container --- lib/attachmentlist.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index b5513ade7..f6a1b59d0 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -82,7 +82,8 @@ class AttachmentList extends Widget $atts = new File; $att = $atts->getAttachments($this->notice->id); if (empty($att)) return 0; - $this->out->elementStart('dl', array('id' =>'attachments')); + $this->out->elementStart('dl', array('id' =>'attachments', + 'class' => 'entry-content')); $this->out->element('dt', null, _('Attachments')); $this->out->elementStart('dd'); $this->out->elementStart('ol', array('class' => 'attachments')); -- cgit v1.2.3-54-g00ecf From 75d6b0707ce719a23526ed8c66de7240a9481285 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 07:55:52 +0000 Subject: Style for entity_aliases --- theme/base/css/display.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 8957a5b40..d01be7700 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -548,7 +548,8 @@ margin-bottom:18px; .entity_profile .entity_location, .entity_profile .entity_url, .entity_profile .entity_note, -.entity_profile .entity_tags { +.entity_profile .entity_tags, +.entity_profile .entity_aliases { margin-left:113px; margin-bottom:4px; } -- cgit v1.2.3-54-g00ecf From 79547d99cf59fe9e2df94e33989d5a1d3b85be1b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 02:11:34 -0700 Subject: blow cache when new notice in conversation is saved --- classes/Notice.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/classes/Notice.php b/classes/Notice.php index 6f9b73be4..8689dd427 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -339,6 +339,19 @@ class Notice extends Memcached_DataObject $this->blowPublicCache($blowLast); $this->blowTagCache($blowLast); $this->blowGroupCache($blowLast); + $this->blowConversationCache($blowLast); + } + + function blowConversationCache($blowLast=false) + { + $cache = common_memcache(); + if ($cache) { + $ck = 'notice:conversation:'.$this->conversation; + $cache->delete($ck); + if ($blowLast) { + $cache->delete($ck.';last'); + } + } } function blowGroupCache($blowLast=false) -- cgit v1.2.3-54-g00ecf From 262f864555dcad18fbdd044f753584dae5729e86 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 02:57:16 -0700 Subject: don't try to load a null notice into the list --- classes/Notice.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index 8689dd427..59ffef91a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -690,7 +690,10 @@ class Notice extends Memcached_DataObject if (!empty($cache)) { $notices = array(); foreach ($ids as $id) { - $notices[] = Notice::staticGet('id', $id); + $n = Notice::staticGet('id', $id); + if (!empty($n)) { + $notices[] = $n; + } } return new ArrayWrapper($notices); } else { -- cgit v1.2.3-54-g00ecf From 3ca9e85ce4f0db7f160f9a8e989bec898bfbbf55 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 09:43:30 -0700 Subject: update conversations to use newer query format --- actions/conversation.php | 12 ++--------- classes/Notice.php | 53 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/actions/conversation.php b/actions/conversation.php index d3fc5b6a9..654a670f5 100644 --- a/actions/conversation.php +++ b/actions/conversation.php @@ -63,6 +63,7 @@ class ConversationAction extends Action if (empty($this->id)) { return false; } + $this->id = $this->id+0; $this->page = $this->trimmed('page'); if (empty($this->page)) { $this->page = 1; @@ -106,18 +107,10 @@ class ConversationAction extends Action function showContent() { - // FIXME this needs to be a tree, not a list - - $qry = 'SELECT * FROM notice WHERE conversation = %s '; - $offset = ($this->page-1) * NOTICES_PER_PAGE; $limit = NOTICES_PER_PAGE + 1; - $txt = sprintf($qry, $this->id); - - $notices = Notice::getStream($txt, - 'notice:conversation:'.$this->id, - $offset, $limit); + $notices = Notice::conversationStream($this->id, $offset, $limit); $ct = new ConversationTree($notices, $this); @@ -126,7 +119,6 @@ class ConversationAction extends Action $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'conversation', array('id' => $this->id)); } - } /** diff --git a/classes/Notice.php b/classes/Notice.php index 59ffef91a..44179b254 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -346,7 +346,7 @@ class Notice extends Memcached_DataObject { $cache = common_memcache(); if ($cache) { - $ck = 'notice:conversation:'.$this->conversation; + $ck = 'notice:conversation_ids:'.$this->conversation; $cache->delete($ck); if ($blowLast) { $cache->delete($ck.';last'); @@ -762,6 +762,57 @@ class Notice extends Memcached_DataObject return $ids; } + function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) + { + $ids = Notice::stream(array('Notice', '_conversationStreamDirect'), + array($id), + 'notice:conversation_ids:'.$id, + $offset, $limit, $since_id, $max_id, $since); + + return Notice::getStreamByIds($ids); + } + + function _conversationStreamDirect($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->whereAdd('conversation = '.$id); + + $notice->orderBy('id DESC'); + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } + + if ($since_id != 0) { + $notice->whereAdd('id > ' . $since_id); + } + + if ($max_id != 0) { + $notice->whereAdd('id <= ' . $max_id); + } + + if (!is_null($since)) { + $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $ids = array(); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + $notice->free(); + $notice = NULL; + + return $ids; + } + function addToInboxes() { $enabled = common_config('inboxes', 'enabled'); -- cgit v1.2.3-54-g00ecf From 1e17f1256a1166db6bd3acd35fd437262ba27ffd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 16:55:19 +0000 Subject: Shows the selected file attachment under the form_notice textarea --- js/util.js | 9 +++++++++ theme/base/css/display.css | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/js/util.js b/js/util.js index 221c85120..9156045bb 100644 --- a/js/util.js +++ b/js/util.js @@ -233,6 +233,7 @@ $(document).ready(function(){ $("#form_notice").each(addAjaxHidden); NoticeReply(); NoticeAttachments(); + NoticeDataAttachSelected(); }); function NoticeReply() { @@ -310,3 +311,11 @@ function NoticeAttachments() { } ); } + +function NoticeDataAttachSelected() { + $('#notice_data-attach').change(function() { + S = '
      '+$(this).val()+'
      '; + NDAS = $('#notice_data-attach_selected'); + (NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S); + }); +} diff --git a/theme/base/css/display.css b/theme/base/css/display.css index d01be7700..bfcc9a7fa 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -510,10 +510,11 @@ margin-bottom:7px; margin-left:18px; float:left; } -#form_notice .error { +#form_notice .error, +#form_notice .success { float:left; clear:both; -width:96.9%; +width:81.5%; margin-bottom:0; line-height:1.618; } -- cgit v1.2.3-54-g00ecf From 5cc5bae4a91a6f0ac7bf3569d268e203da78274d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 17:00:32 +0000 Subject: Adds a scrollbar if the filename is too long for the attached file --- theme/base/css/display.css | 1 + 1 file changed, 1 insertion(+) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index bfcc9a7fa..c8f23e4f5 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -517,6 +517,7 @@ clear:both; width:81.5%; margin-bottom:0; line-height:1.618; +overflow:auto; } /* entity_profile */ -- cgit v1.2.3-54-g00ecf From 4d56bc6a0adba63c5546d5d18a70fa2c989839be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 11:08:32 -0700 Subject: streamline the file action --- actions/file.php | 44 ++++++++++++++++++++++++++++++++------------ classes/Notice.php | 14 ++++++++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/actions/file.php b/actions/file.php index bb245c4a7..271f57ab9 100644 --- a/actions/file.php +++ b/actions/file.php @@ -21,20 +21,40 @@ if (!defined('LACONICA')) { exit(1); } require_once(INSTALLDIR.'/actions/shownotice.php'); -class FileAction extends ShowNoticeAction +class FileAction extends Action { - function showPage() { - $source_url = common_local_url('file', array('notice' => $this->notice->id)); - $query = "select file_redirection.url as url from file join file_redirection on file.id = file_redirection.file_id where file.url = '$source_url'"; - $file = new File_redirection; - $file->query($query); - $file->fetch(); - if (empty($file->url)) { - die('nothing attached here'); - } else { - header("Location: {$file->url}"); - die(); + var $id = null; + var $filerec = null; + + function prepare($args) + { + parent::prepare($args); + $this->id = $this->trimmed('notice'); + if (empty($this->id)) { + $this->clientError(_('No notice id')); + } + $notice = Notice::staticGet('id', $this->id); + if (empty($notice)) { + $this->clientError(_('No notice')); + } + $atts = $notice->attachments(); + if (empty($atts)) { + $this->clientError(_('No attachments')); + } + foreach ($atts as $att) { + if (!empty($att->filename)) { + $this->filerec = $att; + break; + } } + if (empty($this->filerec)) { + $this->clientError(_('No uploaded attachments')); + } + return true; + } + + function handle() { + common_redirect($this->filerec->url); } } diff --git a/classes/Notice.php b/classes/Notice.php index 44179b254..9960d3d0a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -331,6 +331,20 @@ class Notice extends Memcached_DataObject return $n_attachments; } + function attachments() { + // XXX: cache this + $att = array(); + $f2p = new File_to_post; + $f2p->post_id = $this->id; + if ($f2p->find()) { + while ($f2p->fetch()) { + $f = File::staticGet($f2p->file_id); + $att[] = clone($f); + } + } + return $att; + } + function blowCaches($blowLast=false) { $this->blowSubsCache($blowLast); -- cgit v1.2.3-54-g00ecf From 09010c4c2b80bb94607e2946fa94bca5ff160fed Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 11:08:55 -0700 Subject: show backtrace on error --- index.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index cb26e2196..cb6a0fe60 100644 --- a/index.php +++ b/index.php @@ -48,7 +48,14 @@ function handleError($error) $logmsg .= " : ". $error->getDebugInfo(); } common_log(LOG_ERR, $logmsg); - if ($error instanceof DB_DataObject_Error) { + if(common_config('site', 'logdebug')) { + $bt = $error->getBacktrace(); + foreach ($bt as $line) { + common_log(LOG_ERR, $line); + } + } + if ($error instanceof DB_DataObject_Error || + $error instanceof DB_Error) { $msg = sprintf(_('The database for %s isn\'t responding correctly, '. 'so the site won\'t work properly. '. 'The site admins probably know about the problem, '. -- cgit v1.2.3-54-g00ecf From 638905c270824b3c0e673ae9872937c06fbd862e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 11:10:34 -0700 Subject: avoid getting duplicate errors on upload --- actions/newnotice.php | 43 +++++++++++++++++++++--------------- classes/File.php | 5 +++-- classes/File_redirection.php | 52 ++++++++++++++++++-------------------------- classes/File_to_post.php | 20 ++++++++++++----- 4 files changed, 64 insertions(+), 56 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 4a2c369f0..3677f54c2 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -236,6 +236,7 @@ class NewnoticeAction extends Action $this->deleteFile($filename); $this->clientError(_('Max notice size is 140 chars, including attachment URL.')); } + $fileRecord = $this->rememberFile($filename, $mimetype, $short_fileurl); } $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, @@ -249,7 +250,7 @@ class NewnoticeAction extends Action } if (isset($mimetype)) { - $this->attachFile($notice, $filename, $mimetype, $short_fileurl); + $this->attachFile($notice, $fileRecord); } common_broadcast_notice($notice); @@ -304,12 +305,12 @@ class NewnoticeAction extends Action @unlink($filepath); } - function attachFile($notice, $filename, $mimetype, $short) + function rememberFile($filename, $mimetype, $short) { $file = new File; $file->filename = $filename; - $file->url = common_local_url('file', array('notice' => $notice->id)); + $file->url = File::url($filename); $filepath = File::path($filename); @@ -324,28 +325,34 @@ class NewnoticeAction extends Action $this->clientError(_('There was a database error while saving your file. Please try again.')); } - $file_redir = new File_redirection; - $file_redir->url = File::url($filename); - $file_redir->file_id = $file_id; + $this->maybeAddRedir($file_id, $short); + } - $result = $file_redir->insert(); + function maybeAddRedir($file_id, $url) + { + $file_redir = File_redirection::staticGet('url', $url); - if (!$result) { - common_log_db_error($file_redir, "INSERT", __FILE__); - $this->clientError(_('There was a database error while saving your file. Please try again.')); - } + if (empty($file_redir)) { + $file_redir = new File_redirection; + $file_redir->url = $url; + $file_redir->file_id = $file_id; - $f2p = new File_to_post; - $f2p->file_id = $file_id; - $f2p->post_id = $notice->id; - $f2p->insert(); + $result = $file_redir->insert(); - if (!$result) { - common_log_db_error($f2p, "INSERT", __FILE__); - $this->clientError(_('There was a database error while saving your file. Please try again.')); + if (!$result) { + common_log_db_error($file_redir, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); + } } } + function attachFile($notice, $filerec) + { + File_to_post::processNew($filerec->id, $notice->id); + + $this->maybeAddRedir($filerec->id, common_local_url('file', array('notice' => $this->notice->id))); + } + /** * Show an Ajax-y error message * diff --git a/classes/File.php b/classes/File.php index b98c9e665..5dd7cd865 100644 --- a/classes/File.php +++ b/classes/File.php @@ -91,9 +91,10 @@ class File extends Memcached_DataObject $given_url = File_redirection::_canonUrl($given_url); if (empty($given_url)) return -1; // error, no url to process $file = File::staticGet('url', $given_url); - if (empty($file->id)) { + if (empty($file)) { $file_redir = File_redirection::staticGet('url', $given_url); - if (empty($file_redir->id)) { + if (empty($file_redir)) { + common_debug("processNew() '$given_url' not a known redirect.\n"); $redir_data = File_redirection::where($given_url); $redir_url = $redir_data['url']; if ($redir_url === $given_url) { diff --git a/classes/File_redirection.php b/classes/File_redirection.php index c173017e2..d6fa0bcb6 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -66,21 +66,17 @@ class File_redirection extends Memcached_DataObject // let's see if we know this... $a = File::staticGet('url', $short_url); - if (empty($a->id)) { + + if (!empty($a)) { + // this is a direct link to $a->url + return $a->url; + } else { $b = File_redirection::staticGet('url', $short_url); - if (empty($b->id)) { - // we'll have to figure it out - } else { + if (!empty($b)) { // this is a redirect to $b->file_id - $a = File::staticGet($b->file_id); - $url = $a->url; + $a = File::staticGet('id', $b->file_id); + return $a->url; } - } else { - // this is a direct link to $a->url - $url = $a->url; - } - if (isset($url)) { - return $url; } $curlh = File_redirection::_commonCurl($short_url, $redirs); @@ -118,28 +114,22 @@ class File_redirection extends Memcached_DataObject } function makeShort($long_url) { - $long_url = File_redirection::_canonUrl($long_url); - // do we already know this long_url and have a short redirection for it? - $file = new File; - $file_redir = new File_redirection; - $file->url = $long_url; - $file->joinAdd($file_redir); - $file->selectAdd('length(file_redirection.url) as len'); - $file->limit(1); - $file->orderBy('len'); - $file->find(true); - if (!empty($file->url) && (strlen($file->url) < strlen($long_url))) { - return $file->url; - } - // if yet unknown, we must find a short url according to user settings - $short_url = File_redirection::_userMakeShort($long_url, common_current_user()); - return $short_url; + $canon = File_redirection::_canonUrl($long_url); + + $short_url = File_redirection::_userMakeShort($canon); + + // Did we get one? Is it shorter? + if (!empty($short_url) && mb_strlen($short_url) < mb_strlen($long_url)) { + return $short_url; + } else { + return $long_url; + } } - function _userMakeShort($long_url, $user) { + function _userMakeShort($long_url) { $short_url = common_shorten_url($long_url); - if ($short_url) { + if (!empty($short_url) && $short_url != $long_url) { $short_url = (string)$short_url; // store it $file = File::staticGet('url', $long_url); @@ -162,7 +152,7 @@ class File_redirection extends Memcached_DataObject } return $short_url; } - return $long_url; + return null; } function _canonUrl($in_url, $default_scheme = 'http://') { diff --git a/classes/File_to_post.php b/classes/File_to_post.php index db0a8d216..d35febb77 100644 --- a/classes/File_to_post.php +++ b/classes/File_to_post.php @@ -25,7 +25,7 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; * Table Definition for file_to_post */ -class File_to_post extends Memcached_DataObject +class File_to_post extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -44,17 +44,27 @@ class File_to_post extends Memcached_DataObject function processNew($file_id, $notice_id) { static $seen = array(); if (empty($seen[$notice_id]) || !in_array($file_id, $seen[$notice_id])) { - $f2p = new File_to_post; - $f2p->file_id = $file_id; - $f2p->post_id = $notice_id; - $f2p->insert(); + + $f2p = File_to_post::pkeyGet(array('post_id' => $notice_id, + 'file_id' => $file_id)); + if (empty($f2p)) { + $f2p = new File_to_post; + $f2p->file_id = $file_id; + $f2p->post_id = $notice_id; + $f2p->insert(); + } + if (empty($seen[$notice_id])) { $seen[$notice_id] = array($file_id); } else { $seen[$notice_id][] = $file_id; } } + } + function &pkeyGet($kv) + { + return Memcached_DataObject::pkeyGet('File_to_post', $kv); } } -- cgit v1.2.3-54-g00ecf From c96572c0909793fd1f38def21f2577e13d98766d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 11:23:47 -0700 Subject: fix caching for conversations, again --- classes/Notice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index 9960d3d0a..5bcfa896e 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -360,7 +360,7 @@ class Notice extends Memcached_DataObject { $cache = common_memcache(); if ($cache) { - $ck = 'notice:conversation_ids:'.$this->conversation; + $ck = common_cache_key('notice:conversation_ids:'.$this->conversation); $cache->delete($ck); if ($blowLast) { $cache->delete($ck.';last'); -- cgit v1.2.3-54-g00ecf From 0eb77e67532cbbdfd1f099303ae8e1614296b87a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 18:57:39 +0000 Subject: Added fragment identifier to the "in context" URL which points to the notice location in the Conversation page. --- lib/noticelist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/noticelist.php b/lib/noticelist.php index 6f05c63d6..44726a17b 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -432,7 +432,7 @@ class NoticeListItem extends Widget $this->out->elementStart('dl', 'response'); $this->out->element('dt', null, _('To')); $this->out->elementStart('dd'); - $this->out->element('a', array('href' => $convurl), + $this->out->element('a', array('href' => $convurl.'#notice-'.$this->notice->id), _('in context')); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); -- cgit v1.2.3-54-g00ecf From 27076227620d0beca7586affa8e89154a1648d70 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 25 Jun 2009 12:52:10 -0700 Subject: Return clippy to his rightful place next to attachments --- lib/util.php | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/util.php b/lib/util.php index 30b767c3e..f6d50b180 100644 --- a/lib/util.php +++ b/lib/util.php @@ -497,6 +497,22 @@ function common_linkify($url) { $attrs = array('href' => $longurl, 'rel' => 'external'); + $is_attachment = false; + $attachment_id = null; + $has_thumb = false; + + // Check to see whether there's a filename associated with this URL. + // If there is, it's an upload and qualifies as an attachment + + $localfile = File::staticGet('url', $longurl); + + if (!empty($localfile)) { + if (isset($localfile->filename)) { + $is_attachment = true; + $attachment_id = $localfile->id; + } + } + // if this URL is an attachment, then we set class='attachment' and id='attahcment-ID' // where ID is the id of the attachment for the given URL. // @@ -504,24 +520,35 @@ function common_linkify($url) { // we're currently picking up oembeds only. // I think the best option is another file_view table in the db // and associated dbobject. + $query = "select file_oembed.file_id as file_id from file join file_oembed on file.id = file_oembed.file_id where file.url='$longurl'"; $file = new File; $file->query($query); $file->fetch(); if (!empty($file->file_id)) { + $is_attachment = true; + $attachment_id = $file->file_id; + $query = "select file_thumbnail.file_id as file_id from file join file_thumbnail on file.id = file_thumbnail.file_id where file.url='$longurl'"; $file2 = new File; $file2->query($query); $file2->fetch(); - if (empty($file2->file_id)) { - $attrs['class'] = 'attachment'; - } else { + if (!empty($file2)) { + $has_thumb = true; + } + } + + // Add clippy + if ($is_attachment) { + $attrs['class'] = 'attachment'; + if ($has_thumb) { $attrs['class'] = 'attachment thumbnail'; } - $attrs['id'] = "attachment-{$file->file_id}"; + $attrs['id'] = "attachment-{$attachment_id}"; } + return XMLStringer::estring('a', $attrs, $display); } -- cgit v1.2.3-54-g00ecf From a7cdf32df541bf73a47f1255b3e9f0a22c4724b4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 13:23:59 -0700 Subject: max public page --- actions/public.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/actions/public.php b/actions/public.php index 27153f131..9851285c4 100644 --- a/actions/public.php +++ b/actions/public.php @@ -35,6 +35,10 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php'; require_once INSTALLDIR.'/lib/noticelist.php'; require_once INSTALLDIR.'/lib/feedlist.php'; +// Farther than any human will go + +define('MAX_PUBLIC_PAGE', 100); + /** * Action for displaying the public stream * @@ -74,6 +78,10 @@ class PublicAction extends Action parent::prepare($args); $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; + if ($this->page > MAX_PUBLIC_PAGE) { + $this->clientError(sprintf(_("Beyond the page limit (%s)"), MAX_PUBLIC_PAGE)); + } + common_set_returnto($this->selfUrl()); return true; -- cgit v1.2.3-54-g00ecf From d1d5347ba3a567205fef36633b52f19a24485a42 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 20:36:02 +0000 Subject: Using transparent background colour instead of solid for notice on hover --- theme/default/css/display.css | 2 +- theme/identica/css/display.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index f592e930f..89197bddb 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -245,7 +245,7 @@ div.notice-options input { font-family:sans-serif; } #content .notices li:hover { -background-color:#FCFCFC; +background-color:rgba(240, 240, 240, 0.2); } #conversation .notices li:hover { background-color:transparent; diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 09ad4c972..025debf34 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -245,7 +245,7 @@ div.notice-options input { font-family:sans-serif; } #content .notices li:hover { -background-color:#FCFCFC; +background-color:rgba(240, 240, 240, 0.2); } #conversation .notices li:hover { background-color:transparent; -- cgit v1.2.3-54-g00ecf From 03d31911e18f8ca0ba2f8425943b4c244114a066 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 25 Jun 2009 13:51:29 -0700 Subject: FileAction redirections weren't being added (e.g.: /notice/$notice_id/file) --- actions/newnotice.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 3677f54c2..15caff6ea 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -326,6 +326,8 @@ class NewnoticeAction extends Action } $this->maybeAddRedir($file_id, $short); + + return $file; } function maybeAddRedir($file_id, $url) @@ -350,7 +352,8 @@ class NewnoticeAction extends Action { File_to_post::processNew($filerec->id, $notice->id); - $this->maybeAddRedir($filerec->id, common_local_url('file', array('notice' => $this->notice->id))); + $this->maybeAddRedir($filerec->id, + common_local_url('file', array('notice' => $notice->id))); } /** -- cgit v1.2.3-54-g00ecf From 6a0571d51b0cafb0dbc7caf3aa61cdfd17d6c7ce Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 21:01:07 +0000 Subject: Added functionality to remove the notice data attachment --- js/util.js | 14 ++++++++++---- theme/base/css/display.css | 11 +++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/js/util.js b/js/util.js index 9156045bb..e7c54b74a 100644 --- a/js/util.js +++ b/js/util.js @@ -222,6 +222,7 @@ $(document).ready(function(){ } $("#notice_data-text").val(""); $("#notice_data-attach").val(""); + $('#notice_data-attach_selected').remove(); counter(); } $("#form_notice").removeClass("processing"); @@ -233,7 +234,7 @@ $(document).ready(function(){ $("#form_notice").each(addAjaxHidden); NoticeReply(); NoticeAttachments(); - NoticeDataAttachSelected(); + NoticeDataAttach(); }); function NoticeReply() { @@ -312,10 +313,15 @@ function NoticeAttachments() { ); } -function NoticeDataAttachSelected() { - $('#notice_data-attach').change(function() { - S = '
      '+$(this).val()+'
      '; +function NoticeDataAttach() { + NDA = $('#notice_data-attach'); + NDA.change(function() { + S = '
      '+$(this).val()+'
      '; NDAS = $('#notice_data-attach_selected'); (NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S); + $('#notice_data-attach_selected button').click(function(){ + $('#notice_data-attach_selected').remove(); + NDA.val(''); + }); }); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index c8f23e4f5..78fcd7ece 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -517,8 +517,19 @@ clear:both; width:81.5%; margin-bottom:0; line-height:1.618; +} +#form_notice #notice_data-attach_selected code { +float:left; +width:90%; +display:block; +font-size:1.1em; +line-height:1.8; overflow:auto; } +#form_notice #notice_data-attach_selected button { +float:right; +font-size:0.8em; +} /* entity_profile */ .entity_profile { -- cgit v1.2.3-54-g00ecf From c4da201fc01206817034207c01d9e2d051605757 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 25 Jun 2009 21:25:41 +0000 Subject: IE UI update for notice_data_attach_selected --- theme/base/css/ie.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index da200388e..43fb01492 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -19,6 +19,12 @@ display:block; width:17%; max-width:17%; } +#form_notice #notice_data-attach_selected { +width:78.5%; +} +#form_notice #notice_data-attach_selected button { +padding:0 4px; +} #anon_notice { max-width:39%; } -- cgit v1.2.3-54-g00ecf From 74d9b0f820c588f2959457e83aaf5b9d4f2ea399 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 26 Jun 2009 05:38:43 +0000 Subject: Removed unnecessary assignment to variable for background image on --- js/userdesign.go.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/userdesign.go.js b/js/userdesign.go.js index b54b492cc..833b19adc 100644 --- a/js/userdesign.go.js +++ b/js/userdesign.go.js @@ -89,11 +89,10 @@ $(document).ready(function() { $('body').css({'background-image':'none'}); }); $('#design_background-image_on').focus(function() { - var bis = $('#design_background-image_onoff img')[0].src; - $('body').css({'background-image':'url('+bis+')'}); + $('body').css({'background-image':'url('+$('#design_background-image_onoff img')[0].src+')'}); }); $('#design_background-image_repeat').click(function() { ($(this)[0].checked) ? $('body').css({'background-repeat':'repeat'}) : $('body').css({'background-repeat':'no-repeat'}); }); -}); \ No newline at end of file +}); -- cgit v1.2.3-54-g00ecf From 994768b82101fdd2a08a92e30967ded6714b87dc Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Jun 2009 23:00:46 -0700 Subject: break up big inbox queries into lots of small ones --- classes/Group_inbox.php | 6 +++ classes/Notice.php | 112 ++++++++++++++++++++++++++++++++--------------- classes/Notice_inbox.php | 1 + classes/Profile.php | 48 ++++++++++++++++++++ classes/User.php | 46 +++---------------- classes/User_group.php | 24 ++++++++++ 6 files changed, 161 insertions(+), 76 deletions(-) diff --git a/classes/Group_inbox.php b/classes/Group_inbox.php index b80ba4272..1af7439f7 100644 --- a/classes/Group_inbox.php +++ b/classes/Group_inbox.php @@ -14,8 +14,14 @@ class Group_inbox extends Memcached_DataObject public $created; // datetime() not_null /* Static get */ + function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Group_inbox',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function &pkeyGet($kv) + { + return Memcached_DataObject::pkeyGet('Group_inbox', $kv); + } } diff --git a/classes/Notice.php b/classes/Notice.php index 5bcfa896e..fdcef1bc2 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -832,24 +832,60 @@ class Notice extends Memcached_DataObject $enabled = common_config('inboxes', 'enabled'); if ($enabled === true || $enabled === 'transitional') { - $inbox = new Notice_inbox(); - $UT = common_config('db','type')=='pgsql'?'"user"':'user'; - $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' . - "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " . - "FROM $UT JOIN subscription ON $UT.id = subscription.subscriber " . - 'WHERE subscription.subscribed = ' . $this->profile_id . ' ' . - 'AND NOT EXISTS (SELECT user_id, notice_id ' . - 'FROM notice_inbox ' . - "WHERE user_id = $UT.id " . - 'AND notice_id = ' . $this->id . ' )'; - if ($enabled === 'transitional') { - $qry .= " AND $UT.inboxed = 1"; + + $users = $this->getSubscribedUsers(); + + // FIXME: kind of ignoring 'transitional'... + // we'll probably stop supporting inboxless mode + // in 0.9.x + + foreach ($users as $id) { + $this->addToUserInbox($id, NOTICE_INBOX_SOURCE_SUB); } - $inbox->query($qry); } + return; } + function getSubscribedUsers() + { + $user = new User(); + + $qry = + 'SELECT id ' . + 'FROM user JOIN subscription '. + 'ON user.id = subscription.subscriber ' . + 'WHERE subscription.subscribed = %d '; + + $user->query(sprintf($qry, $this->profile_id)); + + $ids = array(); + + while ($user->fetch()) { + $ids[] = $user->id; + } + + $user->free(); + + return $ids; + } + + function addToUserInbox($user_id, $source) + { + $inbox = Notice_inbox::pkeyGet(array('user_id' => $user_id, + 'notice_id' => $this->id)); + if (empty($inbox)) { + $inbox = new Notice_inbox(); + $inbox->user_id = $user_id; + $inbox->notice_id = $this->id; + $inbox->source = $source; + $inbox->created = $this->created; + return $inbox->insert(); + } + + return true; + } + function saveGroups() { $enabled = common_config('inboxes', 'enabled'); @@ -888,13 +924,7 @@ class Notice extends Memcached_DataObject if ($profile->isMember($group)) { - $gi = new Group_inbox(); - - $gi->group_id = $group->id; - $gi->notice_id = $this->id; - $gi->created = common_sql_now(); - - $result = $gi->insert(); + $result = $this->addToGroupInbox($group); if (!$result) { common_log_db_error($gi, 'INSERT', __FILE__); @@ -902,27 +932,37 @@ class Notice extends Memcached_DataObject // FIXME: do this in an offline daemon - $this->addToGroupInboxes($group); + $this->addToGroupMemberInboxes($group); } } } - function addToGroupInboxes($group) + function addToGroupInbox($group) + { + $gi = Group_inbox::pkeyGet(array('group_id' => $group->id, + 'notice_id' => $this->id)); + + if (empty($gi)) { + + $gi = new Group_inbox(); + + $gi->group_id = $group->id; + $gi->notice_id = $this->id; + $gi->created = $this->created; + + return $gi->insert(); + } + + return true; + } + + function addToGroupMemberInboxes($group) { - $inbox = new Notice_inbox(); - $UT = common_config('db','type')=='pgsql'?'"user"':'user'; - $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' . - "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', " . NOTICE_INBOX_SOURCE_GROUP . " " . - "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " . - 'WHERE group_member.group_id = ' . $group->id . ' ' . - 'AND NOT EXISTS (SELECT user_id, notice_id ' . - 'FROM notice_inbox ' . - "WHERE user_id = $UT.id " . - 'AND notice_id = ' . $this->id . ' )'; - if ($enabled === 'transitional') { - $qry .= " AND $UT.inboxed = 1"; - } - $result = $inbox->query($qry); + $users = $group->getUserMembers(); + + foreach ($users as $id) { + $this->addToUserInbox($id, NOTICE_INBOX_SOURCE_GROUP); + } } function saveReplies() diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 4ca2e9ae3..940381f84 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -27,6 +27,7 @@ define('INBOX_CACHE_WINDOW', 101); define('NOTICE_INBOX_SOURCE_SUB', 1); define('NOTICE_INBOX_SOURCE_GROUP', 2); +define('NOTICE_INBOX_SOURCE_REPLY', 3); define('NOTICE_INBOX_SOURCE_GATEWAY', -1); class Notice_inbox extends Memcached_DataObject diff --git a/classes/Profile.php b/classes/Profile.php index 6b27c80cb..a0ed6b3ca 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -289,4 +289,52 @@ class Profile extends Memcached_DataObject return Avatar::defaultImage($size); } } + + function getSubscriptions($offset=0, $limit=null) + { + $qry = + 'SELECT profile.* ' . + 'FROM profile JOIN subscription ' . + 'ON profile.id = subscription.subscribed ' . + 'WHERE subscription.subscriber = %d ' . + 'AND subscription.subscribed != subscription.subscriber ' . + 'ORDER BY subscription.created DESC '; + + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + + $profile = new Profile(); + + $profile->query(sprintf($qry, $this->id)); + + return $profile; + } + + function getSubscribers($offset=0, $limit=null) + { + $qry = + 'SELECT profile.* ' . + 'FROM profile JOIN subscription ' . + 'ON profile.id = subscription.subscriber ' . + 'WHERE subscription.subscribed = %d ' . + 'AND subscription.subscribed != subscription.subscriber ' . + 'ORDER BY subscription.created DESC '; + + if ($offset) { + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + } + + $profile = new Profile(); + + $cnt = $profile->query(sprintf($qry, $this->id)); + + return $profile; + } } diff --git a/classes/User.php b/classes/User.php index a01a3106f..62a3f8a66 100644 --- a/classes/User.php +++ b/classes/User.php @@ -600,50 +600,16 @@ class User extends Memcached_DataObject function getSubscriptions($offset=0, $limit=null) { - $qry = - 'SELECT profile.* ' . - 'FROM profile JOIN subscription ' . - 'ON profile.id = subscription.subscribed ' . - 'WHERE subscription.subscriber = %d ' . - 'AND subscription.subscribed != subscription.subscriber ' . - 'ORDER BY subscription.created DESC '; - - if (common_config('db','type') == 'pgsql') { - $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; - } else { - $qry .= ' LIMIT ' . $offset . ', ' . $limit; - } - - $profile = new Profile(); - - $profile->query(sprintf($qry, $this->id)); - - return $profile; + $profile = $this->getProfile(); + assert(!empty($profile)); + return $profile->getSubscriptions($offset, $limit); } function getSubscribers($offset=0, $limit=null) { - $qry = - 'SELECT profile.* ' . - 'FROM profile JOIN subscription ' . - 'ON profile.id = subscription.subscriber ' . - 'WHERE subscription.subscribed = %d ' . - 'AND subscription.subscribed != subscription.subscriber ' . - 'ORDER BY subscription.created DESC '; - - if ($offset) { - if (common_config('db','type') == 'pgsql') { - $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; - } else { - $qry .= ' LIMIT ' . $offset . ', ' . $limit; - } - } - - $profile = new Profile(); - - $cnt = $profile->query(sprintf($qry, $this->id)); - - return $profile; + $profile = $this->getProfile(); + assert(!empty($profile)); + return $profile->getSubscribers($offset, $limit); } function getTaggedSubscribers($tag, $offset=0, $limit=null) diff --git a/classes/User_group.php b/classes/User_group.php index 8a56b9e52..9b4b01ead 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -246,4 +246,28 @@ class User_group extends Memcached_DataObject return Design::staticGet('id', $this->design_id); } + function getUserMembers() + { + // XXX: cache this + + $user = new User(); + + $qry = + 'SELECT id ' . + 'FROM user JOIN group_member '. + 'ON user.id = group_member.profile_id ' . + 'WHERE group_member.group_id = %d '; + + $user->query(sprintf($qry, $this->id)); + + $ids = array(); + + while ($user->fetch()) { + $ids[] = $user->id; + } + + $user->free(); + + return $ids; + } } -- cgit v1.2.3-54-g00ecf