code:
# Translation of StatusNet - TagSub 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 - TagSub\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:16+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-12-03 13:51:31+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-tagsub\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Form legend.
msgid "Unsubscribe from this tag"
msgstr "Huwag nang magpasipi mula sa tatak na ito"

#. TRANS: Submit button text to unsubscribe from a tag.
msgctxt "BUTTON"
msgid "Unsubscribe"
msgstr "Pahintuin na ang pagtanggap ng sipi"

#. TRANS: Submit button title to unsubscribe from a tag.
msgid "Unsubscribe from this tag."
msgstr "Huwag nang sumipi mula sa tatak na ito."

#. TRANS: Plugin description.
msgid "Plugin to allow following all messages with a given tag."
msgstr ""
"Pagpapasak upang mapayagan ang pagsunod sa lahat ng mga mensaheng may "
"ibinigay na tatak."

#. TRANS: SubMirror plugin menu item on user settings page.
msgctxt "MENU"
msgid "Tags"
msgstr "Mga tatak"

#. TRANS: SubMirror plugin tooltip for user settings menu item.
msgid "Configure tag subscriptions"
msgstr "Isaayos ang mga pagpapasipi ng tatak"

#. TRANS: Menu item text for tags submenu.
msgid "Tags"
msgstr "Mga tatak"

#. TRANS: Form legend.
msgid "Subscribe to this tag"
msgstr "Magpasipi para sa tatak na ito"

#. TRANS: Submit button text to subscribe to a tag.
msgctxt "BUTTON"
msgid "Subscribe"
msgstr "Pumayag na tumanggap ng sipi"

#. TRANS: Submit button title to subscribe to a tag.
msgid "Subscribe to this tag."
msgstr "Sumipi mula sa tatak na ito."

#. TRANS: Page title when tag unsubscription succeeded.
msgid "Unsubscribed"
msgstr "Hindi na nagpapasipi"

#. TRANS: Client error displayed trying to perform any request method other than POST.
#. TRANS: Do not translate POST.
msgid "This action only accepts POST requests."
msgstr "Ang galaw na ito ay tumatanggap lamang ng mga kahilingan ng PAGPASKIL."

#. TRANS: Client error displayed when the session token is not okay.
msgid "There was a problem with your session token. Try again, please."
msgstr ""
"Nagkaroon ng isang suliranin sa kahalip ng sesyon mo.  Pakisubukan uli."

#. TRANS: Error message displayed when trying to perform an action that requires a logged in user.
msgid "Not logged in."
msgstr "Hindi nakalagda."

#. TRANS: Client error displayed trying to subscribe to a non-existing profile.
msgid "No such profile."
msgstr "Walang ganyang balangkas."

#. TRANS: Page title when tag subscription succeeded.
msgid "Subscribed"
msgstr "Nagpapasipi na"

#. TRANS: Header for subscriptions overview for a user (first page).
#. TRANS: %s is a user nickname.
#, php-format
msgid "%s's tag subscriptions"
msgstr "Mga pagpapasipi ng tatak ni %s"

#. TRANS: Header for subscriptions overview for a user (not first page).
#. TRANS: %1$s is a user nickname, %2$d is the page number.
#, php-format
msgid "%1$s's tag subscriptions, page %2$d"
msgstr "Mga pagpapasipi ng tatak ni %1$s, pahina %2$d"

#. TRANS: Page notice for page with an overview of all tag subscriptions
#. TRANS: of the logged in user's own profile.
msgid ""
"You have subscribed to receive all notices on this site containing the "
"following tags:"
msgstr ""
"Nagpasipi ka upang makatanggap ng lahat ng mga pabatid sa sityong ito na "
"naglalaman ng sumusunod na mga tatak:"

#. TRANS: Page notice for page with an overview of all subscriptions of a user other
#. TRANS: than the logged in user. %s is the user nickname.
#, php-format
msgid ""
"%s has subscribed to receive all notices on this site containing the "
"following tags:"
msgstr ""
"Si %s ay nagpasipi upang makatanggap ng lahat ng mga pabatid sa sityong ito "
"na naglalaman ng sumusunod na mga tatak:"

#. TRANS: Tag subscription list text when the logged in user has no tag subscriptions.
msgid ""
"You are not listening to any hash tags right now. You can push the "
"\"Subscribe\" button on any hashtag page to automatically receive any public "
"messages on this site that use that tag, even if you are not subscribed to "
"the poster."
msgstr ""
"Hindi ka nakikinig sa anumang mga tatak ng muling paghahayag sa ngayon.  "
"Mapipindot mo ang pindutang \"Magpasipi\" sa anumang pahina ng tatak ng "
"muling pagpapahayag upang kusang makatanggap ng anumang mensaheng pangmadla "
"sa pook na ito na gumagamit ng ganyang tatak, kahit na hindi ka nagpapasipi "
"ng karatula."

#. TRANS: Tag subscription list text when looking at the subscriptions for a of a user other
#. TRANS: than the logged in user that has no tag subscriptions. %s is the user nickname.
#. TRANS: Subscription list text when looking at the subscriptions for a of a user that has none
#. TRANS: as an anonymous user. %s is the user nickname.
#, php-format
msgid "%s is not following any tags."
msgstr "Hindi sinusundan ni %s ang anumang mga tatak."

#. TRANS: %1$s is a URL to a tag, %2$s is a tag,
#. TRANS: %3$s a date string.
#, php-format
msgid "#%2$s since %3$s"
msgstr "#%2$s magmula pa noong %3$s"


code:
# Translation of StatusNet - TagSub 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 - TagSub\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:16+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-12-03 13:51:31+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-tagsub\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: Form legend.
msgid "Unsubscribe from this tag"
msgstr "Відписатися від цього теґу"

#. TRANS: Submit button text to unsubscribe from a tag.
msgctxt "BUTTON"
msgid "Unsubscribe"
msgstr "Відписатись"

#. TRANS: Submit button title to unsubscribe from a tag.
#, fuzzy
msgid "Unsubscribe from this tag."
msgstr "Відписатися від цього теґу"

#. TRANS: Plugin description.
msgid "Plugin to allow following all messages with a given tag."
msgstr "Додаток, який дозволяє відслідковувати дописи позначені певним теґом"

#. TRANS: SubMirror plugin menu item on user settings page.
msgctxt "MENU"
msgid "Tags"
msgstr "Теґи"

#. TRANS: SubMirror plugin tooltip for user settings menu item.
msgid "Configure tag subscriptions"
msgstr "Налаштування підписок на теґи"

#. TRANS: Menu item text for tags submenu.
msgid "Tags"
msgstr "Теґи"

#. TRANS: Form legend.
msgid "Subscribe to this tag"
msgstr "Підписатися на цей теґ"

#. TRANS: Submit button text to subscribe to a tag.
msgctxt "BUTTON"
msgid "Subscribe"
msgstr "Підписатись"

#. TRANS: Submit button title to subscribe to a tag.
#, fuzzy
msgid "Subscribe to this tag."
msgstr "Підписатися на цей теґ"

#. TRANS: Page title when tag unsubscription succeeded.
msgid "Unsubscribed"
msgstr "Відписано"

#. TRANS: Client error displayed trying to perform any request method other than POST.
#. TRANS: Do not translate POST.
msgid "This action only accepts POST requests."
msgstr "Ця дія приймає лише запити POST."

#. TRANS: Client error displayed when the session token is not okay.
msgid "There was a problem with your session token. Try again, please."
msgstr "Виникли певні проблеми з токеном сесії. Спробуйте знов, будь ласка."

#. TRANS: Error message displayed when trying to perform an action that requires a logged in user.
msgid "Not logged in."
msgstr "Не увійшли."

#. TRANS: Client error displayed trying to subscribe to a non-existing profile.
msgid "No such profile."
msgstr "Немає такого профілю."

#. TRANS: Page title when tag subscription succeeded.
msgid "Subscribed"
msgstr "Підписано"

#. TRANS: Header for subscriptions overview for a user (first page).
#. TRANS: %s is a user nickname.
#, php-format
msgid "%s's tag subscriptions"
msgstr "Підписки на теґи %s"

#. TRANS: Header for subscriptions overview for a user (not first page).
#. TRANS: %1$s is a user nickname, %2$d is the page number.
#, php-format
msgid "%1$s's tag subscriptions, page %2$d"
msgstr "Підписки на теґи %1$s, сторінка %2$d"

#. TRANS: Page notice for page with an overview of all tag subscriptions
#. TRANS: of the logged in user's own profile.
msgid ""
"You have subscribed to receive all notices on this site containing the "
"following tags:"
msgstr ""
"Ви підписалися на отримання всіх дописів на цьому сайті, що позначені теґами:"

#. TRANS: Page notice for page with an overview of all subscriptions of a user other
#. TRANS: than the logged in user. %s is the user nickname.
#, php-format
msgid ""
"%s has subscribed to receive all notices on this site containing the "
"following tags:"
msgstr ""
"%s підписаний на отримання всіх дописів на цьому сайті, що позначені теґами:"

