code:
#!/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:e:';
$longoptions = array('id=', 'nickname=', 'email=');

$helptext = <<<END_OF_USEREMAIL_HELP
useremail.php [options]
Queries a user's registered email address, or queries the users with a given registered email.

  -i --id       id of the user to query
  -n --nickname nickname of the user to query
  -e --email    email address to query

END_OF_USEREMAIL_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

if (have_option('i', 'id')) {
    $id = get_option_value('i', 'id');
    $user = User::getKV('id', $id);
    if (empty($user)) {
        print "Can't find user with ID $id\n";
        exit(1);
    }
} else if (have_option('n', 'nickname')) {
    $nickname = get_option_value('n', 'nickname');
    $user = User::getKV('nickname', $nickname);
    if (empty($user)) {
        print "Can't find user with nickname '$nickname'\n";
        exit(1);
    }
}

if (!empty($user)) {
    if (empty($user->email)) {
        // Check for unconfirmed emails
        $unconfirmed_email = new Confirm_address();
        $unconfirmed_email->user_id = $user->id;
        $unconfirmed_email->address_type = 'email';
        $unconfirmed_email->find(true);

        if (empty($unconfirmed_email->address)) {
            print "No email registered for user '$user->nickname'\n";
        } else {
            print "Unconfirmed Adress: $unconfirmed_email->address\n";
        }
    } else {
        print "$user->email\n";
    }
    exit(0);
}

if (have_option('e', 'email')) {
    $user = new User();
    $user->email = get_option_value('e', 'email');
    $user->find(false);
    if (!$user->fetch()) {
        // Check unconfirmed emails
        $unconfirmed_email = new Confirm_address();
        $unconfirmed_email->address = $user->email;
        $unconfirmed_email->address_type = 'email';
        $unconfirmed_email->find(true);

        if (empty($unconfirmed_email->user_id)) {
            print "No users with email $user->email\n";
        } else {
            $user=User::getKV('id', $unconfirmed_email->user_id);
            print "Unconfirmed Address: $user->id $user->nickname\n";
        }
        exit(0);
    }
    do {
        print "$user->id $user->nickname\n";
    } while ($user->fetch());
} else {
    print "You must provide either an ID, email, or a nickname.\n";
    exit(1);
}


code:
#!/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:r:d';
$longoptions = array('id=', 'nickname=', 'role=', 'delete');

$helptext = <<<END_OF_USERROLE_HELP
userrole.php [options]
modifies a role for the given user

Available roles: owner moderator administrator sandboxed silenced deleted

  -d --delete   delete the role
  -i --id       ID of the user
  -n --nickname nickname of the user
  -r --role     role to add (or delete)

END_OF_USERROLE_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

if (have_option('i', 'id')) {
    $id = get_option_value('i', 'id');
    $profile = Profile::getKV('id', $id);
    if (empty($profile)) {
        print "Can't find user with ID $id\n";
        exit(1);
    }
} else if (have_option('n', 'nickname')) {
    $nickname = get_option_value('n', 'nickname');
    $user = User::getKV('nickname', $nickname);
    if (empty($user)) {
        print "Can't find user with nickname '$nickname'\n";
        exit(1);
    }
    $profile = $user->getProfile();
    if (empty($profile)) {
        print "User with ID $id has no profile\n";
        exit(1);
    }
} else {
    print "You must provide either an ID or a nickname.\n";
    exit(1);
}

$role = get_option_value('r', 'role');

if (empty($role)) {
    print "You must provide a role.\n";
    exit(1);
}

if (have_option('d', 'delete')) {
    print "Revoking role '$role' from user '$profile->nickname' ($profile->id)...";
    try {
        $profile->revokeRole($role);
        print "OK\n";
    } catch (Exception $e) {
        print "FAIL\n";
        print $e->getMessage();
        print "\n";
    }
} else {
    print "Granting role '$role' to user '$profile->nickname' ($profile->id)...";
    try {
        $profile->grantRole($role);
        print "OK\n";
    } catch (Exception $e) {
        print "FAIL\n";
        print $e->getMessage();
        print "\n";
    }
}

repo_name: RMichael/gnu

license: mit


code:
Initial simple way to Webfinger enable your domain -- needs PHP.
================================================================

This guide needs some updating, since it will only guide you to present
XML data (while the curl command likely gives you JSON). The workaround
is to simply make curl get 'webfinger.xml' instead, and/or have another
file that contains JSON, but that requires editing the PHP file as well.

Step 1
======

Put the 'dot-well-known' on your website, so it loads at:

     https://example.com/.well-known/

(Remember the . at the beginning of this one, which is common practice
for "hidden" files and why we have renamed it "dot-")

Step 2
======

Edit the .well-known/host-meta file and replace "example.com" with the
domain name you're hosting the .well-known directory on.

Using vim you can do this as a quick method:
    $ vim .well-known/host-meta [ENTER]
    :%s/example.com/domain.com/    [ENTER]
    :wq [ENTER]

Step 3
======

For each user on your site, and this might only be you...

In the webfinger directory, make a copy of the example@example.com.xml file
so that it's called (replace username and example.com with appropriate
values, the domain name should be the same as you're "socialifying"):

     username@example.com.xml

Then edit the file contents, replacing "social.example.com" with your
GNU social instance's base path, and change the user ID number (and
nickname for the FOAF link) to that of your account on your social
site. If you don't know your user ID number, you can see this on your
GNU social profile page by looking at the destination URLs in the
Feeds links.

PROTIP: You can get the bulk of the contents (note the <Subject> element though)
        from curling down your real webfinger data:
$ curl https://social.example.com/.well-known/webfinger?resource=acct:username@social.example.com

Finally
=======

Using this method, though fiddly, you can now be @user@domain without
the need for any prefixes for subdomains, etc.


code:
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0">
 <Link rel="lrdd" type="application/xrd+xml"
        template="https://example.com/.well-known/webfinger?resource={uri}"/>
</XRD>


code:
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
  <Subject>acct:username@example.com</Subject>
  <Alias>acct:username@social.example.com</Alias>
  <Alias>https://social.example.com/user/1</Alias>
  <Link rel="http://webfinger.net/rel/profile-page"
        type="text/html"
	href="https://social.example.com/user/1"/>

  <Link rel="http://schemas.google.com/g/2010#updates-from"
       type="application/atom+xml"
       href="https://social.example.com/api/statuses/user_timeline/1.atom"/>

  <!-- Is this/was this ever supported?
       <Link rel="http://microformats.org/profile/hcard"
       type="text/html"
       href="https://social.example.com/hcard"/> -->

  <Link rel="http://gmpg.org/xfn/11"
	type="text/html"
	href="https://social.example.com/user/1"/>

  <Link rel="describedby"
	type="application/rdf+xml"
	href="https://social.example.com/username/foaf"/>

  <Link rel="http://salmon-protocol.org/ns/salmon-replies"
	href="https://social.example.com/main/salmon/user/1"/>

  <Link rel="http://salmon-protocol.org/ns/salmon-mention"
	href="https://social.example.com/main/salmon/user/1"/>

  <Link rel="http://ostatus.org/schema/1.0/subscribe"
	template="https://social.example.com/main/ostatussub?profile={uri}"/>
</XRD>


code:
<?php

/*
 * GNU social
 * Copyright (C) 2010, Free Software Foundation, 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/>.
 */

// basename should make sure we can't escape this directory
$u = basename($_GET['resource']);

if (!strpos($u, '@')) {
    throw new Exception('Bad resource');
    exit(1);
}

if (mb_strpos($u, 'acct:')===0) {
    $u = substr($u, 5);
}

// Just to be a little bit safer, you know, with all the unicode stuff going on
$u = filter_var($u, FILTER_SANITIZE_EMAIL);

$f = $u . ".xml";

if (file_exists($f)) {
  header('Content-Disposition: attachment; filename="'.urlencode($f).'"');
  header('Content-type: application/xrd+xml');
  echo file_get_contents($f);
}


code:
<?php

if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
    print "This script must be run from the command line\n";
    exit();
}

// XXX: we should probably have some common source for this stuff

