code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Plugin to pull WikiHow-style user avatars at OpenID setup time.
 * These are not currently exposed via OpenID.
 *
 * PHP version 5
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Plugins
 * @package   StatusNet
 * @author    Brion Vibber <brion@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Sample plugin main class
 *
 * Each plugin requires a main class to interact with the StatusNet system.
 *
 * @category  Plugins
 * @package   WikiHowProfilePlugin
 * @author    Brion Vibber <brion@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class WikiHowProfilePlugin extends Plugin
{
    function onPluginVersion(&$versions)
    {
        $versions[] = array('name' => 'WikiHow avatar fetcher',
                            'version' => GNUSOCIAL_VERSION,
                            'author' => 'Brion Vibber',
                            'homepage' => 'http://status.net/wiki/Plugin:Sample',
                            'rawdescription' =>
                            // TRANS: Plugin description.
                            _m('Fetches avatar and other profile information for WikiHow users when setting up an account via OpenID.'));
        return true;
    }

    /**
     * Hook for OpenID user creation; we'll pull the avatar.
     *
     * @param User $user
     * @param string $canonical OpenID provider URL
     * @param array $sreg query data from provider
     */
    function onEndOpenIDCreateNewUser($user, $canonical, $sreg)
    {
        $this->updateProfile($user, $canonical);
        return true;
    }

    /**
     * Hook for OpenID profile updating; we'll pull the avatar.
     *
     * @param User $user
     * @param string $canonical OpenID provider URL (wiki profile page)
     * @param array $sreg query data from provider
     */
    function onEndOpenIDUpdateUser($user, $canonical, $sreg)
    {
        $this->updateProfile($user, $canonical);
        return true;
    }

    /**
     * @param User $user
     * @param string $canonical OpenID provider URL (wiki profile page)
     */
    private function updateProfile($user, $canonical)
    {
        $prefix = 'http://www.wikihow.com/User:';

        if (substr($canonical, 0, strlen($prefix)) == $prefix) {
            // Yes, it's a WikiHow user!
            $profile = $this->fetchProfile($canonical);

            if (!empty($profile['avatar'])) {
                $this->saveAvatar($user, $profile['avatar']);
            }
        }
    }

    /**
     * Given a user's WikiHow profile URL, find their avatar.
     *
     * @param string $profileUrl user page on the wiki
     *
     * @return array of data; possible members:
     *               'avatar' => full URL to avatar image
     *
     * @throws Exception on various low-level failures
     *
     * @todo pull location, web site, and about sections -- they aren't currently marked up cleanly.
     */
    private function fetchProfile($profileUrl)
    {
        $client = HTTPClient::start();
        $response = $client->get($profileUrl);
        if (!$response->isOk()) {
            // TRANS: Exception thrown when fetching a WikiHow profile page fails.
            throw new Exception(_m('WikiHow profile page fetch failed.'));
            // HTTP error response already logged.
            return false;
        }

        // Suppress warnings during HTML parsing; non-well-formed bits will
        // spew horrible warning everywhere even though it works fine.
        $old = error_reporting();
        error_reporting($old & ~E_WARNING);

        $dom = new DOMDocument();
        $ok = $dom->loadHTML($response->getBody());

        error_reporting($old);

        if (!$ok) {
            // TRANS: Exception thrown when parsing a WikiHow profile page fails.
            throw new Exception(_m('HTML parse failure during check for WikiHow avatar.'));
            return false;
        }

        $data = array();

        $avatar = $dom->getElementById('avatarULimg');
        if ($avatar) {
            $src = $avatar->getAttribute('src');

            $base = new Net_URL2($profileUrl);
            $absolute = $base->resolve($src);
            $avatarUrl = strval($absolute);

            common_log(LOG_DEBUG, "WikiHow avatar found for $profileUrl - $avatarUrl");
            $data['avatar'] = $avatarUrl;
        }

        return $data;
    }

    /**
     * Actually save the avatar we found locally.
     *
     * @param User $user
     * @param string $url to avatar URL
     * @todo merge wrapper funcs for this into common place for 1.0 core
     */
    private function saveAvatar($user, $url)
    {
        if (!common_valid_http_url($url)) {
            // TRANS: Server exception thrown when an avatar URL is invalid.
            // TRANS: %s is the invalid avatar URL.
            throw new ServerException(sprintf(_m('Invalid avatar URL %s.'), $url));
        }

        // @todo FIXME: This should be better encapsulated
        // ripped from OStatus via oauthstore.php (for old OMB client)
        $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
        try {
            if (!copy($url, $temp_filename)) {
                // TRANS: Exception thrown when fetching an avatar from a URL fails.
                // TRANS: %s is a URL.
                throw new ServerException(sprintf(_m('Unable to fetch avatar from %s.'), $url));
            }

            $profile = $user->getProfile();
            $id = $profile->id;
            // @fixme should we be using different ids?

            $imagefile = new ImageFile($id, $temp_filename);
            $filename = Avatar::filename($id,
                                         image_type_to_extension($imagefile->type),
                                         null,
                                         common_timestamp());
            rename($temp_filename, Avatar::path($filename));
        } catch (Exception $e) {
            unlink($temp_filename);
            throw $e;
        }
        $profile->setOriginal($filename);
    }
}


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#. TRANS: Plugin description.
#: WikiHowProfilePlugin.php:60
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
#: WikiHowProfilePlugin.php:126
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
#: WikiHowProfilePlugin.php:143
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#: WikiHowProfilePlugin.php:176
#, php-format
msgid "Invalid avatar URL %s."
msgstr ""

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#: WikiHowProfilePlugin.php:186
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr ""

license: mit


code:
# Translation of StatusNet - WikiHowProfile to German (Deutsch)
# Exported from translatewiki.net
#
# Author: ChrisiPK
# Author: Giftpflanze
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: German <https://translatewiki.net/wiki/Portal:de>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: de\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Holt Avatar- und andere Profilinformationen für WikiHow-Benutzer beim "
"Aufsetzen eines Kontos über OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Laden des WikiHow-Profils fehlgeschlagen."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr "HTML-Parsingfehler bei der Suche des WikiHow-Avatars."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Ungültige Avatar-URL %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Kann Avatar nicht von %s holen."


code:
# Translation of StatusNet - WikiHowProfile to Spanish (español)
# Exported from translatewiki.net
#
# Author: Armando-Martin
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Recupera el avatar y otra información de perfil para los usuarios de WikiHow "
"al crear una cuenta mediante OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Error al recuperar la página de perfil de WikiHow."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""
"Error de interpretación de HTML durante la comprobación del avatar de "
"WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "La dirección URL del avatar, %s, es incorrecta."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "No se pudo recuperar el avatar desde %s."


