summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README141
-rw-r--r--actions/getfile.php145
-rw-r--r--classes/User.php14
-rw-r--r--db/notice_source.sql2
-rw-r--r--extlib/README58
-rw-r--r--htaccess.sample8
-rw-r--r--lib/common.php4
-rw-r--r--lib/router.php4
-rw-r--r--scripts/makegroupadmin.php89
-rw-r--r--scripts/registeruser.php81
10 files changed, 321 insertions, 225 deletions
diff --git a/README b/README
index 5cd310270..a10628ac7 100644
--- a/README
+++ b/README
@@ -2,8 +2,8 @@
README
------
-StatusNet 0.8.1 ("Second Guessing")
-26 Aug 2009
+StatusNet 0.8.2 ("Life and How to Live It")
+1 Nov 2009
This is the README file for StatusNet (formerly Laconica), the Open
Source microblogging platform. It includes installation instructions,
@@ -77,49 +77,81 @@ for additional terms.
New this version
================
-This is a minor feature and bugfix release since version 0.8.0,
-released Jul 15 2009. Notable changes this version:
-
-- Laconica has been renamed StatusNet. With a few minor compatibility
- exceptions, all references to "Laconica" in code, documentation
- and comments were changed to "StatusNet".
-- A new plugin to support "infinite scroll".
-- A new plugin to support reCaptcha <http://recaptcha.net>.
-- Better logging of server errors.
-- Add an Openid-only mode for authentication.
-- 'lite' parameter for some Twitter API methods.
-- A new plugin to auto-complete nicknames for @-replies.
-- Configuration options to disable OpenID, SMS, Twitter, post-by-email, and IM.
-- Support for lighttpd <http://lighttpd.org/> using 404-based
- rewrites.
-- Support for using Twitter's OAuth authentication as a client.
-- First version of the groups API.
-- Can configure a site-wide design, including background image and
- colors.
-- Improved algorithm for replies and conversations, making
- conversation trees more accurate and useful.
-- Add a script to create a simulation database for testing/debugging.
-- Sanitize HTML for OEmbed.
-- Improved queue management for DB-based queuing.
-- More complete URL detection.
-- Hashtags now support full Unicode character set.
-- Notice inboxes are now garbage-collected on a regular basis
- at notice-write time.
-- PiwikAnalyticsPlugin updated for latest Piwik interface.
-- Attachment and notice pages can be embedded with OEmbed
- <http://www.oembed.com>.
-- Failed authentication is logged.
-- PostgreSQL schema and support brought up-to-date with 0.8.x features.
-- The installer works with PostgreSQL as well as MySQL.
-- RSS 1.0 feeds use HTTP Basic authentication in private mode.
-- Many, many bug fixes, particularly with performance.
-- Better (=working) garbage collection for old sessions.
-- Better (=working) search queries.
-- Some cleanup of HTML output.
-- Better error handling when updating Facebook.
-- Considerably better performance when using replication for API
- calls.
-- Initial unit tests.
+This is a minor feature and bugfix release since version 0.8.1,
+released Aug 26 2009. Notable changes this version:
+
+- New script for deleting user accounts. Not particularly safe or
+ community-friendly. Better for deleting abusive accounts than for
+ users who are 'retiring'.
+- Improved detection of URLs in notices, specifically for punctuation
+ chars like ~, :, $, _, -, +, !, @, and %.
+- Removed some extra <dl> semantic HTML code.
+- Correct error in status-network database ini file (having multiple
+ statusnet sites with a single codebase)
+- Fixed error output for Twitter posting failures.
+- Fixed bug in Twitter queue handler that requeued inapplicable
+ notices ad infinitum.
+- Improve FOAF output for remote users.
+- new commands to join and leave groups.
+- Fixed bug in which you cannot turn off importing friends timelines
+ flag.
+- Better error handling in Twitter posting.
+- Show oEmbed data for XHTML files as well as plain HTML.
+- Updated bug database link in README.
+- require HTML tidy extension.
+- add support for HTTP Basic Auth in PHP CGI or FastCGI (e.g. GoDaddy).
+- autofocus input to selected entry elements depending on page.
+- updated layout for filter-by-tag form.
+- better layout for inbox and outbox pages.
+- fix highlighting search terms in attributes of notice list elements.
+- Correctly handle errors in linkback plugin.
+- Updated biz theme.
+- Updated cloudy theme.
+- Don't match '::' as an IPv6 address.
+- Use the same decision logic for deciding whether to mark an
+ attachment as an enclosure in RSS or as a paperclip item in Web
+ output.
+- Fixed a bug in the Piwik plugin that hard-coded the site ID.
+- Add a param, inreplyto, to notice/new to allow an explicit response
+ to another notice.
+- Show username in subject of emails.
+- Check if avatar exists before trying to delete it.
+- Correctly add omb_version to response for request token in OMB.
+- Add a few more SMS carriers.
+- Add a few more notice sources.
+- Vary: header.
+- Improvements to the AutoCompletePlugin.
+- Check for 'dl' before using it.
+- Make it impossible to delete self-subscriptions via the API.
+- Fix pagination of tagged user pages.
+- Make PiwikAnalyticsPlugin work with addPlugin().
+- Removed trailing single space in user nicknames in notice lists.
+- Show context link if a notice starts a conversation.
+- blacklist all files and directories in install dir.
+- handle GoDaddy-style PATH_INFO, including script name.
+- add home_timeline synonym for friends_timeline.
+- Add a popup window for the realtime plugin.
+- Add some more streams for the realtime plugin.
+- Fix a bug that overwrote group creation timestamp on every edit.
+- Moved HTTP error code strings to a class variable.
+- The Twitter API now returns server errors in the correct format.
+- Reset the doctype for HTML output.
+- Fixed a number of notices.
+- Don't show search suggestions for private sites.
+- Some corrections to FBConnect nav overrides.
+- Slightly less database-intensive session management.
+- Updated name of software in installer script.
+- Include long-form attachment URLs if url-shortener is disabled.
+- Include updated localisations for Polish, Greek, Hebrew, Icelandic,
+ Norwegian, and Chinese.
+- Include upstream fixes to gettext.php.
+- Correct for regression in Facebook API for updates.
+- Ignore "Sent from my iPhone" (and similar) in mail updates.
+- Use the NICKNAME_FMT constant for detecting nicknames.
+- Check for site servername config'd.
+- Compatibility fix for empty status updates with Twitter API.
+- a script to register a new user.
+- a script to make a user admin of a group.
Prerequisites
=============
@@ -225,9 +257,9 @@ especially if you've previously installed PHP/MySQL packages.
1. Unpack the tarball you downloaded on your Web server. Usually a
command like this will work:
- tar zxf statusnet-0.8.1.tar.gz
+ tar zxf statusnet-0.8.2.tar.gz
- ...which will make a statusnet-0.8.1 subdirectory in your current
+ ...which will make a statusnet-0.8.2 subdirectory in your current
directory. (If you don't have shell access on your Web server, you
may have to unpack the tarball on your local computer and FTP the
files to the server.)
@@ -235,7 +267,7 @@ especially if you've previously installed PHP/MySQL packages.
2. Move the tarball to a directory of your choosing in your Web root
directory. Usually something like this will work:
- mv statusnet-0.8.1 /var/www/mublog
+ mv statusnet-0.8.2 /var/www/mublog
This will make your StatusNet instance available in the mublog path of
your server, like "http://example.net/mublog". "microblog" or
@@ -755,12 +787,6 @@ private site, but users of the private site may be able to subscribe
to users on a remote site. (Or not... it's not well tested.) The
"proper behaviour" hasn't been defined here, so handle with care.
-If fancy URLs is enabled, access to file attachments can also be
-restricted to logged-in users only. Uncomment the appropriate rewrite
-rule in .htaccess or your server's httpd.conf. (This most likely will
-not work if you are using a virtual server for attachments, so consider
-the performance/security tradeoff.)
-
Upgrading
=========
@@ -774,7 +800,7 @@ with this situation.
If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've
been tracking the "git" version of the software, you will probably
want to upgrade and keep your existing data. There is no automated
-upgrade procedure in StatusNet 0.8.1. Try these step-by-step
+upgrade procedure in StatusNet 0.8.2. Try these step-by-step
instructions; read to the end first before trying them.
0. Download StatusNet and set up all the prerequisites as if you were
@@ -795,7 +821,7 @@ instructions; read to the end first before trying them.
5. Once all writing processes to your site are turned off, make a
final backup of the Web directory and database.
6. Move your StatusNet directory to a backup spot, like "mublog.bak".
-7. Unpack your StatusNet 0.8.1 tarball and move it to "mublog" or
+7. Unpack your StatusNet 0.8.2 tarball and move it to "mublog" or
wherever your code used to be.
8. Copy the config.php file and avatar directory from your old
directory to your new directory.
@@ -1568,7 +1594,7 @@ repository (see below), and you get a compilation error ("unexpected
T_STRING") in the browser, check to see that you don't have any
conflicts in your code.
-If you upgraded to StatusNet 0.8.1 without reading the "Notice
+If you upgraded to StatusNet 0.8.2 without reading the "Notice
inboxes" section above, and all your users' 'Personal' tabs are empty,
read the "Notice inboxes" section above.
@@ -1676,6 +1702,7 @@ if anyone's been overlooked in error.
* Jeffery To
* Federico Marani
* Craig Andrews
+* mEDI
Thanks also to the developers of our upstream library code and to the
thousands of people who have tried out Identi.ca, installed StatusNet,
diff --git a/actions/getfile.php b/actions/getfile.php
deleted file mode 100644
index ecda34c0f..000000000
--- a/actions/getfile.php
+++ /dev/null
@@ -1,145 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Returns a given file attachment, allowing private sites to only allow
- * access to file attachments after login.
- *
- * PHP version 5
- *
- * LICENCE: 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 <http://www.gnu.org/licenses/>.
- *
- * @category Personal
- * @package StatusNet
- * @author Jeffery To <jeffery.to@gmail.com>
- * @copyright 2008-2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once 'MIME/Type.php';
-
-/**
- * Action for getting a file attachment
- *
- * @category Personal
- * @package StatusNet
- * @author Jeffery To <jeffery.to@gmail.com>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-class GetfileAction extends Action
-{
- /**
- * Path of file to return
- */
-
- var $path = null;
-
- /**
- * Get file name
- *
- * @param array $args $_REQUEST array
- *
- * @return success flag
- */
-
- function prepare($args)
- {
- parent::prepare($args);
-
- $filename = $this->trimmed('filename');
- $path = null;
-
- if ($filename) {
- $path = common_config('attachments', 'dir') . $filename;
- }
-
- if (empty($path) or !file_exists($path)) {
- $this->clientError(_('No such file.'), 404);
- return false;
- }
- if (!is_readable($path)) {
- $this->clientError(_('Cannot read file.'), 403);
- return false;
- }
-
- $this->path = $path;
- return true;
- }
-
- /**
- * Is this page read-only?
- *
- * @return boolean true
- */
-
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * Last-modified date for file
- *
- * @return int last-modified date as unix timestamp
- */
-
- function lastModified()
- {
- return filemtime($this->path);
- }
-
- /**
- * etag for file
- *
- * This returns the same data (inode, size, mtime) as Apache would,
- * but in decimal instead of hex.
- *
- * @return string etag http header
- */
- function etag()
- {
- $stat = stat($this->path);
- return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
- }
-
- /**
- * Handle input, produce output
- *
- * @param array $args $_REQUEST contents
- *
- * @return void
- */
-
- function handle($args)
- {
- // undo headers set by PHP sessions
- $sec = session_cache_expire() * 60;
- header('Expires: ' . date(DATE_RFC1123, time() + $sec));
- header('Cache-Control: public, max-age=' . $sec);
- header('Pragma: public');
-
- parent::handle($args);
-
- $path = $this->path;
- header('Content-Type: ' . MIME_Type::autoDetect($path));
- readfile($path);
- }
-}
diff --git a/classes/User.php b/classes/User.php
index 007662131..7ab9f307a 100644
--- a/classes/User.php
+++ b/classes/User.php
@@ -120,15 +120,11 @@ class User extends Memcached_DataObject
function allowed_nickname($nickname)
{
// XXX: should already be validated for size, content, etc.
-
- $blacklist = array();
-
- //all directory and file names should be blacklisted
- $d = dir(INSTALLDIR);
- while (false !== ($entry = $d->read())) {
- $blacklist[]=$entry;
- }
- $d->close();
+ static $blacklist = array('rss', 'xrds', 'doc', 'main',
+ 'settings', 'notice', 'user',
+ 'search', 'avatar', 'tag', 'tags',
+ 'api', 'message', 'group', 'groups',
+ 'local');
$merged = array_merge($blacklist, common_config('nickname', 'blacklist'));
return !in_array($nickname, $merged);
}
diff --git a/db/notice_source.sql b/db/notice_source.sql
index 2657763f4..5c5c939dd 100644
--- a/db/notice_source.sql
+++ b/db/notice_source.sql
@@ -7,6 +7,7 @@ VALUES
('anyio', 'Any.IO', 'http://any.io/', now()),
('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()),
('bti','bti','http://gregkh.github.com/bti/', now()),
+ ('choqok', 'Choqok', 'http://choqok.gnufolks.org/', now()),
('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
@@ -43,6 +44,7 @@ VALUES
('rygh.no','rygh.no','http://rygh.no/', now()),
('ryghsms','ryghsms','http://sms.rygh.no/', now()),
('smob','SMOB','http://smob.sioc-project.org/', now()),
+ ('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()),
('spaz','Spaz','http://funkatron.com/spaz', now()),
('tarpipe','tarpipe','http://tarpipe.com/', now()),
('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()),
diff --git a/extlib/README b/extlib/README
new file mode 100644
index 000000000..cfc2f9c8c
--- /dev/null
+++ b/extlib/README
@@ -0,0 +1,58 @@
+DO NOT "FIX" CODE IN THIS DIRECTORY.
+
+ONLY UPSTREAM VERSIONS OF SOFTWARE GO IN THIS DIRECTORY.
+
+This directory is provided as a courtesy to our users who might be
+unable or unwilling to find and install libraries we depend on.
+
+If we "fix" software in this directory, we hamstring users who do the
+right thing and keep a single version of upstream libraries in a
+system-wide library. We introduce subtle and maddening bugs where
+our code is "accidentally" using the "wrong" library version. We may
+unwittingly interfere with other software that depends on the
+canonical release versions of those same libraries!
+
+Forking upstream software for trivial reasons makes us bad citizens in
+the Open Source community and adds unnecessary heartache for our
+users. Don't make us "that" project.
+
+FAQ:
+
+Q: What should we do when we find a bug in upstream software?
+
+A: First and foremost, REPORT THE BUG, and if possible send in a patch.
+
+ Watch for a release of the upstream software and integrate with it
+ when it's released.
+
+ In the meantime, work around the bug, if at all possible. Usually,
+ it's quite possible, if slightly harder or less efficient.
+
+Q: What if the bug can't be worked around?
+
+A: If the upstream developers have accepted a bug patch, it's
+ undesirable but acceptable to apply that patch to the library in
+ the extlib dir. Ideally, use a release version for upstream or a
+ version control system snapshot.
+
+ Note that this is a last resort.
+
+Q: What if upstream is unresponsive or won't accept a patch?
+
+A: Try again.
+
+Q: I tried again, and upstream is still unresponsive and nobody's
+ checked on my patch. Now what?
+
+A: If the upstream project is moribund and there's a way to adopt it,
+ propose having the StatusNet dev team adopt the project. Or, adopt
+ it yourself.
+
+Q: What if there's no upstream authority and it can't be adopted?
+
+A: Then we fork it. Make a new name and a new version. Include it in
+ lib/ instead of extlib/, and use the StatusNet_* prefix to change
+ the namespace to avoid collisions.
+
+ This is a last resort; consult with the rest of the dev group
+ before taking this radical step.
diff --git a/htaccess.sample b/htaccess.sample
index 373108c81..37eb8e01e 100644
--- a/htaccess.sample
+++ b/htaccess.sample
@@ -5,14 +5,6 @@
RewriteBase /mublog/
- # If your site is private and want access to file attachments
- # restricted to logged-in users only, uncomment this rule.
- #
- # If you have a custom attachment path
- # ($config['attachments']['path']), change "file/" to match.
- #
- #RewriteRule ^file/(.*) getfile/$1
-
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?p=$1 [L,QSA]
diff --git a/lib/common.php b/lib/common.php
index 0b4e03184..016b04481 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -19,10 +19,10 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-define('STATUSNET_VERSION', '0.8.2dev');
+define('STATUSNET_VERSION', '0.8.2rc2');
define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility
-define('STATUSNET_CODENAME', 'Second Guessing');
+define('STATUSNET_CODENAME', 'Life and How to Live It');
define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48);
diff --git a/lib/router.php b/lib/router.php
index 7455d9cf8..5529e60ac 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -171,10 +171,6 @@ class Router
array('action' => 'attachment_thumbnail'),
array('attachment' => '[0-9]+'));
- $m->connect('getfile/:filename',
- array('action' => 'getfile'),
- array('filename' => '[A-Za-z0-9._-]+'));
-
$m->connect('notice/new', array('action' => 'newnotice'));
$m->connect('notice/new?replyto=:replyto',
array('action' => 'newnotice'),
diff --git a/scripts/makegroupadmin.php b/scripts/makegroupadmin.php
new file mode 100644
index 000000000..a68798451
--- /dev/null
+++ b/scripts/makegroupadmin.php
@@ -0,0 +1,89 @@
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, 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 <http://www.gnu.org/licenses/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'g:n:';
+$longoptions = array('nickname=', 'group=');
+
+$helptext = <<<END_OF_MAKEGROUPADMIN_HELP
+makegroupadmin.php [options]
+makes a user the admin of a group
+
+ -g --group group to add an admin to
+ -n --nickname nickname of the new admin
+
+END_OF_MAKEGROUPADMIN_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+$nickname = get_option_value('n', 'nickname');
+$groupname = get_option_value('g', 'group');
+
+if (empty($nickname) || empty($groupname)) {
+ print "Must provide a nickname and group.\n";
+ exit(1);
+}
+
+try {
+
+ $user = User::staticGet('nickname', $nickname);
+
+ if (empty($user)) {
+ throw new Exception("No user named '$nickname'.");
+ }
+
+ $group = User_group::staticGet('nickname', $groupname);
+
+ if (empty($group)) {
+ throw new Exception("No group named '$groupname'.");
+ }
+
+ $member = Group_member::pkeyGet(array('group_id' => $group->id,
+ 'profile_id' => $user->id));
+
+ if (empty($member)) {
+ $member = new Group_member();
+
+ $member->group_id = $group->id;
+ $member->profile_id = $user->id;
+ $member->created = common_sql_now();
+
+ if (!$member->insert()) {
+ throw new Exception("Can't add '$nickname' to '$groupname'.");
+ }
+ }
+
+ if ($member->is_admin) {
+ throw new Exception("'$nickname' is already an admin of '$groupname'.");
+ }
+
+ $orig = clone($member);
+
+ $member->is_admin = 1;
+
+ if (!$member->update($orig)) {
+ throw new Exception("Can't make '$nickname' admin of '$groupname'.");
+ }
+
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+ exit(1);
+}
diff --git a/scripts/registeruser.php b/scripts/registeruser.php
new file mode 100644
index 000000000..5d9c8862d
--- /dev/null
+++ b/scripts/registeruser.php
@@ -0,0 +1,81 @@
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, 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 <http://www.gnu.org/licenses/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'n:w:f:e:';
+$longoptions = array('nickname=', 'password=', 'fullname=', 'email=');
+
+$helptext = <<<END_OF_REGISTERUSER_HELP
+registeruser.php [options]
+registers a user in the database
+
+ -n --nickname nickname of the new user
+ -w --password password of the new user
+ -f --fullname full name of the new user (optional)
+ -e --email email address of the new user (optional)
+
+END_OF_REGISTERUSER_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+$nickname = get_option_value('n', 'nickname');
+$password = get_option_value('w', 'password');
+$fullname = get_option_value('f', 'fullname');
+
+$email = get_option_value('e', 'email');
+
+if (empty($nickname) || empty($password)) {
+ print "Must provide a username and password.\n";
+ exit(1);
+}
+
+try {
+
+ $user = User::staticGet('nickname', $nickname);
+
+ if (!empty($user)) {
+ throw new Exception("A user named '$nickname' already exists.");
+ }
+
+ $user = User::register(array('nickname' => $nickname,
+ 'password' => $password,
+ 'fullname' => $fullname));
+
+ if (empty($user)) {
+ throw new Exception("Can't register user '$nickname' with password '$password' and fullname '$fullname'.");
+ }
+
+ if (!empty($email)) {
+
+ $orig = clone($user);
+
+ $user->email = $email;
+
+ if (!$user->updateKeys($orig)) {
+ print "Failed!\n";
+ throw new Exception("Can't update email address.");
+ }
+ }
+
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+ exit(1);
+}