define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
define('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class ActivityGenerationTests extends PHPUnit_Framework_TestCase
{
    static $author1 = null;
    static $author2 = null;

    static $targetUser1 = null;
    static $targetUser2 = null;

    static $targetGroup1 = null;
    static $targetGroup2 = null;

    public static function setUpBeforeClass()
    {
        $authorNick1 = 'activitygenerationtestsuser' . common_random_hexstr(4);
        $authorNick2 = 'activitygenerationtestsuser' . common_random_hexstr(4);

        $targetNick1 = 'activitygenerationteststarget' . common_random_hexstr(4);
        $targetNick2 = 'activitygenerationteststarget' . common_random_hexstr(4);

        $groupNick1 = 'activitygenerationtestsgroup' . common_random_hexstr(4);
        $groupNick2 = 'activitygenerationtestsgroup' . common_random_hexstr(4);

        try{
        	self::$author1 = User::register(array('nickname' => $authorNick1,
                                              'email' => $authorNick1 . '@example.net',
                                              'email_confirmed' => true));

        	self::$author2 = User::register(array('nickname' => $authorNick2,
                                              'email' => $authorNick2 . '@example.net',
                                              'email_confirmed' => true));

        	self::$targetUser1 = User::register(array('nickname' => $targetNick1,
                                                  'email' => $targetNick1 . '@example.net',
                                                  'email_confirmed' => true));

        	self::$targetUser2 = User::register(array('nickname' => $targetNick2,
                                                  'email' => $targetNick2 . '@example.net',
                                                  'email_confirmed' => true));

        	self::$targetGroup1 = User_group::register(array('nickname' => $groupNick1,
                                                         'userid' => self::$author1->id,
                                                         'aliases' => array(),
                                                         'local' => true,
                                                         'location' => null,
                                                         'description' => null,
                                                         'fullname' => null,
                                                         'homepage' => null,
                                                         'mainpage' => null));
        	self::$targetGroup2 = User_group::register(array('nickname' => $groupNick2,
                                                         'userid' => self::$author1->id,
                                                         'aliases' => array(),
                                                         'local' => true,
                                                         'location' => null,
                                                         'description' => null,
                                                         'fullname' => null,
                                                         'homepage' => null,
                                                         'mainpage' => null));
        } catch (Exception $e) {
        	self::tearDownAfterClass();
        	throw $e;
        }
    }

    public function testBasicNoticeActivity()
    {
        $notice = $this->_fakeNotice();

        $entry = $notice->asAtomEntry(true);

        $element = $this->_entryToElement($entry, false);

        $this->assertEquals($notice->getUri(), ActivityUtils::childContent($element, 'id'));
        $this->assertEquals('New note by '. self::$author1->nickname, ActivityUtils::childContent($element, 'title'));
        $this->assertEquals($notice->rendered, ActivityUtils::childContent($element, 'content'));
        $this->assertEquals(strtotime($notice->created), strtotime(ActivityUtils::childContent($element, 'published')));
        $this->assertEquals(strtotime($notice->created), strtotime(ActivityUtils::childContent($element, 'updated')));
        $this->assertEquals(ActivityVerb::POST, ActivityUtils::childContent($element, 'verb', Activity::SPEC));
        $this->assertEquals(ActivityObject::NOTE, ActivityUtils::childContent($element, 'object-type', Activity::SPEC));
    }

    public function testNamespaceFlag()
    {
        $notice = $this->_fakeNotice();

        $entry = $notice->asAtomEntry(true);

        $element = $this->_entryToElement($entry, false);

        $this->assertTrue($element->hasAttribute('xmlns'));
        $this->assertTrue($element->hasAttribute('xmlns:thr'));
        $this->assertTrue($element->hasAttribute('xmlns:georss'));
        $this->assertTrue($element->hasAttribute('xmlns:activity'));
        $this->assertTrue($element->hasAttribute('xmlns:media'));
        $this->assertTrue($element->hasAttribute('xmlns:poco'));
        $this->assertTrue($element->hasAttribute('xmlns:ostatus'));
        $this->assertTrue($element->hasAttribute('xmlns:statusnet'));

        $entry = $notice->asAtomEntry(false);

        $element = $this->_entryToElement($entry, true);

        $this->assertFalse($element->hasAttribute('xmlns'));
        $this->assertFalse($element->hasAttribute('xmlns:thr'));
        $this->assertFalse($element->hasAttribute('xmlns:georss'));
        $this->assertFalse($element->hasAttribute('xmlns:activity'));
        $this->assertFalse($element->hasAttribute('xmlns:media'));
        $this->assertFalse($element->hasAttribute('xmlns:poco'));
        $this->assertFalse($element->hasAttribute('xmlns:ostatus'));
        $this->assertFalse($element->hasAttribute('xmlns:statusnet'));
    }

    public function testSourceFlag()
    {
        $notice = $this->_fakeNotice();

        // Test with no source

        $entry = $notice->asAtomEntry(false, false);

        $element = $this->_entryToElement($entry, true);

        $source = ActivityUtils::child($element, 'source');

        $this->assertNull($source);

        // Test with source

        $entry = $notice->asAtomEntry(false, true);

        $element = $this->_entryToElement($entry, true);

        $source = ActivityUtils::child($element, 'source');

        $this->assertNotNull($source);
    }

    public function testSourceContent()
    {
        $notice = $this->_fakeNotice();
        // make a time difference!
        sleep(2);
        $notice2 = $this->_fakeNotice();

        $entry = $notice->asAtomEntry(false, true);

        $element = $this->_entryToElement($entry, true);

        $source = ActivityUtils::child($element, 'source');

        $atomUrl = common_local_url('ApiTimelineUser', array('id' => self::$author1->id, 'format' => 'atom'));

        $profile = self::$author1->getProfile();

        $this->assertEquals($atomUrl, ActivityUtils::childContent($source, 'id'));
        $this->assertEquals($atomUrl, ActivityUtils::getLink($source, 'self', 'application/atom+xml'));
        $this->assertEquals($profile->profileurl, ActivityUtils::getPermalink($source));
        $this->assertEquals(strtotime($notice2->created), strtotime(ActivityUtils::childContent($source, 'updated')));
        // XXX: do we care here?
        $this->assertFalse(is_null(ActivityUtils::childContent($source, 'title')));
        $this->assertEquals(common_config('license', 'url'), ActivityUtils::getLink($source, 'license'));
    }

    public function testAuthorFlag()
    {
        $notice = $this->_fakeNotice();

        // Test with no author

        $entry = $notice->asAtomEntry(false, false, false);

        $element = $this->_entryToElement($entry, true);

        $this->assertNull(ActivityUtils::child($element, 'author'));
        $this->assertNull(ActivityUtils::child($element, 'actor', Activity::SPEC));

        // Test with source

        $entry = $notice->asAtomEntry(false, false, true);

        $element = $this->_entryToElement($entry, true);

        $author = ActivityUtils::child($element, 'author');
        $actor  = ActivityUtils::child($element, 'actor', Activity::SPEC);

        $this->assertFalse(is_null($author));
        $this->assertTrue(is_null($actor)); // <activity:actor> is obsolete, no longer added
    }

    public function testAuthorContent()
    {
        $notice = $this->_fakeNotice();

        // Test with author

        $entry = $notice->asAtomEntry(false, false, true);

        $element = $this->_entryToElement($entry, true);

        $author = ActivityUtils::child($element, 'author');

        $this->assertEquals(self::$author1->getNickname(), ActivityUtils::childContent($author, 'name'));
        $this->assertEquals(self::$author1->getUri(), ActivityUtils::childContent($author, 'uri'));
    }

    /**
     * We no longer create <activity:actor> entries, they have merged to <atom:author>
     */
    public function testActorContent()
    {
        $notice = $this->_fakeNotice();

        // Test with author

        $entry = $notice->asAtomEntry(false, false, true);

        $element = $this->_entryToElement($entry, true);

        $actor = ActivityUtils::child($element, 'actor', Activity::SPEC);

        $this->assertEquals($actor, null);
    }

    public function testReplyLink()
    {
        $orig = $this->_fakeNotice(self::$targetUser1);

        $text = "@" . self::$targetUser1->nickname . " reply text " . common_random_hexstr(4);

        $reply = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null, 'reply_to' => $orig->id));

        $entry = $reply->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $irt = ActivityUtils::child($element, 'in-reply-to', 'http://purl.org/syndication/thread/1.0');

        $this->assertNotNull($irt);
        $this->assertEquals($orig->getUri(), $irt->getAttribute('ref'));
        $this->assertEquals($orig->getUrl(), $irt->getAttribute('href'));
    }

    public function testReplyAttention()
    {
        $orig = $this->_fakeNotice(self::$targetUser1);

        $text = "@" . self::$targetUser1->nickname . " reply text " . common_random_hexstr(4);

        $reply = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null, 'reply_to' => $orig->id));

        $entry = $reply->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $this->assertEquals(self::$targetUser1->getUri(), ActivityUtils::getLink($element, 'mentioned'));
    }

    public function testMultipleReplyAttention()
    {
        $orig = $this->_fakeNotice(self::$targetUser1);

        $text = "@" . self::$targetUser1->nickname . " reply text " . common_random_hexstr(4);

        $reply = Notice::saveNew(self::$targetUser2->id, $text, 'test', array('uri' => null, 'reply_to' => $orig->id));

        $text = "@" . self::$targetUser1->nickname . " @" . self::$targetUser2->nickname . " reply text " . common_random_hexstr(4);

        $reply2 = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null, 'reply_to' => $reply->id));

        $entry = $reply2->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $links = ActivityUtils::getLinks($element, 'mentioned');

        $hrefs = array();

        foreach ($links as $link) {
            $hrefs[] = $link->getAttribute('href');
        }

        $this->assertTrue(in_array(self::$targetUser1->getUri(), $hrefs));
        $this->assertTrue(in_array(self::$targetUser2->getUri(), $hrefs));
    }

    public function testGroupPostAttention()
    {
        $text = "!" . self::$targetGroup1->nickname . " reply text " . common_random_hexstr(4);

        $notice = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null));

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $this->assertEquals(self::$targetGroup1->getUri(), ActivityUtils::getLink($element, 'mentioned'));
    }

    public function testMultipleGroupPostAttention()
    {
        $text = "!" . self::$targetGroup1->nickname . " !" . self::$targetGroup2->nickname . " reply text " . common_random_hexstr(4);

        $notice = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null));

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $links = ActivityUtils::getLinks($element, 'mentioned');

        $hrefs = array();

        foreach ($links as $link) {
            $hrefs[] = $link->getAttribute('href');
        }

        $this->assertTrue(in_array(self::$targetGroup1->getUri(), $hrefs));
        $this->assertTrue(in_array(self::$targetGroup2->getUri(), $hrefs));

    }

    public function testRepeatLink()
    {
        $notice = $this->_fakeNotice(self::$author1);
        $repeat = $notice->repeat(self::$author2->getProfile(), 'test');

        $entry = $repeat->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', 'http://status.net/schema/api/1/');

        $this->assertNotNull($noticeInfo);
        $this->assertEquals($notice->id, $noticeInfo->getAttribute('repeat_of'));
        $this->assertEquals($repeat->id, $noticeInfo->getAttribute('local_id'));
    }

    public function testTag()
    {
        $tag1 = common_random_hexstr(4);

        $notice = $this->_fakeNotice(self::$author1, '#' . $tag1);

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $category = ActivityUtils::child($element, 'category');

        $this->assertNotNull($category);
        $this->assertEquals($tag1, $category->getAttribute('term'));
    }

    public function testMultiTag()
    {
        $tag1 = common_random_hexstr(4);
        $tag2 = common_random_hexstr(4);

        $notice = $this->_fakeNotice(self::$author1, '#' . $tag1 . ' #' . $tag2);

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $categories = $element->getElementsByTagName('category');

        $this->assertNotNull($categories);
        $this->assertEquals(2, $categories->length);

        $terms = array();

        for ($i = 0; $i < $categories->length; $i++) {
            $cat = $categories->item($i);
            $terms[] = $cat->getAttribute('term');
        }

        $this->assertTrue(in_array($tag1, $terms));
        $this->assertTrue(in_array($tag2, $terms));
    }

    public function testGeotaggedActivity()
    {
        $notice = Notice::saveNew(self::$author1->id, common_random_hexstr(4), 'test', array('uri' => null, 'lat' => 45.5, 'lon' => -73.6));

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $this->assertEquals('45.5000000 -73.6000000', ActivityUtils::childContent($element, 'point', "http://www.georss.org/georss"));
    }

    public function testNoticeInfo()
    {
        $notice = $this->_fakeNotice();

        $entry = $notice->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals($notice->id, $noticeInfo->getAttribute('local_id'));
        $this->assertEquals($notice->source, $noticeInfo->getAttribute('source'));
        $this->assertEquals('', $noticeInfo->getAttribute('repeat_of'));
        $this->assertEquals('', $noticeInfo->getAttribute('repeated'));
//        $this->assertEquals('', $noticeInfo->getAttribute('favorite'));
        $this->assertEquals('', $noticeInfo->getAttribute('source_link'));
    }

    public function testNoticeInfoRepeatOf()
    {
        $notice = $this->_fakeNotice();

        $repeat = $notice->repeat(self::$author2->getProfile(), 'test');

        $entry = $repeat->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals($notice->id, $noticeInfo->getAttribute('repeat_of'));
    }

    public function testNoticeInfoRepeated()
    {
        $notice = $this->_fakeNotice();

        $repeat = $notice->repeat(self::$author2->getProfile(), 'test');

        $entry = $notice->asAtomEntry(false, false, false, self::$author2->getProfile());

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals('true', $noticeInfo->getAttribute('repeated'));

        $entry = $notice->asAtomEntry(false, false, false, self::$targetUser1->getProfile());

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals('false', $noticeInfo->getAttribute('repeated'));
    }