code:
# Translation of StatusNet - WikiHowProfile to Basque (euskara)
# Exported from translatewiki.net
#
# Author: Artsuaga
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Abatarraren %s URL helbidea okerra da."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Ezin izan da abatarra lortu %s helbidetik."


code:
# Translation of StatusNet - WikiHowProfile to French (français)
# Exported from translatewiki.net
#
# Author: DavidL
# Author: Verdy p
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: French <https://translatewiki.net/wiki/Portal:fr>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: fr\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Récupère l’avatar et les autres informations de profil des utilisateurs "
"WikiHow lorsqu’ils créent un compte via OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "La recherche de la page de profile WikiHow a échoué."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""
"Échec de l'interprétation HTML durant la vérification de l'avatar WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Adresse URL d’avatar « %s » invalide."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Impossible de récupérer l’avatar depuis « %s »."


code:
# Translation of StatusNet - WikiHowProfile to Galician (galego)
# Exported from translatewiki.net
#
# Author: Toliño
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: Galician <https://translatewiki.net/wiki/Portal:gl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: gl\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Recupera o avatar e outra información de perfil para os usuarios de WikiHow "
"ao crear unha conta mediante o OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Erro ao recuperar a páxina de perfil WikiHow."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr "Erro de interpretación HTML durante a comprobación do avatar WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "O enderezo URL do avatar, %s, é incorrecto."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Non se puido recuperar o avatar desde %s."


code:
# Translation of StatusNet - WikiHowProfile to Interlingua (interlingua)
# Exported from translatewiki.net
#
# Author: McDutchie
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: Interlingua <https://translatewiki.net/wiki/Portal:ia>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ia\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Obtene le avatar e altere informationes de profilo pro usatores de WikiHow "
"durante le creation de un conto via OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Le obtention del pagina de profilo de WikiHow ha fallite."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""
"Problema de interpretar le HTML durante le verification del presentia de un "
"avatar de WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "URL de avatar %s invalide."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Incapace de obtener avatar ab %s."


code:
# Translation of StatusNet - WikiHowProfile to Macedonian (македонски)
# Exported from translatewiki.net
#
# Author: Bjankuloski06
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: Macedonian <https://translatewiki.net/wiki/Portal:mk>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: mk\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n == 1 || n%10 == 1) ? 0 : 1;\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Презема аватар и други профилни податоци за корисници на WikiHow при "
"создавање на сметка преку OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Не успеав да ја добијам профилната страница од WikiHow."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr "Не успеа парсирањето на HTML при проверката на аватар од WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Неважечка URL-адреса на аватарот: %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Не можев да го преземам аватарот од %s."


code:
# Translation of StatusNet - WikiHowProfile to Malay (Bahasa Melayu)
# Exported from translatewiki.net
#
# Author: Anakmalaysia
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:28+0000\n"
"Language-Team: Malay <https://translatewiki.net/wiki/Portal:ms>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ms\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Mengambil avatar dan maklumat profil yang lain untuk pengguna WikiHow "
"apabila membuka akaun melalui OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "URL avatar %s tidak sah."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Avatar tidak dapat diambil dari %s."


code:
# Translation of StatusNet - WikiHowProfile to Dutch (Nederlands)
# Exported from translatewiki.net
#
# Author: Siebrand
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Dutch <https://translatewiki.net/wiki/Portal:nl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: nl\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Haalt avatar- en andere gegevens op voor WikiHow-gebruikers die een "
"gebruiker aanmaken via OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Het ophalen van de profielpagina van WikiHow is mislukt."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""
"Het verwerken van de HTML is mislukt tijdens het controleren op de WikiHow-"
"avatar."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Ongeldige avatar-URL %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Het was niet mogelijk om de avatar op te halen van %s."


code:
# Translation of StatusNet - WikiHowProfile to Russian (русский)
# Exported from translatewiki.net
#
# Author: Lockal
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Russian <https://translatewiki.net/wiki/Portal:ru>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ru\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Запрашивает аватару и прочую информацию из профиля пользователя WikiHow при "
"создании учётной записи с помощью OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Неверный URL-адрес аватары %s"

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Не удаётся получить аватару из %s."


code:
# Translation of StatusNet - WikiHowProfile to Tagalog (Tagalog)
# Exported from translatewiki.net
#
# Author: AnakngAraw
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Tagalog <https://translatewiki.net/wiki/Portal:tl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: tl\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Dumarampot ng abatar at ibang kabatiran ng balangkas para sa mga tagagamit "
"ng WikiHow kapag nagtatalaga ng isang akawnt sa pamamagitan ng OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr "Nabigo ang pagsalok sa pahina ng balangkas ng WikiHow."

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr "Kabiguan ng parse ng HTML habang sinusuri para sa abatar ng WikiHow."

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Hindi tanggap na URL ng abatar ang %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Hindi nagawang damputin ang huwaran mula sa %s."


code:
# Translation of StatusNet - WikiHowProfile to Turkish (Türkçe)
# Exported from translatewiki.net
#
# Author: Maidis
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Turkish <https://translatewiki.net/wiki/Portal:tr>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: tr\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"OpenID aracılığıyla hesap oluşturan WikiHow kullanıcıları için kullanıcı "
"resimlerini ve diğer profil bilgilerini alır."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Geçersiz kullanıcı resmi bağlantısı %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "%s'ten kullanıcı resmi alınamıyor."


code:
# Translation of StatusNet - WikiHowProfile to Ukrainian (українська)
# Exported from translatewiki.net
#
# Author: Boogie
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - WikiHowProfile\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Ukrainian <https://translatewiki.net/wiki/Portal:uk>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:54+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: uk\n"
"X-Message-Group: #out-statusnet-plugin-wikihowprofile\n"
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: Plugin description.
msgid ""
"Fetches avatar and other profile information for WikiHow users when setting "
"up an account via OpenID."
msgstr ""
"Запитує аватар та іншу супутню інформацію з WikiHow для користувачів, котрі "
"створюють акаунти через OpenID."

#. TRANS: Exception thrown when fetching a WikiHow profile page fails.
msgid "WikiHow profile page fetch failed."
msgstr ""

#. TRANS: Exception thrown when parsing a WikiHow profile page fails.
msgid "HTML parse failure during check for WikiHow avatar."
msgstr ""

#. TRANS: Server exception thrown when an avatar URL is invalid.
#. TRANS: %s is the invalid avatar URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Невірна URL-адреса аватари %s."

