Upgrading
=========
-IMPORTANT NOTE: StatusNet 0.7.4 introduced a fix for some
-incorrectly-stored international characters ("UTF-8"). For new
-installations, it will now store non-ASCII characters correctly.
-However, older installations will have the incorrect storage, and will
-consequently show up "wrong" in browsers. See below for how to deal
-with this situation.
-
-If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've
+If you've been using StatusNet 0.9.9 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.9.9. Try these step-by-step
+want to upgrade and keep your existing data. 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
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 "statusnet.bak".
-7. Unpack your StatusNet 0.9.9 tarball and move it to "statusnet" or
+7. Unpack your StatusNet 1.0.0 tarball and move it to "statusnet" or
wherever your code used to be.
8. Copy the config.php file and the contents of the avatar/, background/,
file/, and local/ subdirectories from your old directory to your new
directory.
9. Copy htaccess.sample to .htaccess in the new directory. Change the
RewriteBase to use the correct path.
-10. Rebuild the database.
+10. Upgrade the database.
NOTE: this step is destructive and cannot be
reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't
do it without a known-good backup!
- If your database is at version 0.8.0 or higher in the 0.8.x line, you can run a
- special upgrade script:
-
- mysql -u<rootuser> -p<rootpassword> <database> db/08to09.sql
-
- If you are upgrading from any 0.9.x version like 0.9.6, run this script:
+ In your new StatusNet 1.0.0 directory and AFTER YOU MAKE A
+ BACKUP run the upgrade.php script like this:
- mysql -u<rootuser> -p<rootpassword> <database> db/096to097.sql
+ php ./scripts/upgrade.php
- Despite the name, it should work for any 0.9.x branch.
-
- Otherwise, go to your StatusNet directory and AFTER YOU MAKE A
- BACKUP run the rebuilddb.sh script like this:
-
- ./scripts/rebuilddb.sh rootuser rootpassword database db/statusnet.sql
-
- Here, rootuser and rootpassword are the username and password for a
- user who can drop and create databases as well as tables; typically
- that's _not_ the user StatusNet runs as. Note that rebuilddb.sh drops
- your database and rebuilds it; if there is an error you have no
- database. Make sure you have a backup.
- For PostgreSQL databases there is an equivalent, rebuilddb_psql.sh,
- which operates slightly differently. Read the documentation in that
- script before running it.
11. Use mysql or psql client to log into your database and make sure that
the notice, user, profile, subscription etc. tables are non-empty.
12. Turn back on the Web server, and check that things still work.
-13. Turn back on XMPP bots and email maildaemon. Note that the XMPP
- bots have changed since version 0.5; see above for details.
-
-If you're upgrading from very old versions, you may want to look at
-the fixup_* scripts in the scripts directories. These will store some
-precooked data in the DB. All upgraders should check out the inboxes
-options below.
-
-NOTE: the database definition file, laconica.ini, has been renamed to
-statusnet.ini (since this is the recommended database name). If you
-have a line in your config.php pointing to the old name, you'll need
-to update it.
+13. Turn back on XMPP bots and email maildaemon.
NOTE: the 1.0.0 version of StatusNet changed the URLs for all admin
panels from /admin/* to /panel/*. This now allows the (popular)
'panel'. If you have an existing user named 'panel', you should rename
them before upgrading.
-Notice inboxes
---------------
-
-Notice inboxes are now required. If you don't have inboxes enabled,
-StatusNet will no longer run.
-
UTF-8 Database
--------------
+If you are upgrading from a 0.8.x or 0.9.x version, you can safely
+skip this section.
+
StatusNet 0.7.4 introduced a fix for some incorrectly-stored
international characters ("UTF-8"). This fix is not
backwards-compatible; installations from before 0.7.4 will show
option enabled.
2. When you're ready, set $config['db']['utf8'] to true, so that
new notices will be stored correctly.
+
+Older versions
+==============
+
+IMPORTANT NOTE: StatusNet 0.7.4 introduced a fix for some
+incorrectly-stored international characters ("UTF-8"). For new
+installations, it will now store non-ASCII characters correctly.
+However, older installations will have the incorrect storage, and will
+consequently show up "wrong" in browsers. See below for how to deal
+with this situation.
+
+NOTE: the database definition file, laconica.ini, has been renamed to
+statusnet.ini (since this is the recommended database name). If you
+have a line in your config.php pointing to the old name, you'll need
+to update it.
+
+Note that the XMPP bots have changed since version 0.5; see above for
+details.
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2011, 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 = 'u:a';
+$longoptions = array('uri=', 'all');
+
+$helptext = <<<UPDATE_OSTATUS_PROFILES
+update_ostatus_profiles.php [options]
+Refetch / update OStatus profile info and avatars. Useful if you
+do something like accidentally delete your avatars directory when
+you have no backup.
+
+ -u --uri OStatus profile URI to update
+ -a --all update all
+
+
+UPDATE_OSTATUS_PROFILES;
+
+require_once INSTALLDIR . '/scripts/commandline.inc';
+
+/*
+ * Hacky class to remove some checks and get public access to
+ * protected mentods
+ */
+class LooseOstatusProfile extends Ostatus_profile
+{
+ /**
+ * Download and update given avatar image
+ *
+ * @param string $url
+ * @throws Exception in various failure cases
+ */
+ public function updateAvatar($url)
+ {
+ if (!common_valid_http_url($url)) {
+ // TRANS: Server exception. %s is a URL.
+ throw new ServerException(sprintf(_m('Invalid avatar URL %s.'), $url));
+ }
+
+ if ($this->isGroup()) {
+ $self = $this->localGroup();
+ } else {
+ $self = $this->localProfile();
+ }
+ if (!$self) {
+ throw new ServerException(sprintf(
+ // TRANS: Server exception. %s is a URI.
+ _m('Tried to update avatar for unsaved remote profile %s.'),
+ $this->uri));
+ }
+
+ // @fixme this should be better encapsulated
+ // ripped from oauthstore.php (for old OMB client)
+ $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
+ try {
+ if (!copy($url, $temp_filename)) {
+ // TRANS: Server exception. %s is a URL.
+ throw new ServerException(sprintf(_m('Unable to fetch avatar from %s.'), $url));
+ }
+
+ if ($this->isGroup()) {
+ $id = $this->group_id;
+ } else {
+ $id = $this->profile_id;
+ }
+ // @fixme should we be using different ids?
+ $imagefile = new ImageFile($id, $temp_filename);
+ $filename = Avatar::filename($id,
+ image_type_to_extension($imagefile->type),
+ null,
+ common_timestamp());
+ rename($temp_filename, Avatar::path($filename));
+ } catch (Exception $e) {
+ unlink($temp_filename);
+ throw $e;
+ }
+ // @fixme hardcoded chmod is lame, but seems to be necessary to
+ // keep from accidentally saving images from command-line (queues)
+ // that can't be read from web server, which causes hard-to-notice
+ // problems later on:
+ //
+ // http://status.net/open-source/issues/2663
+ chmod(Avatar::path($filename), 0644);
+
+ $self->setOriginal($filename);
+
+ $orig = clone($this);
+ $this->avatar = $url;
+ $this->update($orig);
+ }
+
+ /**
+ * Look up and if necessary create an Ostatus_profile for the remote entity
+ * with the given profile page URL. This should never return null -- you
+ * will either get an object or an exception will be thrown.
+ *
+ * @param string $profile_url
+ * @return Ostatus_profile
+ * @throws Exception on various error conditions
+ * @throws OStatusShadowException if this reference would obscure a local user/group
+ */
+ public static function updateProfileURL($profile_url, $hints=array())
+ {
+ $oprofile = null;
+
+ $hints['profileurl'] = $profile_url;
+
+ // Fetch the URL
+ // XXX: HTTP caching
+
+ $client = new HTTPClient();
+ $client->setHeader('Accept', 'text/html,application/xhtml+xml');
+ $response = $client->get($profile_url);
+
+ if (!$response->isOk()) {
+ // TRANS: Exception. %s is a profile URL.
+ throw new Exception(sprintf(_('Could not reach profile page %s.'),$profile_url));
+ }
+
+ // Check if we have a non-canonical URL
+
+ $finalUrl = $response->getUrl();
+
+ if ($finalUrl != $profile_url) {
+ $hints['profileurl'] = $finalUrl;
+ }
+
+ // Try to get some hCard data
+
+ $body = $response->getBody();
+
+ $hcardHints = DiscoveryHints::hcardHints($body, $finalUrl);
+
+ if (!empty($hcardHints)) {
+ $hints = array_merge($hints, $hcardHints);
+ }
+
+ // Check if they've got an LRDD header
+
+ $lrdd = LinkHeader::getLink($response, 'lrdd', 'application/xrd+xml');
+
+ if (!empty($lrdd)) {
+
+ $xrd = Discovery::fetchXrd($lrdd);
+ $xrdHints = DiscoveryHints::fromXRD($xrd);
+
+ $hints = array_merge($hints, $xrdHints);
+ }
+
+ // If discovery found a feedurl (probably from LRDD), use it.
+
+ if (array_key_exists('feedurl', $hints)) {
+ return self::ensureFeedURL($hints['feedurl'], $hints);
+ }
+
+ // Get the feed URL from HTML
+
+ $discover = new FeedDiscovery();
+
+ $feedurl = $discover->discoverFromHTML($finalUrl, $body);
+
+ if (!empty($feedurl)) {
+ $hints['feedurl'] = $feedurl;
+ return self::ensureFeedURL($feedurl, $hints);
+ }
+
+ // TRANS: Exception. %s is a URL.
+ throw new Exception(sprintf(_m('Could not find a feed URL for profile page %s.'),$finalUrl));
+ }
+
+ /**
+ * Look up, and if necessary create, an Ostatus_profile for the remote
+ * entity with the given webfinger address.
+ * This should never return null -- you will either get an object or
+ * an exception will be thrown.
+ *
+ * @param string $addr webfinger address
+ * @return Ostatus_profile
+ * @throws Exception on error conditions
+ * @throws OStatusShadowException if this reference would obscure a local user/group
+ */
+ public static function updateWebfinger($addr)
+ {
+ $disco = new Discovery();
+
+ try {
+ $xrd = $disco->lookup($addr);
+ } catch (Exception $e) {
+ // Save negative cache entry so we don't waste time looking it up again.
+ // @fixme distinguish temporary failures?
+ self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
+ // TRANS: Exception.
+ throw new Exception(_m('Not a valid webfinger address.'));
+ }
+
+ $hints = array('webfinger' => $addr);
+
+ $dhints = DiscoveryHints::fromXRD($xrd);
+
+ $hints = array_merge($hints, $dhints);
+
+ // If there's an Hcard, let's grab its info
+ if (array_key_exists('hcard', $hints)) {
+ if (!array_key_exists('profileurl', $hints) ||
+ $hints['hcard'] != $hints['profileurl']) {
+ $hcardHints = DiscoveryHints::fromHcardUrl($hints['hcard']);
+ $hints = array_merge($hcardHints, $hints);
+ }
+ }
+
+ // If we got a feed URL, try that
+ if (array_key_exists('feedurl', $hints)) {
+ try {
+ common_log(LOG_INFO, "Discovery on acct:$addr with feed URL " . $hints['feedurl']);
+ $oprofile = self::ensureFeedURL($hints['feedurl'], $hints);
+ self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
+ return $oprofile;
+ } catch (Exception $e) {
+ common_log(LOG_WARNING, "Failed creating profile from feed URL '$feedUrl': " . $e->getMessage());
+ // keep looking
+ }
+ }
+
+ // If we got a profile page, try that!
+ if (array_key_exists('profileurl', $hints)) {
+ try {
+ common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
+ $oprofile = self::ensureProfileURL($hints['profileurl'], $hints);
+ self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
+ return $oprofile;
+ } catch (OStatusShadowException $e) {
+ // We've ended up with a remote reference to a local user or group.
+ // @fixme ideally we should be able to say who it was so we can
+ // go back and refer to it the regular way
+ throw $e;
+ } catch (Exception $e) {
+ common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
+ // keep looking
+ //
+ // @fixme this means an error discovering from profile page
+ // may give us a corrupt entry using the webfinger URI, which
+ // will obscure the correct page-keyed profile later on.
+ }
+ }
+ throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'),$addr));
+ }
+}
+
+function pullOstatusProfile($uri) {
+
+ $oprofile = null;
+
+ if (Validate::email($uri)) {
+ $oprofile = LooseOstatusProfile::updateWebfinger($uri);
+ } else if (Validate::uri($uri)) {
+ $oprofile = LooseOstatusProfile::updateProfileURL($uri);
+ } else {
+ print "Sorry, we could not reach the address: $uri\n";
+ return false;
+ }
+
+ return $oprofile;
+}
+
+$quiet = have_option('q', 'quiet');
+
+$lop = new LooseOstatusProfile();
+
+if (have_option('u', 'uri')) {
+ $lop->uri = get_option_value('u', 'uri');
+} else if (!have_option('a', 'all')) {
+ show_help();
+ exit(1);
+}
+
+$cnt = $lop->find();
+
+if (!empty($cnt)) {
+ if (!$quiet) { echo "Found {$cnt} OStatus profiles:\n"; }
+} else {
+ if (have_option('u', 'uri')) {
+ if (!$quiet) { echo "Couldn't find an existing OStatus profile with that URI.\n"; }
+ } else {
+ if (!$quiet) { echo "Couldn't find any existing OStatus profiles.\n"; }
+ }
+ exit(0);
+}
+
+while($lop->fetch()) {
+ if (!$quiet) { echo "Updating OStatus profile '{$lop->uri}' ... "; }
+ try {
+ $oprofile = pullOstatusProfile($lop->uri);
+
+ if (!empty($oprofile)) {
+ $orig = clone($lop);
+ $lop->avatar = $oprofile->avatar;
+ $lop->update($orig);
+ $lop->updateAvatar($oprofile->avatar);
+ if (!$quiet) { print "Done.\n"; }
+ }
+ } catch (Exception $e) {
+ if (!$quiet) { print $e->getMessage() . "\n"; }
+ common_log(LOG_WARN, $e->getMessage(), __FILE__);
+ // continue on error
+ }
+}
+
+if (!$quiet) { echo "OK.\n"; }
+++ /dev/null
-b2.PXYLSJBuLkZnUQ7H.2gOSSTbVllQM_XyN0ya4sO9CNt5uBUATEGyKd3LkkR0QXTSduKb7xj7Bp1TX6.8XdIDsOVVuXe.3HPnPLtSacZm66.NLY3JGhJv1MfGvcJU42YEQiUvpAhZRe46E.lv38ZPzxvhjjAmGFyFv8UNuhdw6sNIlTwBdct3k1GKA1YSEeVJ_xLiAVa8IaU_XG8PlxMovsBPePOry8__.aAp5loHtmqX6vEVu3lcHEn5NvSZ502QoWkK_20Y.6oja.Fqqxtr6eli_AQXaVzWWDEu_D4_rDV9Mz_.EC8KzXKo.YdUaWQfS9akqNm1v54wTNM4ZDegsbKnaNUR7J0OYgzpzcPj4L57yWKFm7k2af.v2loGrUOKJGO3rBcOQSfUz5jyCKDdd29cdd2L96XA0Uy31RjvdWSsprigS94HjoE9e5TUMHHZt47Wi50DsMq5R87uznHTouuHOKyxT3c_wCejxb_A0lVM5JL4VnrjVEo0CkY5ju1fDXfXG.Q8T4WYbnW_4i4W.DAuaFiRxIsLtrSG5bpMvJWQ8MTfc39gaLkNtGACL_O8IxX7iyFjARapuIXPhu3v3ndEt6qlgcUsEBl6zhxe6WcTQssBTUSDSPQWMmbA8TCYe1xwHd3ukSdqkhkALdIri2oeLLhkbNQRKxouIWHqL5aH0r7CCKM.P87rJE1meb28ux00FrBg4Fa62RM5S5Wn24u0odvPGK9JGmzisi.zM2cULr8C03gwBEeGDXzLIPevVnoqcYvtUfs8_B9xtaFzsKEM.04JX94e5Y_qWqfJs2.vWdY02BwWNsM1ONUzsS5qBzFhNpVnvZYHkNuOGXLb7cg7sL0Zm9pGMQPJsffThK2KY5EGSxbCB_JMqZmu9UtmcFyrsny7Yo1z6uCgu7GzN9_6Tc_DGW4OyuOm6XaLZSbGApmGosEKRKIODNAUGyT6QChSEwnPxhgYVpIn1TYualgrBtwvON5d84Up5.mxTH5ZHDjQcW04oE1dp2mBQhlUHvTF.PbEuUztvA8mMuLZgERcE01oOKkDlh9gvjZNiMs6f8SPmulKmtvheecitvB4Urgkae_PiXbcD4aOL4PyjwByX4zpCw9NG8Ga.6JLv1nH.vEE5XBCzh0_rnEmv0XzNBjiE8nj_p2pntfxmdpEeSGrA8WzigZTHrjawltlC_sMGLqR0EfRqoVrs3NtH8jafQ8DoqKUnR1wiG1BFC9PiQzPbPunYvVT_vMILkfwHDS7gY4bfZAlLrfbC0n8EKumGJc1o1ag_VsfnO2O8vE9667oVTaAGMmxXA_g1qpPVJTDWHRm4kwA6SWTZ6RCSb0Scd_DTXN4cevjn3sSGOCKE5Tocd1s4JRCuDPGQ9XI1OXGSKZrUuuM8mUlZqj6A.FWgdv2c5qXoRla.Qlb6encfFh8gnBNNoIR5X4F9PFl7.Yq38Vi0BJ7zIJVYAU8UXqJqPKKN.qH4A941m8jG7trm9NBrsRIkyCJBE5W1UVZ4x4sBDSuJMT_UCYCyn_qsjHkYpJOaYt44c7PT5U_S8oVUUe0qtuvmQ5DK.cZAU1hdw9fINikie3yGxO66lWRPtmM1rqTHwEHqaJXkn4mnRhQmHE.pqB.N_Byir3AiezaA2EGi6Z7.G99XrOjxJ0tIyim39AkoPZbeWqVlLDL.4AGCzPLQyndMClwWJdjcHBaSrxGGL1OpZ9cGA6w1zLD_6uyP4gK2pGTGxvOk4TFqrpc07eX7j6agiBfkUzYykXSm_JYDVZqiivMwKVEynFsX24erN0kd379wr_QI8Ov2nfXudbZn9EY1bhmupuAtMqpW.dNGk7YJ3AD31zrfz2KcZjdQuLkTYwqW4zI3YEI0jFqk0WYXSUmCNRzbdvmoZI1kAWRw2COuUnYeMfoTiMeJGgUd.g--
\ No newline at end of file
+++ /dev/null
-WJofugbSJAtzh.lFcHxO_WHM64iJd7qHJFbsqC9VLnpiqoBxdbE0iwoKozxZC331Svk6O9Un9jonWUrQeTndGO8hldPlxqGdFdbl6OjoucDGG_h6qBw3Ugnbethbyuew1qOaUr6ItfU4Pe9O2GtUj2KbqxZpUAvMeiS20hykHbIZ8n_1.fl.fTToLiJn58zcLc1_ryM0f5jbkIGwmGX_SG6isGJRzC4.BiNmntpJ5ZCKa80e7oUH9S6NlM5SEmXoA3zhuzkbBxF_fKLendcC7EafnTT34MbgD5s4uwTyubSBJvdmBu.mWSO9xrnojM903Vo8h3.UdG.id1LmFrj4xxd24IQqZM2v4zOfl8ugF8ChHaIzp82A1AOuk0ulkqKgiALia6bsZMbKdPZtlu_HGrF06tCt5VGvu5f0ZgjRk_kOlP_f_oppyVKRWzZpSH9GryOpoqJA2vlxgEH2BvZqaaUYEmaYJjIh7eNkLRLVorbK7rGhPf_L5qfHir.31Ar1zZxWgvhjSW7ipkvsNr_3j7oOh1LSTVWNHo.dpLT0_dib6syFopav2FqStJG0RTsWNXkQ_6h.jf439DjwuZmCLMcbUrMAMrRVcsUyR5nfqP5cP0igSx8m.oONA7O.txOXSzc3HjqvIVSTRO8BIHx.vTMJ6mq4NUmZ6_pHWapHbO9esUlIyXf5CF2qhtlM9aulr2fwCf8BqtjQctAtvYLrI_qKP95wNaB_qhcuFsZN1aiql.FtigHe2YYTix4SWg9.67VSBAyOqjWcA5jbyoomf8Gxzks9PZQfSuKbkbw_x3XOshGl4QMo6CEypV0qIYVVW77bOJc7I0WgwgxuAKg6lROlmsIdN0.SeTV4sY1ZcoLEgdNCNb81SVstXdE0iPXPZZsEStez.qluWnQoVkkWfOaBe78PxPZUvQS02RaR0FCH4bksqGWXLA8chAHIe4vPNerCLJwskKG3rA43xRDEZY7sgdEfA93iTztmIRq8dkYA6dJOxOMtvpSdh9jds04xpdmfhb23bVYp1XCp3qWka6JoKlzvQU2THqFr7gNU3KMCbr2ngHHkDTZGNO__MLa3SKlp2Vg3qHXxkivFUmWTNUz5vuW7v.FhsKOVFIFfSrTl3pjJMD3hyIlxzf_HJ60q1LRBkwqxrA9e8Fr5tqWQj.evL5kqz_r26MdHFeMTx9VwfDnHLaVx3eu5Wy2NJmLVPRLNn4t1VhexsEdLquy0ynBVBOBBRa2HbYgv0lXOP.QRl5twTKwJO6fx6J4_L_HhPv6jhcQej1LtUyGyKwLuXrHxnHCOqD.e9ZL_xnqSRthM6NvBsvbnZOPr7falUuQWPzbikXMFUvSlckeetPi2Z11l9pH.cxZDj19B38v7jwT5zZMQN9FzQvTCvzrQCpHxfIxwh3a2cx18BEMKHL7MJWDsoYVURtI3iIdR84WzXcr3kkCz.LM8tqTKVkzHLk8Grx8KT3dF5ZIVhWK5yyb05RFOZdoZQ4cWXmvsaQhDUd6Dm2KRJiypSFntLLSp34URsLaqzxaakMnywHvfmsINah4oKBBy8.NFBRULU9SqTyIOwf6_ggWG06J1WJxWV94RRCD1rMNNM9ISMOo4yB_dmfLHnXKOZm1lOnisEN36gsxniy_psLN3Ed1ozRtbbD.wALfE.92DrDA9ASPOdu08P7xer76iXVbdt_4cg5whY59Hq2N.A1mrSbetDbSu7NeziZ.nBvSUg_YpVvMo2H3elySL.1UsLPFznStGuYfbISN79MZecU.ScSCtaeZQ2cBFekXMNT77HWZmv6YLsz84ceQwL_MidvAYqPh6PUNiBl8iwFR5PCpTB54.g0m3zuALOqF9hJ598v9rh9Zlu1SfE.UfmGpUICMSuXH7C8zHMq4TFZGzCuBY9EOuBc.JQaCfBr8N3jnDq2bwlQjDmgbVW2xm2WpPMCB0OxkqoggA0i4ZZA3gSfqhlZ9mdmr_l9mUe0dOd_EkyWyu0l.Z1.VQLY2KJHl.8pZWyP6S_RAFmABOlEGP3m1E8NxaMP87o9ot_BNg21DeHbwADKbv16deRlDrKmntHoPwfsaTPNo5KembI_4nHxQ3y2B2OjsUPcLYFZZtsP4ukLBhYusR8SdtsEC._plxsMQzS9nH.zRP8nbluMlUjCKgfepGN_rCq.NeGON.L_.FowXEOcX7M1SD.IfihdAHqk0zUpuyTfe.9E77aEu26iIZOGmyOwSqRvN9HksJx.iMk5xL.xah7hl.NByMBbmkRDS52wDMxygNpPXsIHdvu8OyLxq.ZsNBGF.IHs0qiquX4.RZ2TBqTQ6O4AhzOTpFeZlG3UzdmxsEtDI2a7tY_27Gg39apf_83ijjiLaJE2RG5Mb9krZ2RCIAXaFez74o_oqli5dy6WyT4lEIKtw38T7m1bJ_xpLju5FBQUE54RpsK.ZWSAoyh3c05b2mBeN2id_NV7sM4MinY7rEsOgNVevUNrWebNrrdunUF8gsa59cXdGSKvmUw9kEKW_Z6Y14AICD43zlmVGYDYlSLqpHsu32m9aGuQFlqzBlHCKPg9uD9dyFKsZJI8l2yq91sEj9snlYhApmHLVQzGWLiOJCJUclByiPmVD_.OnHE84lBcv0bkXKFYXvUhFs2Xu1VrN1mGXz50KkG4Xovzkw0ueuWlJ2vozPUf9CkJ1mlOA4jwuFLMrQZmN04aXyR3ZWFN8pdSVITI0ADqNr9OGacCra.emTRIWdBLEj18kp39vhlR6BpxI2V0FQjC_27n2hkDUNAUNFaJ1Q84OO2mgzZnPXcN7NYz57W3lB_mMVUtKngnRlTNWn1sFdN6.WFQ1szScjtpFa68NBv5pLUOvKy49VWjn14uS4aUoDL_fbMi9tGw0tlrMEr74fm5hJNwPX1QKd3cy0jqDHLIpZTb1aNxIz_KU4XIJ2wx0gZZQH2zV7eTxsrozzo3J0TtiQC6pPOqbnsRF1TuX1..DV5LzUdKX0TUXyO8x0710.EF4z6pim0HuVKzV2VBKmG6qtzpIRCKzVk14lx2E9YkJTQusU9qZnw9Ixu_YL0Ue_4LachvurMZDYTIRcSyd4St3TmtZswmeLPS6Md6NtHwxQEy.RVLhuCmliiZcw9hB.CH6v0UX1i9E6r_FZyboWtnzX42mZDrJR4n1u2nGFzYwJrDN_kJ3uHKs4EoV9ESEd5AojHDWSkOs4lKbyRlYwhGrHgB25mZ2xRdBtkHMDupYisNjOJ.QEIXzpK291wKHWTL.VdeTOLqGxsthxoR7AOdnzalMIuUItxagzB14Gw2eZ5PcIZvcgO9C4BouZW4SAg0D0Xhmd4A0MW0an7NqzXM4VDVg6WMgeBHqL54yfHjK4oMkwDUQTvqNH13AKINKbtr5t5JJzfpSN0fmfysA1Z1PdkJROhFkyH1_ZXcoMJp2XbYSk6ZXm69U4j4QCYe_vmkp3NM802bMpohywJRxYstmfIxinJukmZOEiSClAk1MhRGVlj60w8ggV29QYa_pdqUjTm0DwYZQF1Z_NVkhVXVv7bQMpRQJPIMwf3TggPPHVAMA1tk0OdPFOCx1207E-
\ No newline at end of file
+++ /dev/null
-8Yd1y.bSJBPj3Ul5NjhQHFX0dN0NuJAfBObEdgIY2QDh0bVXkzcJbNlBamPSFBZqHojxbPzIj5GlY3XdxGMY6ttYzBHvc_FK5krngYtlLSmBtjRArxI_bBfngIxeI2kFC3wPvHIdzp8gygRp2.IlDahWHABFhAPrPrxAkAOqv6O3tKUTTzcnZX22eOdoXVXQSMiphlDQIxpfbdpLnduBvMxvI.hwrfAW4iIVY7iBjkdnrtdAVj4N2.u65khGuAwaX9i6Buca3XQJm601Atf6fjM57yOFA0.laixrOss1_F36iqrc4mOeWnYI_UDw8SgIrXroswrJ.KwXlqCdICxel3Ui0hfrOoGnCt4HHT9tiObu9VG.GxM2KQ_tjb1LwFFX0WEisFKXfQwpR_2NU..0j1icWhnmPHFJGsImvX1dFgeTqcNvoAcfZ0y9c8KQKzV5CbQeg9_oPC7uviIdxQK2lJ7SzgRfZAw4FDeDXKDxuVZRE7jZYQEWtkmp9dFlFLM_L0dPk4kiJuRrRPJ8DAyWSiex_ib1mJ3bHAxbsEcWoUunIOivWVdZDudCBath8AdoAQ0P8_f.fl8jYgbZil49Qhg.WmFD_H0w7ikdEi1iHsWnjSrDORtAjENGvoEje0h.gMBf38FbQ6vW2BbKC.RBKp.cQhVPvDHel1UFtqZ8IJm7mTP0BDSDG2iFJp1_N7L5MUoUxEwgskMxeQf99vE1UybdR4q0kbx6i_RR3_6.AQ5QKk1EBeKAfnVYDdwcLGVgWd9JxxvekkL7Scl1ncZ9ViLvlC3Hfrbtrm2Q5rr17pIG6L.a6gDKKH1NGgapyLUCVtKZ27Ysd9ExMF1yHfMAyOKL5I7KaJmZTZnxWQ9ex.hHS6tZ9WjPFhjvpve7H_mB8ZXNBdEc4bL.iRdknHNe3WSSgCLWf2RVFZ4wmVMYW4KwGpIp7iGbaUDBYdBFkcCmv6zeneEsLGJHUYipsay5unopuFyBe611pwFRNHZ3XznmqaK8TXl18k_PCmQ6g93.fXFeWKmszw_FArltYuXHNIm3zwRobvDo7Rp0znnt76Q0ha3q5WHggFd6.QmC6jywGLpki_09v0Pc6qGh4gpGt1vZeZrA1OGQ7VSB7Muo4Mr4TbQU_6342nXeG0tBImIanPZsQrew1.tOmAfn16UpzcCuEC3NWw99yipIaEZirdr4teITB7xX3x6UGRcjtoAlz8oo6VEYaFX7ybG6Bo.K4hspnJLWH6jKK4hcpYedE2qSB0W4z_ieFy6Y.2qrx8_3CL1_8h5w6PjXOFTmsyk0v0DXQVuGh8QxPgPVyrWyDzlXJZ.5_mHTohGRGCI41I6jGJcCOh3qEQZKF2VYb.3o00Le9YlXxpBIBh7rBw5vNypp9jSd.W6VPnQ53xM6QzVbYW4OV3gkVE__AgvKNUzfRHiK9dN7evwvKX66W4tUPGQapjGbRWnFc3Q_0__oMYTtSR3EMxs0Lvkjh87s0SMxy0gzvVCfNt4VrdZCzdBd8N8Tcj5Pc4KJ09ikPtNB3V8i6jtcVUuKzs32B37O6AA2iOydQdsPDEhfkDA0S_ocu3DqqBsJOYmzjRq39e1WFhlRijNftxHF6DRvzpSIIm5VzcwIg8LLl4zbHyeRXEmBDp.KvlfP_.z2IUqilhGeccCmV2XFD_VFidZclzscmceMmuBOXYmaplSW3sX94eM7mp2dyDjVXtR4igukNU8Fabaqilu98OKIv9mLdTlE9u7t25KNqMHQQOsYNM4BUocalSN1K3JOot544vz9VbWJfIljF2L6DCduJd6h9aDH5wLMjljRqrteltA3yz86ensnOZ5wmU8X3NMpPN.OCXM8zxqdhEGxE_jeXkpf4AKIFWYrn8zH84sFU60gpy3xMOleKK6NfrFDRdzxkBIJGV7yhBaDi1_0iZuwm8hVLFe2odNyEKbllCeXYpeMJwe3w_e7XQD1T2Zv4bvK69qYPhmkngPs7_nCYYUFWKlvkg0njZyxn3kNSTONHjzrLSlTWMvGobei1GV74wJzWmmZpC1yQNOe_8Stjbj5Lg47iELys5kCMWU1NyIQf16AT35xTlPCYJ_RNVy3yDNeh5kqy9AMX_HIJOHw8xwJEUoiqKzWzLV.BWmpzcny9_7P2naXBrzRlOYmYyWUtp.P0gGNxLZXtEaKKGgdQB.fYXUyuKH0ptXqj1YCl1g1KWo3.AwndjDy0PE8ZYCaCjz.EyXqx.8bvfJycccGRw5RVU74aydE0DRCC3vF6VI9qbPWK89HNTMWxPSSTHdChY6yAhNsc5UhDwsAmhZ_UIYynZ8AM_oCS232.einbw9fYI4X6yZm_fD60DJ1FsBweU9ivf3Y4X2ucLFY8xPp_8SxZ5UtaP67TKflzMYjuvhGXAUF9.1u8ZKJGOliFmMxIwJ7lPJs93HfZgLN2eyH6F.rZjREeyd0fbsRzZ_vMEs4fx6sX4eIGVoyVFpO5b11kxnBqlKnATI_nw1.exkl5sQj00clwphsecXiVLaDFCEjG94ve_1cw2foqQUoX6pUfqr_hSSpnacdacPclbxWPehuN5LpjMso_5b4v.rj4s9VtzRqxovBinIgBdTFAH560aN5f7wuN5ZZT_BT5aCFNwQBYoDfCTaU9jw3aaXU29vEJmYZcvC9WCpU0RTntciGlx8rIbagu7cUGrYFvLbU2ZekazCMklPO5Sno_z5zzxLnTpFxesNoreOj7M3Cp1RHKUmqAog04bYC9kPFvH_q.jF2g507LEN3nPL9EJUx460UG_o4HRQOhDi2YrmrHk.gLZECgnMwCN770fhL
\ No newline at end of file
+++ /dev/null
-#!/bin/bash
-
-export user=$1
-export password=$2
-export DB=$3
-export SCR=$4
-
-mysqladmin -u $user --password=$password -f drop $DB
-mysqladmin -u $user --password=$password create $DB
-mysql -u $user --password=$password $DB < $SCR
-
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 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__) . '/..'));
-
-$helptext = <<<ENDOFHELP
-USAGE: decache.php <table> <id> [<column>]
-Clears the cache for the object in table <table> with id <id>
-If <column> is specified, use that instead of 'id'
-
-
-ENDOFHELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-if (count($args) < 2 || count($args) > 3) {
- show_help();
-}
-
-$table = $args[0];
-$id = $args[1];
-if (count($args) > 2) {
- $column = $args[2];
-} else {
- $column = 'id';
-}
-
-$object = Memcached_DataObject::staticGet($table, $column, $id);
-
-if (!$object) {
- print "No such '$table' with $column = '$id'; it's possible some cache keys won't be cleared properly.\n";
- $class = ucfirst($table);
- $object = new $class();
- $object->column = $id;
-}
-
-$result = $object->decache();
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the 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__) . '/..'));
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-common_log(LOG_INFO, 'Fixing up conversations.');
-
-$notice = new Notice();
-$notice->query('select id, reply_to from notice where conversation is null');
-
-while ($notice->fetch()) {
-
- $cid = null;
-
- $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;
- }
-
- unset($reply);
- $reply = null;
- }
-
- print "$notice->conversation";
-
- $result = $notice->update($orig);
-
- if (!$result) {
- common_log_db_error($notice, 'UPDATE', __FILE__);
- continue;
- }
-
- $orig = null;
- unset($orig);
-
- print ".\n";
-}
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, 2010 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 = 'i:n:a';
-$longoptions = array('id=', 'nickname=', 'all', 'dry-run');
-
-$helptext = <<<END_OF_UPDATEAVATARURL_HELP
-fixup_group_uri.php [options]
-Fill in unstored URIs for groups in the system (added during 0.9)
-
- -i --id ID of group to update
- -n --nickname nickname of the group to update
- -a --all update all
- --dry-run don't change anything
-
-END_OF_UPDATEAVATARURL_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-try {
- $user = null;
-
- if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
- $group = User_group::staticGet('id', $id);
- if (empty($group)) {
- throw new Exception("Can't find group with id '$id'.");
- }
- updateGroupUri($group);
- } else if (have_option('n', 'nickname')) {
- $nickname = get_option_value('n', 'nickname');
- $group = User_group::staticGet('nickname', $nickname);
- if (empty($group)) {
- throw new Exception("Can't find group with nickname '$nickname'");
- }
- updateGroupUri($group);
- } else if (have_option('a', 'all')) {
- $group = new User_group();
- $group->whereAdd('uri IS NULL');
- if ($group->find()) {
- while ($group->fetch()) {
- updateGroupUri($group);
- }
- }
- } else {
- show_help();
- exit(1);
- }
-} catch (Exception $e) {
- print $e->getMessage()."\n";
- exit(1);
-}
-
-function updateGroupUri($group)
-{
- if (!have_option('q', 'quiet')) {
- print "Updating URI for group '".$group->nickname."' (".$group->id.")...";
- }
-
- if (empty($group->uri)) {
- // Using clone here was screwing up the group->find() iteration
- $orig = User_group::staticGet('id', $group->id);
-
- $group->uri = $group->getUri();
- if (have_option('dry_run')) {
- echo " would have set $group->uri ";
- } else {
- if (!$group->update($orig)) {
- throw new Exception("Can't update uri for group " . $group->nickname . ".");
- }
- echo " set $group->uri ";
- }
- } else {
- print " already set, keeping $group->uri ";
- }
-
- if (have_option('v', 'verbose')) {
- print "DONE.";
- }
- if (!have_option('q', 'quiet') || have_option('v', 'verbose')) {
- print "\n";
- }
-}
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-// 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();
-}
-
-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('STATUSNET', true);
-define('LACONICA', true); // compatibility
-
-require_once(INSTALLDIR . '/lib/common.php');
-
-$start_at = ($argc > 1) ? $argv[1] : null;
-
-common_log(LOG_INFO, 'Updating user inboxes.');
-
-$user = new User();
-
-if ($start_at) {
- $user->whereAdd('id >= ' . $start_at);
-}
-
-$cnt = $user->find();
-$cache = Cache::instance();
-
-while ($user->fetch()) {
- common_log(LOG_INFO, 'Updating inbox for user ' . $user->id);
- $user->query('BEGIN');
- $inbox = new Notice_inbox();
- $result = $inbox->query('INSERT LOW_PRIORITY 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 ' .
- 'WHERE subscription.subscriber = ' . $user->id . ' ' .
- 'AND notice.created >= subscription.created ' .
- 'AND NOT EXISTS (SELECT user_id, notice_id ' .
- 'FROM notice_inbox ' .
- 'WHERE user_id = ' . $user->id . ' ' .
- 'AND notice_id = notice.id)');
- 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(Cache::key('user:notices_with_friends:' . $user->id));
- }
-}
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-// 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('STATUSNET', true);
-define('LACONICA', true); // compatibility
-
-require_once(INSTALLDIR . '/lib/common.php');
-
-common_log(LOG_INFO, 'Starting to render old notices.');
-
-$start_at = ($argc > 1) ? $argv[1] : null;
-
-$notice = new Notice();
-if ($start_at) {
- $notice->whereAdd('id >= ' . $start_at);
-}
-$cnt = $notice->find();
-
-while ($notice->fetch()) {
- common_log(LOG_INFO, 'Pre-rendering notice #' . $notice->id);
- $original = clone($notice);
- $notice->rendered = common_render_content($notice->content, $notice);
- $result = $notice->update($original);
- if (!$result) {
- common_log_db_error($notice, 'UPDATE', __FILE__);
- }
-}
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the 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__) . '/..'));
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-common_log(LOG_INFO, 'Initializing conversation table...');
-
-$notice = new Notice();
-$notice->query('select distinct conversation from notice');
-
-while ($notice->fetch()) {
- $id = $notice->conversation;
-
- if ($id) {
- $uri = common_local_url('conversation', array('id' => $id));
-
- // @fixme db_dataobject won't save our value for an autoincrement
- // so we're bypassing the insert wrappers
- $conv = new Conversation();
- $sql = "insert into conversation (id,uri,created) values(%d,'%s','%s')";
- $sql = sprintf($sql,
- $id,
- $conv->escape($uri),
- $conv->escape(common_sql_now()));
- echo "$id ";
- $conv->query($sql);
- print "... ";
- }
-}
-print "done.\n";
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - a distributed open-source microblogging tool
- * Copyright (C) 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 = 'i:n:af:';
-$longoptions = array('id=', 'nickname=', 'all', 'file=');
-
-$helptext = <<<END_OF_INITIALIZEINBOX_HELP
-initializeinbox.php [options]
-initialize the inbox for a user
-
- -i --id ID of user to update
- -n --nickname nickname of the user to update
- -f FILENAME read list of IDs from FILENAME (1 per line)
- --file=FILENAME ditto
- -a --all update all
-
-END_OF_INITIALIZEINBOX_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-try {
- $user = null;
-
- if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
- $user = User::staticGet('id', $id);
- if (empty($user)) {
- throw new Exception("Can't find user with id '$id'.");
- }
- initializeInbox($user);
- } else if (have_option('n', 'nickname')) {
- $nickname = get_option_value('n', 'nickname');
- $user = User::staticGet('nickname', $nickname);
- if (empty($user)) {
- throw new Exception("Can't find user with nickname '$nickname'");
- }
- initializeInbox($user);
- } else if (have_option('a', 'all')) {
- $user = new User();
- if ($user->find()) {
- while ($user->fetch()) {
- initializeInbox($user);
- }
- }
- } else if (have_option('f', 'file')) {
- $filename = get_option_value('f', 'file');
- if (!file_exists($filename)) {
- throw new Exception("No such file '$filename'.");
- } else if (!is_readable($filename)) {
- throw new Exception("Can't read '$filename'.");
- }
- $ids = file($filename);
- foreach ($ids as $id) {
- $user = User::staticGet('id', $id);
- if (empty($user)) {
- print "Can't find user with id '$id'.\n";
- }
- initializeInbox($user);
- }
- } else {
- show_help();
- exit(1);
- }
-} catch (Exception $e) {
- print $e->getMessage()."\n";
- exit(1);
-}
-
-function initializeInbox($user)
-{
- if (!have_option('q', 'quiet')) {
- print "Initializing inbox for $user->nickname...";
- }
-
- $inbox = Inbox::staticGet('user_id', $user->id);
-
- if ($inbox && !empty($inbox->fake)) {
- if (!have_option('q', 'quiet')) {
- echo "(replacing faux cached inbox)";
- }
- $inbox = false;
- }
- if (!empty($inbox)) {
- if (!have_option('q', 'quiet')) {
- print "SKIP\n";
- }
- } else {
- $inbox = Inbox::initialize($user->id);
- if (!have_option('q', 'quiet')) {
- if (empty($inbox)) {
- print "ERR\n";
- } else {
- print "DONE\n";
- }
- }
- }
-}
+++ /dev/null
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - a distributed open-source microblogging tool
- * Copyright (C) 2011, 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 = 'u:a';
-$longoptions = array('uri=', 'all');
-
-$helptext = <<<UPDATE_OSTATUS_PROFILES
-update_ostatus_profiles.php [options]
-Refetch / update OStatus profile info and avatars. Useful if you
-do something like accidentally delete your avatars directory when
-you have no backup.
-
- -u --uri OStatus profile URI to update
- -a --all update all
-
-
-UPDATE_OSTATUS_PROFILES;
-
-require_once INSTALLDIR . '/scripts/commandline.inc';
-
-/*
- * Hacky class to remove some checks and get public access to
- * protected mentods
- */
-class LooseOstatusProfile extends Ostatus_profile
-{
- /**
- * Download and update given avatar image
- *
- * @param string $url
- * @throws Exception in various failure cases
- */
- public function updateAvatar($url)
- {
- if (!common_valid_http_url($url)) {
- // TRANS: Server exception. %s is a URL.
- throw new ServerException(sprintf(_m('Invalid avatar URL %s.'), $url));
- }
-
- if ($this->isGroup()) {
- $self = $this->localGroup();
- } else {
- $self = $this->localProfile();
- }
- if (!$self) {
- throw new ServerException(sprintf(
- // TRANS: Server exception. %s is a URI.
- _m('Tried to update avatar for unsaved remote profile %s.'),
- $this->uri));
- }
-
- // @fixme this should be better encapsulated
- // ripped from oauthstore.php (for old OMB client)
- $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
- try {
- if (!copy($url, $temp_filename)) {
- // TRANS: Server exception. %s is a URL.
- throw new ServerException(sprintf(_m('Unable to fetch avatar from %s.'), $url));
- }
-
- if ($this->isGroup()) {
- $id = $this->group_id;
- } else {
- $id = $this->profile_id;
- }
- // @fixme should we be using different ids?
- $imagefile = new ImageFile($id, $temp_filename);
- $filename = Avatar::filename($id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- } catch (Exception $e) {
- unlink($temp_filename);
- throw $e;
- }
- // @fixme hardcoded chmod is lame, but seems to be necessary to
- // keep from accidentally saving images from command-line (queues)
- // that can't be read from web server, which causes hard-to-notice
- // problems later on:
- //
- // http://status.net/open-source/issues/2663
- chmod(Avatar::path($filename), 0644);
-
- $self->setOriginal($filename);
-
- $orig = clone($this);
- $this->avatar = $url;
- $this->update($orig);
- }
-
- /**
- * Look up and if necessary create an Ostatus_profile for the remote entity
- * with the given profile page URL. This should never return null -- you
- * will either get an object or an exception will be thrown.
- *
- * @param string $profile_url
- * @return Ostatus_profile
- * @throws Exception on various error conditions
- * @throws OStatusShadowException if this reference would obscure a local user/group
- */
- public static function updateProfileURL($profile_url, $hints=array())
- {
- $oprofile = null;
-
- $hints['profileurl'] = $profile_url;
-
- // Fetch the URL
- // XXX: HTTP caching
-
- $client = new HTTPClient();
- $client->setHeader('Accept', 'text/html,application/xhtml+xml');
- $response = $client->get($profile_url);
-
- if (!$response->isOk()) {
- // TRANS: Exception. %s is a profile URL.
- throw new Exception(sprintf(_('Could not reach profile page %s.'),$profile_url));
- }
-
- // Check if we have a non-canonical URL
-
- $finalUrl = $response->getUrl();
-
- if ($finalUrl != $profile_url) {
- $hints['profileurl'] = $finalUrl;
- }
-
- // Try to get some hCard data
-
- $body = $response->getBody();
-
- $hcardHints = DiscoveryHints::hcardHints($body, $finalUrl);
-
- if (!empty($hcardHints)) {
- $hints = array_merge($hints, $hcardHints);
- }
-
- // Check if they've got an LRDD header
-
- $lrdd = LinkHeader::getLink($response, 'lrdd', 'application/xrd+xml');
-
- if (!empty($lrdd)) {
-
- $xrd = Discovery::fetchXrd($lrdd);
- $xrdHints = DiscoveryHints::fromXRD($xrd);
-
- $hints = array_merge($hints, $xrdHints);
- }
-
- // If discovery found a feedurl (probably from LRDD), use it.
-
- if (array_key_exists('feedurl', $hints)) {
- return self::ensureFeedURL($hints['feedurl'], $hints);
- }
-
- // Get the feed URL from HTML
-
- $discover = new FeedDiscovery();
-
- $feedurl = $discover->discoverFromHTML($finalUrl, $body);
-
- if (!empty($feedurl)) {
- $hints['feedurl'] = $feedurl;
- return self::ensureFeedURL($feedurl, $hints);
- }
-
- // TRANS: Exception. %s is a URL.
- throw new Exception(sprintf(_m('Could not find a feed URL for profile page %s.'),$finalUrl));
- }
-
- /**
- * Look up, and if necessary create, an Ostatus_profile for the remote
- * entity with the given webfinger address.
- * This should never return null -- you will either get an object or
- * an exception will be thrown.
- *
- * @param string $addr webfinger address
- * @return Ostatus_profile
- * @throws Exception on error conditions
- * @throws OStatusShadowException if this reference would obscure a local user/group
- */
- public static function updateWebfinger($addr)
- {
- $disco = new Discovery();
-
- try {
- $xrd = $disco->lookup($addr);
- } catch (Exception $e) {
- // Save negative cache entry so we don't waste time looking it up again.
- // @fixme distinguish temporary failures?
- self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
- // TRANS: Exception.
- throw new Exception(_m('Not a valid webfinger address.'));
- }
-
- $hints = array('webfinger' => $addr);
-
- $dhints = DiscoveryHints::fromXRD($xrd);
-
- $hints = array_merge($hints, $dhints);
-
- // If there's an Hcard, let's grab its info
- if (array_key_exists('hcard', $hints)) {
- if (!array_key_exists('profileurl', $hints) ||
- $hints['hcard'] != $hints['profileurl']) {
- $hcardHints = DiscoveryHints::fromHcardUrl($hints['hcard']);
- $hints = array_merge($hcardHints, $hints);
- }
- }
-
- // If we got a feed URL, try that
- if (array_key_exists('feedurl', $hints)) {
- try {
- common_log(LOG_INFO, "Discovery on acct:$addr with feed URL " . $hints['feedurl']);
- $oprofile = self::ensureFeedURL($hints['feedurl'], $hints);
- self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
- return $oprofile;
- } catch (Exception $e) {
- common_log(LOG_WARNING, "Failed creating profile from feed URL '$feedUrl': " . $e->getMessage());
- // keep looking
- }
- }
-
- // If we got a profile page, try that!
- if (array_key_exists('profileurl', $hints)) {
- try {
- common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
- $oprofile = self::ensureProfileURL($hints['profileurl'], $hints);
- self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
- return $oprofile;
- } catch (OStatusShadowException $e) {
- // We've ended up with a remote reference to a local user or group.
- // @fixme ideally we should be able to say who it was so we can
- // go back and refer to it the regular way
- throw $e;
- } catch (Exception $e) {
- common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
- // keep looking
- //
- // @fixme this means an error discovering from profile page
- // may give us a corrupt entry using the webfinger URI, which
- // will obscure the correct page-keyed profile later on.
- }
- }
- throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'),$addr));
- }
-}
-
-function pullOstatusProfile($uri) {
-
- $oprofile = null;
-
- if (Validate::email($uri)) {
- $oprofile = LooseOstatusProfile::updateWebfinger($uri);
- } else if (Validate::uri($uri)) {
- $oprofile = LooseOstatusProfile::updateProfileURL($uri);
- } else {
- print "Sorry, we could not reach the address: $uri\n";
- return false;
- }
-
- return $oprofile;
-}
-
-$quiet = have_option('q', 'quiet');
-
-$lop = new LooseOstatusProfile();
-
-if (have_option('u', 'uri')) {
- $lop->uri = get_option_value('u', 'uri');
-} else if (!have_option('a', 'all')) {
- show_help();
- exit(1);
-}
-
-$cnt = $lop->find();
-
-if (!empty($cnt)) {
- if (!$quiet) { echo "Found {$cnt} OStatus profiles:\n"; }
-} else {
- if (have_option('u', 'uri')) {
- if (!$quiet) { echo "Couldn't find an existing OStatus profile with that URI.\n"; }
- } else {
- if (!$quiet) { echo "Couldn't find any existing OStatus profiles.\n"; }
- }
- exit(0);
-}
-
-while($lop->fetch()) {
- if (!$quiet) { echo "Updating OStatus profile '{$lop->uri}' ... "; }
- try {
- $oprofile = pullOstatusProfile($lop->uri);
-
- if (!empty($oprofile)) {
- $orig = clone($lop);
- $lop->avatar = $oprofile->avatar;
- $lop->update($orig);
- $lop->updateAvatar($oprofile->avatar);
- if (!$quiet) { print "Done.\n"; }
- }
- } catch (Exception $e) {
- if (!$quiet) { print $e->getMessage() . "\n"; }
- common_log(LOG_WARN, $e->getMessage(), __FILE__);
- // continue on error
- }
-}
-
-if (!$quiet) { echo "OK.\n"; }
+++ /dev/null
-#!/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 = 'i:n:a';
-$longoptions = array('id=', 'nickname=', 'all');
-
-$helptext = <<<END_OF_UPDATEAVATARURL_HELP
-updateavatarurl.php [options]
-update the URLs of all avatars in the system
-
- -i --id ID of user to update
- -n --nickname nickname of the user to update
- -a --all update all
-
-END_OF_UPDATEAVATARURL_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-try {
- $user = null;
-
- if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
- $user = User::staticGet('id', $id);
- if (empty($user)) {
- throw new Exception("Can't find user with id '$id'.");
- }
- updateAvatars($user);
- } else if (have_option('n', 'nickname')) {
- $nickname = get_option_value('n', 'nickname');
- $user = User::staticGet('nickname', $nickname);
- if (empty($user)) {
- throw new Exception("Can't find user with nickname '$nickname'");
- }
- updateAvatars($user);
- } else if (have_option('a', 'all')) {
- $user = new User();
- if ($user->find()) {
- while ($user->fetch()) {
- updateAvatars($user);
- }
- }
- } else {
- show_help();
- exit(1);
- }
-} catch (Exception $e) {
- print $e->getMessage()."\n";
- exit(1);
-}
-
-function updateAvatars($user)
-{
- $touched = false;
-
- if (!have_option('q', 'quiet')) {
- print "Updating avatars for user '".$user->nickname."' (".$user->id.")...";
- }
-
- $avatar = new Avatar();
-
- $avatar->profile_id = $user->id;
-
- if (!$avatar->find()) {
- if (have_option('v', 'verbose')) {
- print "(none found)...";
- }
- } else {
- while ($avatar->fetch()) {
- if (have_option('v', 'verbose')) {
- if ($avatar->original) {
- print "original...";
- } else {
- print $avatar->width."...";
- }
- }
-
- $orig_url = $avatar->url;
-
- $avatar->url = Avatar::url($avatar->filename);
-
- if ($avatar->url != $orig_url) {
- $sql =
- "UPDATE avatar SET url = '" . $avatar->url . "' ".
- "WHERE profile_id = " . $avatar->profile_id . " ".
- "AND width = " . $avatar->width . " " .
- "AND height = " . $avatar->height . " ";
-
- if ($avatar->original) {
- $sql .= "AND original = 1 ";
- }
-
- if (!$avatar->query($sql)) {
- throw new Exception("Can't update avatar for user " . $user->nickname . ".");
- } else {
- $touched = true;
- }
- }
- }
- }
-
- if ($touched) {
- $profile = $user->getProfile();
- common_broadcast_profile($profile);
- }
-
- if (have_option('v', 'verbose')) {
- print "DONE.";
- }
- if (!have_option('q', 'quiet') || have_option('v', 'verbose')) {
- print "\n";
- }
-}
+++ /dev/null
-#!/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 = 'i:n:a';
-$longoptions = array('id=', 'nickname=', 'all');
-
-$helptext = <<<END_OF_UPDATEAVATARURL_HELP
-updateavatarurl_group.php [options]
-update the URLs of all group avatars in the system
-
- -i --id ID of group to update
- -n --nickname nickname of the group to update
- -a --all update all
-
-END_OF_UPDATEAVATARURL_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-try {
- $user = null;
-
- if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
- $group = User_group::staticGet('id', $id);
- if (empty($group)) {
- throw new Exception("Can't find group with id '$id'.");
- }
- updateGroupAvatars($group);
- } else if (have_option('n', 'nickname')) {
- $nickname = get_option_value('n', 'nickname');
- $group = User_group::staticGet('nickname', $nickname);
- if (empty($group)) {
- throw new Exception("Can't find group with nickname '$nickname'");
- }
- updateGroupAvatars($group);
- } else if (have_option('a', 'all')) {
- $group = new User_group();
- if ($group->find()) {
- while ($group->fetch()) {
- updateGroupAvatars($group);
- }
- }
- } else {
- show_help();
- exit(1);
- }
-} catch (Exception $e) {
- print $e->getMessage()."\n";
- exit(1);
-}
-
-function updateGroupAvatars($group)
-{
- if (!have_option('q', 'quiet')) {
- print "Updating avatars for group '".$group->nickname."' (".$group->id.")...";
- }
-
- if (empty($group->original_logo)) {
- print "(none found)...";
- } else {
- // Using clone here was screwing up the group->find() iteration
- $orig = User_group::staticGet('id', $group->id);
-
- $group->original_logo = Avatar::url(basename($group->original_logo));
- $group->homepage_logo = Avatar::url(basename($group->homepage_logo));
- $group->stream_logo = Avatar::url(basename($group->stream_logo));
- $group->mini_logo = Avatar::url(basename($group->mini_logo));
-
- if (!$group->update($orig)) {
- throw new Exception("Can't update avatars for group " . $group->nickname . ".");
- }
- }
-
- if (have_option('v', 'verbose')) {
- print "DONE.";
- }
- if (!have_option('q', 'quiet') || have_option('v', 'verbose')) {
- print "\n";
- }
-}
+++ /dev/null
-#!/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 = 'i:n:a';
-$longoptions = array('id=', 'nickname=', 'all');
-
-$helptext = <<<END_OF_UPDATEPROFILEURL_HELP
-updateprofileurl.php [options]
-update the URLs of all avatars in the system
-
- -i --id ID of user to update
- -n --nickname nickname of the user to update
- -a --all update all
-
-END_OF_UPDATEPROFILEURL_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-try {
- $user = null;
-
- if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
- $user = User::staticGet('id', $id);
- if (empty($user)) {
- throw new Exception("Can't find user with id '$id'.");
- }
- updateProfileURL($user);
- } else if (have_option('n', 'nickname')) {
- $nickname = get_option_value('n', 'nickname');
- $user = User::staticGet('nickname', $nickname);
- if (empty($user)) {
- throw new Exception("Can't find user with nickname '$nickname'");
- }
- updateProfileURL($user);
- } else if (have_option('a', 'all')) {
- $user = new User();
- if ($user->find()) {
- while ($user->fetch()) {
- updateProfileURL($user);
- }
- }
- } else {
- show_help();
- exit(1);
- }
-} catch (Exception $e) {
- print $e->getMessage()."\n";
- exit(1);
-}
-
-function updateProfileURL($user)
-{
- $profile = $user->getProfile();
-
- if (empty($profile)) {
- throw new Exception("Can't find profile for user $user->nickname ($user->id)");
- }
-
- $orig = clone($profile);
-
- $profile->profileurl = common_profile_url($user->nickname);
-
- if (!have_option('q', 'quiet')) {
- print "Updating profile url for $user->nickname ($user->id) ".
- "from $orig->profileurl to $profile->profileurl...";
- }
-
- $result = $profile->update($orig);
-
- if (!$result) {
- print "FAIL.\n";
- common_log_db_error($profile, 'UPDATE', __FILE__);
- throw new Exception("Can't update profile for user $user->nickname ($user->id)");
- }
-
- common_broadcast_profile($profile);
-
- print "OK.\n";
-}
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008-2011, 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 = '';
+$longoptions = array();
+
+$helptext = <<<END_OF_UPDATEURLS_HELP
+updateurls.php [options]
+update stored URLs in the system
+
+END_OF_UPDATEURLS_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+function main()
+{
+ updateUserUrls();
+ updateGroupUrls();
+}
+
+function updateUserUrls()
+{
+ printfnq("Updating user URLs...\n");
+
+ // XXX: only update user URLs where out-of-date
+
+ $user = new User();
+ if ($user->find()) {
+ while ($user->fetch()) {
+ printfv("Updating user {$user->nickname}...");
+ try {
+ $profile = $user->getProfile();
+
+ updateProfileUrl($profile);
+ updateAvatarUrls($profile);
+
+ // Broadcast for remote users
+
+ common_broadcast_profile($profile);
+
+ } catch (Exception $e) {
+ printv("Error updating URLs: " . $e->getMessage());
+ }
+ printfv("DONE.");
+ }
+ }
+}
+
+function updateProfileUrl($profile)
+{
+ $orig = clone($profile);
+ $profile->profileurl = common_profile_url($profile->nickname);
+ $profile->update($orig);
+}
+
+function updateAvatarUrls($profile)
+{
+ $avatar = new Avatar();
+
+ $avatar->profile_id = $profile->id;
+ if ($avatar->find()) {
+ while ($avatar->fetch()) {
+ $orig_url = $avatar->url;
+ $avatar->url = Avatar::url($avatar->filename);
+ if ($avatar->url != $orig_url) {
+ $sql =
+ "UPDATE avatar SET url = '" . $avatar->url . "' ".
+ "WHERE profile_id = " . $avatar->profile_id . " ".
+ "AND width = " . $avatar->width . " " .
+ "AND height = " . $avatar->height . " ";
+
+ if ($avatar->original) {
+ $sql .= "AND original = 1 ";
+ }
+
+ if (!$avatar->query($sql)) {
+ throw new Exception("Can't update avatar for user " . $profile->nickname . ".");
+ } else {
+ $touched = true;
+ }
+ }
+ }
+ }
+}
+
+function updateGroupUrls()
+{
+ printfnq("Updating group URLs...\n");
+
+ $group = new User_group();
+
+ if ($group->find()) {
+ while ($group->fetch()) {
+ try {
+ printfv("Updating group {$group->nickname}...");
+ $orig = User_group::staticGet('id', $group->id);
+ if (!empty($group->original_logo)) {
+ $group->original_logo = Avatar::url(basename($group->original_logo));
+ $group->homepage_logo = Avatar::url(basename($group->homepage_logo));
+ $group->stream_logo = Avatar::url(basename($group->stream_logo));
+ $group->mini_logo = Avatar::url(basename($group->mini_logo));
+ }
+ // XXX: this is a hack to see if a group is local or not
+ $localUri = common_local_url('groupbyid',
+ array('id' => $group->id));
+ if ($group->getUri() != $localUri) {
+ $group->mainpage = common_local_url('showgroup',
+ array('nickname' => $group->nickname));
+ }
+ $group->update($orig);
+ printfv("DONE.");
+ } catch (Exception $e) {
+ printv("Can't update avatars for group " . $group->nickname . ": ". $e->getMessage());
+ }
+ }
+ }
+}
+
+main();
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008-2011 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 = 'x::';
+$longoptions = array('extensions=');
+
+$helptext = <<<END_OF_UPGRADE_HELP
+php upgrade.php [options]
+Upgrade database schema and data to latest software
+
+END_OF_UPGRADE_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+function main()
+{
+ updateSchemaCore();
+ updateSchemaPlugins();
+
+ // These replace old "fixup_*" scripts
+
+ fixupNoticeRendered();
+ fixupNoticeConversation();
+ initConversation();
+ initInbox();
+ fixupGroupURI();
+ initLocalGroup();
+ initNoticeReshare();
+}
+
+function tableDefs()
+{
+ $schema = array();
+ require INSTALLDIR.'/db/core.php';
+ return $schema;
+}
+
+function updateSchemaCore()
+{
+ printfnq("Upgrading core schema...");
+
+ $schema = Schema::get();
+ $schemaUpdater = new SchemaUpdater($schema);
+ foreach (tableDefs() as $table => $def) {
+ $schemaUpdater->register($table, $def);
+ }
+ $schemaUpdater->checkSchema();
+
+ printfnq("DONE.\n");
+}
+
+function updateSchemaPlugins()
+{
+ printfnq("Upgrading plugin schema...");
+
+ Event::handle('CheckSchema');
+
+ printfnq("DONE.\n");
+}
+
+function fixupNoticeRendered()
+{
+ printfnq("Ensuring all notices have rendered HTML...");
+
+ $notice = new Notice();
+
+ $notice->whereAdd('rendered IS NULL');
+ $notice->find();
+
+ while ($notice->fetch()) {
+ $original = clone($notice);
+ $notice->rendered = common_render_content($notice->content, $notice);
+ $notice->update($original);
+ }
+
+ printfnq("DONE.\n");
+}
+
+function fixupNoticeConversation()
+{
+ printfnq("Ensuring all notices have a conversation ID...");
+
+ $notice = new Notice();
+ $notice->whereAdd('conversation is null');
+ $notice->orderBy('id'); // try to get originals before replies
+ $notice->find();
+
+ while ($notice->fetch()) {
+ try {
+ $cid = null;
+
+ $orig = clone($notice);
+
+ if (empty($notice->reply_to)) {
+ $notice->conversation = $notice->id;
+ } else {
+ $reply = Notice::staticGet('id', $notice->reply_to);
+
+ if (empty($reply)) {
+ $notice->conversation = $notice->id;
+ } else if (empty($reply->conversation)) {
+ $notice->conversation = $notice->id;
+ } else {
+ $notice->conversation = $reply->conversation;
+ }
+
+ unset($reply);
+ $reply = null;
+ }
+
+ $result = $notice->update($orig);
+
+ $orig = null;
+ unset($orig);
+ } catch (Exception $e) {
+ printv("Error setting conversation: " . $e->getMessage());
+ }
+ }
+
+ printfnq("DONE.\n");
+}
+
+function fixupGroupURI()
+{
+ printfnq("Ensuring all groups have an URI...");
+
+ $group = new User_group();
+ $group->whereAdd('uri IS NULL');
+
+ if ($group->find()) {
+ while ($group->fetch()) {
+ $orig = User_group::staticGet('id', $group->id);
+ $group->uri = $group->getUri();
+ $group->update($orig);
+ }
+ }
+
+ printfnq("DONE.\n");
+}
+
+function initConversation()
+{
+ printfnq("Ensuring all conversations have a row in conversation table...");
+
+ $notice = new Notice();
+ $notice->query('select distinct notice.conversation from notice '.
+ 'where notice.conversation is not null '.
+ 'and not exists (select conversation.id from conversation where id = notice.conversation)');
+
+ while ($notice->fetch()) {
+
+ $id = $notice->conversation;
+
+ $uri = common_local_url('conversation', array('id' => $id));
+
+ // @fixme db_dataobject won't save our value for an autoincrement
+ // so we're bypassing the insert wrappers
+ $conv = new Conversation();
+ $sql = "insert into conversation (id,uri,created) values(%d,'%s','%s')";
+ $sql = sprintf($sql,
+ $id,
+ $conv->escape($uri),
+ $conv->escape(common_sql_now()));
+ $conv->query($sql);
+ }
+
+ printfnq("DONE.\n");
+}
+
+function initInbox()
+{
+ printfnq("Ensuring all users have an inbox...");
+
+ $user = new User();
+ $user->whereAdd('not exists (select user_id from inbox where user_id = user.id)');
+ $user->orderBy('id');
+
+ if ($user->find()) {
+
+ while ($user->fetch()) {
+
+ try {
+ $notice = new Notice();
+
+ $notice->selectAdd();
+ $notice->selectAdd('id');
+ $notice->joinAdd(array('profile_id', 'subscription:subscribed'));
+ $notice->whereAdd('subscription.subscriber = ' . $user->id);
+ $notice->whereAdd('notice.created >= subscription.created');
+
+ $ids = array();
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ $ids[] = $notice->id;
+ }
+ }
+
+ $notice = null;
+
+ $inbox = new Inbox();
+ $inbox->user_id = $user->id;
+ $inbox->pack($ids);
+ $inbox->insert();
+ } catch (Exception $e) {
+ printv("Error initializing inbox: " . $e->getMessage());
+ }
+ }
+ }
+
+ printfnq("DONE.\n");
+}
+
+function initLocalGroup()
+{
+ printfnq("Ensuring all local user groups have a local_group...");
+
+ $group = new User_group();
+ $group->whereAdd('NOT EXISTS (select group_id from local_group where group_id = user_group.id)');
+ $group->find();
+
+ while ($group->fetch()) {
+ try {
+ // Hack to check for local groups
+ if ($group->getUri() == common_local_url('groupbyid', array('id' => $group->id))) {
+ $lg = new Local_group();
+
+ $lg->group_id = $group->id;
+ $lg->nickname = $group->nickname;
+ $lg->created = $group->created; // XXX: common_sql_now() ?
+ $lg->modified = $group->modified;
+
+ $lg->insert();
+ }
+ } catch (Exception $e) {
+ printfv("Error initializing local group for {$group->nickname}:" . $e->getMessage());
+ }
+ }
+
+ printfnq("DONE.\n");
+}
+
+function initNoticeReshare()
+{
+ printfnq("Ensuring all reshares have the correct verb and object-type...");
+
+ $notice = new Notice();
+ $notice->whereAdd('repeat_of is not null');
+ $notice->whereAdd('(verb != "'.ActivityVerb::SHARE.'" OR object_type != "'.ActivityObject::ACTIVITY.'")');
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ try {
+ $orig = Notice::staticGet('id', $notice->id);
+ $notice->verb = ActivityVerb::SHARE;
+ $notice->object_type = ActivityObject::ACTIVITY;
+ $notice->update($orig);
+ } catch (Exception $e) {
+ printfv("Error updating verb and object_type for {$notice->id}:" . $e->getMessage());
+ }
+ }
+ }
+
+ printfnq("DONE.\n");
+}
+
+main();