/*    public function testNoticeInfoFave()
    {
        $notice = $this->_fakeNotice();

        $fave = Fave::addNew(self::$author2->getProfile(), $notice);

        // Should be set if user has faved

        $entry = $notice->asAtomEntry(false, false, false, self::$author2);

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals('true', $noticeInfo->getAttribute('favorite'));

        // Shouldn't be set if user has not faved

        $entry = $notice->asAtomEntry(false, false, false, self::$targetUser1);

        $element = $this->_entryToElement($entry, true);

        $noticeInfo = ActivityUtils::child($element, 'notice_info', "http://status.net/schema/api/1/");

        $this->assertEquals('false', $noticeInfo->getAttribute('favorite'));
    }*/

    public function testConversationLink()
    {
        $orig = $this->_fakeNotice(self::$targetUser1);

        $text = "@" . self::$targetUser1->nickname . " reply text " . common_random_hexstr(4);

        $reply = Notice::saveNew(self::$author1->id, $text, 'test', array('uri' => null, 'reply_to' => $orig->id));

        $conv = Conversation::getKV('id', $reply->conversation);

        $entry = $reply->asAtomEntry();

        $element = $this->_entryToElement($entry, true);

        $this->assertEquals($conv->getUrl(), ActivityUtils::getLink($element, 'ostatus:conversation'));
    }

    public static function tearDownAfterClass()
    {
        if (!is_null(self::$author1)) {
            self::$author1->getProfile()->delete();
        }

        if (!is_null(self::$author2)) {
            self::$author2->getProfile()->delete();
        }

        if (!is_null(self::$targetUser1)) {
            self::$targetUser1->getProfile()->delete();
        }

        if (!is_null(self::$targetUser2)) {
            self::$targetUser2->getProfile()->delete();
        }

        if (!is_null(self::$targetGroup1)) {
            self::$targetGroup1->delete();
        }

        if (!is_null(self::$targetGroup2)) {
            self::$targetGroup2->delete();
        }
    }

    private function _fakeNotice($user = null, $text = null)
    {
        if (empty($user)) {
            $user = self::$author1;
        }

        if (empty($text)) {
            $text = "fake-o text-o " . common_random_hexstr(32);
        }

        return Notice::saveNew($user->id, $text, 'test', array('uri' => null));
    }

    private function _entryToElement($entry, $namespace = false)
    {
        $xml = '<?xml version="1.0" encoding="utf-8"?>'."\n\n";
        $xml .= '<feed';
        if ($namespace) {
            $xml .= ' xmlns="http://www.w3.org/2005/Atom"';
            $xml .= ' xmlns:thr="http://purl.org/syndication/thread/1.0"';
            $xml .= ' xmlns:georss="http://www.georss.org/georss"';
            $xml .= ' xmlns:activity="http://activitystrea.ms/spec/1.0/"';
            $xml .= ' xmlns:media="http://purl.org/syndication/atommedia"';
            $xml .= ' xmlns:poco="http://portablecontacts.net/spec/1.0"';
            $xml .= ' xmlns:ostatus="http://ostatus.org/schema/1.0"';
            $xml .= ' xmlns:statusnet="http://status.net/schema/api/1/"';
        }
        $xml .= '>' . "\n" . $entry . "\n" . '</feed>' . "\n";
        $doc = DOMDocument::loadXML($xml);
        $feed = $doc->documentElement;
        $entries = $feed->getElementsByTagName('entry');

        return $entries->item(0);
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class CommandInterpreterTest extends PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider commandInterpreterCases
     */
    public function testCommandInterpreter($input, $expectedType, $comment='')
    {
        $inter = new CommandInterpreter();

        $cmd = $inter->handle_command(null, $input);

        $type = $cmd ? get_class($cmd) : null;
        $this->assertEquals(strtolower($expectedType), strtolower($type), $comment);
    }

    static public function commandInterpreterCases()
    {
        $sets = array(
            array('help', 'HelpCommand'),
            array('help me bro', null, 'help does not accept multiple params'),
            array('HeLP', 'HelpCommand', 'case check'),
            array('HeLP Me BRO!', null, 'case & non-params check'),

            array('login', 'LoginCommand'),
            array('login to savings!', null, 'login does not accept params'),

            array('lose', null, 'lose must have at least 1 parameter'),
            array('lose foobar', 'LoseCommand', 'lose requires 1 parameter'),
            array('lose        foobar', 'LoseCommand', 'check for space norm'),
            array('lose more weight', null, 'lose does not accept multiple params'),

            array('subscribers', 'SubscribersCommand'),
            array('subscribers foo', null, 'subscribers does not take params'),

            array('subscriptions', 'SubscriptionsCommand'),
            array('subscriptions foo', null, 'subscriptions does not take params'),

            array('groups', 'GroupsCommand'),
            array('groups foo', null, 'groups does not take params'),

            array('off', 'OffCommand', 'off accepts 0 or 1 params'),
            array('off foo', 'OffCommand', 'off accepts 0 or 1 params'),
            array('off foo bar', null, 'off accepts 0 or 1 params'),

            array('stop', 'OffCommand', 'stop accepts 0 params'),
            array('stop foo', null, 'stop accepts 0 params'),

            array('quit', 'OffCommand', 'quit accepts 0 params'),
            array('quit foo', null, 'quit accepts 0 params'),

            array('on', 'OnCommand', 'on accepts 0 or 1 params'),
            array('on foo', 'OnCommand', 'on accepts 0 or 1 params'),
            array('on foo bar', null, 'on accepts 0 or 1 params'),

            array('join', null),
            array('join foo', 'JoinCommand'),
            array('join foo bar', null),

            array('drop', null),
            array('drop foo', 'DropCommand'),
            array('drop foo bar', null),

            array('follow', null),
            array('follow foo', 'SubCommand'),
            array('follow foo bar', null),

            array('sub', null),
            array('sub foo', 'SubCommand'),
            array('sub foo bar', null),

            array('leave', null),
            array('leave foo', 'UnsubCommand'),
            array('leave foo bar', null),

            array('unsub', null),
            array('unsub foo', 'UnsubCommand'),
            array('unsub foo bar', null),

            array('leave', null),
            array('leave foo', 'UnsubCommand'),
            array('leave foo bar', null),

            array('d', null),
            array('d foo', null),
            array('d foo bar', 'MessageCommand'),

            array('dm', null),
            array('dm foo', null),
            array('dm foo bar', 'MessageCommand'),

            array('r', null),
            array('r foo', null),
            array('r foo bar', 'ReplyCommand'),

            array('reply', null),
            array('reply foo', null),
            array('reply foo bar', 'ReplyCommand'),

            array('repeat', null),
            array('repeat foo', 'RepeatCommand'),
            array('repeat foo bar', null),

            array('rp', null),
            array('rp foo', 'RepeatCommand'),
            array('rp foo bar', null),

            array('rt', null),
            array('rt foo', 'RepeatCommand'),
            array('rt foo bar', null),

            array('rd', null),
            array('rd foo', 'RepeatCommand'),
            array('rd foo bar', null),

            array('whois', null),
            array('whois foo', 'WhoisCommand'),
            array('whois foo bar', null),

/*            array('fav', null),
            array('fav foo', 'FavCommand'),
            array('fav foo bar', null),*/

            array('nudge', null),
            array('nudge foo', 'NudgeCommand'),
            array('nudge foo bar', null),

            array('stats', 'StatsCommand'),
            array('stats foo', null),

            array('invite', null),
            array('invite foo', 'InviteCommand'),
            array('invite foo bar', null),

            array('track', null),
            array('track foo', 'SearchSubTrackCommand'),
            array('track off', 'SearchSubTrackOffCommand'),
            array('track foo bar', null),
            array('track off foo', null),

            array('untrack', null),
            array('untrack foo', 'SearchSubUntrackCommand'),
            array('untrack all', 'SearchSubTrackOffCommand'),
            array('untrack foo bar', null),
            array('untrack all foo', null),

            array('tracking', 'SearchSubTrackingCommand'),
            array('tracking foo', null),

            array('tracks', 'SearchSubTrackingCommand'),
            array('tracks foo', null),

        );
        return $sets;
    }

}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class CurryTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     *
     */
    public function testProduction($callback, $curry_params, $call_params, $expected)
    {
        $params = array_merge(array($callback), $curry_params);
        $curried = call_user_func_array('curry', $params);
        $result = call_user_func_array($curried, $call_params);
        $this->assertEquals($expected, $result);
    }

    static public function provider()
    {
        $obj = new CurryTestHelperObj('oldval');
        return array(array(array('CurryTest', 'callback'),
                           array('curried'),
                           array('called'),
                           'called|curried'),
                     array(array('CurryTest', 'callback'),
                           array('curried1', 'curried2'),
                           array('called1', 'called2'),
                           'called1|called2|curried1|curried2'),
                     array(array('CurryTest', 'callbackObj'),
                           array($obj),
                           array('newval1'),
                           'oldval|newval1'),
                     // Confirm object identity is retained...
                     array(array('CurryTest', 'callbackObj'),
                           array($obj),
                           array('newval2'),
                           'newval1|newval2'));
    }

    static function callback()
    {
        $args = func_get_args();
        return implode("|", $args);
    }

    static function callbackObj($val, $obj)
    {
        $old = $obj->val;
        $obj->val = $val;
        return "$old|$val";
    }
}