#. TRANS: Exception thrown when fetching an avatar from a URL fails.
#. TRANS: %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Неможливо завантажити аватару з %s."


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2009, StatusNet, Inc.
 *
 * Plugin to implement cache interface for XCache variable cache
 *
 * PHP version 5
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Cache
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * A plugin to use XCache's variable cache for the cache interface
 *
 * New plugin interface lets us use alternative cache systems
 * for caching. This one uses XCache's variable cache.
 *
 * @category  Cache
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */
class XCachePlugin extends Plugin
{
    /**
     * Get a value associated with a key
     *
     * The value should have been set previously.
     *
     * @param string &$key   in; Lookup key
     * @param mixed  &$value out; value associated with key
     *
     * @return boolean hook success
     */
    function onStartCacheGet(&$key, &$value)
    {
        if (!xcache_isset($key)) {
            $value = false;
        } else {
            $value = xcache_get($key);
            $value = unserialize($value);
        }
        Event::handle('EndCacheGet', array($key, &$value));
        return false;
    }

    /**
     * Associate a value with a key
     *
     * @param string  &$key     in; Key to use for lookups
     * @param mixed   &$value   in; Value to associate
     * @param integer &$flag    in; Flag (passed through to Memcache)
     * @param integer &$expiry  in; Expiry (passed through to Memcache)
     * @param boolean &$success out; Whether the set was successful
     *
     * @return boolean hook success
     */
    function onStartCacheSet(&$key, &$value, &$flag, &$expiry, &$success)
    {
        $success = xcache_set($key, serialize($value));

        Event::handle('EndCacheSet', array($key, $value, $flag,
                                           $expiry));
        return false;
    }

    /**
     * Delete a value associated with a key
     *
     * @param string  &$key     in; Key to lookup
     * @param boolean &$success out; whether it worked
     *
     * @return boolean hook success
     */
    function onStartCacheDelete(&$key, &$success)
    {
        $success = xcache_unset($key);
        Event::handle('EndCacheDelete', array($key));
        return false;
    }

    function onPluginVersion(&$versions)
    {
        $versions[] = array('name' => 'XCache',
                            'version' => GNUSOCIAL_VERSION,
                            'author' => 'Craig Andrews',
                            'homepage' => 'http://status.net/wiki/Plugin:XCache',
                            'rawdescription' =>
                            // TRANS: Plugin description.
                            _m('Use the XCache variable cache to cache query results.'));
        return true;
    }
}


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#. TRANS: Plugin description.
#: XCachePlugin.php:117
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""


code:
# Translation of StatusNet - XCache to Asturian (asturianu)
# Exported from translatewiki.net
#
# Author: Xuacu
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Asturian <https://translatewiki.net/wiki/Portal:ast>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ast\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Usar la cache variable XCache pa "
"cachear los resultaos de la consulta."


code:
# Translation of StatusNet - XCache to Breton (brezhoneg)
# Exported from translatewiki.net
#
# Author: Fulup
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Breton <https://translatewiki.net/wiki/Portal:br>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: br\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Ober gant ar grubuilh hegemm XCache</"
"a> da grubuilhañ disoc'hoù ar rekedoù."


code:
# Translation of StatusNet - XCache to German (Deutsch)
# Exported from translatewiki.net
#
# Author: Giftpflanze
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: German <https://translatewiki.net/wiki/Portal:de>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: de\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Benutze den XCache variablen "
"Cache um Suchergebnisse zu cachen."


code:
# Translation of StatusNet - XCache to Spanish (español)
# Exported from translatewiki.net
#
# Author: Locos epraix
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Language-Team: Spanish <https://translatewiki.net/wiki/Portal:es>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: es\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Utilice la caché variable XCache "
"para guardar los resultados de consultas."


code:
# Translation of StatusNet - XCache to Basque (euskara)
# Exported from translatewiki.net
#
# Author: Artsuaga
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:29+0000\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Erabili XCache aldagairen katxea "
"kontsultako emaitzak katxeatzeko."


code:
# Translation of StatusNet - XCache to Finnish (suomi)
# Exported from translatewiki.net
#
# Author: Centerlink
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Finnish <https://translatewiki.net/wiki/Portal:fi>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: fi\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Käytä XCache-muuttujavälimuistia "
"kyselyn tulosten tallentamiseksi välimuistiin."


code:
# Translation of StatusNet - XCache to French (français)
# Exported from translatewiki.net
#
# Author: Verdy p
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: French <https://translatewiki.net/wiki/Portal:fr>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: fr\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Utilisez le cache variable XCache</"
"a> pour mettre en cache les résultats de requêtes."


code:
# Translation of StatusNet - XCache to Galician (galego)
# Exported from translatewiki.net
#
# Author: Toliño
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Galician <https://translatewiki.net/wiki/Portal:gl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: gl\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Usar a caché variable XCache "
"para gardar os resultados das pescudas na memoria caché."


code:
# Translation of StatusNet - XCache to Hebrew (עברית)
# Exported from translatewiki.net
#
# Author: YaronSh
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Hebrew <https://translatewiki.net/wiki/Portal:he>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: he\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"שימוש במשתנה XCache לשמירת "
"תוצאות השאילתות במטמון."


code:
# Translation of StatusNet - XCache to Interlingua (interlingua)
# Exported from translatewiki.net
#
# Author: McDutchie
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Interlingua <https://translatewiki.net/wiki/Portal:ia>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ia\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Usar le cache de variabiles XCache</"
"a> pro immagazinar le resultatos de consultas."


code:
# Translation of StatusNet - XCache to Indonesian (Bahasa Indonesia)
# Exported from translatewiki.net
#
# Author: Farras
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Indonesian <https://translatewiki.net/wiki/Portal:id>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: id\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Gunakan tembolok variabel XCache "
"untuk menembolokkan hasil pencarian."


code:
# Translation of StatusNet - XCache to Macedonian (македонски)
# Exported from translatewiki.net
#
# Author: Bjankuloski06
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Macedonian <https://translatewiki.net/wiki/Portal:mk>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: mk\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n == 1 || n%10 == 1) ? 0 : 1;\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Користи променлив кеш XCache за "
"кеширање на резултати од барања."


code:
# Translation of StatusNet - XCache to Malay (Bahasa Melayu)
# Exported from translatewiki.net
#
# Author: Anakmalaysia
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Malay <https://translatewiki.net/wiki/Portal:ms>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ms\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Gunakan ''cache'' pembolehubah XCache untuk menyimpan hasil pertanyaan dalam ''cache''."


code:
# Translation of StatusNet - XCache to Norwegian Bokmål (norsk (bokmål))
# Exported from translatewiki.net
#
# Author: Nghtwlkr
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:30+0000\n"
"Language-Team: Norwegian Bokmål <https://translatewiki.net/wiki/Portal:nb>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: nb\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Bruk XCache-"
"variabelhurtiglageret til å hurtiglagre søkeresultat."


