code:
<?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/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) {
    exit(1);
}

class User_urlshortener_prefs extends Managed_DataObject
{
    ###START_AUTOCODE
    /* the code below is auto generated do not remove the above tag */

    public $__table = 'user_urlshortener_prefs';         // table name
    public $user_id;                         // int(4)  primary_key not_null
    public $urlshorteningservice;            // varchar(50)   default_ur1.ca
    public $maxurllength;                    // int(4)   not_null
    public $maxnoticelength;                 // int(4)   not_null
    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP

    /* the code above is auto generated do not remove the tag below */
    ###END_AUTOCODE

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
                'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'),
                'maxurllength' => array('type' => 'int', 'not null' => true, 'description' => 'urls greater than this length will be shortened, 0 = always, null = never'),
                'maxnoticelength' => array('type' => 'int', 'not null' => true, 'description' => 'notices with content greater than this value will have all urls shortened, 0 = always, -1 = only if notice text is longer than max allowed'),

                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('user_id'),
            'foreign keys' => array(
                'user_urlshortener_prefs_user_id_fkey' => array('user', array('user_id' => 'id')),
            ),
        );
    }

    static function maxUrlLength($user)
    {
        $def = common_config('url', 'maxurllength');

        $prefs = self::getPrefs($user);

        if (empty($prefs)) {
            return $def;
        } else {
            return $prefs->maxurllength;
        }
    }

    static function maxNoticeLength($user)
    {
        $def = common_config('url', 'maxnoticelength');

        if ($def == -1) {
            /*
             * maxContent==0 means infinite length,
             * but maxNoticeLength==0 means "always shorten"
             * so if maxContent==0 we must set this to -1
             */
            $def = Notice::maxContent() ?: -1;
        }

        $prefs = self::getPrefs($user);

        if (empty($prefs)) {
            return $def;
        } else {
            return $prefs->maxnoticelength;
        }
    }

    static function urlShorteningService($user)
    {
        $def = common_config('url', 'shortener');

        $prefs = self::getPrefs($user);

        if (empty($prefs)) {
            if (!empty($user)) {
                return $user->urlshorteningservice;
            } else {
                return $def;
            }
        } else {
            return $prefs->urlshorteningservice;
        }
    }

    static function getPrefs($user)
    {
        if (empty($user)) {
            return null;
        }

        $prefs = User_urlshortener_prefs::getKV('user_id', $user->id);

        return $prefs;
    }
}


code:
<?php
/**
 * Table Definition for user_username
 */
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';

class User_username extends Managed_DataObject
{
    ###START_AUTOCODE
    /* the code below is auto generated do not remove the above tag */

    public $__table = 'user_username';                     // table name
    public $user_id;                        // int(4)  not_null
    public $provider_name;                  // varchar(255)  primary_key not_null
    public $username;                       // varchar(255)  primary_key not_null
    public $created;                        // datetime()   not_null
    public $modified;                       // timestamp()   not_null default_CURRENT_TIMESTAMP

    /* the code above is auto generated do not remove the tag below */
    ###END_AUTOCODE

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'provider_name' => array('type' => 'varchar', 'length' => 255, 'description' => 'provider name'),
                'username' => array('type' => 'varchar', 'length' => 255, 'description' => 'username'),
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice id this title relates to'),
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('provider_name', 'username'),
            'indexes' => array(
                'user_id_idx' => array('user_id')
            ),
            'foreign keys' => array(
                'user_username_user_id_fkey' => array('user', array('user_id' => 'id')),
            ),
        );
    }

    /**
    * Register a user with a username on a given provider
    * @param User User object
    * @param string username on the given provider
    * @param provider_name string name of the provider
    * @return mixed User_username instance if the registration succeeded, false if it did not
    */
    static function register($user, $username, $provider_name)
    {
        $user_username = new User_username();
        $user_username->user_id = $user->id;
        $user_username->provider_name = $provider_name;
        $user_username->username = $username;
        $user_username->created = common_sql_now();

        if($user_username->insert()){
            return $user_username;
        }else{
            return false;
        }
    }
}

license: mit


code:
[status_network]
site_id = 129
nickname = 130
hostname = 2
pathname = 2
dbhost = 2
dbuser = 2
dbpass = 2
dbname = 2
sitename = 2
theme = 2
logo = 2
created = 142
modified = 384

[status_network__keys]
site_id  = K
nickname = U
hostname = U
pathname = U

[status_network_tag]
site_id = 129
tag = 130
created = 142

[status_network_tag__keys]
site_id = K
tag = K


code:
<?php

/**
 *
 * Some notes...
 *
 * Drupal docs don't list a bool type, but it might be nice to use rather than 'tinyint'
 * Note however that we use bitfields and things as well in tinyints, and PG's
 * "bool" type isn't 100% compatible with 0/1 checks. Just keeping tinyints. :)
 *
 * decimal <-> numeric
 *
 * MySQL 'timestamp' columns were formerly used for 'modified' files for their
 * auto-updating properties. This didn't play well with changes to cache usage
 * in 0.9.x, as we don't know the timestamp value at INSERT time and never
 * have a chance to load it up again before caching. For now I'm leaving them
 * in, but we may want to clean them up later.
 *
 * Current code should be setting 'created' and 'modified' fields explicitly;
 * this also avoids mismatches between server and client timezone settings.
 *
 *
 * fulltext indexes?
 * got one or two things wanting a custom charset setting on a field?
 *
 * foreign keys are kinda funky...
 *     those specified in inline syntax (as all in the original .sql) are NEVER ENFORCED on mysql
 *     those made with an explicit 'foreign key' WITHIN INNODB and IF there's a proper index, do get enforced
 *     double-check what we've been doing on postgres?
 */

$classes = array('Schema_version',
                 'Profile',
                 'Avatar',
                 'Sms_carrier',
                 'User',
                 'Subscription',
                 'Group_join_queue',
                 'Subscription_queue',
                 'Oauth_token_association',
                 'Notice',
                 'Notice_source',
                 'Reply',
                 'Consumer',
                 'Token',
                 'Nonce',
                 'Oauth_application',
                 'Oauth_application_user',
                 'Confirm_address',
                 'Remember_me',
                 'Queue_item',
                 'Notice_tag',
                 'Foreign_service',
                 'Foreign_user',
                 'Foreign_link',
                 'Foreign_subscription',
                 'Invitation',
                 'Profile_prefs',
                 'Profile_tag',
                 'Profile_list',
                 'Profile_tag_subscription',
                 'Profile_block',
                 'User_group',
                 'Related_group',
                 'Group_inbox',
                 'Group_member',
                 'File',
                 'File_redirection',
                 'File_thumbnail',
                 'File_to_post',
                 'Group_block',
                 'Group_alias',
                 'Session',
                 'Deleted_notice',
                 'Config',
                 'Profile_role',
                 'Location_namespace',
                 'Login_token',
                 'User_location_prefs',
                 'User_im_prefs',
                 'Conversation',
                 'Local_group',
                 'User_urlshortener_prefs',
                 'Old_school_prefs',
                 'User_username',
                 'Attention',
);

foreach ($classes as $cls) {
    $schema[strtolower($cls)] = call_user_func(array($cls, 'schemaDef'));
}


