]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x
authorSarven Capadisli <csarven@status.net>
Wed, 24 Mar 2010 22:33:00 +0000 (23:33 +0100)
committerSarven Capadisli <csarven@status.net>
Wed, 24 Mar 2010 22:33:00 +0000 (23:33 +0100)
classes/Notice.php
lib/apiaction.php
plugins/OStatus/actions/usersalmon.php
plugins/OStatus/classes/Magicsig.php
plugins/OStatus/extlib/Math/BigInteger.php
plugins/OStatus/lib/magicenvelope.php
plugins/OStatus/lib/safecrypt_rsa.php [deleted file]
plugins/OStatus/lib/safemath_biginteger.php [deleted file]
plugins/OStatus/tests/remote-tests.php
scripts/fixup_deletions.php [new file with mode: 0755]

index f7194e3394ee893c24fd63a1f3c97a36093abd13..be3e9ca2a6721d69b38e960dbc406b44db97fa5d 100644 (file)
@@ -421,7 +421,9 @@ class Notice extends Memcached_DataObject
         }
 
         $profile = Profile::staticGet($this->profile_id);
-        $profile->blowNoticeCount();
+        if (!empty($profile)) {
+            $profile->blowNoticeCount();
+        }
     }
 
     /**
index e6aaf931618ec48ff037465b27faa5cd207ae2fb..9fc1a0779916d38722c65fee087998b5aff070d1 100644 (file)
@@ -1273,7 +1273,7 @@ class ApiAction extends Action
                 if (empty($local)) {
                     return null;
                 } else {
-                    return User_group::staticGet('id', $local->id);
+                    return User_group::staticGet('id', $local->group_id);
                 }
             }
 
index ecdcfa193994068cae0c9dda10cefb2c9cce6440..6c360c49f96c442ba4e40e8d820bcf78ed4e4457 100644 (file)
@@ -92,7 +92,7 @@ class UsersalmonAction extends SalmonAction
             throw new ClientException("Not to anyone in reply to anything!");
         }
 
-        $existing = Notice::staticGet('uri', $this->act->object->id);
+        $existing = Notice::staticGet('uri', $this->act->objects[0]->id);
 
         if (!empty($existing)) {
             common_log(LOG_ERR, "Not saving notice '{$existing->uri}'; already exists.");
@@ -143,7 +143,7 @@ class UsersalmonAction extends SalmonAction
 
     function handleFavorite()
     {
-        $notice = $this->getNotice($this->act->object);
+        $notice = $this->getNotice($this->act->objects[0]);
         $profile = $this->ensureProfile()->localProfile();
 
         $old = Fave::pkeyGet(array('user_id' => $profile->id,
@@ -164,7 +164,7 @@ class UsersalmonAction extends SalmonAction
      */
     function handleUnfavorite()
     {
-        $notice = $this->getNotice($this->act->object);
+        $notice = $this->getNotice($this->act->objects[0]);
         $profile = $this->ensureProfile()->localProfile();
 
         $fave = Fave::pkeyGet(array('user_id' => $profile->id,
index 87c684c93d87702eac562585797a0167070c4ad9..864fef62856ea45dc25381bebb81f0c197f157c7 100644 (file)
@@ -27,6 +27,8 @@
  * @link      http://status.net/
  */
 
+require_once 'Crypt/RSA.php';
+
 class Magicsig extends Memcached_DataObject
 {
 
@@ -50,7 +52,15 @@ class Magicsig extends Memcached_DataObject
     {
         $obj =  parent::staticGet(__CLASS__, $k, $v);
         if (!empty($obj)) {
-            return Magicsig::fromString($obj->keypair);
+            $obj = Magicsig::fromString($obj->keypair);
+
+            // Double check keys: Crypt_RSA did not
+            // consistently generate good keypairs.
+            // We've also moved to 1024 bit keys.
+            if (strlen($obj->publicKey->modulus->toBits()) != 1024) {
+                $obj->delete();
+                return false;
+            }
         }
 
         return $obj;
@@ -100,16 +110,16 @@ class Magicsig extends Memcached_DataObject
 
     public function generate($user_id)
     {
-        $rsa = new SafeCrypt_RSA();
+        $rsa = new Crypt_RSA();
         
         $keypair = $rsa->createKey();
 
         $rsa->loadKey($keypair['privatekey']);
 
-        $this->privateKey = new SafeCrypt_RSA();
+        $this->privateKey = new Crypt_RSA();
         $this->privateKey->loadKey($keypair['privatekey']);
 
-        $this->publicKey = new SafeCrypt_RSA();
+        $this->publicKey = new Crypt_RSA();
         $this->publicKey->loadKey($keypair['publickey']);
         
         $this->user_id = $user_id;
@@ -161,7 +171,7 @@ class Magicsig extends Memcached_DataObject
     {
         common_log(LOG_DEBUG, "Adding ".$type." key: (".$mod .', '. $exp .")");
 
-        $rsa = new SafeCrypt_RSA();
+        $rsa = new Crypt_RSA();
         $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
         $rsa->setHash('sha256');
         $rsa->modulus = new Math_BigInteger(base64_url_decode($mod), 256);
index 9733351d4220dc7eef8cc4c83294b55896605bb0..4373805f99c42b860bcc1463bd1ce04ffe4b421e 100644 (file)
@@ -67,7 +67,7 @@
  * @author     Jim Wigginton <terrafrost@php.net>
  * @copyright  MMVI Jim Wigginton
  * @license    http://www.gnu.org/licenses/lgpl.txt
- * @version    $Id: BigInteger.php,v 1.31 2010/03/01 17:28:19 terrafrost Exp $
+ * @version    $Id: BigInteger.php,v 1.33 2010/03/22 22:32:03 terrafrost Exp $
  * @link       http://pear.php.net/package/Math_BigInteger
  */
 
@@ -294,7 +294,7 @@ class Math_BigInteger {
                 $this->value = array();
         }
 
-        if ($x === 0) {
+        if (empty($x)) {
             return;
         }
 
@@ -718,7 +718,7 @@ class Math_BigInteger {
      *
      * Will be called, automatically, when serialize() is called on a Math_BigInteger object.
      *
-     * @see __wakeup
+     * @see __wakeup()
      * @access public
      */
     function __sleep()
@@ -740,7 +740,7 @@ class Math_BigInteger {
      *
      * Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
      *
-     * @see __sleep
+     * @see __sleep()
      * @access public
      */
     function __wakeup()
index 9266cab5cf40351de6f7949212fc10ec061a9645..799b5e307961a840fc04f8be975f2f67536d560d 100644 (file)
@@ -59,12 +59,21 @@ class MagicEnvelope
         }
         if ($xrd->links) {
             if ($link = Discovery::getService($xrd->links, Magicsig::PUBLICKEYREL)) {
-                list($type, $keypair) = explode(',', $link['href']);
-                if (empty($keypair)) {
+                $keypair = false;
+                $parts = explode(',', $link['href']);
+                if (count($parts) == 2) {
+                    $keypair = $parts[1];
+                } else {
                     // Backwards compatibility check for separator bug in 0.9.0
-                    list($type, $keypair) = explode(';', $link['href']);
+                    $parts = explode(';', $link['href']);
+                    if (count($parts) == 2) {
+                        $keypair = $parts[1];
+                    }
+                }
+                
+                if ($keypair) {
+                    return $keypair;
                 }
-                return $keypair;
             }
         }
         throw new Exception('Unable to locate signer public key');
diff --git a/plugins/OStatus/lib/safecrypt_rsa.php b/plugins/OStatus/lib/safecrypt_rsa.php
deleted file mode 100644 (file)
index f3aa2c9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-require_once 'Crypt/RSA.php';
-
-/**
- * Crypt_RSA stores a Math_BigInteger with value 0, which triggers a bug
- * in Math_BigInteger's wakeup function which spews notices to log or output.
- * This wrapper replaces it with a version that survives serialization.
- */
-class SafeCrypt_RSA extends Crypt_RSA
-{
-    function __construct()
-    {
-        parent::__construct();
-        $this->zero = new SafeMath_BigInteger();
-    }
-}
-
diff --git a/plugins/OStatus/lib/safemath_biginteger.php b/plugins/OStatus/lib/safemath_biginteger.php
deleted file mode 100644 (file)
index c05e24d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-require_once 'Math/BigInteger.php';
-
-/**
- * Crypt_RSA stores a Math_BigInteger with value 0, which triggers a bug
- * in Math_BigInteger's wakeup function which spews notices to log or output.
- * This wrapper replaces it with a version that survives serialization.
- */
-class SafeMath_BigInteger extends Math_BigInteger
-{
-    function __wakeup()
-    {
-        if ($this->hex == '') {
-            $this->hex = '0';
-        }
-        parent::__wakeup();
-    }
-}
-
index b064114911212580df7cece401e451c70e7d99b2..24b4b1660af84f2108cae8484815405919b17989 100644 (file)
@@ -75,11 +75,16 @@ class OStatusTester extends TestBase
     {
         $this->setup();
 
-        $this->testLocalPost();
-        $this->testMentionUrl();
-        $this->testSubscribe();
-        $this->testUnsubscribe();
+        $methods = get_class_methods($this);
+        foreach ($methods as $method) {
+            if (strtolower(substr($method, 0, 4)) == 'test') {
+                print "\n";
+                print "== $method ==\n";
+                call_user_func(array($this, $method));
+            }
+        }
 
+        print "\n";
         $this->log("DONE!");
     }
 
@@ -126,6 +131,26 @@ class OStatusTester extends TestBase
         $this->assertTrue($this->pub->hasSubscriber($this->sub->getProfileUri()));
     }
 
+    function testPush()
+    {
+        $this->assertTrue($this->sub->hasSubscription($this->pub->getProfileUri()));
+        $this->assertTrue($this->pub->hasSubscriber($this->sub->getProfileUri()));
+
+        $name = $this->sub->username;
+        $post = $this->pub->post("Regular post, which $name should get via PuSH");
+        $this->sub->assertReceived($post);
+    }
+
+    function testMentionSubscribee()
+    {
+        $this->assertTrue($this->sub->hasSubscription($this->pub->getProfileUri()));
+        $this->assertFalse($this->pub->hasSubscription($this->sub->getProfileUri()));
+
+        $name = $this->pub->username;
+        $post = $this->sub->post("Just a quick note back to my remote subscribee @$name");
+        $this->pub->assertReceived($post);
+    }
+
     function testUnsubscribe()
     {
         $this->assertTrue($this->sub->hasSubscription($this->pub->getProfileUri()));
@@ -350,6 +375,7 @@ class SNTestClient extends TestBase
         $this->assertEqual($this->fullname, $data['name']);
         $this->assertEqual($this->homepage, $data['url']);
         $this->assertEqual($this->bio, $data['description']);
+        $this->log("  looks good!");
     }
 
     /**
@@ -386,11 +412,11 @@ class SNTestClient extends TestBase
             }
             $tries--;
             if ($tries) {
-                $this->log("Didn't see it yet, waiting $timeout seconds");
+                $this->log("  didn't see it yet, waiting $timeout seconds");
                 sleep($timeout);
             }
         }
-        throw new Exception("Message $notice_uri not received by $this->username");
+        throw new Exception("  message $notice_uri not received by $this->username");
     }
 
     /**
@@ -420,10 +446,9 @@ class SNTestClient extends TestBase
         }
         foreach ($entries as $entry) {
             if ($entry->id == $notice_uri) {
-                $this->log("found it $notice_uri");
+                $this->log("  found it $notice_uri");
                 return true;
             }
-            //$this->log("nope... " . $entry->id);
         }
         return false;
     }
@@ -493,15 +518,15 @@ class SNTestClient extends TestBase
                 foreach ($follows as $follow) {
                     $target = $follow->getAttributeNS($ns_rdf, 'resource');
                     if ($target == ($subscribed . '#acct')) {
-                        $this->log("Confirmed $subscriber subscribed to $subscribed");
+                        $this->log("  confirmed $subscriber subscribed to $subscribed");
                         return true;
                     }
                 }
-                $this->log("We found $subscriber but they don't follow $subscribed");
+                $this->log("  we found $subscriber but they don't follow $subscribed");
                 return false;
             }
         }
-        $this->log("Can't find $subscriber in {$this->username}'s social graph.");
+        $this->log("  can't find $subscriber in {$this->username}'s social graph.");
         return false;
     }
 
diff --git a/scripts/fixup_deletions.php b/scripts/fixup_deletions.php
new file mode 100755 (executable)
index 0000000..07ada7f
--- /dev/null
@@ -0,0 +1,166 @@
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 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__) . '/..'));
+
+$longoptions = array('dry-run', 'start=', 'end=');
+
+$helptext = <<<END_OF_USERROLE_HELP
+fixup_deletions.php [options]
+Finds notices posted by deleted users and cleans them up.
+Stray incompletely deleted items cause various fun problems!
+
+     --dry-run  look but don't touch
+     --start=N  start looking at profile_id N instead of 1
+     --end=N    end looking at profile_id N instead of the max
+
+END_OF_USERROLE_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+/**
+ * Find the highest profile_id currently listed in the notice table;
+ * this field is indexed and should return very quickly.
+ *
+ * We check notice.profile_id rather than profile.id because we're
+ * looking for notices left behind after deletion; if the most recent
+ * accounts were deleted, we wouldn't have them from profile.
+ *
+ * @return int
+ * @access private
+ */
+function get_max_profile_id()
+{
+    $query = 'SELECT MAX(profile_id) AS id FROM notice';
+
+    $profile = new Profile();
+    $profile->query($query);
+
+    if ($profile->fetch()) {
+        return intval($profile->id);
+    } else {
+        die("Something went awry; could not look up max used profile_id.");
+    }
+}
+
+/**
+ * Check for profiles in the given id range that are missing, presumed deleted.
+ *
+ * @param int $start beginning profile.id, inclusive
+ * @param int $end final profile.id, inclusive
+ * @return array of integer profile.ids
+ * @access private
+ */
+function get_missing_profiles($start, $end)
+{
+    $query = sprintf("SELECT id FROM profile WHERE id BETWEEN %d AND %d",
+                     $start, $end);
+
+    $profile = new Profile();
+    $profile->query($query);
+
+    $all = range($start, $end);
+    $known = array();
+    while ($row = $profile->fetch()) {
+        $known[] = intval($profile->id);
+    }
+    unset($profile);
+
+    $missing = array_diff($all, $known);
+    return $missing;
+}
+
+/**
+ * Look for stray notices from this profile and, if present, kill them.
+ *
+ * @param int $profile_id
+ * @param bool $dry if true, we won't delete anything
+ */
+function cleanup_missing_profile($profile_id, $dry)
+{
+    $notice = new Notice();
+    $notice->profile_id = $profile_id;
+    $notice->find();
+    if ($notice->N == 0) {
+        return;
+    }
+
+    $s = ($notice->N == 1) ? '' : 's';
+    print "Deleted profile $profile_id has $notice->N stray notice$s:\n";
+
+    while ($notice->fetch()) {
+        print "  notice $notice->id";
+        if ($dry) {
+            print " (skipped; dry run)\n";
+        } else {
+            $victim = clone($notice);
+            try {
+                $victim->delete();
+                print " (deleted)\n";
+            } catch (Exception $e) {
+                print " FAILED: ";
+                print $e->getMessage();
+                print "\n";
+            }
+        }
+    }
+}
+
+$dry = have_option('dry-run');
+
+$max_profile_id = get_max_profile_id();
+$chunk = 1000;
+
+if (have_option('start')) {
+    $begin = intval(get_option_value('start'));
+} else {
+    $begin = 1;
+}
+if (have_option('end')) {
+    $final = min($max_profile_id, intval(get_option_value('end')));
+} else {
+    $final = $max_profile_id;
+}
+
+if ($begin < 1) {
+    die("Silly human, you can't begin before profile number 1!\n");
+}
+if ($final < $begin) {
+    die("Silly human, you can't end at $final if it's before $begin!\n");
+}
+
+// Identify missing profiles...
+for ($start = $begin; $start <= $final; $start += $chunk) {
+    $end = min($start + $chunk - 1, $final);
+
+    print "Checking for missing profiles between id $start and $end";
+    if ($dry) {
+        print " (dry run)";
+    }
+    print "...\n";
+    $missing = get_missing_profiles($start, $end);
+
+    foreach ($missing as $profile_id) {
+        cleanup_missing_profile($profile_id, $dry);
+    }
+}
+
+echo "done.\n";
+