#. TRANS: Tag subscription list text when the logged in user has no tag subscriptions.
msgid ""
"You are not listening to any hash tags right now. You can push the "
"\"Subscribe\" button on any hashtag page to automatically receive any public "
"messages on this site that use that tag, even if you are not subscribed to "
"the poster."
msgstr ""
"Наразі ви не маєте підписок на жоден теґ. Натисніть на кнопку «Підписатися» "
"на будь-якій сторінці теґу, щоб мати можливість отримувати автоматично всі "
"дописи, які будуть позначені відповідною міткою, тоді ви отримуватимете "
"дописи від користувачів, до яких ви навіть не підписані."

#. TRANS: Tag subscription list text when looking at the subscriptions for a of a user other
#. TRANS: than the logged in user that has no tag subscriptions. %s is the user nickname.
#. TRANS: Subscription list text when looking at the subscriptions for a of a user that has none
#. TRANS: as an anonymous user. %s is the user nickname.
#, fuzzy, php-format
msgid "%s is not following any tags."
msgstr "%s не підписаний до жодних тегів"

#. TRANS: %1$s is a URL to a tag, %2$s is a tag,
#. TRANS: %3$s a date string.
#, fuzzy, php-format
msgid "#%2$s since %3$s"
msgstr "#%s протягом %s"

license: mit


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Plugin to push RSS/Atom updates to a PubSubHubBub hub
 *
 * PHP version 5
 *
 * LICENCE: 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  Plugin
 * @package   StatusNet
 * @author    Craig Andrews <candrews@integralblue.com>
 * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
 * @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')) {
    exit(1);
}

class TightUrlPlugin extends UrlShortenerPlugin
{
    public $serviceUrl;

    function onInitializePlugin(){
        parent::onInitializePlugin();
        if(!isset($this->serviceUrl)){
            // TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
            throw new Exception(_m('You must specify a serviceUrl.'));
        }
    }

    protected function shorten($url)
    {
        $response = $this->http_get(sprintf($this->serviceUrl,urlencode($url)));
        if (!$response) return;
        $dom = new DOMDocument();
        @$dom->loadHTML($response);
        $y = @simplexml_import_dom($dom);
        if (!isset($y->body)) return;
        $xml = $y->body->p[0]->code[0]->a->attributes();
        if (isset($xml['href'])) {
            return strval($xml['href']);
        }
    }

    function onPluginVersion(&$versions)
    {
        $versions[] = array('name' => sprintf('TightUrl (%s)', $this->shortenerName),
                            'version' => GNUSOCIAL_VERSION,
                            'author' => 'Craig Andrews',
                            'homepage' => 'http://status.net/wiki/Plugin:TightUrl',
                            'rawdescription' =>
                            // TRANS: Plugin description. %s is the shortener name.
                            sprintf(_m('Uses %1$s URL-shortener service.'),
                                    $this->shortenerName));
        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: Exception thrown when the TightUrl plugin has been configured incorrectly.
#: TightUrlPlugin.php:42
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#: TightUrlPlugin.php:68
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""


code:
# Translation of StatusNet - TightUrl to German (Deutsch)
# Exported from translatewiki.net
#
# Author: ChrisiPK
# Author: The Evil IP address
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:16+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Du musst eine serviceUrl angeben."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Benutzung des %1$s-URL-Kürzungsdienstes."


code:
# Translation of StatusNet - TightUrl to Spanish (español)
# Exported from translatewiki.net
#
# Author: Armando-Martin
# Author: Translationista
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:16+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Debe especificar un \"serviceUrl\"."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Utiliza el servicio de acortamiento de URL %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:16+0000\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:38+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: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Url zerbitzu bat adierazi behar duzu."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "%1$s URL-laburtze zerbitzua erabiliz."


code:
# Translation of StatusNet - TightUrl to French (français)
# Exported from translatewiki.net
#
# Author: Crochet.david
# Author: Peter17
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Vous devez spécifier un serviceUrl."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Utilise le service de raccourcissement d’URL %1$s</"
"a>."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Cómpre especificar un serviceUrl."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Emprega o servizo de abreviación de enderezos URL %1"
"$s."


code:
# Translation of StatusNet - TightUrl to Hebrew (עברית)
# Exported from translatewiki.net
#
# Author: Amire80
# Author: YaronSh
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "יש להזין serviceUrl."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "שימוש בשירות קיצור הכתובות %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Es necessari specificar un \"serviceUrl\"."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Usa le servicio de accurtamento de URL %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Menggunakan layanan pemendek URL %1$s."


code:
# Translation of StatusNet - TightUrl to Japanese (日本語)
# Exported from translatewiki.net
#
# Author: Shirayuki
# Author: 青子守歌
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+0000\n"
"Language-Team: Japanese <https://translatewiki.net/wiki/Portal:ja>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-06-19 11:23:38+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: ja\n"
"X-Message-Group: #out-statusnet-plugin-tighturl\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "serviceUrl を指定する必要があります。"

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "%1$sをURL短縮サービスとして使用する。"


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n == 1 || n%10 == 1) ? 0 : 1;\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Мора да наведете serviceUrl."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Користи %1$s - служба за скратување на URL-"
"адреси."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Menggunakan khidmat pemendekan URL %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Bruker URL-forkortertjenesten %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:17+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "U moet een serviceUrl opgeven."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Gebruikt de dienst %1$s om URL's korter te "
"maken."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:18+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Usa o serviço de abreviação de URLs %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:18+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-19 11:23:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Utiliza o serviço de encurtamento de URL %1$s"


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:18+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:38+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-tighturl\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: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr "Использование службы сокращения URL %1$s."


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:18+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:38+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-tighturl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANS: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr "Dapat kang tumukoy ng isang URL ng paglilingkod."

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Gumagamit ng palingkurang pampaiksi ng URL na %1$s</"
"a>"


code:
# Translation of StatusNet - TightUrl 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 - TightUrl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:10:18+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:38+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-tighturl\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: Exception thrown when the TightUrl plugin has been configured incorrectly.
msgid "You must specify a serviceUrl."
msgstr ""

#. TRANS: Plugin description. %s is the shortener name.
#, php-format
msgid "Uses %1$s URL-shortener service."
msgstr ""
"Використання %1$s для скорочення URL-адрес."


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Use TinyMCE library to allow rich text editing in the browser
 *
 * 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  WYSIWYG
 * @package   StatusNet
 * @author    Evan Prodromou <evan@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);
}