code:
# Translation of StatusNet - XCache to Dutch (Nederlands)
# Exported from translatewiki.net
#
# Author: Siebrand
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Dutch <https://translatewiki.net/wiki/Portal:nl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: nl\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"XCache cache gebruiken voor het "
"cachen van zoekopdrachtresultaten."


code:
# Translation of StatusNet - XCache to Polish (polski)
# Exported from translatewiki.net
#
# Author: BeginaFelicysym
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"Plural-Forms: nplurals=3; plural=(n == 1) ? 0 : ( (n%10 >= 2 && n%10 <= 4 && "
"(n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Używa zmiennej pamięci podręcznej XCache do buforowania wyników kwerendy."


code:
# Translation of StatusNet - XCache to Portuguese (português)
# Exported from translatewiki.net
#
# Author: Waldir
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Portuguese <https://translatewiki.net/wiki/Portal:pt>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: pt\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Utilizar a cache variável XCache "
"para armazenar resultados de consultas."


code:
# Translation of StatusNet - XCache to Brazilian Portuguese (português do Brasil)
# Exported from translatewiki.net
#
# Author: Giro720
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Brazilian Portuguese <https://translatewiki.net/wiki/Portal:"
"pt-br>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: pt-br\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Utilizar o cache variável XCache "
"para guardar os resultados de consultas."


code:
# Translation of StatusNet - XCache to Russian (русский)
# Exported from translatewiki.net
#
# Author: Александр Сигачёв
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Russian <https://translatewiki.net/wiki/Portal:ru>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: ru\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Использование XCache для "
"кеширования результатов запросов."


code:
# Translation of StatusNet - XCache to Tagalog (Tagalog)
# Exported from translatewiki.net
#
# Author: AnakngAraw
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Tagalog <https://translatewiki.net/wiki/Portal:tl>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: tl\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Gamitin ang nababagong taguan na XCache upang ikubli ang mga kinalabasan ng pagtatanong."


code:
# Translation of StatusNet - XCache to Turkish (Türkçe)
# Exported from translatewiki.net
#
# Author: Maidis
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Turkish <https://translatewiki.net/wiki/Portal:tr>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: tr\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Sorgulama sonuçlarını saklamak için XCache değişken önbelleğini kullan."


code:
# Translation of StatusNet - XCache to Ukrainian (українська)
# Exported from translatewiki.net
#
# Author: Boogie
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - XCache\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:31+0000\n"
"Language-Team: Ukrainian <https://translatewiki.net/wiki/Portal:uk>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-05 21:52:14+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: uk\n"
"X-Message-Group: #out-statusnet-plugin-xcache\n"
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: Plugin description.
msgid ""
"Use the XCache variable cache to "
"cache query results."
msgstr ""
"Використання XCache для "
"різноманітних запитів щодо кешу."