class CurryTestHelperObj
{
    public $val='';

    function __construct($val)
    {
        $this->val = $val;
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class HashTagDetectionTests extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     *
     */
    public function testProduction($content, $expected)
    {
        $rendered = common_render_text($content);
        $this->assertEquals($expected, $rendered);
    }

    static public function provider()
    {
        return array(
                     array('hello',
                           'hello'),
                     array('#hello people',
                           '# common_canonical_tag('hello'))) . '" rel="tag">hello people'),
                     array('"#hello" people',
                           '"# common_canonical_tag('hello'))) . '" rel="tag">hello" people'),
                     array('say "#hello" people',
                           'say "# common_canonical_tag('hello'))) . '" rel="tag">hello" people'),
                     array('say (#hello) people',
                           'say (# common_canonical_tag('hello'))) . '" rel="tag">hello) people'),
                     array('say [#hello] people',
                           'say [# common_canonical_tag('hello'))) . '" rel="tag">hello] people'),
                     array('say {#hello} people',
                           'say {# common_canonical_tag('hello'))) . '" rel="tag">hello} people'),
                     array('say \'#hello\' people',
                           'say \'# common_canonical_tag('hello'))) . '" rel="tag">hello\' people'),

                     // Unicode legit letters
                     array('#éclair yummy',
                           '# common_canonical_tag('éclair'))) . '" rel="tag">éclair yummy'),
                     array('#维基百科 zh.wikipedia!',
                           '# common_canonical_tag('维基百科'))) . '" rel="tag">维基百科 zh.wikipedia!'),
                     array('#Россия russia',
                           '# common_canonical_tag('Россия'))) . '" rel="tag">Россия russia'),

                     // Unicode punctuators -- the ideographic "，" separates the tag, just as "," does
                     array('#维基百科,zh.wikipedia!',
                           '# common_canonical_tag('维基百科'))) . '" rel="tag">维基百科,zh.wikipedia!'),
                     array('#维基百科，zh.wikipedia!',
                           '# common_canonical_tag('维基百科'))) . '" rel="tag">维基百科，zh.wikipedia!'),

                     );
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

// Make sure this is loaded
// XXX: how to test other plugins...?

addPlugin('Geonames');

class LocationTest extends PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider locationNames
     */

    public function testLocationFromName($name, $language, $location)
    {
        $result = Location::fromName($name, $language);
        $this->assertEquals($result, $location);
    }

    static public function locationNames()
    {
        return array(array('Montreal', 'en', null),
                     array('San Francisco, CA', 'en', null),
                     array('Paris, France', 'en', null),
                     array('Paris, Texas', 'en', null));
    }

    /**
     * @dataProvider locationIds
     */

    public function testLocationFromId($id, $ns, $language, $location)
    {
        $result = Location::fromId($id, $ns, $language);
        $this->assertEquals($result, $location);
    }

    static public function locationIds()
    {
        return array(array(6077243, GeonamesPlugin::LOCATION_NS, 'en', null),
                     array(5391959, GeonamesPlugin::LOCATION_NS, 'en', null));
    }

    /**
     * @dataProvider locationLatLons
     */

    public function testLocationFromLatLon($lat, $lon, $language, $location)
    {
        $result = Location::fromLatLon($lat, $lon, $language);
        $this->assertEquals($location, $result->location_id);
    }

    static public function locationLatLons()
    {
        return array(array(37.77493, -122.41942, 'en', null),
                     array(45.509, -73.588, 'en', null));
    }

    /**
     * @dataProvider nameOfLocation
     */

    public function testLocationGetName($location, $language, $name)
    {
        $result = empty($location)?null:$location->getName($language);
        $this->assertEquals($name, $result);
    }

    static public function nameOfLocation()
    {
        $loc = Location::fromName('Montreal', 'en');
        return array(array($loc, 'en', null), //'Montreal'),
                     array($loc, 'fr', null));//'Montréal'));
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class MediaFileTest extends PHPUnit_Framework_TestCase
{

    public function setup()
    {
        $this->old_attachments_supported = common_config('attachments', 'supported');
        $GLOBALS['config']['attachments']['supported'] = true;
    }

    public function tearDown()
    {
        $GLOBALS['config']['attachments']['supported'] = $this->old_attachments_supported;
    }

    /**
     * @dataProvider fileTypeCases
     *
     */
    public function testMimeType($filename, $expectedType)
    {
        if (!file_exists($filename)) {
            throw new Exception("Test file $filename missing");
        }

        $type = MediaFile::getUploadedMimeType($filename, basename($filename));
        $this->assertEquals($expectedType, $type);
    }

    /**
     * @dataProvider fileTypeCases
     *
     */
    public function testUploadedMimeType($filename, $expectedType)
    {
        if (!file_exists($filename)) {
            throw new Exception("WTF? $filename test file missing");
        }
        $tmp = tmpfile();
        fwrite($tmp, file_get_contents($filename));

        $tmp_metadata = stream_get_meta_data($tmp);
        $type = MediaFile::getUploadedMimeType($tmp_metadata['uri'], basename($filename));
        $this->assertEquals($expectedType, $type);
    }

    static public function fileTypeCases()
    {
        $base = dirname(__FILE__);
        $dir = "$base/sample-uploads";
        $files = array(
            "image.png" => "image/png",
            "image.gif" => "image/gif",
            "image.jpg" => "image/jpeg",
            "image.jpeg" => "image/jpeg",

            "office.pdf" => "application/pdf",

            "wordproc.odt" => "application/vnd.oasis.opendocument.text",
            "wordproc.ott" => "application/vnd.oasis.opendocument.text-template",
            "wordproc.doc" => "application/msword",
            "wordproc.docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "wordproc.rtf" => "text/rtf",

            "spreadsheet.ods" => "application/vnd.oasis.opendocument.spreadsheet",
            "spreadsheet.ots" => "application/vnd.oasis.opendocument.spreadsheet-template",
            "spreadsheet.xls" => "application/vnd.ms-office", //"application/vnd.ms-excel",
            "spreadsheet.xlt" => "application/vnd.ms-office", //"application/vnd.ms-excel",
            "spreadsheet.xlsx" => "application/octet-stream", //"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",

            "presentation.odp" => "application/vnd.oasis.opendocument.presentation",
            "presentation.otp" => "application/vnd.oasis.opendocument.presentation-template",
            "presentation.ppt" => "application/vnd.ms-powerpoint",
            "presentation.pptx" => 'application/zip', //"application/vnd.openxmlformats-officedocument.presentationml.presentation",
        );

        $dataset = array();
        foreach ($files as $file => $type) {
            $dataset[] = array("$dir/$file", $type);
        }
        return $dataset;
    }

}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

/**
 * Test cases for nickname validity and normalization.
 */
class NicknameTest extends PHPUnit_Framework_TestCase
{
    /**
     * Basic test using Nickname::normalize()
     *
     * @dataProvider provider
     */
    public function testBasic($input, $expected, $expectedException=null)
    {
        $exception = null;
        $normalized = false;
        try {
            $normalized = Nickname::normalize($input);
        } catch (NicknameException $e) {
            $exception = $e;
        }

        if ($expected === false) {
            if ($expectedException) {
                if ($exception) {
                    $stuff = get_class($exception) . ': ' . $exception->getMessage();
                } else {
                    $stuff = var_export($exception, true);
                }
                $this->assertTrue($exception && $exception instanceof $expectedException,
                        "invalid input '$input' expected to fail with $expectedException, " .
                        "got $stuff");
            } else {
                $this->assertTrue($normalized == false,
                        "invalid input '$input' expected to fail");
            }
        } else {
            $msg = "normalized input nickname '$input' expected to normalize to '$expected', got ";
            if ($exception) {
                $msg .= get_class($exception) . ': ' . $exception->getMessage();
            } else {
                $msg .= "'$normalized'";
            }
            $this->assertEquals($expected, $normalized, $msg);
        }
    }

    /**
     * Test on the regex matching used in common_find_mentions
     * (testing on the full notice rendering is difficult as it needs
     * to be able to pull from global state)
     *
     * @dataProvider provider
     */
    public function testAtReply($input, $expected, $expectedException=null)
    {
        if ($expected == false) {
            // nothing to do
        } else {
            $text = "@{$input} awesome! :)";
            $matches = common_find_mentions_raw($text);
            $this->assertEquals(1, count($matches));
            $this->assertEquals($expected, Nickname::normalize($matches[0][0]));
        }
    }

    static public function provider()
    {
        return array(
                     array('evan', 'evan'),

                     // Case and underscore variants
                     array('Evan', 'evan'),
                     array('EVAN', 'evan'),
                     array('ev_an', 'evan'),
                     array('E__V_an', 'evan'),
                     array('evan1', 'evan1'),
                     array('evan_1', 'evan1'),
                     array('0x20', '0x20'),
                     array('1234', '1234'), // should this be allowed though? :)
                     array('12__34', '1234'),

                     // Some (currently) invalid chars...
                     array('^#@&^#@', false, 'NicknameInvalidException'), // all invalid :D
                     array('ev.an', false, 'NicknameInvalidException'),
                     array('ev/an', false, 'NicknameInvalidException'),
                     array('ev an', false, 'NicknameInvalidException'),
                     array('ev-an', false, 'NicknameInvalidException'),

                     // Non-ASCII letters; currently not allowed, in future
                     // we'll add them at least with conversion to ASCII.
                     // Not much use until we have storage of display names,
                     // though.
                     array('évan', false, 'NicknameInvalidException'), // so far...
                     array('Évan', false, 'NicknameInvalidException'), // so far...

                     // Length checks
                     array('', false, 'NicknameEmptyException'),
                     array('___', false, 'NicknameEmptyException'),
                     array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'), // 64 chars
                     array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_', false, 'NicknameTooLongException'), // the _ is too long...
                     array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', false, 'NicknameTooLongException'), // 65 chars -- too long
                     );
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

$config['site']['server'] = 'example.net';
$config['site']['path']   = '/apps/statusnet';

class TagURITest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     */
    public function testProduction($format, $args, $uri)
    {
        $minted = call_user_func_array(array('TagURI', 'mint'),
                                       array_merge(array($format), $args));

        $this->assertEquals($uri, $minted);
    }

    static public function provider()
    {
        return array(array('favorite:%d:%d',
                           array(1, 3),
                           'tag:example.net,'.date('Y-m-d').':apps:statusnet:favorite:1:3'));
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class URLDetectionTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     *
     */
    public function testProduction($content, $expected)
    {
        $rendered = common_render_text($content);
        // hack!
        $rendered = preg_replace('/id="attachment-\d+"/', 'id="attachment-XXX"', $rendered);
        $this->assertEquals($expected, $rendered);
    }

    /**
     * @dataProvider linkifyProvider
     *
     */
    public function testLinkifyProduction($content, $expected, $config)
    {
        $rendered = common_render_text($content);
        // hack!
        $rendered = preg_replace('/id="attachment-\d+"/', 'id="attachment-XXX"', $rendered);
        if(common_config('linkify', $config)){
            $this->assertEquals($expected, $rendered);
        } else {
            $content = common_remove_unicode_formatting(nl2br(htmlspecialchars($content)));
            $this->assertEquals($content, $rendered);
        }
    }

    static public function provider()
    {
        return array(
                     array('not a link :: no way',
                           'not a link :: no way'),
                     array('link http://www.somesite.com/xyz/35637563@N00/52803365/ link',
                           'link http://www.somesite.com/xyz/35637563@N00/52803365/ link'),
                     array('http://127.0.0.1',
                           'http://127.0.0.1'),
                     array('http://[::1]:99/test.php',
                           'http://[::1]:99/test.php'),
                     array('http://::1/test.php',
                           'http://::1/test.php'),
                     array('http://::1',
                           'http://::1'),
                     array('http://127.0.0.1',
                           'http://127.0.0.1'),
                     array('http://example.com',
                           'http://example.com'),
                     array('http://example.com.',
                           'http://example.com.'),
                     array('/var/lib/example.so',
                           '/var/lib/example.so'),
                     array('example',
                           'example'),
                     array('mailto:user@example.com',
                           'mailto:user@example.com'),
                     array('mailto:user@example.com?subject=test',
                           'mailto:user@example.com?subject=test'),
                     array('xmpp:user@example.com',
                           'xmpp:user@example.com'),
                     array('#example',
                           '# common_canonical_tag('example'))) . '" rel="tag">example'),
                     array('#example.com',
                           '# common_canonical_tag('example.com'))) . '" rel="tag">example.com'),
                     array('#.net',
                           '# common_canonical_tag('.net'))) . '" rel="tag">.net'),
                     array('http://example',
                           'http://example'),
                     array('http://3xampl3',
                           'http://3xampl3'),
                     array('http://example/',
                           'http://example/'),
                     array('http://example/path',
                           'http://example/path'),
                     array('http://example.com',
                           'http://example.com'),
                     array('https://example.com',
                           'https://example.com'),
                     array('ftp://example.com',
                           'ftp://example.com'),
                     array('ftps://example.com',
                           'ftps://example.com'),
                     array('http://user@example.com',
                           'http://user@example.com'),
                     array('http://user:pass@example.com',
                           'http://user:pass@example.com'),
                     array('http://example.com:8080',
                           'http://example.com:8080'),
                     array('http://example.com:8080/test.php',
                           'http://example.com:8080/test.php'),
                     array('http://www.example.com',
                           'http://www.example.com'),
                     array('http://example.com/',
                           'http://example.com/'),
                     array('http://example.com/path',
                           'http://example.com/path'),
                     array('http://example.com/path.html',
                           'http://example.com/path.html'),
                     array('http://example.com/path.html#fragment',
                           'http://example.com/path.html#fragment'),
                     array('http://example.com/path.php?foo=bar&bar=foo',
                           'http://example.com/path.php?foo=bar&bar=foo'),
                     array('http://example.com.',
                           'http://example.com.'),
                     array('http://müllärör.de',
                           'http://müllärör.de'),
                     array('http://ﺱﺲﺷ.com',
                           'http://ﺱﺲﺷ.com'),
                     array('http://сделаткартинки.com',
                           'http://сделаткартинки.com'),
                     array('http://tūdaliņ.lv',
                           'http://tūdaliņ.lv'),
                     array('http://brændendekærlighed.com',
                           'http://brændendekærlighed.com'),
                     array('http://あーるいん.com',
                           'http://あーるいん.com'),
                     array('http://예비교사.com',
                           'http://예비교사.com'),
                     array('http://example.com.',
                           'http://example.com.'),
                     array('http://example.com?',
                           'http://example.com?'),
                     array('http://example.com!',
                           'http://example.com!'),
                     array('http://example.com,',
                           'http://example.com,'),
                     array('http://example.com;',
                           'http://example.com;'),
                     array('http://example.com:',
                           'http://example.com:'),
                     array('\'http://example.com\'',
                           '\'http://example.com\''),
                     array('"http://example.com"',
                           '"http://example.com"'),
                     array('"http://example.com/"',
                           '"http://example.com/"'),
                     array('http://example.com',
                           'http://example.com'),
                     array('(http://example.com)',
                           '(http://example.com)'),
                     array('[http://example.com]',
                           '[http://example.com]'),
                     array('<http://example.com>',
                           '<http://example.com>'),
                     array('http://example.com/path/(foo)/bar',
                           'http://example.com/path/(foo)/bar'),
                     array('http://example.com/path/[foo]/bar',
                           'http://example.com/path/[foo]/bar'),
                     array('http://example.com/path/foo/(bar)',
                           'http://example.com/path/foo/(bar)'),
                     //Not a valid url - urls cannot contain unencoded square brackets
                     array('http://example.com/path/foo/[bar]',
                           'http://example.com/path/foo/[bar]'),
                     array('Hey, check out my cool site http://example.com okay?',
                           'Hey, check out my cool site http://example.com okay?'),
                     array('What about parens (e.g. http://example.com/path/foo/(bar))?',
                           'What about parens (e.g. http://example.com/path/foo/(bar))?'),
                     array('What about parens (e.g. http://example.com/path/foo/(bar)?',
                           'What about parens (e.g. http://example.com/path/foo/(bar)?'),
                     array('What about parens (e.g. http://example.com/path/foo/(bar).)?',
                           'What about parens (e.g. http://example.com/path/foo/(bar).)?'),
                     //Not a valid url - urls cannot contain unencoded commas
                     array('What about parens (e.g. http://example.com/path/(foo,bar)?',
                           'What about parens (e.g. http://example.com/path/(foo,bar)?'),
                     array('Unbalanced too (e.g. http://example.com/path/((((foo)/bar)?',
                           'Unbalanced too (e.g. http://example.com/path/((((foo)/bar)?'),
                     array('Unbalanced too (e.g. http://example.com/path/(foo))))/bar)?',
                           'Unbalanced too (e.g. http://example.com/path/(foo))))/bar)?'),
                     array('Unbalanced too (e.g. http://example.com/path/foo/((((bar)?',
                           'Unbalanced too (e.g. http://example.com/path/foo/((((bar)?'),
                     array('Unbalanced too (e.g. http://example.com/path/foo/(bar))))?',
                           'Unbalanced too (e.g. http://example.com/path/foo/(bar))))?'),
                     array('file.ext',
                           'file.ext'),
                     array('file.html',
                           'file.html'),
                     array('file.php',
                           'file.php'),

                     // scheme-less HTTP URLs with @ in the path: http://status.net/open-source/issues/2248
                     array('http://flickr.com/photos/34807140@N05/3838905434',
                           'http://flickr.com/photos/34807140@N05/3838905434'),
                     );
    }

    static public function linkifyProvider()
    {
        return array(
            //bare ip addresses are no longer supported
            array('127.0.0.1',
                  '127.0.0.1',
                  'bare_ipv4'),
            array('127.0.0.1:99',
                  '127.0.0.1:99',
                  'bare_ipv4'),
            array('127.0.0.1/Name:test.php',
                  '127.0.0.1/Name:test.php',
                  'bare_ipv4'),
            array('127.0.0.1/~test',
                  '127.0.0.1/~test',
                  'bare_ipv4'),
            array('127.0.0.1/+test',
                  '127.0.0.1/+test',
                  'bare_ipv4'),
            array('127.0.0.1/$test',
                  '127.0.0.1/$test',
                  'bare_ipv4'),
            array('127.0.0.1/\'test',
                  '127.0.0.1/\'test',
                  'bare_ipv4'),
            array('127.0.0.1/"test',
                  '127.0.0.1/"test',
                  'bare_ipv4'),
            array('127.0.0.1/test"test',
                  '127.0.0.1/test"test',
                  'bare_ipv4'),
            array('127.0.0.1/-test',
                  '127.0.0.1/-test',
                  'bare_ipv4'),
            array('127.0.0.1/_test',
                  '127.0.0.1/_test',
                  'bare_ipv4'),
            array('127.0.0.1/!test',
                  '127.0.0.1/!test',
                  'bare_ipv4'),
            array('127.0.0.1/*test',
                  '127.0.0.1/*test',
                  'bare_ipv4'),
            array('127.0.0.1/test%20stuff',
                  '127.0.0.1/test%20stuff',
                  'bare_ipv4'),
            array('2001:4978:1b5:0:21d:e0ff:fe66:59ab/test.php',
                  '2001:4978:1b5:0:21d:e0ff:fe66:59ab/test.php',
                  'bare_ipv6'),
            array('[2001:4978:1b5:0:21d:e0ff:fe66:59ab]:99/test.php',
                  '[2001:4978:1b5:0:21d:e0ff:fe66:59ab]:99/test.php',
                  'bare_ipv6'),
            array('2001:4978:1b5:0:21d:e0ff:fe66:59ab',
                  '2001:4978:1b5:0:21d:e0ff:fe66:59ab',
                  'bare_ipv6'),
            array('example.com',
                  'example.com',
                  'bare_domains'),
            array('flickr.com/photos/34807140@N05/3838905434',
                  'flickr.com/photos/34807140@N05/3838905434',
                  'bare_domains'),
            array('What about parens (e.g. example.com/path/foo/(bar))?',
                  'What about parens (e.g. example.com/path/foo/(bar))?',
                  'bare_domains'),
            array('What about parens (e.g. example.com/path/foo/(bar)?',
                  'What about parens (e.g. example.com/path/foo/(bar)?',
                  'bare_domains'),
            array('What about parens (e.g. example.com/path/foo/(bar).)?',
                  'What about parens (e.g. example.com/path/foo/(bar).?',
                  'bare_domains'),
            array('What about parens (e.g. example.com/path/(foo,bar)?',
                  'What about parens (e.g. example.com/path/(foo,bar)?',
                  'bare_domains'),
            array('example.com',
                  'example.com',
                  'bare_domains'),
            array('example.org',
                  'example.org',
                  'bare_domains'),
            array('example.co.uk',
                  'example.co.uk',
                  'bare_domains'),
            array('www.example.co.uk',
                  'www.example.co.uk',
                  'bare_domains'),
            array('farm1.images.example.co.uk',
                  'farm1.images.example.co.uk',
                  'bare_domains'),
            array('example.museum',
                  'example.museum',
                  'bare_domains'),
            array('example.travel',
                  'example.travel',
                  'bare_domains'),
            array('example.com.',
                  'example.com.',
                  'bare_domains'),
            array('example.com?',
                  'example.com?',
                  'bare_domains'),
            array('example.com!',
                  'example.com!',
                  'bare_domains'),
            array('example.com,',
                  'example.com,',
                  'bare_domains'),
            array('example.com;',
                  'example.com;',
                  'bare_domains'),
            array('example.com:',
                  'example.com:',
                  'bare_domains'),
            array('\'example.com\'',
                  '\'example.com\'',
                  'bare_domains'),
            array('"example.com"',
                  '"example.com"',
                  'bare_domains'),
            array('example.com',
                  'example.com',
                  'bare_domains'),
            array('(example.com)',
                  '(example.com)',
                  'bare_domains'),
            array('[example.com]',
                  '[example.com]',
                  'bare_domains'),
            array('<example.com>',
                  '<example.com>',
                  'bare_domains'),
            array('Hey, check out my cool site example.com okay?',
                  'Hey, check out my cool site example.com okay?',
                  'bare_domains'),
            array('Hey, check out my cool site example.com.I made it.',
                  'Hey, check out my cool site example.com.I made it.',
                  'bare_domains'),
            array('Hey, check out my cool site example.com.Funny thing...',
                  'Hey, check out my cool site example.com.Funny thing...',
                  'bare_domains'),
            array('Hey, check out my cool site example.com.You will love it.',
                  'Hey, check out my cool site example.com.You will love it.',
                  'bare_domains'),
            array('example.com:8080/test.php',
                  'example.com:8080/test.php',
                  'bare_domains'),
            array('user_name+other@example.com',
                  'user_name+other@example.com',
                  'bare_domains'),
            array('user@example.com',
                  'user@example.com',
                  'bare_domains'),
        );
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class UUIDTest extends PHPUnit_Framework_TestCase
{
    public function testGenerate()
    {
        $result = UUID::gen();
        $this->assertRegExp('/^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/',
                            $result);
        // Check version number
        $this->assertEquals(0x4000, hexdec(substr($result, 14, 4)) & 0xF000);
        $this->assertEquals(0x8000, hexdec(substr($result, 19, 4)) & 0xC000);
    }

    public function testUnique()
    {
        $reps = 100;
        $ids = array();

        for ($i = 0; $i < $reps; $i++) {
            $ids[] = UUID::gen();
        }

        $this->assertEquals(count($ids), count(array_unique($ids)), "UUIDs must be unique");
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class UserFeedParseTests extends PHPUnit_Framework_TestCase
{
    public function testFeed1()
    {
        global $_testfeed1;
        $dom = DOMDocument::loadXML($_testfeed1);
        $this->assertFalse(empty($dom));

        $entries = $dom->getElementsByTagName('entry');

        $entry1 = $entries->item(0);
        $this->assertFalse(empty($entry1));

        $feedEl = $dom->getElementsByTagName('feed')->item(0);
        $this->assertFalse(empty($feedEl));

        // Test actor (from activity:subject)

        $act1 = new Activity($entry1, $feedEl);
        $this->assertFalse(empty($act1));
        $this->assertFalse(empty($act1->actor));
        $this->assertEquals($act1->actor->type, ActivityObject::PERSON);
        $this->assertEquals($act1->actor->title, 'Zach Copley');
        $this->assertEquals($act1->actor->id, 'http://localhost/statusnet/user/1');
        $this->assertEquals($act1->actor->link, 'http://localhost/statusnet/zach');

        $avatars = $act1->actor->avatarLinks;

        $this->assertEquals(
                $avatars[0]->url,
                'http://localhost/statusnet/theme/default/default-avatar-profile.png'
        );

        $this->assertEquals(
                $avatars[1]->url,
                'http://localhost/statusnet/theme/default/default-avatar-stream.png'
        );

        $this->assertEquals(
                $avatars[2]->url,
                'http://localhost/statusnet/theme/default/default-avatar-mini.png'
        );

        $this->assertEquals($act1->actor->displayName, 'Zach Copley');

        $poco = $act1->actor->poco;
        $this->assertEquals($poco->preferredUsername, 'zach');
        $this->assertEquals($poco->address->formatted, 'El Cerrito, CA');
        $this->assertEquals($poco->urls[0]->type, 'homepage');
        $this->assertEquals($poco->urls[0]->value, 'http://zach.copley.name');
        $this->assertEquals($poco->urls[0]->primary, true);
        $this->assertEquals($poco->note, 'Zach Hack Attack');

        // test the post

        //var_export($act1);
        $this->assertEquals($act1->objects[0]->type, 'http://activitystrea.ms/schema/1.0/note');
        $this->assertEquals($act1->objects[0]->title, 'And now for something completely insane...');

        $this->assertEquals($act1->objects[0]->content, 'And now for something completely insane...');
        $this->assertEquals($act1->objects[0]->id, 'http://localhost/statusnet/notice/3');

    }

}

$_testfeed1 = <<<TESTFEED1
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0">
 <id>http://localhost/statusnet/api/statuses/user_timeline/1.atom</id>
 <title>zach timeline</title>
 <subtitle>Updates from zach on Zach Dev!</subtitle>
 <logo>http://localhost/statusnet/theme/default/default-avatar-profile.png</logo>
 <updated>2010-03-04T01:41:14+00:00</updated>
<author>
 <name>zach</name>
 <uri>http://localhost/statusnet/user/1</uri>

</author>
 <link href="http://localhost/statusnet/zach" rel="alternate" type="text/html"/>
 <link href="http://localhost/statusnet/main/sup#1" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/>
 <link href="http://localhost/statusnet/main/push/hub" rel="hub"/>
 <link href="http://localhost/statusnet/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-replies"/>
 <link href="http://localhost/statusnet/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-mention"/>
 <link href="http://localhost/statusnet/api/statuses/user_timeline/1.atom" rel="self" type="application/atom+xml"/>
<activity:subject>
 <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
 <id>http://localhost/statusnet/user/1</id>
 <title>Zach Copley</title>
 <link rel="alternate" type="text/html" href="http://localhost/statusnet/zach"/>
 <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://localhost/statusnet/theme/default/default-avatar-profile.png"/>
 <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://localhost/statusnet/theme/default/default-avatar-stream.png"/>
 <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://localhost/statusnet/theme/default/default-avatar-mini.png"/>

<poco:preferredUsername>zach</poco:preferredUsername>
<poco:displayName>Zach Copley</poco:displayName>
<poco:note>Zach Hack Attack</poco:note>
<poco:address>
 <poco:formatted>El Cerrito, CA</poco:formatted>
</poco:address>
<poco:urls>
 <poco:type>homepage</poco:type>
 <poco:value>http://zach.copley.name</poco:value>
 <poco:primary>true</poco:primary>

</poco:urls>
</activity:subject>
<entry>
 <title>And now for something completely insane...</title>
 <link rel="alternate" type="text/html" href="http://localhost/statusnet/notice/3"/>
 <id>http://localhost/statusnet/notice/3</id>
 <published>2010-03-04T01:41:07+00:00</published>
 <updated>2010-03-04T01:41:07+00:00</updated>
 <link rel="ostatus:conversation" href="http://localhost/statusnet/conversation/3"/>
 <content type="html">And now for something completely insane...</content>
</entry>

</feed>
TESTFEED1;


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class UserRightsTest extends PHPUnit_Framework_TestCase
{
    protected $user = null;

    function setUp()
    {
        $user = User::getKV('nickname', 'userrightstestuser');
        if ($user) {
            // Leftover from a broken test run?
            $profile = $user->getProfile();
            $user->delete();
            $profile->delete();
        }
        $this->user = User::register(array('nickname' => 'userrightstestuser'));
        if (!$this->user) {
            throw new Exception("Couldn't register userrightstestuser");
        }
    }

    function tearDown()
    {
        if ($this->user) {
            $profile = $this->user->getProfile();
            $this->user->delete();
            $profile->delete();
        }
    }

    function testInvalidRole()
    {
        $this->assertFalse($this->user->hasRole('invalidrole'));
    }

    function standardRoles()
    {
        return array(array('admin'),
                     array('moderator'));
    }

    /**
     * @dataProvider standardRoles
     *
     */

    function testUngrantedRole($role)
    {
        $this->assertFalse($this->user->hasRole($role));
    }

    /**
     * @dataProvider standardRoles
     *
     */

    function testGrantedRole($role)
    {
        $this->user->grantRole($role);
        $this->assertTrue($this->user->hasRole($role));
    }
}


code:
<?php

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('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

mb_internal_encoding('UTF-8'); // @fixme this probably belongs in common.php?

require_once INSTALLDIR . '/lib/common.php';
require_once INSTALLDIR . '/plugins/Xmpp/XmppPlugin.php';

class XmppValidateTest extends PHPUnit_Framework_TestCase
{
	public function setUp()
	{
		if(!array_key_exists('Xmpp', GNUsocial::getActivePlugins())){
			$this->markTestSkipped('XmppPlugin is not enabled.');
		}
	}
    /**
     * @dataProvider validationCases
     *
     */
    public function testValidate($jid, $validFull, $validBase)
    {
    	$xmpp = new TestXmppPlugin();
    	$this->assertEquals($validFull || $validBase, $xmpp->validate($jid));
        $this->assertEquals($validFull, $xmpp->validateFullJid($jid), "validating as full or base JID");
        $this->assertEquals($validBase, $xmpp->validateBaseJid($jid), "validating as base JID only");
    }

    /**
     * @dataProvider normalizationCases
     *
     */
    public function testNormalize($jid, $expected)
    {
    	$xmpp = new XmppPlugin();
        $this->assertEquals($expected, $xmpp->normalize($jid));
    }

    /**
     * @dataProvider domainCheckCases()
     */
    public function testDomainCheck($domain, $expected, $note)
    {
    	$xmpp = new TestXmppPlugin();
        $this->assertEquals($expected, $xmpp->checkDomain($domain), $note);
    }

    static public function validationCases()
    {
        $long1023 = "long1023" . str_repeat('x', 1023 - 8);
        $long1024 = "long1024" . str_repeat('x', 1024 - 8);
        return array(
            // Our own test cases for standard things & those mentioned in bug reports
            // (jid, valid_full, valid_base)
            array('user@example.com', true, true),
            array('user@example.com/resource', true, false),
            array('user with spaces@example.com', false, false), // not kosher

            array('user.@example.com', true, true), // "common in intranets"
            array('example.com', true, true),
            array('example.com/resource', true, false),
            array('jabchat', true, true),

            array("$long1023@$long1023/$long1023", true, false), // max 1023 "bytes" per portion per spec. Do they really mean bytes though?
            array("$long1024@$long1023/$long1023", false, false),
            array("$long1023@$long1024/$long1023", false, false),
            array("$long1023@$long1023/$long1024", false, false),

            // Borrowed from test_jabber_jutil.c in libpurple
            array("gmail.com", true, true),
            array("gmail.com/Test", true, false),
            array("gmail.com/Test@", true, false),
            array("gmail.com/@", true, false),
            array("gmail.com/Test@alkjaweflkj", true, false),
            array("mark.doliner@gmail.com", true, true),
            array("mark.doliner@gmail.com/Test12345", true, false),
            array("mark.doliner@gmail.com/Test@12345", true, false),
            array("mark.doliner@gmail.com/Te/st@12@//345", true, false),
            array("わいど@conference.jabber.org", true, true),
            array("まりるーむ@conference.jabber.org", true, true),
            array("mark.doliner@gmail.com/まりるーむ", true, false),
            array("mark.doliner@gmail/stuff.org", true, false),
            array("stuart@nödåtXäYZ.se", true, true),
            array("stuart@nödåtXäYZ.se/まりるーむ", true, false),
            array("mark.doliner@わいど.org", true, true),
            array("nick@まつ.おおかみ.net", true, true),
            array("paul@10.0.42.230/s", true, false),
            array("paul@[::1]", true, true), /* IPv6 */
            array("paul@[2001:470:1f05:d58::2]", true, true),
            array("paul@[2001:470:1f05:d58::2]/foo", true, false),
            array("pa=ul@10.0.42.230", true, true),
            array("pa,ul@10.0.42.230", true, true),

            array("@gmail.com", false, false),
            array("@@gmail.com", false, false),
            array("mark.doliner@@gmail.com/Test12345", false, false),
            array("mark@doliner@gmail.com/Test12345", false, false),
            array("@gmail.com/Test@12345", false, false),
            array("/Test@12345", false, false),
            array("mark.doliner@", false, false),
            array("mark.doliner/", false, false),
            array("mark.doliner@gmail_stuff.org", false, false),
            array("mark.doliner@gmail[stuff.org", false, false),
            array("mark.doliner@gmail\\stuff.org", false, false),
            array("paul@[::1]124", false, false),
            array("paul@2[::1]124/as", false, false),
            array("paul@まつ.おおかみ/\x01", false, false),

            /*
             * RFC 3454 Section 6 reads, in part,
             * "If a string contains any RandALCat character, the
             *  string MUST NOT contain any LCat character."
             * The character is U+066D (ARABIC FIVE POINTED STAR).
             */
            // Leaving this one commented out for the moment
            // as it shouldn't hurt anything for our purposes.
            //array("foo@example.com/٭simplexe٭", false, false)
        );
    }

    static public function normalizationCases()
    {
        return array(
            // Borrowed from test_jabber_jutil.c in libpurple
            array('PaUL@DaRkRain42.org', 'paul@darkrain42.org'),
            array('PaUL@DaRkRain42.org/', 'paul@darkrain42.org'),
            array('PaUL@DaRkRain42.org/resource', 'paul@darkrain42.org'),

            // Also adapted from libpurple tests...
            array('Ф@darkrain42.org', 'ф@darkrain42.org'),
            array('paul@Өarkrain.org', 'paul@өarkrain.org'),
        );
    }

    static public function domainCheckCases()
    {
        return array(
            array('gmail.com', true, 'known SRV record'),
            array('jabber.org', true, 'known SRV record'),
            array('status.net', true, 'known SRV record'),
            array('status.leuksman.com', true, 'known no SRV record but valid domain'),
        );
    }

}

class TestXmppPlugin extends XmppPlugin {
	public function checkDomain($domain)
	{
		return parent::checkDomain($domain);
	}

	public function validateBaseJid($jid, $check_domain=false)
	{
		return parent::validateBaseJid($jid, $check_domain);
	}

	public function validateFullJid($jid, $check_domain=false)
	{
		return parent::validateFullJid($jid, $check_domain);
	}
}


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - the 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__) . '/../..'));

$shortoptions = 'n:p:';
$longoptions = array('nickname=', 'password=', 'dry-run');

$helptext = <<<END_OF_HELP
USAGE: atompub_test.php [options]

Runs some tests on the AtomPub interface for the site. You must provide
a user account to authenticate as; it will be used to make some test
posts on the site.

Options:
  -n<user>  --nickname=<user>  Nickname of account to post as
  -p<pass>  --password=<pass>  Password for account
  --dry-run                    Skip tests that modify the site (post, delete)

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

$user = get_option_value('n', 'nickname');
$pass = get_option_value('p', 'password');

if (!$user) {
    die("Must set a user: --nickname=<username>\n");
}
if (!$pass) {
    die("Must set a password: --password=<username>\n");
}

// discover the feed...
// @fixme will this actually work?
$url = common_local_url('ApiTimelineUser', array('format' => 'atom', 'id' => $user));

echo "Collection URL is: $url\n";

$collection = new AtomPubClient($url, $user, $pass);

// confirm the feed has edit links ..... ?

echo "Posting an empty message (should fail)... ";
try {
    $noticeUrl = $collection->post('');
    die("FAILED, succeeded!\n");
} catch (Exception $e) {
    echo "ok\n";
}

echo "Posting an invalid XML message (should fail)... ";
try {
    $noticeUrl = $collection->post('<feed<entry>barf</yomomma>');
    die("FAILED, succeeded!\n");
} catch (Exception $e) {
    echo "ok\n";
}

echo "Posting a valid XML but non-Atom message (should fail)... ";
try {
    $noticeUrl = $collection->post('<feed xmlns="http://notatom.com"><id>arf</id><entry><id>barf</id></entry></feed>');
    die("FAILED, succeeded!\n");
} catch (Exception $e) {
    echo "ok\n";
}

// post!
$rand = mt_rand(0, 99999);
$atom = <<<END_ATOM
<entry xmlns="http://www.w3.org/2005/Atom">
    <title>This is an AtomPub test post title ($rand)</title>
    <content>This is an AtomPub test post content ($rand)</content>
</entry>
END_ATOM;

echo "Posting a new message... ";
$noticeUrl = $collection->post($atom);
echo "ok, got $noticeUrl\n";

echo "Fetching the new notice... ";
$notice = new AtomPubClient($noticeUrl, $user, $pass);
$body = $notice->get();
AtomPubClient::validateAtomEntry($body);
echo "ok\n";

echo "Getting the notice ID URI... ";
$noticeUri = AtomPubClient::entryId($body);
echo "ok: $noticeUri\n";

echo "Confirming new entry points to itself right... ";
$editUrl = AtomPubClient::entryEditURL($body);
if ($editUrl != $noticeUrl) {
    die("Entry lists edit URL as $editUrl, no match!\n");
}
echo "OK\n";

echo "Refetching the collection... ";
$feed = $collection->get();
echo "ok\n";

echo "Confirming new entry is in the feed... ";
$entry = AtomPubClient::getEntryInFeed($feed, $noticeUri);
if (!$entry) {
    die("missing!\n");
}
//  edit URL should match
echo "ok\n";

echo "Editing notice (should fail)... ";
try {
    $notice->put($target, $atom2);
    die("ERROR: editing a notice should have failed.\n");
} catch (Exception $e) {
    echo "ok (failed as expected)\n";
}

echo "Deleting notice... ";
$notice->delete();
echo "ok\n";

echo "Refetching deleted notice to confirm it's gone... ";
try {
    $body = $notice->get();
    var_dump($body);
    die("ERROR: notice should be gone now.\n");
} catch (Exception $e) {
    echo "ok\n";
}

echo "Refetching the collection.. ";
$feed = $collection->get();
echo "ok\n";

echo "Confirming deleted notice is no longer in the feed... ";
$entry = AtomPubClient::getEntryInFeed($feed, $noticeUri);
if ($entry) {
    die("still there!\n");
}
echo "ok\n";

// make subscriptions
// make some posts
// make sure the posts go through or not depending on the subs
// remove subscriptions
// test that they don't go through now

// group memberships too

// make sure we can't post to someone else's feed!
// make sure we can't delete someone else's messages
// make sure we can't create/delete someone else's subscriptions
// make sure we can't create/delete someone else's group memberships


code:
Some very rough test scripts for hitting up the OAuth endpoints.

These instructions assume you understand the basics of how OAuth
works. You may want to read up about it first. Here are some good
resources for learning about OAuth:

    http://hueniverse.com/oauth/
    http://tools.ietf.org/html/rfc5849

To use these scripts (and OAuth in general) first you will need to
register and OAuth client application with your StatusNet instance:

    http://example.status.net/settings/oauthapps

oauth.ini
---------

Using oauth.ini.sample as a guide, put your StatusNet OAuth endpoints
and consumer key and secret in a file called oauth.ini and save it
in the same directory as these scripts.

fetch_temp_creds.php
--------------------

Will fetch a request token, token secret and a URL to authorize the
token.  Once you authorize the request token, you can exchange it
for an access token.

example usage:

    $ php fetch_temp_creds.php
    Request Token
       - oauth_token        = 89d481e376edc622f08da5791e6a4446
       - oauth_token_secret = 6d028bcd1ea125cbed7da2f254219885
    Authorize URL
        http://example.status.net/api/oauth/authorize?oauth_token=89d481e376edc622f08da5791e6a4446

    Now paste the Authorize URL into your browser and authorize your temporary credentials.

fetch_token_creds.php
---------------------

After you have authorized your request token, you will be presented
with a verifier code, or pin, in your browser, which you will need
to get an access token. Make sure you copy it into a text buffer
or write it down or something. Then call fetch_token_credentials.php
to exchange your temporary credentials for real token credentials.

example usage:

    $ php fetch_token_creds.php -t 89d481e376edc622f08da5791e6a4446 -s 6d028bcd1ea125cbed7da2f254219885 -v 305162
    Access Token
       - oauth_token        = 9b354df102d8e2b4621122c85d8d045c
       - oauth_token_secret = 1800a88f1574b47d595214a74e5b1ec5

oauth_verify_credentials.php
----------------------------

Now you should have real token credentials (an OAuth access token)
and you can access protected API resources. This is an example
script that calls /api/account/verify_credentials.xml.

example usage:

    $ php oauth_verify_creds.php -t 80305cd15c5c69834364ac02d7f9178c -s 673e3b2978b1b92c8edbfe172505fee1
    <?xml version="1.0" encoding="UTF-8"?>
    <user xmlns:statusnet="http://status.net/schema/api/1/">
     <id>23</id>
     <name>zach</name>
     <screen_name>zach</screen_name>
     <location></location>
     <description></description>
     <profile_image_url>http://example.status.net/theme/default/default-avatar-stream.png</profile_image_url>
     <url></url>
     <protected>false</protected>
     <followers_count>0</followers_count>
     <profile_background_color></profile_background_color>
     <profile_text_color></profile_text_color>
     <profile_link_color></profile_link_color>
     <profile_sidebar_fill_color></profile_sidebar_fill_color>
     <profile_sidebar_border_color></profile_sidebar_border_color>
     <friends_count>0</friends_count>
     <created_at>Thu Sep 30 23:11:00 +0000 2010</created_at>
     <favourites_count>0</favourites_count>
     <utc_offset>0</utc_offset>
     <time_zone>UTC</time_zone>
     <profile_background_image_url></profile_background_image_url>
     <profile_background_tile>false</profile_background_tile>
     <statuses_count>4</statuses_count>
     <following>true</following>
     <statusnet:blocking>false</statusnet:blocking>
     <notifications>true</notifications>
     <status>
      <text>gar</text>
      <truncated>false</truncated>
      <created_at>Wed Oct 06 23:40:14 +0000 2010</created_at>
      <in_reply_to_status_id></in_reply_to_status_id>
      <source>web</source>
      <id>7</id>
      <in_reply_to_user_id></in_reply_to_user_id>
      <in_reply_to_screen_name></in_reply_to_screen_name>
      <geo></geo>
      <favorited>false</favorited>
      <statusnet:html>gar</statusnet:html>
     </status>
     <statusnet:profile_url>http://example.status.net/statusnet/zach</statusnet:profile_url>
    </user>

oauth_post_notice.php
---------------------

This is another test script that lets you post a notice via OAuth.

example usage:

    $ php oauth_post_notice.php -t 80305cd15c5c69834364ac02d7f9178c -s 673e3b2978b1b92c8edbfe172505fee1 -u 'Test test test...'
    <?xml version="1.0" encoding="UTF-8"?>
    <status xmlns:statusnet="http://status.net/schema/api/1/">
     <text>Test test test...</text>
     <truncated>false</truncated>
     <created_at>Fri Oct 08 02:37:35 +0000 2010</created_at>
     <in_reply_to_status_id></in_reply_to_status_id>
     <source>Banana</source>
     <id>8</id>
     <in_reply_to_user_id></in_reply_to_user_id>
     <in_reply_to_screen_name></in_reply_to_screen_name>
     <geo></geo>
     <favorited>false</favorited>
     <user>
      <id>23</id>
      <name>zach</name>
      <screen_name>zach</screen_name>
      <location></location>
      <description></description>
      <profile_image_url>http://example.status.net/statusnet/theme/default/default-avatar-stream.png</profile_image_url>
      <url></url>
      <protected>false</protected>
      <followers_count>0</followers_count>
      <profile_background_color></profile_background_color>
      <profile_text_color></profile_text_color>
      <profile_link_color></profile_link_color>
      <profile_sidebar_fill_color></profile_sidebar_fill_color>
      <profile_sidebar_border_color></profile_sidebar_border_color>
      <friends_count>0</friends_count>
      <created_at>Thu Sep 30 23:11:00 +0000 2010</created_at>
      <favourites_count>0</favourites_count>
      <utc_offset>0</utc_offset>
      <time_zone>UTC</time_zone>
      <profile_background_image_url></profile_background_image_url>
      <profile_background_tile>false</profile_background_tile>
      <statuses_count>5</statuses_count>
      <following>true</following>
      <statusnet:blocking>false</statusnet:blocking>
      <notifications>true</notifications>
      <statusnet:profile_url>http://example.status.net/statusnet/zach</statusnet:profile_url>
     </user>
     <statusnet:html>Test test test...</statusnet:html>
    </status>

path: tests/oauth/README


code:
#!/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__) . '/../..'));

require_once INSTALLDIR . '/scripts/commandline.inc';
require_once INSTALLDIR . '/extlib/OAuth.php';

$ini = parse_ini_file("oauth.ini");

// Check to make sure we have everything we need from the ini file
foreach(array('consumer_key', 'consumer_secret', 'apiroot', 'request_token_url') as $inikey) {
    if (empty($ini[$inikey])) {
        print "You forgot to specify a $inikey in your oauth.ini file.\n";
        exit(1);
    }
}

$consumer = new OAuthConsumer($ini['consumer_key'], $ini['consumer_secret']);
$endpoint = $ini['apiroot'] . $ini['request_token_url'];
$parsed   = parse_url($endpoint);
$params   = array();

parse_str($parsed['query'], $params);
$params['oauth_callback'] = 'oob'; // out-of-band

$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();

try {
    $req = OAuthRequest::from_consumer_and_token(
        $consumer,
        null,
        "POST",
        $endpoint,
        $params
    );
    $req->sign_request($hmac_method, $consumer, NULL);
    $r = httpRequest($endpoint, $req->to_postdata());
} catch (Exception $e) {
    // oh noez
    print $e->getMessage();
    print "\nOAuth Request:\n";
    var_dump($req);
    exit(1);
}

$body       = $r->getBody();
$tokenStuff = array();

parse_str($body, $tokenStuff);

$tok       = $tokenStuff['oauth_token'];
$confirmed = $tokenStuff['oauth_callback_confirmed'];

if (empty($tokenStuff['oauth_token'])
    || empty($tokenStuff['oauth_token_secret'])
    || empty($confirmed)
    || $confirmed != 'true')
{
    print "Error! HTTP response body: $body\n";
    exit(1);
}

$authurl = $ini['apiroot'] . $ini['authorize_url'] . '?oauth_token=' . $tok;

print "Request Token\n";
print '   - oauth_token        = ' . $tokenStuff['oauth_token'] . "\n";
print '   - oauth_token_secret = ' . $tokenStuff['oauth_token_secret'] . "\n";
print "Authorize URL\n    $authurl\n\n";
print "Now paste the Authorize URL into your browser and authorize your temporary credentials.\n";

function httpRequest($endpoint, $poststr)
{
    $request = HTTPClient::start();

    $request->setConfig(
        array(
            'follow_redirects' => true,
	    'connect_timeout' => 120,
	    'timeout' => 120,
	    'ssl_verify_peer' => false,
	    'ssl_verify_host' => false
        )
    );

    // Turn signed request query string back into an array
    parse_str($poststr, $postdata);
    return $request->post($endpoint, null, $postdata);
}