/**
 * Use TinyMCE library to allow rich text editing in the browser
 *
 * Converts the notice form in browser to a rich-text editor.
 *
 * FIXME: this plugin DOES NOT load its static files from the configured
 * plugin server if one exists. There are cross-server permissions errors
 * if you try to do that (something about window.tinymce).
 *
 * @category  WYSIWYG
 * @package   StatusNet
 * @author    Evan Prodromou <evan@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 TinyMCEPlugin extends Plugin
{
    var $html;

    // By default, TinyMCE editor will be available to all users.
    // With restricted on, only users who have been granted the
    // "richedit" role get it.
    public $restricted = false;

    function onEndShowScripts($action)
    {
        if (common_logged_in() && $this->isAllowedRichEdit()) {
            $action->script(common_path('plugins/TinyMCE/js/jquery.tinymce.js'));
            $action->inlineScript($this->_inlineScript());
        }

        return true;
    }

    function onEndShowStyles($action)
    {
        if ($this->isAllowedRichEdit()) {
            $action->style('span#notice_data-text_container, span#notice_data-text_parent { float: left }');
        }
        return true;
    }

    function onPluginVersion(&$versions)
    {
        $versions[] = array('name' => 'TinyMCE',
            'version' => GNUSOCIAL_VERSION,
            'author' => 'Evan Prodromou',
            'homepage' => 'http://status.net/wiki/Plugin:TinyMCE',
            'rawdescription' =>
            // TRANS: Plugin description.
            _m('Use TinyMCE library to allow rich text editing in the browser.'));
        return true;
    }

    /**
     * Sanitize HTML input and strip out potentially dangerous bits.
     *
     * @param string $raw HTML
     * @return string HTML
     */
    private function sanitizeHtml($raw)
    {
        require_once INSTALLDIR . '/extlib/htmLawed/htmLawed.php';

        $config = array('safe' => 1,
            'deny_attribute' => 'id,style,on*');

        return htmLawed($raw, $config);
    }

    /**
     * Hook for new-notice form processing to take our HTML goodies;
     * won't affect API posting etc.
     *
     * @param NewNoticeAction $action
     * @param User $user
     * @param string $content
     * @param array $options
     * @return boolean hook return
     */
    function onStartSaveNewNoticeWeb($action, $user, &$content, &$options)
    {
        if ($action->arg('richedit') && $this->isAllowedRichEdit()) {
            $html = $this->sanitizeHtml($content);
            $options['rendered'] = $html;
            $content = common_strip_html($html);
        }
        return true;
    }

    /**
     * Hook for new-notice form processing to process file upload appending...
     *
     * @param NewNoticeAction $action
     * @param MediaFile $media
     * @param string $content
     * @param array $options
     * @return boolean hook return
     */
    function onStartSaveNewNoticeAppendAttachment($action, $media, &$content, &$options)
    {
        if ($action->arg('richedit') && $this->isAllowedRichEdit()) {
            // See if we've got a placeholder inline image; if so, fill it!
            $dom = new DOMDocument();

            if ($dom->loadHTML($options['rendered'])) {
                $imgs = $dom->getElementsByTagName('img');
                foreach ($imgs as $img) {
                    if (preg_match('/(^| )placeholder( |$)/', $img->getAttribute('class'))) {
                        // Create a link to the attachment page...
                        $this->formatAttachment($img, $media);
                    }
                }
                $options['rendered'] = $this->saveHtml($dom);
            }

            // The regular code will append the short URL to the plaintext content.
            // Carry on and let it through...
        }
        return true;
    }

    /**
     * Format the attachment placeholder img with the final version.
     *
     * @param DOMElement $img
     * @param MediaFile $media
     */
    private function formatAttachment($img, $media)
    {
        $parent = $img->parentNode;
        $dom = $img->ownerDocument;

        $link = $dom->createElement('a');
        $link->setAttribute('href', $media->fileurl);
        $link->setAttribute('title', File::url($media->filename));

        if ($this->isEmbeddable($media)) {
            // Fix the the <img> attributes and wrap the link around it...
            $this->insertImage($img, $media);
            $parent->replaceChild($link, $img); //it dies in here?!
            $link->appendChild($img);
        } else {
            // Not an image? Replace it with a text link.
            $link->setAttribute('rel', 'external');
            $link->setAttribute('class', 'attachment');
            $link->setAttribute('id', 'attachment-' . $media->fileRecord->id);
            $text = $dom->createTextNode($media->shortUrl());
            $link->appendChild($text);
            $parent->replaceChild($link, $img);
        }
    }

    /**
     * Is this media file a type we can display inline?
     *
     * @param MediaFile $media
     * @return boolean
     */
    private function isEmbeddable($media)
    {
        $showable = array('image/png',
                          'image/gif',
                          'image/jpeg');
        return in_array($media->mimetype, $showable);
    }

    /**
     * Rewrite and resize a placeholder image element to match the uploaded
     * file. If the holder is smaller than the file, the file is scaled to fit
     * with correct aspect ratio (but will be loaded at full resolution).
     *
     * @param DOMElement $img
     * @param MediaFile $media
     */
    private function insertImage($img, $media)
    {
        $img->setAttribute('src', $media->fileRecord->url);

        $holderWidth = intval($img->getAttribute('width'));
        $holderHeight = intval($img->getAttribute('height'));

        $path = File::path($media->filename);
        $imgInfo = getimagesize($path);

        if ($imgInfo) {
            $origWidth = $imgInfo[0];
            $origHeight = $imgInfo[1];

            list($width, $height) = $this->sizeBox(
                    $origWidth, $origHeight,
                    $holderWidth, $holderHeight);

            $img->setAttribute('width', $width);
            $img->setAttribute('height', $height);
        }
    }

    /**
     *
     * @param int $origWidth
     * @param int $origHeight
     * @param int $holderWidth
     * @param int $holderHeight
     * @return array($width, $height)
     */
    private function sizeBox($origWidth, $origHeight, $holderWidth, $holderHeight)
    {
        $holderAspect = $holderWidth / $holderHeight;
        $origAspect = $origWidth / $origHeight;
        if ($origAspect >= 1.0) {
            // wide image
            if ($origWidth > $holderWidth) {
                return array($holderWidth, intval($holderWidth / $origAspect));
            } else {
                return array($origWidth, $origHeight);
            }
        } else {
            if ($origHeight > $holderHeight) {
                return array(intval($holderWidth * $origAspect), $holderHeight);
            } else {
                return array($origWidth, $origHeight);
            }
        }
    }

    private function saveHtml($dom)
    {
        $html = $dom->saveHTML();
        // hack to remove surrounding crap added to the dom
        // all we wanted was a fragment
        $stripped = preg_replace('/^.*<body[^>]*>(.*)<\/body.*$/is', '$1', $html);
        return $stripped;
    }

    function _inlineScript()
    {
        $path = common_path('plugins/TinyMCE/js/tiny_mce.js');
        $placeholder = common_path('plugins/TinyMCE/icons/placeholder.png');

        // Note: the normal on-submit triggering to save data from
        // the HTML editor into the textarea doesn't play well with
        // our AJAX form submission. Manually moving it to trigger
        // on our send button click.
        $scr = <<<END_OF_SCRIPT
        (function() {
        var origInit = SN.Init.NoticeFormSetup;
        SN.Init.NoticeFormSetup = function(form) {
            origInit(form);
            var noticeForm = form;
            var textarea = form.find('.notice_data-text');
            if (textarea.length == 0) return;
            textarea.tinymce({
                script_url : '{$path}',
                // General options
                theme : "advanced",
                plugins : "paste,fullscreen,autoresize,inlinepopups,tabfocus,linkautodetect",
                theme_advanced_buttons1 : "bold,italic,strikethrough,|,undo,redo,|,link,unlink,image,|,fullscreen",
                theme_advanced_buttons2 : "",
                theme_advanced_buttons3 : "",
                add_form_submit_trigger : false,
                theme_advanced_resizing : true,
                tabfocus_elements: ":prev,:next",
                setup: function(ed) {
                    noticeForm.append('<input type="hidden" name="richedit" value="1">');

                    form.find('.submit:first').click(function() {
                        tinymce.triggerSave();
                    });

                    var origCounter = SN.U.CharacterCount;
                    SN.U.CharacterCount = function(form) {
                        var text = $(ed.getDoc()).text();
                        return text.length;
                    };
                    ed.onKeyUp.add(function (ed, e) {
                        SN.U.Counter(noticeForm);
                    });

                    form.find('input[type=file]').change(function() {
                        var img = '<img src="{$placeholder}" class="placeholder" width="320" height="240">';
                        var html = tinyMCE.activeEditor.getContent();
                        ed.setContent(html + img);
                    });
                }
            });
        };
        })();
END_OF_SCRIPT;

        return $scr;
    }

    /**
     * Does the current user have permission to use the rich-text editor?
     * Always true unless the plugin's "restricted" setting is on, in which
     * case it's limited to users with the "richedit" role.
     *
     * @fixme make that more sanely configurable :)
     *
     * @return boolean
     */
    private function isAllowedRichEdit()
    {
        if ($this->restricted) {
            $user = common_current_user();
            return !empty($user) && $user->hasRole('richedit');
        } else {
            return true;
        }
    }
}