code:
XMPP (eXtended Message and Presence Protocol, <http://xmpp.org/>) is the
federating instant-messaging protocol of the future. It is wildly used
all over the world by organisations, private individuals and everyone.

GNU social allows you to receive and distribute messages via XMPP using
this plugin. To get it running, you must also use an active XMPP account.

Installation
============
Add an addPlugin call to your config.php with your settings. Please read
the "Pre-requisites" section of what is required for this to work.

Example
-------
The example account "update@site.example" is hosted on a machine which
can be reached at the hostname "xmpp.site.example".

addPlugin('Xmpp', array(
    'user'      => 'update',
    'server'    => 'site.example',
    'host'      => 'xmpp.site.example',
    'password'  => '...',
));

Pre-requisites
==============

0. You may want to strongly consider setting up your own XMPP server.
   We highly recommend the XMPP server "Prosody" <https://prosody.im/>
   because it is actively developed and highly secure and efficient. It
   is of course also free software under the MIT license. The following
   three pages will help you get it running, even self-hosted at home:

      0.1 https://prosody.im/doc/dns
      0.2 https://prosody.im/doc/install
      0.3 https://prosody.im/doc/configure

1. You must register an XMPP user ID (JID) which is used to send and
   receive messages. Call it something like "update@site.example" or
   similar to hint at what the account is made for. You may register
   the account on any public server (jabber.org, jit.si, etc...) if
   you cannot run one yourself.

   GNU social will not register anything for you, this must be done
   manually, preferrably using an XMPP client like Swift, Empathy,
   Jitsi or maybe even the commandline on your own server. With
   prosody, that'd be (perhaps prepended with 'sudo'):

      prosodyctl adduser update@site.example

2. Configure your site's XMPP variables, as described below in the
   Settings section below.

3. Learn to use the GNU social daemons for processing notice queues,
   background checks and other processes which would be too slow to
   perform on an active site. Using XMPP requires the "imdaemon" to
   run, since a long-running XMPP connection is somewhat necessary.

Settings
========

Required
--------
user        User part of the jid (like 'update')
server      Host part of the jid (like 'site.example')
password    The account's password. (your secret string)

Optional
--------
resource    JID resource. Default: 'gnusocial'
encryption  TLS server? Default: true
host        Hostname for XMPP server? Default: same as server
port        XMPP server port. Default: 5222
debug       Log extra debug info. Default: false
public      JIDs that should get the public feed (see "Public feed").

Since we do not currently support DNS SRV record lookup, please note
that you may have to enter an alternative 'host' parameter. This is
the case when update@site.example is not handled by the direct _address_
"site.example" but rather something like "xmpp.site.example".

Public feed
===========

You can send *all* messages from your social networking site to a
third-party service using XMPP. This can be useful for providing
search, indexing, bridging, or other cool services. Maybe a text
display next to your coffee machine at work.

To configure a downstream site to receive your public stream, add
their "JID" (Jabber ID) in the "public" array in your addPlugin call.
For example

addPlugin(array(
    [...]
    'public' => array('awesomebot@site.example'),

As the Pre-requisites section says, please only try to configure this
with daemons running properly in the background.

path: plugins/Xmpp/README


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2009, StatusNet, Inc.
 *
 * Send and receive notices using the XMPP network
 *
 * PHP version 5
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  IM
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Plugin for XMPP
 *
 * @category  Plugin
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class XmppPlugin extends ImPlugin
{
    public $server = null;
    public $port = 5222;
    public $user =  'update';
    public $resource = 'gnusocial';
    public $encryption = true;
    public $password = null;
    public $host = null;  // only set if != server
    public $debug = false; // print extra debug info

    public $transport = 'xmpp';

    function getDisplayName(){
        // TRANS: Plugin display name.
        return _m('XMPP/Jabber');
    }

    /**
     * Splits a Jabber ID (JID) into node, domain, and resource portions.
     *
     * Based on validation routine submitted by:
     * @copyright 2009 Patrick Georgi <patrick@georgi-clan.de>
     * @license Licensed under ISC-L, which is compatible with everything else that keeps the copyright notice intact.
     *
     * @param string $jid string to check
     *
     * @return array with "node", "domain", and "resource" indices
     * @throws Exception if input is not valid
     */
    protected function splitJid($jid)
    {
        $chars = '';
        /* the following definitions come from stringprep, Appendix C,
           which is used in its entirety by nodeprop, Chapter 5, "Prohibited Output" */
        /* C1.1 ASCII space characters */
        $chars .= "\x{20}";
        /* C1.2 Non-ASCII space characters */
        $chars .= "\x{a0}\x{1680}\x{2000}-\x{200b}\x{202f}\x{205f}\x{3000a}";
        /* C2.1 ASCII control characters */
        $chars .= "\x{00}-\x{1f}\x{7f}";
        /* C2.2 Non-ASCII control characters */
        $chars .= "\x{80}-\x{9f}\x{6dd}\x{70f}\x{180e}\x{200c}\x{200d}\x{2028}\x{2029}\x{2060}-\x{2063}\x{206a}-\x{206f}\x{feff}\x{fff9}-\x{fffc}\x{1d173}-\x{1d17a}";
        /* C3 - Private Use */
        $chars .= "\x{e000}-\x{f8ff}\x{f0000}-\x{ffffd}\x{100000}-\x{10fffd}";
        /* C4 - Non-character code points */
        $chars .= "\x{fdd0}-\x{fdef}\x{fffe}\x{ffff}\x{1fffe}\x{1ffff}\x{2fffe}\x{2ffff}\x{3fffe}\x{3ffff}\x{4fffe}\x{4ffff}\x{5fffe}\x{5ffff}\x{6fffe}\x{6ffff}\x{7fffe}\x{7ffff}\x{8fffe}\x{8ffff}\x{9fffe}\x{9ffff}\x{afffe}\x{affff}\x{bfffe}\x{bffff}\x{cfffe}\x{cffff}\x{dfffe}\x{dffff}\x{efffe}\x{effff}\x{ffffe}\x{fffff}\x{10fffe}\x{10ffff}";
        /* C5 - Surrogate codes */
        $chars .= "\x{d800}-\x{dfff}";
        /* C6 - Inappropriate for plain text */
        $chars .= "\x{fff9}-\x{fffd}";
        /* C7 - Inappropriate for canonical representation */
        $chars .= "\x{2ff0}-\x{2ffb}";
        /* C8 - Change display properties or are deprecated */
        $chars .= "\x{340}\x{341}\x{200e}\x{200f}\x{202a}-\x{202e}\x{206a}-\x{206f}";
        /* C9 - Tagging characters */
        $chars .= "\x{e0001}\x{e0020}-\x{e007f}";

        /* Nodeprep forbids some more characters */
        $nodeprepchars = $chars;
        $nodeprepchars .= "\x{22}\x{26}\x{27}\x{2f}\x{3a}\x{3c}\x{3e}\x{40}";

        $parts = explode("/", $jid, 2);
        if (count($parts) > 1) {
            $resource = $parts[1];
            if ($resource == '') {
                // Warning: empty resource isn't legit.
                // But if we're normalizing, we may as well take it...
            }
        } else {
            $resource = null;
        }

        $node = explode("@", $parts[0]);
        if ((count($node) > 2) || (count($node) == 0)) {
            // TRANS: Exception thrown when using too many @ signs in a Jabber ID.
            throw new Exception(_m('Invalid JID: too many @s.'));
        } else if (count($node) == 1) {
            $domain = $node[0];
            $node = null;
        } else {
            $domain = $node[1];
            $node = $node[0];
            if ($node == '') {
            // TRANS: Exception thrown when using @ sign not followed by a Jabber ID.
                throw new Exception(_m('Invalid JID: @ but no node'));
            }
        }

        // Length limits per http://xmpp.org/rfcs/rfc3920.html#addressing
        if ($node !== null) {
            if (strlen($node) > 1023) {
                // TRANS: Exception thrown when using too long a Jabber ID (>1023).
                throw new Exception(_m('Invalid JID: node too long.'));
            }
            if (preg_match("/[".$nodeprepchars."]/u", $node)) {
                // TRANS: Exception thrown when using an invalid Jabber ID.
                // TRANS: %s is the invalid Jabber ID.
                throw new Exception(sprintf(_m('Invalid JID node "%s".'),$node));
            }
        }

        if (strlen($domain) > 1023) {
            // TRANS: Exception thrown when using too long a Jabber domain (>1023).
            throw new Exception(_m('Invalid JID: domain too long.'));
        }
        if (!common_valid_domain($domain)) {
            // TRANS: Exception thrown when using an invalid Jabber domain name.
            // TRANS: %s is the invalid domain name.
            throw new Exception(sprintf(_m('Invalid JID domain name "%s".'),$domain));
        }

        if ($resource !== null) {
            if (strlen($resource) > 1023) {
                // TRANS: Exception thrown when using too long a resource (>1023).
                throw new Exception("Invalid JID: resource too long.");
            }
            if (preg_match("/[".$chars."]/u", $resource)) {
                // TRANS: Exception thrown when using an invalid Jabber resource.
                // TRANS: %s is the invalid resource.
                throw new Exception(sprintf(_m('Invalid JID resource "%s".'),$resource));
            }
        }

        return array('node' => is_null($node) ? null : mb_strtolower($node),
                     'domain' => is_null($domain) ? null : mb_strtolower($domain),
                     'resource' => $resource);
    }

    /**
     * Checks whether a string is a syntactically valid Jabber ID (JID),
     * either with or without a resource.
     *
     * Note that a bare domain can be a valid JID.
     *
     * @param string $jid string to check
     * @param bool $check_domain whether we should validate that domain...
     *
     * @return     boolean whether the string is a valid JID
     */
    protected function validateFullJid($jid, $check_domain=false)
    {
        try {
            $parts = $this->splitJid($jid);
            if ($check_domain) {
                if (!$this->checkDomain($parts['domain'])) {
                    return false;
                }
            }
            return $parts['resource'] !== ''; // missing or present; empty ain't kosher
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * Checks whether a string is a syntactically valid base Jabber ID (JID).
     * A base JID won't include a resource specifier on the end; since we
     * take it off when reading input we can't really use them reliably
     * to direct outgoing messages yet (sorry guys!)
     *
     * Note that a bare domain can be a valid JID.
     *
     * @param string $jid string to check
     * @param bool $check_domain whether we should validate that domain...
     *
     * @return     boolean whether the string is a valid JID
     */
    protected function validateBaseJid($jid, $check_domain=false)
    {
        try {
            $parts = $this->splitJid($jid);
            if ($check_domain) {
                if (!$this->checkDomain($parts['domain'])) {
                    return false;
                }
            }
            return ($parts['resource'] === null); // missing; empty ain't kosher
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * Normalizes a Jabber ID for comparison, dropping the resource component if any.
     *
     * @param string $jid JID to check
     * @param bool $check_domain if true, reject if the domain isn't findable
     *
     * @return string an equivalent JID in normalized (lowercase) form
     */
    function normalize($jid)
    {
        try {
            $parts = $this->splitJid($jid);
            if ($parts['node'] !== null) {
                return $parts['node'] . '@' . $parts['domain'];
            } else {
                return $parts['domain'];
            }
        } catch (Exception $e) {
            return null;
        }
    }

    /**
     * Check if this domain's got some legit DNS record
     */
    protected function checkDomain($domain)
    {
        if (checkdnsrr("_xmpp-server._tcp." . $domain, "SRV")) {
            return true;
        }
        if (checkdnsrr($domain, "ANY")) {
            return true;
        }
        return false;
    }

    function daemonScreenname()
    {
        $ret = $this->user . '@' . $this->server;
        if($this->resource)
        {
            return $ret . '/' . $this->resource;
        }else{
            return $ret;
        }
    }

    function validate($screenname)
    {
        return $this->validateBaseJid($screenname, common_config('email', 'check_domain'));
    }

    /**
     * Load related modules when needed
     *
     * @param string $cls Name of the class to be loaded
     *
     * @return boolean hook value; true means continue processing, false means stop.
     */

    function onAutoload($cls)
    {
        $dir = dirname(__FILE__);

        switch ($cls)
        {
        case 'XMPPHP_XMPP':
            require_once $dir . '/extlib/XMPPHP/XMPP.php';
            return false;
        }

        return parent::onAutoload($cls);
    }

    function onStartImDaemonIoManagers(&$classes)
    {
        parent::onStartImDaemonIoManagers($classes);
        $classes[] = new XmppManager($this); // handles pings/reconnects
        return true;
    }

    function microiduri($screenname)
    {
        return 'xmpp:' . $screenname;
    }

    function sendMessage($screenname, $body)
    {
        $this->queuedConnection()->message($screenname, $body, 'chat');
    }

    function sendNotice($screenname, Notice $notice)
    {
        $msg   = $this->formatNotice($notice);
        $entry = $this->format_entry($notice);

        $this->queuedConnection()->message($screenname, $msg, 'chat', null, $entry);
        return true;
    }

    /**
     * extra information for XMPP messages, as defined by Twitter
     *
     * @param Profile $profile Profile of the sending user
     * @param Notice  $notice  Notice being sent
     *
     * @return string Extra information (Atom, HTML, addresses) in string format
     */
    protected function format_entry(Notice $notice)
    {
        $profile = $notice->getProfile();

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

        $xs = new XMLStringer();
        $xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im'));
        $xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
        $xs->element('a', array('href' => $profile->profileurl), $profile->nickname);
        try {
            $parent = $notice->getParent();
            $orig_profile = $parent->getProfile();
            $orig_profurl = $orig_profile->getUrl();
            $xs->text(" => ");
            $xs->element('a', array('href' => $orig_profurl), $orig_profile->nickname);
            $xs->text(": ");
        } catch (InvalidUrlException $e) {
            $xs->text(sprintf(' => %s', $orig_profile->nickname));
        } catch (Exception $e) {
            $xs->text(": ");
        }
        if (!empty($notice->rendered)) {
            $notice->rendered = str_replace("\t", "", $notice->rendered);
            $xs->raw($notice->rendered);
        } else {
            $xs->raw(common_render_content($notice->content, $notice));
        }
        $xs->text(" ");
        $xs->element('a', array(
            'href'=>common_local_url('conversation',
                array('id' => $notice->conversation)).'#notice-'.$notice->id),
             // TRANS: Link description to notice in conversation.
             // TRANS: %s is a notice ID.
             sprintf(_m('[%u]'),$notice->id));
        $xs->elementEnd('body');
        $xs->elementEnd('html');

        $html = $xs->getString();

        return $html . ' ' . $entry;
    }

    function receiveRawMessage($pl)
    {
        $from = $this->normalize($pl['from']);

        if ($pl['type'] != 'chat') {
            $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from: " . $pl['xml']->toString());
            return true;
        }

        if (mb_strlen($pl['body']) == 0) {
            $this->log(LOG_WARNING, "Ignoring message with empty body from $from: "  . $pl['xml']->toString());
            return true;
        }

        $this->handleIncoming($from, $pl['body']);

        return true;
    }

    /**
     * Build a queue-proxied XMPP interface object. Any outgoing messages
     * will be run back through us for enqueing rather than sent directly.
     *
     * @return QueuedXMPP
     * @throws Exception if server settings are invalid.
     */
    function queuedConnection(){
        if(!isset($this->server)){
            // TRANS: Exception thrown when the plugin configuration is incorrect.
            throw new Exception(_m('You must specify a server in the configuration.'));
        }
        if(!isset($this->port)){
            // TRANS: Exception thrown when the plugin configuration is incorrect.
            throw new Exception(_m('You must specify a port in the configuration.'));
        }
        if(!isset($this->user)){
            // TRANS: Exception thrown when the plugin configuration is incorrect.
            throw new Exception(_m('You must specify a user in the configuration.'));
        }
        if(!isset($this->password)){
            // TRANS: Exception thrown when the plugin configuration is incorrect.
            throw new Exception(_m('You must specify a password in the configuration.'));
        }

        return new QueuedXMPP($this, $this->host ?
                                    $this->host :
                                    $this->server,
                                    $this->port,
                                    $this->user,
                                    $this->password,
                                    $this->resource,
                                    $this->server,
                                    $this->debug ?
                                    true : false,
                                    $this->debug ?
                                    XMPPHP_Log::LEVEL_VERBOSE :  null
                                    );
    }

    /**
     * Add XMPP plugin daemon to the list of daemon to start
     *
     * @param array $daemons the list of daemons to run
     *
     * @return boolean hook return
     */
    function onGetValidDaemons(&$daemons)
    {
        if( isset($this->server) &&
            isset($this->port)   &&
            isset($this->user)   &&
            isset($this->password) ){

            array_push(
                $daemons,
                INSTALLDIR
                . '/scripts/imdaemon.php'
            );
        }

        return true;
    }

    function onPluginVersion(&$versions)
    {
        $versions[] = array('name' => 'XMPP',
                            'version' => GNUSOCIAL_VERSION,
                            'author' => 'Craig Andrews, Evan Prodromou',
                            'homepage' => 'http://status.net/wiki/Plugin:XMPP',
                            'rawdescription' =>
                            // TRANS: Plugin description.
                            _m('The XMPP plugin allows users to send and receive notices over the XMPP/Jabber network.'));
        return true;
    }
}


code:
<?php
/**
 * XMPPHP: The PHP XMPP Library
 * Copyright (C) 2008  Nathanael C. Fritz
 * This file is part of SleekXMPP.
 *
 * XMPPHP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XMPPHP 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XMPPHP; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   xmpphp
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 */

/** XMPPHP_XMLStream */
require_once dirname(__FILE__) . "/XMPP.php";

/**
 * XMPPHP Main Class
 *
 * @category   xmpphp
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 * @version	$Id$
 */
class XMPPHP_BOSH extends XMPPHP_XMPP {

		protected $rid;
		protected $sid;
		protected $http_server;
		protected $http_buffer = Array();
		protected $session = false;

		public function connect($server, $wait='1', $session=false) {
			$this->http_server = $server;
			$this->use_encryption = false;
			$this->session = $session;

			$this->rid = 3001;
			$this->sid = null;
			if($session)
			{
				$this->loadSession();
			}
			if(!$this->sid) {
				$body = $this->__buildBody();
				$body->addAttribute('hold','1');
				$body->addAttribute('to', $this->host);
				$body->addAttribute('route', "xmpp:{$this->host}:{$this->port}");
				$body->addAttribute('secure','true');
				$body->addAttribute('xmpp:version','1.6', 'urn:xmpp:xbosh');
				$body->addAttribute('wait', strval($wait));
				$body->addAttribute('ack','1');
				$body->addAttribute('xmlns:xmpp','urn:xmpp:xbosh');
				$buff = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>";
				xml_parse($this->parser, $buff, false);
				$response = $this->__sendBody($body);
				$rxml = new SimpleXMLElement($response);
				$this->sid = $rxml['sid'];

			} else {
				$buff = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>";
				xml_parse($this->parser, $buff, false);
			}
		}

		public function __sendBody($body=null, $recv=true) {
			if(!$body) {
				$body = $this->__buildBody();
			}
			$ch = curl_init($this->http_server);
			curl_setopt($ch, CURLOPT_HEADER, 0);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $body->asXML());
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
			$header = array('Accept-Encoding: gzip, deflate','Content-Type: text/xml; charset=utf-8');
			curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
			curl_setopt($ch, CURLOPT_VERBOSE, 0);
			$output = '';
			if($recv) {
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
				$output = curl_exec($ch);
				$this->http_buffer[] = $output;
			}
			curl_close($ch);
			return $output;
		}

		public function __buildBody($sub=null) {
			$xml = new SimpleXMLElement("<body xmlns='http://jabber.org/protocol/httpbind' xmlns:xmpp='urn:xmpp:xbosh' />");
			$xml->addAttribute('content', 'text/xml; charset=utf-8');
			$xml->addAttribute('rid', $this->rid);
			$this->rid += 1;
			if($this->sid) $xml->addAttribute('sid', $this->sid);
			#if($this->sid) $xml->addAttribute('xmlns', 'http://jabber.org/protocol/httpbind');
			$xml->addAttribute('xml:lang', 'en');
			if($sub) { // ok, so simplexml is lame
				$p = dom_import_simplexml($xml);
				$c = dom_import_simplexml($sub);
				$cn = $p->ownerDocument->importNode($c, true);
				$p->appendChild($cn);
				$xml = simplexml_import_dom($p);
			}
			return $xml;
		}

		public function __process() {
			if($this->http_buffer) {
				$this->__parseBuffer();
			} else {
				$this->__sendBody();
				$this->__parseBuffer();
			}
		}

		public function __parseBuffer() {
			while ($this->http_buffer) {
				$idx = key($this->http_buffer);
				$buffer = $this->http_buffer[$idx];
				unset($this->http_buffer[$idx]);
				if($buffer) {
					$xml = new SimpleXMLElement($buffer);
					$children = $xml->xpath('child::node()');
					foreach ($children as $child) {
						$buff = $child->asXML();
						$this->log->log("RECV: $buff",  XMPPHP_Log::LEVEL_VERBOSE);
						xml_parse($this->parser, $buff, false);
					}
				}
			}
		}

		public function send($msg) {
			$this->log->log("SEND: $msg",  XMPPHP_Log::LEVEL_VERBOSE);
			$msg = new SimpleXMLElement($msg);
			#$msg->addAttribute('xmlns', 'jabber:client');
			$this->__sendBody($this->__buildBody($msg), true);
			#$this->__parseBuffer();
		}

		public function reset() {
			$this->xml_depth = 0;
			unset($this->xmlobj);
			$this->xmlobj = array();
			$this->setupParser();
			#$this->send($this->stream_start);
			$body = $this->__buildBody();
			$body->addAttribute('to', $this->host);
			$body->addAttribute('xmpp:restart', 'true', 'urn:xmpp:xbosh');
			$buff = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>";
			$response = $this->__sendBody($body);
			$this->been_reset = true;
			xml_parse($this->parser, $buff, false);
		}

		public function loadSession() {
			if(isset($_SESSION['XMPPHP_BOSH_RID'])) $this->rid = $_SESSION['XMPPHP_BOSH_RID'];
			if(isset($_SESSION['XMPPHP_BOSH_SID'])) $this->sid = $_SESSION['XMPPHP_BOSH_SID'];
			if(isset($_SESSION['XMPPHP_BOSH_authed'])) $this->authed = $_SESSION['XMPPHP_BOSH_authed'];
			if(isset($_SESSION['XMPPHP_BOSH_jid'])) $this->jid = $_SESSION['XMPPHP_BOSH_jid'];
			if(isset($_SESSION['XMPPHP_BOSH_fulljid'])) $this->fulljid = $_SESSION['XMPPHP_BOSH_fulljid'];
		}

		public function saveSession() {
			$_SESSION['XMPPHP_BOSH_RID'] = (string) $this->rid;
			$_SESSION['XMPPHP_BOSH_SID'] = (string) $this->sid;
			$_SESSION['XMPPHP_BOSH_authed'] = (boolean) $this->authed;
			$_SESSION['XMPPHP_BOSH_jid'] = (string) $this->jid;
			$_SESSION['XMPPHP_BOSH_fulljid'] = (string) $this->fulljid;
		}
}


code:
<?php
/**
 * XMPPHP: The PHP XMPP Library
 * Copyright (C) 2008  Nathanael C. Fritz
 * This file is part of SleekXMPP.
 *
 * XMPPHP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XMPPHP 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XMPPHP; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   xmpphp
 * @package    XMPPHP
 * @author     Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author     Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 */

/**
 * XMPPHP Exception
 *
 * @category   xmpphp
 * @package    XMPPHP
 * @author     Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author     Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 * @version    $Id$
 */
class XMPPHP_Exception extends Exception {
}


code:
<?php
/**
 * XMPPHP: The PHP XMPP Library
 * Copyright (C) 2008  Nathanael C. Fritz
 * This file is part of SleekXMPP.
 *
 * XMPPHP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XMPPHP 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XMPPHP; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   xmpphp
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 */

/**
 * XMPPHP Log
 *
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 * @version	$Id$
 */
class XMPPHP_Log {

	const LEVEL_ERROR   = 0;
	const LEVEL_WARNING = 1;
	const LEVEL_INFO	= 2;
	const LEVEL_DEBUG   = 3;
	const LEVEL_VERBOSE = 4;

	/**
	 * @var array
	 */
	protected $data = array();

	/**
	 * @var array
	 */
	protected $names = array('ERROR', 'WARNING', 'INFO', 'DEBUG', 'VERBOSE');

	/**
	 * @var integer
	 */
	protected $runlevel;

	/**
	 * @var boolean
	 */
	protected $printout;

	/**
	 * Constructor
	 *
	 * @param boolean $printout
	 * @param string  $runlevel
	 */
	public function __construct($printout = false, $runlevel = self::LEVEL_INFO) {
		$this->printout = (boolean)$printout;
		$this->runlevel = (int)$runlevel;
	}

	/**
	 * Add a message to the log data array
	 * If printout in this instance is set to true, directly output the message
	 *
	 * @param string  $msg
	 * @param integer $runlevel
	 */
	public function log($msg, $runlevel = self::LEVEL_INFO) {
		$time = time();
		#$this->data[] = array($this->runlevel, $msg, $time);
		if($this->printout and $runlevel <= $this->runlevel) {
			$this->writeLine($msg, $runlevel, $time);
		}
	}

	/**
	 * Output the complete log.
	 * Log will be cleared if $clear = true
	 *
	 * @param boolean $clear
	 * @param integer $runlevel
	 */
	public function printout($clear = true, $runlevel = null) {
		if($runlevel === null) {
			$runlevel = $this->runlevel;
		}
		foreach($this->data as $data) {
			if($runlevel <= $data[0]) {
				$this->writeLine($data[1], $runlevel, $data[2]);
			}
		}
		if($clear) {
			$this->data = array();
		}
	}

	protected function writeLine($msg, $runlevel, $time) {
		//echo date('Y-m-d H:i:s', $time)." [".$this->names[$runlevel]."]: ".$msg."\n";
		echo $time." [".$this->names[$runlevel]."]: ".$msg."\n";
		flush();
	}
}


code:
<?php
/**
 * XMPPHP: The PHP XMPP Library
 * Copyright (C) 2008  Nathanael C. Fritz
 * This file is part of SleekXMPP.
 *
 * XMPPHP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XMPPHP 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XMPPHP; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   xmpphp
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 */

/**
 * XMPPHP Roster Object
 *
 * @category   xmpphp
 * @package	XMPPHP
 * @author	 Nathanael C. Fritz <JID: fritzy@netflint.net>
 * @author	 Stephan Wentz <JID: stephan@jabber.wentz.it>
 * @author	 Michael Garvin <JID: gar@netflint.net>
 * @copyright  2008 Nathanael C. Fritz
 * @version	$Id$
 */

class Roster {
	/**
	 * Roster array, handles contacts and presence.  Indexed by jid.
	 * Contains array with potentially two indexes 'contact' and 'presence'
	 * @var array
	 */
	protected $roster_array = array();
	/**
	 * Constructor
	 *
	 */
	public function __construct($roster_array = array()) {
		if ($this->verifyRoster($roster_array)) {
			$this->roster_array = $roster_array; //Allow for prepopulation with existing roster
		} else {
			$this->roster_array = array();
		}
	}

	/**
	 *
	 * Check that a given roster array is of a valid structure (empty is still valid)
	 *
	 * @param array $roster_array
	 */
	protected function verifyRoster($roster_array) {
		#TODO once we know *what* a valid roster array looks like
		return True;
	}

	/**
	 *
	 * Add given contact to roster
	 *
	 * @param string $jid
	 * @param string $subscription
	 * @param string $name
	 * @param array $groups
	 */
	public function addContact($jid, $subscription, $name='', $groups=array()) {
		$contact = array('jid' => $jid, 'subscription' => $subscription, 'name' => $name, 'groups' => $groups);
		if ($this->isContact($jid)) {
			$this->roster_array[$jid]['contact'] = $contact;
		} else {
			$this->roster_array[$jid] = array('contact' => $contact);
		}
	}

	/**
	 *
	 * Retrieve contact via jid
	 *
	 * @param string $jid
	 */
	public function getContact($jid) {
		if ($this->isContact($jid)) {
			return $this->roster_array[$jid]['contact'];
		}
	}

	/**
	 *
	 * Discover if a contact exists in the roster via jid
	 *
	 * @param string $jid
	 */
	public function isContact($jid) {
		return (array_key_exists($jid, $this->roster_array));
	}

	/**
	 *
	 * Set presence
	 *
	 * @param string $presence
	 * @param integer $priority
	 * @param string $show
	 * @param string $status
	*/
	public function setPresence($presence, $priority, $show, $status) {
		list($jid, $resource) = split("/", $presence);
		if ($show != 'unavailable') {
			if (!$this->isContact($jid)) {
				$this->addContact($jid, 'not-in-roster');
			}
			$resource = $resource ? $resource : '';
			$this->roster_array[$jid]['presence'][$resource] = array('priority' => $priority, 'show' => $show, 'status' => $status);
		} else { //Nuke unavailable resources to save memory
			unset($this->roster_array[$jid]['resource'][$resource]);
		}
	}

	/*
	 *
	 * Return best presence for jid
	 *
	 * @param string $jid
	 */
	public function getPresence($jid) {
		$split = split("/", $jid);
		$jid = $split[0];
		if($this->isContact($jid)) {
			$current = array('resource' => '', 'active' => '', 'priority' => -129, 'show' => '', 'status' => ''); //Priorities can only be -128 = 127
			foreach($this->roster_array[$jid]['presence'] as $resource => $presence) {
				//Highest available priority or just highest priority
				if ($presence['priority'] > $current['priority'] and (($presence['show'] == "chat" or $presence['show'] == "available") or ($current['show'] != "chat" or $current['show'] != "available"))) {
					$current = $presence;
					$current['resource'] = $resource;
				}
			}
			return $current;
		}
	}
	/**
	 *
	 * Get roster
	 *
	 */
	public function getRoster() {
		return $this->roster_array;
	}
}
?>