code:
insert into foreign_service
    (id, name, description, created)
values
    ('1','Twitter', 'Twitter Micro-blogging service', now()),
    ('2','Facebook', 'Facebook', now()),
    ('3','FacebookConnect', 'Facebook Connect', now());


code:
insert into location_namespace
    (id, description, created)
values
    (1, 'Geonames', now()),
    (2, 'Where on Earth', now());


code:
INSERT INTO notice_source
    (code, name, url, created)
VALUES
    ('adium', 'Adium', 'http://www.adiumx.com/', now()),
    ('Afficheur', 'Afficheur', 'http://afficheur.sourceforge.jp/', now()),
    ('AgentSolo.com','AgentSolo.com','http://www.agentsolo.com/', now()),
    ('anyio', 'Any.IO', 'http://any.io/', now()),
    ('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()),
    ('bti','bti','http://gregkh.github.com/bti/', now()),
    ('choqok', 'Choqok', 'http://choqok.gnufolks.org/', now()),
    ('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
    ('DarterosStatus', 'Darteros Status', 'http://www.darteros.com/doc/Darteros_Status', now()),
    ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
    ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
    ('drupal','Drupal','http://drupal.org/', now()),
    ('eventbox','EventBox','http://thecosmicmachine.com/eventbox/', now()),
    ('identica-mode','Emacs Identica-mode','http://nongnu.org/identica-mode/', now()),
    ('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
    ('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
    ('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()),
    ('gNewBook', 'gNewBook', 'http://www.gnewbook.org/', now()),
    ('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),
    ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
    ('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
    ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()),
    ('identichat','identichat','http://identichat.prosody.im/', now()),
    ('IdentiCurse','IdentiCurse','http://identicurse.net/', now()),
    ('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()),
    ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
    ('Jiminy','Jiminy','http://code.google.com/p/jiminy/', now()),
    ('LaTwit','LaTwit','http://latwit.mac65.com/', now()),
    ('LiveTweeter', 'LiveTweeter', 'http://addons.songbirdnest.com/addon/1204', now()),
    ('livetweeter', 'livetweeter', 'http://addons.songbirdnest.com/addon/1204', now()),
    ('maisha', 'Maisha', 'http://maisha.grango.org/', now()),
    ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()),
    ('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()),
    ('moconica','Moconica','http://moconica.com/', now()),
    ('mustard', 'mustard', 'http://mustard.macno.org', now()),
    ('nambu','Nambu','http://www.nambu.com/', now()),
    ('peoplebrowsr', 'PeopleBrowsr', 'http://www.peoplebrowsr.com/', now()),
    ('Pikchur','Pikchur','http://www.pikchur.com/', now()),
    ('Ping.fm','Ping.fm','http://ping.fm/', now()),
    ('pingvine','PingVine','http://pingvine.com/', now()),
    ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()),
    ('posty','Posty','http://spreadingfunkyness.com/posty/', now()),
    ('qtwitter','qTwitter','http://qtwitter.ayoy.net/', now()),
    ('qwit', 'Qwit', 'http://code.google.com/p/qwit/', now()),
    ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()),
    ('rssdent','rssdent','http://github.com/zcopley/rssdent/tree/master', now()),
    ('rygh.no','rygh.no','http://rygh.no/', now()),
    ('ryghsms','ryghsms','http://sms.rygh.no/', now()),
    ('smob','SMOB','http://smob.sioc-project.org/', now()),
    ('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()),
    ('spaz','Spaz','http://funkatron.com/spaz', now()),
    ('StatusNet Desktop', 'StatusNet Desktop', 'http://status.net/desktop', now()),
    ('StatusNet Mobile', 'StatusNet Mobile', 'http://status.net/mobile', now()),
    ('StatusNet iPhone', 'iPhone', 'http://status.net/iphone', now()),
    ('StatusNet Android', 'Android', 'http://status.net/android', now()),
    ('StatusNet Blackberry', 'Blackberry', 'http://status.net/blackberry', now()),
    ('tarpipe','tarpipe','http://tarpipe.com/', now()),
    ('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()),
    ('tr.im','tr.im','http://tr.im/', now()),
    ('triklepost', 'Tricklepost', 'http://github.com/zcopley/tricklepost/tree/master', now()),
    ('tweenky','Tweenky','http://beta.tweenky.com/', now()),
    ('TweetDeck', 'TweetDeck', 'http://www.tweetdeck.com/', now()),
    ('twhirl','Twhirl','http://www.twhirl.org/', now()),
    ('twibble','twibble','http://www.twibble.de/', now()),
    ('Twidge','Twidge','http://software.complete.org/twidge', now()),
    ('twidge','Twidge','http://software.complete.org/twidge', now()),
    ('twidroid','twidroid','http://www.twidroid.com/', now()),
    ('twittelator','Twittelator','http://www.stone.com/iPhone/Twittelator/', now()),
    ('twitter','Twitter','http://twitter.com/', now()),
    ('twitterfeed','twitterfeed','http://twitterfeed.com/', now()),
    ('twitterphoto','TwitterPhoto','http://richfish.org/twitterphoto/', now()),
    ('twitterpm','Net::Twitter','http://search.cpan.org/dist/Net-Twitter/', now()),
    ('twittertools','Twitter Tools','http://wordpress.org/extend/plugins/twitter-tools/', now()),
    ('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()),
    ('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()),
    ('Updating.Me','Updating.Me','http://updating.me/', now()),
    ('urfastr','urfastr','http://urfastr.net/', now()),
    ('yatca','Yatca','http://www.yatca.com/', now()),
    ('rss.me', 'rss.me', 'http://rss.me/', now());


code:
/* For managing multiple sites */

create table status_network (

    site_id  integer auto_increment primary key comment 'unique id',
    nickname varchar(64)  unique key comment 'nickname',
    hostname varchar(255) unique key comment 'alternate hostname if any',
    pathname varchar(255) unique key comment 'alternate pathname if any',

    dbhost varchar(255) comment 'database host',
    dbuser varchar(255) comment 'database username',
    dbpass varchar(255) comment 'database password',
    dbname varchar(255) comment 'database name',

    sitename varchar(255) comment 'display name',
    theme varchar(255) comment 'theme name',
    logo varchar(255) comment 'site logo',

    tags text comment 'site meta-info tags (pipe-separated)',

    created datetime not null comment 'date this record was created',
    modified timestamp comment 'date this record was modified'

) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;

create table status_network_tag (
    site_id integer  comment 'unique id',
    tag varchar(64) comment 'tag name',
    created datetime not null comment 'date the record was created',

    constraint primary key (site_id, tag),
    index status_network_tag_tag_idx (tag)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;


code:
INSERT INTO sms_carrier
    (id, name, email_pattern, created)
VALUES
    (100056, '3 River Wireless', '%s@sms.3rivers.net', now()),
    (100057, '7-11 Speakout', '%s@cingularme.com', now()),
    (100058, 'Airtel (Karnataka, India)', '%s@airtelkk.com', now()),
    (100059, 'Alaska Communications Systems', '%s@msg.acsalaska.com', now()),
    (100060, 'Alltel Wireless', '%s@message.alltel.com', now()),
    (100061, 'AT&T Wireless', '%s@txt.att.net', now()),
    (100062, 'Bell Mobility (Canada)', '%s@txt.bell.ca', now()),
    (100063, 'Boost Mobile', '%s@myboostmobile.com', now()),
    (100064, 'Cellular One (Dobson)', '%s@mobile.celloneusa.com', now()),
    (100065, 'Cingular (Postpaid)', '%s@cingularme.com', now()),
    (100066, 'Centennial Wireless', '%s@cwemail.com', now()),
    (100067, 'Cingular (GoPhone prepaid)', '%s@cingularme.com', now()),
    (100068, 'Claro (Nicaragua)', '%s@ideasclaro-ca.com', now()),
    (100069, 'Comcel', '%s@comcel.com.co', now()),
    (100070, 'Cricket', '%s@sms.mycricket.com', now()),
    (100071, 'CTI', '%s@sms.ctimovil.com.ar', now()),
    (100072, 'Emtel (Mauritius)', '%s@emtelworld.net', now()),
    (100073, 'Fido (Canada)', '%s@fido.ca', now()),
    (100074, 'General Communications Inc.', '%s@msg.gci.net', now()),
    (100075, 'Globalstar', '%s@msg.globalstarusa.com', now()),
    (100076, 'Helio', '%s@myhelio.com', now()),
    (100077, 'Illinois Valley Cellular', '%s@ivctext.com', now()),
    (100078, 'i wireless', '%s.iws@iwspcs.net', now()),
    (100079, 'Meteor (Ireland)', '%s@sms.mymeteor.ie', now()),
    (100080, 'Mero Mobile (Nepal)', '%s@sms.spicenepal.com', now()),
    (100081, 'MetroPCS', '%s@mymetropcs.com', now()),
    (100082, 'Movicom', '%s@movimensaje.com.ar', now()),
    (100083, 'Mobitel (Sri Lanka)', '%s@sms.mobitel.lk', now()),
    (100084, 'Movistar (Colombia)', '%s@movistar.com.co', now()),
    (100085, 'MTN (South Africa)', '%s@sms.co.za', now()),
    (100086, 'MTS (Canada)', '%s@text.mtsmobility.com', now()),
    (100087, 'Nextel (Argentina)', '%s@nextel.net.ar', now()),
    (100088, 'Orange (Poland)', '%s@orange.pl', now()),
    (100089, 'Personal (Argentina)', '%s@personal-net.com.ar', now()),
    (100090, 'Plus GSM (Poland)', '%s@text.plusgsm.pl', now()),
    (100091, 'President\'s Choice (Canada)', '%s@txt.bell.ca', now()),
    (100092, 'Qwest', '%s@qwestmp.com', now()),
    (100093, 'Rogers (Canada)', '%s@pcs.rogers.com', now()),
    (100094, 'Sasktel (Canada)', '%s@sms.sasktel.com', now()),
    (100095, 'Setar Mobile email (Aruba)', '%s@mas.aw', now()),
    (100096, 'Solo Mobile', '%s@txt.bell.ca', now()),
    (100097, 'Sprint (PCS)', '%s@messaging.sprintpcs.com', now()),
    (100098, 'Sprint (Nextel)', '%s@page.nextel.com', now()),
    (100099, 'Suncom', '%s@tms.suncom.com', now()),
    (100100, 'T-Mobile', '%s@tmomail.net', now()),
    (100101, 'T-Mobile (Austria)', '%s@sms.t-mobile.at', now()),
    (100102, 'Telus Mobility (Canada)', '%s@msg.telus.com', now()),
    (100103, 'Thumb Cellular', '%s@sms.thumbcellular.com', now()),
    (100104, 'Tigo (Formerly Ola)', '%s@sms.tigo.com.co', now()),
    (100105, 'Unicel', '%s@utext.com', now()),
    (100106, 'US Cellular', '%s@email.uscc.net', now()),
    (100107, 'Verizon', '%s@vtext.com', now()),
    (100108, 'Virgin Mobile (Canada)', '%s@vmobile.ca', now()),
    (100109, 'Virgin Mobile (USA)', '%s@vmobl.com', now()),
    (100110, 'YCC', '%s@sms.ycc.ru', now()),
    (100111, 'Orange (UK)', '%s@orange.net', now()),
    (100112, 'Cincinnati Bell Wireless', '%s@gocbw.com', now()),
    (100113, 'T-Mobile Germany', '%s@t-mobile-sms.de', now()),
    (100114, 'Vodafone Germany', '%s@vodafone-sms.de', now()),
    (100115, 'E-Plus', '%s@smsmail.eplus.de', now()),
    (100116, 'Cellular South', '%s@csouth1.com', now()),
    (100117, 'ChinaMobile (139)', '%s@139.com', now()),
    (100118, 'Dialog Axiata', '%s@dialog.lk', now());


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

%%site.name%% is a
social network based on the Free Software [GNU social](http://www.gnu.org/software/social/) tool.

If you [register](%%action.register%%) for an account,
you can post small (%%site.textlimit%% chars or less) text notices
about yourself, where you are, what you're doing, or practically
anything you want. You can also subscribe to the notices of your
friends, or other people you're interested in, and follow them on the
Web or in an [RSS](http://en.wikipedia.org/wiki/RSS) feed.

path: doc-src/about


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

%%site.name%% provides an API that applications can use to interact with it.
More information about this API can be found on the [StatusNet Wiki](http://status.net/wiki/API).

path: doc-src/api


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

There are a number of options for getting in contact with responsible
people for %%site.name%%.

Bugs
----

If you think you've found a bug in the underlying [GNU social](https://gnu.io/social/) software,
or if there's a new feature you'd like to see, add it into the [GNU social task list](https://bugz.foocorp.net/).
Don't forget to check the list of existing bugs to make sure it hasn't already been reported!

Email
-----

You can reach the responsible party for this server at [%%site.email%%](mailto:%%site.email%%).

Post a notice
-------------

If you have a question about how to do something, just post a notice with
your question, preferrably tagged with #NewHere. Watch your inbox for replies.

path: doc-src/contact


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

These are some *Frequently Asked Questions* about this service, with
some answers.

What is this site?
----------------------

This is a social network, running the GNU social software.

You can use it to make connections between friends, family and
colleagues -- writing short notices about yourself, where you are, and
what you're doing, and those notices will be sent to all your contacts.

In the future, we'll be adding support for photo, video and file
sharing, as well as events, better contact management and mobile
devices.

path: doc-src/faq


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

Users on %%site.name%% can create *groups* that other users can join.
Groups can be a great way to share information and entertainment with
a group of people who have a common interest or background; who work
together on a team; or who have a particular knowledge or skill.

You can find out about groups on the server on the
[Groups](%%action.groups%%) page. You can join a group by clicking on
the "Join" button either in the group list or on the group's home page.

Starting a new group
--------------------

You can start a new group for friends and colleagues. Note that all
groups are free for anyone to join.

To start a new group, use the [new group](%%action.newgroup%%) tool
and fill out the form. Describe your group as best you can if you want
people to be able to find it.

When choosing the nickname for your group, try to keep it short. The
nickname is sometimes included in messages to and from the group, so
the less chars the better. Try using acronyms for organizations, or
airport codes for places (like 'pdx' instead of 'portland').

Sending messages to a group
---------------------------

You can send a message to a group using the syntax "!groupname"
anywhere in the message. If you have more than one group named, the
notice will go to each group. Only members can send notices to a
group, and groups do not respond to direct messages (DMs).

You can also select the group from the "To:" drop down when posting.

You can make a group message private by clicking the "private" button
before posting.

Receiving messages
------------------

New group messages will appear in your inbox, and will also come to
your phone or IM client if you've set them up to receive notices.

Private groups
--------------

The administrator can make a group private. For a private group, all
notices will marked as private for group members only. Also,
administrators will have to approve all new members to the group.

Private groups are visible in the group directory.

path: doc-src/groups


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

%%site.name%% is a **social service**. Users can post short
(%%site.textlimit%% character) status messages which are broadcast to
their friends and colleagues on the service and (optionally) onto the Web.

You can also broadcast other types of data, like bookmarks, event
invitations, polls, and questions.

If you'd like to try it out, first [register](%%action.register%%) a new account.
Then, on the [public timeline](%%action.top%%), enter your message into
the textbox at the top of the page, and click "Send". It will go out on the
public timeline and to anyone who is subscribed to your notices.

To subscribe to other people's notifications, go to their profile page
and click the "subscribe" button. They'll get a notice that you're now
subscribed to their notifications.

path: doc-src/help


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

You can post messages to %%site.name%% using a [Jabber](http://jabber.org/) client
on your computer, mobile phone, or other platform. ([GTalk](http://talk.google.com/),
Google's Jabber program, will also work.) This can be a convenient way to keep
up with your friends on %%site.name%%.

If you don't already have a Jabber account, you can use GTalk or one of the other
[public Jabber services](http://www.jabber.org/im-services). You'll probably also
need an IM client like [Pidgin](http://www.pidgin.im/).

Managing your IM settings
-------------------------

Use the [IM settings](%%action.imsettings%%) page to set your IM preferences. You can add or change your Jabber address and set the flags for Jabber update.

When you add or change your address, you'll receive a message from **%%xmpp.user%%@%%xmpp.server%%** asking you to confirm the change. (You may need to
add %%xmpp.user%%@%%xmpp.server%% to your buddy list *before* changing your IM
settings; this is definitely true for GTalk.)

Sending updates
---------------

You send updates by sending messages to %%xmpp.user%%@%%xmpp.server%%. Messages
should be less than %%site.textlimit%% characters; longer messages will be truncated.

Commands
--------

You can do some minor management of your account through Jabber. These are the
currently-implemented commands:

* **on** - turn on notifications
* **off** - turn off notifications
* **help** - show this help
* **follow <nickname>** - subscribe to user
* **groups** - lists the groups you have joined
* **subscriptions** - list the people you follow
* **subscribers** - list the people that follow you
* **leave <nickname>** - unsubscribe from user
* **d <nickname> <text>** - direct message to user
* **get <nickname>** - get last notice from user
* **whois <nickname>** - get profile info on user
* **lose <nickname>** - force user to stop following you
* **fav <nickname>** - add user's last notice as a 'fave'
* **fav #<notice_id>** - add notice with the given id as a 'fave'
* **repeat #<notice_id>** - repeat a notice with a given id
* **repeat <nickname>** - repeat the last notice from user
* **reply #<notice_id>** - reply to notice with a given id
* **reply <nickname>** - reply to the last notice from user
* **join <group>** - join group
* **login** - Get a link to login to the web interface
* **drop <group>** - leave group
* **stats** - get your stats
* **stop** - same as 'off'
* **quit** - same as 'off'
* **sub <nickname>** - same as 'follow'
* **unsub <nickname>** - same as 'leave'
* **last <nickname>** - same as 'get'
* **on <nickname>** - not yet implemented.
* **off <nickname>** - not yet implemented.
* **nudge <nickname>** - remind a user to update.
* **invite <phone number>** - not yet implemented.
* **track <word>** - not yet implemented.
* **untrack <word>** - not yet implemented.
* **track off** - not yet implemented.
* **untrack all** - not yet implemented.
* **tracks** - not yet implemented.
* **tracking** - not yet implemented.

path: doc-src/im


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

This document outlines this service's respect for your personal
privacy as a user of the service.

- Almost all the text and files that users upload to this site is
  available under the site license (see the license block at the bottom
  of this page). Users agree to the license when they register to use
  the site for the first time. Typically that means that the data can
  be copied far and wide, for commercial and non-commercial purposes,
  and in modified or unmodified form. If you're not OK with that,
  don't use the service.
- The following data items are considered *private data* that won't be
  shared with other users, business partners, or the public at large:
  * your password
  * your email address
  * your IM address (AIM, Jabber, or other instant messaging address)
  * your phone number
  * your "private messages"
  * your login credentials (username and password) for other services (Twitter, Facebook, etc.)
- Some private data may be published in aggregate, e.g. "30% of our
  users are registered with Hotmail addresses."
- Your notices (including files) can be downloaded and re-used by
  other services, either one-by-one or in bulk as
  [RSS](http://en.wikipedia.org/wiki/RSS) files.
- Your profile information (including subscriptions and avatars) can be
  downloaded and re-used by other services, either scraped from the HTML
  interface or in bulk as [FOAF](http://en.wikipedia.org/wiki/FOAF) files.
- Your notices will be forwarded to users who subscribe to them,
  including users on another microblogging service.
- Your profile information will be sent to microblogging services for
  users who subscribe to you or to whom you subscribe.
- Based on your email preferences, you may receive automated email
  messages for important system events, such as when others subscribe
  to your notices.
- Based on your email preferences, you may receive an email
  newsletter. You can opt out of the newsletter if you don't want to
  receive it.
- In urgent situations, administrators may send you email directly to
  your registered email address, even if you've requested no notices
  or newsletter. *Administrators will use digitally-signed email.*
- This service will comply with court orders to turn over your private
  information.

path: doc-src/privacy


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

You can post messages to %%site.name%% using many kinds of cell
phones that support SMS messaging. This site does not support SMS
directly; rather, it uses your carrier's email gateway to send and
receive messages.

Managing your SMS settings
--------------------------

Use the [SMS settings](%%action.smssettings%%) page to set your SMS
preferences. You can add or change your SMS number and set the
flags for SMS updates.

When you add or change your phone number, you'll receive a message on your
phone with a verification code. Enter it into the SMS settings page to
confirm that the owner of the phone authorizes sending it messages.

Note that only the carriers listed in the drop down list on the form
are supported by %%site.name%%. They're the only ones we know how to
make email addresses for.

Receiving messages
------------------

Once you've verified your phone number, you can enable sending
messages to your phone. If you have a lot of friends and a typical
phone, it can be hard to keep up.

Sending messages
----------------

To send a message, you must send an email to the incoming email
address visible on your SMS settings page. The method for sending
email from your phone varies from carrier to carrier and from handset
to handet; if in doubt, ask your carrier.

Keep your incoming email address a secret -- it's the only way we know
you're really you!

Commands
--------

You can use the following commands with %%site.name%%.

* on - turn on notifications
* off - turn off notifications
* help - show this help
* follow <nickname> - subscribe to user
* leave <nickname> - unsubscribe from user
* d <nickname> <text> - direct message to user
* get <nickname> - get last notice from user
* whois <nickname> - get profile info on user
* fav <nickname> - add user's last notice as a 'fave'
* stats - get your stats
* stop - same as 'off'
* quit - same as 'off'
* sub <nickname> - same as 'follow'
* unsub <nickname> - same as 'leave'
* last <nickname> - same as 'get'
* on <nickname> - not yet implemented.
* off <nickname> - not yet implemented.
* nudge <nickname> - not yet implemented.
* invite <phone number> - not yet implemented.
* track <word> - not yet implemented.
* untrack <word> - not yet implemented.
* track off - not yet implemented.
* untrack all - not yet implemented.
* tracks - not yet implemented.
* tracking - not yet implemented.

path: doc-src/sms


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

This service uses a Free microblogging tool called **GNU social**.
GNU social is available under the [GNU Affero General Public License
Version 3.0](http://www.fsf.org/licensing/licenses/agpl-3.0.html), a
Free Software license for network services.

You can get a copy of the software by following links from the
[GNU social main site](http://gnu.io/)¹. The version of the software
that runs on *this* site is unmodified from that version. The site
also depends on certain libraries and other software; these are all
bundled in the [GNU social repository](https://gitorious.org/social/mainline)²
and release archive files.

References
----------
1. GNU social main site, <http://gnu.io>
2. GNU social repository, <https://gitorious.org/social/mainline>

path: doc-src/source


code:
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->

%%site.name%% supports
[tags](http://en.wikipedia.org/wiki/Tag_(metadata)) to help you
organize your activities here. You can use tags for people and for
notices.

Tagging a notice
----------------

You can tag a notice using a *hashtag*; a # character followed by
letters and numbers as well as '.', '-', and '_'. Note that accented
latin characters are not supported, and non-roman scripts are right out.

The HTML for the notice will link to a stream of all the other notices
with that tag. This can be a great way to keep track of a conversation.

Tagging yourself
----------------

You can also add tags for yourself on your [profile
settings](%%action.profilesettings%%) page or by using the edit tags
button on your profile page. Use single words to
describe yourself, your experiences and your interest. The tags will
become links on your profile page to a list of all the users on the
site who use that same tag. It can be a nice way to find people who
are related to you geographically or who have a common interest.

Tagging others
--------------

You can also tag other users by using the edit tags button next to
their profile. Such tags are called *people tags*. Once you have
created a people tag, you can add or remove users from it using the
tag's edit form. This makes it easy to organize your subscriptions
into groups and sort through them separately. Also, it will let
you create custom lists of people that others can subscribe to.

You can also send a notice "to the attention of" your subscribers
whom you've marked with a particular tag (note: *not* people who've
marked themselves with that tag). "@#family hello" will send a
notice to all your subscribers you've marked with the tag 'family'.

Private and public people tags
------------------------------

A private people tag is only visible to the creator, it cannot be
subscribed to, but the timeline can be viewed. To create a new
private prepend a '.' to the tag in the tags editing box. To set
an existing public tag as private or vice-versa, go to the tag's
edit page.

path: doc-src/tags


code:
The gist
--------

We (the folks at [%%site.broughtby%%](%%site.broughtbyurl%%)) run a
service called %%site.name%% and would love for you to use it. Our
service is designed to give you as much control and ownership over
what goes in your notice stream as possible and encourage you to
express yourself freely. However, be responsible in what you post. In
particular, make sure that none of the prohibited items listed below
appear in your notice stream or get linked to from your notice stream (things
like spam, viruses, or hate content).

You can review our [Public Stream](%%action.top%%) to get a sense
of the types of notices that are welcome on our service (or not!). If
you find a %%site.name%% account that you believe violates our terms
of service, please check our [Contact](%%doc.contact%%) documentation.

(Note: Automattic, Inc., original creators of the below Terms of
Service, decided to make them available under a Creative Commons
Sharealike license, which means you’re more than welcome to steal it
and repurpose it for your own use. Just make sure to replace
references to us with ones to you. They’d appreciate a link to
[WordPress.com](http://www.wordpress.com/) somewhere on your site.
They spent a lot of money and time on the below, and other people
shouldn’t need to do the same. (We didn't!))

Terms of Service
----------------

The following terms and conditions govern all use of the %%site.name%%
website and all content, services and products available at or through
the website (taken together, the Website). The Website is owned and
operated by %%site.broughtby%% (“Operator”). The Website is offered
subject to your acceptance without modification of all of the terms
and conditions contained herein and all other operating rules,
policies (including, without limitation, Operator’s [Privacy
Policy](%%doc.privacy%%))
and procedures that may be published from time to time on this Site by
Operator (collectively, the “Agreement”).

Please read this Agreement carefully before accessing or using the
Website. By accessing or using any part of the web site, you agree to
become bound by the terms and conditions of this agreement. If you do
not agree to all the terms and conditions of this agreement, then you
may not access the Website or use any services. If these terms and
conditions are considered an offer by Operator, acceptance is
expressly limited to these terms. The Website is available only to
individuals who are at least 13 years old.

Your %%site.name%% Account and Site. If you
create a notice stream on the Website, you are responsible for
maintaining the security of your account and notice stream, and you
are fully responsible for all activities that occur under the account
and any other actions taken in connection with the notice stream. You
must not describe or assign keywords to your notice stream in a
misleading or unlawful manner, including in a manner intended to trade
on the name or reputation of others, and Operator may change or remove
any description or keyword that it considers inappropriate or
unlawful, or otherwise likely to cause Operator liability. You must
immediately notify Operator of any unauthorized uses of your notice
stream, your account or any other breaches of security. Operator will
not be liable for any acts or omissions by You, including any damages
of any kind incurred as a result of such acts or omissions.

Responsibility of Contributors. If you operate a
notice stream, comment on a notice stream, post material to the
Website, post links on the Website, or otherwise make (or allow any
third party to make) material available by means of the Website (any
such material, “Content”), You are entirely responsible for the
content of, and any harm resulting from, that Content. That is the
case regardless of whether the Content in question constitutes text,
graphics, an audio file, or computer software. By making Content
available, you represent and warrant that:

the downloading, copying and use of the Content will not infringe
the proprietary rights, including but not limited to the copyright,
patent, trademark or trade secret rights, of any third party;

if your employer has rights to intellectual property you create,
you have either (i) received permission from your employer to post or
make available the Content, including but not limited to any software,
or (ii) secured from your employer a waiver as to all rights in or to
the Content;

you have fully complied with any third-party licenses
relating to the Content, and have done all things necessary to
successfully pass through to end users any required terms;

the Content does not contain or install any viruses, worms, malware,
Trojan horses or other harmful or destructive content;

the Content is not spam, and does not contain unethical or
unwanted commercial content designed to drive traffic to third party
sites or boost the search engine rankings of third party sites, or to
further unlawful acts (such as phishing) or mislead recipients as to
the source of the material (such as spoofing);

if the Content is machine- or randomly-generated, it is for
purposes of direct entertainment, information and/or utility for you
or other users, and not for spam,

the Content is not libelous or defamatory (more info on
what that means), does not contain threats or incite violence towards
individuals or entities, and does not violate the privacy or publicity
rights of any third party;

your notice stream is not getting advertised via unwanted electronic
messages such as spam links on newsgroups, email lists, other notice streams
and web sites, and similar unsolicited promotional methods;

your notice stream is not named in a manner that misleads your
readers into thinking that you are another person or company. For
example, your notice stream’s URL or name is not the name of a person other
than yourself or company other than your own; and

you have, in the case of Content that includes computer code,
accurately categorized and/or described the type, nature, uses and
effects of the materials, whether requested to do so by Operator or
otherwise.

By submitting Content to Operator for inclusion on your Website, you
grant Operator a world-wide, royalty-free, and non-exclusive license
to reproduce, modify, adapt and publish the Content solely for the
purpose of displaying, distributing and promoting your notice
stream.

By submitting Content to Operator for inclusion on your Website,
you grant all readers the right to use, re-use, modify and/or
re-distribute the Content under the terms of the %%license.title%%.

If you delete Content, Operator will use reasonable efforts to remove it from
the Website, but you acknowledge that caching or references to the
Content may not be made immediately unavailable.

Without limiting any of those representations or warranties, Operator
has the right (though not the obligation) to, in Operator’s sole
discretion (i) refuse or remove any content that, in Operator’s
reasonable opinion, violates any Operator policy or is in any way
harmful or objectionable, or (ii) terminate or deny access to and use
of the Website to any individual or entity for any reason, in
Operator’s sole discretion.

Responsibility of Website Visitors. Operator has not reviewed,
and cannot review, all of the material, including computer software,
posted to the Website, and cannot therefore be responsible for that
material’s content, use or effects. By operating the Website,
Operator does not represent or imply that it endorses the material
there posted, or that it believes such material to be accurate, useful
or non-harmful. You are responsible for taking precautions as
necessary to protect yourself and your computer systems from viruses,
worms, Trojan horses, and other harmful or destructive content. The
Website may contain content that is offensive, indecent, or otherwise
objectionable, as well as content containing technical inaccuracies,
typographical mistakes, and other errors. The Website may also contain
material that violates the privacy or publicity rights, or infringes
the intellectual property and other proprietary rights, of third
parties, or the downloading, copying or use of which is subject to
additional terms and conditions, stated or unstated. Operator
disclaims any responsibility for any harm resulting from the use by
visitors of the Website, or from any downloading by those visitors of
content there posted.

Content Posted on Other Websites. We have not reviewed, and
cannot review, all of the material, including computer software, made
available through the websites and webpages to which %%site.name%%
links, and that link to %%site.name%%. Operator does not have any
control over those external websites and webpages, and is not
responsible for their contents or their use. By linking to a
external website or webpage, Operator does not represent or
imply that it endorses such website or webpage. You are responsible
for taking precautions as necessary to protect yourself and your
computer systems from viruses, worms, Trojan horses, and other harmful
or destructive content. Operator disclaims any responsibility for
any harm resulting from your use of external websites and
webpages.

Copyright Infringement and DMCA Policy. As Operator asks
others to respect its intellectual property rights, it respects the
intellectual property rights of others. If you believe that material
located on or linked to by %%site.name%% violates your copyright, you
are encouraged to notify Operator in accordance with Operator’s
Digital Millennium Copyright Act (”DMCA”) Policy. Operator will
respond to all such notices, including as required or appropriate by
removing the infringing material or disabling all links to the
infringing material. In the case of a visitor who may infringe or
repeatedly infringes the copyrights or other intellectual property
rights of Operator or others, Operator may, in its discretion,
terminate or deny access to and use of the Website. In the case of
such termination, Operator will have no obligation to provide a
refund of any amounts previously paid to Operator.

Intellectual Property. This Agreement does not
transfer from Operator to you any Operator or third party intellectual
property, and all right, title and interest in and to such property
will remain (as between the parties) solely with Operator.
%%site.name%%, the %%site.name%% logo, and all other trademarks,
service marks, graphics and logos used in connection with
%%site.name%%, or the Website are trademarks or registered trademarks
of Operator or Operator’s licensors. Other trademarks, service marks,
graphics and logos used in connection with the Website may be the
trademarks of other third parties. Your use of the Website grants you
no right or license to reproduce or otherwise use any Operator or
third-party trademarks.

Changes. Operator reserves the right, at its sole
discretion, to modify or replace any part of this Agreement. It is
your responsibility to check this Agreement periodically for changes.
Your continued use of or access to the Website following the posting
of any changes to this Agreement constitutes acceptance of those
changes. Operator may also, in the future, offer new services and/or
features through the Website (including, the release of new tools and
resources). Such new features and/or services shall be subject to the
terms and conditions of this Agreement.

Termination. Operator may terminate your access
to all or any part of the Website at any time, with or without cause,
with or without notice, effective immediately. If you wish to
terminate this Agreement or your %%site.name%% account (if you have
one), you may simply discontinue using the Website. All provisions of
this Agreement which by their nature should survive termination shall
survive termination, including, without limitation, ownership
provisions, warranty disclaimers, indemnity and limitations of
liability.

Disclaimer of Warranties. The Website is provided
“as is”. Operator and its suppliers and licensors hereby disclaim all
warranties of any kind, express or implied, including, without
limitation, the warranties of merchantability, fitness for a
particular purpose and non-infringement. Neither Operator nor its
suppliers and licensors, makes any warranty that the Website will be
error free or that access thereto will be continuous or uninterrupted.
If you’re actually reading this, here’s a treat. You understand that
you download from, or otherwise obtain content or services through,
the Website at your own discretion and risk.

Limitation of Liability. In no event will
Operator, or its suppliers or licensors, be liable with respect to any
subject matter of this agreement under any contract, negligence,
strict liability or other legal or equitable theory for: (i) any
special, incidental or consequential damages; (ii) the cost of
procurement or substitute products or services; (iii) for interruption
of use or loss or corruption of data; or (iv) for any amounts that
exceed the fees paid by you to Operator under this agreement during
the twelve (12) month period prior to the cause of action. Operator
shall have no liability for any failure or delay due to matters beyond
their reasonable control. The foregoing shall not apply to the extent
prohibited by applicable law.

General Representation and Warranty. You
represent and warrant that (i) your use of the Website will be in
strict accordance with the Operator Privacy Policy, with this
Agreement and with all applicable laws and regulations (including
without limitation any local laws or regulations in your country,
state, city, or other governmental area, regarding online conduct and
acceptable content, and including all applicable laws regarding the
transmission of technical data exported from the United States or the
country in which you reside) and (ii) your use of the Website will not
infringe or misappropriate the intellectual property rights of any
third party.

Indemnification. You agree to indemnify and hold
harmless Operator, its contractors, and its licensors, and their
respective directors, officers, employees and agents from and against
any and all claims and expenses, including attorneys’ fees, arising
out of your use of the Website, including but not limited to out of
your violation this Agreement.

Miscellaneous. This Agreement constitutes the
entire agreement between Operator and you concerning the subject
matter hereof, and they may only be modified by a written amendment
signed by an authorized executive of Operator, or by the posting by
Operator of a revised version. If any part of this Agreement is held
invalid or unenforceable, that part will be construed to reflect the
parties’ original intent, and the remaining portions will remain in
full force and effect. A waiver by either party of any term or
condition of this Agreement or any breach thereof, in any one
instance, will not waive such term or condition or any subsequent
breach thereof. You may assign your rights under this Agreement to any
party that consents to, and agrees to be bound by, its terms and
conditions; Operator may assign its rights under this Agreement
without condition. This Agreement will be binding upon and will inure
to the benefit of the parties, their successors and permitted
assigns.

*Originally published by Automattic, Inc. as the [WordPress.com Terms
of Service](http://en.wordpress.com/tos/) and made available by them
under the [Creative Commons Attribution-ShareAlike 3.0
License](http://creativecommons.org/licenses/by-sa/3.0/).
Modifications to remove reference to "VIP services", rename "blog" to
"notice stream", remove the choice-of-venue clause, and add variables
specific to instances of this software made by Control Yourself, Inc.
and made available under the terms of the same license.*

path: doc-src/tos


code:
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


code:
<?php

/**
 * This is the PHP OpenID library by JanRain, Inc.
 *
 * This module contains core utility functionality used by the
 * library.  See Consumer.php and Server.php for the consumer and
 * server implementations.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: See the COPYING file included in this distribution.
 *
 * @package OpenID
 * @author JanRain, Inc. <openid@janrain.com>
 * @copyright 2005-2008 Janrain, Inc.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
 */

/**
 * The library version string
 */
define('Auth_OpenID_VERSION', '2.2.2');

/**
 * Require the fetcher code.
 */
require_once "Auth/Yadis/PlainHTTPFetcher.php";
require_once "Auth/Yadis/ParanoidHTTPFetcher.php";
require_once "Auth/OpenID/BigMath.php";
require_once "Auth/OpenID/URINorm.php";

/**
 * Status code returned by the server when the only option is to show
 * an error page, since we do not have enough information to redirect
 * back to the consumer. The associated value is an error message that
 * should be displayed on an HTML error page.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_LOCAL_ERROR', 'local_error');

/**
 * Status code returned when there is an error to return in key-value
 * form to the consumer. The caller should return a 400 Bad Request
 * response with content-type text/plain and the value as the body.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_REMOTE_ERROR', 'remote_error');

/**
 * Status code returned when there is a key-value form OK response to
 * the consumer. The value associated with this code is the
 * response. The caller should return a 200 OK response with
 * content-type text/plain and the value as the body.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_REMOTE_OK', 'remote_ok');

/**
 * Status code returned when there is a redirect back to the
 * consumer. The value is the URL to redirect back to. The caller
 * should return a 302 Found redirect with a Location: header
 * containing the URL.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_REDIRECT', 'redirect');

/**
 * Status code returned when the caller needs to authenticate the
 * user. The associated value is a {@link Auth_OpenID_ServerRequest}
 * object that can be used to complete the authentication. If the user
 * has taken some authentication action, use the retry() method of the
 * {@link Auth_OpenID_ServerRequest} object to complete the request.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_DO_AUTH', 'do_auth');

/**
 * Status code returned when there were no OpenID arguments
 * passed. This code indicates that the caller should return a 200 OK
 * response and display an HTML page that says that this is an OpenID
 * server endpoint.
 *
 * @see Auth_OpenID_Server
 */
define('Auth_OpenID_DO_ABOUT', 'do_about');

/**
 * Defines for regexes and format checking.
 */
define('Auth_OpenID_letters',
       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");

define('Auth_OpenID_digits',
       "0123456789");

define('Auth_OpenID_punct',
       "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");

Auth_OpenID_include_init();

/**
 * The OpenID utility function class.
 *
 * @package OpenID
 * @access private
 */
class Auth_OpenID {

    /**
     * Return true if $thing is an Auth_OpenID_FailureResponse object;
     * false if not.
     *
     * @access private
     */
    static function isFailure($thing)
    {
        return is_a($thing, 'Auth_OpenID_FailureResponse');
    }

    /**
     * Gets the query data from the server environment based on the
     * request method used.  If GET was used, this looks at
     * $_SERVER['QUERY_STRING'] directly.  If POST was used, this
     * fetches data from the special php://input file stream.
     *
     * Returns an associative array of the query arguments.
     *
     * Skips invalid key/value pairs (i.e. keys with no '=value'
     * portion).
     *
     * Returns an empty array if neither GET nor POST was used, or if
     * POST was used but php://input cannot be opened.
     *
     * See background:
     * http://lists.openidenabled.com/pipermail/dev/2007-March/000395.html
     *
     * @access private
     */
    static function getQuery($query_str=null)
    {
        $data = array();

        if ($query_str !== null) {
            $data = Auth_OpenID::params_from_string($query_str);
        } else if (!array_key_exists('REQUEST_METHOD', $_SERVER)) {
            // Do nothing.
        } else {
          // XXX HACK FIXME HORRIBLE.
          //
          // POSTing to a URL with query parameters is acceptable, but
          // we don't have a clean way to distinguish those parameters
          // when we need to do things like return_to verification
          // which only want to look at one kind of parameter.  We're
          // going to emulate the behavior of some other environments
          // by defaulting to GET and overwriting with POST if POST
          // data is available.
          $data = Auth_OpenID::params_from_string($_SERVER['QUERY_STRING']);

          if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $str = file_get_contents('php://input');

            if ($str === false) {
              $post = array();
            } else {
              $post = Auth_OpenID::params_from_string($str);
            }

            $data = array_merge($data, $post);
          }
        }

        return $data;
    }

    static function params_from_string($str)
    {
        $chunks = explode("&", $str);

        $data = array();
        foreach ($chunks as $chunk) {
            $parts = explode("=", $chunk, 2);

            if (count($parts) != 2) {
                continue;
            }

            list($k, $v) = $parts;
            $data[urldecode($k)] = urldecode($v);
        }

        return $data;
    }

    /**
     * Create dir_name as a directory if it does not exist. If it
     * exists, make sure that it is, in fact, a directory.  Returns
     * true if the operation succeeded; false if not.
     *
     * @access private
     */
    static function ensureDir($dir_name)
    {
        if (is_dir($dir_name) || @mkdir($dir_name)) {
            return true;
        } else {
            $parent_dir = dirname($dir_name);

            // Terminal case; there is no parent directory to create.
            if ($parent_dir == $dir_name) {
                return true;
            }

            return (Auth_OpenID::ensureDir($parent_dir) && @mkdir($dir_name));
        }
    }

    /**
     * Adds a string prefix to all values of an array.  Returns a new
     * array containing the prefixed values.
     *
     * @access private
     */
    static function addPrefix($values, $prefix)
    {
        $new_values = array();
        foreach ($values as $s) {
            $new_values[] = $prefix . $s;
        }
        return $new_values;
    }

    /**
     * Convenience function for getting array values.  Given an array
     * $arr and a key $key, get the corresponding value from the array
     * or return $default if the key is absent.
     *
     * @access private
     */
    static function arrayGet($arr, $key, $fallback = null)
    {
        if (is_array($arr)) {
            if (array_key_exists($key, $arr)) {
                return $arr[$key];
            } else {
                return $fallback;
            }
        } else {
            trigger_error("Auth_OpenID::arrayGet (key = ".$key.") expected " .
                          "array as first parameter, got " .
                          gettype($arr), E_USER_WARNING);

            return false;
        }
    }

    /**
     * Replacement for PHP's broken parse_str.
     */
    static function parse_str($query)
    {
        if ($query === null) {
            return null;
        }

        $parts = explode('&', $query);

        $new_parts = array();
        for ($i = 0; $i < count($parts); $i++) {
            $pair = explode('=', $parts[$i]);

            if (count($pair) != 2) {
                continue;
            }

            list($key, $value) = $pair;
            $new_parts[urldecode($key)] = urldecode($value);
        }

        return $new_parts;
    }

    /**
     * Implements the PHP 5 'http_build_query' functionality.
     *
     * @access private
     * @param array $data Either an array key/value pairs or an array
     * of arrays, each of which holding two values: a key and a value,
     * sequentially.
     * @return string $result The result of url-encoding the key/value
     * pairs from $data into a URL query string
     * (e.g. "username=bob&id=56").
     */
    static function httpBuildQuery($data)
    {
        $pairs = array();
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $pairs[] = urlencode($value[0])."=".urlencode($value[1]);
            } else {
                $pairs[] = urlencode($key)."=".urlencode($value);
            }
        }
        return implode("&", $pairs);
    }

    /**
     * "Appends" query arguments onto a URL.  The URL may or may not
     * already have arguments (following a question mark).
     *
     * @access private
     * @param string $url A URL, which may or may not already have
     * arguments.
     * @param array $args Either an array key/value pairs or an array of
     * arrays, each of which holding two values: a key and a value,
     * sequentially.  If $args is an ordinary key/value array, the
     * parameters will be added to the URL in sorted alphabetical order;
     * if $args is an array of arrays, their order will be preserved.
     * @return string $url The original URL with the new parameters added.
     *
     */
    static function appendArgs($url, $args)
    {
        if (count($args) == 0) {
            return $url;
        }

        // Non-empty array; if it is an array of arrays, use
        // multisort; otherwise use sort.
        if (array_key_exists(0, $args) &&
            is_array($args[0])) {
            // Do nothing here.
        } else {
            $keys = array_keys($args);
            sort($keys);
            $new_args = array();
            foreach ($keys as $key) {
                $new_args[] = array($key, $args[$key]);
            }
            $args = $new_args;
        }

        $sep = '?';
        if (strpos($url, '?') !== false) {
            $sep = '&';
        }

        return $url . $sep . Auth_OpenID::httpBuildQuery($args);
    }

    /**
     * Implements python's urlunparse, which is not available in PHP.
     * Given the specified components of a URL, this function rebuilds
     * and returns the URL.
     *
     * @access private
     * @param string $scheme The scheme (e.g. 'http').  Defaults to 'http'.
     * @param string $host The host.  Required.
     * @param string $port The port.
     * @param string $path The path.
     * @param string $query The query.
     * @param string $fragment The fragment.
     * @return string $url The URL resulting from assembling the
     * specified components.
     */
    static function urlunparse($scheme, $host, $port = null, $path = '/',
                        $query = '', $fragment = '')
    {

        if (!$scheme) {
            $scheme = 'http';
        }

        if (!$host) {
            return false;
        }

        if (!$path) {
            $path = '';
        }

        $result = $scheme . "://" . $host;

        if ($port) {
            $result .= ":" . $port;
        }

        $result .= $path;

        if ($query) {
            $result .= "?" . $query;
        }

        if ($fragment) {
            $result .= "#" . $fragment;
        }

        return $result;
    }

    /**
     * Given a URL, this "normalizes" it by adding a trailing slash
     * and / or a leading http:// scheme where necessary.  Returns
     * null if the original URL is malformed and cannot be normalized.
     *
     * @access private
     * @param string $url The URL to be normalized.
     * @return mixed $new_url The URL after normalization, or null if
     * $url was malformed.
     */
    static function normalizeUrl($url)
    {
        @$parsed = parse_url($url);

        if (!$parsed) {
            return null;
        }

        if (isset($parsed['scheme']) &&
            isset($parsed['host'])) {
            $scheme = strtolower($parsed['scheme']);
            if (!in_array($scheme, array('http', 'https'))) {
                return null;
            }
        } else {
            $url = 'http://' . $url;
        }

        $normalized = Auth_OpenID_urinorm($url);
        if ($normalized === null) {
            return null;
        }
        list($defragged, $frag) = Auth_OpenID::urldefrag($normalized);
        return $defragged;
    }

    /**
     * Replacement (wrapper) for PHP's intval() because it's broken.
     *
     * @access private
     */
    static function intval($value)
    {
        $re = "/^\\d+$/";

        if (!preg_match($re, $value)) {
            return false;
        }

        return intval($value);
    }

    /**
     * Count the number of bytes in a string independently of
     * multibyte support conditions.
     *
     * @param string $str The string of bytes to count.
     * @return int The number of bytes in $str.
     */
    static function bytes($str)
    {
        return strlen(bin2hex($str)) / 2;
    }

    /**
     * Get the bytes in a string independently of multibyte support
     * conditions.
     */
    static function toBytes($str)
    {
        $hex = bin2hex($str);

        if (!$hex) {
            return array();
        }

        $b = array();
        for ($i = 0; $i < strlen($hex); $i += 2) {
            $b[] = chr(base_convert(substr($hex, $i, 2), 16, 10));
        }

        return $b;
    }

    static function urldefrag($url)
    {
        $parts = explode("#", $url, 2);

        if (count($parts) == 1) {
            return array($parts[0], "");
        } else {
            return $parts;
        }
    }

    static function filter($callback, &$sequence)
    {
        $result = array();

        foreach ($sequence as $item) {
            if (call_user_func_array($callback, array($item))) {
                $result[] = $item;
            }
        }

        return $result;
    }

    static function update(&$dest, &$src)
    {
        foreach ($src as $k => $v) {
            $dest[$k] = $v;
        }
    }

    /**
     * Wrap PHP's standard error_log functionality.  Use this to
     * perform all logging. It will interpolate any additional
     * arguments into the format string before logging.
     *
     * @param string $format_string The sprintf format for the message
     */
    static function log($format_string)
    {
        $args = func_get_args();
        $message = call_user_func_array('sprintf', $args);
        error_log($message);
    }

    static function autoSubmitHTML($form, $title="OpenId transaction in progress")
    {
        return("".
               "<title>".
               $title .
               "</title>".
               "".
               $form .
               "".
               "".
               "");
    }
}

/*
 * Function to run when this file is included.
 * Abstracted to a function to make life easier
 * for some PHP optimizers.
 */
function Auth_OpenID_include_init() {
  if (Auth_OpenID_getMathLib() === null) {
    Auth_OpenID_setNoMathSupport();
  }
}