code:
tinyMCE.addI18n({en:{
common:{
edit_confirm:"Do you want to use the WYSIWYG mode for this textarea?",
apply:"Apply",
insert:"Insert",
update:"Update",
cancel:"Cancel",
close:"Close",
browse:"Browse",
class_name:"Class",
not_set:"-- Not set --",
clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?",
clipboard_no_support:"Currently not supported by your browser, use keyboard shortcuts instead.",
popup_blocked:"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.",
invalid_data:"{#field} is invalid",
invalid_data_number:"{#field} must be a number",
invalid_data_min:"{#field} must be a number greater than {#min}",
invalid_data_size:"{#field} must be a number or percentage",
more_colors:"More colors"
},
colors:{
'000000':'Black',
'993300':'Burnt orange',
'333300':'Dark olive',
'003300':'Dark green',
'003366':'Dark azure',
'000080':'Navy Blue',
'333399':'Indigo',
'333333':'Very dark gray',
'800000':'Maroon',
'FF6600':'Orange',
'808000':'Olive',
'008000':'Green',
'008080':'Teal',
'0000FF':'Blue',
'666699':'Grayish blue',
'808080':'Gray',
'FF0000':'Red',
'FF9900':'Amber',
'99CC00':'Yellow green',
'339966':'Sea green',
'33CCCC':'Turquoise',
'3366FF':'Royal blue',
'800080':'Purple',
'999999':'Medium gray',
'FF00FF':'Magenta',
'FFCC00':'Gold',
'FFFF00':'Yellow',
'00FF00':'Lime',
'00FFFF':'Aqua',
'00CCFF':'Sky blue',
'993366':'Brown',
'C0C0C0':'Silver',
'FF99CC':'Pink',
'FFCC99':'Peach',
'FFFF99':'Light yellow',
'CCFFCC':'Pale green',
'CCFFFF':'Pale cyan',
'99CCFF':'Light sky blue',
'CC99FF':'Plum',
'FFFFFF':'White'
},
contextmenu:{
align:"Alignment",
left:"Left",
center:"Center",
right:"Right",
full:"Full"
},
insertdatetime:{
date_fmt:"%Y-%m-%d",
time_fmt:"%H:%M:%S",
insertdate_desc:"Insert date",
inserttime_desc:"Insert time",
months_long:"January,February,March,April,May,June,July,August,September,October,November,December",
months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",
day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"
},
print:{
print_desc:"Print"
},
preview:{
preview_desc:"Preview"
},
directionality:{
ltr_desc:"Direction left to right",
rtl_desc:"Direction right to left"
},
layer:{
insertlayer_desc:"Insert new layer",
forward_desc:"Move forward",
backward_desc:"Move backward",
absolute_desc:"Toggle absolute positioning",
content:"New layer..."
},
save:{
save_desc:"Save",
cancel_desc:"Cancel all changes"
},
nonbreaking:{
nonbreaking_desc:"Insert non-breaking space character"
},
iespell:{
iespell_desc:"Run spell checking",
download:"ieSpell not detected. Do you want to install it now?"
},
advhr:{
advhr_desc:"Horizontal rule"
},
emotions:{
emotions_desc:"Emotions"
},
searchreplace:{
search_desc:"Find",
replace_desc:"Find/Replace"
},
advimage:{
image_desc:"Insert/edit image"
},
advlink:{
link_desc:"Insert/edit link"
},
xhtmlxtras:{
cite_desc:"Citation",
abbr_desc:"Abbreviation",
acronym_desc:"Acronym",
del_desc:"Deletion",
ins_desc:"Insertion",
attribs_desc:"Insert/Edit Attributes"
},
style:{
desc:"Edit CSS Style"
},
paste:{
paste_text_desc:"Paste as Plain Text",
paste_word_desc:"Paste from Word",
selectall_desc:"Select All",
plaintext_mode_sticky:"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.",
plaintext_mode:"Paste is now in plain text mode. Click again to toggle back to regular paste mode."
},
paste_dlg:{
text_title:"Use CTRL+V on your keyboard to paste the text into the window.",
text_linebreaks:"Keep linebreaks",
word_title:"Use CTRL+V on your keyboard to paste the text into the window."
},
table:{
desc:"Inserts a new table",
row_before_desc:"Insert row before",
row_after_desc:"Insert row after",
delete_row_desc:"Delete row",
col_before_desc:"Insert column before",
col_after_desc:"Insert column after",
delete_col_desc:"Remove column",
split_cells_desc:"Split merged table cells",
merge_cells_desc:"Merge table cells",
row_desc:"Table row properties",
cell_desc:"Table cell properties",
props_desc:"Table properties",
paste_row_before_desc:"Paste table row before",
paste_row_after_desc:"Paste table row after",
cut_row_desc:"Cut table row",
copy_row_desc:"Copy table row",
del:"Delete table",
row:"Row",
col:"Column",
cell:"Cell"
},
autosave:{
unload_msg:"The changes you made will be lost if you navigate away from this page.",
restore_content:"Restore auto-saved content.",
warning_message:"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?."
},
fullscreen:{
desc:"Toggle fullscreen mode"
},
media:{
desc:"Insert / edit embedded media",
edit:"Edit embedded media"
},
fullpage:{
desc:"Document properties"
},
template:{
desc:"Insert predefined template content"
},
visualchars:{
desc:"Visual control characters on/off."
},
spellchecker:{
desc:"Toggle spellchecker",
menu:"Spellchecker settings",
ignore_word:"Ignore word",
ignore_words:"Ignore all",
langs:"Languages",
wait:"Please wait...",
sug:"Suggestions",
no_sug:"No suggestions",
no_mpell:"No misspellings found.",
learn_word:"Learn word"
},
pagebreak:{
desc:"Insert page break."
},
advlist:{
types:"Types",
def:"Default",
lower_alpha:"Lower alpha",
lower_greek:"Lower greek",
lower_roman:"Lower roman",
upper_alpha:"Upper alpha",
upper_roman:"Upper roman",
circle:"Circle",
disc:"Disc",
square:"Square"
},
aria:{
rich_text_area:"Rich Text Area"
},
wordcount:{
words: 'Words: '
}
}});


code:
input.radio {border:1px none #000; background:transparent; vertical-align:middle;}
.panel_wrapper div.current {height:80px;}
#width {width:50px; vertical-align:middle;}
#width2 {width:50px; vertical-align:middle;}
#size {width:100px;}


code:
/**
 * editor_plugin_src.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://tinymce.moxiecode.com/license
 * Contributing: http://tinymce.moxiecode.com/contributing
 */

(function() {
	tinymce.create('tinymce.plugins.AdvancedHRPlugin', {
		init : function(ed, url) {
			// Register commands
			ed.addCommand('mceAdvancedHr', function() {
				ed.windowManager.open({
					file : url + '/rule.htm',
					width : 250 + parseInt(ed.getLang('advhr.delta_width', 0)),
					height : 160 + parseInt(ed.getLang('advhr.delta_height', 0)),
					inline : 1
				}, {
					plugin_url : url
				});
			});

			// Register buttons
			ed.addButton('advhr', {
				title : 'advhr.advhr_desc',
				cmd : 'mceAdvancedHr'
			});

			ed.onNodeChange.add(function(ed, cm, n) {
				cm.setActive('advhr', n.nodeName == 'HR');
			});

			ed.onClick.add(function(ed, e) {
				e = e.target;

				if (e.nodeName === 'HR')
					ed.selection.select(e);
			});
		},

		getInfo : function() {
			return {
				longname : 'Advanced HR',
				author : 'Moxiecode Systems AB',
				authorurl : 'http://tinymce.moxiecode.com',
				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',
				version : tinymce.majorVersion + "." + tinymce.minorVersion
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add('advhr', tinymce.plugins.AdvancedHRPlugin);
})();


code:
var AdvHRDialog = {
	init : function(ed) {
		var dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w;

		w = dom.getAttrib(n, 'width');
		f.width.value = w ? parseInt(w) : (dom.getStyle('width') || '');
		f.size.value = dom.getAttrib(n, 'size') || parseInt(dom.getStyle('height')) || '';
		f.noshade.checked = !!dom.getAttrib(n, 'noshade') || !!dom.getStyle('border-width');
		selectByValue(f, 'width2', w.indexOf('%') != -1 ? '%' : 'px');
	},

	update : function() {
		var ed = tinyMCEPopup.editor, h, f = document.forms[0], st = '';

		h = '<hr';

		if (f.size.value) {
			h += ' size="' + f.size.value + '"';
			st += ' height:' + f.size.value + 'px;';
		}

		if (f.width.value) {
			h += ' width="' + f.width.value + (f.width2.value == '%' ? '%' : '') + '"';
			st += ' width:' + f.width.value + (f.width2.value == '%' ? '%' : 'px') + ';';
		}

		if (f.noshade.checked) {
			h += ' noshade="noshade"';
			st += ' border-width: 1px; border-style: solid; border-color: #CCCCCC; color: #ffffff;';
		}

		if (ed.settings.inline_styles)
			h += ' style="' + tinymce.trim(st) + '"';

		h += ' />';

		ed.execCommand("mceInsertContent", false, h);
		tinyMCEPopup.close();
	}
};

tinyMCEPopup.requireLangPack();
tinyMCEPopup.onInit.add(AdvHRDialog.init, AdvHRDialog);


code:
tinyMCE.addI18n('en.advhr_dlg',{
normal:"Normal",
width:"Width",
widthunits:"Units",
size:"Height",
noshade:"No shadow"
});


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<title>{#advhr.advhr_desc}</title>

	<link href="css/advhr.css" rel="stylesheet" type="text/css" />

<form onsubmit="AdvHRDialog.update();return false;" action="#">

{#advhr.advhr_desc}

						{#advhr_dlg.width}

							<input id="width" name="width" type="text" value="" class="mceFocus" />
							{#advhr_dlg.widthunits}
							<select name="width2" id="width2" aria-labelledby="width_unit_label">
								<option value="">px</option>
								<option value="%">%</option>
							</select>

						{#advhr_dlg.size}
						<select id="size" name="size">
							<option value="">{#advhr_dlg.normal}</option>
							<option value="1">1</option>
							<option value="2">2</option>
							<option value="3">3</option>
							<option value="4">4</option>
							<option value="5">5</option>
						</select>

						{#advhr_dlg.noshade}
						<input type="checkbox" name="noshade" id="noshade" class="radio" />

		<input type="submit" id="insert" name="insert" value="{#insert}" />
		<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />

</form>


code:
#src_list, #over_list, #out_list {width:280px;}
.mceActionPanel {margin-top:7px;}
.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;}
.checkbox {border:0;}
.panel_wrapper div.current {height:305px;}
#prev {margin:0; border:1px solid #000; width:428px; height:150px; overflow:auto;}
#align, #classlist {width:150px;}
#width, #height {vertical-align:middle; width:50px; text-align:center;}
#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;}
#class_list {width:180px;}
input {width: 280px;}
#constrain, #onmousemovecheck {width:auto;}
#id, #dir, #lang, #usemap, #longdesc {width:200px;}


code:
/**
 * editor_plugin_src.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://tinymce.moxiecode.com/license
 * Contributing: http://tinymce.moxiecode.com/contributing
 */

(function() {
	tinymce.create('tinymce.plugins.AdvancedImagePlugin', {
		init : function(ed, url) {
			// Register commands
			ed.addCommand('mceAdvImage', function() {
				// Internal image object like a flash placeholder
				if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1)
					return;

				ed.windowManager.open({
					file : url + '/image.htm',
					width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)),
					height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)),
					inline : 1
				}, {
					plugin_url : url
				});
			});

			// Register buttons
			ed.addButton('image', {
				title : 'advimage.image_desc',
				cmd : 'mceAdvImage'
			});
		},

		getInfo : function() {
			return {
				longname : 'Advanced image',
				author : 'Moxiecode Systems AB',
				authorurl : 'http://tinymce.moxiecode.com',
				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',
				version : tinymce.majorVersion + "." + tinymce.minorVersion
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin);
})();


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<title>{#advimage_dlg.dialog_title}</title>

	<link href="css/advimage.css" rel="stylesheet" type="text/css" />

	{#advimage_dlg.dialog_title}
	<form onsubmit="ImageDialog.insert();return false;" action="#">

{#advimage_dlg.tab_general}

{#advimage_dlg.tab_appearance}

{#advimage_dlg.tab_advanced}

				<fieldset>
						<legend>{#advimage_dlg.general}</legend>

								{#advimage_dlg.src}

										<input name="src" type="text" id="src" value="" class="mceFocus" onchange="ImageDialog.showPreviewImage(this.value);" aria-required="true" />

								{#advimage_dlg.image_list}
								<select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"><option value=""></option></select>

								{#advimage_dlg.alt}
								<input id="alt" name="alt" type="text" value="" />

								{#advimage_dlg.title}
								<input id="title" name="title" type="text" value="" />

				</fieldset>

				<fieldset>
					<legend>{#advimage_dlg.preview}</legend>

				</fieldset>

				<fieldset>
					<legend>{#advimage_dlg.tab_appearance}</legend>

							{#advimage_dlg.align}
							<select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();">
									<option value="">{#not_set}</option>
									<option value="baseline">{#advimage_dlg.align_baseline}</option>
									<option value="top">{#advimage_dlg.align_top}</option>
									<option value="middle">{#advimage_dlg.align_middle}</option>
									<option value="bottom">{#advimage_dlg.align_bottom}</option>
									<option value="text-top">{#advimage_dlg.align_texttop}</option>
									<option value="text-bottom">{#advimage_dlg.align_textbottom}</option>
									<option value="left">{#advimage_dlg.align_left}</option>
									<option value="right">{#advimage_dlg.align_right}</option>
								</select>

									Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam
									nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum
									edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam
									erat volutpat.

							{#advimage_dlg.dimensions}

								{#advimage_dlg.width}
								<input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" aria-labelledby="width_voiceLabel" /> x
								{#advimage_dlg.height}
								<input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" aria-labelledby="height_voiceLabel" /> px

										<input id="constrain" type="checkbox" name="constrain" class="checkbox" />
										{#advimage_dlg.constrain_proportions}

							{#advimage_dlg.vspace}
							<input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" />

							{#advimage_dlg.hspace}
							<input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" />

							{#advimage_dlg.border}
							<input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" />

							{#class_name}
							<select id="class_list" name="class_list" class="mceEditableSelect"><option value=""></option></select>

							{#advimage_dlg.style}
							<input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" />

				</fieldset>

				<fieldset>
					<legend>{#advimage_dlg.swap_image}</legend>

					<input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" aria-controls="onmouseoversrc onmouseoutsrc" />
					{#advimage_dlg.alt_image}

								{#advimage_dlg.mouseover}

										<input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" />

								{#advimage_dlg.image_list}
								<select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select>

								{#advimage_dlg.mouseout}

										<input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" />

								{#advimage_dlg.image_list}
								<select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select>

				</fieldset>

				<fieldset>
					<legend>{#advimage_dlg.misc}</legend>

							{#advimage_dlg.id}
							<input id="id" name="id" type="text" value="" />

							{#advimage_dlg.langdir}

								<select id="dir" name="dir" onchange="ImageDialog.changeAppearance();">
										<option value="">{#not_set}</option>
										<option value="ltr">{#advimage_dlg.ltr}</option>
										<option value="rtl">{#advimage_dlg.rtl}</option>
								</select>

							{#advimage_dlg.langcode}

								<input id="lang" name="lang" type="text" value="" />

							{#advimage_dlg.map}

								<input id="usemap" name="usemap" type="text" value="" />

							{#advimage_dlg.long_desc}

										<input id="longdesc" name="longdesc" type="text" value="" />

				</fieldset>

			<input type="submit" id="insert" name="insert" value="{#insert}" />
			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />

	</form>


code:
var ImageDialog = {
	preInit : function() {
		var url;

		tinyMCEPopup.requireLangPack();

		if (url = tinyMCEPopup.getParam("external_image_list_url"))
			document.write('');
	},

	init : function(ed) {
		var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode(), fl = tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList');

		tinyMCEPopup.resizeToInnerSize();
		this.fillClassList('class_list');
		this.fillFileList('src_list', fl);
		this.fillFileList('over_list', fl);
		this.fillFileList('out_list', fl);
		TinyMCE_EditableSelects.init();

		if (n.nodeName == 'IMG') {
			nl.src.value = dom.getAttrib(n, 'src');
			nl.width.value = dom.getAttrib(n, 'width');
			nl.height.value = dom.getAttrib(n, 'height');
			nl.alt.value = dom.getAttrib(n, 'alt');
			nl.title.value = dom.getAttrib(n, 'title');
			nl.vspace.value = this.getAttrib(n, 'vspace');
			nl.hspace.value = this.getAttrib(n, 'hspace');
			nl.border.value = this.getAttrib(n, 'border');
			selectByValue(f, 'align', this.getAttrib(n, 'align'));
			selectByValue(f, 'class_list', dom.getAttrib(n, 'class'), true, true);
			nl.style.value = dom.getAttrib(n, 'style');
			nl.id.value = dom.getAttrib(n, 'id');
			nl.dir.value = dom.getAttrib(n, 'dir');
			nl.lang.value = dom.getAttrib(n, 'lang');
			nl.usemap.value = dom.getAttrib(n, 'usemap');
			nl.longdesc.value = dom.getAttrib(n, 'longdesc');
			nl.insert.value = ed.getLang('update');

			if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover')))
				nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');

			if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout')))
				nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');

			if (ed.settings.inline_styles) {
				// Move attribs to styles
				if (dom.getAttrib(n, 'align'))
					this.updateStyle('align');

				if (dom.getAttrib(n, 'hspace'))
					this.updateStyle('hspace');

				if (dom.getAttrib(n, 'border'))
					this.updateStyle('border');

				if (dom.getAttrib(n, 'vspace'))
					this.updateStyle('vspace');
			}
		}

		// Setup browse button
		document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');
		if (isVisible('srcbrowser'))
			document.getElementById('src').style.width = '260px';

		// Setup browse button
		document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image');
		if (isVisible('overbrowser'))
			document.getElementById('onmouseoversrc').style.width = '260px';

		// Setup browse button
		document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image');
		if (isVisible('outbrowser'))
			document.getElementById('onmouseoutsrc').style.width = '260px';

		// If option enabled default contrain proportions to checked
		if (ed.getParam("advimage_constrain_proportions", true))
			f.constrain.checked = true;

		// Check swap image if valid data
		if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value)
			this.setSwapImage(true);
		else
			this.setSwapImage(false);

		this.changeAppearance();
		this.showPreviewImage(nl.src.value, 1);
	},

	insert : function(file, title) {
		var ed = tinyMCEPopup.editor, t = this, f = document.forms[0];

		if (f.src.value === '') {
			if (ed.selection.getNode().nodeName == 'IMG') {
				ed.dom.remove(ed.selection.getNode());
				ed.execCommand('mceRepaint');
			}

			tinyMCEPopup.close();
			return;
		}

		if (tinyMCEPopup.getParam("accessibility_warnings", 1)) {
			if (!f.alt.value) {
				tinyMCEPopup.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) {
					if (s)
						t.insertAndClose();
				});

				return;
			}
		}

		t.insertAndClose();
	},

	insertAndClose : function() {
		var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el;

		tinyMCEPopup.restoreSelection();

		// Fixes crash in Safari
		if (tinymce.isWebKit)
			ed.getWin().focus();

		if (!ed.settings.inline_styles) {
			args = {
				vspace : nl.vspace.value,
				hspace : nl.hspace.value,
				border : nl.border.value,
				align : getSelectValue(f, 'align')
			};
		} else {
			// Remove deprecated values
			args = {
				vspace : '',
				hspace : '',
				border : '',
				align : ''
			};
		}

		tinymce.extend(args, {
			src : nl.src.value.replace(/ /g, '%20'),
			width : nl.width.value,
			height : nl.height.value,
			alt : nl.alt.value,
			title : nl.title.value,
			'class' : getSelectValue(f, 'class_list'),
			style : nl.style.value,
			id : nl.id.value,
			dir : nl.dir.value,
			lang : nl.lang.value,
			usemap : nl.usemap.value,
			longdesc : nl.longdesc.value
		});

		args.onmouseover = args.onmouseout = '';

		if (f.onmousemovecheck.checked) {
			if (nl.onmouseoversrc.value)
				args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';";

			if (nl.onmouseoutsrc.value)
				args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';";
		}

		el = ed.selection.getNode();

		if (el && el.nodeName == 'IMG') {
			ed.dom.setAttribs(el, args);
		} else {
			ed.execCommand('mceInsertContent', false, '', {skip_undo : 1});
			ed.dom.setAttribs('__mce_tmp', args);
			ed.dom.setAttrib('__mce_tmp', 'id', '');
			ed.undoManager.add();
		}

		tinyMCEPopup.editor.execCommand('mceRepaint');
		tinyMCEPopup.editor.focus();
		tinyMCEPopup.close();
	},

	getAttrib : function(e, at) {
		var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;

		if (ed.settings.inline_styles) {
			switch (at) {
				case 'align':
					if (v = dom.getStyle(e, 'float'))
						return v;

					if (v = dom.getStyle(e, 'vertical-align'))
						return v;

					break;

				case 'hspace':
					v = dom.getStyle(e, 'margin-left')
					v2 = dom.getStyle(e, 'margin-right');

					if (v && v == v2)
						return parseInt(v.replace(/[^0-9]/g, ''));

					break;

				case 'vspace':
					v = dom.getStyle(e, 'margin-top')
					v2 = dom.getStyle(e, 'margin-bottom');
					if (v && v == v2)
						return parseInt(v.replace(/[^0-9]/g, ''));

					break;

				case 'border':
					v = 0;

					tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {
						sv = dom.getStyle(e, 'border-' + sv + '-width');

						// False or not the same as prev
						if (!sv || (sv != v && v !== 0)) {
							v = 0;
							return false;
						}

						if (sv)
							v = sv;
					});

					if (v)
						return parseInt(v.replace(/[^0-9]/g, ''));

					break;
			}
		}

		if (v = dom.getAttrib(e, at))
			return v;

		return '';
	},

	setSwapImage : function(st) {
		var f = document.forms[0];

		f.onmousemovecheck.checked = st;
		setBrowserDisabled('overbrowser', !st);
		setBrowserDisabled('outbrowser', !st);

		if (f.over_list)
			f.over_list.disabled = !st;

		if (f.out_list)
			f.out_list.disabled = !st;

		f.onmouseoversrc.disabled = !st;
		f.onmouseoutsrc.disabled  = !st;
	},

	fillClassList : function(id) {
		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;

		if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {
			cl = [];

			tinymce.each(v.split(';'), function(v) {
				var p = v.split('=');

				cl.push({'title' : p[0], 'class' : p[1]});
			});
		} else
			cl = tinyMCEPopup.editor.dom.getClasses();

		if (cl.length > 0) {
			lst.options.length = 0;
			lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');

			tinymce.each(cl, function(o) {
				lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);
			});
		} else
			dom.remove(dom.getParent(id, 'tr'));
	},

	fillFileList : function(id, l) {
		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;

		l = typeof(l) === 'function' ? l() : window[l];
		lst.options.length = 0;

		if (l && l.length > 0) {
			lst.options[lst.options.length] = new Option('', '');

			tinymce.each(l, function(o) {
				lst.options[lst.options.length] = new Option(o[0], o[1]);
			});
		} else
			dom.remove(dom.getParent(id, 'tr'));
	},

	resetImageData : function() {
		var f = document.forms[0];

		f.elements.width.value = f.elements.height.value = '';
	},

	updateImageData : function(img, st) {
		var f = document.forms[0];

		if (!st) {
			f.elements.width.value = img.width;
			f.elements.height.value = img.height;
		}

		this.preloadImg = img;
	},

	changeAppearance : function() {
		var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg');

		if (img) {
			if (ed.getParam('inline_styles')) {
				ed.dom.setAttrib(img, 'style', f.style.value);
			} else {
				img.align = f.align.value;
				img.border = f.border.value;
				img.hspace = f.hspace.value;
				img.vspace = f.vspace.value;
			}
		}
	},

	changeHeight : function() {
		var f = document.forms[0], tp, t = this;

		if (!f.constrain.checked || !t.preloadImg) {
			return;
		}

		if (f.width.value == "" || f.height.value == "")
			return;

		tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height;
		f.height.value = tp.toFixed(0);
	},

	changeWidth : function() {
		var f = document.forms[0], tp, t = this;

		if (!f.constrain.checked || !t.preloadImg) {
			return;
		}

		if (f.width.value == "" || f.height.value == "")
			return;

		tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width;
		f.width.value = tp.toFixed(0);
	},

	updateStyle : function(ty) {
		var dom = tinyMCEPopup.dom, b, bStyle, bColor, v, isIE = tinymce.isIE, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value});

		if (tinyMCEPopup.editor.settings.inline_styles) {
			// Handle align
			if (ty == 'align') {
				dom.setStyle(img, 'float', '');
				dom.setStyle(img, 'vertical-align', '');

				v = getSelectValue(f, 'align');
				if (v) {
					if (v == 'left' || v == 'right')
						dom.setStyle(img, 'float', v);
					else
						img.style.verticalAlign = v;
				}
			}

			// Handle border
			if (ty == 'border') {
				b = img.style.border ? img.style.border.split(' ') : [];
				bStyle = dom.getStyle(img, 'border-style');
				bColor = dom.getStyle(img, 'border-color');

				dom.setStyle(img, 'border', '');

				v = f.border.value;
				if (v || v == '0') {
					if (v == '0')
						img.style.border = isIE ? '0' : '0 none none';
					else {
						if (b.length == 3 && b[isIE ? 2 : 1])
							bStyle = b[isIE ? 2 : 1];
						else if (!bStyle || bStyle == 'none')
							bStyle = 'solid';
						if (b.length == 3 && b[isIE ? 0 : 2])
							bColor = b[isIE ? 0 : 2];
						else if (!bColor || bColor == 'none')
							bColor = 'black';
						img.style.border = v + 'px ' + bStyle + ' ' + bColor;
					}
				}
			}

			// Handle hspace
			if (ty == 'hspace') {
				dom.setStyle(img, 'marginLeft', '');
				dom.setStyle(img, 'marginRight', '');

				v = f.hspace.value;
				if (v) {
					img.style.marginLeft = v + 'px';
					img.style.marginRight = v + 'px';
				}
			}

			// Handle vspace
			if (ty == 'vspace') {
				dom.setStyle(img, 'marginTop', '');
				dom.setStyle(img, 'marginBottom', '');

				v = f.vspace.value;
				if (v) {
					img.style.marginTop = v + 'px';
					img.style.marginBottom = v + 'px';
				}
			}

			// Merge
			dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText), 'img');
		}
	},

	changeMouseMove : function() {
	},

	showPreviewImage : function(u, st) {
		if (!u) {
			tinyMCEPopup.dom.setHTML('prev', '');
			return;
		}

		if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true))
			this.resetImageData();

		u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u);

		if (!st)
			tinyMCEPopup.dom.setHTML('prev', '');
		else
			tinyMCEPopup.dom.setHTML('prev', '');
	}
};

ImageDialog.preInit();
tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);


code:
tinyMCE.addI18n('en.advimage_dlg',{
tab_general:"General",
tab_appearance:"Appearance",
tab_advanced:"Advanced",
general:"General",
title:"Title",
preview:"Preview",
constrain_proportions:"Constrain proportions",
langdir:"Language direction",
langcode:"Language code",
long_desc:"Long description link",
style:"Style",
classes:"Classes",
ltr:"Left to right",
rtl:"Right to left",
id:"Id",
map:"Image map",
swap_image:"Swap image",
alt_image:"Alternative image",
mouseover:"for mouse over",
mouseout:"for mouse out",
misc:"Miscellaneous",
example_img:"Appearance preview image",
missing_alt:"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.",
dialog_title:"Insert/edit image",
src:"Image URL",
alt:"Image description",
list:"Image list",
border:"Border",
dimensions:"Dimensions",
width:"Width",
height:"Height",
vspace:"Vertical space",
hspace:"Horizontal space",
align:"Alignment",
align_baseline:"Baseline",
align_top:"Top",
align_middle:"Middle",
align_bottom:"Bottom",
align_texttop:"Text top",
align_textbottom:"Text bottom",
align_left:"Left",
align_right:"Right",
image_list:"Image list"
});


code:
.mceLinkList, .mceAnchorList, #targetlist {width:280px;}
.mceActionPanel {margin-top:7px;}
.panel_wrapper div.current {height:320px;}
#classlist, #title, #href {width:280px;}
#popupurl, #popupname {width:200px;}
#popupwidth, #popupheight, #popupleft, #popuptop {width:30px;vertical-align:middle;text-align:center;}
#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {width:200px;}
#events_panel input {width:200px;}


code:
/**
 * editor_plugin_src.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://tinymce.moxiecode.com/license
 * Contributing: http://tinymce.moxiecode.com/contributing
 */

(function() {
	tinymce.create('tinymce.plugins.AdvancedLinkPlugin', {
		init : function(ed, url) {
			this.editor = ed;

			// Register commands
			ed.addCommand('mceAdvLink', function() {
				var se = ed.selection;

				// No selection and not in link
				if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A'))
					return;

				ed.windowManager.open({
					file : url + '/link.htm',
					width : 480 + parseInt(ed.getLang('advlink.delta_width', 0)),
					height : 400 + parseInt(ed.getLang('advlink.delta_height', 0)),
					inline : 1
				}, {
					plugin_url : url
				});
			});

			// Register buttons
			ed.addButton('link', {
				title : 'advlink.link_desc',
				cmd : 'mceAdvLink'
			});

			ed.addShortcut('ctrl+k', 'advlink.advlink_desc', 'mceAdvLink');

			ed.onNodeChange.add(function(ed, cm, n, co) {
				cm.setDisabled('link', co && n.nodeName != 'A');
				cm.setActive('link', n.nodeName == 'A' && !n.name);
			});
		},

		getInfo : function() {
			return {
				longname : 'Advanced link',
				author : 'Moxiecode Systems AB',
				authorurl : 'http://tinymce.moxiecode.com',
				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',
				version : tinymce.majorVersion + "." + tinymce.minorVersion
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add('advlink', tinymce.plugins.AdvancedLinkPlugin);
})();


code:
/* Functions for the advlink plugin popup */

tinyMCEPopup.requireLangPack();

var templates = {
	"window.open" : "window.open('${url}','${target}','${options}')"
};

function preinit() {
	var url;

	if (url = tinyMCEPopup.getParam("external_link_list_url"))
		document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
}

function changeClass() {
	var f = document.forms[0];

	f.classes.value = getSelectValue(f, 'classlist');
}

function init() {
	tinyMCEPopup.resizeToInnerSize();

	var formObj = document.forms[0];
	var inst = tinyMCEPopup.editor;
	var elm = inst.selection.getNode();
	var action = "insert";
	var html;

	document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink');
	document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink');
	document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target');

	// Link list
	html = getLinkListHTML('linklisthref','href');
	if (html == "")
		document.getElementById("linklisthrefrow").style.display = 'none';
	else
		document.getElementById("linklisthrefcontainer").innerHTML = html;

	// Anchor list
	html = getAnchorListHTML('anchorlist','href');
	if (html == "")
		document.getElementById("anchorlistrow").style.display = 'none';
	else
		document.getElementById("anchorlistcontainer").innerHTML = html;

	// Resize some elements
	if (isVisible('hrefbrowser'))
		document.getElementById('href').style.width = '260px';

	if (isVisible('popupurlbrowser'))
		document.getElementById('popupurl').style.width = '180px';

	elm = inst.dom.getParent(elm, "A");
	if (elm != null && elm.nodeName == "A")
		action = "update";

	formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true);

	setPopupControlsDisabled(true);

	if (action == "update") {
		var href = inst.dom.getAttrib(elm, 'href');
		var onclick = inst.dom.getAttrib(elm, 'onclick');

		// Setup form data
		setFormValue('href', href);
		setFormValue('title', inst.dom.getAttrib(elm, 'title'));
		setFormValue('id', inst.dom.getAttrib(elm, 'id'));
		setFormValue('style', inst.dom.getAttrib(elm, "style"));
		setFormValue('rel', inst.dom.getAttrib(elm, 'rel'));
		setFormValue('rev', inst.dom.getAttrib(elm, 'rev'));
		setFormValue('charset', inst.dom.getAttrib(elm, 'charset'));
		setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang'));
		setFormValue('dir', inst.dom.getAttrib(elm, 'dir'));
		setFormValue('lang', inst.dom.getAttrib(elm, 'lang'));
		setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
		setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
		setFormValue('type', inst.dom.getAttrib(elm, 'type'));
		setFormValue('onfocus', inst.dom.getAttrib(elm, 'onfocus'));
		setFormValue('onblur', inst.dom.getAttrib(elm, 'onblur'));
		setFormValue('onclick', onclick);
		setFormValue('ondblclick', inst.dom.getAttrib(elm, 'ondblclick'));
		setFormValue('onmousedown', inst.dom.getAttrib(elm, 'onmousedown'));
		setFormValue('onmouseup', inst.dom.getAttrib(elm, 'onmouseup'));
		setFormValue('onmouseover', inst.dom.getAttrib(elm, 'onmouseover'));
		setFormValue('onmousemove', inst.dom.getAttrib(elm, 'onmousemove'));
		setFormValue('onmouseout', inst.dom.getAttrib(elm, 'onmouseout'));
		setFormValue('onkeypress', inst.dom.getAttrib(elm, 'onkeypress'));
		setFormValue('onkeydown', inst.dom.getAttrib(elm, 'onkeydown'));
		setFormValue('onkeyup', inst.dom.getAttrib(elm, 'onkeyup'));
		setFormValue('target', inst.dom.getAttrib(elm, 'target'));
		setFormValue('classes', inst.dom.getAttrib(elm, 'class'));

		// Parse onclick data
		if (onclick != null && onclick.indexOf('window.open') != -1)
			parseWindowOpen(onclick);
		else
			parseFunction(onclick);

		// Select by the values
		selectByValue(formObj, 'dir', inst.dom.getAttrib(elm, 'dir'));
		selectByValue(formObj, 'rel', inst.dom.getAttrib(elm, 'rel'));
		selectByValue(formObj, 'rev', inst.dom.getAttrib(elm, 'rev'));
		selectByValue(formObj, 'linklisthref', href);

		if (href.charAt(0) == '#')
			selectByValue(formObj, 'anchorlist', href);

		addClassesToList('classlist', 'advlink_styles');

		selectByValue(formObj, 'classlist', inst.dom.getAttrib(elm, 'class'), true);
		selectByValue(formObj, 'targetlist', inst.dom.getAttrib(elm, 'target'), true);
	} else
		addClassesToList('classlist', 'advlink_styles');
}

function checkPrefix(n) {
	if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_email')))
		n.value = 'mailto:' + n.value;

	if (/^\s*www\./i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_external')))
		n.value = 'http://' + n.value;
}

function setFormValue(name, value) {
	document.forms[0].elements[name].value = value;
}

function parseWindowOpen(onclick) {
	var formObj = document.forms[0];

	// Preprocess center code
	if (onclick.indexOf('return false;') != -1) {
		formObj.popupreturn.checked = true;
		onclick = onclick.replace('return false;', '');
	} else
		formObj.popupreturn.checked = false;

	var onClickData = parseLink(onclick);

	if (onClickData != null) {
		formObj.ispopup.checked = true;
		setPopupControlsDisabled(false);

		var onClickWindowOptions = parseOptions(onClickData['options']);
		var url = onClickData['url'];

		formObj.popupname.value = onClickData['target'];
		formObj.popupurl.value = url;
		formObj.popupwidth.value = getOption(onClickWindowOptions, 'width');
		formObj.popupheight.value = getOption(onClickWindowOptions, 'height');

		formObj.popupleft.value = getOption(onClickWindowOptions, 'left');
		formObj.popuptop.value = getOption(onClickWindowOptions, 'top');

		if (formObj.popupleft.value.indexOf('screen') != -1)
			formObj.popupleft.value = "c";

		if (formObj.popuptop.value.indexOf('screen') != -1)
			formObj.popuptop.value = "c";

		formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes";
		formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes";
		formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes";
		formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes";
		formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes";
		formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes";
		formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes";

		buildOnClick();
	}
}

function parseFunction(onclick) {
	var formObj = document.forms[0];
	var onClickData = parseLink(onclick);

	// TODO: Add stuff here
}

function getOption(opts, name) {
	return typeof(opts[name]) == "undefined" ? "" : opts[name];
}

function setPopupControlsDisabled(state) {
	var formObj = document.forms[0];

	formObj.popupname.disabled = state;
	formObj.popupurl.disabled = state;
	formObj.popupwidth.disabled = state;
	formObj.popupheight.disabled = state;
	formObj.popupleft.disabled = state;
	formObj.popuptop.disabled = state;
	formObj.popuplocation.disabled = state;
	formObj.popupscrollbars.disabled = state;
	formObj.popupmenubar.disabled = state;
	formObj.popupresizable.disabled = state;
	formObj.popuptoolbar.disabled = state;
	formObj.popupstatus.disabled = state;
	formObj.popupreturn.disabled = state;
	formObj.popupdependent.disabled = state;

	setBrowserDisabled('popupurlbrowser', state);
}

function parseLink(link) {
	link = link.replace(new RegExp(''', 'g'), "'");

	var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1");

	// Is function name a template function
	var template = templates[fnName];
	if (template) {
		// Build regexp
		var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi"));
		var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\(";
		var replaceStr = "";
		for (var i=0; i<variableNames.length; i++) {
			// Is string value
			if (variableNames[i].indexOf("'${") != -1)
				regExp += "'(.*)'";
			else // Number value
				regExp += "([0-9]*)";

			replaceStr += "$" + (i+1);

			// Cleanup variable name
			variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), "");

			if (i != variableNames.length-1) {
				regExp += "\\s*,\\s*";
				replaceStr += "<delim>";
			} else
				regExp += ".*";
		}

		regExp += "\\);?";

		// Build variable array
		var variables = [];
		variables["_function"] = fnName;
		var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>');
		for (var i=0; i<variableNames.length; i++)
			variables[variableNames[i]] = variableValues[i];

		return variables;
	}

	return null;
}

function parseOptions(opts) {
	if (opts == null || opts == "")
		return [];

	// Cleanup the options
	opts = opts.toLowerCase();
	opts = opts.replace(/;/g, ",");
	opts = opts.replace(/[^0-9a-z=,]/g, "");

	var optionChunks = opts.split(',');
	var options = [];

	for (var i=0; i<optionChunks.length; i++) {
		var parts = optionChunks[i].split('=');

		if (parts.length == 2)
			options[parts[0]] = parts[1];
	}

	return options;
}

function buildOnClick() {
	var formObj = document.forms[0];

	if (!formObj.ispopup.checked) {
		formObj.onclick.value = "";
		return;
	}

	var onclick = "window.open('";
	var url = formObj.popupurl.value;

	onclick += url + "','";
	onclick += formObj.popupname.value + "','";

	if (formObj.popuplocation.checked)
		onclick += "location=yes,";

	if (formObj.popupscrollbars.checked)
		onclick += "scrollbars=yes,";

	if (formObj.popupmenubar.checked)
		onclick += "menubar=yes,";

	if (formObj.popupresizable.checked)
		onclick += "resizable=yes,";

	if (formObj.popuptoolbar.checked)
		onclick += "toolbar=yes,";

	if (formObj.popupstatus.checked)
		onclick += "status=yes,";

	if (formObj.popupdependent.checked)
		onclick += "dependent=yes,";

	if (formObj.popupwidth.value != "")
		onclick += "width=" + formObj.popupwidth.value + ",";

	if (formObj.popupheight.value != "")
		onclick += "height=" + formObj.popupheight.value + ",";

	if (formObj.popupleft.value != "") {
		if (formObj.popupleft.value != "c")
			onclick += "left=" + formObj.popupleft.value + ",";
		else
			onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',";
	}

	if (formObj.popuptop.value != "") {
		if (formObj.popuptop.value != "c")
			onclick += "top=" + formObj.popuptop.value + ",";
		else
			onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',";
	}

	if (onclick.charAt(onclick.length-1) == ',')
		onclick = onclick.substring(0, onclick.length-1);

	onclick += "');";

	if (formObj.popupreturn.checked)
		onclick += "return false;";

	// tinyMCE.debug(onclick);

	formObj.onclick.value = onclick;

	if (formObj.href.value == "")
		formObj.href.value = url;
}

function setAttrib(elm, attrib, value) {
	var formObj = document.forms[0];
	var valueElm = formObj.elements[attrib.toLowerCase()];
	var dom = tinyMCEPopup.editor.dom;

	if (typeof(value) == "undefined" || value == null) {
		value = "";

		if (valueElm)
			value = valueElm.value;
	}

	// Clean up the style
	if (attrib == 'style')
		value = dom.serializeStyle(dom.parseStyle(value), 'a');

	dom.setAttrib(elm, attrib, value);
}

function getAnchorListHTML(id, target) {
	var ed = tinyMCEPopup.editor, nodes = ed.dom.select('a'), name, i, len, html = "";

	for (i=0, len=nodes.length; i<len; i++) {
		if ((name = ed.dom.getAttrib(nodes[i], "name")) != "")
			html += '<option value="#' + name + '">' + name + '</option>';
	}

	if (html == "")
		return "";

	html = '<select id="' + id + '" name="' + id + '" class="mceAnchorList"'
		+ ' onchange="this.form.' + target + '.value=this.options[this.selectedIndex].value"'
		+ '>'
		+ '<option value="">---</option>'
		+ html
		+ '</select>';

	return html;
}

function insertAction() {
	var inst = tinyMCEPopup.editor;
	var elm, elementArray, i;

	elm = inst.selection.getNode();
	checkPrefix(document.forms[0].href);

	elm = inst.dom.getParent(elm, "A");

	// Remove element if there is no href
	if (!document.forms[0].href.value) {
		i = inst.selection.getBookmark();
		inst.dom.remove(elm, 1);
		inst.selection.moveToBookmark(i);
		tinyMCEPopup.execCommand("mceEndUndoLevel");
		tinyMCEPopup.close();
		return;
	}

	// Create new anchor elements
	if (elm == null) {
		inst.getDoc().execCommand("unlink", false, null);
		tinyMCEPopup.execCommand("mceInsertLink", false, "#mce_temp_url#", {skip_undo : 1});

		elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';});
		for (i=0; i<elementArray.length; i++)
			setAllAttribs(elm = elementArray[i]);
	} else
		setAllAttribs(elm);

	// Don't move caret if selection was image
	if (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG') {
		inst.focus();
		inst.selection.select(elm);
		inst.selection.collapse(0);
		tinyMCEPopup.storeSelection();
	}

	tinyMCEPopup.execCommand("mceEndUndoLevel");
	tinyMCEPopup.close();
}

function setAllAttribs(elm) {
	var formObj = document.forms[0];
	var href = formObj.href.value.replace(/ /g, '%20');
	var target = getSelectValue(formObj, 'targetlist');

	setAttrib(elm, 'href', href);
	setAttrib(elm, 'title');
	setAttrib(elm, 'target', target == '_self' ? '' : target);
	setAttrib(elm, 'id');
	setAttrib(elm, 'style');
	setAttrib(elm, 'class', getSelectValue(formObj, 'classlist'));
	setAttrib(elm, 'rel');
	setAttrib(elm, 'rev');
	setAttrib(elm, 'charset');
	setAttrib(elm, 'hreflang');
	setAttrib(elm, 'dir');
	setAttrib(elm, 'lang');
	setAttrib(elm, 'tabindex');
	setAttrib(elm, 'accesskey');
	setAttrib(elm, 'type');
	setAttrib(elm, 'onfocus');
	setAttrib(elm, 'onblur');
	setAttrib(elm, 'onclick');
	setAttrib(elm, 'ondblclick');
	setAttrib(elm, 'onmousedown');
	setAttrib(elm, 'onmouseup');
	setAttrib(elm, 'onmouseover');
	setAttrib(elm, 'onmousemove');
	setAttrib(elm, 'onmouseout');
	setAttrib(elm, 'onkeypress');
	setAttrib(elm, 'onkeydown');
	setAttrib(elm, 'onkeyup');

	// Refresh in old MSIE
	if (tinyMCE.isMSIE5)
		elm.outerHTML = elm.outerHTML;
}

function getSelectValue(form_obj, field_name) {
	var elm = form_obj.elements[field_name];

	if (!elm || elm.options == null || elm.selectedIndex == -1)
		return "";

	return elm.options[elm.selectedIndex].value;
}

function getLinkListHTML(elm_id, target_form_element, onchange_func) {
	if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0)
		return "";

	var html = "";

	html += '<select id="' + elm_id + '" name="' + elm_id + '"';
	html += ' class="mceLinkList" onfoc2us="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
	html += 'this.options[this.selectedIndex].value;';

	if (typeof(onchange_func) != "undefined")
		html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);';

	html += '"><option value="">---</option>';

	for (var i=0; i<tinyMCELinkList.length; i++)
		html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';

	html += '</select>';

	return html;

	// tinyMCE.debug('-- image list start --', html, '-- image list end --');
}

function getTargetListHTML(elm_id, target_form_element) {
	var targets = tinyMCEPopup.getParam('theme_advanced_link_targets', '').split(';');
	var html = '';

	html += '<select id="' + elm_id + '" name="' + elm_id + '" onf2ocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
	html += 'this.options[this.selectedIndex].value;">';
	html += '<option value="_self">' + tinyMCEPopup.getLang('advlink_dlg.target_same') + '</option>';
	html += '<option value="_blank">' + tinyMCEPopup.getLang('advlink_dlg.target_blank') + ' (_blank)</option>';
	html += '<option value="_parent">' + tinyMCEPopup.getLang('advlink_dlg.target_parent') + ' (_parent)</option>';
	html += '<option value="_top">' + tinyMCEPopup.getLang('advlink_dlg.target_top') + ' (_top)</option>';

	for (var i=0; i<targets.length; i++) {
		var key, value;

		if (targets[i] == "")
			continue;

		key = targets[i].split('=')[0];
		value = targets[i].split('=')[1];

		html += '<option value="' + key + '">' + value + ' (' + key + ')</option>';
	}

	html += '</select>';

	return html;
}

// While loading
preinit();
tinyMCEPopup.onInit.add(init);


code:
tinyMCE.addI18n('en.advlink_dlg',{
title:"Insert/edit link",
url:"Link URL",
target:"Target",
titlefield:"Title",
is_email:"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",
is_external:"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",
list:"Link list",
general_tab:"General",
popup_tab:"Popup",
events_tab:"Events",
advanced_tab:"Advanced",
general_props:"General properties",
popup_props:"Popup properties",
event_props:"Events",
advanced_props:"Advanced properties",
popup_opts:"Options",
anchor_names:"Anchors",
target_same:"Open in this window / frame",
target_parent:"Open in parent window / frame",
target_top:"Open in top frame (replaces all frames)",
target_blank:"Open in new window",
popup:"Javascript popup",
popup_url:"Popup URL",
popup_name:"Window name",
popup_return:"Insert 'return false'",
popup_scrollbars:"Show scrollbars",
popup_statusbar:"Show status bar",
popup_toolbar:"Show toolbars",
popup_menubar:"Show menu bar",
popup_location:"Show location bar",
popup_resizable:"Make window resizable",
popup_dependent:"Dependent (Mozilla/Firefox only)",
popup_size:"Size",
width:"Width",
height:"Height",
popup_position:"Position (X/Y)",
id:"Id",
style:"Style",
classes:"Classes",
target_name:"Target name",
langdir:"Language direction",
target_langcode:"Target language",
langcode:"Language code",
encoding:"Target character encoding",
mime:"Target MIME type",
rel:"Relationship page to target",
rev:"Relationship target to page",
tabindex:"Tabindex",
accesskey:"Accesskey",
ltr:"Left to right",
rtl:"Right to left",
link_list:"Link list"
});